./PaxHeaders.1636/yadifa-2.6.5-112010000644000000000000000000000013214505005620014414 xustar000000000000000030 mtime=1695812496.109750804 30 atime=1695812499.079793341 30 ctime=1695812496.109750804 yadifa-2.6.5-11201/0000775000374500037450000000000014505005620014276 5ustar00signersigner00000000000000yadifa-2.6.5-11201/PaxHeaders.1636/m40000644000000000000000000000013214505005615014603 xustar000000000000000030 mtime=1695812493.932719625 30 atime=1695812499.079793341 30 ctime=1695812493.932719625 yadifa-2.6.5-11201/m4/0000775000374500037450000000000014505005615014622 5ustar00signersigner00000000000000yadifa-2.6.5-11201/m4/PaxHeaders.1636/contributions0000644000000000000000000000013214505005615017505 xustar000000000000000030 mtime=1695812493.946719825 30 atime=1695812499.079793341 30 ctime=1695812493.946719825 yadifa-2.6.5-11201/m4/contributions/0000775000374500037450000000000014505005615017524 5ustar00signersigner00000000000000yadifa-2.6.5-11201/m4/contributions/PaxHeaders.1636/20201002-bug_971605_message_5.mbox0000644000000000000000000000013214505005531024672 xustar000000000000000030 mtime=1695812441.214964601 30 atime=1695812441.214964601 30 ctime=1695812493.946719825 yadifa-2.6.5-11201/m4/contributions/20201002-bug_971605_message_5.mbox0000664000374500037450000000345214505005531024640 0ustar00signersigner00000000000000From helmut@subdivi.de Fri Oct 02 20:22:05 2020 Received: (at submit) by bugs.debian.org; 2 Oct 2020 20:22:06 +0000 Date: Fri, 2 Oct 2020 22:21:42 +0200 From: Helmut Grohne To: Debian Bug Tracking System Subject: yadifa FTCBFS: detects cpu features from uname MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="EVF5PPMfhYS0aIcm" Content-Disposition: inline X-Reportbug-Version: 7.7.0 Delivered-To: submit@bugs.debian.org --EVF5PPMfhYS0aIcm Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Source: yadifa Version: 2.3.10-1 Tags: ftbfs patch upstream User: debian-cross@lists.debian.org Usertags: ftcbfs When building yadifa on amd64 for an architecture that does not have multilib support via -m64, the build fails, because yadifa concludes that when building on amd64, one must pass -m64 to the compiler. That's broken. For detecting the cpu, one should use AC_CANONICAL_HOST instead of uname. Beyond that, -m64 is wrong on x32 and that actually breaks native builds on x32. The attached patch fixes both. Please consider applying it. Helmut --EVF5PPMfhYS0aIcm Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="cross.patch" --- yadifa-2.3.10.orig/m4/eurid.m4 +++ yadifa-2.3.10/m4/eurid.m4 @@ -316,18 +316,15 @@ ;; esac -case "$(uname -m)" in - x86_64) +AC_REQUIRE([AC_CANONICAL_HOST]) +AS_IF([test "$host_cpu" = x86_64],[ AC_DEFINE_UNQUOTED([HAS_CPU_AMDINTEL], [1], [i386, Athlon, Opteron, Core2, i3, i5, i7, ...]) AM_CONDITIONAL([HAS_CPU_AMDINTEL], [true]) AC_MSG_RESULT([AMD/Intel]) - CFLAGS3264=-m64 + AS_IF([test "$host" = x86_64-linux-gnux32],,[CFLAGS3264=-m64]) CPU_UNKNOWN=0 cpu_intel_compatible=1 - ;; - *) - ;; -esac +]) case "${CPU_UNKNOWN}" in 1) --EVF5PPMfhYS0aIcm-- yadifa-2.6.5-11201/m4/PaxHeaders.1636/libtool.m40000644000000000000000000000007413073474206016600 xustar000000000000000030 atime=1695812088.571914043 30 ctime=1695812493.919719438 yadifa-2.6.5-11201/m4/libtool.m40000644000374500037450000105743213073474206016547 0ustar00signersigner00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file 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. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS yadifa-2.6.5-11201/m4/PaxHeaders.1636/ltoptions.m40000644000000000000000000000007413073474206017167 xustar000000000000000030 atime=1695812088.555913814 30 ctime=1695812493.922719481 yadifa-2.6.5-11201/m4/ltoptions.m40000644000374500037450000003007313073474206017125 0ustar00signersigner00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file 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. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) yadifa-2.6.5-11201/m4/PaxHeaders.1636/ltsugar.m40000644000000000000000000000007313073474206016614 xustar000000000000000030 atime=1695812088.553913785 29 ctime=1695812493.92471951 yadifa-2.6.5-11201/m4/ltsugar.m40000644000374500037450000001042413073474206016551 0ustar00signersigner00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file 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. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) yadifa-2.6.5-11201/m4/PaxHeaders.1636/ltversion.m40000644000000000000000000000007413073474206017161 xustar000000000000000030 atime=1695812088.553913785 30 ctime=1695812493.926719539 yadifa-2.6.5-11201/m4/ltversion.m40000644000374500037450000000126213073474206017115 0ustar00signersigner00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file 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. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) yadifa-2.6.5-11201/m4/PaxHeaders.1636/lt~obsolete.m40000644000000000000000000000007413073474206017506 xustar000000000000000030 atime=1695812088.549913728 30 ctime=1695812493.928719568 yadifa-2.6.5-11201/m4/lt~obsolete.m40000644000374500037450000001375613073474206017455 0ustar00signersigner00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file 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. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) yadifa-2.6.5-11201/m4/PaxHeaders.1636/eurid.m40000644000000000000000000000013214505005533016231 xustar000000000000000030 mtime=1695812443.955003843 30 atime=1695812444.398010188 30 ctime=1695812493.930719596 yadifa-2.6.5-11201/m4/eurid.m40000664000374500037450000010747714505005533016213 0ustar00signersigner00000000000000dnl ############################################################################ dnl dnl Copyright (c) 2011-2023, EURid vzw. All rights reserved. dnl The YADIFA TM software product is provided under the BSD 3-clause license: dnl dnl Redistribution and use in source and binary forms, with or without dnl modification, are permitted provided that the following conditions dnl are met: dnl dnl * Redistributions of source code must retain the above copyright dnl notice, this list of conditions and the following disclaimer. dnl * Redistributions in binary form must reproduce the above copyright dnl notice, this list of conditions and the following disclaimer in dnl the documentation and/or other materials provided with the dnl distribution. dnl * Neither the name of EURid nor the names of its contributors may be dnl used to endorse or promote products derived from this software dnl without specific prior written permission. dnl dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" dnl AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE dnl IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE dnl ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE dnl LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR dnl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS dnl INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN dnl CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) dnl ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE dnl POSSIBILITY OF SUCH DAMAGE. dnl dnl ############################################################################ dnl Assume it is true cpu_intel_compatible=1 icc_enabled=0 dnl #################################################### dnl dnl AC_HAS_ENABLE(low-case --enable-*, up-case HAS_*, text, config.h text,ifyes,ifno) dnl dnl This macro creates a parameter with dnl _ a shell-variable-name that will be used for --enable-VARIABLENAME dnl '_' of the variable name will be replaced by a '-' in the command dnl dnl _ SOMETHINGSOMETHING that will be transformed into a HAS_SOMETHINGSOMETHING define (both C & Makefile) dnl dnl _ A text to be put next to the --enable-this line in the --help dnl dnl _ An optional text to be put in the config.h output file. If not set or empty, the --help text is used dnl dnl _ A block to execute if the option is enabled (--enable-this) dnl dnl _ A block to execute if the option is disabled (--disable-this or not set) dnl dnl #################################################### AC_DEFUN([AC_HAS_ENABLE], [ # # AC_HAS_ENABLE $1 # # CHECKING AC_MSG_CHECKING(if [$2] has been enabled) # ARG ENABLE AC_ARG_ENABLE([$1], AS_HELP_STRING([--enable-[translit($1,[_],[-])]], [Enable $3])) dnl # MSG RESULT dnl AC_MSG_RESULT($enable_[$1]) dnl echo "enabled: '$enable_[$1]'" # CASE case "y$enable_[$1]" in yyes) # DEFINE Y AC_DEFINE_UNQUOTED([HAS_$2], [1], ifelse($4,,[$3 enabled.],$4)) # CONDITIONAL Y enable_[$1]="yes" AC_MSG_RESULT([yes]) # IF YES $5 # ENDIF ;; yno|y|*) # DEFINE N AC_DEFINE_UNQUOTED([HAS_$2], [0], ifelse($4,,[$3 disabled.],$4)) # CONDITIONAL N enable_[$1]="no" AC_MSG_RESULT([no]) # IF NO $6 # ENDIF ;; esac # CONDITIONAL AM_CONDITIONAL([HAS_$2], [test y$enable_[$1] = yyes]) # SUBST AC_SUBST(HAS_$2) # AC_HAS_ENABLE $1 DONE ]) dnl #################################################### dnl dnl AC_FORCE_ENABLE(var) dnl dnl Forces --enable-var dnl dnl #################################################### AC_DEFUN([AC_FORCE_ENABLE], [ # # AC_FORCE_ENABLE $1 # enable_[$1]=yes AC_DEFINE_UNQUOTED([HAS_$2], [1], [$1 = $2 enabled]) AM_CONDITIONAL([HAS_$2], [test y$enable_[$1] = yyes]) AC_SUBST(HAS_$2) # AC_FORCE_ENABLE $1 DONE ]) dnl #################################################### dnl dnl AC_FORCE_ENABLE(var) dnl dnl Forces --enable-var dnl dnl #################################################### AC_DEFUN([AC_FORCE_DISABLE], [ # # AC_FORCE_DISABLE $1 # enable_[$1]=no AC_DEFINE_UNQUOTED([HAS_$2], [0], [$1 = $2 enabled]) AM_CONDITIONAL([HAS_$2], [test y$enable_[$1] = yyes]) AC_SUBST(HAS_$2) # AC_FORCE_DISABLE $1 DONE ]) dnl #################################################### dnl dnl AC_HAS_DISABLE(low-case --disable-*, up-case HAS_*, text, config.h text,ifyes,ifno) dnl dnl This macro creates a parameter with dnl _ a shell-variable-name that will be used for --disable-VARIABLENAME dnl '_' of the variable name will be replaced by a '-' in the command dnl dnl _ SOMETHINGSOMETHING that will be transformed into a HAS_SOMETHINGSOMETHING define (both C & Makefile) dnl dnl _ A text to be put next to the --disable-this line in the --help dnl dnl _ An optional text to be put in the config.h output file. If not set or empty, the --help text is used dnl dnl _ A block to execute if the option is enabled (--enable-this or not set) dnl dnl _ A block to execute if the option is disabled (--disable-this) dnl dnl #################################################### AC_DEFUN([AC_HAS_DISABLE], [ # # AC_HAS_DISABLE $1 # # CHECKING AC_MSG_CHECKING(if [$2] has been disabled) # ARG ENABLE AC_ARG_ENABLE([$1], AS_HELP_STRING([--disable-[translit($1,[_],[-])]],[Disable $3])) # MSG RESULT dnl echo "enabled: '$enable_[$1]'" # CASE case "y$enable_[$1]" in yyes|y) # DEFINE Y AC_DEFINE_UNQUOTED([HAS_$2], [1], ifelse($4,,[$3 enabled.],$4)) # CONDITIONAL Y enable_[$1]=yes AC_MSG_RESULT([no]) # IF YES $5 # ENDIF ;; yno|*) # DEFINE N AC_DEFINE_UNQUOTED([HAS_$2], [0], ifelse($4,,[$3 disabled.],$4)) # CONDITIONAL N enable_[$1]=no AC_MSG_RESULT([yes]) # IF NO $6 # ENDIF ;; esac # CONDITIONAL AM_CONDITIONAL([HAS_$2], [test y$enable_[$1] != yno]) # SUBST AC_SUBST(HAS_$2) # AC_HAS_DISABLE $1 DONE ]) dnl #################################################### dnl dnl AC_HAS_WITH(low-case --with-*, up-case HAS_*, text, config.h text,ifyes,ifno) dnl dnl This macro creates a parameter with dnl _ a shell-variable-name that will be used for --with-VARIABLENAME dnl '_' of the variable name will be replaced by a '-' in the command dnl dnl _ SOMETHINGSOMETHING that will be transformed into a HAS_SOMETHINGSOMETHING define (both C & Makefile) dnl dnl _ A text to be put next to the --with-this line in the --help dnl dnl _ An optional text to be put in the config.h output file. If not set or empty, the --help text is used dnl dnl _ A block to execute if the option is withd (--with-this) dnl dnl _ A block to execute if the option is withoutd (--without-this or not set) dnl dnl #################################################### AC_DEFUN([AC_HAS_WITH], [ # # AC_HAS_WITH $1 # # CHECKING AC_MSG_CHECKING(if [translit($1,[_A-Z],[ a-z])] has been given) # ARG WITH AC_ARG_WITH([$1], AS_HELP_STRING([--with-[translit($1,[_],[-])]], [With $3]), [ # DEFINE Y AC_DEFINE_UNQUOTED([HAS_$2], [1], ifelse($4,,[With $3.],$4)) # CONDITIONAL Y AC_DEFINE_UNQUOTED([HAS_WITH_$2], "$with_[$1]" // $withval, ifelse($4,,[build $3.],$4)) with_[$1]="yes" AC_MSG_RESULT([yes]) # IF YES $5 # ENDIF ] , [ # DEFINE N AC_DEFINE_UNQUOTED([HAS_$2], [0], ifelse($4,,[Without $3.],$4)) # CONDITIONAL N with_[$1]="no" AC_MSG_RESULT([no]) # IF NO $6 # ENDIF ]) # CONDITIONAL AM_CONDITIONAL([HAS_$2], [test "y$with_[$1]" == "yyes"]) # SUBST AC_SUBST([HAS_$2]) # AC_HAS_WITH $1 DONE ]) dnl #################################################### dnl dnl AC_HAS_WITHOUT(low-case --without-*, up-case HAS_*, text, config.h text,ifyes,ifno) dnl dnl This macro creates a parameter with dnl _ a shell-variable-name that will be used for --without-VARIABLENAME dnl '_' of the variable name will be replaced by a '-' in the command dnl dnl _ SOMETHINGSOMETHING that will be transformed into a HAS_SOMETHINGSOMETHING define (both C & Makefile) dnl dnl _ A text to be put next to the --without-this line in the --help dnl dnl _ An optional text to be put in the config.h output file. If not set or empty, the --help text is used dnl dnl _ A block to execute if the option is withd (--with-this or not set) dnl dnl _ A block to execute if the option is withoutd (--without-this) dnl dnl #################################################### AC_DEFUN([AC_HAS_WITHOUT], [ # # AC_HAS_WITHOUT $1 # # CHECKING AC_MSG_CHECKING(if [$1] has to be build) # ARG WITH AC_ARG_WITH([$1], AS_HELP_STRING([--without-[translit($1,[_],[-])]],[Without $3])) # MSG RESULT case "y$with_[$1]" in yyes|y) # DEFINE Y AC_DEFINE_UNQUOTED([HAS_$2], [1], ifelse($4,,[With $3.],$4)) # CONDITIONAL Y with_[$1]=yes AC_MSG_RESULT([yes]) # IF YES $5 # ENDIF ;; yno|*) # DEFINE N AC_DEFINE_UNQUOTED([HAS_$2], [0], ifelse($4,,[Without $3.],$4)) # CONDITIONAL N with_[$1]=no AC_MSG_RESULT([no]) # IF NO $6 # ENDIF ;; esac dnl # CONDITIONAL AM_CONDITIONAL([HAS_$2], [test "y$with_[$1]" != "yno"]) # Used to check the test was correct (it is) #AM_CONDITIONAL([TEST_HAS_$2], [echo test "y$with_[$1]" != "yno" > /tmp/test_has_$2.txt]) # SUBST AC_SUBST([HAS_$2]) # AC_HAS_WITHOUT $1 DONE ]) dnl handles Darwin libtoolize -> glibtoolize AC_DEFUN([AC_DARWIN_LIBTOOL], [ case "$(uname -s)" in Darwin) alias libtoolize="glibtoolize" which libtool > /dev/null 2>&1 if [[ $? -ne 0 ]] then which glibtool > /dev/null 2>&1 if [[ $? -eq 0 ]] then alias libtool="glibtool" fi fi echo 'brol' | sed 's/brol/truc/' > /dev/null 2>&1 if [[ $? -ne 0 ]] then alias sed="gsed" fi AC_MSG_RESULT([Darwin workaround]) ;; *) AC_MSG_RESULT([nothing to do]) ;; esac ]) AC_DEFUN([YA_TRY_LINK], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([$1],[$2],[$3],[$4])]) ]) ac_os_workaround_done=0 AC_DEFUN([AC_OS_WORKAROUND], [ if [[ $ac_os_workaround_done -eq 0 ]] then ac_os_workaround_done=1 AC_MSG_CHECKING(what kind of OS this is) is_darwin_os=0 is_bsd_family=0 is_solaris_family=0 is_linux_family=0 case "$(uname -s)" in Darwin) is_darwin_os=1 is_bsd_family=1 osx_version_major=$(uname -r|sed 's/\..*//') AC_MSG_RESULT([OSX $osx_version_major]) CFLAGS="$CFLAGS -D__APPLE_USE_RFC_3542=1" ;; FreeBSD) is_bsd_family=1 AC_MSG_RESULT([BSD]) ;; Linux) is_linux_family=1 AC_MSG_RESULT([Linux]) ;; SunOS) is_solaris_family=1 AC_MSG_RESULT([SunOS]) ;; *) AC_MSG_RESULT([not specifically supported]) ;; esac if [[ "$is_darwin_os" = "" ]] then echo "OS detection failed to give relevant results" exit 1; fi if [[ $is_darwin_os -ne 0 ]] then AC_DEFINE_UNQUOTED(IS_DARWIN_OS, [1], [OSX]) is_darwin_os_txt="yes" if [[ $osx_version_major -ge 14 ]] then osx_version_major_ge14="yes" else osx_version_major_ge14="no" fi else AC_DEFINE_UNQUOTED(IS_DARWIN_OS, [0], [OSX]) is_darwin_os_txt="no" osx_version_major_ge14="no" fi AM_CONDITIONAL([IS_DARWIN_OS], [test "y$isdarwin_os_txt" == "yyes"]) AM_CONDITIONAL([IS_DARWIN_GE14], [test "y$osx_version_major_ge14" == "yyes"]) AC_SUBST(IS_DARWIN_OS) AC_SUBST(IS_DARWIN_GE14) if [[ $is_bsd_family -ne 0 ]] then is_bsd_family_txt="yes" AC_DEFINE_UNQUOTED(IS_BSD_FAMILY, [1], [BSD]) else is_bsd_family_txt="no" AC_DEFINE_UNQUOTED(IS_BSD_FAMILY, [0], [BSD]) fi AM_CONDITIONAL([IS_BSD_FAMILY], [test "y$is_bsd_family_txt" == "yyes"]) AC_SUBST(IS_BSD_FAMILY) if [[ $is_linux_family -ne 0 ]] then is_linux_family_txt="yes" AC_DEFINE_UNQUOTED(IS_LINUX_FAMILY, [1], [LINUX]) else is_linux_family_txt="no" AC_DEFINE_UNQUOTED(IS_LINUX_FAMILY, [0], [LINUX]) fi AM_CONDITIONAL([IS_LINUX_FAMILY], [test "y$is_linux_family_txt" == "yyes"]) AC_SUBST(IS_LINUX_FAMILY) if [[ $is_solaris_family -ne 0 ]] then is_solaris_family_txt="yes" AC_DEFINE_UNQUOTED(IS_SOLARIS_FAMILY, [1], [SOLARIS]) else is_solaris_family_txt="no" AC_DEFINE_UNQUOTED(IS_SOLARIS_FAMILY, [0], [SOLARIS]) fi AM_CONDITIONAL([IS_SOLARIS_FAMILY], [test "y$is_solaris_family_txt" == "yyes"]) AC_SUBST(IS_SOLARIS_FAMILY) fi ]) dnl Compiler support dnl #################################################### dnl dnl COMPILER SUPPORT dnl dnl #################################################### AC_DEFUN([AC_COMPILER_SUPPORTS], [ # # AC_COMPILER_SUPPORTS $1 # # CHECKING AC_MSG_CHECKING(if compiler supports [$1]) if [[ "$CC" = "" ]] then AC_MSG_RESULT("[compiler not set yet, fix this]") exit 1 fi cat > test-gcc-$2.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC $1 test-gcc-$2.c -o test-gcc-$2 > /dev/null 2>&1 if [[ $? -ne 0 ]] then has_cc_[$2]="no" AM_CONDITIONAL(HAS_CC_$2, [false]) AC_DEFINE_UNQUOTED([HAS_CC_$2], [0], [Compiler supports feature]) AC_MSG_RESULT([no]) else has_cc_[$2]="yes" AM_CONDITIONAL(HAS_CC_$2, [true]) AC_DEFINE_UNQUOTED([HAS_CC_$2], [1], [Compiler supports feature]) AC_MSG_RESULT([yes]) fi # CONDITIONAL AM_CONDITIONAL(HAS_CC_$2, [test "y$has_cc_[$2]" == "yyes"]) # SUBST AC_SUBST(HAS_CC_$2) rm -rf test-gcc-$2* ]) dnl setgroups support AC_DEFUN([AC_SETGROUPS_CHECK], [ AC_MSG_CHECKING([for setgroups]) AC_CHECK_LIB(c,setgroups, [ AC_DEFINE_UNQUOTED([HAS_SETGROUPS], [1], [The system supports setgroups]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ] ) ]) dnl __sync builtins AC_DEFUN([AC_SYNC_BUILTINS], [ AC_MSG_CHECKING([if the compiler supports __sync builtins]) cat > sync_builtin_test.c <<_ACEOF typedef int atomic_flag; static int atomic_flag_test_and_set(atomic_flag* v) { atomic_flag old = __sync_fetch_and_or(v, (atomic_flag)1); return old; } static void atomic_flag_clear(atomic_flag* v) { __sync_fetch_and_and(v, (atomic_flag)0); } int main() { atomic_flag f; atomic_flag old = atomic_flag_test_and_set(&f); atomic_flag_clear(&f); return 0; } _ACEOF ${CC} ${CFLAGS} sync_builtin_test.c -o sync_builtin_test > /dev/null 2>&1 ./sync_builtin_test > /dev/null 2>&1 if [[ $? -eq 0 ]]; then has_sync_builtins=1 AC_MSG_RESULT([yes]) else has_sync_builtins=0 AC_MSG_RESULT([no]) fi rm -f sync_builtin_test sync_builtin_test.c # CONDITIONAL AM_CONDITIONAL([HAS_SYNC_BUILTINS], [test $has_sync_builtins -eq 1]) # SUBST AC_SUBST(HAS_SYNC_BUILTINS) AC_DEFINE_UNQUOTED([HAS_SYNC_BUILTINS], [$has_sync_builtins], [An alternative to be used if stdatomics is not available]) ]) dnl #################################################### dnl Memory aligment issues (T1000) AC_DEFUN([AC_MEMALIGN_CHECK], [ AC_MSG_CHECKING([if memory accesses must be size-aligned]) cat > memalign_issues_test.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif int main(int argc, char** argv) { char* p = (char*)malloc(8); p++; int* intp= (int*)p; *intp=1; return 0; } _ACEOF ${CC} ${CFLAGS} memalign_issues_test.c -o memalign_issues_test > /dev/null 2>&1 ./memalign_issues_test > /dev/null 2>&1 if [[ $? -ne 0 ]]; then has_memalign_issues=1 AC_MSG_RESULT([yes]) else has_memalign_issues=0 AC_MSG_RESULT([no]) fi rm -f memalign_issues_test memalign_issues_test.c # CONDITIONAL AM_CONDITIONAL([HAS_MEMALIGN_ISSUES], [test $has_memalign_issues -eq 1]) # SUBST AC_SUBST(HAS_MEMALIGN_ISSUES) AC_DEFINE_UNQUOTED([HAS_MEMALIGN_ISSUES], [$has_memalign_issues], [Define this to enable slow but safe unaligned memory accesses]) ]) dnl #################################################### dnl Architecture AC_DEFUN([AC_CPU_CHECK], [ AC_DEFINE_UNQUOTED([DEFAULT_ASSUMED_CPU_COUNT], [2], [number of hardware core if the auto-detect fails]) cpu_intel_compatible=1 AC_MSG_CHECKING([for the CPU options]) cpu_unknown=1 has_cpu_niagara=0 has_cpu_amdintel=0 CFLAGS3264= case "$(uname -i 2>/dev/null)" in SUNW,SPARC-Enterprise-T1000) AC_DEFINE_UNQUOTED([HAS_CPU_NIAGARA], [1], [T1000 has a Niagara cpu]) has_cpu_niagara=1 AC_MSG_RESULT([UtrasparcT1]) CFLAGS3264=-m64 cpu_unknown=0 cpu_intel_compatible=0 ;; *) ;; esac AC_REQUIRE([AC_CANONICAL_HOST]) AS_IF([test "x$host_cpu" = xx86_64],[ AC_DEFINE_UNQUOTED([HAS_CPU_AMDINTEL], [1], [i386, Athlon, Opteron, Core2, i3, i5, i7, ...]) AM_CONDITIONAL([HAS_CPU_AMDINTEL], [true]) AC_MSG_RESULT([AMD/Intel ($host)]) AS_IF([test "x$host" = "xx86_64-linux-gnux32"],,[CFLAGS3264=-m64]) CPU_UNKNOWN=0 cpu_intel_compatible=1 ]) case "${cpu_unknown}" in 1) AC_MSG_RESULT([generic]) ;; 0) ;; esac AM_CONDITIONAL([HAS_CPU_NIAGARA], [test $has_cpu_niagara -eq 1]) AM_CONDITIONAL([HAS_CPU_AMDINTEL], [test $has_cpu_amdintel -eq 1]) if [[ "$is_solaris_family" = "" ]] then echo "OS must be detected first" exit 1 fi if [[ $is_solaris_family -eq 1 ]] then echo "Solaris ..." AC_MSG_CHECKING([if either force 32 or 64 bits is enabled]) if [[ ! "$enable_force32bits" = "yes" ]] then if [[ ! "$enable_force64bits" = "yes" ]] then AC_MSG_RESULT([no, forcing 64 bits]) enable_force64bits="yes" else AC_MSG_RESULT([yes]) fi else AC_MSG_RESULT([yes]) fi else echo "Not Solaris ..." fi echo "Force ..." dnl Forced 32/64 bits architecture AC_MSG_CHECKING([if force 32 bits is enabled]) AC_ARG_ENABLE(force32bits, AS_HELP_STRING([--enable-force32bits], [Forces a 32 bits binary compilation]), [enable_force32bits=yes], [enable_force32bits=no]) AC_MSG_RESULT($enable_force32bits) case "$enable_force32bits" in yes) CFLAGS3264=-m32 ;; *) ;; esac AM_CONDITIONAL([FORCE32BITS], [test "y$enable_force32bits" == "yyes"]) AC_MSG_CHECKING([if force 64 bits is enabled]) AC_ARG_ENABLE(force64bits, AS_HELP_STRING([--enable-force64bits], [Forces a 64 bits binary compilation]), [enable_force64bits=yes], [enable_force64bits=no]) AC_MSG_RESULT($enable_force64bits) case "$enable_force64bits" in yes) CFLAGS3264=-m64 if [[ "$enable_force32" = "yes" ]] then echo "cannot do both --enable-force32bits and --enable-force64bits at the same time" exit 1 fi ;; *) ;; esac AM_CONDITIONAL([FORCE64BITS], [test "y$enable_force64bits" = "yyes"]) ]) dnl #################################################### dnl Endianness AC_DEFUN([AC_ENDIANNESS], [ # # AC_ENDIANNESS # # CHECKING AC_MSG_CHECKING([endianness: ]) if [[ "$CC" = "" ]] then AC_MSG_RESULT("[compiler not set yet, fix this]") exit 1 fi cat > test-gcc-endian.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif #if defined __FreeBSD__ #if HAVE_SYS_ENDIAN_H #include #endif #elif defined __APPLE__ #if HAVE_MACHINE_ENDIAN_H #include #endif #elif defined __sun #if HAVE_SYS_BYTEORDER_H #include #endif #else #if HAVE_ENDIAN_H #include #endif #if HAVE_BYTESWAP_H #include #endif #endif static int magic = 0x00525545; int main(int argc,char** argv) { (void)argc; (void)argv; int pp = -1; int c = -1; #if defined _BIG_ENDIAN pp = 2; #elif defined _LITTLE_ENDIAN pp = 1; #endif #ifdef __BYTE_ORDER #if __BYTE_ORDER == __LITTLE_ENDIAN pp = 1; #elif __BYTE_ORDER == __BIG_ENDIAN pp = 2; #endif // printf("__BYTE_ORDER=%x\n", __BYTE_ORDER); #endif #ifdef _BYTE_ORDER #if _BYTE_ORDER == _LITTLE_ENDIAN pp = 1; #elif _BYTE_ORDER == _BIG_ENDIAN pp = 2; #endif printf("_BYTE_ORDER=%x\n", _BYTE_ORDER); #endif #ifdef BYTE_ORDER #if BYTE_ORDER == LITTLE_ENDIAN pp = 1; #elif BYTE_ORDER == BIG_ENDIAN pp = 2; #endif // printf("BYTE_ORDER=%x\n", BYTE_ORDER); #endif # #ifdef WORDS_BIGENDIAN // printf("WORDS_BIGENDIAN=%x\n", WORDS_BIGENDIAN); if(pp == 1) // could be -1 or 2 { pp = -2; } else { pp = 2; } #endif char *p = (char*)&magic; if(*p == '\0') { c = 2; } else if(*p == 'E') { c = 1; } if((pp < 0) || (c < 0)) { printf("*** WARNING *** preprocessor says %i, real test says %i *** WARNING ***\n", pp, c); } if(c == pp) { return c; } else { return -1; } } _ACEOF $CC $1 test-gcc-endian.c -o test-gcc-endian > /dev/null 2>&1 if [[ $? -ne 0 ]] then AC_MSG_RESULT("[failed to compile test]") exit 1 fi ./test-gcc-endian if [[ $? -eq 1 ]] then cpu_endian="little" AC_MSG_RESULT([little]) else cpu_endian="big" AC_MSG_RESULT([big]) fi # CONDITIONAL AM_CONDITIONAL(HAS_LITTLE_ENDIAN, [test "$cpu_endian" == "little"]) AM_CONDITIONAL(HAS_BIG_ENDIAN, [test "$cpu_endian" == "big"]) # SUBST AC_SUBST(HAS_LITTLE_ENDIAN) AC_SUBST(HAS_BIG_ENDIAN) rm -f test-gcc-endian.c* test-gcc-endian ]) dnl #################################################### dnl Compiler AC_DEFUN([AC_COMPILER_CHECK], [ AC_OS_WORKAROUND AC_CPU_CHECK cat /etc/redhat-version > /dev/null 2>&1 if [[ $? -eq 0 ]] then is_redhat_family=1 else is_redhat_family=0 fi EURID_CFLAGS= VERSION_OPT=--version $CC --version > /dev/null 2>&1 if [[ $? -ne 0 ]] then $CC -V > /dev/null 2>&1 if [[ $? -ne 0 ]] then CCVER='0.0' CCNAME='unknown' VERSION_OPT='' else VERSION_OPT='-V' fi fi if [[ ! "$VERSION_OPT" = "" ]] then dnl $CC --version 2>&1 dnl $CC $VERSION_OPT 2>&1|head -1 dnl $CC $VERSION_OPT 2>&1|head -1|sed 's/[[^0-9.]]*\([[0-9.]]*\).*/\1/' dnl $CC $VERSION_OPT 2>&1|head -1|sed -e 's/.*clang.*/clang/' -e 's/.*gcc.*/gcc/' -e 's/.*icc.*/icc/' -e 's/.*Sun C.*/Sun C/'|tr A-Z a-z CCVER=$($CC $VERSION_OPT 2>&1|head -1|sed 's/[[^0-9.]]*\([[0-9.]]*\).*/\1/') dnl echo $CC $VERSION_OPT "2>&1" |head -1|sed 's/[[^0-9.]]*\([[0-9.]]*\).*/\1/' if [[ "$CCVER" = "" ]] then CCVER='0.0' fi CCNAME=$($CC $VERSION_OPT 2>&1|head -1|sed -e 's/.*clang.*/clang/' -e 's/.*gcc.*/gcc/' -e 's/.*icc.*/icc/' -e 's/.*Sun C.*/Sun C/'|tr A-Z a-z) dnl echo $CC $VERSION_OPT "2>&1"|head -1|sed -e 's/.*clang.*/clang/' -e 's/.*gcc.*/gcc/' -e 's/.*icc.*/icc/' -e 's/.*Sun C.*/Sun C/'|tr A-Z a-z if [[ "$CCNAME" = "" ]] then CCNAME='unknown' fi else CCVER='0.0' CCNAME='unknown' fi # version opt CCMAJOR=$(echo $CCVER | sed 's/\./ /g' | awk '{ print @S|@1}') CCMINOR=$(echo $CCVER | sed 's/\./ /g' | awk '{ print @S|@2}') dnl echo "$CC $VERSION_OPT : CCNAME='$CCNAME' CCVER='$CCVER' CCMAJOR='$CCMAJOR' CCMINOR='$CCMINOR'" if [[ "$CCMAJOR" = "" ]] then CCMAJOR=0 fi if [[ "$CCMINOR" = "" ]] then CCMINOR=0 fi uses_icc=0 uses_gcc=0 uses_clang=0 uses_sunc=0 uses_unknown=0 if [[ "$CCNAME" = "gcc" ]] then CCOPTIMISATIONFLAGS=-O3 if [[ $CCMAJOR -lt 4 ]] then CCOPTIMISATIONFLAGS=-O0 echo "WARNING: GCC < 4.0 has optimisations issues with YADIFA." sleep 1 elif [[ $CCMAJOR -eq 4 ]] then if [[ $CCMINOR -lt 6 ]] then CCOPTIMISATIONFLAGS=-O0 echo "WARNING: GCC before 4.6 have optimisation issues with YADIFA." sleep 1 elif [[ $CCMINOR -eq 6 ]] then CCOPTIMISATIONFLAGS=-O2 else # hopefully after 4.6 the issue is fixed ... CCOPTIMISATIONFLAGS=-O3 fi fi uses_gcc=1 elif [[ "$CCNAME" = "icc" ]] then echo "ICC" CCOPTIMISATIONFLAGS=-O3 uses_icc=1 AR=xiar elif [[ "$CCNAME" = "clang" ]] then echo "CLANG" CCOPTIMISATIONFLAGS=-O3 uses_clang=1 elif [[ "$CCNAME" = "Sun C" ]] then echo "Sun C" CCOPTIMISATIONFLAGS=-xO5 uses_sunc=1 else echo "unsupported compiler" CCNAME=$CC CCOPTIMISATIONFLAGS=-O2 uses_unknown=1 fi AM_CONDITIONAL([USES_ICC], [test $uses_icc -eq 1]) AM_CONDITIONAL([USES_GCC], [test $uses_gcc -eq 1]) AM_CONDITIONAL([USES_CLANG], [test $uses_clang -eq 1]) AM_CONDITIONAL([USES_SUNC], [test $uses_sunc -eq 1]) AM_CONDITIONAL([USES_UNKNOWN], [test $uses_unknown -eq 1]) # # We've been told RedHat does not like -O3 at all, so ... # if [[ $is_redhat_family -ne 0 ]] then if [[ "$CCOPTIMISATIONFLAGS " eq "-O3" ]] then CCOPTIMISATIONFLAGS=-O2 fi fi echo "detected compiler is $CCNAME $CCMAJOR $CCMINOR" AC_SUBST(CCOPTIMISATIONFLAGS, $CCOPTIMISATIONFLAGS) if [[ $cpu_intel_compatible -eq 0 ]] then if [[ $icc_enabled -ne 0 ]] then echo "ERROR: cannot enable ICC with CPU other than x86 or amd64" exit 1 fi fi AC_COMPILER_SUPPORTS([-mtune=native],TUNE_NATIVE) AC_COMPILER_SUPPORTS([-fno-ident],NO_IDENT) AC_COMPILER_SUPPORTS([-ansi],ANSI) AC_COMPILER_SUPPORTS([-ansi-alias],ANSI_ALIAS) AC_COMPILER_SUPPORTS([-pedantic],PEDANTIC) AC_COMPILER_SUPPORTS([-std=gnu11],STD_GNU11) AC_COMPILER_SUPPORTS([-std=c11],STD_C11) AC_COMPILER_SUPPORTS([-std=gnu99],STD_GNU99) AC_COMPILER_SUPPORTS([-std=c99],STD_C99) AC_COMPILER_SUPPORTS([-xc99],XC99) AC_COMPILER_SUPPORTS([-m32],M32) AC_COMPILER_SUPPORTS([-m64],M64) AC_COMPILER_SUPPORTS([-Wall],WALL) AC_COMPILER_SUPPORTS([-g],G) AC_COMPILER_SUPPORTS([-g3],G3) AC_COMPILER_SUPPORTS([-gdwarf-2],DWARF2) AC_COMPILER_SUPPORTS([-gdwarf-3],DWARF3) AC_COMPILER_SUPPORTS([-gdwarf-4],DWARF4) AC_COMPILER_SUPPORTS([-fstack-protector --param=ssp-buffer-size=4],STACK_PROTECTOR) AC_COMPILER_SUPPORTS([-fexceptions],EXCEPTIONS) AC_COMPILER_SUPPORTS([-Werror=missing-field-initializers],MISSING_FIELD_INITIALIZERS) AC_COMPILER_SUPPORTS([-fsanitize=address],SANITIZE_ADDRESS) AC_COMPILER_SUPPORTS([-fno-omit-frame-pointer],NO_OMIT_FRAME_POINTER) AC_COMPILER_SUPPORTS([-faddress-sanitizer],ADDRESS_SANITIZER_CHECK) AC_COMPILER_SUPPORTS([-fcatch_undefined_behavior],CATCH_UNDEFINED_BEHAVIOR) AC_COMPILER_SUPPORTS([-rdynamic],RDYNAMIC) AC_CHECK_HEADERS([arpa/inet.h]) AC_CHECK_HEADERS([asm/unistd.h]) AC_CHECK_HEADERS([assert.h]) AC_CHECK_HEADERS([bfd.h]) AC_CHECK_HEADERS([byteswap.h]) AC_CHECK_HEADERS([cpuid.h]) AC_CHECK_HEADERS([ctype.h]) AC_CHECK_HEADERS([dirent.h]) AC_CHECK_HEADERS([dlfcn.h]) AC_CHECK_HEADERS([endian.h]) AC_CHECK_HEADERS([errno.h]) AC_CHECK_HEADERS([execinfo.h]) AC_CHECK_HEADERS([fcntl.h]) AC_CHECK_HEADERS([getopt.h]) AC_CHECK_HEADERS([grp.h]) AC_CHECK_HEADERS([limits.h]) AC_CHECK_HEADERS([linux/limits.h]) AC_CHECK_HEADERS([mach/clock.h]) AC_CHECK_HEADERS([machine/endian.h]) AC_CHECK_HEADERS([mach/mach.h]) AC_CHECK_HEADERS([malloc.h]) AC_CHECK_HEADERS([netdb.h]) AC_CHECK_HEADERS([net/ethernet.h]) AC_CHECK_HEADERS([netinet/in.h]) AC_CHECK_HEADERS([netinet6/in6.h]) AC_CHECK_HEADERS([netinet/tcp.h]) AC_CHECK_HEADERS([pcap/pcap.h]) AC_CHECK_HEADERS([poll.h]) AC_CHECK_HEADERS([pthread.h]) AC_CHECK_HEADERS([pwd.h]) AC_CHECK_HEADERS([sched.h]) AC_CHECK_HEADERS([signal.h]) AC_CHECK_HEADERS([stdarg.h]) AC_CHECK_HEADERS([stdatomic.h]) AC_CHECK_HEADERS([stdbool.h]) AC_CHECK_HEADERS([stddef.h]) AC_CHECK_HEADERS([stdint.h]) AC_CHECK_HEADERS([stdio.h]) AC_CHECK_HEADERS([stdlib.h]) AC_CHECK_HEADERS([string.h]) AC_CHECK_HEADERS([strings.h]) AC_CHECK_HEADERS([sys/byteorder.h]) AC_CHECK_HEADERS([sys/cpuset.h]) AC_CHECK_HEADERS([sys/endian.h]) AC_CHECK_HEADERS([sys/file.h]) AC_CHECK_HEADERS([sys/ipc.h]) AC_CHECK_HEADERS([syslog.h]) AC_CHECK_HEADERS([sys/mman.h]) AC_CHECK_HEADERS([sys/msg.h]) AC_CHECK_HEADERS([sys/param.h]) AC_CHECK_HEADERS([sys/prctl.h]) AC_CHECK_HEADERS([sys/resource.h]) AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([sys/stat.h]) AC_CHECK_HEADERS([sys/syslimits.h]) AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([sys/types.h]) AC_CHECK_HEADERS([sys/un.h]) AC_CHECK_HEADERS([sys/wait.h]) AC_CHECK_HEADERS([tcl.h]) AC_CHECK_HEADERS([time.h]) AC_CHECK_HEADERS([ucontext.h]) AC_CHECK_HEADERS([unistd.h]) AC_CHECK_HEADERS([stdnoreturn.h]) AC_MEMALIGN_CHECK AC_SYNC_BUILTINS AC_SETGROUPS_CHECK AC_ENDIANNESS ]) dnl #################################################### dnl timegm support AC_DEFUN([AC_TIMEGM_CHECK], [ AC_MSG_CHECKING([for timegm]) YA_TRY_LINK([#include],[struct tm t; timegm(&t);],[AC_DEFINE_UNQUOTED([HAS_TIMEGM], [1], [The system supports timegm]) echo yes],[echo no]) ]) dnl #################################################### dnl mremap support AC_DEFUN([AC_MREMAP_CHECK], [ AC_MSG_CHECKING([for mremap]) YA_TRY_LINK([#define _GNU_SOURCE #include],[mremap(0,0,0,0);],[AC_DEFINE_UNQUOTED([HAS_MREMAP], [1], [The system supports mremap]) echo yes],[echo no]) ]) dnl #################################################### dnl pthread spinlock support AC_DEFUN([AC_PTHREAD_SPINLOCK_CHECK], [ AC_MSG_CHECKING([for pthread_spin_init]) AC_SEARCH_LIBS(pthread_spin_init,pthread,[AC_DEFINE_UNQUOTED([HAS_PTHREAD_SPINLOCK], [1], [The system supports spinlocks]) echo yes],[echo no]) ]) dnl #################################################### dnl pthread_setname_np support AC_DEFUN([AC_PTHREAD_SETNAME_NP_CHECK], [ AC_MSG_CHECKING([for pthread_setname_np]) AC_SEARCH_LIBS(pthread_setname_np, pthread,[AC_DEFINE_UNQUOTED([HAS_PTHREAD_SETNAME_NP], [1], [The system supports thread names]) echo yes],[echo no]) ]) dnl #################################################### dnl pthread_setaffinity_np support AC_DEFUN([AC_PTHREAD_SETAFFINITY_NP_CHECK], [ AC_MSG_CHECKING([for pthread_setaffinity_np]) AC_SEARCH_LIBS(pthread_setaffinity_np,pthread,[AC_DEFINE_UNQUOTED([HAS_PTHREAD_SETAFFINITY_NP], [1], [The system supports thread affinity]) echo yes],[echo no]) ]) dnl #################################################### dnl gettid support AC_DEFUN([AC_GETTID_CHECK], [ AC_MSG_CHECKING([for gettid]) AC_SEARCH_LIBS(gettid,,[AC_DEFINE_UNQUOTED([HAVE_GETTID], [1], [The system supports gettid]) echo yes],[echo no]) ]) dnl #################################################### dnl gethostbyname inet_pton inet_ntop ... (Solaris requires a lib) AC_DEFUN([AC_GETHOSTBYNAME_CHECK], [ AC_MSG_CHECKING([for gethostbyname inet_pton inet_ntop]) AC_MSG_CHECKING([if gethostbyname requires some lib]) YA_TRY_LINK([#include],[struct hostent *host = gethostbyname("www.yadifa.eu.");], [ AC_MSG_RESULT([no]) ], [ AC_MSG_CHECKING([if gethostbyname requires nsl]) OLD_LDFLAGS="$LDFLAGS" LDFLAGS="-lnsl $LDFLAGS" YA_TRY_LINK([#include],[struct hostent *host = gethostbyname("www.yadifa.eu.");], [ AC_MSG_RESULT([yes]) ], [ LDFLAGS="$OLDLDFLAGS" AC_MSG_RESULT([no, and I could not find it ...]) exit 1; ]) ]) ]) dnl #################################################### dnl LTO AC_DEFUN([AC_CHECK_LTO], [ AC_MSG_CHECKING(if LTO has been enabled) AC_ARG_ENABLE(lto, AS_HELP_STRING([--enable-lto], [Enable LTO support, requires gold linker]), [enable_lto=yes], [enable_lto=no]) AC_MSG_RESULT($enable_lto) case "$enable_lto" in yes) type -p gold if [[ $? -ne 0 ]] then AC_MSG_RESULT([WARNING: 'gold' not found]) sleep 1 fi if [[ ! "$LD" = "" ]] then $LD -v |grep -i gold > /dev/null 2>&1 if [[ $? -ne 0 ]] then AC_MSG_RESULT([WARNING: LTO enabled but LD ($LD) is not gold]) sleep 1 fi else AC_MSG_RESULT([LD not defined]) fi ;; no|*) ;; esac AM_CONDITIONAL(HAS_LTO_SUPPORT, [test "x$enable_lto" == "yyes"]) ]) dnl #################################################### AC_DEFUN([AC_SOCKADDR_SA_LEN_CHECK], [ dnl Check for sa_len field AC_MSG_CHECKING([if sockaddr has a sa_len field]) cat > sockaddr_sa_len.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETINET6_IN6_H #include #endif int main(int argc, char** argv) { struct sockaddr sa; sa.sa_len = 4; } _ACEOF has_sockaddr_sa_len=0 ${CC} ${CFLAGS} sockaddr_sa_len.c > /dev/null 2>&1 if [[ $? -eq 0 ]]; then has_sockaddr_sa_len=1; AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi rm -f sockaddr_sa_len.c sockaddr_sa_len AM_CONDITIONAL([HAS_SOCKADDR_SA_LEN], [test $has_sockaddr_sa_len = yes]) AC_DEFINE_UNQUOTED([HAS_SOCKADDR_SA_LEN], [$has_sockaddr_sa_len], [The sockaddr struct has an sa_len field]) ]) dnl #################################################### AC_DEFUN([AC_SOCKADDR_IN_SIN_LEN_CHECK], [ dnl Check for sin_len field AC_MSG_CHECKING([if sockaddr_in has a sin_len field]) cat > sockaddr_in_sin_len.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETINET6_IN6_H #include #endif int main(int argc, char** argv) { struct sockaddr_in sa; sa.sin_len = sizeof(struct sockaddr_in); } _ACEOF has_sockaddr_in_sin_len=0 ${CC} ${CFLAGS} sockaddr_in_sin_len.c > /dev/null 2>&1 if [[ $? -eq 0 ]]; then has_sockaddr_in_sin_len=1; AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi rm -f sockaddr_in_sin_len.c sockaddr_in_sin_len AM_CONDITIONAL([HAS_SOCKADDR_IN_SIN_LEN], [test $has_sockaddr_in_sin_len = yes]) AC_DEFINE_UNQUOTED([HAS_SOCKADDR_IN_SIN_LEN], [$has_sockaddr_in_sin_len], [The sockaddr_in struct has an sin_len field]) ]) dnl #################################################### AC_DEFUN([AC_SOCKADDR_IN6_SIN6_LEN_CHECK], [ dnl Check for sin6_len field AC_MSG_CHECKING([if sockaddr_in6 has a sin6_len field]) cat > sockaddr_in6_sin6_len.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETINET6_IN6_H #include #endif int main(int argc, char** argv) { struct sockaddr_in6 sa; sa.sin6_len = sizeof(struct sockaddr_in6); } _ACEOF has_sockaddr_in6_sin6_len=0 ${CC} ${CFLAGS} sockaddr_in6_sin6_len.c > /dev/null 2>&1 if [[ $? -eq 0 ]]; then has_sockaddr_in6_sin6_len=1; AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi rm -f sockaddr_in6_sin6_len.c sockaddr_in6_sin6_len AM_CONDITIONAL([HAS_SOCKADDR_IN6_SIN6_LEN], [test $has_sockaddr_in6_sin6_len = yes]) AC_DEFINE_UNQUOTED([HAS_SOCKADDR_IN6_SIN6_LEN], [$has_sockaddr_in6_sin6_len], [The sockaddr_in6 struct has an sin6_len field]) ]) dnl #################################################### AC_DEFUN([AC_EURID_SUMMARY], [ cat <&1|grep Bstatic > /dev/null if [[ $? -eq 0 ]] then echo "not supported" LDDYN="" LDSTAT="" else echo "supported" fi LIBS="$LDDYN $LIBS" AC_SEARCH_LIBS([gethostbyname],[nsl],,[exit 1]) AC_SEARCH_LIBS([socket],[socket],,[exit 1]) AC_SEARCH_LIBS([dlopen],[dl],,[exit 1]) AC_SEARCH_LIBS([pthread_self],[pthread],,[exit 1]) AC_SEARCH_LIBS([backtrace],[execinfo],,[exit 1]) AC_SEARCH_LIBS([backtrace_symbols],[execinfo],,[exit 1]) dnl AC_GETHOSTBYNAME_CHECK if [[ $requires_tcl -eq 1 ]] then echo "TCL is required by this setup ..." if [[ "$tcl_version" = "" ]] then echo "tcl_version empty, expected something like 'tcl8.x'" exit 1 fi CFLAGS="$CFLAGS -DWITHTCLINCLUDED" if [[ ! "${tcl_includedir}" = "/usr/include" ]] && [[ ! "${tcl_includedir}" = "" ]] then CFLAGS="$CFLAGS -I${tcl_includedir}" fi if [[ ! "${tcl_libdir}" = "/usr/lib" ]] && [[ ! "${tcl_libdir}" = "/lib" ]] && [[ ! "${tcl_libdir}" = "" ]] then LDFLAGS="-L${tcl_libdir} $LDFLAGS" fi echo "searching for library '$tcl_version' in the system" AC_SEARCH_LIBS(Tcl_Main, [${tcl_version}], ,[echo "could not find ${tcl_version} :: tcl_includedir=${tcl_includedir} :: tcl_libdir=${tcl_libdir}"; exit 1]) fi dnl SSL if [[ $requires_ssl -eq 1 ]] then echo "SSL is required by this setup ..." AC_YADIFA_ADD_SSL else echo "SSL is not required by this setup" fi dnl DNSCORE if [[ $requires_dnscore -eq 1 ]] then AC_SEARCH_LIBS([clock_gettime],[rt]) AC_MSG_CHECKING(for the DNS Core library) if [[ ! -d ${srcdir}/../../lib/dnscore ]] then AC_CHECK_LIB([dnscore], [dnscore_init],,[exit],[$LDSTAT -ldnscore $LDDYN -lssl]) else CFLAGS="-I${srcdir}/../../lib/dnscore/include $CFLAGS" LDFLAGS="-L../../lib/dnscore/.libs $LDFLAGS" LDFLAGS="$LDFLAGS $LDSTAT -ldnscore $LDDYN" fi AC_SUBST(DNSCORE) fi dnl DNSDB if [[ $requires_dnsdb -eq 1 ]] then AC_MSG_CHECKING(for the DNS Database library) if [[ ! -d ${srcdir}/../../lib/dnsdb ]] then AC_CHECK_LIB([dnsdb], [zdb_init],,[exit],[$LDSTAT -ldnscore $LDDYN -lssl]) else echo "embedded" CFLAGS="-I${srcdir}/../../lib/dnsdb/include $CFLAGS" LDFLAGS="-L../../lib/dnsdb/.libs $LDFLAGS" LDFLAGS="$LDFLAGS $LDSTAT -ldnsdb $LDDYN" fi AC_SUBST(DNSDB) fi dnl DNSLG if [[ $requires_dnslg -eq 1 ]] then AC_MSG_CHECKING(for the DNS Looking Glass library) if [[ ! -d ${srcdir}/../../lib/dnslg ]] then AC_CHECK_LIB([dnslg], [dnslg_init],,[exit],[$LDSTAT -ldnscore $LDDYN ]) else CFLAGS="-I${srcdir}/../../lib/dnslg/include $CFLAGS" LDFLAGS="-L../../lib/dnslg/.libs $LDFLAGS" LDFLAGS="$LDFLAGS $LDSTAT -ldnslg $LDDYN" fi AC_SUBST(DNSLG) fi LDFLAGS="$LDFLAGS $LDDYN" LIBS="$LDDYN $LIBS" ]) dnl Features AC_DEFUN([AC_YADIFA_FEATURES], [ AC_CHECK_ENABLE_RRL dnl MASTER dnl ========================================================================== dnl NOTE: Putting the empty optional text (,,) is mandatory AC_HAS_DISABLE(master,MASTER_SUPPORT,[DNS master],, AC_YADIFA_ENABLE_SSL , enable_dynupdate='no' enable_rrsig_management='no') dnl CTRL module dnl ========================================================================== AC_HAS_DISABLE(ctrl,CTRL,[yadifa ctrl remote control tool]) dnl ZONESIGN dnl ========================================================================== dnl AC_HAS_ENABLE(zonesign,ZONESIGN,[yadifa zonesign tool]) AM_CONDITIONAL([HAS_ZONESIGN], [xno = xyes]) dnl KEYGEN dnl ========================================================================== AC_HAS_ENABLE(keygen,KEYGEN,[yadifa keygen tool]) dnl NSID dnl ========================================================================== AC_HAS_DISABLE(nsid,NSID_SUPPORT,[NSID support]) dnl ACL dnl ========================================================================== dnl AC_HAS_DISABLE(acl,ACL_SUPPORT,[ACL support],, dnl AC_YADIFA_ENABLE_SSL dnl , dnl enable_tsig='no' dnl ) AC_FORCE_ENABLE(acl,ACL_SUPPORT) AC_YADIFA_ENABLE_SSL dnl TSIG dnl ========================================================================== dnl AC_HAS_DISABLE(tsig,TSIG_SUPPORT,[TSIG support],, dnl AC_YADIFA_ENABLE_SSL dnl , dnl ) AC_FORCE_ENABLE(tsig,TSIG_SUPPORT) AC_YADIFA_ENABLE_SSL dnl DYNUPDATE dnl ========================================================================== AC_HAS_DISABLE(dynupdate,DYNUPDATE_SUPPORT,[dynamic update support]) dnl RRSIG_MANAGEMENT dnl ========================================================================== AC_HAS_DISABLE(rrsig_management,RRSIG_MANAGEMENT_SUPPORT,[RRSIG verification and generation for zones],, AC_YADIFA_ENABLE_SSL , ) AM_CONDITIONAL([HAS_DNSSEC_SUPPORT], [true]) AC_DEFINE_UNQUOTED([HAS_DNSSEC_SUPPORT], [1], [MUST be enabled if either NSEC3 or NSEC are enabled]) AC_SUBST(ZDB_HAS_DNSSEC_SUPPORT) AC_YADIFA_ENABLE_SSL AM_CONDITIONAL(HAS_NSEC_SUPPORT,[true]) AC_DEFINE_UNQUOTED([HAS_NSEC_SUPPORT], [1], [NSEC enabled]) AC_SUBST(HAS_NSEC_SUPPORT) AM_CONDITIONAL(HAS_NSEC3_SUPPORT,[true]) AC_DEFINE_UNQUOTED([HAS_NSEC3_SUPPORT], [1], [NSEC3 enabled]) AC_SUBST(HAS_NSEC3_SUPPORT) dnl ZALLOC dnl ========================================================================== AC_HAS_DISABLE(zalloc,ZALLOC_SUPPORT,[zalloc memory system]) dnl ZALLOC STATISTICS dnl ================= AC_HAS_ENABLE(zalloc_statistics,ZALLOC_STATISTICS_SUPPORT,[zalloc statistics support]) dnl ZALLOC DEBUG dnl ============ AC_HAS_ENABLE(zalloc_debug,ZALLOC_DEBUG_SUPPORT,[zalloc debug support for yadifa objects]) dnl MALLOC DEBUG dnl ============ AC_HAS_ENABLE(malloc_debug,MALLOC_DEBUG_SUPPORT,[malloc debug support for yadifa objects]) dnl LIBC MALLOC DEBUG dnl ============ dnl AC_HAS_ENABLE(libc_malloc_debug,LIBC_MALLOC_DEBUG_SUPPORT,[libc malloc debug support monitors program-wide allocations (DEPRECATED)]) AC_FORCE_DISABLE(libc_malloc_debug,LIBC_MALLOC_DEBUG_SUPPORT) dnl BFD STACKTRACE DEBUG dnl ==================== AC_HAS_ENABLE(bfd_debug,BFD_DEBUG_SUPPORT,[bfd debug support]) case "$enable_bfd_debug" in yes) AC_SEARCH_LIBS([dlinfo],[dl],[],[echo no dl],) AC_SEARCH_LIBS([sha1_init_ctx],[iberty],[],[echo iberty],) AC_SEARCH_LIBS([bfd_init],[bfd],[],[echo no bfd;exit 1],) ;; no|*) ;; esac dnl MUTEX STACKTRACE DEBUG dnl ====================== AC_HAS_ENABLE(mutex_debug,MUTEX_DEBUG_SUPPORT,[mutex debug support]) dnl ZONE MUTEX DEBUG dnl ================ AC_HAS_ENABLE(lock_debug,LOCK_DEBUG_SUPPORT,[zone lock debug support]) dnl FILEPOOL CACHE dnl ================ dnl AC_HAS_ENABLE(filepool_cache,FILEPOOL_CACHE,[file pool uses cache (dev)]) dnl INSTANCIATED ZONES DEBUG dnl ======================== AC_HAS_ENABLE(track_zones_debug,TRACK_ZONES_DEBUG_SUPPORT,[tracking of the instanciated zones for detecting potential leaks. Relatively cheap with a small (<100) amount of zones.]) dnl LOG THREAD ID dnl ============= AC_HAS_ENABLE(log_thread_id,LOG_THREAD_ID,[a column with an alphanumeric id consistent in the lowest 32 bits of a thread id in each log line]) dnl LOG THREAD TAG dnl ============== AC_HAS_DISABLE(log_thread_tag,LOG_THREAD_TAG,[a column with a 8 letters human-readable tag identifying a thread in each log line]) dnl LOG PID dnl ======= AC_HAS_DISABLE(log_pid,LOG_PID,[a column with the pid in each line of log]) dnl ASCII 7 dnl ======= AC_HAS_ENABLE(full_ascii7,FULL_ASCII7,[acceptance of ASCII7 characters in DNS names (not recommended)]) dnl ECDSA dnl ===== AC_HAS_DISABLE(ecdsa,ECDSA_SUPPORT,[Elliptic Curve (ECDSA) support (Use this if the available SSL library does not support it properly)]) dnl EDDSA dnl ===== dnl AC_HAS_DISABLE(eddsa, EDDSA_SUPPORT,[Edward Curve (EDDSA) support (Use this if the available SSL library does not support it properly)]) AC_MSG_CHECKING(if EDDSA has been disabled) AC_ARG_ENABLE(EDDSA, AS_HELP_STRING([--disable-eddsa]), [Disable EDDSA]) case "y$enable_eddsa" in yyes|y) if test "x$ac_cv_func_EVP_PKEY_new_raw_public_key" == xyes; then AC_DEFINE_UNQUOTED([HAS_EDDSA_SUPPORT], [1], [EDDSA support enabled (EVP_PKEY_new_raw_public_key found)]) enable_eddsa=yes AC_MSG_RESULT([no]) else AC_DEFINE_UNQUOTED([HAS_EDDSA_SUPPORT], [0], [EDDSA support disabled (EVP_PKEY_new_raw_public_key not found)]) enable_eddsa=no AC_MSG_RESULT([yes]) fi ;; yno|*) AC_DEFINE_UNQUOTED([HAS_EDDSA_SUPPORT], [0], [EDDSA support disabled]) enable_eddsa=no AC_MSG_RESULT([yes]) ;; esac AM_CONDITIONAL([HAS_EDDSA], [test y$enable_eddsa != yno]) AC_SUBST(HAS_EDDSA) dnl SYSTEMD-RESOLVED dnl ================ AC_HAS_ENABLE(systemd_resolved_avoidance, SYSTEMD_RESOLVED_AVOIDANCE, [to set do-not-listen to "127.0.0.53 port 53" by default (otherwise the list is empty by default)]) dnl NON-AA AXFR (non-AA AXFR as sent by MS DNS) dnl ========================================================================== AC_HAS_ENABLE(non_aa_axfr_support,NON_AA_AXFR_SUPPORT,[defaults axfr-strict-authority to no. Lenient acceptance of AXFR answer from master that do not have AA bit by default (Microsoft DNS)]) dnl TCP MANAGER dnl ========================================================================== dnl not for release dnl AC_HAS_ENABLE(tcp_manager,TCP_MANAGER,[Enables the TCP manager (experimental)]) dnl STRDUP dnl ========================================================================== dnl include strdup AC_MSG_CHECKING(if has strdup) AM_CONDITIONAL([HAS_STRDUP], [false]) cat > strdup_test.c <<_ACEOF #include #include int main(int argc, char** argv) { char* p = strdup("test"); return 0; } _ACEOF ${CC} ${CFLAGS} strdup_test.c -o strdup_test if [[ $? -eq 0 ]]; then has_strdup=1; echo "yes" else echo "no" fi rm -f strdup_test strdup_test.c AM_CONDITIONAL([HAS_STRDUP], [test $has_strdup = yes]) dnl EVENT DYNAMIC MODULE dnl ========================================================================== AC_HAS_ENABLE(event_dynamic_module,EVENT_DYNAMIC_MODULE,[Adds support for dynamically loaded module that gets events from yadifad and is allowed to fetch some information]) dnl logdir dnl ========================================================================== AC_HAS_WITH(logdir, LOGDIR, [the log file directory set to this], [where to put the log files], logdir="$withval" with_logdir="$logdir" , logdir=${localstatedir}/log/yadifa with_logdir="$logdir" ) AC_SUBST(logdir) echo "LOGDIR=$logdir" AC_SOCKADDR_SA_LEN_CHECK AC_SOCKADDR_IN_SIN_LEN_CHECK AC_SOCKADDR_IN6_SIN6_LEN_CHECK ]) dnl NOTIMESTAMP dnl ========================================================================== AC_HAS_DISABLE(build_timestamp,BUILD_TIMESTAMP,[Disable timestamps in the build]) dnl close_ex file-descriptor double-close protection (debug) dnl ========================================================================== AC_HAS_ENABLE(fd_close_debug, CLOSE_EX_REF, [close_ex(fd) to change the value of fd to detect double-closes issues (debug)]) AC_HAS_DISABLE(yadifa,YADIFA,[controller for yadifad],[building with controller]) AC_HAS_DISABLE(dnssec_tools,DNSSEC_TOOLS,[DNSSEC module for yadifa],[enable DNSSEC module for yadifa]) AC_DEFUN([AC_YADIFA_SUMMARY], [ if [[ "$disable_acl" = "yes" ]]; then enable_acl="no"; else enable_acl="yes";fi if [[ "$disable_tsig" = "yes" ]]; then enable_tsig="no"; else enable_tsig="yes";fi echo echo SUMMARY echo _____________________ echo echo CC ................ : $CC echo LD ................ : $LD echo AR ................ : $AR echo CFLAGS ............ : $CFLAGS echo CXXFLAGS .......... : $CXXFLAGS echo CPPFLAGS .......... : $CPPFLAGS echo LDFLAGS ........... : $LDFLAGS echo LIBS .............. : $LIBS echo echo ZALLOC ............ : $enable_zalloc echo ZALLOC STATISTICS . : $enable_zalloc_statistics echo ZALLOC DEBUG ...... : $enable_zalloc_debug echo ACL ............... : $enable_acl echo TSIG .............. : $enable_tsig echo MASTER ............ : $enable_master echo DYNUPDATE ......... : $enable_dynupdate echo RRSIG MANAGEMENT .. : $enable_rrsig_management echo CTRL .............. : $enable_ctrl echo NSEC .............. : $enable_nsec echo NSEC3 ............. : $enable_nsec3 echo RRL ............... : $enable_rrl echo echo TCL ............... : $with_tcl if [[ "$with_tcl" = "yes" ]]; then echo TCL used ............................ : $tcl_version echo TCL library ......................... : $tcl_libdir echo "TCL includes ........................ : $tcl_includedir" fi echo ]) yadifa-2.6.5-11201/PaxHeaders.1636/INSTALL0000644000000000000000000000013214505005532015367 xustar000000000000000030 mtime=1695812442.530983449 30 atime=1695812442.530983449 30 ctime=1695812493.901719181 yadifa-2.6.5-11201/INSTALL0000664000374500037450000004173114505005532015337 0ustar00signersigner00000000000000Quick installation ****************** You will need the most up-to-date aclocal, autoheader, automake, autoconf, make and a C compiler installed (clang, icc or gcc >= 4.6) By default gcc is used but you can specify your compiler adding CC=x in ./configure. ie: ./configure CC=clang openssl has to be build with shared Note that gcc < 4.6 will be build with -O0 and > 4.6 with -O3 ./configure make sudo make install cd /usr/local sudo mkdir -p var/run var/log var/zones/keys var/zones/masters var/zones/slaves var/zones/xfr Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" With "Homebrew" installed for openssl support: ./configure -with-openssl=/usr/local/opt/openssl@1.1 CFLAGS="-O2 -g -DDEBUG=0 -DNDEBUG=1" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `--with-openssl=DIR' Use the openssl from directory DIR (where DIR is the PREFIX of openssl) `--enable-tiny-footprint' This will change the behaviour of the memory allocation of the database. It will take the smallest increase in memory required to fulfill an allocation instead of getting a bunch at once. Disabled by default. `--enable-messages' Will use recvmsg/sendmsg instead of recvfrom/sendto. This is only useful if * any interface the server listens from has aliased IPs. (ie: eth0 & eth0:1) AND * the server is configured to listen to 0.0.0.0 (it's its default) Having aliased addresses on interfaces can also be handled without using messages but enumerating the listen addresses in yadifad.conf instead. ie: listen 192.0.2.1, 192.0.2.2 `--enable-lto' Will use the Link Time Optimisations of gcc (or ipo for ICC) The gain of speed is very marginal so it is not recommended `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. yadifa-2.6.5-11201/PaxHeaders.1636/NEWS0000644000000000000000000000013114505005532015034 xustar000000000000000030 mtime=1695812442.714986084 29 atime=1695812442.71398607 30 ctime=1695812493.903719209 yadifa-2.6.5-11201/NEWS0000664000374500037450000000001414505005532014772 0ustar00signersigner00000000000000See README yadifa-2.6.5-11201/PaxHeaders.1636/README0000644000000000000000000000013214505005533015217 xustar000000000000000030 mtime=1695812443.564998257 30 atime=1695812443.564998257 30 ctime=1695812493.905719238 yadifa-2.6.5-11201/README0000664000374500037450000000377514505005533015175 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ 20230906: YADIFA 2.6.5-public Secondaries will nolonger enforce the TTL value of the NSEC3PARAM record. Fixes an issue caused by a limitation of the select system call. yadifa-2.6.5-11201/PaxHeaders.1636/AUTHORS0000644000000000000000000000013214505005531015405 xustar000000000000000030 mtime=1695812441.301965847 30 atime=1695812441.301965847 30 ctime=1695812493.907719267 yadifa-2.6.5-11201/AUTHORS0000664000374500037450000000013514505005531015346 0ustar00signersigner00000000000000Gery Van Emelen Eric Diaz Fernandez yadifa-2.6.5-11201/PaxHeaders.1636/ChangeLog0000644000000000000000000000013114505005533016110 xustar000000000000000030 mtime=1695812443.200993045 30 atime=1695812443.200993045 29 ctime=1695812493.91071931 yadifa-2.6.5-11201/ChangeLog0000664000374500037450000017673414505005533016075 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ 20230906: YADIFA 2.6.5-public Secondaries will nolonger enforce the TTL value of the NSEC3PARAM record. Fixes an issue caused by a limitation of the select system call. 20230301: YADIFA 2.6.4-public Fixes an issue building for 32 bits targets. 20230213: YADIFA 2.6.3-public Fixes an issue where the answer to a DNSSEC query to a wild record right below the apex in a DNSSEC3 zone would not return all the relevant NSEC3 records Fixes an issue where the answer to a DNSSEC query to a wild record in an NSEC zone would incorrectly use the name of the query in the answer Fixes an issue where NSEC3-owning labels were not compressed Complies with Fedora https://fedoraproject.org/wiki/Changes/PortingToModernC (see m4/contributions/20230118-fedora-toolchain-porting-to-modern-c.patch) 20221209: YADIFA 2.6.2-public Fixes an issue trying to link the backtrace call while building yadifad on FreeBSD 20221130: YADIFA 2.6.1-public Fixes an issue where the answer of an TSIG-signed IXFR query over an undefined domain would not be properly signed. Fixes an issue building for big-endian architectures. 20221004: YADIFA 2.6.0-public The server can optionally load the locally stored zone before asking for the last version to its primary (load-local-first) The server now avoids storing temporary zone transfer images to disk if the zone is small enough (axfr-memory-threshold) zone transfers source address can now be specified in the configuration (transfer-source) The server now allows to sign a zone using only zone signing keys. Fixes online chain generation started from an zone that is not covered by DNSSEC. Fixes an issue where a generated DNSKEY could be missing smart fields if the storage became full right before they needed to be written. Fixes an issue that could occur using EDDSA on big-enough data sets. 20220228: YADIFA 2.5.4-public Fixes an issue handling CNAME records. 20211025: YADIFA 2.5.3-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet with privileged access. 20210929: YADIFA 2.5.2-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet with privileged access. Fixes an issue where a corrupted configuration file could lead to a crash while starting-up. 20210924: YADIFA 2.5.1-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet. Fixes an issue where yadifad would sometimes reply with an AXFR instead of an IXFR if the journal is under maintenance. Increased the pid column in the logger to 6 characters Drastically increased the limit for TCP queries. Note that using a high enough number compared to the available memory will cause yadifad to warn about limits and OOM kill risks. In practice a few hundred TCP queries should be enough. 20210602: YADIFA 2.5.0-public Adds a new, friendlier, TCP manager. When enabled, TCP connections aren't closed harshly after some time has elapased without any activity. In a nutshell: It is enabled using --enable-tcp-manager. It works using a quota of allowed parallel connections per host. There is one value for the registeres hosts and one for unknown hosts. All defined primaries are automatically added to the TCP manager as registered hosts. The server's local addresses are automatically added to the registered hosts. The default timeout is set to 3 seconds but doesn't imply a connection will be closed : only that it is a candidate for being closed. EDDSA support has been enable. Sending a TCP message now uses a single system call (message_send_tcp) Fixes an issue in some FreeBSD setups where UDP messages couldn't be sent by YADIFA. Fixes an issue in FreeBSD where TCP connections would sometimes be closed too quickly. Fixes an issue where failed dynamic updates prerequisites would return SERVFAIL instead of the more accurate error code. Fixes atomic usage for older C compilers. Fixes an issue where some RRSIG records may not be updated in time if they happened to have their update bundled with NSEC3 records updates while the incremental change could not be immediately written in the journal. Fixes the yadifa keygen module to understand "help" as a command and not as a domain. 20210223: YADIFA 2.4.2-public Fixes an issue where records below delegation are not ignored (https://github.com/yadifa/yadifa/issues/12). Fixes an issue in the _mm model where shutting down while still initializing may not stop properly. Changes default user/group to 'yadifa' user in example configuration. Fixes an issue with autoconf 2.70 obsolete functions. Fixes an issue where an unknown key configured in a zone acl may lead to a crash. Fixes an issue where an query without EDNS involving ACLs using optional keys would incorrectly be rejected. Fixes an issue where a network thread with a failed context would incorrectly have its context deleted. Adds a feature to yadifad to ensure that the dates in the key-roll section can be successfully applied for the next 10 years (--check-policies). Added support for primary and secondary variant options. Fixes builds for gcc 11. 20201209: YADIFA 2.4.1-public Fixes an issue in dnscore where a DNS TCP query would not return the real DNS error code. Fixes an issue that could happen when a network model isn't supported. Fixes the propagation of sendmmsg/recvmmsg function availability detection. Fixes an issue where yadifad would issue a warning when a key with algorithm > 7 is used with an NSEC zone. Fixes an issue that will occur on a chrooted environment where a managed-path would be used incorrectly. Fixes CNAME answers not following the aliases chain. Fixes CNAME recursion not returning the same answer as named in NXDOMAIN cases (reported by https://github.com/SivaKesava1, see https://github.com/yadifa/yadifa/issues/11) Adds patch for musl support (from https://github.com/kolbma, see https://github.com/yadifa/yadifa/issues/9#issuecomment-723047226) Adds stack size fix for musl support (the default size is way too small) Now imports a custom version of stdatomic.h for systems where it is missing, located in dnscore/thirdpary/stdatomic.h Made for CentOS 7 and any other release where that file is missing. The import is only active if strictly needed and will only be visible during the build. At the moment, it is not being installed with the other headers. The original source of the file was taken from https://gist.github.com/nhatminhle/5181506 YAKEYROLLD 2.4.1 Fixes the handling of incomplete TCP queries. Fixes a possible race-condition when initialising the keyroll context error codes. The keyroll now has another automatic recovery layer where it completely restarts the handling of a domain, generating a one-step update to put the zone in the expected state. 20201012: YADIFA 2.4.0-public Fixes an issue that could happen with multiprocess logging. Fixes an issue parsing a *. domain. Improves support for LibreSSL. Added contributions directories with community-provided patches. Readied the source for the release. Many changes have been made since version 2.3.x. Please read the manual for more information. YAKEYROLLD 2.4.0 Since version 2.4.0, yadifad optionally allows dynamic update of RRSIG records. The external key managing tool using this feature is being released along with it. Please read the manual for more information. YADIFA CTRL 2.4.0 The updated version of the command line controller has been made more user-friendly. Please read the manual for more information. 20200722: YADIFA 2.4.0-67 Default listen is now "0.0.0.0,::0" Added "do-not-listen" feature to avoid conflicts with systemd-resolved, default is empty. Added --enable-systemd-resolved-avoidance in the configure script to change the default of "do-not-listen" to "127.0.0.53 port 53" Zone file reader now decodes \ddd tokens. Text zone parsing is now more lenient in what it accepts: unescaped @ and $ in a domain will be read as '@' and '$', with a warning. Improves the configuration update by keeping a timestamp of all files involved and checking they have been modified. Logger configuration can now be reconfigured during runtime. In the event of an incorrect reconfiguration of the network, yadifad will periodically try to reconfigure itself reading the configuration files. Fixes a potential issue in NSEC3 replying. Fixes TXT parsing issues. Fixes a leak with the chroot remapping when reconfiguring. Fixes a leak processing the command line. Fixes a leak in the policies configuration. 20200630: YADIFA 2.4.0-64 Network setup errors will now stop yadifad if they occur during the first configuration. If they occur during a reconfiguration the error will be logged every minute instead of every second. Fixes DSA API usage with OpenSSL 1.1.0 Fixes an other side effect of FreeBSD's process-shared mutexes where a thread waiting on a condition wouldn't always be woken up. Fixes IPv6 handling in FreeBSD. Fixes an issue where the logging could lock when daemonizing. Fixes the build-time-configuration paths when using cmake. Fixes an issue where a sync clean command would not delete the journal if the zone wasn't dynamically updated since the start of yadifad. Fixes an issue where the size of the buffer given for a message would be slightly bigger than needed. Duplicate but identical definition of a TSIG key are nolonger considered an error. Increased the log output handling control commands (mostly error conditions) yadifa ctrl: The fqdn isn't set by default anymore (it used to be '.' by default) Adds the "freeze", "thaw", "unfreeze", "freezeall", "unfreezeall" and "thawall" friendly keywords to yadfia ctrl. Adds the "notify" command. The FQDN has no default value anymore. Fixes the friendly parsing of the command line. Fixes several minor issues with the console output of the command line. 20200608: YADIFA 2.4.0-52 This is version is going to production as primary and for public release. Fixes limit case issues giving NSEC3 answers for some zone structures (mostly *, * + CNAME) Fixes an issue where the packet reader may not allocate enough room for SOA records (found in yakeyrolld) YKEYROLL-1.0.5-4 This is version is going to production as primary and for public release. Fixes the handling of more limit cases (broken setup). 20200515: YADIFA 2.4.0-51 In an effort to find issues using different tools, the code has been partially ported to compile in Visual Studio 2019. (Doesn't run) The code analyser from Visual Studio 2019 reported 290 potential issues, 5 of which were valid (understand: errors) and not reported by other analysers. We have used a mmap.c MIT-licensed code from github to help in this task. We'll have to decide to keep it or to write ours when we will do a Windows release. Adds a DNS pcap analyser tool to measure DNS traffic from a network pcap file. Used to find why so many packets were lost in the benchmark. (resut: The benchmark tool was broken.) Adds a --disable-filepool-cache build configure option. Logs clarity has been improved. Improved usability:
network-model option can now use words instead of just numbers, respectively: single, buffered, multi for 0, 1, 2. Fixes an issue that could occur in the logger service with some settings. Fixes an issue in the new network model. Fixes a memory leak that could occur in the cirular_file layer of the journal. Fixes a memory leak that could occur in the journal depending on the reason it was closed. Fixes a memory leak that could occur at shutdown while destroying a file pool. Fixes an issue where trying to print a corrupted fqdn (e.g.: random bytes) could have an undefined behaviour. Fixes an issue using the drop-before-load feature where the memory of the previous zone would not be completely freed yet before the new version of the zone started to load. Fixes a race condition that could occur while detaching stdout/stderr from console. Fixes missing AA flag in primary notification. Fixes a rare issue where a signal could block the logger. Fixes TSIG-covered answers of an unsupported opcode. YKEYROLL-1.0.5-3 Fixes the handling of several limit cases (all coming from a broken, corrupted state). 20200320: YADIFA 2.4.0-50 Efforts have been made to reduce the memory usage in the case where a lot of specific listening addresses are defined. A new network-model taking advantage of the multiple-send/receive of some kernels has been added. (recvmmsg, sendmmsg) Back-ported gcc-10 compatibility fix from the main development branch (trunk) This issue was reported by several distributions already using the yet-to-be-released gcc-10 (We are using gcc-9) Adds the tcp_manager for experimentation (an alternative way to keep track of opened TCP connections). Fixes a potential memory leak that could sometimes happen freeing NSEC3 records without removing their attached RRSIG first. Fixes FreeBSD 12.1/libressl build issue. YKEYROLL-1.0.5-2 Now handles SIGHUP to reopen the log files. Imrpoved the command line options help. 20200212: YADIFA 2.4.0-49 This version is going for production. Fixes an issue with signature expiration value where the time was sometimes incorrectly taken from the oldest key. The RRL tables are now growing faster in order to avoid wasting resources. YKEYROLL-1.0.4-2 This version is going for production. Now keeps the expected starting point and end point for all steps. This is used to verify the state before and after each update. Now has a "print" mode that logs the "plan" out (logs all the known steps). 20200128: YADIFA 2.4.0-48 New nameserver infrastructure update. In
, adds a log_files_disabled flag to disable checking the log-path directory for existence and writing rights. Without this, yadifad would refuse to work without a proper log output directory like we have on our SELinux setup. Fixes an issue that would occur if SELinux would reject a write operation with EPERM to a socket we have succesfully opened for writing. yadifad would not complain and end-up hammering both the socket creation and the logs Fixes an issue that would occur if SELinux would reject a read operation with EPERM on a socket we have successfully opened for reading. This happens, notably, the notify service, producing a lot of log lines. Now such an issue will make yadifad pause for one second. 20200106: YADIFA 2.4.0-45 Fixes an issue where having no ZSK would trigger a useless maintenance pass. Fixes an issue where notifies could stop being sent when their queue was full. (New dynamic queue used at minimal increased CPU cost for this part) Fixes an issue where reopening or syncing would have their effect delayed. Fixes an issue that could occur for DSA T parameter deduction from a public key. Made the command line more friendly using the new features from dnscore. YKEYROLL 1.0.3-0 Now filters-out publish and unpublish meta lines. Fixes an issue where retrying to send a message to an unresponsive server could have the message content reset. 20191120: YKEYROLL-1.0.2-3 This version is going for production. Adds switching to a uid/gid set in the configuration file (must be set to the same as yadifad). Adds process mutual-exclusion for plan generation. Improves shutdown speed. Reduces logging. 20191118: YADIFA 2.4.0-43 Fixes an issue where enabling key activation leniency would incorrectly enable deactivation leniency. Fixes an issue where redundant signatures would be kept longuer than needed. The journal name for the root zone will now be root_zone.cjf (only one dot) intead of ..cjf, as that name was troublesome. YKEYROLL-1.0.1-9 This version is going for production. Can now work in a loop without detaching from console. 20191106: YADIFA 2.4.0-42 This version is going for production. Issues found by CLion's code inspector fixed or marked as invalid. Downgrades several "error" into "notice". More generally, an effort has been made to reduce the log size. Setting a policy field with an incorrect value will now log an error instead of stopping yadifad. Slave zones don't run sanitization anymore, as the primary is "right". This avoids thight rules being counter-productive in production environments. Fixes an issue that would occur if an update happens at tahe same time as the removal of a DNSKEY when a maintenance has started. Fixes an issue where the authoritative bit coudl be flipped off in some operations. Fixes an issue where removing and adding the same record in a single update would incorrectly drop its signature. Fixes an issue where a secondary receiving an inccorrect IXFR stream (specifically: finishing on an incomplete page) would not reject the broken page. Fixes an issue where a primary would cut an IXFR page in half if a shutdown was triggered while the page was being read from the journal. Fixes an issue in the policy date computation that could lead to a time period without signature coverage. 20191010: YADIFA 2.4.0-41 Fixes typos. YKEYROLL-1.0.0 Improved error codes returned by the keyroll policies. Fixes an error that could occur parsing a corrupted step file. 20190927: YADIFA 2.4.0-40 Adds a tool to append an IXFR in text form (so, from a dig command) to a journal. This is an unfriendly pure dev tool meant to create some tests scenarii. The cjf-scan tool, used to print the content of a journal, can now print its content in a way similar to the dig command. Simply use the "-clean" command line option before the journal file name. Both the above tools mean that a journal can be dumped as text, edited then re-created as binary. Although not initially created for this purpose, it can be a powerful fix tool. Fixes the "11:04" issue. It was triggered by an optimisation not being handled on all exit paths of the maintenance function, potentially leading to a buffer overflow. Fixes an issue in the journal: If the first update written into a dynamically sized journal is bigger that the default size of the journal (64KB) then yadifad incorrectly tries to shift-out content to make room, which it obviously cannot do. 20190920: YADIFA 2.4.0-39 In
, adds axfr-strict-authority option. Defaulted to enabled unless yadifad was built-configured using --enable-non-aa-axfr-support. Improves TXT parsing (github/ JZerf). Fixes an potential crash on SIGHUP if the zone loader calee gives an incorrect answer (github/kolbma). Fixes an issue where a UDP query with invalid return address (port 0) would trigger an EINVAL leading yadifa to shutdown the thread. Fixes an issue with IPv6 aliased replies. Depending on the OS/release the value could be wrong. The fix tries several options. This has been tested on several Debian and RedHat variants and seems to work properly. 20190919: YADIFA 2.4.0-38 note: Serial bump due to issues during rpm packaging. Reduces the number of warnings triggered by type bitmap fixes. Now only prints one and leaves the rest available as debug. Contains code to track the "11:04" issue and verify the hypothesis of its cause. 20190913: YADIFA 2.4.0-26 Timestamp in dns-udp are now human-readable. Writing a zone as text now computes and updates the approximate wire size for the zone (AXFR/IXFR trigger accuracy) yadifad now replies to ENDS# bad format. Fixes an issue in dns-udp where the message size would not be reset on the received side. Fixes an issue in dns-udp where the rate-limiter would fire before a message would be checked for actual IO (aggregated queries). Fixes an issue in dns-udp where a very slow call-back would slow down the processing part of the receiver enough to trigger a timeout of the query. Fixes a warning that would be shown for keys being both NSEC and NSEC3. Fixes an issue where the '#' character was incorrectly set as a zone comment. Fixes an issue where a journal with an invalid character in a name would trigger an infinite error loop (until program shutdown). Fixes an issue where a DNSKEY dynamic update coming with an RRSIG push could fail under certain conditions. Fixes some typos. YKEYROLL-beta Improves error reporting. Allows different configuration files. Fixes corrupted plan handling. Updates the configuration example. Correction updates are now merged in a single step, then played. Added error-retries-cases in daemon mode. Added a --timeus-offset parameter (not publicly documented) to lie about the current time. Added a --dryrun parameter. Fixes an issue handling key duplicates. 20190627: YADIFA 2.4.0-25 Fixes an issue where a corrupted journal would prevent a secondary from working. Fixes an issue replaying NSEC3 chain changes as a secondary that could occur when a discrepancy was found. If a corrupted journal is found, yadifad now renames it adding ".bad" to its name. 20190613: YADIFA 2.4.0-24 Adds safeguards for the logger shutdown. FreeBSD 12.0 issue diagnostic: There was an elusive issue occurring only on FreeBSD 12.0 related to shared mutexes. After posting an the issue anonymously with a proof-of-concept code, it turns out it was bug in FreeBSD: An unlocked mutex is still being accessed by the thread library right after the effective unlock has occurred. yadifad destroys a structure containing mutexes right after it is unlocked for the last time. FreeBSD has issued a fix, but at the moment the fix appeared to have side effects. This may have been us not rebuilding "world" properly (First time we do this), or it may be that the patch wasn't complete at the time. The matter is closed as far as yadifad's source code is concerned so this is something to watch after the next FreeBSD update. Added the "freebsd12-test" proof-of-concept code in the test section of the code. Adds the IP_MTU_DISCOVER IP_PMTUDISC_OMIT patch: patch received 20190323 from daisuke.higashi@gmail.com /* * Linux 3.15 has IP_PMTUDISC_OMIT which makes sockets * ignore PMTU information and send packets with DF=0. * Fragmentation is allowed if and only if the packet * size exceeds the outgoing interface MTU or the packet * encounters smaller MTU link in network. * This mitigates DNS fragmentation attacks by preventing * forged PMTU information. * FreeBSD already has same semantics without setting * the option. */ Added sereral fixes for NetBSD builds. Ultimately, NetBSD declares but does not implement PSHARED. This makes that platform unusable for the moment. Logs have been improved (level & verbosity, some have been downgraded to debug). Improves command-line help. Internally, INVALID and UNPROCESSABLE messages are now seen as the same error. In
, added log_unprocessable boolean to add a warning log for bad DNS messages. If yadifad is not started as root but requires elevated privileges in order to bind an addess, it will stop. Fixes build on older sytems (FreeBSD). Fixes an incorrect warning message related to TSIG. Fixes an issue with garbage collection at shutdown. Fixes an issue that would occur if the signature max-interval was set high enough to end up in an integer overflow. Fixes an issue where newly added keys would not always be taken into account in the computations. Fixes an issue where the nttl cache could overflow. Fixes an issue in the path provider of yadifad where an empty secondary zone file setting could lead to a NULL pointer reference. Fixes an issue where the KSK public key would not be stored, losing the flags of the key as seen by libdnscore. Fixes an issue in dns-udp that would occur when TCP fails with a DNS error. Fixes an issue in dns-udp where the thread_pool destruction order could trigger some issues. Fixes an issue where a TCP read time-out from a client (thus when the server is sending) could lead to an indefinitely held connection. Fixes an issue that could happen in the RRL, leading to the current state pool being misused. Fixes an issue where an error code sent from the socket server would nto be interpreted correctly. Fixes an issue in the text parser that was being tripped in the yakeyrolld. Fixes an issue where asking the help from the command line would return to the shell with a non-zero value. YKEYROLL-alpha Code commited in alpha state to avoid potential issues related to a certain event. The new keyroll software is being written in C. It is based on the YADIFA framework. It's main features are: _ cron-like timings, _ KSK/ZSK separation, _ RRSIG push usage, _ one event per file and one file per event, _ integrity milestones, _ extension of the time-line on demand. 20190326: YADIFA 2.4.0-23 Added autogen.sh in the make dist. Improved yadifad startup so that simply asking for its version would not go through service start. Improved AXFR log messages: now showing the peer's IP address. 20190322: YADIFA 2.4.0-22 EDDSA is known but not handled. (EDDSA handling code is in the 2.5.x branch) Sanitization now checks for DNSKEY matching RRSIG records. Fixes an issue where yadifad would abort in a specific condition: A zone that allows RRSIG pushed by dynamic updates with a bunch of inactive ZSK keys available, one of them still in the zone with said inactive ZSK key in the zone having signature expiring after its deactivation date AND in the future with an active key in the zone that does not expire and is fully usable (key pair available) with a single KSK key in the zone that has no private part available ... ... was considered fubar and triggering an emergency stop (ending up in an abort()) Fixes an issue handling BigNum from OpenSSL being sometimes smaller than expected. Fixes a double-free issue (crashed yadifad the 20190311). Fixes an issue that would occur on a secondary when the journal is too small to work optimally. Added a "dsfromkey" in the test section, to be added in the command line later 20190218: YADIFA 2.4.0-21 Fixes an issue where killing yadifad while thread creation is in limbo would not work. yadifad will now ignore all signals until notify service thread is up and running (thus outside of limbo) Fixes an issue where policies would be tried on non-policed zones. 20190213: YADIFA 2.4.0-19 Improves CPU usage by inlining several small domain-related functions. Sanitization now occurs only once, after the journal has been replayed. Code marked as obsolete has been removed. Fixes an issue where an internal update message woudln't be properly initialised. Fixes an irrelevant warning when "publish" equals "active" or "inactive" equals "delete" in a DNSKEY key. Fixes embedded delegation issues. _ Sanitization complaining about wrong glue resource records in embedded delegations _ Sanitization complaining about unexpected signatures in embedded delegations _ Internal state is now correctly set. Fixes a policy issue where a DNSSEC chain would not be added if the DNSKEY was not already generated and added. Fixes an issue where removing an RRSIG covering a type could sometimes invalidate an RRSIG covering another in the same domain. Fixes an issue where a query that would return an RDATA with a '.' domain and require additionals, would trigger a memory underflow with undefined results. Fixes an issue that could occur when replaying NSEC3 updates from the journal. Fixes dnssec-policy NSEC chain generation that could not be completed because of an interference by the internal integrity tests. Fixes an issue with NSEC3 type bitmap handling that would occur on an empty broken zone without RRSIG records. Fixes an issue where reading corrupted messages would not be handled properly. Fixes an issue where the illegal addition of a DS resource record would not be handled properly. 20190205: YADIFA 2.4.0-18 Signature verification now has an abstract API (easier extension to future algorithms e.g.: EDDSA). Added our own zone test program. This includes signatures verification. It's in the test section and the feature should be moved inside the command line later. Fixes an issue where deleting a DNSKEY in a dynamic update would not be handled properly. Fixes an issue where removing an RRSIG in signature maintenance would not change the type bitmap in the associated NSEC3 record. Fixes an issue where maintenance would remove an RRSIG for a replacement (exchange) that could not be created (e.g.: private key missing). Fixes an issue managing a zone with an NSEC3PARAM record but no NSEC3 chain. Fixes an issue where NSEC3 chain recomputation could be called before RRSIG changes would be known. Fixes an issue where stopping yadifad while it started a signature thread (in a window of a few instructions) would trigger an assertion. Fixes an issue where dnssec-policies could conflict with RRSIG pushed with a dynamic update. Fixes an issue parsing records with a class ANY in update messages. 20190109: YADIFA 2.4.0-17 Added a test for the keyroll feature (test section). Key creation time is now systematically set in newly created keys. 20181122: YADIFA 2.4.0-11 Fixes handling of several limit cases in chain updates (that should never happen in a sane system). Fixes some minor memory leaks. This is the first release that is meant to prevent DNSKEY with incorrect "smart" setup making yadifad trying to take them at every occasion (e.g.: dynamic update). 20181122: YADIFA-2.4.0-10 Made to caters for the needs of an internal project. 20180802: YADIFA 2.4.0-1 Fixes all fixable -Wextra warnings (that ar not in -Wall for some reason) One of these warnings would have showed the suprise-issue with the ACL ... These fixes needs to be thoroughly tested before being used on anything production. 20180725: YADIFA 2.4.0 alpha Fixes an issue where a secondary having downloaded a invalid zone from an primary will proceed re-download it and failing until the zone is fixed on the primary. Now it will wait until the axfr-retry + random(axfr-retry-jitter) elapsed. It is now possible to change the network configuration at runtime. It is now possible to have threads logged with a tag instead of an opaque hexadecimal ID. (--enable-log-thread-tag) It is now possible to pipe execute loggers output. e.g.: my-zipped-channel "|/usr/bin/gzip - >> /var/log/yadifa.log.gz" Obviously, outputs are run using the uid/gid set for the server. As the command can be restarted for several reasons so using >> is the obvious choice. The maximum number of queries that are queued on an overloaded server is now configurable. Note this is currently only used by network-model 1 and the ram usage in bytes is about (workers * size * 64) For a server that only needs to answer 10000 queries per second, it would be suitable to use: e.g.: network-model-worker-backlog-size 10000 Our artificial benchmark tests are showing that setting this value to 500000 is enough to handle about 2.5 millions queries per second on a server with the appropriate hardware configured properly (network queues, ...). The zone journal maximum size is now an hard limit instead of "best effort within a few bytes". The --disable-messages ./configure option has now been removed as the send & recv are not suitable for proper aliased addresses handling. The build system has been changed: From now on, to do a debug build, add CFLAGS='-O0 -g3 -DEBUG=1' to the configure command. e.g.: ./configure --enable-shared --enable-log-thread-tag CC=clang CFLAGS='-O0 -g3 -DDEBUG=1' A release build that keeps the symbols would be: ./configure --enable-log-thread-tag CC=clang CFLAGS='-O3 -g -DDEBUG=0' The dnszone library has been merged into dnscore and dnsdb. Several of our unit tests have been added as well as the valgrind suppression file (yadifad.supp). Several simplifications and abstractions have been made on the internal APIs. Network model 1 is the only model available from this version. dnssec-thread-count parameter is now obsolete 20180213: YADIFA 2.3.8 Fixes the OPT record Z flags not being cleared in server answers. 20171207: YADIFA 2.3.0 - 2.3.7 From now on, both primary and secondaries are updating the zone in the same manner (journal transactions) Messages are now default (--enable-messages). Disable them using --disable-messages. Adds more (dynamic) update validation. Adds a build option to remove compile date and time from various help messages (--disable-build-timestamp) A primary can now be configured to allow updating RRSIG records externally (e.g.: update add domain. RRSIG ...) Fixes an issue where closing an (a)XFR stream could lead to a race over the file descriptors. Fixes an issue where an AXFR query would return a version of the zone too old to be upgradable by following incremntal updates. Fixes an issue where zones with big-enough NSEC3 coverage (several millions NSEC3 record) could potentially reach an internal limit of the database. Fixes an issue where shutting down YADIFA while a zone is being downloaded (AXFR) may make it wait forever. Fixes an issue where the secondary would complain about a missing private key. Fixes an issue where a specifically truncated IXFR query may make YADIFA replying with an AXFR. Fixes an issue where an IXFR query returning "not implemented" instead of an AXFR would be retried later as an IXFR. Fixes an issue where hammering reopening the logs on an overloaded server would not work properly. 20170912: YADIFA 2.2.6 Fixes an issue where a maliciously crafted message may block the server. (CVE-2017-14339) 20170420: YADIFA 2.2.5 Fixes an issue on message-enabled servers where the return address would not be captured Increased the maximum number of network interfaces to 256 20170406: YADIFA 2.2.4 Fixes an issue with relative include names that would not always be properly computed Fixes an issue where concurrent configuration reloads could lead to a crash 20170223: YADIFA 2.3.1 (internal) Added thread_pool_try_enqueue_call to give up if a queue is full or overworked (distance project) Fixes an issue with the CW queuing mechanism when trying to fill a full queue. 20161124: YADIFA 2.3.0 (internal) ECDSA can now be disabled at ./configure time. The support of ECDSA is not available in the openssl package of older Linux distributions. You can now add --disable-ecdsa at configure time to allow a build on these systems. Processed signals are now logged upon processing (info level) to allow the admin to know when a signal has effectively gone through. CPU affinity can now be tuned to stick a worker on a core. In
: thread-affinity-multiplier can be used to use every (1) or every odd (2) logical CPU. Parameter range from 0 to 4. (default is 0 = autodetect) By default, if hypertheading is detected, the multiplier is set to 2, else to 1. thread-affinity-base can be used to chose the first local CPU to consider. Parameter range from 0 to 3. (default is 0) In the end, network workers will have their affinity set to (base + multiplier * workerindex). The main purpose is to avoid using the hyperthread logical CPU as it can be counterproductive in some setups for high (10Gbps) troughput. Fixes: - fixed an issue on servers using the network-model 1 model (
: network-model 1) - fixed an issue where the removal in a certain order of hash/hash* related domains would end-up triggering an abort - fixed an issue where querying a signed domain that was deleted would answer NOERROR instead of NXDOMAIN - fixed an issue where a zone loaded with a journal would not be marked "dirty" and thus would not be fully dumped on disk upon kill -USR1 - fixed an issue with network aliases not configured on all setups of --enable-messages - fixed an issue with the logger not releasing the log files before reconfiguration - fixed an issue with the journal where heavy load would prevent notification to secondaries 20161108: YADIFA 2.2.2 OpenSSL 1.1.0 crypto API support 20160719: YADIFA 2.2.1 Multi-primary support: Added axfr-retry-failure-delay-multiplier and axfr-retry-failure-delay-max
parameters to increase the time between two AXFR/IXFR retries on a primary. Fixes: - fixed an issue that would crash a YADIFA secondary when restarting with a journal present - fixed an issue in AXFR/IXFR retry timing management 20160715: YADIFA 2.2.0 Multi-primary support: In , the primaries field is now a list. When the primary fails to answer, it is moved to the end of the list and (new) first one is used instead. There is a true-multiprimary setting, defaulted to 'no'. In true multiprimary mode, changing the primary implies dropping local zone data and ignore serial values. This is to be used for a setup with truly independent primaries. By default, the primary change occurs at first failure. This can be changed to a higher value with multiprimary-retries (maximum: 255) This mostly makes sense on true-multiprimary mode as you want to be sure before reloading a zone completely. Smart signing: Keys with smart signing information are now handled by YADIFA. DNSSEC policies: YADIFA generates an rolls your keys and makes a non-DNSSEC zone into an NSEC or NSEC3 one. Support for ECDSA algorithm. Better support for huge incremental changes of a zone: YADIFA used to do the modification in one go, which could make it unresponsive for very big changes. Now the changes are applied more slowly, allowing queries to be answered. New network model: A new network model can be enabled. This model's main purpose is to be more resistent to system stalls with minimal, if any, performance loss.
network-model 1 NSEC3 management improved. Several improvements have been made on the way NSEC3 is handlded. Chains partially covering the zone are now accepted. Fixes: - fixed an issue where the maximum pid value supported was 99999 - fixed an issue with RRSIG TTL values that were not always at the expected value. - fixed an issue with the $TTL not being respected. 20160126: YADIFA 2.1.6 Fixes: - fixed an issue where the referral would not be measured for UDP on a optimised build. 20160108: YADIFA 2.1.5 Dynamic updates do not use temporary files anymore which improves their general performance. The statistics now shows the referrals. Fixes: - fixed an issue where getting a huge incremental transfer would prevent the server from answering queries while applying the changes. - fixed an issue serving IXFR that would occur when a incremental change step was bigger than 64KB - fixed an issue for Solaris with the memory alignment fix not active everywhere - fixed an issue on the Solaris build settings - fixed an issue where sometimes yadifad would not find a configuration file given as a parameter with a relative path - fixed an issue where a wild-card would not be properly returned with an AXFR - fixed an issue where dynamically updating a zone at a speed such that the zone file would need to be written multiple times on disk before finishing the previous write could lead to a deadlock 20151026: YADIFA 2.1.4 The zone reader error reporting has been improved. Stacktrace support added for Solaris. Known issue: - Adding and or removing NSEC3PARAM dynamically is not properly handled. Fixes: - fixed an issue where an NSEC3 answer proving a * query would lead to a crash - fixed an issue where a private key may be not recognised as such - fixed an issue where dynamic update prerequisite check would fail a valid match - fixed an issue where zone signature maintenance would only start if all private keys were available. 20150821: YADIFA 2.1.3 Fixes: - fixed an issue that could lead to a crash at startup - fixed an issue where parsing a TYPE#### record would stop the parser prematurely 20150814: YADIFA 2.1.2 The ./configure script has a new option: --enable-full-ascii7 This changes the behaviour of DNS name validation to accept all the ASCII7 characters instead of only the DNS-space ones. Enabling this option is not recommended. Fixes: - fixes an issue where the hmac-shaX identification string sent with a TSIG had the suffix ".sig-alg.reg.int". 20150714: YADIFA 2.1.1 The yadifa command line has a new option: --config|-c file : read the specific configuration file instead of ~/.yadifa.rc Issues detected on the NSEC3 database have now been upgraded from debug to info/warning Fixes: - fixed an issue where, on some cases; the garbage collector for the zones was not triggering for a long time. - fixed an issue in the Makefile (courtesy of DENIC) - fixed an issue where a few bytes could be leaked in some rare cases when failing to unload a zone - fixed an issue in RRL where some values of IPv6 prefix - fixed an issue accepting some answers on IXFR transfers 20150424: YADIFA 2.1.0 New journal file format: This new format addresses a few issues like having maximum journal file and a relatively constant random access time even for very big sizes. The internal messaging queue has been changed to address huge amount of zones. New CHaos queries supported: hostname id.server Known issues: _ building successfully with LTO may require to append both AR=gcc-ar and RANLIB=gcc-ranlib to the ./configure command 20150403: YADIFA 2.0.6 This release is a public release. This minor update's sole purpose is to fix YADIFA builds on OpenBSD. Fixes: - fixed a crash that could occur while sending a massive amount of notifications - OpenBSD builds are fixed. Tested on: OpenBSD 5.6 amd64, standard installation. Configure: ./configure Tested on: OpenBSD 5.6 amd64, with gcc 4.9 installed. Configure: ./configure CC=egcc 20150226: YADIFA 2.0.5 This release is a public release. Fixes: - fixed an issue with huge IXFR transfers as a primary - fixed an issue with notifications on secondary-secondary-primary setup - fixed an issue with a potential infinite loop loading an AXFR from a primary - fixed missing hmac-sha* from configuration - fixed an issue with TLSA records parsing - fixed an issue with base 16 encoding - fixed an issue parsing * domains - fixed an issue with some RRL motivated answers - increased the maximum number of network interfaces from 5 to 16 - fixed an error in the configuration examples where "statistics" was used instead of "stats" - minor fixes and improvements 20141216: YADIFA 2.0.4 This release is a public release. By popular demand, the default log file directory is now PREFIX/var/log/yadifa. It can be set using --with-logdir=/my/dir Improved build mechanism. It has been tested to work automatically on Linux, FreeBSD, OSX, SunOS. RedHat family builds will use -O2 as maximum optimisations. Note that some optional features are now enabled by default but can be disabled. Fixes: - fixed an issue with the AXFR transfer where the serial number would not be properly taken into account - fixed an issue with the notify mechanism that could occur if the server was only listening to 127.0.0.1 - fixed an issue with bogus DNSKEY records that may potentially lead to a crash in openssl - fixed a reported potential "tmpfile" vulnerability on DEBUG builds (generated with make debug) - fixed an issue with IPv6 connections on some architectures - typos fixes - minor fixes and improvements 20141104: Architecture portability enhancements. On Solaris, if no --enable-force32bits nor --enable-force64bits is set, then 64 bits will be forced (fixes an issue at link-time) ELF 64-bit MSB executable SPARCV9 Version 1, UltraSPARC3 Extensions Required, dynamically linked, not stripped, no debugging information available PATH=/opt/csw/bin:/usr/ccs/bin:$PATH ./configure --enable-force32bits PATH=/opt/csw/bin:/usr/ccs/bin:$PATH make 20141030: Architecture portability enhancements. FreeBSD 9 FreeBSD dnode3 9.0-RELEASE-p3 FreeBSD 9.0-RELEASE-p3 #0: Tue Jun 12 02:52:29 UTC 2012 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 gcc (GCC) 4.2.1 20070831 patched [FreeBSD] ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 9.0 (900044), not stripped Ubuntu Linux dnode10 3.2.0-49-generic #75-Ubuntu SMP Tue Jun 18 17:39:32 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xe3b8601b9b5e59f8c9ce519cacbe9b8ff544ff1d, not stripped OSX Darwin RD-Mac-Mini.local 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun 3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64 Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) Mach-O 64-bit executable x86_64 20141029: Architecture portability enhancements. uname -a gcc --version file yadifad YellowDog Linux Linux 2.6.29-3.ydl61.4 #1 SMP Mon Sep 7 14:50:27 PDT 2009 ppc64 ppc64 ppc64 GNU/Linux gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44) ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped note: using --enable-force64bits failed because of ssl, no simple/quick way to install openssl-devel.ppc64 seemed available Debian PPC64 Linux 3.2.0-3-powerpc64 #1 SMP Mon Jul 23 08:03:56 UTC 2012 ppc64 GNU/Linux gcc (Debian 4.6.3-8) 4.6.3 ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xedc47c984a4af7eb9a7ecbc0f135e4d064ba08f0, with unknown capability 0x41000000 = 0x13676e75, with unknown capability 0x10000 = 0xb0401, not stripped note: using --enable-force64bits failed because of ssl, no simple/quick way to install openssl-devel.ppc64 seemed available 20141016: YADIFA 2.0.2 TCP fallback support on truncation 20140905: YADIFA 2.0.0 This release is a public release Fixes: - fixed a log incorrectly reporting an error when the client didn't close the TCP connection fast enough - fixed an issue with the statistics on TCP queries Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. 20140829: YADIFA 2.0.0-beta3-public This release is a public release - --disable-master feature at configure now builds a secondary-only server Fixes: - fixed an issue with TSIG signed queries - fixed an issue with thread pool live resizing - fixed an issue where reading an undeleted obsolete journal ending at the start of a newly transferred zone from the primary would incorrectly trigger an error Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. 20140630: YADIFA 2.0.0-beta2-public This release is a public release - basepath disabled - pidpath removed, only pidfile remains - log reopen notification is now timestamped - secondary zones no longer complain about missing NSEC/NSEC3 private keys - the error code ZRE_FILE_NOT_FOUND has been replaced by the more accurate code ZRE_NO_VALID_FILE_FOUND - default logging settings no longer output debug Fixes: - fixed issue in flag computation (AD,CD) - fixed an issue with journal truncation sometimes leading to a crash - zone parsing now correctly accepts '#' as a comment marker - zone parsing now rejects wrong fqdn as soon as it reads them, leading to a more accurate error message - removing the last dnskey of a zone no longer crashes the server Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. yadifa remote client commands prototype is now available with the following supported commands: -shutdown shuts down yadifa e.g. ./yadifa -s "192.0.2.1 port 53" -t shutdown -cfgreload reloads the and sections of the yadifad configuration e.g. ./yadifa -s "192.0.2.1 port 53" -t cfgreload -logreopen closes and reopen the log files e.g. ./yadifa -s "192.0.2.1 port 53" -t logreopen -freezeall prevents all zones from being updated dynamically with nsupdate e.g. ./yadifa -s "192.0.2.1 port 53" -t freezeall -freeze prevents a zone from being updated dynamically with nsupdate e.g. ./yadifa -s "192.0.2.1 port 53" -t freeze -q somedomain.eu -unfreezeall enables updates of all zones again e.g. ./yadifa -s "192.0.2.1 port 53" -t unfreezeall -unfreeze enables updates of a zone again e.g. ./yadifa -s "192.0.2.1 port 53" -t unfreeze -q somedomain.eu In order to work, the allow-control ACL must be defined either in
for the global commands and may also be defined in for the ones targeting a specific zone. e.g. allow-control 127.0.0.1 Note that tsig is not supported in the client yet. 20140528: YADIFA 2.0.0-beta1-public This release is a public release - NSID implemented (enabled at ./configure time with --enable-nsid - generic parser for: - getops - zone file - resolv.conf - configuration - '@' can now be used in a zone file - new binary for controlling 'yadifad' (yadifa) - framework is rewritten for multi core systems - single core server has been removed Fixes: - fixed several minor issues Know issues: - removing all dnskeys from a zone file crashes the server - yadifa has some issues with nodelay, nocork 20130424: YADIFA 1.1.0 _ added DSA signature _ added SHA-256 SHA-384 SHA-512 digest algorithms _ now supports additional DNSSEC algorithms: DSASHA1 DSASHA1_NSEC3 RSASHA256_NSEC3 RSASHA512_NSEC3 _ Respone Rate Limitation implemented (enabled at ./configure time with --enable-rrl) _ --enable-tiny-footprint now reduces the memory usage further by reducing the standard log queue from 2^20 to 2^12 entries _ the general speed has been slightly improved _ dynamic updates pending for more than 3 seconds are now dropped with an error _ dynamic provisioning Fixes: _ fixed a memory leak that could occur at NSEC3 generation when loading the zone failed in a particular way _ fixed a memory leak at ixfr send _ fixed handling of '_' character that was improperly stored in the database _ fixed bandwidth limit settings (tcp stream in and out) not always being taken from the configuration _ fixed TSIG answer verification for notifies _ fixed error codes not being registered and thus logged as unknown hexadecimal error code. _ other minor fixes 20130612: YADIFA 1.0.3 Fixes only (backports from 1.1.0) Fixes: _ fixed an issue preventing YADIFA from being build from another directory _ fixed an issue with OSX systems where gsed has to be used instead of sed _ fixed an issue with the '_' character not being properly handled _ fixed an issue where reading MX record from a zone file would incorrecly be rejected as invalid _ fixed an issue where the OPT record would not be properly written _ fixed an issue where an undefined ACL reference would be silently ignored _ fixed missing code tags for several error codes. From now on unregistered codes are dumped in hexadicimal. _ fixed portability issues with BSD and OSX _ fixed several minor issues 20120921: YADIFA 1.0.2 Fixes only Fixes: _ fixed an issue where the journal file was sometimes not properly closed at the end of a task _ fixed an issue where the TCP usage slots would sometimes wrongly return that they were all being used _ fixed an issue on IXFR processing (secondary side) where the type of answer from the primary would not be properly detected _ fixed an issue with TSIG on secrets not exactly 16 bytes long (binary form) _ fixed an issue on 32 bits architectures where the sig-validity-* fields would not be properly handled if not set on each zone section. _ slightly improved the replay time of big journal files _ fixed several minor issues Known issues: _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120709: YADIFA 1.0.1 _ logging repeat compression is now by channel instead of global Fixes: _ fixed an issue where glibc whould assert if libgcc_s.so (libgcc_s.so.1) and libc.so (libc.so.6) where not available inside the chrooted directory of YADIFA _ fixed an issue in the syslog module Known issues: _ on 32 bits architectures, the sig-validity-* fields are not properly copied from
to as a workaround, set the sig-validity fields in each container in 32 bits architectures ie: sig-validity-interval 7 sig-validity-regeneration 168 sig-validity-jitter 3600 _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120625: YADIFA 1.0.0 _ LTO support can be enabled with --enable-lto but this is not working with clang. LTO does not increase the performance significally _ parallel processing of listening addresses can now be enabled. It can be set using thread-count-by-address in the
section. By default YADIFA will not use parallel processing as this feature has not been as thoroughly tested as the single-thread processing model _ default parameters tuning _ fixes Known issue: _ on 32 bits architectures, the sig-validity-* fields are not properly copied from
to as a workaround, set the sig-validity fields in each container in 32 bits architectures ie: sig-validity-interval 7 sig-validity-regeneration 168 sig-validity-jitter 3600 20120530: YADIFA 1.0.0RC3 _ the configuration parser now ignores undefined logger names and report them with a warning _ syslog messages are now put in the name of "yadifad" instead of the name used for the "syslog" channel _ syslog messages do not print the time from YADIFA anymore _ improved the steps involved in loading a locally cached secondary zone _ zones are now loaded in background _ man page yadifad-conf.man5 renamed into yadifad.conf.man5 Fixes: _ AXFR/IXFR answers with the RA bit set are nolonger rejected as invalid _ YADIFA now answers to SIGINT again (shutdown) _ fixed an issue where obsolete AXFR files were not always being deleted _ fixed an issue occurring when both IPv4 and IPv6 were available to handle a notify _ fixed journal replay issue where some RRSIGs records were not properly removed _ fixed an issue occurring with IPv6 queries _ fixed an issue in the generation of a specific NSEC3 error answer _ fixed named query style layout Known issue: _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120328: YADIFA 1.0.0RC2 _ fixed logging issue on work file creation error _ fixed an issue where IXFR queries could be rejected as being wrongly formatted _ fixed an issue in the query logging text _ enabled command line options ( -u uid -g gid -d ) 20120319: YADIFA 1.0.0RC1 Is a full functional authoritative name server: - works as primary or secondary name server - AXFR - IXFR - NOTIFY - NSUPDATE - TSIG - CLASSES: - IN - CH (just for version) - TYPES: - AAAA - CNAME - DNSKEY - DS - HINFO - MX - NAPTR - NS - NSEC3 - NSEC3PARAM - NSEC - PTR - RRSIG - SOA - SRV - SSHFP - TXT - Automatic resigning - DNSSEC algorithms: - 5 (RSASHA1) - 7 (RSASHA1-NSEC3 - ACL's KNOWN ISSUES: NSEC3: _ cannot work with multiple NSEC3PARAM chains with mixed OPT-IN/OUT settings _ adding a new NSEC3 chain expects that the primary sends the NSEC3PARAM first (it does not seems to be always the case) We have a case where a primary starts with 2 thousands NSEC3 opt-out records then adds 6 millions NSEC3 opt-in records but does not give the NSEC3PARAM record first. The secondary server rejects them all because it's unable to link them to a chain. (This one has high priority) DNSSEC: _ it is not allowed to change the zone security mode (unsecure, NSEC, or NSEC3). Once the zone is loaded it keeps its security mode. _ dynamic updates of NSEC as well as NSEC3 records are refused QUIT: the server will shutdown on the following conditions: _ detection of an impossible situation or an internal integrity issue (ie: for any reason the SOA has vanished from a zone) _ memory limit reached which prevents any more work _ ipc issue which prevent internal services communication ACL: _ since the access control is set by zone and CHAOS class is not implemented as a configurable zone, it is not possible (yet) to specifically block CHAOS queries. 20111121: YADIFA 0.5.5 - many fixes KNOWN ISSUE: NSEC3 secondary zone replay fails. 20110706: YADIFA 0.5.0 - secondary mode, AXFR/IXFR (no TSIG yet for the secondary-side transfer) - answers to a notify from the primary - polls the (first) primary on the primaries list - maintains the .axfr & .ix files (deletes the obsoletes ones) - TSIG queries are checked - Replays the zone journal on startup after the zone load (journaling) - Answers IXFR queries (journaling) 20110601: YADIFA 0.4.0 Operational: - It works as a no dnssec name server - No notifies to secondary name servers - daemon - Answers AXFR queries with TSIG - nsupdate functionality (journaling) - TSIG on client server side will be transmitted, but not checked - ACL works - The zone has SOA, NS A resource records. 20110524: YADIFA 0.3.0 First release internally of yadifad 20110524115500 GMT+1. Operational: - It works as a no dnssec name server - No notifies to secondary name servers - daemon - Answers AXFR queries - The zone has SOA, NS A resource records. 20091224: YADIFA 0.2.0 _ Answers AXFR queries _ ACL based on IP and TSIG (not all query types are ACL'ed yet) 20091104: YADIFA 0.1.0 YADIFA is a work in progress. The main goal is to have an alternative for BIND or NSD. Version 0.1.0 is an authoritative server only. It has no: - AXFR/IXFR functionality - dynupdate - support for NSEC - support for NSEC3 - caching mechanism - additional tools (eg.dig, dnssectools, drill,...) It has: - a very fast way to give authoritative answer - a very fast method for loading the database and checking the zone files This first release is to have a feeling how it works in an operational environment. TODO Everything what is not implemented, has to be implemented. Most of the code is there, but is not activated. No comformity tests has been done. (This of course is on the todo list) Bug Reports and Mailing Lists Bugs reports should be sent to bugreport@yadifa.eu yadifa-2.6.5-11201/PaxHeaders.1636/Makefile.in0000644000000000000000000000013114505005546016407 xustar000000000000000029 mtime=1695812454.40515351 30 atime=1695812489.642658182 30 ctime=1695812493.912719338 yadifa-2.6.5-11201/Makefile.in0000664000374500037450000007714114505005546016364 0ustar00signersigner00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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@ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ #SUBDIRS += test/journal-server @HAS_TESTS_TRUE@am__append_1 = test/circular-file-test test/cjf-scan \ @HAS_TESTS_TRUE@ test/cmdline-test test/collection-test \ @HAS_TESTS_TRUE@ test/daemonised-logger-test test/dnskey-test \ @HAS_TESTS_TRUE@ test/dnsname-test test/dnssec-test \ @HAS_TESTS_TRUE@ test/dnsserver-test test/dsfromkey-test \ @HAS_TESTS_TRUE@ test/filepool-test test/file-test \ @HAS_TESTS_TRUE@ test/freebsd12-test test/ipc-test \ @HAS_TESTS_TRUE@ test/journal-fusion test/journal-from-ixfr \ @HAS_TESTS_TRUE@ test/journal-speed-test test/keygen-test \ @HAS_TESTS_TRUE@ test/limiter-test test/logger-test \ @HAS_TESTS_TRUE@ test/message-test test/mutex-test \ @HAS_TESTS_TRUE@ test/network-interfaces-forall-test \ @HAS_TESTS_TRUE@ test/notify-test test/nsec3-answer \ @HAS_TESTS_TRUE@ test/nsec3-hash test/openssl111a-ecdsa-test \ @HAS_TESTS_TRUE@ test/openssl111a-eddsa-test test/parser-test \ @HAS_TESTS_TRUE@ test/protocol-test test/query-hammer-test \ @HAS_TESTS_TRUE@ test/rrsig-test \ @HAS_TESTS_TRUE@ test/shared-circular-buffer-test \ @HAS_TESTS_TRUE@ test/shared-heap-test \ @HAS_TESTS_TRUE@ test/simple-http-server-test test/skeleton \ @HAS_TESTS_TRUE@ test/stream-test test/threaded-queue \ @HAS_TESTS_TRUE@ test/update-test test/xfr test/zone-save-test subdir = . DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ $(srcdir)/config.h.in $(dist_noinst_DATA) COPYING ar-lib \ compile config.guess config.sub install-sh missing ltmain.sh ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/eurid.m4 $(top_srcdir)/m4/yadifa.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = 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 DATA = $(dist_noinst_DATA) 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 \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # 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)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = lib/dnscore lib/dnsdb etc doc var sbin/yadifad \ sbin/yakeyrolld lib/dnslg bin/yadifa test/circular-file-test \ test/cjf-scan test/cmdline-test test/collection-test \ test/daemonised-logger-test test/dnskey-test test/dnsname-test \ test/dnssec-test test/dnsserver-test test/dsfromkey-test \ test/filepool-test test/file-test test/freebsd12-test \ test/ipc-test test/journal-fusion test/journal-from-ixfr \ test/journal-speed-test test/keygen-test test/limiter-test \ test/logger-test test/message-test test/mutex-test \ test/network-interfaces-forall-test test/notify-test \ test/nsec3-answer test/nsec3-hash test/openssl111a-ecdsa-test \ test/openssl111a-eddsa-test test/parser-test \ test/protocol-test test/query-hammer-test test/rrsig-test \ test/shared-circular-buffer-test test/shared-heap-test \ test/simple-http-server-test test/skeleton test/stream-test \ test/threaded-queue test/update-test test/xfr \ test/zone-save-test DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) 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" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCOPTIMISATIONFLAGS = @CCOPTIMISATIONFLAGS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DNSCORE = @DNSCORE@ DNSDB = @DNSDB@ DNSLG = @DNSLG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAS_ACL_SUPPORT = @HAS_ACL_SUPPORT@ HAS_BFD_DEBUG_SUPPORT = @HAS_BFD_DEBUG_SUPPORT@ HAS_BIG_ENDIAN = @HAS_BIG_ENDIAN@ HAS_BUILD_TIMESTAMP = @HAS_BUILD_TIMESTAMP@ HAS_CC_ADDRESS_SANITIZER_CHECK = @HAS_CC_ADDRESS_SANITIZER_CHECK@ HAS_CC_ANSI = @HAS_CC_ANSI@ HAS_CC_ANSI_ALIAS = @HAS_CC_ANSI_ALIAS@ HAS_CC_CATCH_UNDEFINED_BEHAVIOR = @HAS_CC_CATCH_UNDEFINED_BEHAVIOR@ HAS_CC_DWARF2 = @HAS_CC_DWARF2@ HAS_CC_DWARF3 = @HAS_CC_DWARF3@ HAS_CC_DWARF4 = @HAS_CC_DWARF4@ HAS_CC_EXCEPTIONS = @HAS_CC_EXCEPTIONS@ HAS_CC_G = @HAS_CC_G@ HAS_CC_G3 = @HAS_CC_G3@ HAS_CC_M32 = @HAS_CC_M32@ HAS_CC_M64 = @HAS_CC_M64@ HAS_CC_MISSING_FIELD_INITIALIZERS = @HAS_CC_MISSING_FIELD_INITIALIZERS@ HAS_CC_NO_IDENT = @HAS_CC_NO_IDENT@ HAS_CC_NO_OMIT_FRAME_POINTER = @HAS_CC_NO_OMIT_FRAME_POINTER@ HAS_CC_PEDANTIC = @HAS_CC_PEDANTIC@ HAS_CC_RDYNAMIC = @HAS_CC_RDYNAMIC@ HAS_CC_SANITIZE_ADDRESS = @HAS_CC_SANITIZE_ADDRESS@ HAS_CC_STACK_PROTECTOR = @HAS_CC_STACK_PROTECTOR@ HAS_CC_STD_C11 = @HAS_CC_STD_C11@ HAS_CC_STD_C99 = @HAS_CC_STD_C99@ HAS_CC_STD_GNU11 = @HAS_CC_STD_GNU11@ HAS_CC_STD_GNU99 = @HAS_CC_STD_GNU99@ HAS_CC_TUNE_NATIVE = @HAS_CC_TUNE_NATIVE@ HAS_CC_WALL = @HAS_CC_WALL@ HAS_CC_XC99 = @HAS_CC_XC99@ HAS_CLOSE_EX_REF = @HAS_CLOSE_EX_REF@ HAS_CTRL = @HAS_CTRL@ HAS_DNSSEC_TOOLS = @HAS_DNSSEC_TOOLS@ HAS_DYNUPDATE_SUPPORT = @HAS_DYNUPDATE_SUPPORT@ HAS_ECDSA_SUPPORT = @HAS_ECDSA_SUPPORT@ HAS_EDDSA = @HAS_EDDSA@ HAS_EVENT_DYNAMIC_MODULE = @HAS_EVENT_DYNAMIC_MODULE@ HAS_FULL_ASCII7 = @HAS_FULL_ASCII7@ HAS_KEYGEN = @HAS_KEYGEN@ HAS_LIBC_MALLOC_DEBUG_SUPPORT = @HAS_LIBC_MALLOC_DEBUG_SUPPORT@ HAS_LITTLE_ENDIAN = @HAS_LITTLE_ENDIAN@ HAS_LOCK_DEBUG_SUPPORT = @HAS_LOCK_DEBUG_SUPPORT@ HAS_LOGDIR = @HAS_LOGDIR@ HAS_LOG_PID = @HAS_LOG_PID@ HAS_LOG_THREAD_ID = @HAS_LOG_THREAD_ID@ HAS_LOG_THREAD_TAG = @HAS_LOG_THREAD_TAG@ HAS_MALLOC_DEBUG_SUPPORT = @HAS_MALLOC_DEBUG_SUPPORT@ HAS_MASTER_SUPPORT = @HAS_MASTER_SUPPORT@ HAS_MEMALIGN_ISSUES = @HAS_MEMALIGN_ISSUES@ HAS_MUTEX_DEBUG_SUPPORT = @HAS_MUTEX_DEBUG_SUPPORT@ HAS_NON_AA_AXFR_SUPPORT = @HAS_NON_AA_AXFR_SUPPORT@ HAS_NSEC3_SUPPORT = @HAS_NSEC3_SUPPORT@ HAS_NSEC_SUPPORT = @HAS_NSEC_SUPPORT@ HAS_NSID_SUPPORT = @HAS_NSID_SUPPORT@ HAS_RRL_SUPPORT = @HAS_RRL_SUPPORT@ HAS_RRSIG_MANAGEMENT_SUPPORT = @HAS_RRSIG_MANAGEMENT_SUPPORT@ HAS_SYNC_BUILTINS = @HAS_SYNC_BUILTINS@ HAS_SYSTEMD_RESOLVED_AVOIDANCE = @HAS_SYSTEMD_RESOLVED_AVOIDANCE@ HAS_TESTS = @HAS_TESTS@ HAS_TOOLS = @HAS_TOOLS@ HAS_TRACK_ZONES_DEBUG_SUPPORT = @HAS_TRACK_ZONES_DEBUG_SUPPORT@ HAS_TSIG_SUPPORT = @HAS_TSIG_SUPPORT@ HAS_YADIFA = @HAS_YADIFA@ HAS_ZALLOC_DEBUG_SUPPORT = @HAS_ZALLOC_DEBUG_SUPPORT@ HAS_ZALLOC_STATISTICS_SUPPORT = @HAS_ZALLOC_STATISTICS_SUPPORT@ HAS_ZALLOC_SUPPORT = @HAS_ZALLOC_SUPPORT@ HAVE_RECVMMSG = @HAVE_RECVMMSG@ HAVE_SENDMMSG = @HAVE_SENDMMSG@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IS_BSD_FAMILY = @IS_BSD_FAMILY@ IS_DARWIN_GE14 = @IS_DARWIN_GE14@ IS_DARWIN_OS = @IS_DARWIN_OS@ IS_LINUX_FAMILY = @IS_LINUX_FAMILY@ IS_SOLARIS_FAMILY = @IS_SOLARIS_FAMILY@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL = @OPENSSL@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZDB_HAS_DNSSEC_SUPPORT = @ZDB_HAS_DNSSEC_SUPPORT@ 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_CXX = @ac_ct_CXX@ 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@ 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@ logdir = @logdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 dist_noinst_DATA = VERSION yadifa.supp autogen.sh m4/contributions/20201002-bug_971605_message_5.mbox SUBDIRS = lib/dnscore lib/dnsdb etc doc var sbin/yadifad \ sbin/yakeyrolld lib/dnslg bin/yadifa $(am__append_1) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then rm -f stamp-h1; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt # 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" 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" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist 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 -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @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 -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) config.h 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-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-tags 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 $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -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: uninstall-am: .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip distcheck distclean distclean-generic \ distclean-hdr distclean-libtool distclean-tags distcleancheck \ distdir distuninstallcheck 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 uninstall \ uninstall-am features: for m in $(SUBDIRS); do $(MAKE) -C $$m features;done # 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: yadifa-2.6.5-11201/PaxHeaders.1636/Makefile.am0000644000000000000000000000013214505005533016373 xustar000000000000000030 mtime=1695812443.617999017 30 atime=1695812444.031004932 30 ctime=1695812493.914719367 yadifa-2.6.5-11201/Makefile.am0000664000374500037450000000667714505005533016355 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ACLOCAL_AMFLAGS = -I m4 dist_noinst_DATA = VERSION yadifa.supp autogen.sh m4/contributions/20201002-bug_971605_message_5.mbox SUBDIRS = lib/dnscore lib/dnsdb SUBDIRS += etc doc var SUBDIRS += sbin/yadifad SUBDIRS += sbin/yakeyrolld SUBDIRS += lib/dnslg SUBDIRS += bin/yadifa if HAS_TESTS SUBDIRS += test/circular-file-test SUBDIRS += test/cjf-scan SUBDIRS += test/cmdline-test SUBDIRS += test/collection-test SUBDIRS += test/daemonised-logger-test SUBDIRS += test/dnskey-test SUBDIRS += test/dnsname-test SUBDIRS += test/dnssec-test SUBDIRS += test/dnsserver-test SUBDIRS += test/dsfromkey-test SUBDIRS += test/filepool-test SUBDIRS += test/file-test SUBDIRS += test/freebsd12-test SUBDIRS += test/ipc-test SUBDIRS += test/journal-fusion SUBDIRS += test/journal-from-ixfr #SUBDIRS += test/journal-server SUBDIRS += test/journal-speed-test SUBDIRS += test/keygen-test SUBDIRS += test/limiter-test SUBDIRS += test/logger-test SUBDIRS += test/message-test SUBDIRS += test/mutex-test SUBDIRS += test/network-interfaces-forall-test SUBDIRS += test/notify-test SUBDIRS += test/nsec3-answer SUBDIRS += test/nsec3-hash SUBDIRS += test/openssl111a-ecdsa-test SUBDIRS += test/openssl111a-eddsa-test SUBDIRS += test/parser-test SUBDIRS += test/protocol-test SUBDIRS += test/query-hammer-test SUBDIRS += test/rrsig-test SUBDIRS += test/shared-circular-buffer-test SUBDIRS += test/shared-heap-test SUBDIRS += test/simple-http-server-test SUBDIRS += test/skeleton SUBDIRS += test/stream-test SUBDIRS += test/threaded-queue SUBDIRS += test/update-test SUBDIRS += test/xfr SUBDIRS += test/zone-save-test endif features: for m in $(SUBDIRS); do $(MAKE) -C $$m features;done yadifa-2.6.5-11201/PaxHeaders.1636/configure0000644000000000000000000000013114505005557016250 xustar000000000000000030 mtime=1695812463.985290717 30 atime=1695812463.993290832 29 ctime=1695812493.91771941 yadifa-2.6.5-11201/configure0000775000374500037450000332162514505005557016232 0ustar00signersigner00000000000000#! /bin/sh # From configure.ac Revision: 11168 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for yadifa 2.6.5-11201. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and info@yadifa.eu $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='yadifa' PACKAGE_TARNAME='yadifa' PACKAGE_VERSION='2.6.5-11201' PACKAGE_STRING='yadifa 2.6.5-11201' PACKAGE_BUGREPORT='info@yadifa.eu' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_list= ac_func_list= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS HAS_TOOLS HAS_TOOLS_FALSE HAS_TOOLS_TRUE HAS_TESTS HAS_TESTS_FALSE HAS_TESTS_TRUE HAS_LTO_SUPPORT_FALSE HAS_LTO_SUPPORT_TRUE DNSLG DNSDB DNSCORE HAS_SOCKADDR_IN6_SIN6_LEN_FALSE HAS_SOCKADDR_IN6_SIN6_LEN_TRUE HAS_SOCKADDR_IN_SIN_LEN_FALSE HAS_SOCKADDR_IN_SIN_LEN_TRUE HAS_SOCKADDR_SA_LEN_FALSE HAS_SOCKADDR_SA_LEN_TRUE logdir HAS_LOGDIR HAS_LOGDIR_FALSE HAS_LOGDIR_TRUE HAS_EVENT_DYNAMIC_MODULE HAS_EVENT_DYNAMIC_MODULE_FALSE HAS_EVENT_DYNAMIC_MODULE_TRUE HAS_STRDUP_FALSE HAS_STRDUP_TRUE HAS_NON_AA_AXFR_SUPPORT HAS_NON_AA_AXFR_SUPPORT_FALSE HAS_NON_AA_AXFR_SUPPORT_TRUE HAS_SYSTEMD_RESOLVED_AVOIDANCE HAS_SYSTEMD_RESOLVED_AVOIDANCE_FALSE HAS_SYSTEMD_RESOLVED_AVOIDANCE_TRUE HAS_EDDSA HAS_EDDSA_FALSE HAS_EDDSA_TRUE HAS_ECDSA_SUPPORT HAS_ECDSA_SUPPORT_FALSE HAS_ECDSA_SUPPORT_TRUE HAS_FULL_ASCII7 HAS_FULL_ASCII7_FALSE HAS_FULL_ASCII7_TRUE HAS_LOG_PID HAS_LOG_PID_FALSE HAS_LOG_PID_TRUE HAS_LOG_THREAD_TAG HAS_LOG_THREAD_TAG_FALSE HAS_LOG_THREAD_TAG_TRUE HAS_LOG_THREAD_ID HAS_LOG_THREAD_ID_FALSE HAS_LOG_THREAD_ID_TRUE HAS_TRACK_ZONES_DEBUG_SUPPORT HAS_TRACK_ZONES_DEBUG_SUPPORT_FALSE HAS_TRACK_ZONES_DEBUG_SUPPORT_TRUE HAS_LOCK_DEBUG_SUPPORT HAS_LOCK_DEBUG_SUPPORT_FALSE HAS_LOCK_DEBUG_SUPPORT_TRUE HAS_MUTEX_DEBUG_SUPPORT HAS_MUTEX_DEBUG_SUPPORT_FALSE HAS_MUTEX_DEBUG_SUPPORT_TRUE HAS_BFD_DEBUG_SUPPORT HAS_BFD_DEBUG_SUPPORT_FALSE HAS_BFD_DEBUG_SUPPORT_TRUE HAS_LIBC_MALLOC_DEBUG_SUPPORT HAS_LIBC_MALLOC_DEBUG_SUPPORT_FALSE HAS_LIBC_MALLOC_DEBUG_SUPPORT_TRUE HAS_MALLOC_DEBUG_SUPPORT HAS_MALLOC_DEBUG_SUPPORT_FALSE HAS_MALLOC_DEBUG_SUPPORT_TRUE HAS_ZALLOC_DEBUG_SUPPORT HAS_ZALLOC_DEBUG_SUPPORT_FALSE HAS_ZALLOC_DEBUG_SUPPORT_TRUE HAS_ZALLOC_STATISTICS_SUPPORT HAS_ZALLOC_STATISTICS_SUPPORT_FALSE HAS_ZALLOC_STATISTICS_SUPPORT_TRUE HAS_ZALLOC_SUPPORT HAS_ZALLOC_SUPPORT_FALSE HAS_ZALLOC_SUPPORT_TRUE HAS_NSEC3_SUPPORT HAS_NSEC3_SUPPORT_FALSE HAS_NSEC3_SUPPORT_TRUE HAS_NSEC_SUPPORT HAS_NSEC_SUPPORT_FALSE HAS_NSEC_SUPPORT_TRUE ZDB_HAS_DNSSEC_SUPPORT HAS_DNSSEC_SUPPORT_FALSE HAS_DNSSEC_SUPPORT_TRUE HAS_RRSIG_MANAGEMENT_SUPPORT HAS_RRSIG_MANAGEMENT_SUPPORT_FALSE HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE HAS_DYNUPDATE_SUPPORT HAS_DYNUPDATE_SUPPORT_FALSE HAS_DYNUPDATE_SUPPORT_TRUE HAS_TSIG_SUPPORT HAS_TSIG_SUPPORT_FALSE HAS_TSIG_SUPPORT_TRUE HAS_ACL_SUPPORT HAS_ACL_SUPPORT_FALSE HAS_ACL_SUPPORT_TRUE HAS_NSID_SUPPORT HAS_NSID_SUPPORT_FALSE HAS_NSID_SUPPORT_TRUE HAS_KEYGEN HAS_KEYGEN_FALSE HAS_KEYGEN_TRUE HAS_ZONESIGN_FALSE HAS_ZONESIGN_TRUE HAS_CTRL HAS_CTRL_FALSE HAS_CTRL_TRUE HAS_MASTER_SUPPORT HAS_MASTER_SUPPORT_FALSE HAS_MASTER_SUPPORT_TRUE HAS_RRL_SUPPORT HAS_RRL_SUPPORT_FALSE HAS_RRL_SUPPORT_TRUE OPENSSL HAVE_RECVMMSG HAVE_SENDMMSG HAVE_RECVMMSG_FALSE HAVE_RECVMMSG_TRUE HAVE_SENDMMSG_FALSE HAVE_SENDMMSG_TRUE HAS_BIG_ENDIAN HAS_LITTLE_ENDIAN HAS_BIG_ENDIAN_FALSE HAS_BIG_ENDIAN_TRUE HAS_LITTLE_ENDIAN_FALSE HAS_LITTLE_ENDIAN_TRUE HAS_SYNC_BUILTINS HAS_SYNC_BUILTINS_FALSE HAS_SYNC_BUILTINS_TRUE HAS_MEMALIGN_ISSUES HAS_MEMALIGN_ISSUES_FALSE HAS_MEMALIGN_ISSUES_TRUE HAS_CC_RDYNAMIC HAS_CC_RDYNAMIC_FALSE HAS_CC_RDYNAMIC_TRUE HAS_CC_CATCH_UNDEFINED_BEHAVIOR HAS_CC_CATCH_UNDEFINED_BEHAVIOR_FALSE HAS_CC_CATCH_UNDEFINED_BEHAVIOR_TRUE HAS_CC_ADDRESS_SANITIZER_CHECK HAS_CC_ADDRESS_SANITIZER_CHECK_FALSE HAS_CC_ADDRESS_SANITIZER_CHECK_TRUE HAS_CC_NO_OMIT_FRAME_POINTER HAS_CC_NO_OMIT_FRAME_POINTER_FALSE HAS_CC_NO_OMIT_FRAME_POINTER_TRUE HAS_CC_SANITIZE_ADDRESS HAS_CC_SANITIZE_ADDRESS_FALSE HAS_CC_SANITIZE_ADDRESS_TRUE HAS_CC_MISSING_FIELD_INITIALIZERS HAS_CC_MISSING_FIELD_INITIALIZERS_FALSE HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE HAS_CC_EXCEPTIONS HAS_CC_EXCEPTIONS_FALSE HAS_CC_EXCEPTIONS_TRUE HAS_CC_STACK_PROTECTOR HAS_CC_STACK_PROTECTOR_FALSE HAS_CC_STACK_PROTECTOR_TRUE HAS_CC_DWARF4 HAS_CC_DWARF4_FALSE HAS_CC_DWARF4_TRUE HAS_CC_DWARF3 HAS_CC_DWARF3_FALSE HAS_CC_DWARF3_TRUE HAS_CC_DWARF2 HAS_CC_DWARF2_FALSE HAS_CC_DWARF2_TRUE HAS_CC_G3 HAS_CC_G3_FALSE HAS_CC_G3_TRUE HAS_CC_G HAS_CC_G_FALSE HAS_CC_G_TRUE HAS_CC_WALL HAS_CC_WALL_FALSE HAS_CC_WALL_TRUE HAS_CC_M64 HAS_CC_M64_FALSE HAS_CC_M64_TRUE HAS_CC_M32 HAS_CC_M32_FALSE HAS_CC_M32_TRUE HAS_CC_XC99 HAS_CC_XC99_FALSE HAS_CC_XC99_TRUE HAS_CC_STD_C99 HAS_CC_STD_C99_FALSE HAS_CC_STD_C99_TRUE HAS_CC_STD_GNU99 HAS_CC_STD_GNU99_FALSE HAS_CC_STD_GNU99_TRUE HAS_CC_STD_C11 HAS_CC_STD_C11_FALSE HAS_CC_STD_C11_TRUE HAS_CC_STD_GNU11 HAS_CC_STD_GNU11_FALSE HAS_CC_STD_GNU11_TRUE HAS_CC_PEDANTIC HAS_CC_PEDANTIC_FALSE HAS_CC_PEDANTIC_TRUE HAS_CC_ANSI_ALIAS HAS_CC_ANSI_ALIAS_FALSE HAS_CC_ANSI_ALIAS_TRUE HAS_CC_ANSI HAS_CC_ANSI_FALSE HAS_CC_ANSI_TRUE HAS_CC_NO_IDENT HAS_CC_NO_IDENT_FALSE HAS_CC_NO_IDENT_TRUE HAS_CC_TUNE_NATIVE HAS_CC_TUNE_NATIVE_FALSE HAS_CC_TUNE_NATIVE_TRUE CCOPTIMISATIONFLAGS USES_UNKNOWN_FALSE USES_UNKNOWN_TRUE USES_SUNC_FALSE USES_SUNC_TRUE USES_CLANG_FALSE USES_CLANG_TRUE USES_GCC_FALSE USES_GCC_TRUE USES_ICC_FALSE USES_ICC_TRUE FORCE64BITS_FALSE FORCE64BITS_TRUE FORCE32BITS_FALSE FORCE32BITS_TRUE HAS_CPU_NIAGARA_FALSE HAS_CPU_NIAGARA_TRUE HAS_CPU_AMDINTEL_FALSE HAS_CPU_AMDINTEL_TRUE IS_SOLARIS_FAMILY IS_SOLARIS_FAMILY_FALSE IS_SOLARIS_FAMILY_TRUE IS_LINUX_FAMILY IS_LINUX_FAMILY_FALSE IS_LINUX_FAMILY_TRUE IS_BSD_FAMILY IS_BSD_FAMILY_FALSE IS_BSD_FAMILY_TRUE IS_DARWIN_GE14 IS_DARWIN_OS IS_DARWIN_GE14_FALSE IS_DARWIN_GE14_TRUE IS_DARWIN_OS_FALSE IS_DARWIN_OS_TRUE CXXCPP am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX LIBOBJS CPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC ac_ct_AR AR AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM HAS_DNSSEC_TOOLS HAS_DNSSEC_TOOLS_FALSE HAS_DNSSEC_TOOLS_TRUE HAS_YADIFA HAS_YADIFA_FALSE HAS_YADIFA_TRUE HAS_CLOSE_EX_REF HAS_CLOSE_EX_REF_FALSE HAS_CLOSE_EX_REF_TRUE HAS_BUILD_TIMESTAMP HAS_BUILD_TIMESTAMP_FALSE HAS_BUILD_TIMESTAMP_TRUE target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_build_timestamp enable_fd_close_debug enable_yadifa enable_dnssec_tools enable_silent_rules enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_largefile enable_force32bits enable_force64bits with_openssl_lib with_openssl_include with_openssl enable_rrl enable_master enable_ctrl enable_keygen enable_nsid enable_dynupdate enable_rrsig_management enable_zalloc enable_zalloc_statistics enable_zalloc_debug enable_malloc_debug enable_bfd_debug enable_mutex_debug enable_lock_debug enable_track_zones_debug enable_log_thread_id enable_log_thread_tag enable_log_pid enable_full_ascii7 enable_ecdsa enable_EDDSA enable_systemd_resolved_avoidance enable_non_aa_axfr_support enable_event_dynamic_module with_logdir enable_lto with_tests with_tools ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP CXX CXXFLAGS CCC CXXCPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures yadifa 2.6.5-11201 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/yadifa] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of yadifa 2.6.5-11201:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-build-timestamp Disable Disable timestamps in the build --enable-fd-close-debug Enable close_ex(fd) to change the value of fd to detect double-closes issues (debug) --disable-yadifa Disable controller for yadifad --disable-dnssec-tools Disable DNSSEC module for yadifa --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=no] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-largefile omit support for large files --enable-force32bits Forces a 32 bits binary compilation --enable-force64bits Forces a 64 bits binary compilation --disable-rrl Disable DNS Response Rate Limiter --disable-master Disable DNS master --disable-ctrl Disable yadifa ctrl remote control tool --enable-keygen Enable yadifa keygen tool --disable-nsid Disable NSID support --disable-dynupdate Disable dynamic update support --disable-rrsig-management Disable RRSIG verification and generation for zones --disable-zalloc Disable zalloc memory system --enable-zalloc-statistics Enable zalloc statistics support --enable-zalloc-debug Enable zalloc debug support for yadifa objects --enable-malloc-debug Enable malloc debug support for yadifa objects --enable-bfd-debug Enable bfd debug support --enable-mutex-debug Enable mutex debug support --enable-lock-debug Enable zone lock debug support --enable-track-zones-debug Enable tracking of the instanciated zones for detecting potential leaks. Relatively cheap with a small (<100) amount of zones. --enable-log-thread-id Enable a column with an alphanumeric id consistent in the lowest 32 bits of a thread id in each log line --disable-log-thread-tag Disable a column with a 8 letters human-readable tag identifying a thread in each log line --disable-log-pid Disable a column with the pid in each line of log --enable-full-ascii7 Enable acceptance of ASCII7 characters in DNS names (not recommended) --disable-ecdsa Disable Elliptic Curve (ECDSA) support (Use this if the available SSL library does not support it properly) --disable-eddsa --enable-systemd-resolved-avoidance Enable to set do-not-listen to "127.0.0.53 port 53" by default (otherwise the list is empty by default) --enable-non-aa-axfr-support Enable defaults axfr-strict-authority to no. Lenient acceptance of AXFR answer from master that do not have AA bit by default (Microsoft DNS) --enable-event-dynamic-module Enable Adds support for dynamically loaded module that gets events from yadifad and is allowed to fetch some information --enable-lto Enable LTO support, requires gold linker Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-openssl-lib=DIR the openssl library from directory DIR --with-openssl-include=DIR the openssl headers from directory DIR --with-openssl=DIR the openssl from directory DIR --with-logdir With the log file directory set to this --without-tests Without various internal test programs --without-tools Without provided DNS-related tools Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF yadifa configure 2.6.5-11201 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ----------------------------- ## ## Report this to info@yadifa.eu ## ## ----------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl # ac_fn_c_find_intX_t LINENO BITS VAR # ----------------------------------- # Finds a signed integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_intX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 $as_echo_n "checking for int$2_t... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in int$2_t 'int' 'long int' \ 'long long int' 'short int' 'signed char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main () { static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main () { static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else case $ac_type in #( int$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if eval test \"x\$"$3"\" = x"no"; then : else break fi done fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_find_intX_t # ac_fn_c_find_uintX_t LINENO BITS VAR # ------------------------------------ # Finds an unsigned integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_uintX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 $as_echo_n "checking for uint$2_t... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : case $ac_type in #( uint$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if eval test \"x\$"$3"\" = x"no"; then : else break fi done fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_find_uintX_t cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by yadifa $as_me 2.6.5-11201, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi as_fn_append ac_header_list " sys/time.h" as_fn_append ac_header_list " unistd.h" as_fn_append ac_func_list " alarm" as_fn_append ac_header_list " stdlib.h" as_fn_append ac_header_list " sys/param.h" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu echo echo echo "YADIFA BUNDLE START" echo "-------------------" echo echo $0 cpu_intel_compatible=1 icc_enabled=0 ac_os_workaround_done=0 requires_tcl=0 requires_ssl=0 requires_dnscore=0 requires_dnsdb=0 requires_dnslg=0 requires_dnstcl=0 # # AC_HAS_DISABLE build_timestamp # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if BUILD_TIMESTAMP has been disabled" >&5 $as_echo_n "checking if BUILD_TIMESTAMP has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-build_timestamp was given. if test "${enable_build_timestamp+set}" = set; then : enableval=$enable_build_timestamp; fi # MSG RESULT # CASE case "y$enable_build_timestamp" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_BUILD_TIMESTAMP 1 _ACEOF # CONDITIONAL Y enable_build_timestamp=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_BUILD_TIMESTAMP 0 _ACEOF # CONDITIONAL N enable_build_timestamp=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_build_timestamp != yno; then HAS_BUILD_TIMESTAMP_TRUE= HAS_BUILD_TIMESTAMP_FALSE='#' else HAS_BUILD_TIMESTAMP_TRUE='#' HAS_BUILD_TIMESTAMP_FALSE= fi # SUBST # AC_HAS_DISABLE build_timestamp DONE # # AC_HAS_ENABLE fd_close_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if CLOSE_EX_REF has been enabled" >&5 $as_echo_n "checking if CLOSE_EX_REF has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-fd_close_debug was given. if test "${enable_fd_close_debug+set}" = set; then : enableval=$enable_fd_close_debug; fi # CASE case "y$enable_fd_close_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_CLOSE_EX_REF 1 _ACEOF # CONDITIONAL Y enable_fd_close_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_CLOSE_EX_REF 0 _ACEOF # CONDITIONAL N enable_fd_close_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_fd_close_debug = yyes; then HAS_CLOSE_EX_REF_TRUE= HAS_CLOSE_EX_REF_FALSE='#' else HAS_CLOSE_EX_REF_TRUE='#' HAS_CLOSE_EX_REF_FALSE= fi # SUBST # AC_HAS_ENABLE fd_close_debug DONE # # AC_HAS_DISABLE yadifa # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if YADIFA has been disabled" >&5 $as_echo_n "checking if YADIFA has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-yadifa was given. if test "${enable_yadifa+set}" = set; then : enableval=$enable_yadifa; fi # MSG RESULT # CASE case "y$enable_yadifa" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_YADIFA 1 _ACEOF # CONDITIONAL Y enable_yadifa=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_YADIFA 0 _ACEOF # CONDITIONAL N enable_yadifa=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_yadifa != yno; then HAS_YADIFA_TRUE= HAS_YADIFA_FALSE='#' else HAS_YADIFA_TRUE='#' HAS_YADIFA_FALSE= fi # SUBST # AC_HAS_DISABLE yadifa DONE # # AC_HAS_DISABLE dnssec_tools # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if DNSSEC_TOOLS has been disabled" >&5 $as_echo_n "checking if DNSSEC_TOOLS has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-dnssec_tools was given. if test "${enable_dnssec_tools+set}" = set; then : enableval=$enable_dnssec_tools; fi # MSG RESULT # CASE case "y$enable_dnssec_tools" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_DNSSEC_TOOLS 1 _ACEOF # CONDITIONAL Y enable_dnssec_tools=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_DNSSEC_TOOLS 0 _ACEOF # CONDITIONAL N enable_dnssec_tools=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_dnssec_tools != yno; then HAS_DNSSEC_TOOLS_TRUE= HAS_DNSSEC_TOOLS_FALSE='#' else HAS_DNSSEC_TOOLS_TRUE='#' HAS_DNSSEC_TOOLS_FALSE= fi # SUBST # AC_HAS_DISABLE dnssec_tools DONE ac_aux_dir= for ac_dir in . "$srcdir"/.; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in . \"$srcdir\"/." "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. am__api_version='1.13' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='yadifa' VERSION='2.6.5-11201' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a pax tar archive" >&5 $as_echo_n "checking how to create a pax tar archive... " >&6; } # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_pax-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do { echo "$as_me:$LINENO: $_am_tar --version" >&5 ($_am_tar --version) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && break done am__tar="$_am_tar --format=posix -chf - "'"$$tardir"' am__tar_="$_am_tar --format=posix -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x pax -w "$$tardir"' am__tar_='pax -L -x pax -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H pax -L' am__tar_='find "$tardir" -print | cpio -o -H pax -L' am__untar='cpio -i -H pax -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_pax}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -rf conftest.dir if test -s conftest.tar; then { echo "$as_me:$LINENO: $am__untar &5 ($am__untar &5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 (cat conftest.dir/file) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } grep GrepMe conftest.dir/file >/dev/null 2>&1 && break fi done rm -rf conftest.dir if ${am_cv_prog_tar_pax+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_prog_tar_pax=$_am_tool fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_pax" >&5 $as_echo "$am_cv_prog_tar_pax" >&6; } ac_config_headers="$ac_config_headers config.h" DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi if test -n "$ac_tool_prefix"; then for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} { $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 $as_echo_n "checking the archiver ($AR) interface... " >&6; } if ${am_cv_ar_interface+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_ar_interface=ar cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int some_variable = 0; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 $as_echo "$am_cv_ar_interface" >&6; } case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) as_fn_error $? "could not determine $AR interface" "$LINENO" 5 ;; esac # automake version < 1.14 if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. if { ac_try='cc -c conftest.$ac_ext >&5' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # cc works too. : else # cc exists but doesn't like -o. eval ac_cv_prog_cc_${ac_cc}_c_o=no fi fi fi else eval ac_cv_prog_cc_${ac_cc}_c_o=no fi rm -f core conftest* fi if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h fi # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.2' macro_revision='1.3337' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=no fi enable_dlopen=no enable_win32_dll=no # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: case "$(uname -s)" in Darwin) alias libtoolize="glibtoolize" which libtool > /dev/null 2>&1 if [ $? -ne 0 ] then which glibtool > /dev/null 2>&1 if [ $? -eq 0 ] then alias libtool="glibtool" fi fi echo 'brol' | sed 's/brol/truc/' > /dev/null 2>&1 if [ $? -ne 0 ] then alias sed="gsed" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: Darwin workaround" >&5 $as_echo "Darwin workaround" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: nothing to do" >&5 $as_echo "nothing to do" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for printf in -lc" >&5 $as_echo_n "checking for printf in -lc... " >&6; } if ${ac_cv_lib_c_printf+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char printf (); int main () { return printf (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_printf=yes else ac_cv_lib_c_printf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_printf" >&5 $as_echo "$ac_cv_lib_c_printf" >&6; } if test "x$ac_cv_lib_c_printf" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBC 1 _ACEOF LIBS="-lc $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5 $as_echo_n "checking for library containing pthread_create... " >&6; } if ${ac_cv_search_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF for ac_lib in '' pthread; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_pthread_create=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_pthread_create+:} false; then : break fi done if ${ac_cv_search_pthread_create+:} false; then : else ac_cv_search_pthread_create=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5 $as_echo "$ac_cv_search_pthread_create" >&6; } ac_res=$ac_cv_search_pthread_create if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 $as_echo_n "checking for library containing clock_gettime... " >&6; } if ${ac_cv_search_clock_gettime+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char clock_gettime (); int main () { return clock_gettime (); ; return 0; } _ACEOF for ac_lib in '' rt; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_clock_gettime=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_clock_gettime+:} false; then : break fi done if ${ac_cv_search_clock_gettime+:} false; then : else ac_cv_search_clock_gettime=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 $as_echo "$ac_cv_search_clock_gettime" >&6; } ac_res=$ac_cv_search_clock_gettime if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi # Autoupdate added the next two lines to ensure that your configure # script's behavior did not change. They are probably safe to remove. # # for ac_header in arpa/inet.h fcntl.h netinet/in.h stdlib.h stdio.h string.h sys/time.h syslog.h unistd.h stdatomic.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Check for Darwin or Linux for ac_header in linux/limits.h sys/syslimits.h i386/limits.h ppc/limits.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Check for Darwin or Linux for ac_header in sys/types.h i386/types.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/socket.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default" if test "x$ac_cv_header_sys_socket_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_SOCKET_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" if test "x$ac_cv_type_mode_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define mode_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } if ${ac_cv_struct_tm+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct tm tm; int *p = &tm.tm_sec; return !p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_tm=time.h else ac_cv_struct_tm=sys/time.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 $as_echo "$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then $as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default" if test "x$ac_cv_type_uint8_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT8_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default" if test "x$ac_cv_type_int8_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT8_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default" if test "x$ac_cv_type_uint16_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT16_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default" if test "x$ac_cv_type_int16_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT16_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default" if test "x$ac_cv_type_uint32_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT32_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default" if test "x$ac_cv_type_int32_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT32_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default" if test "x$ac_cv_type_uint64_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT64_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default" if test "x$ac_cv_type_int64_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT64_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default" if test "x$ac_cv_type_long_long" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LONG_LONG 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "u_char" "ac_cv_type_u_char" "$ac_includes_default" if test "x$ac_cv_type_u_char" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_U_CHAR 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "uint8_t" "ac_cv_type_uint8_t" "$ac_includes_default" if test "x$ac_cv_type_uint8_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT8_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default" if test "x$ac_cv_type_int8_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT8_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "uint16_t" "ac_cv_type_uint16_t" "$ac_includes_default" if test "x$ac_cv_type_uint16_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT16_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default" if test "x$ac_cv_type_int16_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT16_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "$ac_includes_default" if test "x$ac_cv_type_uint32_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT32_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default" if test "x$ac_cv_type_int32_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT32_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "$ac_includes_default" if test "x$ac_cv_type_uint64_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UINT64_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default" if test "x$ac_cv_type_int64_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INT64_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default" if test "x$ac_cv_type_long_long" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LONG_LONG 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "u_char" "ac_cv_type_u_char" "$ac_includes_default" if test "x$ac_cv_type_u_char" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_U_CHAR 1 _ACEOF fi for ac_func in bzero memset select socket atexit clock_gettime dup2 fdatasync ftruncate getcwd gethostname getpagesize gettimeofday inet_ntoa localtime_r memchr memmove memset mkdir mkfifo munmap select socket strcasecmp strchr strdup strerror strncasecmp strrchr strtol timegm do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/ioctl.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default" if test "x$ac_cv_header_sys_ioctl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_IOCTL_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 $as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } if ${ac_cv_header_stdbool_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifndef bool "error: bool is not defined" #endif #ifndef false "error: false is not defined" #endif #if false "error: false is not 0" #endif #ifndef true "error: true is not defined" #endif #if true != 1 "error: true is not 1" #endif #ifndef __bool_true_false_are_defined "error: __bool_true_false_are_defined is not defined" #endif struct s { _Bool s: 1; _Bool t; } s; char a[true == 1 ? 1 : -1]; char b[false == 0 ? 1 : -1]; char c[__bool_true_false_are_defined == 1 ? 1 : -1]; char d[(bool) 0.5 == true ? 1 : -1]; /* See body of main program for 'e'. */ char f[(_Bool) 0.0 == false ? 1 : -1]; char g[true]; char h[sizeof (_Bool)]; char i[sizeof s.t]; enum { j = false, k = true, l = false * true, m = true * 256 }; /* The following fails for HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ _Bool n[m]; char o[sizeof n == m * sizeof n[0] ? 1 : -1]; char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; /* Catch a bug in an HP-UX C compiler. See http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html */ _Bool q = true; _Bool *pq = &q; int main () { bool e = &s; *pq |= q; *pq |= ! q; /* Refer to every declared value, to avoid compiler optimizations. */ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + !m + !n + !o + !p + !q + !pq); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdbool_h=yes else ac_cv_header_stdbool_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 $as_echo "$ac_cv_header_stdbool_h" >&6; } ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" if test "x$ac_cv_type__Bool" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE__BOOL 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "ptrdiff_t" "ac_cv_type_ptrdiff_t" "$ac_includes_default" if test "x$ac_cv_type_ptrdiff_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PTRDIFF_T 1 _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5 $as_echo_n "checking for C/C++ restrict keyword... " >&6; } if ${ac_cv_c_restrict+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_restrict=no # The order here caters to the fact that C++ does not require restrict. for ac_kw in __restrict __restrict__ _Restrict restrict; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ typedef int * int_ptr; int foo (int_ptr $ac_kw ip) { return ip[0]; } int main () { int s[1]; int * $ac_kw t = s; t[0] = 0; return foo(t) ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_restrict=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_restrict" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5 $as_echo "$ac_cv_c_restrict" >&6; } case $ac_cv_c_restrict in restrict) ;; no) $as_echo "#define restrict /**/" >>confdefs.h ;; *) cat >>confdefs.h <<_ACEOF #define restrict $ac_cv_c_restrict _ACEOF ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi for ac_header in unistd.h do : ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" if test "x$ac_cv_header_unistd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UNISTD_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working chown" >&5 $as_echo_n "checking for working chown... " >&6; } if ${ac_cv_func_chown_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_chown_works=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #include int main () { char *f = "conftest.chown"; struct stat before, after; if (creat (f, 0600) < 0) return 1; if (stat (f, &before) < 0) return 1; if (chown (f, (uid_t) -1, (gid_t) -1) == -1) return 1; if (stat (f, &after) < 0) return 1; return ! (before.st_uid == after.st_uid && before.st_gid == after.st_gid); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_chown_works=yes else ac_cv_func_chown_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f conftest.chown fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_chown_works" >&5 $as_echo "$ac_cv_func_chown_works" >&6; } if test $ac_cv_func_chown_works = yes; then $as_echo "#define HAVE_CHOWN 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for error_at_line" >&5 $as_echo_n "checking for error_at_line... " >&6; } if ${ac_cv_lib_error_at_line+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { error_at_line (0, 0, "", 0, "an error occurred"); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_error_at_line=yes else ac_cv_lib_error_at_line=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_error_at_line" >&5 $as_echo "$ac_cv_lib_error_at_line" >&6; } if test $ac_cv_lib_error_at_line = no; then case " $LIBOBJS " in *" error.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS error.$ac_objext" ;; esac fi for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if ${ac_cv_func_fork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if ${ac_cv_func_vfork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if ${ac_cv_func_malloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi for ac_header in $ac_header_list do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in $ac_func_list do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mktime" >&5 $as_echo_n "checking for working mktime... " >&6; } if ${ac_cv_func_working_mktime+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_working_mktime=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Test program from Paul Eggert and Tony Leneis. */ #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #ifdef HAVE_UNISTD_H # include #endif #ifndef HAVE_ALARM # define alarm(X) /* empty */ #endif /* Work around redefinition to rpl_putenv by other config tests. */ #undef putenv static time_t time_t_max; static time_t time_t_min; /* Values we'll use to set the TZ environment variable. */ static const char *tz_strings[] = { (const char *) 0, "TZ=GMT0", "TZ=JST-9", "TZ=EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00" }; #define N_STRINGS (sizeof (tz_strings) / sizeof (tz_strings[0])) /* Return 0 if mktime fails to convert a date in the spring-forward gap. Based on a problem report from Andreas Jaeger. */ static int spring_forward_gap () { /* glibc (up to about 1998-10-07) failed this test. */ struct tm tm; /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" instead of "TZ=America/Vancouver" in order to detect the bug even on systems that don't support the Olson extension, or don't have the full zoneinfo tables installed. */ putenv ((char*) "TZ=PST8PDT,M4.1.0,M10.5.0"); tm.tm_year = 98; tm.tm_mon = 3; tm.tm_mday = 5; tm.tm_hour = 2; tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; return mktime (&tm) != (time_t) -1; } static int mktime_test1 (time_t now) { struct tm *lt; return ! (lt = localtime (&now)) || mktime (lt) == now; } static int mktime_test (time_t now) { return (mktime_test1 (now) && mktime_test1 ((time_t) (time_t_max - now)) && mktime_test1 ((time_t) (time_t_min + now))); } static int irix_6_4_bug () { /* Based on code from Ariel Faigon. */ struct tm tm; tm.tm_year = 96; tm.tm_mon = 3; tm.tm_mday = 0; tm.tm_hour = 0; tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; mktime (&tm); return tm.tm_mon == 2 && tm.tm_mday == 31; } static int bigtime_test (int j) { struct tm tm; time_t now; tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j; now = mktime (&tm); if (now != (time_t) -1) { struct tm *lt = localtime (&now); if (! (lt && lt->tm_year == tm.tm_year && lt->tm_mon == tm.tm_mon && lt->tm_mday == tm.tm_mday && lt->tm_hour == tm.tm_hour && lt->tm_min == tm.tm_min && lt->tm_sec == tm.tm_sec && lt->tm_yday == tm.tm_yday && lt->tm_wday == tm.tm_wday && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst) == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst)))) return 0; } return 1; } static int year_2050_test () { /* The correct answer for 2050-02-01 00:00:00 in Pacific time, ignoring leap seconds. */ unsigned long int answer = 2527315200UL; struct tm tm; time_t t; tm.tm_year = 2050 - 1900; tm.tm_mon = 2 - 1; tm.tm_mday = 1; tm.tm_hour = tm.tm_min = tm.tm_sec = 0; tm.tm_isdst = -1; /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" instead of "TZ=America/Vancouver" in order to detect the bug even on systems that don't support the Olson extension, or don't have the full zoneinfo tables installed. */ putenv ((char*) "TZ=PST8PDT,M4.1.0,M10.5.0"); t = mktime (&tm); /* Check that the result is either a failure, or close enough to the correct answer that we can assume the discrepancy is due to leap seconds. */ return (t == (time_t) -1 || (0 < t && answer - 120 <= t && t <= answer + 120)); } int main () { time_t t, delta; int i, j; /* This test makes some buggy mktime implementations loop. Give up after 60 seconds; a mktime slower than that isn't worth using anyway. */ alarm (60); for (;;) { t = (time_t_max << 1) + 1; if (t <= time_t_max) break; time_t_max = t; } time_t_min = - ((time_t) ~ (time_t) 0 == (time_t) -1) - time_t_max; delta = time_t_max / 997; /* a suitable prime number */ for (i = 0; i < N_STRINGS; i++) { if (tz_strings[i]) putenv ((char*) tz_strings[i]); for (t = 0; t <= time_t_max - delta; t += delta) if (! mktime_test (t)) return 1; if (! (mktime_test ((time_t) 1) && mktime_test ((time_t) (60 * 60)) && mktime_test ((time_t) (60 * 60 * 24)))) return 1; for (j = 1; ; j <<= 1) if (! bigtime_test (j)) return 1; else if (INT_MAX / 2 < j) break; if (! bigtime_test (INT_MAX)) return 1; } return ! (irix_6_4_bug () && spring_forward_gap () && year_2050_test ()); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_working_mktime=yes else ac_cv_func_working_mktime=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_working_mktime" >&5 $as_echo "$ac_cv_func_working_mktime" >&6; } if test $ac_cv_func_working_mktime = no; then case " $LIBOBJS " in *" mktime.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mktime.$ac_objext" ;; esac fi for ac_func in getpagesize do : ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" if test "x$ac_cv_func_getpagesize" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETPAGESIZE 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mmap" >&5 $as_echo_n "checking for working mmap... " >&6; } if ${ac_cv_func_mmap_fixed_mapped+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_mmap_fixed_mapped=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default /* malloc might have been renamed as rpl_malloc. */ #undef malloc /* Thanks to Mike Haertel and Jim Avera for this test. Here is a matrix of mmap possibilities: mmap private not fixed mmap private fixed at somewhere currently unmapped mmap private fixed at somewhere already mapped mmap shared not fixed mmap shared fixed at somewhere currently unmapped mmap shared fixed at somewhere already mapped For private mappings, we should verify that changes cannot be read() back from the file, nor mmap's back from the file at a different address. (There have been systems where private was not correctly implemented like the infamous i386 svr4.0, and systems where the VM page cache was not coherent with the file system buffer cache like early versions of FreeBSD and possibly contemporary NetBSD.) For shared mappings, we should conversely verify that changes get propagated back to all the places they're supposed to be. Grep wants private fixed already mapped. The main things grep needs to know about mmap are: * does it exist and is it safe to write into the mmap'd area * how to use it (BSD variants) */ #include #include #if !defined STDC_HEADERS && !defined HAVE_STDLIB_H char *malloc (); #endif /* This mess was copied from the GNU getpagesize.h. */ #ifndef HAVE_GETPAGESIZE # ifdef _SC_PAGESIZE # define getpagesize() sysconf(_SC_PAGESIZE) # else /* no _SC_PAGESIZE */ # ifdef HAVE_SYS_PARAM_H # include # ifdef EXEC_PAGESIZE # define getpagesize() EXEC_PAGESIZE # else /* no EXEC_PAGESIZE */ # ifdef NBPG # define getpagesize() NBPG * CLSIZE # ifndef CLSIZE # define CLSIZE 1 # endif /* no CLSIZE */ # else /* no NBPG */ # ifdef NBPC # define getpagesize() NBPC # else /* no NBPC */ # ifdef PAGESIZE # define getpagesize() PAGESIZE # endif /* PAGESIZE */ # endif /* no NBPC */ # endif /* no NBPG */ # endif /* no EXEC_PAGESIZE */ # else /* no HAVE_SYS_PARAM_H */ # define getpagesize() 8192 /* punt totally */ # endif /* no HAVE_SYS_PARAM_H */ # endif /* no _SC_PAGESIZE */ #endif /* no HAVE_GETPAGESIZE */ int main () { char *data, *data2, *data3; const char *cdata2; int i, pagesize; int fd, fd2; pagesize = getpagesize (); /* First, make a file with some known garbage in it. */ data = (char *) malloc (pagesize); if (!data) return 1; for (i = 0; i < pagesize; ++i) *(data + i) = rand (); umask (0); fd = creat ("conftest.mmap", 0600); if (fd < 0) return 2; if (write (fd, data, pagesize) != pagesize) return 3; close (fd); /* Next, check that the tail of a page is zero-filled. File must have non-zero length, otherwise we risk SIGBUS for entire page. */ fd2 = open ("conftest.txt", O_RDWR | O_CREAT | O_TRUNC, 0600); if (fd2 < 0) return 4; cdata2 = ""; if (write (fd2, cdata2, 1) != 1) return 5; data2 = (char *) mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L); if (data2 == MAP_FAILED) return 6; for (i = 0; i < pagesize; ++i) if (*(data2 + i)) return 7; close (fd2); if (munmap (data2, pagesize)) return 8; /* Next, try to mmap the file at a fixed address which already has something else allocated at it. If we can, also make sure that we see the same garbage. */ fd = open ("conftest.mmap", O_RDWR); if (fd < 0) return 9; if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L)) return 10; for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data2 + i)) return 11; /* Finally, make sure that changes to the mapped area do not percolate back to the file as seen by read(). (This is a bug on some variants of i386 svr4.0.) */ for (i = 0; i < pagesize; ++i) *(data2 + i) = *(data2 + i) + 1; data3 = (char *) malloc (pagesize); if (!data3) return 12; if (read (fd, data3, pagesize) != pagesize) return 13; for (i = 0; i < pagesize; ++i) if (*(data + i) != *(data3 + i)) return 14; close (fd); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_mmap_fixed_mapped=yes else ac_cv_func_mmap_fixed_mapped=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_fixed_mapped" >&5 $as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; } if test $ac_cv_func_mmap_fixed_mapped = yes; then $as_echo "#define HAVE_MMAP 1" >>confdefs.h fi rm -f conftest.mmap conftest.txt for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 $as_echo_n "checking for GNU libc compatible realloc... " >&6; } if ${ac_cv_func_realloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_realloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *realloc (); #endif int main () { return ! realloc (0, 0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_realloc_0_nonnull=yes else ac_cv_func_realloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 $as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } if test $ac_cv_func_realloc_0_nonnull = yes; then : $as_echo "#define HAVE_REALLOC 1" >>confdefs.h else $as_echo "#define HAVE_REALLOC 0" >>confdefs.h case " $LIBOBJS " in *" realloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS realloc.$ac_objext" ;; esac $as_echo "#define realloc rpl_realloc" >>confdefs.h fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec_CXX='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_CXX='-berok' # Determine the default libpath from the value encoded in an empty # executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' ${wl}-bernotok' allow_undefined_flag_CXX=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes # This is similar to how AIX traditionally builds its shared # libraries. archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='${wl}--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" if test "$lt_cv_apple_cc_single_mod" != "yes"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi else ld_shlibs_CXX=no fi ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; gnu*) ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd2*) # C++ shared libraries are fairly broken ld_shlibs_CXX=no ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='${wl}-E' whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then no_undefined_flag_CXX=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='${wl}-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='${wl}-z,text' allow_undefined_flag_CXX='${wl}-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no GCC_CXX="$GXX" LD_CXX="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX="${prev}${p}" else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX="${prev}${p}" else postdeps_CXX="${postdeps_CXX} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$predep_objects_CXX"; then predep_objects_CXX="$p" else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX="$p" else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then postdeps_CXX='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then postdeps_CXX='-library=Cstd -library=Crun' fi ;; esac ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then : else lt_prog_compiler_static_CXX= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 $as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test "X$hardcode_automatic_CXX" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct_CXX" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no && test "$hardcode_minus_L_CXX" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } if test "$hardcode_action_CXX" = relink || test "$inherit_rpath_CXX" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_fn_c_check_member "$LINENO" "struct tm" "tm_zone" "ac_cv_member_struct_tm_tm_zone" "#include #include <$ac_cv_struct_tm> " if test "x$ac_cv_member_struct_tm_tm_zone" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_TM_TM_ZONE 1 _ACEOF fi if test "$ac_cv_member_struct_tm_tm_zone" = yes; then $as_echo "#define HAVE_TM_ZONE 1" >>confdefs.h else ac_fn_c_check_decl "$LINENO" "tzname" "ac_cv_have_decl_tzname" "#include " if test "x$ac_cv_have_decl_tzname" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_TZNAME $ac_have_decl _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tzname" >&5 $as_echo_n "checking for tzname... " >&6; } if ${ac_cv_var_tzname+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if !HAVE_DECL_TZNAME extern char *tzname[]; #endif int main () { return tzname[0][0]; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_var_tzname=yes else ac_cv_var_tzname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_var_tzname" >&5 $as_echo "$ac_cv_var_tzname" >&6; } if test $ac_cv_var_tzname = yes; then $as_echo "#define HAVE_TZNAME 1" >>confdefs.h fi fi ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t" case $ac_cv_c_int16_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int16_t $ac_cv_c_int16_t _ACEOF ;; esac ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t" case $ac_cv_c_int32_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int32_t $ac_cv_c_int32_t _ACEOF ;; esac ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t" case $ac_cv_c_int64_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int64_t $ac_cv_c_int64_t _ACEOF ;; esac ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t" case $ac_cv_c_int8_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int8_t $ac_cv_c_int8_t _ACEOF ;; esac ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" if test "x$ac_cv_type_off_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define off_t long int _ACEOF fi ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" if test "x$ac_cv_type_ssize_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define ssize_t int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t" case $ac_cv_c_uint16_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define uint16_t $ac_cv_c_uint16_t _ACEOF ;; esac ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" case $ac_cv_c_uint32_t in #( no|yes) ;; #( *) $as_echo "#define _UINT32_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint32_t $ac_cv_c_uint32_t _ACEOF ;; esac ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" case $ac_cv_c_uint64_t in #( no|yes) ;; #( *) $as_echo "#define _UINT64_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint64_t $ac_cv_c_uint64_t _ACEOF ;; esac ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t" case $ac_cv_c_uint8_t in #( no|yes) ;; #( *) $as_echo "#define _UINT8_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint8_t $ac_cv_c_uint8_t _ACEOF ;; esac for ac_header in sys/select.h sys/socket.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking types of arguments for select" >&5 $as_echo_n "checking types of arguments for select... " >&6; } if ${ac_cv_func_select_args+:} false; then : $as_echo_n "(cached) " >&6 else for ac_arg234 in 'fd_set *' 'int *' 'void *'; do for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif int main () { extern int select ($ac_arg1, $ac_arg234, $ac_arg234, $ac_arg234, $ac_arg5); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done done done # Provide a safe default value. : "${ac_cv_func_select_args=int,int *,struct timeval *}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_select_args" >&5 $as_echo "$ac_cv_func_select_args" >&6; } ac_save_IFS=$IFS; IFS=',' set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'` IFS=$ac_save_IFS shift cat >>confdefs.h <<_ACEOF #define SELECT_TYPE_ARG1 $1 _ACEOF cat >>confdefs.h <<_ACEOF #define SELECT_TYPE_ARG234 ($2) _ACEOF cat >>confdefs.h <<_ACEOF #define SELECT_TYPE_ARG5 ($3) _ACEOF rm -f conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat correctly handles trailing slash" >&5 $as_echo_n "checking whether lstat correctly handles trailing slash... " >&6; } if ${ac_cv_func_lstat_dereferences_slashed_symlink+:} false; then : $as_echo_n "(cached) " >&6 else rm -f conftest.sym conftest.file echo >conftest.file if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then if test "$cross_compiling" = yes; then : ac_cv_func_lstat_dereferences_slashed_symlink=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; /* Linux will dereference the symlink and fail, as required by POSIX. That is better in the sense that it means we will not have to compile and use the lstat wrapper. */ return lstat ("conftest.sym/", &sbuf) == 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_lstat_dereferences_slashed_symlink=yes else ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi else # If the `ln -s' command failed, then we probably don't even # have an lstat function. ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f conftest.sym conftest.file fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5 $as_echo "$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; } test $ac_cv_func_lstat_dereferences_slashed_symlink = yes && cat >>confdefs.h <<_ACEOF #define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 _ACEOF if test "x$ac_cv_func_lstat_dereferences_slashed_symlink" = xno; then case " $LIBOBJS " in *" lstat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS lstat.$ac_objext" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat accepts an empty string" >&5 $as_echo_n "checking whether stat accepts an empty string... " >&6; } if ${ac_cv_func_stat_empty_string_bug+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_stat_empty_string_bug=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; return stat ("", &sbuf) == 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_stat_empty_string_bug=no else ac_cv_func_stat_empty_string_bug=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_stat_empty_string_bug" >&5 $as_echo "$ac_cv_func_stat_empty_string_bug" >&6; } if test $ac_cv_func_stat_empty_string_bug = yes; then case " $LIBOBJS " in *" stat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS stat.$ac_objext" ;; esac cat >>confdefs.h <<_ACEOF #define HAVE_STAT_EMPTY_STRING_BUG 1 _ACEOF fi # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 $as_echo_n "checking for special C compiler options needed for large files... " >&6; } if ${ac_cv_sys_largefile_CC+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : break fi rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_largefile_CC=' -n32'; break fi rm -f core conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 $as_echo "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 $as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=64; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 $as_echo "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF ;; esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 $as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=1; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 $as_echo "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF ;; esac rm -rf conftest* fi fi if [ $ac_os_workaround_done -eq 0 ] then ac_os_workaround_done=1 { $as_echo "$as_me:${as_lineno-$LINENO}: checking what kind of OS this is" >&5 $as_echo_n "checking what kind of OS this is... " >&6; } is_darwin_os=0 is_bsd_family=0 is_solaris_family=0 is_linux_family=0 case "$(uname -s)" in Darwin) is_darwin_os=1 is_bsd_family=1 osx_version_major=$(uname -r|sed 's/\..*//') { $as_echo "$as_me:${as_lineno-$LINENO}: result: OSX $osx_version_major" >&5 $as_echo "OSX $osx_version_major" >&6; } CFLAGS="$CFLAGS -D__APPLE_USE_RFC_3542=1" ;; FreeBSD) is_bsd_family=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: BSD" >&5 $as_echo "BSD" >&6; } ;; Linux) is_linux_family=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux" >&5 $as_echo "Linux" >&6; } ;; SunOS) is_solaris_family=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: SunOS" >&5 $as_echo "SunOS" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: not specifically supported" >&5 $as_echo "not specifically supported" >&6; } ;; esac if [ "$is_darwin_os" = "" ] then echo "OS detection failed to give relevant results" exit 1; fi if [ $is_darwin_os -ne 0 ] then cat >>confdefs.h <<_ACEOF #define IS_DARWIN_OS 1 _ACEOF is_darwin_os_txt="yes" if [ $osx_version_major -ge 14 ] then osx_version_major_ge14="yes" else osx_version_major_ge14="no" fi else cat >>confdefs.h <<_ACEOF #define IS_DARWIN_OS 0 _ACEOF is_darwin_os_txt="no" osx_version_major_ge14="no" fi if test "y$isdarwin_os_txt" == "yyes"; then IS_DARWIN_OS_TRUE= IS_DARWIN_OS_FALSE='#' else IS_DARWIN_OS_TRUE='#' IS_DARWIN_OS_FALSE= fi if test "y$osx_version_major_ge14" == "yyes"; then IS_DARWIN_GE14_TRUE= IS_DARWIN_GE14_FALSE='#' else IS_DARWIN_GE14_TRUE='#' IS_DARWIN_GE14_FALSE= fi if [ $is_bsd_family -ne 0 ] then is_bsd_family_txt="yes" cat >>confdefs.h <<_ACEOF #define IS_BSD_FAMILY 1 _ACEOF else is_bsd_family_txt="no" cat >>confdefs.h <<_ACEOF #define IS_BSD_FAMILY 0 _ACEOF fi if test "y$is_bsd_family_txt" == "yyes"; then IS_BSD_FAMILY_TRUE= IS_BSD_FAMILY_FALSE='#' else IS_BSD_FAMILY_TRUE='#' IS_BSD_FAMILY_FALSE= fi if [ $is_linux_family -ne 0 ] then is_linux_family_txt="yes" cat >>confdefs.h <<_ACEOF #define IS_LINUX_FAMILY 1 _ACEOF else is_linux_family_txt="no" cat >>confdefs.h <<_ACEOF #define IS_LINUX_FAMILY 0 _ACEOF fi if test "y$is_linux_family_txt" == "yyes"; then IS_LINUX_FAMILY_TRUE= IS_LINUX_FAMILY_FALSE='#' else IS_LINUX_FAMILY_TRUE='#' IS_LINUX_FAMILY_FALSE= fi if [ $is_solaris_family -ne 0 ] then is_solaris_family_txt="yes" cat >>confdefs.h <<_ACEOF #define IS_SOLARIS_FAMILY 1 _ACEOF else is_solaris_family_txt="no" cat >>confdefs.h <<_ACEOF #define IS_SOLARIS_FAMILY 0 _ACEOF fi if test "y$is_solaris_family_txt" == "yyes"; then IS_SOLARIS_FAMILY_TRUE= IS_SOLARIS_FAMILY_FALSE='#' else IS_SOLARIS_FAMILY_TRUE='#' IS_SOLARIS_FAMILY_FALSE= fi fi cat >>confdefs.h <<_ACEOF #define DEFAULT_ASSUMED_CPU_COUNT 2 _ACEOF cpu_intel_compatible=1 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the CPU options" >&5 $as_echo_n "checking for the CPU options... " >&6; } cpu_unknown=1 has_cpu_niagara=0 has_cpu_amdintel=0 CFLAGS3264= case "$(uname -i 2>/dev/null)" in SUNW,SPARC-Enterprise-T1000) cat >>confdefs.h <<_ACEOF #define HAS_CPU_NIAGARA 1 _ACEOF has_cpu_niagara=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: UtrasparcT1" >&5 $as_echo "UtrasparcT1" >&6; } CFLAGS3264=-m64 cpu_unknown=0 cpu_intel_compatible=0 ;; *) ;; esac if test "x$host_cpu" = xx86_64; then : cat >>confdefs.h <<_ACEOF #define HAS_CPU_AMDINTEL 1 _ACEOF if true; then HAS_CPU_AMDINTEL_TRUE= HAS_CPU_AMDINTEL_FALSE='#' else HAS_CPU_AMDINTEL_TRUE='#' HAS_CPU_AMDINTEL_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: AMD/Intel ($host)" >&5 $as_echo "AMD/Intel ($host)" >&6; } if test "x$host" = "xx86_64-linux-gnux32"; then : else CFLAGS3264=-m64 fi CPU_UNKNOWN=0 cpu_intel_compatible=1 fi case "${cpu_unknown}" in 1) { $as_echo "$as_me:${as_lineno-$LINENO}: result: generic" >&5 $as_echo "generic" >&6; } ;; 0) ;; esac if test $has_cpu_niagara -eq 1; then HAS_CPU_NIAGARA_TRUE= HAS_CPU_NIAGARA_FALSE='#' else HAS_CPU_NIAGARA_TRUE='#' HAS_CPU_NIAGARA_FALSE= fi if test $has_cpu_amdintel -eq 1; then HAS_CPU_AMDINTEL_TRUE= HAS_CPU_AMDINTEL_FALSE='#' else HAS_CPU_AMDINTEL_TRUE='#' HAS_CPU_AMDINTEL_FALSE= fi if [ "$is_solaris_family" = "" ] then echo "OS must be detected first" exit 1 fi if [ $is_solaris_family -eq 1 ] then echo "Solaris ..." { $as_echo "$as_me:${as_lineno-$LINENO}: checking if either force 32 or 64 bits is enabled" >&5 $as_echo_n "checking if either force 32 or 64 bits is enabled... " >&6; } if [ ! "$enable_force32bits" = "yes" ] then if [ ! "$enable_force64bits" = "yes" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forcing 64 bits" >&5 $as_echo "no, forcing 64 bits" >&6; } enable_force64bits="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi else echo "Not Solaris ..." fi echo "Force ..." { $as_echo "$as_me:${as_lineno-$LINENO}: checking if force 32 bits is enabled" >&5 $as_echo_n "checking if force 32 bits is enabled... " >&6; } # Check whether --enable-force32bits was given. if test "${enable_force32bits+set}" = set; then : enableval=$enable_force32bits; enable_force32bits=yes else enable_force32bits=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_force32bits" >&5 $as_echo "$enable_force32bits" >&6; } case "$enable_force32bits" in yes) CFLAGS3264=-m32 ;; *) ;; esac if test "y$enable_force32bits" == "yyes"; then FORCE32BITS_TRUE= FORCE32BITS_FALSE='#' else FORCE32BITS_TRUE='#' FORCE32BITS_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if force 64 bits is enabled" >&5 $as_echo_n "checking if force 64 bits is enabled... " >&6; } # Check whether --enable-force64bits was given. if test "${enable_force64bits+set}" = set; then : enableval=$enable_force64bits; enable_force64bits=yes else enable_force64bits=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_force64bits" >&5 $as_echo "$enable_force64bits" >&6; } case "$enable_force64bits" in yes) CFLAGS3264=-m64 if [ "$enable_force32" = "yes" ] then echo "cannot do both --enable-force32bits and --enable-force64bits at the same time" exit 1 fi ;; *) ;; esac if test "y$enable_force64bits" = "yyes"; then FORCE64BITS_TRUE= FORCE64BITS_FALSE='#' else FORCE64BITS_TRUE='#' FORCE64BITS_FALSE= fi cat /etc/redhat-version > /dev/null 2>&1 if [ $? -eq 0 ] then is_redhat_family=1 else is_redhat_family=0 fi EURID_CFLAGS= VERSION_OPT=--version $CC --version > /dev/null 2>&1 if [ $? -ne 0 ] then $CC -V > /dev/null 2>&1 if [ $? -ne 0 ] then CCVER='0.0' CCNAME='unknown' VERSION_OPT='' else VERSION_OPT='-V' fi fi if [ ! "$VERSION_OPT" = "" ] then CCVER=$($CC $VERSION_OPT 2>&1|head -1|sed 's/[^0-9.]*\([0-9.]*\).*/\1/') if [ "$CCVER" = "" ] then CCVER='0.0' fi CCNAME=$($CC $VERSION_OPT 2>&1|head -1|sed -e 's/.*clang.*/clang/' -e 's/.*gcc.*/gcc/' -e 's/.*icc.*/icc/' -e 's/.*Sun C.*/Sun C/'|tr A-Z a-z) if [ "$CCNAME" = "" ] then CCNAME='unknown' fi else CCVER='0.0' CCNAME='unknown' fi # version opt CCMAJOR=$(echo $CCVER | sed 's/\./ /g' | awk '{ print $1}') CCMINOR=$(echo $CCVER | sed 's/\./ /g' | awk '{ print $2}') if [ "$CCMAJOR" = "" ] then CCMAJOR=0 fi if [ "$CCMINOR" = "" ] then CCMINOR=0 fi uses_icc=0 uses_gcc=0 uses_clang=0 uses_sunc=0 uses_unknown=0 if [ "$CCNAME" = "gcc" ] then CCOPTIMISATIONFLAGS=-O3 if [ $CCMAJOR -lt 4 ] then CCOPTIMISATIONFLAGS=-O0 echo "WARNING: GCC < 4.0 has optimisations issues with YADIFA." sleep 1 elif [ $CCMAJOR -eq 4 ] then if [ $CCMINOR -lt 6 ] then CCOPTIMISATIONFLAGS=-O0 echo "WARNING: GCC before 4.6 have optimisation issues with YADIFA." sleep 1 elif [ $CCMINOR -eq 6 ] then CCOPTIMISATIONFLAGS=-O2 else # hopefully after 4.6 the issue is fixed ... CCOPTIMISATIONFLAGS=-O3 fi fi uses_gcc=1 elif [ "$CCNAME" = "icc" ] then echo "ICC" CCOPTIMISATIONFLAGS=-O3 uses_icc=1 AR=xiar elif [ "$CCNAME" = "clang" ] then echo "CLANG" CCOPTIMISATIONFLAGS=-O3 uses_clang=1 elif [ "$CCNAME" = "Sun C" ] then echo "Sun C" CCOPTIMISATIONFLAGS=-xO5 uses_sunc=1 else echo "unsupported compiler" CCNAME=$CC CCOPTIMISATIONFLAGS=-O2 uses_unknown=1 fi if test $uses_icc -eq 1; then USES_ICC_TRUE= USES_ICC_FALSE='#' else USES_ICC_TRUE='#' USES_ICC_FALSE= fi if test $uses_gcc -eq 1; then USES_GCC_TRUE= USES_GCC_FALSE='#' else USES_GCC_TRUE='#' USES_GCC_FALSE= fi if test $uses_clang -eq 1; then USES_CLANG_TRUE= USES_CLANG_FALSE='#' else USES_CLANG_TRUE='#' USES_CLANG_FALSE= fi if test $uses_sunc -eq 1; then USES_SUNC_TRUE= USES_SUNC_FALSE='#' else USES_SUNC_TRUE='#' USES_SUNC_FALSE= fi if test $uses_unknown -eq 1; then USES_UNKNOWN_TRUE= USES_UNKNOWN_FALSE='#' else USES_UNKNOWN_TRUE='#' USES_UNKNOWN_FALSE= fi # # We've been told RedHat does not like -O3 at all, so ... # if [ $is_redhat_family -ne 0 ] then if [ "$CCOPTIMISATIONFLAGS " eq "-O3" ] then CCOPTIMISATIONFLAGS=-O2 fi fi echo "detected compiler is $CCNAME $CCMAJOR $CCMINOR" CCOPTIMISATIONFLAGS=$CCOPTIMISATIONFLAGS if [ $cpu_intel_compatible -eq 0 ] then if [ $icc_enabled -ne 0 ] then echo "ERROR: cannot enable ICC with CPU other than x86 or amd64" exit 1 fi fi # # AC_COMPILER_SUPPORTS -mtune=native # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mtune=native" >&5 $as_echo_n "checking if compiler supports -mtune=native... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-TUNE_NATIVE.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -mtune=native test-gcc-TUNE_NATIVE.c -o test-gcc-TUNE_NATIVE > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_TUNE_NATIVE="no" if false; then HAS_CC_TUNE_NATIVE_TRUE= HAS_CC_TUNE_NATIVE_FALSE='#' else HAS_CC_TUNE_NATIVE_TRUE='#' HAS_CC_TUNE_NATIVE_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_TUNE_NATIVE 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_TUNE_NATIVE="yes" if true; then HAS_CC_TUNE_NATIVE_TRUE= HAS_CC_TUNE_NATIVE_FALSE='#' else HAS_CC_TUNE_NATIVE_TRUE='#' HAS_CC_TUNE_NATIVE_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_TUNE_NATIVE 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_TUNE_NATIVE" == "yyes"; then HAS_CC_TUNE_NATIVE_TRUE= HAS_CC_TUNE_NATIVE_FALSE='#' else HAS_CC_TUNE_NATIVE_TRUE='#' HAS_CC_TUNE_NATIVE_FALSE= fi # SUBST rm -rf test-gcc-TUNE_NATIVE* # # AC_COMPILER_SUPPORTS -fno-ident # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -fno-ident" >&5 $as_echo_n "checking if compiler supports -fno-ident... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-NO_IDENT.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -fno-ident test-gcc-NO_IDENT.c -o test-gcc-NO_IDENT > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_NO_IDENT="no" if false; then HAS_CC_NO_IDENT_TRUE= HAS_CC_NO_IDENT_FALSE='#' else HAS_CC_NO_IDENT_TRUE='#' HAS_CC_NO_IDENT_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_NO_IDENT 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_NO_IDENT="yes" if true; then HAS_CC_NO_IDENT_TRUE= HAS_CC_NO_IDENT_FALSE='#' else HAS_CC_NO_IDENT_TRUE='#' HAS_CC_NO_IDENT_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_NO_IDENT 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_NO_IDENT" == "yyes"; then HAS_CC_NO_IDENT_TRUE= HAS_CC_NO_IDENT_FALSE='#' else HAS_CC_NO_IDENT_TRUE='#' HAS_CC_NO_IDENT_FALSE= fi # SUBST rm -rf test-gcc-NO_IDENT* # # AC_COMPILER_SUPPORTS -ansi # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -ansi" >&5 $as_echo_n "checking if compiler supports -ansi... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-ANSI.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -ansi test-gcc-ANSI.c -o test-gcc-ANSI > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_ANSI="no" if false; then HAS_CC_ANSI_TRUE= HAS_CC_ANSI_FALSE='#' else HAS_CC_ANSI_TRUE='#' HAS_CC_ANSI_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_ANSI 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_ANSI="yes" if true; then HAS_CC_ANSI_TRUE= HAS_CC_ANSI_FALSE='#' else HAS_CC_ANSI_TRUE='#' HAS_CC_ANSI_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_ANSI 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_ANSI" == "yyes"; then HAS_CC_ANSI_TRUE= HAS_CC_ANSI_FALSE='#' else HAS_CC_ANSI_TRUE='#' HAS_CC_ANSI_FALSE= fi # SUBST rm -rf test-gcc-ANSI* # # AC_COMPILER_SUPPORTS -ansi-alias # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -ansi-alias" >&5 $as_echo_n "checking if compiler supports -ansi-alias... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-ANSI_ALIAS.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -ansi-alias test-gcc-ANSI_ALIAS.c -o test-gcc-ANSI_ALIAS > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_ANSI_ALIAS="no" if false; then HAS_CC_ANSI_ALIAS_TRUE= HAS_CC_ANSI_ALIAS_FALSE='#' else HAS_CC_ANSI_ALIAS_TRUE='#' HAS_CC_ANSI_ALIAS_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_ANSI_ALIAS 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_ANSI_ALIAS="yes" if true; then HAS_CC_ANSI_ALIAS_TRUE= HAS_CC_ANSI_ALIAS_FALSE='#' else HAS_CC_ANSI_ALIAS_TRUE='#' HAS_CC_ANSI_ALIAS_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_ANSI_ALIAS 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_ANSI_ALIAS" == "yyes"; then HAS_CC_ANSI_ALIAS_TRUE= HAS_CC_ANSI_ALIAS_FALSE='#' else HAS_CC_ANSI_ALIAS_TRUE='#' HAS_CC_ANSI_ALIAS_FALSE= fi # SUBST rm -rf test-gcc-ANSI_ALIAS* # # AC_COMPILER_SUPPORTS -pedantic # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -pedantic" >&5 $as_echo_n "checking if compiler supports -pedantic... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-PEDANTIC.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -pedantic test-gcc-PEDANTIC.c -o test-gcc-PEDANTIC > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_PEDANTIC="no" if false; then HAS_CC_PEDANTIC_TRUE= HAS_CC_PEDANTIC_FALSE='#' else HAS_CC_PEDANTIC_TRUE='#' HAS_CC_PEDANTIC_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_PEDANTIC 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_PEDANTIC="yes" if true; then HAS_CC_PEDANTIC_TRUE= HAS_CC_PEDANTIC_FALSE='#' else HAS_CC_PEDANTIC_TRUE='#' HAS_CC_PEDANTIC_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_PEDANTIC 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_PEDANTIC" == "yyes"; then HAS_CC_PEDANTIC_TRUE= HAS_CC_PEDANTIC_FALSE='#' else HAS_CC_PEDANTIC_TRUE='#' HAS_CC_PEDANTIC_FALSE= fi # SUBST rm -rf test-gcc-PEDANTIC* # # AC_COMPILER_SUPPORTS -std=gnu11 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -std=gnu11" >&5 $as_echo_n "checking if compiler supports -std=gnu11... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-STD_GNU11.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -std=gnu11 test-gcc-STD_GNU11.c -o test-gcc-STD_GNU11 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_STD_GNU11="no" if false; then HAS_CC_STD_GNU11_TRUE= HAS_CC_STD_GNU11_FALSE='#' else HAS_CC_STD_GNU11_TRUE='#' HAS_CC_STD_GNU11_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_STD_GNU11 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_STD_GNU11="yes" if true; then HAS_CC_STD_GNU11_TRUE= HAS_CC_STD_GNU11_FALSE='#' else HAS_CC_STD_GNU11_TRUE='#' HAS_CC_STD_GNU11_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_STD_GNU11 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_STD_GNU11" == "yyes"; then HAS_CC_STD_GNU11_TRUE= HAS_CC_STD_GNU11_FALSE='#' else HAS_CC_STD_GNU11_TRUE='#' HAS_CC_STD_GNU11_FALSE= fi # SUBST rm -rf test-gcc-STD_GNU11* # # AC_COMPILER_SUPPORTS -std=c11 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -std=c11" >&5 $as_echo_n "checking if compiler supports -std=c11... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-STD_C11.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -std=c11 test-gcc-STD_C11.c -o test-gcc-STD_C11 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_STD_C11="no" if false; then HAS_CC_STD_C11_TRUE= HAS_CC_STD_C11_FALSE='#' else HAS_CC_STD_C11_TRUE='#' HAS_CC_STD_C11_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_STD_C11 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_STD_C11="yes" if true; then HAS_CC_STD_C11_TRUE= HAS_CC_STD_C11_FALSE='#' else HAS_CC_STD_C11_TRUE='#' HAS_CC_STD_C11_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_STD_C11 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_STD_C11" == "yyes"; then HAS_CC_STD_C11_TRUE= HAS_CC_STD_C11_FALSE='#' else HAS_CC_STD_C11_TRUE='#' HAS_CC_STD_C11_FALSE= fi # SUBST rm -rf test-gcc-STD_C11* # # AC_COMPILER_SUPPORTS -std=gnu99 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -std=gnu99" >&5 $as_echo_n "checking if compiler supports -std=gnu99... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-STD_GNU99.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -std=gnu99 test-gcc-STD_GNU99.c -o test-gcc-STD_GNU99 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_STD_GNU99="no" if false; then HAS_CC_STD_GNU99_TRUE= HAS_CC_STD_GNU99_FALSE='#' else HAS_CC_STD_GNU99_TRUE='#' HAS_CC_STD_GNU99_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_STD_GNU99 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_STD_GNU99="yes" if true; then HAS_CC_STD_GNU99_TRUE= HAS_CC_STD_GNU99_FALSE='#' else HAS_CC_STD_GNU99_TRUE='#' HAS_CC_STD_GNU99_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_STD_GNU99 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_STD_GNU99" == "yyes"; then HAS_CC_STD_GNU99_TRUE= HAS_CC_STD_GNU99_FALSE='#' else HAS_CC_STD_GNU99_TRUE='#' HAS_CC_STD_GNU99_FALSE= fi # SUBST rm -rf test-gcc-STD_GNU99* # # AC_COMPILER_SUPPORTS -std=c99 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -std=c99" >&5 $as_echo_n "checking if compiler supports -std=c99... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-STD_C99.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -std=c99 test-gcc-STD_C99.c -o test-gcc-STD_C99 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_STD_C99="no" if false; then HAS_CC_STD_C99_TRUE= HAS_CC_STD_C99_FALSE='#' else HAS_CC_STD_C99_TRUE='#' HAS_CC_STD_C99_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_STD_C99 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_STD_C99="yes" if true; then HAS_CC_STD_C99_TRUE= HAS_CC_STD_C99_FALSE='#' else HAS_CC_STD_C99_TRUE='#' HAS_CC_STD_C99_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_STD_C99 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_STD_C99" == "yyes"; then HAS_CC_STD_C99_TRUE= HAS_CC_STD_C99_FALSE='#' else HAS_CC_STD_C99_TRUE='#' HAS_CC_STD_C99_FALSE= fi # SUBST rm -rf test-gcc-STD_C99* # # AC_COMPILER_SUPPORTS -xc99 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -xc99" >&5 $as_echo_n "checking if compiler supports -xc99... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-XC99.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -xc99 test-gcc-XC99.c -o test-gcc-XC99 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_XC99="no" if false; then HAS_CC_XC99_TRUE= HAS_CC_XC99_FALSE='#' else HAS_CC_XC99_TRUE='#' HAS_CC_XC99_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_XC99 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_XC99="yes" if true; then HAS_CC_XC99_TRUE= HAS_CC_XC99_FALSE='#' else HAS_CC_XC99_TRUE='#' HAS_CC_XC99_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_XC99 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_XC99" == "yyes"; then HAS_CC_XC99_TRUE= HAS_CC_XC99_FALSE='#' else HAS_CC_XC99_TRUE='#' HAS_CC_XC99_FALSE= fi # SUBST rm -rf test-gcc-XC99* # # AC_COMPILER_SUPPORTS -m32 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -m32" >&5 $as_echo_n "checking if compiler supports -m32... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-M32.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -m32 test-gcc-M32.c -o test-gcc-M32 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_M32="no" if false; then HAS_CC_M32_TRUE= HAS_CC_M32_FALSE='#' else HAS_CC_M32_TRUE='#' HAS_CC_M32_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_M32 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_M32="yes" if true; then HAS_CC_M32_TRUE= HAS_CC_M32_FALSE='#' else HAS_CC_M32_TRUE='#' HAS_CC_M32_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_M32 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_M32" == "yyes"; then HAS_CC_M32_TRUE= HAS_CC_M32_FALSE='#' else HAS_CC_M32_TRUE='#' HAS_CC_M32_FALSE= fi # SUBST rm -rf test-gcc-M32* # # AC_COMPILER_SUPPORTS -m64 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -m64" >&5 $as_echo_n "checking if compiler supports -m64... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-M64.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -m64 test-gcc-M64.c -o test-gcc-M64 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_M64="no" if false; then HAS_CC_M64_TRUE= HAS_CC_M64_FALSE='#' else HAS_CC_M64_TRUE='#' HAS_CC_M64_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_M64 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_M64="yes" if true; then HAS_CC_M64_TRUE= HAS_CC_M64_FALSE='#' else HAS_CC_M64_TRUE='#' HAS_CC_M64_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_M64 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_M64" == "yyes"; then HAS_CC_M64_TRUE= HAS_CC_M64_FALSE='#' else HAS_CC_M64_TRUE='#' HAS_CC_M64_FALSE= fi # SUBST rm -rf test-gcc-M64* # # AC_COMPILER_SUPPORTS -Wall # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -Wall" >&5 $as_echo_n "checking if compiler supports -Wall... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-WALL.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -Wall test-gcc-WALL.c -o test-gcc-WALL > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_WALL="no" if false; then HAS_CC_WALL_TRUE= HAS_CC_WALL_FALSE='#' else HAS_CC_WALL_TRUE='#' HAS_CC_WALL_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_WALL 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_WALL="yes" if true; then HAS_CC_WALL_TRUE= HAS_CC_WALL_FALSE='#' else HAS_CC_WALL_TRUE='#' HAS_CC_WALL_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_WALL 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_WALL" == "yyes"; then HAS_CC_WALL_TRUE= HAS_CC_WALL_FALSE='#' else HAS_CC_WALL_TRUE='#' HAS_CC_WALL_FALSE= fi # SUBST rm -rf test-gcc-WALL* # # AC_COMPILER_SUPPORTS -g # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -g" >&5 $as_echo_n "checking if compiler supports -g... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-G.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -g test-gcc-G.c -o test-gcc-G > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_G="no" if false; then HAS_CC_G_TRUE= HAS_CC_G_FALSE='#' else HAS_CC_G_TRUE='#' HAS_CC_G_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_G 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_G="yes" if true; then HAS_CC_G_TRUE= HAS_CC_G_FALSE='#' else HAS_CC_G_TRUE='#' HAS_CC_G_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_G 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_G" == "yyes"; then HAS_CC_G_TRUE= HAS_CC_G_FALSE='#' else HAS_CC_G_TRUE='#' HAS_CC_G_FALSE= fi # SUBST rm -rf test-gcc-G* # # AC_COMPILER_SUPPORTS -g3 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -g3" >&5 $as_echo_n "checking if compiler supports -g3... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-G3.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -g3 test-gcc-G3.c -o test-gcc-G3 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_G3="no" if false; then HAS_CC_G3_TRUE= HAS_CC_G3_FALSE='#' else HAS_CC_G3_TRUE='#' HAS_CC_G3_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_G3 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_G3="yes" if true; then HAS_CC_G3_TRUE= HAS_CC_G3_FALSE='#' else HAS_CC_G3_TRUE='#' HAS_CC_G3_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_G3 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_G3" == "yyes"; then HAS_CC_G3_TRUE= HAS_CC_G3_FALSE='#' else HAS_CC_G3_TRUE='#' HAS_CC_G3_FALSE= fi # SUBST rm -rf test-gcc-G3* # # AC_COMPILER_SUPPORTS -gdwarf-2 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -gdwarf-2" >&5 $as_echo_n "checking if compiler supports -gdwarf-2... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-DWARF2.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -gdwarf-2 test-gcc-DWARF2.c -o test-gcc-DWARF2 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_DWARF2="no" if false; then HAS_CC_DWARF2_TRUE= HAS_CC_DWARF2_FALSE='#' else HAS_CC_DWARF2_TRUE='#' HAS_CC_DWARF2_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_DWARF2 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_DWARF2="yes" if true; then HAS_CC_DWARF2_TRUE= HAS_CC_DWARF2_FALSE='#' else HAS_CC_DWARF2_TRUE='#' HAS_CC_DWARF2_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_DWARF2 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_DWARF2" == "yyes"; then HAS_CC_DWARF2_TRUE= HAS_CC_DWARF2_FALSE='#' else HAS_CC_DWARF2_TRUE='#' HAS_CC_DWARF2_FALSE= fi # SUBST rm -rf test-gcc-DWARF2* # # AC_COMPILER_SUPPORTS -gdwarf-3 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -gdwarf-3" >&5 $as_echo_n "checking if compiler supports -gdwarf-3... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-DWARF3.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -gdwarf-3 test-gcc-DWARF3.c -o test-gcc-DWARF3 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_DWARF3="no" if false; then HAS_CC_DWARF3_TRUE= HAS_CC_DWARF3_FALSE='#' else HAS_CC_DWARF3_TRUE='#' HAS_CC_DWARF3_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_DWARF3 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_DWARF3="yes" if true; then HAS_CC_DWARF3_TRUE= HAS_CC_DWARF3_FALSE='#' else HAS_CC_DWARF3_TRUE='#' HAS_CC_DWARF3_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_DWARF3 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_DWARF3" == "yyes"; then HAS_CC_DWARF3_TRUE= HAS_CC_DWARF3_FALSE='#' else HAS_CC_DWARF3_TRUE='#' HAS_CC_DWARF3_FALSE= fi # SUBST rm -rf test-gcc-DWARF3* # # AC_COMPILER_SUPPORTS -gdwarf-4 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -gdwarf-4" >&5 $as_echo_n "checking if compiler supports -gdwarf-4... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-DWARF4.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -gdwarf-4 test-gcc-DWARF4.c -o test-gcc-DWARF4 > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_DWARF4="no" if false; then HAS_CC_DWARF4_TRUE= HAS_CC_DWARF4_FALSE='#' else HAS_CC_DWARF4_TRUE='#' HAS_CC_DWARF4_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_DWARF4 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_DWARF4="yes" if true; then HAS_CC_DWARF4_TRUE= HAS_CC_DWARF4_FALSE='#' else HAS_CC_DWARF4_TRUE='#' HAS_CC_DWARF4_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_DWARF4 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_DWARF4" == "yyes"; then HAS_CC_DWARF4_TRUE= HAS_CC_DWARF4_FALSE='#' else HAS_CC_DWARF4_TRUE='#' HAS_CC_DWARF4_FALSE= fi # SUBST rm -rf test-gcc-DWARF4* # # AC_COMPILER_SUPPORTS -fstack-protector --param=ssp-buffer-size=4 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -fstack-protector --param=ssp-buffer-size=4" >&5 $as_echo_n "checking if compiler supports -fstack-protector --param=ssp-buffer-size=4... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-STACK_PROTECTOR.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -fstack-protector --param=ssp-buffer-size=4 test-gcc-STACK_PROTECTOR.c -o test-gcc-STACK_PROTECTOR > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_STACK_PROTECTOR="no" if false; then HAS_CC_STACK_PROTECTOR_TRUE= HAS_CC_STACK_PROTECTOR_FALSE='#' else HAS_CC_STACK_PROTECTOR_TRUE='#' HAS_CC_STACK_PROTECTOR_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_STACK_PROTECTOR 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_STACK_PROTECTOR="yes" if true; then HAS_CC_STACK_PROTECTOR_TRUE= HAS_CC_STACK_PROTECTOR_FALSE='#' else HAS_CC_STACK_PROTECTOR_TRUE='#' HAS_CC_STACK_PROTECTOR_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_STACK_PROTECTOR 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_STACK_PROTECTOR" == "yyes"; then HAS_CC_STACK_PROTECTOR_TRUE= HAS_CC_STACK_PROTECTOR_FALSE='#' else HAS_CC_STACK_PROTECTOR_TRUE='#' HAS_CC_STACK_PROTECTOR_FALSE= fi # SUBST rm -rf test-gcc-STACK_PROTECTOR* # # AC_COMPILER_SUPPORTS -fexceptions # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -fexceptions" >&5 $as_echo_n "checking if compiler supports -fexceptions... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-EXCEPTIONS.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -fexceptions test-gcc-EXCEPTIONS.c -o test-gcc-EXCEPTIONS > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_EXCEPTIONS="no" if false; then HAS_CC_EXCEPTIONS_TRUE= HAS_CC_EXCEPTIONS_FALSE='#' else HAS_CC_EXCEPTIONS_TRUE='#' HAS_CC_EXCEPTIONS_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_EXCEPTIONS 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_EXCEPTIONS="yes" if true; then HAS_CC_EXCEPTIONS_TRUE= HAS_CC_EXCEPTIONS_FALSE='#' else HAS_CC_EXCEPTIONS_TRUE='#' HAS_CC_EXCEPTIONS_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_EXCEPTIONS 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_EXCEPTIONS" == "yyes"; then HAS_CC_EXCEPTIONS_TRUE= HAS_CC_EXCEPTIONS_FALSE='#' else HAS_CC_EXCEPTIONS_TRUE='#' HAS_CC_EXCEPTIONS_FALSE= fi # SUBST rm -rf test-gcc-EXCEPTIONS* # # AC_COMPILER_SUPPORTS -Werror=missing-field-initializers # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -Werror=missing-field-initializers" >&5 $as_echo_n "checking if compiler supports -Werror=missing-field-initializers... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-MISSING_FIELD_INITIALIZERS.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -Werror=missing-field-initializers test-gcc-MISSING_FIELD_INITIALIZERS.c -o test-gcc-MISSING_FIELD_INITIALIZERS > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_MISSING_FIELD_INITIALIZERS="no" if false; then HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE= HAS_CC_MISSING_FIELD_INITIALIZERS_FALSE='#' else HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE='#' HAS_CC_MISSING_FIELD_INITIALIZERS_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_MISSING_FIELD_INITIALIZERS 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_MISSING_FIELD_INITIALIZERS="yes" if true; then HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE= HAS_CC_MISSING_FIELD_INITIALIZERS_FALSE='#' else HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE='#' HAS_CC_MISSING_FIELD_INITIALIZERS_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_MISSING_FIELD_INITIALIZERS 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_MISSING_FIELD_INITIALIZERS" == "yyes"; then HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE= HAS_CC_MISSING_FIELD_INITIALIZERS_FALSE='#' else HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE='#' HAS_CC_MISSING_FIELD_INITIALIZERS_FALSE= fi # SUBST rm -rf test-gcc-MISSING_FIELD_INITIALIZERS* # # AC_COMPILER_SUPPORTS -fsanitize=address # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -fsanitize=address" >&5 $as_echo_n "checking if compiler supports -fsanitize=address... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-SANITIZE_ADDRESS.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -fsanitize=address test-gcc-SANITIZE_ADDRESS.c -o test-gcc-SANITIZE_ADDRESS > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_SANITIZE_ADDRESS="no" if false; then HAS_CC_SANITIZE_ADDRESS_TRUE= HAS_CC_SANITIZE_ADDRESS_FALSE='#' else HAS_CC_SANITIZE_ADDRESS_TRUE='#' HAS_CC_SANITIZE_ADDRESS_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_SANITIZE_ADDRESS 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_SANITIZE_ADDRESS="yes" if true; then HAS_CC_SANITIZE_ADDRESS_TRUE= HAS_CC_SANITIZE_ADDRESS_FALSE='#' else HAS_CC_SANITIZE_ADDRESS_TRUE='#' HAS_CC_SANITIZE_ADDRESS_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_SANITIZE_ADDRESS 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_SANITIZE_ADDRESS" == "yyes"; then HAS_CC_SANITIZE_ADDRESS_TRUE= HAS_CC_SANITIZE_ADDRESS_FALSE='#' else HAS_CC_SANITIZE_ADDRESS_TRUE='#' HAS_CC_SANITIZE_ADDRESS_FALSE= fi # SUBST rm -rf test-gcc-SANITIZE_ADDRESS* # # AC_COMPILER_SUPPORTS -fno-omit-frame-pointer # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -fno-omit-frame-pointer" >&5 $as_echo_n "checking if compiler supports -fno-omit-frame-pointer... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-NO_OMIT_FRAME_POINTER.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -fno-omit-frame-pointer test-gcc-NO_OMIT_FRAME_POINTER.c -o test-gcc-NO_OMIT_FRAME_POINTER > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_NO_OMIT_FRAME_POINTER="no" if false; then HAS_CC_NO_OMIT_FRAME_POINTER_TRUE= HAS_CC_NO_OMIT_FRAME_POINTER_FALSE='#' else HAS_CC_NO_OMIT_FRAME_POINTER_TRUE='#' HAS_CC_NO_OMIT_FRAME_POINTER_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_NO_OMIT_FRAME_POINTER 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_NO_OMIT_FRAME_POINTER="yes" if true; then HAS_CC_NO_OMIT_FRAME_POINTER_TRUE= HAS_CC_NO_OMIT_FRAME_POINTER_FALSE='#' else HAS_CC_NO_OMIT_FRAME_POINTER_TRUE='#' HAS_CC_NO_OMIT_FRAME_POINTER_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_NO_OMIT_FRAME_POINTER 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_NO_OMIT_FRAME_POINTER" == "yyes"; then HAS_CC_NO_OMIT_FRAME_POINTER_TRUE= HAS_CC_NO_OMIT_FRAME_POINTER_FALSE='#' else HAS_CC_NO_OMIT_FRAME_POINTER_TRUE='#' HAS_CC_NO_OMIT_FRAME_POINTER_FALSE= fi # SUBST rm -rf test-gcc-NO_OMIT_FRAME_POINTER* # # AC_COMPILER_SUPPORTS -faddress-sanitizer # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -faddress-sanitizer" >&5 $as_echo_n "checking if compiler supports -faddress-sanitizer... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-ADDRESS_SANITIZER_CHECK.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -faddress-sanitizer test-gcc-ADDRESS_SANITIZER_CHECK.c -o test-gcc-ADDRESS_SANITIZER_CHECK > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_ADDRESS_SANITIZER_CHECK="no" if false; then HAS_CC_ADDRESS_SANITIZER_CHECK_TRUE= HAS_CC_ADDRESS_SANITIZER_CHECK_FALSE='#' else HAS_CC_ADDRESS_SANITIZER_CHECK_TRUE='#' HAS_CC_ADDRESS_SANITIZER_CHECK_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_ADDRESS_SANITIZER_CHECK 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_ADDRESS_SANITIZER_CHECK="yes" if true; then HAS_CC_ADDRESS_SANITIZER_CHECK_TRUE= HAS_CC_ADDRESS_SANITIZER_CHECK_FALSE='#' else HAS_CC_ADDRESS_SANITIZER_CHECK_TRUE='#' HAS_CC_ADDRESS_SANITIZER_CHECK_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_ADDRESS_SANITIZER_CHECK 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_ADDRESS_SANITIZER_CHECK" == "yyes"; then HAS_CC_ADDRESS_SANITIZER_CHECK_TRUE= HAS_CC_ADDRESS_SANITIZER_CHECK_FALSE='#' else HAS_CC_ADDRESS_SANITIZER_CHECK_TRUE='#' HAS_CC_ADDRESS_SANITIZER_CHECK_FALSE= fi # SUBST rm -rf test-gcc-ADDRESS_SANITIZER_CHECK* # # AC_COMPILER_SUPPORTS -fcatch_undefined_behavior # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -fcatch_undefined_behavior" >&5 $as_echo_n "checking if compiler supports -fcatch_undefined_behavior... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-CATCH_UNDEFINED_BEHAVIOR.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -fcatch_undefined_behavior test-gcc-CATCH_UNDEFINED_BEHAVIOR.c -o test-gcc-CATCH_UNDEFINED_BEHAVIOR > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_CATCH_UNDEFINED_BEHAVIOR="no" if false; then HAS_CC_CATCH_UNDEFINED_BEHAVIOR_TRUE= HAS_CC_CATCH_UNDEFINED_BEHAVIOR_FALSE='#' else HAS_CC_CATCH_UNDEFINED_BEHAVIOR_TRUE='#' HAS_CC_CATCH_UNDEFINED_BEHAVIOR_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_CATCH_UNDEFINED_BEHAVIOR 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_CATCH_UNDEFINED_BEHAVIOR="yes" if true; then HAS_CC_CATCH_UNDEFINED_BEHAVIOR_TRUE= HAS_CC_CATCH_UNDEFINED_BEHAVIOR_FALSE='#' else HAS_CC_CATCH_UNDEFINED_BEHAVIOR_TRUE='#' HAS_CC_CATCH_UNDEFINED_BEHAVIOR_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_CATCH_UNDEFINED_BEHAVIOR 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_CATCH_UNDEFINED_BEHAVIOR" == "yyes"; then HAS_CC_CATCH_UNDEFINED_BEHAVIOR_TRUE= HAS_CC_CATCH_UNDEFINED_BEHAVIOR_FALSE='#' else HAS_CC_CATCH_UNDEFINED_BEHAVIOR_TRUE='#' HAS_CC_CATCH_UNDEFINED_BEHAVIOR_FALSE= fi # SUBST rm -rf test-gcc-CATCH_UNDEFINED_BEHAVIOR* # # AC_COMPILER_SUPPORTS -rdynamic # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -rdynamic" >&5 $as_echo_n "checking if compiler supports -rdynamic... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-RDYNAMIC.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif int main(int argc,char** argv) { (void)argc; (void)argv; puts("Hello World!"); return 0; } _ACEOF $CC -rdynamic test-gcc-RDYNAMIC.c -o test-gcc-RDYNAMIC > /dev/null 2>&1 if [ $? -ne 0 ] then has_cc_RDYNAMIC="no" if false; then HAS_CC_RDYNAMIC_TRUE= HAS_CC_RDYNAMIC_FALSE='#' else HAS_CC_RDYNAMIC_TRUE='#' HAS_CC_RDYNAMIC_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_RDYNAMIC 0 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else has_cc_RDYNAMIC="yes" if true; then HAS_CC_RDYNAMIC_TRUE= HAS_CC_RDYNAMIC_FALSE='#' else HAS_CC_RDYNAMIC_TRUE='#' HAS_CC_RDYNAMIC_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_CC_RDYNAMIC 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # CONDITIONAL if test "y$has_cc_RDYNAMIC" == "yyes"; then HAS_CC_RDYNAMIC_TRUE= HAS_CC_RDYNAMIC_FALSE='#' else HAS_CC_RDYNAMIC_TRUE='#' HAS_CC_RDYNAMIC_FALSE= fi # SUBST rm -rf test-gcc-RDYNAMIC* for ac_header in arpa/inet.h do : ac_fn_c_check_header_mongrel "$LINENO" "arpa/inet.h" "ac_cv_header_arpa_inet_h" "$ac_includes_default" if test "x$ac_cv_header_arpa_inet_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ARPA_INET_H 1 _ACEOF fi done for ac_header in asm/unistd.h do : ac_fn_c_check_header_mongrel "$LINENO" "asm/unistd.h" "ac_cv_header_asm_unistd_h" "$ac_includes_default" if test "x$ac_cv_header_asm_unistd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ASM_UNISTD_H 1 _ACEOF fi done for ac_header in assert.h do : ac_fn_c_check_header_mongrel "$LINENO" "assert.h" "ac_cv_header_assert_h" "$ac_includes_default" if test "x$ac_cv_header_assert_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ASSERT_H 1 _ACEOF fi done for ac_header in bfd.h do : ac_fn_c_check_header_mongrel "$LINENO" "bfd.h" "ac_cv_header_bfd_h" "$ac_includes_default" if test "x$ac_cv_header_bfd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BFD_H 1 _ACEOF fi done for ac_header in byteswap.h do : ac_fn_c_check_header_mongrel "$LINENO" "byteswap.h" "ac_cv_header_byteswap_h" "$ac_includes_default" if test "x$ac_cv_header_byteswap_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BYTESWAP_H 1 _ACEOF fi done for ac_header in cpuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "cpuid.h" "ac_cv_header_cpuid_h" "$ac_includes_default" if test "x$ac_cv_header_cpuid_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_CPUID_H 1 _ACEOF fi done for ac_header in ctype.h do : ac_fn_c_check_header_mongrel "$LINENO" "ctype.h" "ac_cv_header_ctype_h" "$ac_includes_default" if test "x$ac_cv_header_ctype_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_CTYPE_H 1 _ACEOF fi done for ac_header in dirent.h do : ac_fn_c_check_header_mongrel "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "$ac_includes_default" if test "x$ac_cv_header_dirent_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DIRENT_H 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done for ac_header in endian.h do : ac_fn_c_check_header_mongrel "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default" if test "x$ac_cv_header_endian_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ENDIAN_H 1 _ACEOF fi done for ac_header in errno.h do : ac_fn_c_check_header_mongrel "$LINENO" "errno.h" "ac_cv_header_errno_h" "$ac_includes_default" if test "x$ac_cv_header_errno_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ERRNO_H 1 _ACEOF fi done for ac_header in execinfo.h do : ac_fn_c_check_header_mongrel "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default" if test "x$ac_cv_header_execinfo_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_EXECINFO_H 1 _ACEOF fi done for ac_header in fcntl.h do : ac_fn_c_check_header_mongrel "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" if test "x$ac_cv_header_fcntl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FCNTL_H 1 _ACEOF fi done for ac_header in getopt.h do : ac_fn_c_check_header_mongrel "$LINENO" "getopt.h" "ac_cv_header_getopt_h" "$ac_includes_default" if test "x$ac_cv_header_getopt_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETOPT_H 1 _ACEOF fi done for ac_header in grp.h do : ac_fn_c_check_header_mongrel "$LINENO" "grp.h" "ac_cv_header_grp_h" "$ac_includes_default" if test "x$ac_cv_header_grp_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GRP_H 1 _ACEOF fi done for ac_header in limits.h do : ac_fn_c_check_header_mongrel "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" if test "x$ac_cv_header_limits_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIMITS_H 1 _ACEOF fi done for ac_header in linux/limits.h do : ac_fn_c_check_header_mongrel "$LINENO" "linux/limits.h" "ac_cv_header_linux_limits_h" "$ac_includes_default" if test "x$ac_cv_header_linux_limits_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LINUX_LIMITS_H 1 _ACEOF fi done for ac_header in mach/clock.h do : ac_fn_c_check_header_mongrel "$LINENO" "mach/clock.h" "ac_cv_header_mach_clock_h" "$ac_includes_default" if test "x$ac_cv_header_mach_clock_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MACH_CLOCK_H 1 _ACEOF fi done for ac_header in machine/endian.h do : ac_fn_c_check_header_mongrel "$LINENO" "machine/endian.h" "ac_cv_header_machine_endian_h" "$ac_includes_default" if test "x$ac_cv_header_machine_endian_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MACHINE_ENDIAN_H 1 _ACEOF fi done for ac_header in mach/mach.h do : ac_fn_c_check_header_mongrel "$LINENO" "mach/mach.h" "ac_cv_header_mach_mach_h" "$ac_includes_default" if test "x$ac_cv_header_mach_mach_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MACH_MACH_H 1 _ACEOF fi done for ac_header in malloc.h do : ac_fn_c_check_header_mongrel "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "$ac_includes_default" if test "x$ac_cv_header_malloc_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MALLOC_H 1 _ACEOF fi done for ac_header in netdb.h do : ac_fn_c_check_header_mongrel "$LINENO" "netdb.h" "ac_cv_header_netdb_h" "$ac_includes_default" if test "x$ac_cv_header_netdb_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NETDB_H 1 _ACEOF fi done for ac_header in net/ethernet.h do : ac_fn_c_check_header_mongrel "$LINENO" "net/ethernet.h" "ac_cv_header_net_ethernet_h" "$ac_includes_default" if test "x$ac_cv_header_net_ethernet_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NET_ETHERNET_H 1 _ACEOF fi done for ac_header in netinet/in.h do : ac_fn_c_check_header_mongrel "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default" if test "x$ac_cv_header_netinet_in_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NETINET_IN_H 1 _ACEOF fi done for ac_header in netinet6/in6.h do : ac_fn_c_check_header_mongrel "$LINENO" "netinet6/in6.h" "ac_cv_header_netinet6_in6_h" "$ac_includes_default" if test "x$ac_cv_header_netinet6_in6_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NETINET6_IN6_H 1 _ACEOF fi done for ac_header in netinet/tcp.h do : ac_fn_c_check_header_mongrel "$LINENO" "netinet/tcp.h" "ac_cv_header_netinet_tcp_h" "$ac_includes_default" if test "x$ac_cv_header_netinet_tcp_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NETINET_TCP_H 1 _ACEOF fi done for ac_header in pcap/pcap.h do : ac_fn_c_check_header_mongrel "$LINENO" "pcap/pcap.h" "ac_cv_header_pcap_pcap_h" "$ac_includes_default" if test "x$ac_cv_header_pcap_pcap_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PCAP_PCAP_H 1 _ACEOF fi done for ac_header in poll.h do : ac_fn_c_check_header_mongrel "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default" if test "x$ac_cv_header_poll_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_POLL_H 1 _ACEOF fi done for ac_header in pthread.h do : ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PTHREAD_H 1 _ACEOF fi done for ac_header in pwd.h do : ac_fn_c_check_header_mongrel "$LINENO" "pwd.h" "ac_cv_header_pwd_h" "$ac_includes_default" if test "x$ac_cv_header_pwd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PWD_H 1 _ACEOF fi done for ac_header in sched.h do : ac_fn_c_check_header_mongrel "$LINENO" "sched.h" "ac_cv_header_sched_h" "$ac_includes_default" if test "x$ac_cv_header_sched_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SCHED_H 1 _ACEOF fi done for ac_header in signal.h do : ac_fn_c_check_header_mongrel "$LINENO" "signal.h" "ac_cv_header_signal_h" "$ac_includes_default" if test "x$ac_cv_header_signal_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SIGNAL_H 1 _ACEOF fi done for ac_header in stdarg.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdarg.h" "ac_cv_header_stdarg_h" "$ac_includes_default" if test "x$ac_cv_header_stdarg_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDARG_H 1 _ACEOF fi done for ac_header in stdatomic.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdatomic.h" "ac_cv_header_stdatomic_h" "$ac_includes_default" if test "x$ac_cv_header_stdatomic_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDATOMIC_H 1 _ACEOF fi done for ac_header in stdbool.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default" if test "x$ac_cv_header_stdbool_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDBOOL_H 1 _ACEOF fi done for ac_header in stddef.h do : ac_fn_c_check_header_mongrel "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default" if test "x$ac_cv_header_stddef_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDDEF_H 1 _ACEOF fi done for ac_header in stdint.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" if test "x$ac_cv_header_stdint_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDINT_H 1 _ACEOF fi done for ac_header in stdio.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdio.h" "ac_cv_header_stdio_h" "$ac_includes_default" if test "x$ac_cv_header_stdio_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDIO_H 1 _ACEOF fi done for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done for ac_header in string.h do : ac_fn_c_check_header_mongrel "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" if test "x$ac_cv_header_string_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRING_H 1 _ACEOF fi done for ac_header in strings.h do : ac_fn_c_check_header_mongrel "$LINENO" "strings.h" "ac_cv_header_strings_h" "$ac_includes_default" if test "x$ac_cv_header_strings_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRINGS_H 1 _ACEOF fi done for ac_header in sys/byteorder.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/byteorder.h" "ac_cv_header_sys_byteorder_h" "$ac_includes_default" if test "x$ac_cv_header_sys_byteorder_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_BYTEORDER_H 1 _ACEOF fi done for ac_header in sys/cpuset.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/cpuset.h" "ac_cv_header_sys_cpuset_h" "$ac_includes_default" if test "x$ac_cv_header_sys_cpuset_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_CPUSET_H 1 _ACEOF fi done for ac_header in sys/endian.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/endian.h" "ac_cv_header_sys_endian_h" "$ac_includes_default" if test "x$ac_cv_header_sys_endian_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_ENDIAN_H 1 _ACEOF fi done for ac_header in sys/file.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/file.h" "ac_cv_header_sys_file_h" "$ac_includes_default" if test "x$ac_cv_header_sys_file_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_FILE_H 1 _ACEOF fi done for ac_header in sys/ipc.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/ipc.h" "ac_cv_header_sys_ipc_h" "$ac_includes_default" if test "x$ac_cv_header_sys_ipc_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_IPC_H 1 _ACEOF fi done for ac_header in syslog.h do : ac_fn_c_check_header_mongrel "$LINENO" "syslog.h" "ac_cv_header_syslog_h" "$ac_includes_default" if test "x$ac_cv_header_syslog_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYSLOG_H 1 _ACEOF fi done for ac_header in sys/mman.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" if test "x$ac_cv_header_sys_mman_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_MMAN_H 1 _ACEOF fi done for ac_header in sys/msg.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/msg.h" "ac_cv_header_sys_msg_h" "$ac_includes_default" if test "x$ac_cv_header_sys_msg_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_MSG_H 1 _ACEOF fi done for ac_header in sys/param.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" if test "x$ac_cv_header_sys_param_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_PARAM_H 1 _ACEOF fi done for ac_header in sys/prctl.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/prctl.h" "ac_cv_header_sys_prctl_h" "$ac_includes_default" if test "x$ac_cv_header_sys_prctl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_PRCTL_H 1 _ACEOF fi done for ac_header in sys/resource.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/resource.h" "ac_cv_header_sys_resource_h" "$ac_includes_default" if test "x$ac_cv_header_sys_resource_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_RESOURCE_H 1 _ACEOF fi done for ac_header in sys/socket.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default" if test "x$ac_cv_header_sys_socket_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_SOCKET_H 1 _ACEOF fi done for ac_header in sys/stat.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/stat.h" "ac_cv_header_sys_stat_h" "$ac_includes_default" if test "x$ac_cv_header_sys_stat_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_STAT_H 1 _ACEOF fi done for ac_header in sys/syslimits.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/syslimits.h" "ac_cv_header_sys_syslimits_h" "$ac_includes_default" if test "x$ac_cv_header_sys_syslimits_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_SYSLIMITS_H 1 _ACEOF fi done for ac_header in sys/time.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" if test "x$ac_cv_header_sys_time_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_TIME_H 1 _ACEOF fi done for ac_header in sys/types.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default" if test "x$ac_cv_header_sys_types_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_TYPES_H 1 _ACEOF fi done for ac_header in sys/un.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/un.h" "ac_cv_header_sys_un_h" "$ac_includes_default" if test "x$ac_cv_header_sys_un_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_UN_H 1 _ACEOF fi done for ac_header in sys/wait.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/wait.h" "ac_cv_header_sys_wait_h" "$ac_includes_default" if test "x$ac_cv_header_sys_wait_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_WAIT_H 1 _ACEOF fi done for ac_header in tcl.h do : ac_fn_c_check_header_mongrel "$LINENO" "tcl.h" "ac_cv_header_tcl_h" "$ac_includes_default" if test "x$ac_cv_header_tcl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TCL_H 1 _ACEOF fi done for ac_header in time.h do : ac_fn_c_check_header_mongrel "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default" if test "x$ac_cv_header_time_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TIME_H 1 _ACEOF fi done for ac_header in ucontext.h do : ac_fn_c_check_header_mongrel "$LINENO" "ucontext.h" "ac_cv_header_ucontext_h" "$ac_includes_default" if test "x$ac_cv_header_ucontext_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UCONTEXT_H 1 _ACEOF fi done for ac_header in unistd.h do : ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" if test "x$ac_cv_header_unistd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UNISTD_H 1 _ACEOF fi done for ac_header in stdnoreturn.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdnoreturn.h" "ac_cv_header_stdnoreturn_h" "$ac_includes_default" if test "x$ac_cv_header_stdnoreturn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDNORETURN_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking if memory accesses must be size-aligned" >&5 $as_echo_n "checking if memory accesses must be size-aligned... " >&6; } cat > memalign_issues_test.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif int main(int argc, char** argv) { char* p = (char*)malloc(8); p++; int* intp= (int*)p; *intp=1; return 0; } _ACEOF ${CC} ${CFLAGS} memalign_issues_test.c -o memalign_issues_test > /dev/null 2>&1 ./memalign_issues_test > /dev/null 2>&1 if [ $? -ne 0 ]; then has_memalign_issues=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else has_memalign_issues=0 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f memalign_issues_test memalign_issues_test.c # CONDITIONAL if test $has_memalign_issues -eq 1; then HAS_MEMALIGN_ISSUES_TRUE= HAS_MEMALIGN_ISSUES_FALSE='#' else HAS_MEMALIGN_ISSUES_TRUE='#' HAS_MEMALIGN_ISSUES_FALSE= fi # SUBST cat >>confdefs.h <<_ACEOF #define HAS_MEMALIGN_ISSUES $has_memalign_issues _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler supports __sync builtins" >&5 $as_echo_n "checking if the compiler supports __sync builtins... " >&6; } cat > sync_builtin_test.c <<_ACEOF typedef int atomic_flag; static int atomic_flag_test_and_set(atomic_flag* v) { atomic_flag old = __sync_fetch_and_or(v, (atomic_flag)1); return old; } static void atomic_flag_clear(atomic_flag* v) { __sync_fetch_and_and(v, (atomic_flag)0); } int main() { atomic_flag f; atomic_flag old = atomic_flag_test_and_set(&f); atomic_flag_clear(&f); return 0; } _ACEOF ${CC} ${CFLAGS} sync_builtin_test.c -o sync_builtin_test > /dev/null 2>&1 ./sync_builtin_test > /dev/null 2>&1 if [ $? -eq 0 ]; then has_sync_builtins=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else has_sync_builtins=0 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f sync_builtin_test sync_builtin_test.c # CONDITIONAL if test $has_sync_builtins -eq 1; then HAS_SYNC_BUILTINS_TRUE= HAS_SYNC_BUILTINS_FALSE='#' else HAS_SYNC_BUILTINS_TRUE='#' HAS_SYNC_BUILTINS_FALSE= fi # SUBST cat >>confdefs.h <<_ACEOF #define HAS_SYNC_BUILTINS $has_sync_builtins _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setgroups" >&5 $as_echo_n "checking for setgroups... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setgroups in -lc" >&5 $as_echo_n "checking for setgroups in -lc... " >&6; } if ${ac_cv_lib_c_setgroups+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char setgroups (); int main () { return setgroups (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_setgroups=yes else ac_cv_lib_c_setgroups=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_setgroups" >&5 $as_echo "$ac_cv_lib_c_setgroups" >&6; } if test "x$ac_cv_lib_c_setgroups" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAS_SETGROUPS 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # # AC_ENDIANNESS # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking endianness: " >&5 $as_echo_n "checking endianness: ... " >&6; } if [ "$CC" = "" ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"compiler not set yet, fix this\"" >&5 $as_echo "\"compiler not set yet, fix this\"" >&6; } exit 1 fi cat > test-gcc-endian.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_STDIO_H #include #endif #if defined __FreeBSD__ #if HAVE_SYS_ENDIAN_H #include #endif #elif defined __APPLE__ #if HAVE_MACHINE_ENDIAN_H #include #endif #elif defined __sun #if HAVE_SYS_BYTEORDER_H #include #endif #else #if HAVE_ENDIAN_H #include #endif #if HAVE_BYTESWAP_H #include #endif #endif static int magic = 0x00525545; int main(int argc,char** argv) { (void)argc; (void)argv; int pp = -1; int c = -1; #if defined _BIG_ENDIAN pp = 2; #elif defined _LITTLE_ENDIAN pp = 1; #endif #ifdef __BYTE_ORDER #if __BYTE_ORDER == __LITTLE_ENDIAN pp = 1; #elif __BYTE_ORDER == __BIG_ENDIAN pp = 2; #endif // printf("__BYTE_ORDER=%x\n", __BYTE_ORDER); #endif #ifdef _BYTE_ORDER #if _BYTE_ORDER == _LITTLE_ENDIAN pp = 1; #elif _BYTE_ORDER == _BIG_ENDIAN pp = 2; #endif printf("_BYTE_ORDER=%x\n", _BYTE_ORDER); #endif #ifdef BYTE_ORDER #if BYTE_ORDER == LITTLE_ENDIAN pp = 1; #elif BYTE_ORDER == BIG_ENDIAN pp = 2; #endif // printf("BYTE_ORDER=%x\n", BYTE_ORDER); #endif # #ifdef WORDS_BIGENDIAN // printf("WORDS_BIGENDIAN=%x\n", WORDS_BIGENDIAN); if(pp == 1) // could be -1 or 2 { pp = -2; } else { pp = 2; } #endif char *p = (char*)&magic; if(*p == '\0') { c = 2; } else if(*p == 'E') { c = 1; } if((pp < 0) || (c < 0)) { printf("*** WARNING *** preprocessor says %i, real test says %i *** WARNING ***\n", pp, c); } if(c == pp) { return c; } else { return -1; } } _ACEOF $CC test-gcc-endian.c -o test-gcc-endian > /dev/null 2>&1 if [ $? -ne 0 ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"failed to compile test\"" >&5 $as_echo "\"failed to compile test\"" >&6; } exit 1 fi ./test-gcc-endian if [ $? -eq 1 ] then cpu_endian="little" { $as_echo "$as_me:${as_lineno-$LINENO}: result: little" >&5 $as_echo "little" >&6; } else cpu_endian="big" { $as_echo "$as_me:${as_lineno-$LINENO}: result: big" >&5 $as_echo "big" >&6; } fi # CONDITIONAL if test "$cpu_endian" == "little"; then HAS_LITTLE_ENDIAN_TRUE= HAS_LITTLE_ENDIAN_FALSE='#' else HAS_LITTLE_ENDIAN_TRUE='#' HAS_LITTLE_ENDIAN_FALSE= fi if test "$cpu_endian" == "big"; then HAS_BIG_ENDIAN_TRUE= HAS_BIG_ENDIAN_FALSE='#' else HAS_BIG_ENDIAN_TRUE='#' HAS_BIG_ENDIAN_FALSE= fi # SUBST rm -f test-gcc-endian.c* test-gcc-endian { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_spin_init" >&5 $as_echo_n "checking for pthread_spin_init... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_spin_init" >&5 $as_echo_n "checking for library containing pthread_spin_init... " >&6; } if ${ac_cv_search_pthread_spin_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_spin_init (); int main () { return pthread_spin_init (); ; return 0; } _ACEOF for ac_lib in '' pthread; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_pthread_spin_init=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_pthread_spin_init+:} false; then : break fi done if ${ac_cv_search_pthread_spin_init+:} false; then : else ac_cv_search_pthread_spin_init=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_spin_init" >&5 $as_echo "$ac_cv_search_pthread_spin_init" >&6; } ac_res=$ac_cv_search_pthread_spin_init if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" cat >>confdefs.h <<_ACEOF #define HAS_PTHREAD_SPINLOCK 1 _ACEOF echo yes else echo no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_np" >&5 $as_echo_n "checking for pthread_setname_np... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_setname_np" >&5 $as_echo_n "checking for library containing pthread_setname_np... " >&6; } if ${ac_cv_search_pthread_setname_np+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_setname_np (); int main () { return pthread_setname_np (); ; return 0; } _ACEOF for ac_lib in '' pthread; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_pthread_setname_np=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_pthread_setname_np+:} false; then : break fi done if ${ac_cv_search_pthread_setname_np+:} false; then : else ac_cv_search_pthread_setname_np=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_setname_np" >&5 $as_echo "$ac_cv_search_pthread_setname_np" >&6; } ac_res=$ac_cv_search_pthread_setname_np if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" cat >>confdefs.h <<_ACEOF #define HAS_PTHREAD_SETNAME_NP 1 _ACEOF echo yes else echo no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_setaffinity_np" >&5 $as_echo_n "checking for pthread_setaffinity_np... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_setaffinity_np" >&5 $as_echo_n "checking for library containing pthread_setaffinity_np... " >&6; } if ${ac_cv_search_pthread_setaffinity_np+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_setaffinity_np (); int main () { return pthread_setaffinity_np (); ; return 0; } _ACEOF for ac_lib in '' pthread; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_pthread_setaffinity_np=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_pthread_setaffinity_np+:} false; then : break fi done if ${ac_cv_search_pthread_setaffinity_np+:} false; then : else ac_cv_search_pthread_setaffinity_np=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_setaffinity_np" >&5 $as_echo "$ac_cv_search_pthread_setaffinity_np" >&6; } ac_res=$ac_cv_search_pthread_setaffinity_np if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" cat >>confdefs.h <<_ACEOF #define HAS_PTHREAD_SETAFFINITY_NP 1 _ACEOF echo yes else echo no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gettid" >&5 $as_echo_n "checking for gettid... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gettid" >&5 $as_echo_n "checking for library containing gettid... " >&6; } if ${ac_cv_search_gettid+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gettid (); int main () { return gettid (); ; return 0; } _ACEOF for ac_lib in '' ; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gettid=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gettid+:} false; then : break fi done if ${ac_cv_search_gettid+:} false; then : else ac_cv_search_gettid=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gettid" >&5 $as_echo "$ac_cv_search_gettid" >&6; } ac_res=$ac_cv_search_gettid if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" cat >>confdefs.h <<_ACEOF #define HAVE_GETTID 1 _ACEOF echo yes else echo no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for timegm" >&5 $as_echo_n "checking for timegm... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct tm t; timegm(&t); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mremap" >&5 $as_echo_n "checking for mremap... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _GNU_SOURCE #include int main () { mremap(0,0,0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext echo "mmsg results:" echo "have_sendmmsg='$have_sendmmsg'" echo "have_recvmmsg='$have_recvmmsg'" echo "-------" ac_fn_c_check_func "$LINENO" "sendmmsg" "ac_cv_func_sendmmsg" if test "x$ac_cv_func_sendmmsg" = xyes; then : have_sendmmsg=true cat >>confdefs.h <<_ACEOF #define HAVE_SENDMMSG 1 _ACEOF else have_sendmmsg=false cat >>confdefs.h <<_ACEOF #define HAVE_SENDMMSG 0 _ACEOF fi ac_fn_c_check_func "$LINENO" "recvmmsg" "ac_cv_func_recvmmsg" if test "x$ac_cv_func_recvmmsg" = xyes; then : have_recvmmsg=true cat >>confdefs.h <<_ACEOF #define HAVE_RECVMMSG 1 _ACEOF else have_recvmmsg=false cat >>confdefs.h <<_ACEOF #define HAVE_RECVMMSG 0 _ACEOF fi if test x$have_sendmmsg = xtrue; then HAVE_SENDMMSG_TRUE= HAVE_SENDMMSG_FALSE='#' else HAVE_SENDMMSG_TRUE='#' HAVE_SENDMMSG_FALSE= fi if test x$have_recvmmsg = xtrue; then HAVE_RECVMMSG_TRUE= HAVE_RECVMMSG_FALSE='#' else HAVE_RECVMMSG_TRUE='#' HAVE_RECVMMSG_FALSE= fi requires_ssl=1 SSLDEPS="" echo "Finding the SSL dependencies" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5 $as_echo_n "checking for library containing deflate... " >&6; } if ${ac_cv_search_deflate+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char deflate (); int main () { return deflate (); ; return 0; } _ACEOF for ac_lib in '' z; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_deflate=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_deflate+:} false; then : break fi done if ${ac_cv_search_deflate+:} false; then : else ac_cv_search_deflate=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5 $as_echo "$ac_cv_search_deflate" >&6; } ac_res=$ac_cv_search_deflate if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi echo "SSLDEPS=${SSLDEPS}" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if SSL is available" >&5 $as_echo_n "checking if SSL is available... " >&6; } ac_check_lib_ssl=0 # Check whether --with-openssl_lib was given. if test "${with_openssl_lib+set}" = set; then : withval=$with_openssl_lib; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } LDFLAGS="-L$with_openssl_lib $SSLDEPS $LDFLAGS" echo "LDFLAGS=${LDFLAGS}" ac_check_lib_ssl=1 fi # Check whether --with-openssl_include was given. if test "${with_openssl_include+set}" = set; then : withval=$with_openssl_include; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="-I$with_openssl_include $CFLAGS $CFLAGS3264" echo "CFLAGS=${LDFLAGS}" ac_check_lib_ssl=1 fi # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : withval=$with_openssl; echo "yes" OPENSSL="${withval}" CFLAGS="-I$with_openssl/include $CFLAGS $CFLAGS3264" LDFLAGS="-L$with_openssl/lib $SSLDEPS $LDFLAGS" echo "CFLAGS=$CFLAGS" echo "LDFLAGS=$LDFLAGS" ac_check_lib_ssl=1 else echo "no" CFLAGS="$CFLAGS $CFLAGS3264" LDFLAGS="$SSLDEPS $LDFLAGS" echo "CFLAGS=${CFLAGS}" echo "LDFLAGS=${LDFLAGS}" ac_check_lib_ssl=1 fi if [ $ac_check_lib_ssl -eq 1 ] then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_new" >&5 $as_echo_n "checking for library containing RSA_new... " >&6; } if ${ac_cv_search_RSA_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char RSA_new (); int main () { return RSA_new (); ; return 0; } _ACEOF for ac_lib in '' crypto; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_RSA_new=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_RSA_new+:} false; then : break fi done if ${ac_cv_search_RSA_new+:} false; then : else ac_cv_search_RSA_new=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_new" >&5 $as_echo "$ac_cv_search_RSA_new" >&6; } ac_res=$ac_cv_search_RSA_new if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing SSL_library_init" >&5 $as_echo_n "checking for library containing SSL_library_init... " >&6; } if ${ac_cv_search_SSL_library_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char SSL_library_init (); int main () { return SSL_library_init (); ; return 0; } _ACEOF for ac_lib in '' ssl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_SSL_library_init=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_SSL_library_init+:} false; then : break fi done if ${ac_cv_search_SSL_library_init+:} false; then : else ac_cv_search_SSL_library_init=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_SSL_library_init" >&5 $as_echo "$ac_cv_search_SSL_library_init" >&6; } ac_res=$ac_cv_search_SSL_library_init if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing OPENSSL_init_ssl" >&5 $as_echo_n "checking for library containing OPENSSL_init_ssl... " >&6; } if ${ac_cv_search_OPENSSL_init_ssl+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char OPENSSL_init_ssl (); int main () { return OPENSSL_init_ssl (); ; return 0; } _ACEOF for ac_lib in '' ssl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_OPENSSL_init_ssl=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_OPENSSL_init_ssl+:} false; then : break fi done if ${ac_cv_search_OPENSSL_init_ssl+:} false; then : else ac_cv_search_OPENSSL_init_ssl=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_OPENSSL_init_ssl" >&5 $as_echo "$ac_cv_search_OPENSSL_init_ssl" >&6; } ac_res=$ac_cv_search_OPENSSL_init_ssl if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi fi ac_fn_c_check_func "$LINENO" "EVP_PKEY_new_raw_public_key" "ac_cv_func_EVP_PKEY_new_raw_public_key" if test "x$ac_cv_func_EVP_PKEY_new_raw_public_key" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAS_EVP_PKEY_NEW_RAW_PUBLIC_KEY 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAS_EVP_PKEY_NEW_RAW_PUBLIC_KEY 0 _ACEOF fi cat >>confdefs.h <<_ACEOF #define HAS_OPENSSL 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAS_OPENSSL 0 _ACEOF fi # # AC_HAS_DISABLE rrl # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if RRL_SUPPORT has been disabled" >&5 $as_echo_n "checking if RRL_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-rrl was given. if test "${enable_rrl+set}" = set; then : enableval=$enable_rrl; fi # MSG RESULT # CASE case "y$enable_rrl" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_RRL_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_rrl=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_RRL_SUPPORT 0 _ACEOF # CONDITIONAL N enable_rrl=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_rrl != yno; then HAS_RRL_SUPPORT_TRUE= HAS_RRL_SUPPORT_FALSE='#' else HAS_RRL_SUPPORT_TRUE='#' HAS_RRL_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE rrl DONE # # AC_HAS_DISABLE master # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MASTER_SUPPORT has been disabled" >&5 $as_echo_n "checking if MASTER_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-master was given. if test "${enable_master+set}" = set; then : enableval=$enable_master; fi # MSG RESULT # CASE case "y$enable_master" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_MASTER_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_master=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES requires_ssl=1 # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_MASTER_SUPPORT 0 _ACEOF # CONDITIONAL N enable_master=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO enable_dynupdate='no' enable_rrsig_management='no' # ENDIF ;; esac # CONDITIONAL if test y$enable_master != yno; then HAS_MASTER_SUPPORT_TRUE= HAS_MASTER_SUPPORT_FALSE='#' else HAS_MASTER_SUPPORT_TRUE='#' HAS_MASTER_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE master DONE # # AC_HAS_DISABLE ctrl # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if CTRL has been disabled" >&5 $as_echo_n "checking if CTRL has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-ctrl was given. if test "${enable_ctrl+set}" = set; then : enableval=$enable_ctrl; fi # MSG RESULT # CASE case "y$enable_ctrl" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_CTRL 1 _ACEOF # CONDITIONAL Y enable_ctrl=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_CTRL 0 _ACEOF # CONDITIONAL N enable_ctrl=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_ctrl != yno; then HAS_CTRL_TRUE= HAS_CTRL_FALSE='#' else HAS_CTRL_TRUE='#' HAS_CTRL_FALSE= fi # SUBST # AC_HAS_DISABLE ctrl DONE if xno = xyes; then HAS_ZONESIGN_TRUE= HAS_ZONESIGN_FALSE='#' else HAS_ZONESIGN_TRUE='#' HAS_ZONESIGN_FALSE= fi # # AC_HAS_ENABLE keygen # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if KEYGEN has been enabled" >&5 $as_echo_n "checking if KEYGEN has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-keygen was given. if test "${enable_keygen+set}" = set; then : enableval=$enable_keygen; fi # CASE case "y$enable_keygen" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_KEYGEN 1 _ACEOF # CONDITIONAL Y enable_keygen="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_KEYGEN 0 _ACEOF # CONDITIONAL N enable_keygen="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_keygen = yyes; then HAS_KEYGEN_TRUE= HAS_KEYGEN_FALSE='#' else HAS_KEYGEN_TRUE='#' HAS_KEYGEN_FALSE= fi # SUBST # AC_HAS_ENABLE keygen DONE # # AC_HAS_DISABLE nsid # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if NSID_SUPPORT has been disabled" >&5 $as_echo_n "checking if NSID_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-nsid was given. if test "${enable_nsid+set}" = set; then : enableval=$enable_nsid; fi # MSG RESULT # CASE case "y$enable_nsid" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_NSID_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_nsid=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_NSID_SUPPORT 0 _ACEOF # CONDITIONAL N enable_nsid=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_nsid != yno; then HAS_NSID_SUPPORT_TRUE= HAS_NSID_SUPPORT_FALSE='#' else HAS_NSID_SUPPORT_TRUE='#' HAS_NSID_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE nsid DONE # # AC_FORCE_ENABLE acl # enable_acl=yes cat >>confdefs.h <<_ACEOF #define HAS_ACL_SUPPORT 1 _ACEOF if test y$enable_acl = yyes; then HAS_ACL_SUPPORT_TRUE= HAS_ACL_SUPPORT_FALSE='#' else HAS_ACL_SUPPORT_TRUE='#' HAS_ACL_SUPPORT_FALSE= fi # AC_FORCE_ENABLE acl DONE requires_ssl=1 # # AC_FORCE_ENABLE tsig # enable_tsig=yes cat >>confdefs.h <<_ACEOF #define HAS_TSIG_SUPPORT 1 _ACEOF if test y$enable_tsig = yyes; then HAS_TSIG_SUPPORT_TRUE= HAS_TSIG_SUPPORT_FALSE='#' else HAS_TSIG_SUPPORT_TRUE='#' HAS_TSIG_SUPPORT_FALSE= fi # AC_FORCE_ENABLE tsig DONE requires_ssl=1 # # AC_HAS_DISABLE dynupdate # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if DYNUPDATE_SUPPORT has been disabled" >&5 $as_echo_n "checking if DYNUPDATE_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-dynupdate was given. if test "${enable_dynupdate+set}" = set; then : enableval=$enable_dynupdate; fi # MSG RESULT # CASE case "y$enable_dynupdate" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_DYNUPDATE_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_dynupdate=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_DYNUPDATE_SUPPORT 0 _ACEOF # CONDITIONAL N enable_dynupdate=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_dynupdate != yno; then HAS_DYNUPDATE_SUPPORT_TRUE= HAS_DYNUPDATE_SUPPORT_FALSE='#' else HAS_DYNUPDATE_SUPPORT_TRUE='#' HAS_DYNUPDATE_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE dynupdate DONE # # AC_HAS_DISABLE rrsig_management # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if RRSIG_MANAGEMENT_SUPPORT has been disabled" >&5 $as_echo_n "checking if RRSIG_MANAGEMENT_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-rrsig_management was given. if test "${enable_rrsig_management+set}" = set; then : enableval=$enable_rrsig_management; fi # MSG RESULT # CASE case "y$enable_rrsig_management" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_RRSIG_MANAGEMENT_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_rrsig_management=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES requires_ssl=1 # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_RRSIG_MANAGEMENT_SUPPORT 0 _ACEOF # CONDITIONAL N enable_rrsig_management=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_rrsig_management != yno; then HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE= HAS_RRSIG_MANAGEMENT_SUPPORT_FALSE='#' else HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE='#' HAS_RRSIG_MANAGEMENT_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE rrsig_management DONE if true; then HAS_DNSSEC_SUPPORT_TRUE= HAS_DNSSEC_SUPPORT_FALSE='#' else HAS_DNSSEC_SUPPORT_TRUE='#' HAS_DNSSEC_SUPPORT_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_DNSSEC_SUPPORT 1 _ACEOF requires_ssl=1 if true; then HAS_NSEC_SUPPORT_TRUE= HAS_NSEC_SUPPORT_FALSE='#' else HAS_NSEC_SUPPORT_TRUE='#' HAS_NSEC_SUPPORT_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_NSEC_SUPPORT 1 _ACEOF if true; then HAS_NSEC3_SUPPORT_TRUE= HAS_NSEC3_SUPPORT_FALSE='#' else HAS_NSEC3_SUPPORT_TRUE='#' HAS_NSEC3_SUPPORT_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_NSEC3_SUPPORT 1 _ACEOF # # AC_HAS_DISABLE zalloc # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ZALLOC_SUPPORT has been disabled" >&5 $as_echo_n "checking if ZALLOC_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-zalloc was given. if test "${enable_zalloc+set}" = set; then : enableval=$enable_zalloc; fi # MSG RESULT # CASE case "y$enable_zalloc" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_zalloc=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_SUPPORT 0 _ACEOF # CONDITIONAL N enable_zalloc=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_zalloc != yno; then HAS_ZALLOC_SUPPORT_TRUE= HAS_ZALLOC_SUPPORT_FALSE='#' else HAS_ZALLOC_SUPPORT_TRUE='#' HAS_ZALLOC_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE zalloc DONE # # AC_HAS_ENABLE zalloc_statistics # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ZALLOC_STATISTICS_SUPPORT has been enabled" >&5 $as_echo_n "checking if ZALLOC_STATISTICS_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-zalloc_statistics was given. if test "${enable_zalloc_statistics+set}" = set; then : enableval=$enable_zalloc_statistics; fi # CASE case "y$enable_zalloc_statistics" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_STATISTICS_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_zalloc_statistics="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_STATISTICS_SUPPORT 0 _ACEOF # CONDITIONAL N enable_zalloc_statistics="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_zalloc_statistics = yyes; then HAS_ZALLOC_STATISTICS_SUPPORT_TRUE= HAS_ZALLOC_STATISTICS_SUPPORT_FALSE='#' else HAS_ZALLOC_STATISTICS_SUPPORT_TRUE='#' HAS_ZALLOC_STATISTICS_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE zalloc_statistics DONE # # AC_HAS_ENABLE zalloc_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ZALLOC_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if ZALLOC_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-zalloc_debug was given. if test "${enable_zalloc_debug+set}" = set; then : enableval=$enable_zalloc_debug; fi # CASE case "y$enable_zalloc_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_zalloc_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_zalloc_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_zalloc_debug = yyes; then HAS_ZALLOC_DEBUG_SUPPORT_TRUE= HAS_ZALLOC_DEBUG_SUPPORT_FALSE='#' else HAS_ZALLOC_DEBUG_SUPPORT_TRUE='#' HAS_ZALLOC_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE zalloc_debug DONE # # AC_HAS_ENABLE malloc_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MALLOC_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if MALLOC_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-malloc_debug was given. if test "${enable_malloc_debug+set}" = set; then : enableval=$enable_malloc_debug; fi # CASE case "y$enable_malloc_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_MALLOC_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_malloc_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_MALLOC_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_malloc_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_malloc_debug = yyes; then HAS_MALLOC_DEBUG_SUPPORT_TRUE= HAS_MALLOC_DEBUG_SUPPORT_FALSE='#' else HAS_MALLOC_DEBUG_SUPPORT_TRUE='#' HAS_MALLOC_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE malloc_debug DONE # # AC_FORCE_DISABLE libc_malloc_debug # enable_libc_malloc_debug=no cat >>confdefs.h <<_ACEOF #define HAS_LIBC_MALLOC_DEBUG_SUPPORT 0 _ACEOF if test y$enable_libc_malloc_debug = yyes; then HAS_LIBC_MALLOC_DEBUG_SUPPORT_TRUE= HAS_LIBC_MALLOC_DEBUG_SUPPORT_FALSE='#' else HAS_LIBC_MALLOC_DEBUG_SUPPORT_TRUE='#' HAS_LIBC_MALLOC_DEBUG_SUPPORT_FALSE= fi # AC_FORCE_DISABLE libc_malloc_debug DONE # # AC_HAS_ENABLE bfd_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if BFD_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if BFD_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-bfd_debug was given. if test "${enable_bfd_debug+set}" = set; then : enableval=$enable_bfd_debug; fi # CASE case "y$enable_bfd_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_BFD_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_bfd_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_BFD_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_bfd_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_bfd_debug = yyes; then HAS_BFD_DEBUG_SUPPORT_TRUE= HAS_BFD_DEBUG_SUPPORT_FALSE='#' else HAS_BFD_DEBUG_SUPPORT_TRUE='#' HAS_BFD_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE bfd_debug DONE case "$enable_bfd_debug" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlinfo" >&5 $as_echo_n "checking for library containing dlinfo... " >&6; } if ${ac_cv_search_dlinfo+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlinfo (); int main () { return dlinfo (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlinfo=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlinfo+:} false; then : break fi done if ${ac_cv_search_dlinfo+:} false; then : else ac_cv_search_dlinfo=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlinfo" >&5 $as_echo "$ac_cv_search_dlinfo" >&6; } ac_res=$ac_cv_search_dlinfo if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else echo no dl fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sha1_init_ctx" >&5 $as_echo_n "checking for library containing sha1_init_ctx... " >&6; } if ${ac_cv_search_sha1_init_ctx+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sha1_init_ctx (); int main () { return sha1_init_ctx (); ; return 0; } _ACEOF for ac_lib in '' iberty; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_sha1_init_ctx=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_sha1_init_ctx+:} false; then : break fi done if ${ac_cv_search_sha1_init_ctx+:} false; then : else ac_cv_search_sha1_init_ctx=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sha1_init_ctx" >&5 $as_echo "$ac_cv_search_sha1_init_ctx" >&6; } ac_res=$ac_cv_search_sha1_init_ctx if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else echo iberty fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing bfd_init" >&5 $as_echo_n "checking for library containing bfd_init... " >&6; } if ${ac_cv_search_bfd_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char bfd_init (); int main () { return bfd_init (); ; return 0; } _ACEOF for ac_lib in '' bfd; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_bfd_init=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_bfd_init+:} false; then : break fi done if ${ac_cv_search_bfd_init+:} false; then : else ac_cv_search_bfd_init=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_bfd_init" >&5 $as_echo "$ac_cv_search_bfd_init" >&6; } ac_res=$ac_cv_search_bfd_init if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else echo no bfd;exit 1 fi ;; no|*) ;; esac # # AC_HAS_ENABLE mutex_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MUTEX_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if MUTEX_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-mutex_debug was given. if test "${enable_mutex_debug+set}" = set; then : enableval=$enable_mutex_debug; fi # CASE case "y$enable_mutex_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_MUTEX_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_mutex_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_MUTEX_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_mutex_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_mutex_debug = yyes; then HAS_MUTEX_DEBUG_SUPPORT_TRUE= HAS_MUTEX_DEBUG_SUPPORT_FALSE='#' else HAS_MUTEX_DEBUG_SUPPORT_TRUE='#' HAS_MUTEX_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE mutex_debug DONE # # AC_HAS_ENABLE lock_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LOCK_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if LOCK_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-lock_debug was given. if test "${enable_lock_debug+set}" = set; then : enableval=$enable_lock_debug; fi # CASE case "y$enable_lock_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_LOCK_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_lock_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_LOCK_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_lock_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_lock_debug = yyes; then HAS_LOCK_DEBUG_SUPPORT_TRUE= HAS_LOCK_DEBUG_SUPPORT_FALSE='#' else HAS_LOCK_DEBUG_SUPPORT_TRUE='#' HAS_LOCK_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE lock_debug DONE # # AC_HAS_ENABLE track_zones_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if TRACK_ZONES_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if TRACK_ZONES_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-track_zones_debug was given. if test "${enable_track_zones_debug+set}" = set; then : enableval=$enable_track_zones_debug; fi # CASE case "y$enable_track_zones_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_TRACK_ZONES_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_track_zones_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_TRACK_ZONES_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_track_zones_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_track_zones_debug = yyes; then HAS_TRACK_ZONES_DEBUG_SUPPORT_TRUE= HAS_TRACK_ZONES_DEBUG_SUPPORT_FALSE='#' else HAS_TRACK_ZONES_DEBUG_SUPPORT_TRUE='#' HAS_TRACK_ZONES_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE track_zones_debug DONE # # AC_HAS_ENABLE log_thread_id # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LOG_THREAD_ID has been enabled" >&5 $as_echo_n "checking if LOG_THREAD_ID has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-log_thread_id was given. if test "${enable_log_thread_id+set}" = set; then : enableval=$enable_log_thread_id; fi # CASE case "y$enable_log_thread_id" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_LOG_THREAD_ID 1 _ACEOF # CONDITIONAL Y enable_log_thread_id="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_LOG_THREAD_ID 0 _ACEOF # CONDITIONAL N enable_log_thread_id="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_log_thread_id = yyes; then HAS_LOG_THREAD_ID_TRUE= HAS_LOG_THREAD_ID_FALSE='#' else HAS_LOG_THREAD_ID_TRUE='#' HAS_LOG_THREAD_ID_FALSE= fi # SUBST # AC_HAS_ENABLE log_thread_id DONE # # AC_HAS_DISABLE log_thread_tag # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LOG_THREAD_TAG has been disabled" >&5 $as_echo_n "checking if LOG_THREAD_TAG has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-log_thread_tag was given. if test "${enable_log_thread_tag+set}" = set; then : enableval=$enable_log_thread_tag; fi # MSG RESULT # CASE case "y$enable_log_thread_tag" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_LOG_THREAD_TAG 1 _ACEOF # CONDITIONAL Y enable_log_thread_tag=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_LOG_THREAD_TAG 0 _ACEOF # CONDITIONAL N enable_log_thread_tag=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_log_thread_tag != yno; then HAS_LOG_THREAD_TAG_TRUE= HAS_LOG_THREAD_TAG_FALSE='#' else HAS_LOG_THREAD_TAG_TRUE='#' HAS_LOG_THREAD_TAG_FALSE= fi # SUBST # AC_HAS_DISABLE log_thread_tag DONE # # AC_HAS_DISABLE log_pid # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LOG_PID has been disabled" >&5 $as_echo_n "checking if LOG_PID has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-log_pid was given. if test "${enable_log_pid+set}" = set; then : enableval=$enable_log_pid; fi # MSG RESULT # CASE case "y$enable_log_pid" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_LOG_PID 1 _ACEOF # CONDITIONAL Y enable_log_pid=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_LOG_PID 0 _ACEOF # CONDITIONAL N enable_log_pid=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_log_pid != yno; then HAS_LOG_PID_TRUE= HAS_LOG_PID_FALSE='#' else HAS_LOG_PID_TRUE='#' HAS_LOG_PID_FALSE= fi # SUBST # AC_HAS_DISABLE log_pid DONE # # AC_HAS_ENABLE full_ascii7 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if FULL_ASCII7 has been enabled" >&5 $as_echo_n "checking if FULL_ASCII7 has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-full_ascii7 was given. if test "${enable_full_ascii7+set}" = set; then : enableval=$enable_full_ascii7; fi # CASE case "y$enable_full_ascii7" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_FULL_ASCII7 1 _ACEOF # CONDITIONAL Y enable_full_ascii7="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_FULL_ASCII7 0 _ACEOF # CONDITIONAL N enable_full_ascii7="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_full_ascii7 = yyes; then HAS_FULL_ASCII7_TRUE= HAS_FULL_ASCII7_FALSE='#' else HAS_FULL_ASCII7_TRUE='#' HAS_FULL_ASCII7_FALSE= fi # SUBST # AC_HAS_ENABLE full_ascii7 DONE # # AC_HAS_DISABLE ecdsa # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ECDSA_SUPPORT has been disabled" >&5 $as_echo_n "checking if ECDSA_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-ecdsa was given. if test "${enable_ecdsa+set}" = set; then : enableval=$enable_ecdsa; fi # MSG RESULT # CASE case "y$enable_ecdsa" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_ECDSA_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_ecdsa=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_ECDSA_SUPPORT 0 _ACEOF # CONDITIONAL N enable_ecdsa=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_ecdsa != yno; then HAS_ECDSA_SUPPORT_TRUE= HAS_ECDSA_SUPPORT_FALSE='#' else HAS_ECDSA_SUPPORT_TRUE='#' HAS_ECDSA_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE ecdsa DONE { $as_echo "$as_me:${as_lineno-$LINENO}: checking if EDDSA has been disabled" >&5 $as_echo_n "checking if EDDSA has been disabled... " >&6; } # Check whether --enable-EDDSA was given. if test "${enable_EDDSA+set}" = set; then : enableval=$enable_EDDSA; Disable EDDSA fi case "y$enable_eddsa" in yyes|y) if test "x$ac_cv_func_EVP_PKEY_new_raw_public_key" == xyes; then cat >>confdefs.h <<_ACEOF #define HAS_EDDSA_SUPPORT 1 _ACEOF enable_eddsa=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else cat >>confdefs.h <<_ACEOF #define HAS_EDDSA_SUPPORT 0 _ACEOF enable_eddsa=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi ;; yno|*) cat >>confdefs.h <<_ACEOF #define HAS_EDDSA_SUPPORT 0 _ACEOF enable_eddsa=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ;; esac if test y$enable_eddsa != yno; then HAS_EDDSA_TRUE= HAS_EDDSA_FALSE='#' else HAS_EDDSA_TRUE='#' HAS_EDDSA_FALSE= fi # # AC_HAS_ENABLE systemd_resolved_avoidance # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if SYSTEMD_RESOLVED_AVOIDANCE has been enabled" >&5 $as_echo_n "checking if SYSTEMD_RESOLVED_AVOIDANCE has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-systemd_resolved_avoidance was given. if test "${enable_systemd_resolved_avoidance+set}" = set; then : enableval=$enable_systemd_resolved_avoidance; fi # CASE case "y$enable_systemd_resolved_avoidance" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_SYSTEMD_RESOLVED_AVOIDANCE 1 _ACEOF # CONDITIONAL Y enable_systemd_resolved_avoidance="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_SYSTEMD_RESOLVED_AVOIDANCE 0 _ACEOF # CONDITIONAL N enable_systemd_resolved_avoidance="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_systemd_resolved_avoidance = yyes; then HAS_SYSTEMD_RESOLVED_AVOIDANCE_TRUE= HAS_SYSTEMD_RESOLVED_AVOIDANCE_FALSE='#' else HAS_SYSTEMD_RESOLVED_AVOIDANCE_TRUE='#' HAS_SYSTEMD_RESOLVED_AVOIDANCE_FALSE= fi # SUBST # AC_HAS_ENABLE systemd_resolved_avoidance DONE # # AC_HAS_ENABLE non_aa_axfr_support # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if NON_AA_AXFR_SUPPORT has been enabled" >&5 $as_echo_n "checking if NON_AA_AXFR_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-non_aa_axfr_support was given. if test "${enable_non_aa_axfr_support+set}" = set; then : enableval=$enable_non_aa_axfr_support; fi # CASE case "y$enable_non_aa_axfr_support" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_NON_AA_AXFR_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_non_aa_axfr_support="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_NON_AA_AXFR_SUPPORT 0 _ACEOF # CONDITIONAL N enable_non_aa_axfr_support="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_non_aa_axfr_support = yyes; then HAS_NON_AA_AXFR_SUPPORT_TRUE= HAS_NON_AA_AXFR_SUPPORT_FALSE='#' else HAS_NON_AA_AXFR_SUPPORT_TRUE='#' HAS_NON_AA_AXFR_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE non_aa_axfr_support DONE { $as_echo "$as_me:${as_lineno-$LINENO}: checking if has strdup" >&5 $as_echo_n "checking if has strdup... " >&6; } if false; then HAS_STRDUP_TRUE= HAS_STRDUP_FALSE='#' else HAS_STRDUP_TRUE='#' HAS_STRDUP_FALSE= fi cat > strdup_test.c <<_ACEOF #include #include int main(int argc, char** argv) { char* p = strdup("test"); return 0; } _ACEOF ${CC} ${CFLAGS} strdup_test.c -o strdup_test if [ $? -eq 0 ]; then has_strdup=1; echo "yes" else echo "no" fi rm -f strdup_test strdup_test.c if test $has_strdup = yes; then HAS_STRDUP_TRUE= HAS_STRDUP_FALSE='#' else HAS_STRDUP_TRUE='#' HAS_STRDUP_FALSE= fi # # AC_HAS_ENABLE event_dynamic_module # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if EVENT_DYNAMIC_MODULE has been enabled" >&5 $as_echo_n "checking if EVENT_DYNAMIC_MODULE has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-event_dynamic_module was given. if test "${enable_event_dynamic_module+set}" = set; then : enableval=$enable_event_dynamic_module; fi # CASE case "y$enable_event_dynamic_module" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_EVENT_DYNAMIC_MODULE 1 _ACEOF # CONDITIONAL Y enable_event_dynamic_module="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_EVENT_DYNAMIC_MODULE 0 _ACEOF # CONDITIONAL N enable_event_dynamic_module="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_event_dynamic_module = yyes; then HAS_EVENT_DYNAMIC_MODULE_TRUE= HAS_EVENT_DYNAMIC_MODULE_FALSE='#' else HAS_EVENT_DYNAMIC_MODULE_TRUE='#' HAS_EVENT_DYNAMIC_MODULE_FALSE= fi # SUBST # AC_HAS_ENABLE event_dynamic_module DONE # # AC_HAS_WITH logdir # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if logdir has been given" >&5 $as_echo_n "checking if logdir has been given... " >&6; } # ARG WITH # Check whether --with-logdir was given. if test "${with_logdir+set}" = set; then : withval=$with_logdir; # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_LOGDIR 1 _ACEOF # CONDITIONAL Y cat >>confdefs.h <<_ACEOF #define HAS_WITH_LOGDIR "$with_logdir" // $withval _ACEOF with_logdir="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES logdir="$withval" with_logdir="$logdir" # ENDIF else # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_LOGDIR 0 _ACEOF # CONDITIONAL N with_logdir="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO logdir=${localstatedir}/log/yadifa with_logdir="$logdir" # ENDIF fi # CONDITIONAL if test "y$with_logdir" == "yyes"; then HAS_LOGDIR_TRUE= HAS_LOGDIR_FALSE='#' else HAS_LOGDIR_TRUE='#' HAS_LOGDIR_FALSE= fi # SUBST # AC_HAS_WITH logdir DONE echo "LOGDIR=$logdir" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr has a sa_len field" >&5 $as_echo_n "checking if sockaddr has a sa_len field... " >&6; } cat > sockaddr_sa_len.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETINET6_IN6_H #include #endif int main(int argc, char** argv) { struct sockaddr sa; sa.sa_len = 4; } _ACEOF has_sockaddr_sa_len=0 ${CC} ${CFLAGS} sockaddr_sa_len.c > /dev/null 2>&1 if [ $? -eq 0 ]; then has_sockaddr_sa_len=1; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f sockaddr_sa_len.c sockaddr_sa_len if test $has_sockaddr_sa_len = yes; then HAS_SOCKADDR_SA_LEN_TRUE= HAS_SOCKADDR_SA_LEN_FALSE='#' else HAS_SOCKADDR_SA_LEN_TRUE='#' HAS_SOCKADDR_SA_LEN_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_SOCKADDR_SA_LEN $has_sockaddr_sa_len _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr_in has a sin_len field" >&5 $as_echo_n "checking if sockaddr_in has a sin_len field... " >&6; } cat > sockaddr_in_sin_len.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETINET6_IN6_H #include #endif int main(int argc, char** argv) { struct sockaddr_in sa; sa.sin_len = sizeof(struct sockaddr_in); } _ACEOF has_sockaddr_in_sin_len=0 ${CC} ${CFLAGS} sockaddr_in_sin_len.c > /dev/null 2>&1 if [ $? -eq 0 ]; then has_sockaddr_in_sin_len=1; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f sockaddr_in_sin_len.c sockaddr_in_sin_len if test $has_sockaddr_in_sin_len = yes; then HAS_SOCKADDR_IN_SIN_LEN_TRUE= HAS_SOCKADDR_IN_SIN_LEN_FALSE='#' else HAS_SOCKADDR_IN_SIN_LEN_TRUE='#' HAS_SOCKADDR_IN_SIN_LEN_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_SOCKADDR_IN_SIN_LEN $has_sockaddr_in_sin_len _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr_in6 has a sin6_len field" >&5 $as_echo_n "checking if sockaddr_in6 has a sin6_len field... " >&6; } cat > sockaddr_in6_sin6_len.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETINET6_IN6_H #include #endif int main(int argc, char** argv) { struct sockaddr_in6 sa; sa.sin6_len = sizeof(struct sockaddr_in6); } _ACEOF has_sockaddr_in6_sin6_len=0 ${CC} ${CFLAGS} sockaddr_in6_sin6_len.c > /dev/null 2>&1 if [ $? -eq 0 ]; then has_sockaddr_in6_sin6_len=1; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f sockaddr_in6_sin6_len.c sockaddr_in6_sin6_len if test $has_sockaddr_in6_sin6_len = yes; then HAS_SOCKADDR_IN6_SIN6_LEN_TRUE= HAS_SOCKADDR_IN6_SIN6_LEN_FALSE='#' else HAS_SOCKADDR_IN6_SIN6_LEN_TRUE='#' HAS_SOCKADDR_IN6_SIN6_LEN_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_SOCKADDR_IN6_SIN6_LEN $has_sockaddr_in6_sin6_len _ACEOF LDDYN="-Wl,-Bdynamic" LDSTAT="-Wl,-Bstatic" echo -n "checking if -Bstatic & -Bdynamic are supported ... " $CC -Wl,-Bstatic 2>&1|grep Bstatic > /dev/null if [ $? -eq 0 ] then echo "not supported" LDDYN="" LDSTAT="" else echo "supported" fi LIBS="$LDDYN $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 $as_echo_n "checking for library containing gethostbyname... " >&6; } if ${ac_cv_search_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF for ac_lib in '' nsl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gethostbyname=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gethostbyname+:} false; then : break fi done if ${ac_cv_search_gethostbyname+:} false; then : else ac_cv_search_gethostbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 $as_echo "$ac_cv_search_gethostbyname" >&6; } ac_res=$ac_cv_search_gethostbyname if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 $as_echo_n "checking for library containing socket... " >&6; } if ${ac_cv_search_socket+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF for ac_lib in '' socket; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_socket=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_socket+:} false; then : break fi done if ${ac_cv_search_socket+:} false; then : else ac_cv_search_socket=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 $as_echo "$ac_cv_search_socket" >&6; } ac_res=$ac_cv_search_socket if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_self" >&5 $as_echo_n "checking for library containing pthread_self... " >&6; } if ${ac_cv_search_pthread_self+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_self (); int main () { return pthread_self (); ; return 0; } _ACEOF for ac_lib in '' pthread; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_pthread_self=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_pthread_self+:} false; then : break fi done if ${ac_cv_search_pthread_self+:} false; then : else ac_cv_search_pthread_self=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_self" >&5 $as_echo "$ac_cv_search_pthread_self" >&6; } ac_res=$ac_cv_search_pthread_self if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing backtrace" >&5 $as_echo_n "checking for library containing backtrace... " >&6; } if ${ac_cv_search_backtrace+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char backtrace (); int main () { return backtrace (); ; return 0; } _ACEOF for ac_lib in '' execinfo; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_backtrace=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_backtrace+:} false; then : break fi done if ${ac_cv_search_backtrace+:} false; then : else ac_cv_search_backtrace=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_backtrace" >&5 $as_echo "$ac_cv_search_backtrace" >&6; } ac_res=$ac_cv_search_backtrace if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing backtrace_symbols" >&5 $as_echo_n "checking for library containing backtrace_symbols... " >&6; } if ${ac_cv_search_backtrace_symbols+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char backtrace_symbols (); int main () { return backtrace_symbols (); ; return 0; } _ACEOF for ac_lib in '' execinfo; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_backtrace_symbols=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_backtrace_symbols+:} false; then : break fi done if ${ac_cv_search_backtrace_symbols+:} false; then : else ac_cv_search_backtrace_symbols=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_backtrace_symbols" >&5 $as_echo "$ac_cv_search_backtrace_symbols" >&6; } ac_res=$ac_cv_search_backtrace_symbols if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi if [ $requires_tcl -eq 1 ] then echo "TCL is required by this setup ..." if [ "$tcl_version" = "" ] then echo "tcl_version empty, expected something like 'tcl8.x'" exit 1 fi CFLAGS="$CFLAGS -DWITHTCLINCLUDED" if [ ! "${tcl_includedir}" = "/usr/include" ] && [ ! "${tcl_includedir}" = "" ] then CFLAGS="$CFLAGS -I${tcl_includedir}" fi if [ ! "${tcl_libdir}" = "/usr/lib" ] && [ ! "${tcl_libdir}" = "/lib" ] && [ ! "${tcl_libdir}" = "" ] then LDFLAGS="-L${tcl_libdir} $LDFLAGS" fi echo "searching for library '$tcl_version' in the system" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing Tcl_Main" >&5 $as_echo_n "checking for library containing Tcl_Main... " >&6; } if ${ac_cv_search_Tcl_Main+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char Tcl_Main (); int main () { return Tcl_Main (); ; return 0; } _ACEOF for ac_lib in '' ${tcl_version}; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_Tcl_Main=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_Tcl_Main+:} false; then : break fi done if ${ac_cv_search_Tcl_Main+:} false; then : else ac_cv_search_Tcl_Main=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_Tcl_Main" >&5 $as_echo "$ac_cv_search_Tcl_Main" >&6; } ac_res=$ac_cv_search_Tcl_Main if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else echo "could not find ${tcl_version} :: tcl_includedir=${tcl_includedir} :: tcl_libdir=${tcl_libdir}"; exit 1 fi fi if [ $requires_ssl -eq 1 ] then echo "SSL is required by this setup ..." SSLDEPS="" echo "Finding the SSL dependencies" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5 $as_echo_n "checking for library containing deflate... " >&6; } if ${ac_cv_search_deflate+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char deflate (); int main () { return deflate (); ; return 0; } _ACEOF for ac_lib in '' z; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_deflate=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_deflate+:} false; then : break fi done if ${ac_cv_search_deflate+:} false; then : else ac_cv_search_deflate=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5 $as_echo "$ac_cv_search_deflate" >&6; } ac_res=$ac_cv_search_deflate if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi echo "SSLDEPS=${SSLDEPS}" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if SSL is available" >&5 $as_echo_n "checking if SSL is available... " >&6; } ac_check_lib_ssl=0 # Check whether --with-openssl_lib was given. if test "${with_openssl_lib+set}" = set; then : withval=$with_openssl_lib; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } LDFLAGS="-L$with_openssl_lib $SSLDEPS $LDFLAGS" echo "LDFLAGS=${LDFLAGS}" ac_check_lib_ssl=1 fi # Check whether --with-openssl_include was given. if test "${with_openssl_include+set}" = set; then : withval=$with_openssl_include; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="-I$with_openssl_include $CFLAGS $CFLAGS3264" echo "CFLAGS=${LDFLAGS}" ac_check_lib_ssl=1 fi # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : withval=$with_openssl; echo "yes" OPENSSL="${withval}" CFLAGS="-I$with_openssl/include $CFLAGS $CFLAGS3264" LDFLAGS="-L$with_openssl/lib $SSLDEPS $LDFLAGS" echo "CFLAGS=$CFLAGS" echo "LDFLAGS=$LDFLAGS" ac_check_lib_ssl=1 else echo "no" CFLAGS="$CFLAGS $CFLAGS3264" LDFLAGS="$SSLDEPS $LDFLAGS" echo "CFLAGS=${CFLAGS}" echo "LDFLAGS=${LDFLAGS}" ac_check_lib_ssl=1 fi if [ $ac_check_lib_ssl -eq 1 ] then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_new" >&5 $as_echo_n "checking for library containing RSA_new... " >&6; } if ${ac_cv_search_RSA_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char RSA_new (); int main () { return RSA_new (); ; return 0; } _ACEOF for ac_lib in '' crypto; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_RSA_new=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_RSA_new+:} false; then : break fi done if ${ac_cv_search_RSA_new+:} false; then : else ac_cv_search_RSA_new=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_new" >&5 $as_echo "$ac_cv_search_RSA_new" >&6; } ac_res=$ac_cv_search_RSA_new if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing SSL_library_init" >&5 $as_echo_n "checking for library containing SSL_library_init... " >&6; } if ${ac_cv_search_SSL_library_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char SSL_library_init (); int main () { return SSL_library_init (); ; return 0; } _ACEOF for ac_lib in '' ssl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_SSL_library_init=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_SSL_library_init+:} false; then : break fi done if ${ac_cv_search_SSL_library_init+:} false; then : else ac_cv_search_SSL_library_init=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_SSL_library_init" >&5 $as_echo "$ac_cv_search_SSL_library_init" >&6; } ac_res=$ac_cv_search_SSL_library_init if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing OPENSSL_init_ssl" >&5 $as_echo_n "checking for library containing OPENSSL_init_ssl... " >&6; } if ${ac_cv_search_OPENSSL_init_ssl+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char OPENSSL_init_ssl (); int main () { return OPENSSL_init_ssl (); ; return 0; } _ACEOF for ac_lib in '' ssl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_OPENSSL_init_ssl=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_OPENSSL_init_ssl+:} false; then : break fi done if ${ac_cv_search_OPENSSL_init_ssl+:} false; then : else ac_cv_search_OPENSSL_init_ssl=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_OPENSSL_init_ssl" >&5 $as_echo "$ac_cv_search_OPENSSL_init_ssl" >&6; } ac_res=$ac_cv_search_OPENSSL_init_ssl if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else exit 1 fi fi ac_fn_c_check_func "$LINENO" "EVP_PKEY_new_raw_public_key" "ac_cv_func_EVP_PKEY_new_raw_public_key" if test "x$ac_cv_func_EVP_PKEY_new_raw_public_key" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAS_EVP_PKEY_NEW_RAW_PUBLIC_KEY 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAS_EVP_PKEY_NEW_RAW_PUBLIC_KEY 0 _ACEOF fi cat >>confdefs.h <<_ACEOF #define HAS_OPENSSL 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAS_OPENSSL 0 _ACEOF fi else echo "SSL is not required by this setup" fi if [ $requires_dnscore -eq 1 ] then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 $as_echo_n "checking for library containing clock_gettime... " >&6; } if ${ac_cv_search_clock_gettime+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char clock_gettime (); int main () { return clock_gettime (); ; return 0; } _ACEOF for ac_lib in '' rt; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_clock_gettime=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_clock_gettime+:} false; then : break fi done if ${ac_cv_search_clock_gettime+:} false; then : else ac_cv_search_clock_gettime=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 $as_echo "$ac_cv_search_clock_gettime" >&6; } ac_res=$ac_cv_search_clock_gettime if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the DNS Core library" >&5 $as_echo_n "checking for the DNS Core library... " >&6; } if [ ! -d ${srcdir}/../../lib/dnscore ] then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnscore_init in -ldnscore" >&5 $as_echo_n "checking for dnscore_init in -ldnscore... " >&6; } if ${ac_cv_lib_dnscore_dnscore_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnscore $LDSTAT -ldnscore $LDDYN -lssl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnscore_init (); int main () { return dnscore_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dnscore_dnscore_init=yes else ac_cv_lib_dnscore_dnscore_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnscore_dnscore_init" >&5 $as_echo "$ac_cv_lib_dnscore_dnscore_init" >&6; } if test "x$ac_cv_lib_dnscore_dnscore_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDNSCORE 1 _ACEOF LIBS="-ldnscore $LIBS" else exit fi else CFLAGS="-I${srcdir}/../../lib/dnscore/include $CFLAGS" LDFLAGS="-L../../lib/dnscore/.libs $LDFLAGS" LDFLAGS="$LDFLAGS $LDSTAT -ldnscore $LDDYN" fi fi if [ $requires_dnsdb -eq 1 ] then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the DNS Database library" >&5 $as_echo_n "checking for the DNS Database library... " >&6; } if [ ! -d ${srcdir}/../../lib/dnsdb ] then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for zdb_init in -ldnsdb" >&5 $as_echo_n "checking for zdb_init in -ldnsdb... " >&6; } if ${ac_cv_lib_dnsdb_zdb_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnsdb $LDSTAT -ldnscore $LDDYN -lssl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char zdb_init (); int main () { return zdb_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dnsdb_zdb_init=yes else ac_cv_lib_dnsdb_zdb_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnsdb_zdb_init" >&5 $as_echo "$ac_cv_lib_dnsdb_zdb_init" >&6; } if test "x$ac_cv_lib_dnsdb_zdb_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDNSDB 1 _ACEOF LIBS="-ldnsdb $LIBS" else exit fi else echo "embedded" CFLAGS="-I${srcdir}/../../lib/dnsdb/include $CFLAGS" LDFLAGS="-L../../lib/dnsdb/.libs $LDFLAGS" LDFLAGS="$LDFLAGS $LDSTAT -ldnsdb $LDDYN" fi fi if [ $requires_dnslg -eq 1 ] then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the DNS Looking Glass library" >&5 $as_echo_n "checking for the DNS Looking Glass library... " >&6; } if [ ! -d ${srcdir}/../../lib/dnslg ] then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnslg_init in -ldnslg" >&5 $as_echo_n "checking for dnslg_init in -ldnslg... " >&6; } if ${ac_cv_lib_dnslg_dnslg_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnslg $LDSTAT -ldnscore $LDDYN $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnslg_init (); int main () { return dnslg_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dnslg_dnslg_init=yes else ac_cv_lib_dnslg_dnslg_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnslg_dnslg_init" >&5 $as_echo "$ac_cv_lib_dnslg_dnslg_init" >&6; } if test "x$ac_cv_lib_dnslg_dnslg_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDNSLG 1 _ACEOF LIBS="-ldnslg $LIBS" else exit fi else CFLAGS="-I${srcdir}/../../lib/dnslg/include $CFLAGS" LDFLAGS="-L../../lib/dnslg/.libs $LDFLAGS" LDFLAGS="$LDFLAGS $LDSTAT -ldnslg $LDDYN" fi fi LDFLAGS="$LDFLAGS $LDDYN" LIBS="$LDDYN $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LTO has been enabled" >&5 $as_echo_n "checking if LTO has been enabled... " >&6; } # Check whether --enable-lto was given. if test "${enable_lto+set}" = set; then : enableval=$enable_lto; enable_lto=yes else enable_lto=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_lto" >&5 $as_echo "$enable_lto" >&6; } case "$enable_lto" in yes) type -p gold if [ $? -ne 0 ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: WARNING: 'gold' not found" >&5 $as_echo "WARNING: 'gold' not found" >&6; } sleep 1 fi if [ ! "$LD" = "" ] then $LD -v |grep -i gold > /dev/null 2>&1 if [ $? -ne 0 ] then { $as_echo "$as_me:${as_lineno-$LINENO}: result: WARNING: LTO enabled but LD ($LD) is not gold" >&5 $as_echo "WARNING: LTO enabled but LD ($LD) is not gold" >&6; } sleep 1 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: LD not defined" >&5 $as_echo "LD not defined" >&6; } fi ;; no|*) ;; esac if test "x$enable_lto" == "yyes"; then HAS_LTO_SUPPORT_TRUE= HAS_LTO_SUPPORT_FALSE='#' else HAS_LTO_SUPPORT_TRUE='#' HAS_LTO_SUPPORT_FALSE= fi # # AC_HAS_DISABLE rrl # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if RRL_SUPPORT has been disabled" >&5 $as_echo_n "checking if RRL_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-rrl was given. if test "${enable_rrl+set}" = set; then : enableval=$enable_rrl; fi # MSG RESULT # CASE case "y$enable_rrl" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_RRL_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_rrl=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_RRL_SUPPORT 0 _ACEOF # CONDITIONAL N enable_rrl=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_rrl != yno; then HAS_RRL_SUPPORT_TRUE= HAS_RRL_SUPPORT_FALSE='#' else HAS_RRL_SUPPORT_TRUE='#' HAS_RRL_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE rrl DONE # # AC_HAS_DISABLE master # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MASTER_SUPPORT has been disabled" >&5 $as_echo_n "checking if MASTER_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-master was given. if test "${enable_master+set}" = set; then : enableval=$enable_master; fi # MSG RESULT # CASE case "y$enable_master" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_MASTER_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_master=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES requires_ssl=1 # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_MASTER_SUPPORT 0 _ACEOF # CONDITIONAL N enable_master=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO enable_dynupdate='no' enable_rrsig_management='no' # ENDIF ;; esac # CONDITIONAL if test y$enable_master != yno; then HAS_MASTER_SUPPORT_TRUE= HAS_MASTER_SUPPORT_FALSE='#' else HAS_MASTER_SUPPORT_TRUE='#' HAS_MASTER_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE master DONE # # AC_HAS_DISABLE ctrl # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if CTRL has been disabled" >&5 $as_echo_n "checking if CTRL has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-ctrl was given. if test "${enable_ctrl+set}" = set; then : enableval=$enable_ctrl; fi # MSG RESULT # CASE case "y$enable_ctrl" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_CTRL 1 _ACEOF # CONDITIONAL Y enable_ctrl=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_CTRL 0 _ACEOF # CONDITIONAL N enable_ctrl=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_ctrl != yno; then HAS_CTRL_TRUE= HAS_CTRL_FALSE='#' else HAS_CTRL_TRUE='#' HAS_CTRL_FALSE= fi # SUBST # AC_HAS_DISABLE ctrl DONE if xno = xyes; then HAS_ZONESIGN_TRUE= HAS_ZONESIGN_FALSE='#' else HAS_ZONESIGN_TRUE='#' HAS_ZONESIGN_FALSE= fi # # AC_HAS_ENABLE keygen # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if KEYGEN has been enabled" >&5 $as_echo_n "checking if KEYGEN has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-keygen was given. if test "${enable_keygen+set}" = set; then : enableval=$enable_keygen; fi # CASE case "y$enable_keygen" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_KEYGEN 1 _ACEOF # CONDITIONAL Y enable_keygen="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_KEYGEN 0 _ACEOF # CONDITIONAL N enable_keygen="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_keygen = yyes; then HAS_KEYGEN_TRUE= HAS_KEYGEN_FALSE='#' else HAS_KEYGEN_TRUE='#' HAS_KEYGEN_FALSE= fi # SUBST # AC_HAS_ENABLE keygen DONE # # AC_HAS_DISABLE nsid # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if NSID_SUPPORT has been disabled" >&5 $as_echo_n "checking if NSID_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-nsid was given. if test "${enable_nsid+set}" = set; then : enableval=$enable_nsid; fi # MSG RESULT # CASE case "y$enable_nsid" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_NSID_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_nsid=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_NSID_SUPPORT 0 _ACEOF # CONDITIONAL N enable_nsid=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_nsid != yno; then HAS_NSID_SUPPORT_TRUE= HAS_NSID_SUPPORT_FALSE='#' else HAS_NSID_SUPPORT_TRUE='#' HAS_NSID_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE nsid DONE # # AC_FORCE_ENABLE acl # enable_acl=yes cat >>confdefs.h <<_ACEOF #define HAS_ACL_SUPPORT 1 _ACEOF if test y$enable_acl = yyes; then HAS_ACL_SUPPORT_TRUE= HAS_ACL_SUPPORT_FALSE='#' else HAS_ACL_SUPPORT_TRUE='#' HAS_ACL_SUPPORT_FALSE= fi # AC_FORCE_ENABLE acl DONE requires_ssl=1 # # AC_FORCE_ENABLE tsig # enable_tsig=yes cat >>confdefs.h <<_ACEOF #define HAS_TSIG_SUPPORT 1 _ACEOF if test y$enable_tsig = yyes; then HAS_TSIG_SUPPORT_TRUE= HAS_TSIG_SUPPORT_FALSE='#' else HAS_TSIG_SUPPORT_TRUE='#' HAS_TSIG_SUPPORT_FALSE= fi # AC_FORCE_ENABLE tsig DONE requires_ssl=1 # # AC_HAS_DISABLE dynupdate # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if DYNUPDATE_SUPPORT has been disabled" >&5 $as_echo_n "checking if DYNUPDATE_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-dynupdate was given. if test "${enable_dynupdate+set}" = set; then : enableval=$enable_dynupdate; fi # MSG RESULT # CASE case "y$enable_dynupdate" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_DYNUPDATE_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_dynupdate=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_DYNUPDATE_SUPPORT 0 _ACEOF # CONDITIONAL N enable_dynupdate=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_dynupdate != yno; then HAS_DYNUPDATE_SUPPORT_TRUE= HAS_DYNUPDATE_SUPPORT_FALSE='#' else HAS_DYNUPDATE_SUPPORT_TRUE='#' HAS_DYNUPDATE_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE dynupdate DONE # # AC_HAS_DISABLE rrsig_management # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if RRSIG_MANAGEMENT_SUPPORT has been disabled" >&5 $as_echo_n "checking if RRSIG_MANAGEMENT_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-rrsig_management was given. if test "${enable_rrsig_management+set}" = set; then : enableval=$enable_rrsig_management; fi # MSG RESULT # CASE case "y$enable_rrsig_management" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_RRSIG_MANAGEMENT_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_rrsig_management=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES requires_ssl=1 # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_RRSIG_MANAGEMENT_SUPPORT 0 _ACEOF # CONDITIONAL N enable_rrsig_management=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_rrsig_management != yno; then HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE= HAS_RRSIG_MANAGEMENT_SUPPORT_FALSE='#' else HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE='#' HAS_RRSIG_MANAGEMENT_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE rrsig_management DONE if true; then HAS_DNSSEC_SUPPORT_TRUE= HAS_DNSSEC_SUPPORT_FALSE='#' else HAS_DNSSEC_SUPPORT_TRUE='#' HAS_DNSSEC_SUPPORT_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_DNSSEC_SUPPORT 1 _ACEOF requires_ssl=1 if true; then HAS_NSEC_SUPPORT_TRUE= HAS_NSEC_SUPPORT_FALSE='#' else HAS_NSEC_SUPPORT_TRUE='#' HAS_NSEC_SUPPORT_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_NSEC_SUPPORT 1 _ACEOF if true; then HAS_NSEC3_SUPPORT_TRUE= HAS_NSEC3_SUPPORT_FALSE='#' else HAS_NSEC3_SUPPORT_TRUE='#' HAS_NSEC3_SUPPORT_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_NSEC3_SUPPORT 1 _ACEOF # # AC_HAS_DISABLE zalloc # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ZALLOC_SUPPORT has been disabled" >&5 $as_echo_n "checking if ZALLOC_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-zalloc was given. if test "${enable_zalloc+set}" = set; then : enableval=$enable_zalloc; fi # MSG RESULT # CASE case "y$enable_zalloc" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_zalloc=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_SUPPORT 0 _ACEOF # CONDITIONAL N enable_zalloc=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_zalloc != yno; then HAS_ZALLOC_SUPPORT_TRUE= HAS_ZALLOC_SUPPORT_FALSE='#' else HAS_ZALLOC_SUPPORT_TRUE='#' HAS_ZALLOC_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE zalloc DONE # # AC_HAS_ENABLE zalloc_statistics # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ZALLOC_STATISTICS_SUPPORT has been enabled" >&5 $as_echo_n "checking if ZALLOC_STATISTICS_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-zalloc_statistics was given. if test "${enable_zalloc_statistics+set}" = set; then : enableval=$enable_zalloc_statistics; fi # CASE case "y$enable_zalloc_statistics" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_STATISTICS_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_zalloc_statistics="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_STATISTICS_SUPPORT 0 _ACEOF # CONDITIONAL N enable_zalloc_statistics="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_zalloc_statistics = yyes; then HAS_ZALLOC_STATISTICS_SUPPORT_TRUE= HAS_ZALLOC_STATISTICS_SUPPORT_FALSE='#' else HAS_ZALLOC_STATISTICS_SUPPORT_TRUE='#' HAS_ZALLOC_STATISTICS_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE zalloc_statistics DONE # # AC_HAS_ENABLE zalloc_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ZALLOC_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if ZALLOC_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-zalloc_debug was given. if test "${enable_zalloc_debug+set}" = set; then : enableval=$enable_zalloc_debug; fi # CASE case "y$enable_zalloc_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_zalloc_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_ZALLOC_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_zalloc_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_zalloc_debug = yyes; then HAS_ZALLOC_DEBUG_SUPPORT_TRUE= HAS_ZALLOC_DEBUG_SUPPORT_FALSE='#' else HAS_ZALLOC_DEBUG_SUPPORT_TRUE='#' HAS_ZALLOC_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE zalloc_debug DONE # # AC_HAS_ENABLE malloc_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MALLOC_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if MALLOC_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-malloc_debug was given. if test "${enable_malloc_debug+set}" = set; then : enableval=$enable_malloc_debug; fi # CASE case "y$enable_malloc_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_MALLOC_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_malloc_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_MALLOC_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_malloc_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_malloc_debug = yyes; then HAS_MALLOC_DEBUG_SUPPORT_TRUE= HAS_MALLOC_DEBUG_SUPPORT_FALSE='#' else HAS_MALLOC_DEBUG_SUPPORT_TRUE='#' HAS_MALLOC_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE malloc_debug DONE # # AC_FORCE_DISABLE libc_malloc_debug # enable_libc_malloc_debug=no cat >>confdefs.h <<_ACEOF #define HAS_LIBC_MALLOC_DEBUG_SUPPORT 0 _ACEOF if test y$enable_libc_malloc_debug = yyes; then HAS_LIBC_MALLOC_DEBUG_SUPPORT_TRUE= HAS_LIBC_MALLOC_DEBUG_SUPPORT_FALSE='#' else HAS_LIBC_MALLOC_DEBUG_SUPPORT_TRUE='#' HAS_LIBC_MALLOC_DEBUG_SUPPORT_FALSE= fi # AC_FORCE_DISABLE libc_malloc_debug DONE # # AC_HAS_ENABLE bfd_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if BFD_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if BFD_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-bfd_debug was given. if test "${enable_bfd_debug+set}" = set; then : enableval=$enable_bfd_debug; fi # CASE case "y$enable_bfd_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_BFD_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_bfd_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_BFD_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_bfd_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_bfd_debug = yyes; then HAS_BFD_DEBUG_SUPPORT_TRUE= HAS_BFD_DEBUG_SUPPORT_FALSE='#' else HAS_BFD_DEBUG_SUPPORT_TRUE='#' HAS_BFD_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE bfd_debug DONE case "$enable_bfd_debug" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlinfo" >&5 $as_echo_n "checking for library containing dlinfo... " >&6; } if ${ac_cv_search_dlinfo+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlinfo (); int main () { return dlinfo (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlinfo=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlinfo+:} false; then : break fi done if ${ac_cv_search_dlinfo+:} false; then : else ac_cv_search_dlinfo=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlinfo" >&5 $as_echo "$ac_cv_search_dlinfo" >&6; } ac_res=$ac_cv_search_dlinfo if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else echo no dl fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sha1_init_ctx" >&5 $as_echo_n "checking for library containing sha1_init_ctx... " >&6; } if ${ac_cv_search_sha1_init_ctx+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sha1_init_ctx (); int main () { return sha1_init_ctx (); ; return 0; } _ACEOF for ac_lib in '' iberty; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_sha1_init_ctx=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_sha1_init_ctx+:} false; then : break fi done if ${ac_cv_search_sha1_init_ctx+:} false; then : else ac_cv_search_sha1_init_ctx=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sha1_init_ctx" >&5 $as_echo "$ac_cv_search_sha1_init_ctx" >&6; } ac_res=$ac_cv_search_sha1_init_ctx if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else echo iberty fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing bfd_init" >&5 $as_echo_n "checking for library containing bfd_init... " >&6; } if ${ac_cv_search_bfd_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char bfd_init (); int main () { return bfd_init (); ; return 0; } _ACEOF for ac_lib in '' bfd; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_bfd_init=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_bfd_init+:} false; then : break fi done if ${ac_cv_search_bfd_init+:} false; then : else ac_cv_search_bfd_init=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_bfd_init" >&5 $as_echo "$ac_cv_search_bfd_init" >&6; } ac_res=$ac_cv_search_bfd_init if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else echo no bfd;exit 1 fi ;; no|*) ;; esac # # AC_HAS_ENABLE mutex_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if MUTEX_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if MUTEX_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-mutex_debug was given. if test "${enable_mutex_debug+set}" = set; then : enableval=$enable_mutex_debug; fi # CASE case "y$enable_mutex_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_MUTEX_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_mutex_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_MUTEX_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_mutex_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_mutex_debug = yyes; then HAS_MUTEX_DEBUG_SUPPORT_TRUE= HAS_MUTEX_DEBUG_SUPPORT_FALSE='#' else HAS_MUTEX_DEBUG_SUPPORT_TRUE='#' HAS_MUTEX_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE mutex_debug DONE # # AC_HAS_ENABLE lock_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LOCK_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if LOCK_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-lock_debug was given. if test "${enable_lock_debug+set}" = set; then : enableval=$enable_lock_debug; fi # CASE case "y$enable_lock_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_LOCK_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_lock_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_LOCK_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_lock_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_lock_debug = yyes; then HAS_LOCK_DEBUG_SUPPORT_TRUE= HAS_LOCK_DEBUG_SUPPORT_FALSE='#' else HAS_LOCK_DEBUG_SUPPORT_TRUE='#' HAS_LOCK_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE lock_debug DONE # # AC_HAS_ENABLE track_zones_debug # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if TRACK_ZONES_DEBUG_SUPPORT has been enabled" >&5 $as_echo_n "checking if TRACK_ZONES_DEBUG_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-track_zones_debug was given. if test "${enable_track_zones_debug+set}" = set; then : enableval=$enable_track_zones_debug; fi # CASE case "y$enable_track_zones_debug" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_TRACK_ZONES_DEBUG_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_track_zones_debug="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_TRACK_ZONES_DEBUG_SUPPORT 0 _ACEOF # CONDITIONAL N enable_track_zones_debug="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_track_zones_debug = yyes; then HAS_TRACK_ZONES_DEBUG_SUPPORT_TRUE= HAS_TRACK_ZONES_DEBUG_SUPPORT_FALSE='#' else HAS_TRACK_ZONES_DEBUG_SUPPORT_TRUE='#' HAS_TRACK_ZONES_DEBUG_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE track_zones_debug DONE # # AC_HAS_ENABLE log_thread_id # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LOG_THREAD_ID has been enabled" >&5 $as_echo_n "checking if LOG_THREAD_ID has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-log_thread_id was given. if test "${enable_log_thread_id+set}" = set; then : enableval=$enable_log_thread_id; fi # CASE case "y$enable_log_thread_id" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_LOG_THREAD_ID 1 _ACEOF # CONDITIONAL Y enable_log_thread_id="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_LOG_THREAD_ID 0 _ACEOF # CONDITIONAL N enable_log_thread_id="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_log_thread_id = yyes; then HAS_LOG_THREAD_ID_TRUE= HAS_LOG_THREAD_ID_FALSE='#' else HAS_LOG_THREAD_ID_TRUE='#' HAS_LOG_THREAD_ID_FALSE= fi # SUBST # AC_HAS_ENABLE log_thread_id DONE # # AC_HAS_DISABLE log_thread_tag # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LOG_THREAD_TAG has been disabled" >&5 $as_echo_n "checking if LOG_THREAD_TAG has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-log_thread_tag was given. if test "${enable_log_thread_tag+set}" = set; then : enableval=$enable_log_thread_tag; fi # MSG RESULT # CASE case "y$enable_log_thread_tag" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_LOG_THREAD_TAG 1 _ACEOF # CONDITIONAL Y enable_log_thread_tag=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_LOG_THREAD_TAG 0 _ACEOF # CONDITIONAL N enable_log_thread_tag=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_log_thread_tag != yno; then HAS_LOG_THREAD_TAG_TRUE= HAS_LOG_THREAD_TAG_FALSE='#' else HAS_LOG_THREAD_TAG_TRUE='#' HAS_LOG_THREAD_TAG_FALSE= fi # SUBST # AC_HAS_DISABLE log_thread_tag DONE # # AC_HAS_DISABLE log_pid # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if LOG_PID has been disabled" >&5 $as_echo_n "checking if LOG_PID has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-log_pid was given. if test "${enable_log_pid+set}" = set; then : enableval=$enable_log_pid; fi # MSG RESULT # CASE case "y$enable_log_pid" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_LOG_PID 1 _ACEOF # CONDITIONAL Y enable_log_pid=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_LOG_PID 0 _ACEOF # CONDITIONAL N enable_log_pid=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_log_pid != yno; then HAS_LOG_PID_TRUE= HAS_LOG_PID_FALSE='#' else HAS_LOG_PID_TRUE='#' HAS_LOG_PID_FALSE= fi # SUBST # AC_HAS_DISABLE log_pid DONE # # AC_HAS_ENABLE full_ascii7 # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if FULL_ASCII7 has been enabled" >&5 $as_echo_n "checking if FULL_ASCII7 has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-full_ascii7 was given. if test "${enable_full_ascii7+set}" = set; then : enableval=$enable_full_ascii7; fi # CASE case "y$enable_full_ascii7" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_FULL_ASCII7 1 _ACEOF # CONDITIONAL Y enable_full_ascii7="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_FULL_ASCII7 0 _ACEOF # CONDITIONAL N enable_full_ascii7="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_full_ascii7 = yyes; then HAS_FULL_ASCII7_TRUE= HAS_FULL_ASCII7_FALSE='#' else HAS_FULL_ASCII7_TRUE='#' HAS_FULL_ASCII7_FALSE= fi # SUBST # AC_HAS_ENABLE full_ascii7 DONE # # AC_HAS_DISABLE ecdsa # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ECDSA_SUPPORT has been disabled" >&5 $as_echo_n "checking if ECDSA_SUPPORT has been disabled... " >&6; } # ARG ENABLE # Check whether --enable-ecdsa was given. if test "${enable_ecdsa+set}" = set; then : enableval=$enable_ecdsa; fi # MSG RESULT # CASE case "y$enable_ecdsa" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_ECDSA_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_ecdsa=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_ECDSA_SUPPORT 0 _ACEOF # CONDITIONAL N enable_ecdsa=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_ecdsa != yno; then HAS_ECDSA_SUPPORT_TRUE= HAS_ECDSA_SUPPORT_FALSE='#' else HAS_ECDSA_SUPPORT_TRUE='#' HAS_ECDSA_SUPPORT_FALSE= fi # SUBST # AC_HAS_DISABLE ecdsa DONE { $as_echo "$as_me:${as_lineno-$LINENO}: checking if EDDSA has been disabled" >&5 $as_echo_n "checking if EDDSA has been disabled... " >&6; } # Check whether --enable-EDDSA was given. if test "${enable_EDDSA+set}" = set; then : enableval=$enable_EDDSA; Disable EDDSA fi case "y$enable_eddsa" in yyes|y) if test "x$ac_cv_func_EVP_PKEY_new_raw_public_key" == xyes; then cat >>confdefs.h <<_ACEOF #define HAS_EDDSA_SUPPORT 1 _ACEOF enable_eddsa=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else cat >>confdefs.h <<_ACEOF #define HAS_EDDSA_SUPPORT 0 _ACEOF enable_eddsa=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi ;; yno|*) cat >>confdefs.h <<_ACEOF #define HAS_EDDSA_SUPPORT 0 _ACEOF enable_eddsa=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ;; esac if test y$enable_eddsa != yno; then HAS_EDDSA_TRUE= HAS_EDDSA_FALSE='#' else HAS_EDDSA_TRUE='#' HAS_EDDSA_FALSE= fi # # AC_HAS_ENABLE systemd_resolved_avoidance # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if SYSTEMD_RESOLVED_AVOIDANCE has been enabled" >&5 $as_echo_n "checking if SYSTEMD_RESOLVED_AVOIDANCE has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-systemd_resolved_avoidance was given. if test "${enable_systemd_resolved_avoidance+set}" = set; then : enableval=$enable_systemd_resolved_avoidance; fi # CASE case "y$enable_systemd_resolved_avoidance" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_SYSTEMD_RESOLVED_AVOIDANCE 1 _ACEOF # CONDITIONAL Y enable_systemd_resolved_avoidance="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_SYSTEMD_RESOLVED_AVOIDANCE 0 _ACEOF # CONDITIONAL N enable_systemd_resolved_avoidance="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_systemd_resolved_avoidance = yyes; then HAS_SYSTEMD_RESOLVED_AVOIDANCE_TRUE= HAS_SYSTEMD_RESOLVED_AVOIDANCE_FALSE='#' else HAS_SYSTEMD_RESOLVED_AVOIDANCE_TRUE='#' HAS_SYSTEMD_RESOLVED_AVOIDANCE_FALSE= fi # SUBST # AC_HAS_ENABLE systemd_resolved_avoidance DONE # # AC_HAS_ENABLE non_aa_axfr_support # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if NON_AA_AXFR_SUPPORT has been enabled" >&5 $as_echo_n "checking if NON_AA_AXFR_SUPPORT has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-non_aa_axfr_support was given. if test "${enable_non_aa_axfr_support+set}" = set; then : enableval=$enable_non_aa_axfr_support; fi # CASE case "y$enable_non_aa_axfr_support" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_NON_AA_AXFR_SUPPORT 1 _ACEOF # CONDITIONAL Y enable_non_aa_axfr_support="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_NON_AA_AXFR_SUPPORT 0 _ACEOF # CONDITIONAL N enable_non_aa_axfr_support="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_non_aa_axfr_support = yyes; then HAS_NON_AA_AXFR_SUPPORT_TRUE= HAS_NON_AA_AXFR_SUPPORT_FALSE='#' else HAS_NON_AA_AXFR_SUPPORT_TRUE='#' HAS_NON_AA_AXFR_SUPPORT_FALSE= fi # SUBST # AC_HAS_ENABLE non_aa_axfr_support DONE { $as_echo "$as_me:${as_lineno-$LINENO}: checking if has strdup" >&5 $as_echo_n "checking if has strdup... " >&6; } if false; then HAS_STRDUP_TRUE= HAS_STRDUP_FALSE='#' else HAS_STRDUP_TRUE='#' HAS_STRDUP_FALSE= fi cat > strdup_test.c <<_ACEOF #include #include int main(int argc, char** argv) { char* p = strdup("test"); return 0; } _ACEOF ${CC} ${CFLAGS} strdup_test.c -o strdup_test if [ $? -eq 0 ]; then has_strdup=1; echo "yes" else echo "no" fi rm -f strdup_test strdup_test.c if test $has_strdup = yes; then HAS_STRDUP_TRUE= HAS_STRDUP_FALSE='#' else HAS_STRDUP_TRUE='#' HAS_STRDUP_FALSE= fi # # AC_HAS_ENABLE event_dynamic_module # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if EVENT_DYNAMIC_MODULE has been enabled" >&5 $as_echo_n "checking if EVENT_DYNAMIC_MODULE has been enabled... " >&6; } # ARG ENABLE # Check whether --enable-event_dynamic_module was given. if test "${enable_event_dynamic_module+set}" = set; then : enableval=$enable_event_dynamic_module; fi # CASE case "y$enable_event_dynamic_module" in yyes) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_EVENT_DYNAMIC_MODULE 1 _ACEOF # CONDITIONAL Y enable_event_dynamic_module="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|y|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_EVENT_DYNAMIC_MODULE 0 _ACEOF # CONDITIONAL N enable_event_dynamic_module="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac # CONDITIONAL if test y$enable_event_dynamic_module = yyes; then HAS_EVENT_DYNAMIC_MODULE_TRUE= HAS_EVENT_DYNAMIC_MODULE_FALSE='#' else HAS_EVENT_DYNAMIC_MODULE_TRUE='#' HAS_EVENT_DYNAMIC_MODULE_FALSE= fi # SUBST # AC_HAS_ENABLE event_dynamic_module DONE # # AC_HAS_WITH logdir # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if logdir has been given" >&5 $as_echo_n "checking if logdir has been given... " >&6; } # ARG WITH # Check whether --with-logdir was given. if test "${with_logdir+set}" = set; then : withval=$with_logdir; # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_LOGDIR 1 _ACEOF # CONDITIONAL Y cat >>confdefs.h <<_ACEOF #define HAS_WITH_LOGDIR "$with_logdir" // $withval _ACEOF with_logdir="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES logdir="$withval" with_logdir="$logdir" # ENDIF else # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_LOGDIR 0 _ACEOF # CONDITIONAL N with_logdir="no" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO logdir=${localstatedir}/log/yadifa with_logdir="$logdir" # ENDIF fi # CONDITIONAL if test "y$with_logdir" == "yyes"; then HAS_LOGDIR_TRUE= HAS_LOGDIR_FALSE='#' else HAS_LOGDIR_TRUE='#' HAS_LOGDIR_FALSE= fi # SUBST # AC_HAS_WITH logdir DONE echo "LOGDIR=$logdir" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr has a sa_len field" >&5 $as_echo_n "checking if sockaddr has a sa_len field... " >&6; } cat > sockaddr_sa_len.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETINET6_IN6_H #include #endif int main(int argc, char** argv) { struct sockaddr sa; sa.sa_len = 4; } _ACEOF has_sockaddr_sa_len=0 ${CC} ${CFLAGS} sockaddr_sa_len.c > /dev/null 2>&1 if [ $? -eq 0 ]; then has_sockaddr_sa_len=1; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f sockaddr_sa_len.c sockaddr_sa_len if test $has_sockaddr_sa_len = yes; then HAS_SOCKADDR_SA_LEN_TRUE= HAS_SOCKADDR_SA_LEN_FALSE='#' else HAS_SOCKADDR_SA_LEN_TRUE='#' HAS_SOCKADDR_SA_LEN_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_SOCKADDR_SA_LEN $has_sockaddr_sa_len _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr_in has a sin_len field" >&5 $as_echo_n "checking if sockaddr_in has a sin_len field... " >&6; } cat > sockaddr_in_sin_len.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETINET6_IN6_H #include #endif int main(int argc, char** argv) { struct sockaddr_in sa; sa.sin_len = sizeof(struct sockaddr_in); } _ACEOF has_sockaddr_in_sin_len=0 ${CC} ${CFLAGS} sockaddr_in_sin_len.c > /dev/null 2>&1 if [ $? -eq 0 ]; then has_sockaddr_in_sin_len=1; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f sockaddr_in_sin_len.c sockaddr_in_sin_len if test $has_sockaddr_in_sin_len = yes; then HAS_SOCKADDR_IN_SIN_LEN_TRUE= HAS_SOCKADDR_IN_SIN_LEN_FALSE='#' else HAS_SOCKADDR_IN_SIN_LEN_TRUE='#' HAS_SOCKADDR_IN_SIN_LEN_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_SOCKADDR_IN_SIN_LEN $has_sockaddr_in_sin_len _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr_in6 has a sin6_len field" >&5 $as_echo_n "checking if sockaddr_in6 has a sin6_len field... " >&6; } cat > sockaddr_in6_sin6_len.c <<_ACEOF #include "confdefs.h" #if HAVE_STDLIB_H #include #endif #if HAVE_SYS_TYPES_H #include #endif #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETINET6_IN6_H #include #endif int main(int argc, char** argv) { struct sockaddr_in6 sa; sa.sin6_len = sizeof(struct sockaddr_in6); } _ACEOF has_sockaddr_in6_sin6_len=0 ${CC} ${CFLAGS} sockaddr_in6_sin6_len.c > /dev/null 2>&1 if [ $? -eq 0 ]; then has_sockaddr_in6_sin6_len=1; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f sockaddr_in6_sin6_len.c sockaddr_in6_sin6_len if test $has_sockaddr_in6_sin6_len = yes; then HAS_SOCKADDR_IN6_SIN6_LEN_TRUE= HAS_SOCKADDR_IN6_SIN6_LEN_FALSE='#' else HAS_SOCKADDR_IN6_SIN6_LEN_TRUE='#' HAS_SOCKADDR_IN6_SIN6_LEN_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAS_SOCKADDR_IN6_SIN6_LEN $has_sockaddr_in6_sin6_len _ACEOF cat <&5 $as_echo_n "checking if tests has to be build... " >&6; } # ARG WITH # Check whether --with-tests was given. if test "${with_tests+set}" = set; then : withval=$with_tests; fi # MSG RESULT case "y$with_tests" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_TESTS 1 _ACEOF # CONDITIONAL Y with_tests=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES ac_config_files="$ac_config_files test/circular-file-test/Makefile test/cjf-scan/Makefile test/cmdline-test/Makefile test/collection-test/Makefile test/daemonised-logger-test/Makefile test/dnskey-test/Makefile test/dnsname-test/Makefile test/dnssec-test/Makefile test/dnsserver-test/Makefile test/dsfromkey-test/Makefile test/filepool-test/Makefile test/file-test/Makefile test/freebsd12-test/Makefile test/ipc-test/Makefile test/journal-fusion/Makefile test/journal-from-ixfr/Makefile test/journal-speed-test/Makefile test/keygen-test/Makefile test/limiter-test/Makefile test/logger-test/Makefile test/message-test/Makefile test/mutex-test/Makefile test/notify-test/Makefile test/network-interfaces-forall-test/Makefile test/nsec3-answer/Makefile test/nsec3-hash/Makefile test/openssl111a-ecdsa-test/Makefile test/openssl111a-eddsa-test/Makefile test/parser-test/Makefile test/protocol-test/Makefile test/query-hammer-test/Makefile test/rrsig-test/Makefile test/shared-circular-buffer-test/Makefile test/shared-heap-test/Makefile test/simple-http-server-test/Makefile test/skeleton/Makefile test/stream-test/Makefile test/threaded-queue/Makefile test/update-test/Makefile test/xfr/Makefile test/zone-save-test/Makefile" # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_TESTS 0 _ACEOF # CONDITIONAL N with_tests=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac if test "y$with_tests" != "yno"; then HAS_TESTS_TRUE= HAS_TESTS_FALSE='#' else HAS_TESTS_TRUE='#' HAS_TESTS_FALSE= fi # Used to check the test was correct (it is) #AM_CONDITIONAL([TEST_HAS_TESTS], [echo test "y$with_[tests]" != "yno" > /tmp/test_has_TESTS.txt]) # SUBST # AC_HAS_WITHOUT tests DONE ac_config_files="$ac_config_files bin/yadifa/Makefile" ac_config_files="$ac_config_files sbin/yakeyrolld/Makefile" # # AC_HAS_WITHOUT tools # # CHECKING { $as_echo "$as_me:${as_lineno-$LINENO}: checking if tools has to be build" >&5 $as_echo_n "checking if tools has to be build... " >&6; } # ARG WITH # Check whether --with-tools was given. if test "${with_tools+set}" = set; then : withval=$with_tools; fi # MSG RESULT case "y$with_tools" in yyes|y) # DEFINE Y cat >>confdefs.h <<_ACEOF #define HAS_TOOLS 1 _ACEOF # CONDITIONAL Y with_tools=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # IF YES # ENDIF ;; yno|*) # DEFINE N cat >>confdefs.h <<_ACEOF #define HAS_TOOLS 0 _ACEOF # CONDITIONAL N with_tools=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # IF NO # ENDIF ;; esac if test "y$with_tools" != "yno"; then HAS_TOOLS_TRUE= HAS_TOOLS_FALSE='#' else HAS_TOOLS_TRUE='#' HAS_TOOLS_FALSE= fi # Used to check the test was correct (it is) #AM_CONDITIONAL([TEST_HAS_TOOLS], [echo test "y$with_[tools]" != "yno" > /tmp/test_has_TOOLS.txt]) # SUBST # AC_HAS_WITHOUT tools DONE cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${HAS_BUILD_TIMESTAMP_TRUE}" && test -z "${HAS_BUILD_TIMESTAMP_FALSE}"; then as_fn_error $? "conditional \"HAS_BUILD_TIMESTAMP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CLOSE_EX_REF_TRUE}" && test -z "${HAS_CLOSE_EX_REF_FALSE}"; then as_fn_error $? "conditional \"HAS_CLOSE_EX_REF\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_YADIFA_TRUE}" && test -z "${HAS_YADIFA_FALSE}"; then as_fn_error $? "conditional \"HAS_YADIFA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_DNSSEC_TOOLS_TRUE}" && test -z "${HAS_DNSSEC_TOOLS_FALSE}"; then as_fn_error $? "conditional \"HAS_DNSSEC_TOOLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${IS_DARWIN_OS_TRUE}" && test -z "${IS_DARWIN_OS_FALSE}"; then as_fn_error $? "conditional \"IS_DARWIN_OS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${IS_DARWIN_GE14_TRUE}" && test -z "${IS_DARWIN_GE14_FALSE}"; then as_fn_error $? "conditional \"IS_DARWIN_GE14\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${IS_BSD_FAMILY_TRUE}" && test -z "${IS_BSD_FAMILY_FALSE}"; then as_fn_error $? "conditional \"IS_BSD_FAMILY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${IS_LINUX_FAMILY_TRUE}" && test -z "${IS_LINUX_FAMILY_FALSE}"; then as_fn_error $? "conditional \"IS_LINUX_FAMILY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${IS_SOLARIS_FAMILY_TRUE}" && test -z "${IS_SOLARIS_FAMILY_FALSE}"; then as_fn_error $? "conditional \"IS_SOLARIS_FAMILY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CPU_AMDINTEL_TRUE}" && test -z "${HAS_CPU_AMDINTEL_FALSE}"; then as_fn_error $? "conditional \"HAS_CPU_AMDINTEL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CPU_NIAGARA_TRUE}" && test -z "${HAS_CPU_NIAGARA_FALSE}"; then as_fn_error $? "conditional \"HAS_CPU_NIAGARA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CPU_AMDINTEL_TRUE}" && test -z "${HAS_CPU_AMDINTEL_FALSE}"; then as_fn_error $? "conditional \"HAS_CPU_AMDINTEL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${FORCE32BITS_TRUE}" && test -z "${FORCE32BITS_FALSE}"; then as_fn_error $? "conditional \"FORCE32BITS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${FORCE64BITS_TRUE}" && test -z "${FORCE64BITS_FALSE}"; then as_fn_error $? "conditional \"FORCE64BITS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USES_ICC_TRUE}" && test -z "${USES_ICC_FALSE}"; then as_fn_error $? "conditional \"USES_ICC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USES_GCC_TRUE}" && test -z "${USES_GCC_FALSE}"; then as_fn_error $? "conditional \"USES_GCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USES_CLANG_TRUE}" && test -z "${USES_CLANG_FALSE}"; then as_fn_error $? "conditional \"USES_CLANG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USES_SUNC_TRUE}" && test -z "${USES_SUNC_FALSE}"; then as_fn_error $? "conditional \"USES_SUNC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USES_UNKNOWN_TRUE}" && test -z "${USES_UNKNOWN_FALSE}"; then as_fn_error $? "conditional \"USES_UNKNOWN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_TUNE_NATIVE_TRUE}" && test -z "${HAS_CC_TUNE_NATIVE_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_TUNE_NATIVE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_TUNE_NATIVE_TRUE}" && test -z "${HAS_CC_TUNE_NATIVE_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_TUNE_NATIVE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_TUNE_NATIVE_TRUE}" && test -z "${HAS_CC_TUNE_NATIVE_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_TUNE_NATIVE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_NO_IDENT_TRUE}" && test -z "${HAS_CC_NO_IDENT_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_NO_IDENT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_NO_IDENT_TRUE}" && test -z "${HAS_CC_NO_IDENT_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_NO_IDENT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_NO_IDENT_TRUE}" && test -z "${HAS_CC_NO_IDENT_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_NO_IDENT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_ANSI_TRUE}" && test -z "${HAS_CC_ANSI_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_ANSI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_ANSI_TRUE}" && test -z "${HAS_CC_ANSI_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_ANSI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_ANSI_TRUE}" && test -z "${HAS_CC_ANSI_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_ANSI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_ANSI_ALIAS_TRUE}" && test -z "${HAS_CC_ANSI_ALIAS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_ANSI_ALIAS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_ANSI_ALIAS_TRUE}" && test -z "${HAS_CC_ANSI_ALIAS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_ANSI_ALIAS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_ANSI_ALIAS_TRUE}" && test -z "${HAS_CC_ANSI_ALIAS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_ANSI_ALIAS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_PEDANTIC_TRUE}" && test -z "${HAS_CC_PEDANTIC_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_PEDANTIC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_PEDANTIC_TRUE}" && test -z "${HAS_CC_PEDANTIC_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_PEDANTIC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_PEDANTIC_TRUE}" && test -z "${HAS_CC_PEDANTIC_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_PEDANTIC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_GNU11_TRUE}" && test -z "${HAS_CC_STD_GNU11_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_GNU11\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_GNU11_TRUE}" && test -z "${HAS_CC_STD_GNU11_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_GNU11\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_GNU11_TRUE}" && test -z "${HAS_CC_STD_GNU11_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_GNU11\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_C11_TRUE}" && test -z "${HAS_CC_STD_C11_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_C11\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_C11_TRUE}" && test -z "${HAS_CC_STD_C11_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_C11\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_C11_TRUE}" && test -z "${HAS_CC_STD_C11_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_C11\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_GNU99_TRUE}" && test -z "${HAS_CC_STD_GNU99_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_GNU99\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_GNU99_TRUE}" && test -z "${HAS_CC_STD_GNU99_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_GNU99\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_GNU99_TRUE}" && test -z "${HAS_CC_STD_GNU99_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_GNU99\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_C99_TRUE}" && test -z "${HAS_CC_STD_C99_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_C99\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_C99_TRUE}" && test -z "${HAS_CC_STD_C99_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_C99\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STD_C99_TRUE}" && test -z "${HAS_CC_STD_C99_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STD_C99\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_XC99_TRUE}" && test -z "${HAS_CC_XC99_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_XC99\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_XC99_TRUE}" && test -z "${HAS_CC_XC99_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_XC99\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_XC99_TRUE}" && test -z "${HAS_CC_XC99_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_XC99\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_M32_TRUE}" && test -z "${HAS_CC_M32_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_M32\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_M32_TRUE}" && test -z "${HAS_CC_M32_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_M32\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_M32_TRUE}" && test -z "${HAS_CC_M32_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_M32\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_M64_TRUE}" && test -z "${HAS_CC_M64_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_M64\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_M64_TRUE}" && test -z "${HAS_CC_M64_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_M64\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_M64_TRUE}" && test -z "${HAS_CC_M64_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_M64\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_WALL_TRUE}" && test -z "${HAS_CC_WALL_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_WALL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_WALL_TRUE}" && test -z "${HAS_CC_WALL_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_WALL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_WALL_TRUE}" && test -z "${HAS_CC_WALL_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_WALL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_G_TRUE}" && test -z "${HAS_CC_G_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_G\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_G_TRUE}" && test -z "${HAS_CC_G_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_G\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_G_TRUE}" && test -z "${HAS_CC_G_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_G\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_G3_TRUE}" && test -z "${HAS_CC_G3_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_G3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_G3_TRUE}" && test -z "${HAS_CC_G3_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_G3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_G3_TRUE}" && test -z "${HAS_CC_G3_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_G3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_DWARF2_TRUE}" && test -z "${HAS_CC_DWARF2_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_DWARF2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_DWARF2_TRUE}" && test -z "${HAS_CC_DWARF2_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_DWARF2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_DWARF2_TRUE}" && test -z "${HAS_CC_DWARF2_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_DWARF2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_DWARF3_TRUE}" && test -z "${HAS_CC_DWARF3_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_DWARF3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_DWARF3_TRUE}" && test -z "${HAS_CC_DWARF3_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_DWARF3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_DWARF3_TRUE}" && test -z "${HAS_CC_DWARF3_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_DWARF3\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_DWARF4_TRUE}" && test -z "${HAS_CC_DWARF4_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_DWARF4\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_DWARF4_TRUE}" && test -z "${HAS_CC_DWARF4_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_DWARF4\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_DWARF4_TRUE}" && test -z "${HAS_CC_DWARF4_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_DWARF4\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STACK_PROTECTOR_TRUE}" && test -z "${HAS_CC_STACK_PROTECTOR_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STACK_PROTECTOR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STACK_PROTECTOR_TRUE}" && test -z "${HAS_CC_STACK_PROTECTOR_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STACK_PROTECTOR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_STACK_PROTECTOR_TRUE}" && test -z "${HAS_CC_STACK_PROTECTOR_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_STACK_PROTECTOR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_EXCEPTIONS_TRUE}" && test -z "${HAS_CC_EXCEPTIONS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_EXCEPTIONS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_EXCEPTIONS_TRUE}" && test -z "${HAS_CC_EXCEPTIONS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_EXCEPTIONS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_EXCEPTIONS_TRUE}" && test -z "${HAS_CC_EXCEPTIONS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_EXCEPTIONS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE}" && test -z "${HAS_CC_MISSING_FIELD_INITIALIZERS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_MISSING_FIELD_INITIALIZERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE}" && test -z "${HAS_CC_MISSING_FIELD_INITIALIZERS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_MISSING_FIELD_INITIALIZERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE}" && test -z "${HAS_CC_MISSING_FIELD_INITIALIZERS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_MISSING_FIELD_INITIALIZERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_SANITIZE_ADDRESS_TRUE}" && test -z "${HAS_CC_SANITIZE_ADDRESS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_SANITIZE_ADDRESS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_SANITIZE_ADDRESS_TRUE}" && test -z "${HAS_CC_SANITIZE_ADDRESS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_SANITIZE_ADDRESS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_SANITIZE_ADDRESS_TRUE}" && test -z "${HAS_CC_SANITIZE_ADDRESS_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_SANITIZE_ADDRESS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_NO_OMIT_FRAME_POINTER_TRUE}" && test -z "${HAS_CC_NO_OMIT_FRAME_POINTER_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_NO_OMIT_FRAME_POINTER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_NO_OMIT_FRAME_POINTER_TRUE}" && test -z "${HAS_CC_NO_OMIT_FRAME_POINTER_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_NO_OMIT_FRAME_POINTER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_NO_OMIT_FRAME_POINTER_TRUE}" && test -z "${HAS_CC_NO_OMIT_FRAME_POINTER_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_NO_OMIT_FRAME_POINTER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_ADDRESS_SANITIZER_CHECK_TRUE}" && test -z "${HAS_CC_ADDRESS_SANITIZER_CHECK_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_ADDRESS_SANITIZER_CHECK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_ADDRESS_SANITIZER_CHECK_TRUE}" && test -z "${HAS_CC_ADDRESS_SANITIZER_CHECK_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_ADDRESS_SANITIZER_CHECK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_ADDRESS_SANITIZER_CHECK_TRUE}" && test -z "${HAS_CC_ADDRESS_SANITIZER_CHECK_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_ADDRESS_SANITIZER_CHECK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_CATCH_UNDEFINED_BEHAVIOR_TRUE}" && test -z "${HAS_CC_CATCH_UNDEFINED_BEHAVIOR_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_CATCH_UNDEFINED_BEHAVIOR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_CATCH_UNDEFINED_BEHAVIOR_TRUE}" && test -z "${HAS_CC_CATCH_UNDEFINED_BEHAVIOR_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_CATCH_UNDEFINED_BEHAVIOR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_CATCH_UNDEFINED_BEHAVIOR_TRUE}" && test -z "${HAS_CC_CATCH_UNDEFINED_BEHAVIOR_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_CATCH_UNDEFINED_BEHAVIOR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_RDYNAMIC_TRUE}" && test -z "${HAS_CC_RDYNAMIC_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_RDYNAMIC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_RDYNAMIC_TRUE}" && test -z "${HAS_CC_RDYNAMIC_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_RDYNAMIC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CC_RDYNAMIC_TRUE}" && test -z "${HAS_CC_RDYNAMIC_FALSE}"; then as_fn_error $? "conditional \"HAS_CC_RDYNAMIC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_MEMALIGN_ISSUES_TRUE}" && test -z "${HAS_MEMALIGN_ISSUES_FALSE}"; then as_fn_error $? "conditional \"HAS_MEMALIGN_ISSUES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_SYNC_BUILTINS_TRUE}" && test -z "${HAS_SYNC_BUILTINS_FALSE}"; then as_fn_error $? "conditional \"HAS_SYNC_BUILTINS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LITTLE_ENDIAN_TRUE}" && test -z "${HAS_LITTLE_ENDIAN_FALSE}"; then as_fn_error $? "conditional \"HAS_LITTLE_ENDIAN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_BIG_ENDIAN_TRUE}" && test -z "${HAS_BIG_ENDIAN_FALSE}"; then as_fn_error $? "conditional \"HAS_BIG_ENDIAN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_SENDMMSG_TRUE}" && test -z "${HAVE_SENDMMSG_FALSE}"; then as_fn_error $? "conditional \"HAVE_SENDMMSG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_RECVMMSG_TRUE}" && test -z "${HAVE_RECVMMSG_FALSE}"; then as_fn_error $? "conditional \"HAVE_RECVMMSG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_RRL_SUPPORT_TRUE}" && test -z "${HAS_RRL_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_RRL_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_MASTER_SUPPORT_TRUE}" && test -z "${HAS_MASTER_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_MASTER_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CTRL_TRUE}" && test -z "${HAS_CTRL_FALSE}"; then as_fn_error $? "conditional \"HAS_CTRL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ZONESIGN_TRUE}" && test -z "${HAS_ZONESIGN_FALSE}"; then as_fn_error $? "conditional \"HAS_ZONESIGN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_KEYGEN_TRUE}" && test -z "${HAS_KEYGEN_FALSE}"; then as_fn_error $? "conditional \"HAS_KEYGEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_NSID_SUPPORT_TRUE}" && test -z "${HAS_NSID_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_NSID_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ACL_SUPPORT_TRUE}" && test -z "${HAS_ACL_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_ACL_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_TSIG_SUPPORT_TRUE}" && test -z "${HAS_TSIG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_TSIG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_DYNUPDATE_SUPPORT_TRUE}" && test -z "${HAS_DYNUPDATE_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_DYNUPDATE_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE}" && test -z "${HAS_RRSIG_MANAGEMENT_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_RRSIG_MANAGEMENT_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_DNSSEC_SUPPORT_TRUE}" && test -z "${HAS_DNSSEC_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_DNSSEC_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_NSEC_SUPPORT_TRUE}" && test -z "${HAS_NSEC_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_NSEC_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_NSEC3_SUPPORT_TRUE}" && test -z "${HAS_NSEC3_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_NSEC3_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ZALLOC_SUPPORT_TRUE}" && test -z "${HAS_ZALLOC_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_ZALLOC_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ZALLOC_STATISTICS_SUPPORT_TRUE}" && test -z "${HAS_ZALLOC_STATISTICS_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_ZALLOC_STATISTICS_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ZALLOC_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_ZALLOC_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_ZALLOC_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_MALLOC_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_MALLOC_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_MALLOC_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LIBC_MALLOC_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_LIBC_MALLOC_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_LIBC_MALLOC_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_BFD_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_BFD_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_BFD_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_MUTEX_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_MUTEX_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_MUTEX_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LOCK_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_LOCK_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_LOCK_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_TRACK_ZONES_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_TRACK_ZONES_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_TRACK_ZONES_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LOG_THREAD_ID_TRUE}" && test -z "${HAS_LOG_THREAD_ID_FALSE}"; then as_fn_error $? "conditional \"HAS_LOG_THREAD_ID\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LOG_THREAD_TAG_TRUE}" && test -z "${HAS_LOG_THREAD_TAG_FALSE}"; then as_fn_error $? "conditional \"HAS_LOG_THREAD_TAG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LOG_PID_TRUE}" && test -z "${HAS_LOG_PID_FALSE}"; then as_fn_error $? "conditional \"HAS_LOG_PID\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_FULL_ASCII7_TRUE}" && test -z "${HAS_FULL_ASCII7_FALSE}"; then as_fn_error $? "conditional \"HAS_FULL_ASCII7\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ECDSA_SUPPORT_TRUE}" && test -z "${HAS_ECDSA_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_ECDSA_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_EDDSA_TRUE}" && test -z "${HAS_EDDSA_FALSE}"; then as_fn_error $? "conditional \"HAS_EDDSA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_SYSTEMD_RESOLVED_AVOIDANCE_TRUE}" && test -z "${HAS_SYSTEMD_RESOLVED_AVOIDANCE_FALSE}"; then as_fn_error $? "conditional \"HAS_SYSTEMD_RESOLVED_AVOIDANCE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_NON_AA_AXFR_SUPPORT_TRUE}" && test -z "${HAS_NON_AA_AXFR_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_NON_AA_AXFR_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_STRDUP_TRUE}" && test -z "${HAS_STRDUP_FALSE}"; then as_fn_error $? "conditional \"HAS_STRDUP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_STRDUP_TRUE}" && test -z "${HAS_STRDUP_FALSE}"; then as_fn_error $? "conditional \"HAS_STRDUP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_EVENT_DYNAMIC_MODULE_TRUE}" && test -z "${HAS_EVENT_DYNAMIC_MODULE_FALSE}"; then as_fn_error $? "conditional \"HAS_EVENT_DYNAMIC_MODULE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LOGDIR_TRUE}" && test -z "${HAS_LOGDIR_FALSE}"; then as_fn_error $? "conditional \"HAS_LOGDIR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_SOCKADDR_SA_LEN_TRUE}" && test -z "${HAS_SOCKADDR_SA_LEN_FALSE}"; then as_fn_error $? "conditional \"HAS_SOCKADDR_SA_LEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_SOCKADDR_IN_SIN_LEN_TRUE}" && test -z "${HAS_SOCKADDR_IN_SIN_LEN_FALSE}"; then as_fn_error $? "conditional \"HAS_SOCKADDR_IN_SIN_LEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_SOCKADDR_IN6_SIN6_LEN_TRUE}" && test -z "${HAS_SOCKADDR_IN6_SIN6_LEN_FALSE}"; then as_fn_error $? "conditional \"HAS_SOCKADDR_IN6_SIN6_LEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LTO_SUPPORT_TRUE}" && test -z "${HAS_LTO_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_LTO_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_RRL_SUPPORT_TRUE}" && test -z "${HAS_RRL_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_RRL_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_MASTER_SUPPORT_TRUE}" && test -z "${HAS_MASTER_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_MASTER_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_CTRL_TRUE}" && test -z "${HAS_CTRL_FALSE}"; then as_fn_error $? "conditional \"HAS_CTRL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ZONESIGN_TRUE}" && test -z "${HAS_ZONESIGN_FALSE}"; then as_fn_error $? "conditional \"HAS_ZONESIGN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_KEYGEN_TRUE}" && test -z "${HAS_KEYGEN_FALSE}"; then as_fn_error $? "conditional \"HAS_KEYGEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_NSID_SUPPORT_TRUE}" && test -z "${HAS_NSID_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_NSID_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ACL_SUPPORT_TRUE}" && test -z "${HAS_ACL_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_ACL_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_TSIG_SUPPORT_TRUE}" && test -z "${HAS_TSIG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_TSIG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_DYNUPDATE_SUPPORT_TRUE}" && test -z "${HAS_DYNUPDATE_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_DYNUPDATE_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE}" && test -z "${HAS_RRSIG_MANAGEMENT_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_RRSIG_MANAGEMENT_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_DNSSEC_SUPPORT_TRUE}" && test -z "${HAS_DNSSEC_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_DNSSEC_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_NSEC_SUPPORT_TRUE}" && test -z "${HAS_NSEC_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_NSEC_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_NSEC3_SUPPORT_TRUE}" && test -z "${HAS_NSEC3_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_NSEC3_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ZALLOC_SUPPORT_TRUE}" && test -z "${HAS_ZALLOC_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_ZALLOC_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ZALLOC_STATISTICS_SUPPORT_TRUE}" && test -z "${HAS_ZALLOC_STATISTICS_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_ZALLOC_STATISTICS_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ZALLOC_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_ZALLOC_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_ZALLOC_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_MALLOC_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_MALLOC_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_MALLOC_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LIBC_MALLOC_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_LIBC_MALLOC_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_LIBC_MALLOC_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_BFD_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_BFD_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_BFD_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_MUTEX_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_MUTEX_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_MUTEX_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LOCK_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_LOCK_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_LOCK_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_TRACK_ZONES_DEBUG_SUPPORT_TRUE}" && test -z "${HAS_TRACK_ZONES_DEBUG_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_TRACK_ZONES_DEBUG_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LOG_THREAD_ID_TRUE}" && test -z "${HAS_LOG_THREAD_ID_FALSE}"; then as_fn_error $? "conditional \"HAS_LOG_THREAD_ID\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LOG_THREAD_TAG_TRUE}" && test -z "${HAS_LOG_THREAD_TAG_FALSE}"; then as_fn_error $? "conditional \"HAS_LOG_THREAD_TAG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LOG_PID_TRUE}" && test -z "${HAS_LOG_PID_FALSE}"; then as_fn_error $? "conditional \"HAS_LOG_PID\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_FULL_ASCII7_TRUE}" && test -z "${HAS_FULL_ASCII7_FALSE}"; then as_fn_error $? "conditional \"HAS_FULL_ASCII7\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_ECDSA_SUPPORT_TRUE}" && test -z "${HAS_ECDSA_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_ECDSA_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_EDDSA_TRUE}" && test -z "${HAS_EDDSA_FALSE}"; then as_fn_error $? "conditional \"HAS_EDDSA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_SYSTEMD_RESOLVED_AVOIDANCE_TRUE}" && test -z "${HAS_SYSTEMD_RESOLVED_AVOIDANCE_FALSE}"; then as_fn_error $? "conditional \"HAS_SYSTEMD_RESOLVED_AVOIDANCE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_NON_AA_AXFR_SUPPORT_TRUE}" && test -z "${HAS_NON_AA_AXFR_SUPPORT_FALSE}"; then as_fn_error $? "conditional \"HAS_NON_AA_AXFR_SUPPORT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_STRDUP_TRUE}" && test -z "${HAS_STRDUP_FALSE}"; then as_fn_error $? "conditional \"HAS_STRDUP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_STRDUP_TRUE}" && test -z "${HAS_STRDUP_FALSE}"; then as_fn_error $? "conditional \"HAS_STRDUP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_EVENT_DYNAMIC_MODULE_TRUE}" && test -z "${HAS_EVENT_DYNAMIC_MODULE_FALSE}"; then as_fn_error $? "conditional \"HAS_EVENT_DYNAMIC_MODULE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_LOGDIR_TRUE}" && test -z "${HAS_LOGDIR_FALSE}"; then as_fn_error $? "conditional \"HAS_LOGDIR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_SOCKADDR_SA_LEN_TRUE}" && test -z "${HAS_SOCKADDR_SA_LEN_FALSE}"; then as_fn_error $? "conditional \"HAS_SOCKADDR_SA_LEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_SOCKADDR_IN_SIN_LEN_TRUE}" && test -z "${HAS_SOCKADDR_IN_SIN_LEN_FALSE}"; then as_fn_error $? "conditional \"HAS_SOCKADDR_IN_SIN_LEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_SOCKADDR_IN6_SIN6_LEN_TRUE}" && test -z "${HAS_SOCKADDR_IN6_SIN6_LEN_FALSE}"; then as_fn_error $? "conditional \"HAS_SOCKADDR_IN6_SIN6_LEN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_TESTS_TRUE}" && test -z "${HAS_TESTS_FALSE}"; then as_fn_error $? "conditional \"HAS_TESTS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAS_TOOLS_TRUE}" && test -z "${HAS_TOOLS_FALSE}"; then as_fn_error $? "conditional \"HAS_TOOLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by yadifa $as_me 2.6.5-11201, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ yadifa config.status 2.6.5-11201 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "etc/Makefile") CONFIG_FILES="$CONFIG_FILES etc/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "var/Makefile") CONFIG_FILES="$CONFIG_FILES var/Makefile" ;; "lib/dnscore/Makefile") CONFIG_FILES="$CONFIG_FILES lib/dnscore/Makefile" ;; "lib/dnsdb/Makefile") CONFIG_FILES="$CONFIG_FILES lib/dnsdb/Makefile" ;; "lib/dnslg/Makefile") CONFIG_FILES="$CONFIG_FILES lib/dnslg/Makefile" ;; "sbin/yadifad/Makefile") CONFIG_FILES="$CONFIG_FILES sbin/yadifad/Makefile" ;; "test/circular-file-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/circular-file-test/Makefile" ;; "test/cjf-scan/Makefile") CONFIG_FILES="$CONFIG_FILES test/cjf-scan/Makefile" ;; "test/cmdline-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/cmdline-test/Makefile" ;; "test/collection-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/collection-test/Makefile" ;; "test/daemonised-logger-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/daemonised-logger-test/Makefile" ;; "test/dnskey-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/dnskey-test/Makefile" ;; "test/dnsname-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/dnsname-test/Makefile" ;; "test/dnssec-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/dnssec-test/Makefile" ;; "test/dnsserver-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/dnsserver-test/Makefile" ;; "test/dsfromkey-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/dsfromkey-test/Makefile" ;; "test/filepool-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/filepool-test/Makefile" ;; "test/file-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/file-test/Makefile" ;; "test/freebsd12-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/freebsd12-test/Makefile" ;; "test/ipc-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/ipc-test/Makefile" ;; "test/journal-fusion/Makefile") CONFIG_FILES="$CONFIG_FILES test/journal-fusion/Makefile" ;; "test/journal-from-ixfr/Makefile") CONFIG_FILES="$CONFIG_FILES test/journal-from-ixfr/Makefile" ;; "test/journal-speed-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/journal-speed-test/Makefile" ;; "test/keygen-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/keygen-test/Makefile" ;; "test/limiter-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/limiter-test/Makefile" ;; "test/logger-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/logger-test/Makefile" ;; "test/message-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/message-test/Makefile" ;; "test/mutex-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/mutex-test/Makefile" ;; "test/notify-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/notify-test/Makefile" ;; "test/network-interfaces-forall-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/network-interfaces-forall-test/Makefile" ;; "test/nsec3-answer/Makefile") CONFIG_FILES="$CONFIG_FILES test/nsec3-answer/Makefile" ;; "test/nsec3-hash/Makefile") CONFIG_FILES="$CONFIG_FILES test/nsec3-hash/Makefile" ;; "test/openssl111a-ecdsa-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/openssl111a-ecdsa-test/Makefile" ;; "test/openssl111a-eddsa-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/openssl111a-eddsa-test/Makefile" ;; "test/parser-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/parser-test/Makefile" ;; "test/protocol-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/protocol-test/Makefile" ;; "test/query-hammer-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/query-hammer-test/Makefile" ;; "test/rrsig-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/rrsig-test/Makefile" ;; "test/shared-circular-buffer-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/shared-circular-buffer-test/Makefile" ;; "test/shared-heap-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/shared-heap-test/Makefile" ;; "test/simple-http-server-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/simple-http-server-test/Makefile" ;; "test/skeleton/Makefile") CONFIG_FILES="$CONFIG_FILES test/skeleton/Makefile" ;; "test/stream-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/stream-test/Makefile" ;; "test/threaded-queue/Makefile") CONFIG_FILES="$CONFIG_FILES test/threaded-queue/Makefile" ;; "test/update-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/update-test/Makefile" ;; "test/xfr/Makefile") CONFIG_FILES="$CONFIG_FILES test/xfr/Makefile" ;; "test/zone-save-test/Makefile") CONFIG_FILES="$CONFIG_FILES test/zone-save-test/Makefile" ;; "bin/yadifa/Makefile") CONFIG_FILES="$CONFIG_FILES bin/yadifa/Makefile" ;; "sbin/yakeyrolld/Makefile") CONFIG_FILES="$CONFIG_FILES sbin/yakeyrolld/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="CXX " # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi make features echo echo echo "YADIFA BUNDLE DONE" echo "------------------" echo echo yadifa-2.6.5-11201/PaxHeaders.1636/configure.ac0000644000000000000000000000013214505005533016625 xustar000000000000000030 mtime=1695812443.917003299 30 atime=1695812444.018004745 30 ctime=1695812493.934719653 yadifa-2.6.5-11201/configure.ac0000664000374500037450000001757614505005533016607 0ustar00signersigner00000000000000dnl ############################################################################ dnl dnl Copyright (c) 2011-2023, EURid vzw. All rights reserved. dnl The YADIFA TM software product is provided under the BSD 3-clause license: dnl dnl Redistribution and use in source and binary forms, with or without dnl modification, are permitted provided that the following conditions dnl are met: dnl dnl * Redistributions of source code must retain the above copyright dnl notice, this list of conditions and the following disclaimer. dnl * Redistributions in binary form must reproduce the above copyright dnl notice, this list of conditions and the following disclaimer in dnl the documentation and/or other materials provided with the dnl distribution. dnl * Neither the name of EURid nor the names of its contributors may be dnl used to endorse or promote products derived from this software dnl without specific prior written permission. dnl dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" dnl AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE dnl IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE dnl ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE dnl LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR dnl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS dnl INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN dnl CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) dnl ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE dnl POSSIBILITY OF SUCH DAMAGE. dnl dnl ############################################################################ configure_base_path="$0/" dnl Do NOT change this block of comments dnl ==================================== dnl YADIFA VERSION 2.6.5 DATE 2023-09-06 dnl ==================================== AC_PREREQ([2.69]) AC_REVISION([$Revision: 11168 $]) define(YADIFA_VERSION, [m4_esyscmd( svn info 2> /dev/null | grep 'Last Changed Rev: ' | sed -re 's/.*: (.*)/Revision: \1 $/' -e 's/^/$/' >> revision.txt ; echo $(cat "${configure_base_path}VERSION")-$(grep -r \$Revision: revision.txt configure.ac Makefile.am sbin/* lib/*/* bin/* doc/* etc/* | sed -e 's/^.*\$Revision: *//' -e 's/\$.*//' -e 's/ *//' | sort -n | /usr/bin/tail -1 | tr -d '\n') | tr -d '\n' )]) AC_INIT([yadifa],YADIFA_VERSION,[info@yadifa.eu]) echo echo echo "YADIFA BUNDLE START" echo "-------------------" echo echo $0 m4_include([m4/eurid.m4]) m4_include([m4/yadifa.m4]) AC_CONFIG_AUX_DIR([.]) AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror tar-pax]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) AM_PROG_AR # automake version < 1.14 AM_PROG_CC_C_O LT_INIT([disable-shared]) AC_DARWIN_LIBTOOL dnl obsolete: LT_INIT AC_DEFUN([SYSCONF], [/$prefix/PACKAGE/PACKAGE.conf]) AC_CANONICAL_BUILD dnl Checks for libraries. AC_CHECK_LIB([c], [printf]) AC_SEARCH_LIBS([pthread_create],[pthread],,[exit 1]) AC_SEARCH_LIBS([clock_gettime],[rt],,[exit 1]) dnl Checks for header files. # Autoupdate added the next two lines to ensure that your configure # script's behavior did not change. They are probably safe to remove. dnl AC_CHECK_INCLUDES_DEFAULT dnl AC_PROG_EGREP # # AC_CHECK_HEADERS([arpa/inet.h fcntl.h netinet/in.h stdlib.h stdio.h string.h sys/time.h syslog.h unistd.h stdatomic.h]) # Check for Darwin or Linux AC_CHECK_HEADERS([linux/limits.h sys/syslimits.h i386/limits.h ppc/limits.h]) # Check for Darwin or Linux AC_CHECK_HEADERS([sys/types.h i386/types.h]) AC_CHECK_HEADERS([sys/socket.h]) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_BIGENDIAN AC_TYPE_MODE_T AC_TYPE_PID_T AC_TYPE_SIZE_T AC_STRUCT_TM dnl AC_PROG_RANLIB AC_CHECK_TYPES(uint8_t) AC_CHECK_TYPES(int8_t) AC_CHECK_TYPES(uint16_t) AC_CHECK_TYPES(int16_t) AC_CHECK_TYPES(uint32_t) AC_CHECK_TYPES(int32_t) AC_CHECK_TYPES(uint64_t) AC_CHECK_TYPES(int64_t) AC_CHECK_TYPES(long long) AC_CHECK_TYPES(u_char) AC_CHECK_TYPES(uint8_t) AC_CHECK_TYPES(int8_t) AC_CHECK_TYPES(uint16_t) AC_CHECK_TYPES(int16_t) AC_CHECK_TYPES(uint32_t) AC_CHECK_TYPES(int32_t) AC_CHECK_TYPES(uint64_t) AC_CHECK_TYPES(int64_t) AC_CHECK_TYPES(long long) AC_CHECK_TYPES(u_char) AC_CHECK_FUNCS([bzero memset select socket atexit clock_gettime dup2 fdatasync ftruncate getcwd gethostname getpagesize gettimeofday inet_ntoa localtime_r memchr memmove memset mkdir mkfifo munmap select socket strcasecmp strchr strdup strerror strncasecmp strrchr strtol timegm]) AC_CHECK_HEADERS([sys/ioctl.h]) AC_CHECK_HEADER_STDBOOL AC_CHECK_TYPES([ptrdiff_t]) AC_C_INLINE AC_C_RESTRICT AC_FUNC_CHOWN AC_FUNC_ERROR_AT_LINE AC_FUNC_FORK AC_FUNC_MALLOC AC_FUNC_MKTIME AC_FUNC_MMAP AC_FUNC_REALLOC AC_PROG_CXX AC_STRUCT_TIMEZONE AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T AC_TYPE_INT8_T AC_TYPE_OFF_T AC_TYPE_SSIZE_T AC_TYPE_UID_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T AC_FUNC_SELECT_ARGTYPES AC_FUNC_STAT AC_SYS_LARGEFILE AC_COMPILER_CHECK AC_PTHREAD_SPINLOCK_CHECK AC_PTHREAD_SETNAME_NP_CHECK AC_PTHREAD_SETAFFINITY_NP_CHECK AC_GETTID_CHECK AC_TIMEGM_CHECK AC_MREMAP_CHECK echo "mmsg results:" echo "have_sendmmsg='$have_sendmmsg'" echo "have_recvmmsg='$have_recvmmsg'" echo "-------" AC_CHECK_FUNC(sendmmsg, [ have_sendmmsg=true AC_DEFINE_UNQUOTED([HAVE_SENDMMSG], [1], [Has sendmmsg system call]) ], [ have_sendmmsg=false AC_DEFINE_UNQUOTED([HAVE_SENDMMSG], [0], [Has sendmmsg system call]) ]) AC_CHECK_FUNC(recvmmsg, [ have_recvmmsg=true AC_DEFINE_UNQUOTED([HAVE_RECVMMSG], [1], [Has recvmmsg system call]) ], [ have_recvmmsg=false AC_DEFINE_UNQUOTED([HAVE_RECVMMSG], [0], [Has recvmmsg system call]) ]) AM_CONDITIONAL(HAVE_SENDMMSG, [test x$have_sendmmsg = xtrue]) AM_CONDITIONAL(HAVE_RECVMMSG, [test x$have_recvmmsg = xtrue]) AC_SUBST(HAVE_SENDMMSG) AC_SUBST(HAVE_RECVMMSG) AC_YADIFA_ENABLE_SSL AC_YADIFA_ADD_SSL AC_YADIFA_FEATURES AC_YADIFA_ADD_LIBS AC_CHECK_LTO AC_YADIFA_FEATURES AC_EURID_SUMMARY AC_CONFIG_FILES([ Makefile etc/Makefile doc/Makefile var/Makefile lib/dnscore/Makefile lib/dnsdb/Makefile lib/dnslg/Makefile sbin/yadifad/Makefile ]) AC_HAS_WITHOUT(tests, TESTS, [various internal test programs],, [ AC_CONFIG_FILES([ test/circular-file-test/Makefile test/cjf-scan/Makefile test/cmdline-test/Makefile test/collection-test/Makefile test/daemonised-logger-test/Makefile test/dnskey-test/Makefile test/dnsname-test/Makefile test/dnssec-test/Makefile test/dnsserver-test/Makefile test/dsfromkey-test/Makefile test/filepool-test/Makefile test/file-test/Makefile test/freebsd12-test/Makefile test/ipc-test/Makefile test/journal-fusion/Makefile test/journal-from-ixfr/Makefile test/journal-speed-test/Makefile test/keygen-test/Makefile test/limiter-test/Makefile test/logger-test/Makefile test/message-test/Makefile test/mutex-test/Makefile test/notify-test/Makefile test/network-interfaces-forall-test/Makefile test/nsec3-answer/Makefile test/nsec3-hash/Makefile test/openssl111a-ecdsa-test/Makefile test/openssl111a-eddsa-test/Makefile test/parser-test/Makefile test/protocol-test/Makefile test/query-hammer-test/Makefile test/rrsig-test/Makefile test/shared-circular-buffer-test/Makefile test/shared-heap-test/Makefile test/simple-http-server-test/Makefile test/skeleton/Makefile test/stream-test/Makefile test/threaded-queue/Makefile test/update-test/Makefile test/xfr/Makefile test/zone-save-test/Makefile ]) ],[]) AC_CONFIG_FILES([ bin/yadifa/Makefile ]) AC_CONFIG_FILES([ sbin/yakeyrolld/Makefile ]) AC_HAS_WITHOUT(tools, TOOLS, [provided DNS-related tools],,,,) AC_OUTPUT dnl AC_YADIFA_SUMMARY make features echo echo echo "YADIFA BUNDLE DONE" echo "------------------" echo echo yadifa-2.6.5-11201/PaxHeaders.1636/aclocal.m40000644000000000000000000000013114505005542016176 xustar000000000000000030 mtime=1695812450.398096121 29 atime=1695812450.69610039 30 ctime=1695812493.936719682 yadifa-2.6.5-11201/aclocal.m40000664000374500037450000012142014505005542016141 0ustar00signersigner00000000000000# generated automatically by aclocal 1.13.4 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file 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. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file 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. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.13' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.13.4], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.13.4])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # Copyright (C) 2011-2013 Free Software Foundation, Inc. # # This file 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. # AM_PROG_AR([ACT-IF-FAIL]) # ------------------------- # Try to determine the archiver interface, and trigger the ar-lib wrapper # if it is needed. If the detection of archiver interface fails, run # ACT-IF-FAIL (default is to abort configure with a proper error message). AC_DEFUN([AM_PROG_AR], [AC_BEFORE([$0], [LT_INIT])dnl AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([ar-lib])dnl AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) : ${AR=ar} AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], [am_cv_ar_interface=ar AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a ]) ]) case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) m4_default([$1], [AC_MSG_ERROR([could not determine $AR interface])]) ;; esac AC_SUBST([AR])dnl ]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file 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. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file 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. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file 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. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file 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 macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file 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. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file 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. # AM_PROG_CC_C_O # -------------- # Like AC_PROG_CC_C_O, but changed for automake. AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi dnl Make sure AC_PROG_CC is never called again, or it will override our dnl setting of CC. m4_define([AC_PROG_CC], [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file 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. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file 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. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2013 Free Software Foundation, Inc. # # This file 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. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2013 Free Software Foundation, Inc. # # This file 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. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2013 Free Software Foundation, Inc. # # This file 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. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) yadifa-2.6.5-11201/PaxHeaders.1636/config.h.in0000644000000000000000000000013114505005544016363 xustar000000000000000030 mtime=1695812452.270122932 29 atime=1695812491.09267895 30 ctime=1695812493.938719711 yadifa-2.6.5-11201/config.h.in0000664000374500037450000005403514505005544016335 0ustar00signersigner00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* number of hardware core if the auto-detect fails */ #undef DEFAULT_ASSUMED_CPU_COUNT /* acl = ACL_SUPPORT enabled */ #undef HAS_ACL_SUPPORT /* bfd debug support disabled. */ #undef HAS_BFD_DEBUG_SUPPORT /* Disable timestamps in the build disabled. */ #undef HAS_BUILD_TIMESTAMP /* Compiler supports feature */ #undef HAS_CC_ADDRESS_SANITIZER_CHECK /* Compiler supports feature */ #undef HAS_CC_ANSI /* Compiler supports feature */ #undef HAS_CC_ANSI_ALIAS /* Compiler supports feature */ #undef HAS_CC_CATCH_UNDEFINED_BEHAVIOR /* Compiler supports feature */ #undef HAS_CC_DWARF2 /* Compiler supports feature */ #undef HAS_CC_DWARF3 /* Compiler supports feature */ #undef HAS_CC_DWARF4 /* Compiler supports feature */ #undef HAS_CC_EXCEPTIONS /* Compiler supports feature */ #undef HAS_CC_G /* Compiler supports feature */ #undef HAS_CC_G3 /* Compiler supports feature */ #undef HAS_CC_M32 /* Compiler supports feature */ #undef HAS_CC_M64 /* Compiler supports feature */ #undef HAS_CC_MISSING_FIELD_INITIALIZERS /* Compiler supports feature */ #undef HAS_CC_NO_IDENT /* Compiler supports feature */ #undef HAS_CC_NO_OMIT_FRAME_POINTER /* Compiler supports feature */ #undef HAS_CC_PEDANTIC /* Compiler supports feature */ #undef HAS_CC_RDYNAMIC /* Compiler supports feature */ #undef HAS_CC_SANITIZE_ADDRESS /* Compiler supports feature */ #undef HAS_CC_STACK_PROTECTOR /* Compiler supports feature */ #undef HAS_CC_STD_C11 /* Compiler supports feature */ #undef HAS_CC_STD_C99 /* Compiler supports feature */ #undef HAS_CC_STD_GNU11 /* Compiler supports feature */ #undef HAS_CC_STD_GNU99 /* Compiler supports feature */ #undef HAS_CC_TUNE_NATIVE /* Compiler supports feature */ #undef HAS_CC_WALL /* Compiler supports feature */ #undef HAS_CC_XC99 /* close_ex(fd) to change the value of fd to detect double-closes issues (debug) disabled. */ #undef HAS_CLOSE_EX_REF /* i386, Athlon, Opteron, Core2, i3, i5, i7, ... */ #undef HAS_CPU_AMDINTEL /* T1000 has a Niagara cpu */ #undef HAS_CPU_NIAGARA /* yadifa ctrl remote control tool disabled. */ #undef HAS_CTRL /* MUST be enabled if either NSEC3 or NSEC are enabled */ #undef HAS_DNSSEC_SUPPORT /* enable DNSSEC module for yadifa */ #undef HAS_DNSSEC_TOOLS /* dynamic update support disabled. */ #undef HAS_DYNUPDATE_SUPPORT /* Elliptic Curve (ECDSA) support (Use this if the available SSL library does not support it properly) disabled. */ #undef HAS_ECDSA_SUPPORT /* EDDSA support disabled */ #undef HAS_EDDSA_SUPPORT /* Adds support for dynamically loaded module that gets events from yadifad and is allowed to fetch some information disabled. */ #undef HAS_EVENT_DYNAMIC_MODULE /* Has EVP_PKEY_new_raw_public_key */ #undef HAS_EVP_PKEY_NEW_RAW_PUBLIC_KEY /* acceptance of ASCII7 characters in DNS names (not recommended) disabled. */ #undef HAS_FULL_ASCII7 /* yadifa keygen tool disabled. */ #undef HAS_KEYGEN /* libc_malloc_debug = LIBC_MALLOC_DEBUG_SUPPORT enabled */ #undef HAS_LIBC_MALLOC_DEBUG_SUPPORT /* zone lock debug support disabled. */ #undef HAS_LOCK_DEBUG_SUPPORT /* where to put the log files */ #undef HAS_LOGDIR /* a column with the pid in each line of log disabled. */ #undef HAS_LOG_PID /* a column with an alphanumeric id consistent in the lowest 32 bits of a thread id in each log line disabled. */ #undef HAS_LOG_THREAD_ID /* a column with a 8 letters human-readable tag identifying a thread in each log line disabled. */ #undef HAS_LOG_THREAD_TAG /* malloc debug support for yadifa objects disabled. */ #undef HAS_MALLOC_DEBUG_SUPPORT /* DNS master disabled. */ #undef HAS_MASTER_SUPPORT /* Define this to enable slow but safe unaligned memory accesses */ #undef HAS_MEMALIGN_ISSUES /* mutex debug support disabled. */ #undef HAS_MUTEX_DEBUG_SUPPORT /* defaults axfr-strict-authority to no. Lenient acceptance of AXFR answer from master that do not have AA bit by default (Microsoft DNS) disabled. */ #undef HAS_NON_AA_AXFR_SUPPORT /* NSEC3 enabled */ #undef HAS_NSEC3_SUPPORT /* NSEC enabled */ #undef HAS_NSEC_SUPPORT /* NSID support disabled. */ #undef HAS_NSID_SUPPORT /* not linked with an OpenSSL compatible API */ #undef HAS_OPENSSL /* The system supports thread affinity */ #undef HAS_PTHREAD_SETAFFINITY_NP /* The system supports thread names */ #undef HAS_PTHREAD_SETNAME_NP /* The system supports spinlocks */ #undef HAS_PTHREAD_SPINLOCK /* DNS Response Rate Limiter disabled. */ #undef HAS_RRL_SUPPORT /* RRSIG verification and generation for zones disabled. */ #undef HAS_RRSIG_MANAGEMENT_SUPPORT /* The system supports setgroups */ #undef HAS_SETGROUPS /* The sockaddr_in6 struct has an sin6_len field */ #undef HAS_SOCKADDR_IN6_SIN6_LEN /* The sockaddr_in struct has an sin_len field */ #undef HAS_SOCKADDR_IN_SIN_LEN /* The sockaddr struct has an sa_len field */ #undef HAS_SOCKADDR_SA_LEN /* An alternative to be used if stdatomics is not available */ #undef HAS_SYNC_BUILTINS /* to set do-not-listen to "127.0.0.53 port 53" by default (otherwise the list is empty by default) disabled. */ #undef HAS_SYSTEMD_RESOLVED_AVOIDANCE /* Without various internal test programs. */ #undef HAS_TESTS /* Without provided DNS-related tools. */ #undef HAS_TOOLS /* tracking of the instanciated zones for detecting potential leaks. Relatively cheap with a small (<100) amount of zones. disabled. */ #undef HAS_TRACK_ZONES_DEBUG_SUPPORT /* tsig = TSIG_SUPPORT enabled */ #undef HAS_TSIG_SUPPORT /* where to put the log files */ #undef HAS_WITH_LOGDIR /* building with controller */ #undef HAS_YADIFA /* zalloc debug support for yadifa objects disabled. */ #undef HAS_ZALLOC_DEBUG_SUPPORT /* zalloc statistics support disabled. */ #undef HAS_ZALLOC_STATISTICS_SUPPORT /* zalloc memory system disabled. */ #undef HAS_ZALLOC_SUPPORT /* Define to 1 if you have the `alarm' function. */ #undef HAVE_ALARM /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define to 1 if you have the header file. */ #undef HAVE_ASM_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_ASSERT_H /* Define to 1 if you have the `atexit' function. */ #undef HAVE_ATEXIT /* Define to 1 if you have the header file. */ #undef HAVE_BFD_H /* Define to 1 if you have the header file. */ #undef HAVE_BYTESWAP_H /* Define to 1 if you have the `bzero' function. */ #undef HAVE_BZERO /* Define to 1 if your system has a working `chown' function. */ #undef HAVE_CHOWN /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME /* Define to 1 if you have the header file. */ #undef HAVE_CPUID_H /* Define to 1 if you have the header file. */ #undef HAVE_CTYPE_H /* Define to 1 if you have the declaration of `tzname', and to 0 if you don't. */ #undef HAVE_DECL_TZNAME /* Define to 1 if you have the header file. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the `dup2' function. */ #undef HAVE_DUP2 /* Define to 1 if you have the header file. */ #undef HAVE_ENDIAN_H /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H /* Define to 1 if you have the header file. */ #undef HAVE_EXECINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `fdatasync' function. */ #undef HAVE_FDATASYNC /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the `ftruncate' function. */ #undef HAVE_FTRUNCATE /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD /* Define to 1 if you have the `gethostname' function. */ #undef HAVE_GETHOSTNAME /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE /* The system supports gettid */ #undef HAVE_GETTID /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #undef HAVE_GRP_H /* Define to 1 if you have the header file. */ #undef HAVE_I386_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_I386_TYPES_H /* Define to 1 if you have the `inet_ntoa' function. */ #undef HAVE_INET_NTOA /* Define to 1 if the system has the type `int16_t'. */ #undef HAVE_INT16_T /* Define to 1 if the system has the type `int32_t'. */ #undef HAVE_INT32_T /* Define to 1 if the system has the type `int64_t'. */ #undef HAVE_INT64_T /* Define to 1 if the system has the type `int8_t'. */ #undef HAVE_INT8_T /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `c' library (-lc). */ #undef HAVE_LIBC /* Define to 1 if you have the `dnscore' library (-ldnscore). */ #undef HAVE_LIBDNSCORE /* Define to 1 if you have the `dnsdb' library (-ldnsdb). */ #undef HAVE_LIBDNSDB /* Define to 1 if you have the `dnslg' library (-ldnslg). */ #undef HAVE_LIBDNSLG /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_LIMITS_H /* Define to 1 if you have the `localtime_r' function. */ #undef HAVE_LOCALTIME_R /* Define to 1 if the system has the type `long long'. */ #undef HAVE_LONG_LONG /* Define to 1 if you have the header file. */ #undef HAVE_MACHINE_ENDIAN_H /* Define to 1 if you have the header file. */ #undef HAVE_MACH_CLOCK_H /* Define to 1 if you have the header file. */ #undef HAVE_MACH_MACH_H /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #undef HAVE_MALLOC /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `memchr' function. */ #undef HAVE_MEMCHR /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the `mkdir' function. */ #undef HAVE_MKDIR /* Define to 1 if you have the `mkfifo' function. */ #undef HAVE_MKFIFO /* Define to 1 if you have a working `mmap' system call. */ #undef HAVE_MMAP /* Define to 1 if you have the `munmap' function. */ #undef HAVE_MUNMAP /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET6_IN6_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_TCP_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_ETHERNET_H /* Define to 1 if you have the header file. */ #undef HAVE_PCAP_PCAP_H /* Define to 1 if you have the header file. */ #undef HAVE_POLL_H /* Define to 1 if you have the header file. */ #undef HAVE_PPC_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H /* Define to 1 if the system has the type `ptrdiff_t'. */ #undef HAVE_PTRDIFF_T /* Define to 1 if you have the header file. */ #undef HAVE_PWD_H /* Define to 1 if your system has a GNU libc compatible `realloc' function, and to 0 otherwise. */ #undef HAVE_REALLOC /* Has recvmmsg system call */ #undef HAVE_RECVMMSG /* Define to 1 if you have the header file. */ #undef HAVE_SCHED_H /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Has sendmmsg system call */ #undef HAVE_SENDMMSG /* Define to 1 if you have the header file. */ #undef HAVE_SIGNAL_H /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* Define to 1 if `stat' has the bug that it succeeds when given the zero-length file name argument. */ #undef HAVE_STAT_EMPTY_STRING_BUG /* Define to 1 if you have the header file. */ #undef HAVE_STDARG_H /* Define to 1 if you have the header file. */ #undef HAVE_STDATOMIC_H /* Define to 1 if you have the header file. */ #undef HAVE_STDBOOL_H /* Define to 1 if you have the header file. */ #undef HAVE_STDDEF_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STDNORETURN_H /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP /* Define to 1 if you have the `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strncasecmp' function. */ #undef HAVE_STRNCASECMP /* Define to 1 if you have the `strrchr' function. */ #undef HAVE_STRRCHR /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if `tm_zone' is a member of `struct tm'. */ #undef HAVE_STRUCT_TM_TM_ZONE /* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_BYTEORDER_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_CPUSET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_ENDIAN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IPC_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MMAN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MSG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PRCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_RESOURCE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSLIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_WAIT_H /* Define to 1 if you have the header file. */ #undef HAVE_TCL_H /* Define to 1 if you have the `timegm' function. */ #undef HAVE_TIMEGM /* Define to 1 if you have the header file. */ #undef HAVE_TIME_H /* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use `HAVE_STRUCT_TM_TM_ZONE' instead. */ #undef HAVE_TM_ZONE /* Define to 1 if you don't have `tm_zone' but do have the external array `tzname'. */ #undef HAVE_TZNAME /* Define to 1 if you have the header file. */ #undef HAVE_UCONTEXT_H /* Define to 1 if the system has the type `uint16_t'. */ #undef HAVE_UINT16_T /* Define to 1 if the system has the type `uint32_t'. */ #undef HAVE_UINT32_T /* Define to 1 if the system has the type `uint64_t'. */ #undef HAVE_UINT64_T /* Define to 1 if the system has the type `uint8_t'. */ #undef HAVE_UINT8_T /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if the system has the type `u_char'. */ #undef HAVE_U_CHAR /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* Define to 1 if you have the header file. */ #undef HAVE_VFORK_H /* Define to 1 if `fork' works. */ #undef HAVE_WORKING_FORK /* Define to 1 if `vfork' works. */ #undef HAVE_WORKING_VFORK /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL /* BSD */ #undef IS_BSD_FAMILY /* OSX */ #undef IS_DARWIN_OS /* LINUX */ #undef IS_LINUX_FAMILY /* SOLARIS */ #undef IS_SOLARIS_FAMILY /* Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. */ #undef LSTAT_FOLLOWS_SLASHED_SYMLINK /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to the type of arg 1 for `select'. */ #undef SELECT_TYPE_ARG1 /* Define to the type of args 2, 3 and 4 for `select'. */ #undef SELECT_TYPE_ARG234 /* Define to the type of arg 5 for `select'. */ #undef SELECT_TYPE_ARG5 /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* Version number of package */ #undef VERSION /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* Define for Solaris 2.5.1 so the uint32_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ #undef _UINT32_T /* Define for Solaris 2.5.1 so the uint64_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ #undef _UINT64_T /* Define for Solaris 2.5.1 so the uint8_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ #undef _UINT8_T /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `int' if doesn't define. */ #undef gid_t /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to the type of a signed integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ #undef int16_t /* Define to the type of a signed integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ #undef int32_t /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ #undef int64_t /* Define to the type of a signed integer type of width exactly 8 bits if such a type exists and the standard includes do not define it. */ #undef int8_t /* Define to rpl_malloc if the replacement function should be used. */ #undef malloc /* Define to `int' if does not define. */ #undef mode_t /* Define to `long int' if does not define. */ #undef off_t /* Define to `int' if does not define. */ #undef pid_t /* Define to rpl_realloc if the replacement function should be used. */ #undef realloc /* Define to the equivalent of the C99 'restrict' keyword, or to nothing if this is not supported. Do not define if restrict is supported directly. */ #undef restrict /* Work around a bug in Sun C++: it does not support _Restrict or __restrict__, even though the corresponding Sun C compiler ends up with "#define restrict _Restrict" or "#define restrict __restrict__" in the previous line. Perhaps some future version of Sun C++ will work with restrict; if so, hopefully it defines __RESTRICT like Sun C does. */ #if defined __SUNPRO_CC && !defined __RESTRICT # define _Restrict # define __restrict__ #endif /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to `int' if does not define. */ #undef ssize_t /* Define to `int' if doesn't define. */ #undef uid_t /* Define to the type of an unsigned integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ #undef uint16_t /* Define to the type of an unsigned integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ #undef uint32_t /* Define to the type of an unsigned integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ #undef uint64_t /* Define to the type of an unsigned integer type of width exactly 8 bits if such a type exists and the standard includes do not define it. */ #undef uint8_t /* Define as `fork' if `vfork' does not work. */ #undef vfork yadifa-2.6.5-11201/PaxHeaders.1636/VERSION0000644000000000000000000000013214505005531015405 xustar000000000000000030 mtime=1695812441.301965847 30 atime=1695812445.776029924 30 ctime=1695812493.940719739 yadifa-2.6.5-11201/VERSION0000664000374500037450000000000614505005531015343 0ustar00signersigner000000000000002.6.5 yadifa-2.6.5-11201/PaxHeaders.1636/yadifa.supp0000644000000000000000000000013214505005533016505 xustar000000000000000030 mtime=1695812443.158992443 30 atime=1695812443.158992443 30 ctime=1695812493.942719768 yadifa-2.6.5-11201/yadifa.supp0000664000374500037450000000225514505005533016453 0ustar00signersigner00000000000000{ getpwnam_r Memcheck:Leak fun:getpwnam* } { getgrnam_r Memcheck:Leak fun:getgrnam* } { __nss_lookup_function Memcheck:Leak fun:malloc fun:__nss_lookup_function } { __nss_lookup_function too Memcheck:Leak fun:malloc fun:tsearch fun:__nss_lookup_function } { __nss_database_lookup Memcheck:Leak fun:malloc fun:nss_parse_service_list fun:__nss_database_lookup } { backtrace Memcheck:Leak fun:malloc fun:backtrace_symbols } { openssl Memcheck:Leak fun:malloc fun:CRYPTO_malloc } { bogusrace1 Helgrind:Race fun:sighandler_setxid fun:* obj:/usr/lib/libpthread-2.17.so obj:* } { create_pid_file Helgrind:Race fun:* fun:create_pid_file fun:* } { there_is_a_reason_its_called_random Helgrind:Race fun:random_init_auto fun:* obj:/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so } { ignore_libcrypto_conditional_jump_errors Memcheck:Cond ... obj:/usr/lib/libcrypto.so.1.0.0 } { ignore_libcrypto_value8_jump_errors Memcheck:Value8 ... obj:/usr/lib/libcrypto.so.1.0.0 } { ignore_pthread_create Memcheck:Leak fun:calloc fun:allocate_dtv fun:_dl_allocate_tls fun:pthread_create@GLIBC_2.2.5 } yadifa-2.6.5-11201/PaxHeaders.1636/autogen.sh0000644000000000000000000000013114505005532016333 xustar000000000000000029 mtime=1695812442.71398607 30 atime=1695812443.678999891 30 ctime=1695812493.944719797 yadifa-2.6.5-11201/autogen.sh0000775000374500037450000001007314505005532016302 0ustar00signersigner00000000000000#!/bin/sh ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ if [ "x$DEBUG" = "x" ]; then DEBUG=0 fi debug() { if [ $DEBUG -ne 0 ]; then echo $* fi } doe() { err=$? if [ $err -ne 0 ]; then echo $* exit $err fi } OS=$(uname -s) if [ ! "$OS" = "Darwin" ]; then SED=sed else SED=gsed fi debug "autogen starting with OS='$OS'" AM_VER_HI='' AM_VER_LO='' AM_VER=$(automake --version|grep ^automake|$SED -e 's/.* //' -e 's/\./ /g') if [ "x$AM_VER" = "x" ]; then echo "could not get automake version" exit 1 fi for i in $AM_VER do if [ "x$AM_VER_HI" = "x" ]; then AM_VER_HI=$i else AM_VER_LO=$i break fi done debug "automake version <$AM_VER_HI . $AM_VER_LO>" AC_VER_HI='' AC_VER_LO='' AC_VER=$(autoconf --version|grep ^autoconf|$SED -e 's/.* //' -e 's/\./ /g') if [ "x$AC_VER" = "x" ]; then echo "could not get autoconf version" exit 1 fi for i in $AC_VER do if [ "x$AC_VER_HI" = "x" ] then AC_VER_HI=$i else AC_VER_LO=$i break fi done debug "autoconf version <$AC_VER_HI . $AC_VER_LO>" #### if [ $AM_VER_HI -eq 1 ]; then if [ $AM_VER_LO -lt 14 ]; then echo 'patching configure.ac for automake < 1.14' $SED -i 's/^#.*AM_PROG_CC_C_O/AM_PROG_CC_C_O/' configure.ac fi fi if [ $AC_VER_HI -eq 2 ] then echo "patching prerequisites" $SED -i "s/^AC_PREREQ.*/AC_PREREQ([$AC_VER_HI.$AC_VER_LO])/" configure.ac if [ $AC_VER_LO -lt 60 ]; then for f in $(find . -name \*.m4) do grep AS_HELP_STRING $f > /dev/null 2>&1 if [ $? -eq 0 ]; then debug "patching $f for AC_HELP_STRING usage";fi $SED -i 's/AS_HELP_STRING/AC_HELP_STRING/' $f done else for f in $(find . -name \*.m4) do grep AC_HELP_STRING $f > /dev/null 2>&1 if [ $? -eq 0 ]; then debug "patching $f for AS_HELP_STRING usage";fi $SED -i 's/AC_HELP_STRING/AS_HELP_STRING/' $f done fi fi if [ ! "$OS" = "Darwin" ]; then debug "libtoolize" libtoolize --force doe "libtoolize failed" else debug "glibtoolize (OSX)" glibtoolize doe "glibtoolize failed" fi debug "aclocal" aclocal doe "aclocal failed" debug "autoheader" autoheader -Wall doe "autoheader failed" debug "automake" automake --add-missing -Wall doe "automake failed" debug "autoconf" autoconf -i -Wall doe "autoconf failed" debug "autogen done" yadifa-2.6.5-11201/PaxHeaders.1636/COPYING0000644000000000000000000000013214505005532015371 xustar000000000000000030 mtime=1695812442.629984866 30 atime=1695812442.629984866 30 ctime=1695812493.948719854 yadifa-2.6.5-11201/COPYING0000664000374500037450000000312414505005532015333 0ustar00signersigner00000000000000 Copyright (c) 2011-2023, EURid vzw. All rights reserved. The YADIFA TM software product is provided under the BSD 3-clause license: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of EURid nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. yadifa-2.6.5-11201/PaxHeaders.1636/ar-lib0000644000000000000000000000007412345535677015456 xustar000000000000000030 atime=1695812137.365612867 30 ctime=1695812493.950719883 yadifa-2.6.5-11201/ar-lib0000755000374500037450000001330212345535677015413 0ustar00signersigner00000000000000#! /bin/sh # Wrapper for Microsoft lib.exe me=ar-lib scriptversion=2012-03-01.08; # UTC # Copyright (C) 2010-2013 Free Software Foundation, Inc. # Written by Peter Rosin . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # func_error message func_error () { echo "$me: $1" 1>&2 exit 1 } file_conv= # func_file_conv build_file # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv in mingw) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin) file=`cygpath -m "$file" || echo "$file"` ;; wine) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_at_file at_file operation archive # Iterate over all members in AT_FILE performing OPERATION on ARCHIVE # for each of them. # When interpreting the content of the @FILE, do NOT use func_file_conv, # since the user would need to supply preconverted file names to # binutils ar, at least for MinGW. func_at_file () { operation=$2 archive=$3 at_file_contents=`cat "$1"` eval set x "$at_file_contents" shift for member do $AR -NOLOGO $operation:"$member" "$archive" || exit $? done } case $1 in '') func_error "no command. Try '$0 --help' for more information." ;; -h | --h*) cat <. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: yadifa-2.6.5-11201/PaxHeaders.1636/config.guess0000644000000000000000000000007312345535677016701 xustar000000000000000030 atime=1695812108.573200502 29 ctime=1695812493.95471994 yadifa-2.6.5-11201/config.guess0000755000374500037450000013036112345535677016644 0ustar00signersigner00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-06-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; or1k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: yadifa-2.6.5-11201/PaxHeaders.1636/config.sub0000644000000000000000000000007312345535677016344 xustar000000000000000029 atime=1695812108.55420023 30 ctime=1695812493.957719983 yadifa-2.6.5-11201/config.sub0000755000374500037450000010531512345535677016310 0ustar00signersigner00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-04-24' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 \ | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or1k-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: yadifa-2.6.5-11201/PaxHeaders.1636/install-sh0000644000000000000000000000007412345535677016366 xustar000000000000000030 atime=1695812137.374612996 30 ctime=1695812493.959720011 yadifa-2.6.5-11201/install-sh0000755000374500037450000003325512345535677016334 0ustar00signersigner00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: yadifa-2.6.5-11201/PaxHeaders.1636/missing0000644000000000000000000000007312345535677015760 xustar000000000000000030 atime=1695812107.605186638 29 ctime=1695812493.96172004 yadifa-2.6.5-11201/missing0000755000374500037450000001533112345535677015722 0ustar00signersigner00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2012-06-26.16; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'automa4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: yadifa-2.6.5-11201/PaxHeaders.1636/ltmain.sh0000644000000000000000000000007413073474206016172 xustar000000000000000030 atime=1695812136.627602297 30 ctime=1695812493.963720069 yadifa-2.6.5-11201/ltmain.sh0000644000374500037450000105152213073474206016133 0ustar00signersigner00000000000000 # libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --no-warn don't display warning messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4.2 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION=2.4.2 TIMESTAMP="" package_revision=1.3337 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_warning=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-warning|--no-warn) opt_warning=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" func_resolve_sysroot "$deplib" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 yadifa-2.6.5-11201/PaxHeaders.1636/lib0000644000000000000000000000013214505005617015033 xustar000000000000000030 mtime=1695812495.824746722 30 atime=1695812499.080793355 30 ctime=1695812495.824746722 yadifa-2.6.5-11201/lib/0000775000374500037450000000000014505005617015052 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/PaxHeaders.1636/dnscore0000644000000000000000000000013214505005616016467 xustar000000000000000030 mtime=1695812494.451727058 30 atime=1695812499.080793355 30 ctime=1695812494.451727058 yadifa-2.6.5-11201/lib/dnscore/0000775000374500037450000000000014505005616016506 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/include0000644000000000000000000000013214505005616020112 xustar000000000000000030 mtime=1695812494.111722188 30 atime=1695812499.080793355 30 ctime=1695812494.111722188 yadifa-2.6.5-11201/lib/dnscore/include/0000775000374500037450000000000014505005616020131 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnscore/include/PaxHeaders.1636/dnscore0000644000000000000000000000013214505005616021547 xustar000000000000000030 mtime=1695812494.439726886 30 atime=1695812499.080793355 30 ctime=1695812494.439726886 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/0000775000374500037450000000000014505005616021566 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/thirdparty0000644000000000000000000000013214505005616023741 xustar000000000000000030 mtime=1695812494.127722418 30 atime=1695812499.080793355 30 ctime=1695812494.127722418 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/thirdparty/0000775000374500037450000000000014505005616023760 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnscore/include/dnscore/thirdparty/PaxHeaders.1636/stdatomic.h0000644000000000000000000000013214505005531026152 xustar000000000000000030 mtime=1695812441.787972807 30 atime=1695812445.786030067 30 ctime=1695812494.128722432 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/thirdparty/stdatomic.h0000664000374500037450000003237514505005531026126 0ustar00signersigner00000000000000/* * An implementation of C11 stdatomic.h directly borrowed from FreeBSD * (original copyright follows), with minor modifications for * portability to other systems. Works for recent Clang (that * implement the feature c_atomic) and GCC 4.7+; includes * compatibility for GCC below 4.7 but I wouldn't recommend it. * * Caveats and limitations: * - Only the ``_Atomic parentheses'' notation is implemented, while * the ``_Atomic space'' one is not. * - _Atomic types must be typedef'ed, or programs using them will * not type check correctly (incompatible anonymous structure * types). * - Non-scalar _Atomic types would require runtime support for * runtime locking, which, as far as I know, is not currently * available on any system. */ /*- * Copyright (c) 2011 Ed Schouten * David Chisnall * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/include/stdatomic.h,v 1.10.2.2 2012/05/30 19:21:54 theraven Exp $ */ #ifndef _STDATOMIC_H_ #define _STDATOMIC_H_ #include #include #if !defined(__has_feature) #define __has_feature(x) 0 #endif #if !defined(__has_builtin) #define __has_builtin(x) 0 #endif #if !defined(__GNUC_PREREQ__) #if defined(__GNUC__) && defined(__GNUC_MINOR__) #define __GNUC_PREREQ__(maj, min) \ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) #else #define __GNUC_PREREQ__(maj, min) 0 #endif #endif #if !defined(__CLANG_ATOMICS) && !defined(__GNUC_ATOMICS) #if __has_feature(c_atomic) #define __CLANG_ATOMICS #elif __GNUC_PREREQ__(4, 7) #define __GNUC_ATOMICS #elif !defined(__GNUC__) #error "stdatomic.h does not support your compiler" #endif #endif #if !defined(__CLANG_ATOMICS) #define _Atomic(T) struct { volatile __typeof__(T) __val; } #endif /* * 7.17.2 Initialization. */ #if defined(__CLANG_ATOMICS) #define ATOMIC_VAR_INIT(value) (value) #define atomic_init(obj, value) __c11_atomic_init(obj, value) #else #define ATOMIC_VAR_INIT(value) { .__val = (value) } #define atomic_init(obj, value) do { \ (obj)->__val = (value); \ } while (0) #endif /* * Clang and recent GCC both provide predefined macros for the memory * orderings. If we are using a compiler that doesn't define them, use the * clang values - these will be ignored in the fallback path. */ #ifndef __ATOMIC_RELAXED #define __ATOMIC_RELAXED 0 #endif #ifndef __ATOMIC_CONSUME #define __ATOMIC_CONSUME 1 #endif #ifndef __ATOMIC_ACQUIRE #define __ATOMIC_ACQUIRE 2 #endif #ifndef __ATOMIC_RELEASE #define __ATOMIC_RELEASE 3 #endif #ifndef __ATOMIC_ACQ_REL #define __ATOMIC_ACQ_REL 4 #endif #ifndef __ATOMIC_SEQ_CST #define __ATOMIC_SEQ_CST 5 #endif /* * 7.17.3 Order and consistency. * * The memory_order_* constants that denote the barrier behaviour of the * atomic operations. */ enum memory_order { memory_order_relaxed = __ATOMIC_RELAXED, memory_order_consume = __ATOMIC_CONSUME, memory_order_acquire = __ATOMIC_ACQUIRE, memory_order_release = __ATOMIC_RELEASE, memory_order_acq_rel = __ATOMIC_ACQ_REL, memory_order_seq_cst = __ATOMIC_SEQ_CST }; typedef enum memory_order memory_order; /* * 7.17.4 Fences. */ #ifdef __CLANG_ATOMICS #define atomic_thread_fence(order) __c11_atomic_thread_fence(order) #define atomic_signal_fence(order) __c11_atomic_signal_fence(order) #elif defined(__GNUC_ATOMICS) #define atomic_thread_fence(order) __atomic_thread_fence(order) #define atomic_signal_fence(order) __atomic_signal_fence(order) #else #define atomic_thread_fence(order) __sync_synchronize() #define atomic_signal_fence(order) __asm volatile ("" : : : "memory") #endif /* * 7.17.5 Lock-free property. */ #if defined(__CLANG_ATOMICS) #define atomic_is_lock_free(obj) \ __c11_atomic_is_lock_free(sizeof(obj)) #elif defined(__GNUC_ATOMICS) #define atomic_is_lock_free(obj) \ __atomic_is_lock_free(sizeof((obj)->__val)) #else #define atomic_is_lock_free(obj) \ (sizeof((obj)->__val) <= sizeof(void *)) #endif /* * 7.17.6 Atomic integer types. */ typedef _Atomic(_Bool) atomic_bool; typedef _Atomic(char) atomic_char; typedef _Atomic(signed char) atomic_schar; typedef _Atomic(unsigned char) atomic_uchar; typedef _Atomic(short) atomic_short; typedef _Atomic(unsigned short) atomic_ushort; typedef _Atomic(int) atomic_int; typedef _Atomic(unsigned int) atomic_uint; typedef _Atomic(long) atomic_long; typedef _Atomic(unsigned long) atomic_ulong; typedef _Atomic(long long) atomic_llong; typedef _Atomic(unsigned long long) atomic_ullong; #if 0 typedef _Atomic(char16_t) atomic_char16_t; typedef _Atomic(char32_t) atomic_char32_t; #endif typedef _Atomic(wchar_t) atomic_wchar_t; typedef _Atomic(int_least8_t) atomic_int_least8_t; typedef _Atomic(uint_least8_t) atomic_uint_least8_t; typedef _Atomic(int_least16_t) atomic_int_least16_t; typedef _Atomic(uint_least16_t) atomic_uint_least16_t; typedef _Atomic(int_least32_t) atomic_int_least32_t; typedef _Atomic(uint_least32_t) atomic_uint_least32_t; typedef _Atomic(int_least64_t) atomic_int_least64_t; typedef _Atomic(uint_least64_t) atomic_uint_least64_t; typedef _Atomic(int_fast8_t) atomic_int_fast8_t; typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t; typedef _Atomic(int_fast16_t) atomic_int_fast16_t; typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t; typedef _Atomic(int_fast32_t) atomic_int_fast32_t; typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t; typedef _Atomic(int_fast64_t) atomic_int_fast64_t; typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t; typedef _Atomic(intptr_t) atomic_intptr_t; typedef _Atomic(uintptr_t) atomic_uintptr_t; typedef _Atomic(size_t) atomic_size_t; typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t; typedef _Atomic(intmax_t) atomic_intmax_t; typedef _Atomic(uintmax_t) atomic_uintmax_t; /* * 7.17.7 Operations on atomic types. */ /* * Compiler-specific operations. */ #if defined(__CLANG_ATOMICS) #define atomic_compare_exchange_strong_explicit(object, expected, \ desired, success, failure) \ __c11_atomic_compare_exchange_strong(object, expected, desired, \ success, failure) #define atomic_compare_exchange_weak_explicit(object, expected, \ desired, success, failure) \ __c11_atomic_compare_exchange_weak(object, expected, desired, \ success, failure) #define atomic_exchange_explicit(object, desired, order) \ __c11_atomic_exchange(object, desired, order) #define atomic_fetch_add_explicit(object, operand, order) \ __c11_atomic_fetch_add(object, operand, order) #define atomic_fetch_and_explicit(object, operand, order) \ __c11_atomic_fetch_and(object, operand, order) #define atomic_fetch_or_explicit(object, operand, order) \ __c11_atomic_fetch_or(object, operand, order) #define atomic_fetch_sub_explicit(object, operand, order) \ __c11_atomic_fetch_sub(object, operand, order) #define atomic_fetch_xor_explicit(object, operand, order) \ __c11_atomic_fetch_xor(object, operand, order) #define atomic_load_explicit(object, order) \ __c11_atomic_load(object, order) #define atomic_store_explicit(object, desired, order) \ __c11_atomic_store(object, desired, order) #elif defined(__GNUC_ATOMICS) #define atomic_compare_exchange_strong_explicit(object, expected, \ desired, success, failure) \ __atomic_compare_exchange_n(&(object)->__val, expected, \ desired, 0, success, failure) #define atomic_compare_exchange_weak_explicit(object, expected, \ desired, success, failure) \ __atomic_compare_exchange_n(&(object)->__val, expected, \ desired, 1, success, failure) #define atomic_exchange_explicit(object, desired, order) \ __atomic_exchange_n(&(object)->__val, desired, order) #define atomic_fetch_add_explicit(object, operand, order) \ __atomic_fetch_add(&(object)->__val, operand, order) #define atomic_fetch_and_explicit(object, operand, order) \ __atomic_fetch_and(&(object)->__val, operand, order) #define atomic_fetch_or_explicit(object, operand, order) \ __atomic_fetch_or(&(object)->__val, operand, order) #define atomic_fetch_sub_explicit(object, operand, order) \ __atomic_fetch_sub(&(object)->__val, operand, order) #define atomic_fetch_xor_explicit(object, operand, order) \ __atomic_fetch_xor(&(object)->__val, operand, order) #define atomic_load_explicit(object, order) \ __atomic_load_n(&(object)->__val, order) #define atomic_store_explicit(object, desired, order) \ __atomic_store_n(&(object)->__val, desired, order) #else #define atomic_compare_exchange_strong_explicit(object, expected, \ desired, success, failure) ({ \ __typeof__((object)->__val) __v; \ _Bool __r; \ __v = __sync_val_compare_and_swap(&(object)->__val, \ *(expected), desired); \ __r = *(expected) == __v; \ *(expected) = __v; \ __r; \ }) #define atomic_compare_exchange_weak_explicit(object, expected, \ desired, success, failure) \ atomic_compare_exchange_strong_explicit(object, expected, \ desired, success, failure) #if __has_builtin(__sync_swap) /* Clang provides a full-barrier atomic exchange - use it if available. */ #define atomic_exchange_explicit(object, desired, order) \ __sync_swap(&(object)->__val, desired) #else /* * __sync_lock_test_and_set() is only an acquire barrier in theory (although in * practice it is usually a full barrier) so we need an explicit barrier after * it. */ #define atomic_exchange_explicit(object, desired, order) ({ \ __typeof__((object)->__val) __v; \ __v = __sync_lock_test_and_set(&(object)->__val, desired); \ __sync_synchronize(); \ __v; \ }) #endif #define atomic_fetch_add_explicit(object, operand, order) \ __sync_fetch_and_add(&(object)->__val, operand) #define atomic_fetch_and_explicit(object, operand, order) \ __sync_fetch_and_and(&(object)->__val, operand) #define atomic_fetch_or_explicit(object, operand, order) \ __sync_fetch_and_or(&(object)->__val, operand) #define atomic_fetch_sub_explicit(object, operand, order) \ __sync_fetch_and_sub(&(object)->__val, operand) #define atomic_fetch_xor_explicit(object, operand, order) \ __sync_fetch_and_xor(&(object)->__val, operand) #define atomic_load_explicit(object, order) \ __sync_fetch_and_add(&(object)->__val, 0) #define atomic_store_explicit(object, desired, order) do { \ __sync_synchronize(); \ (object)->__val = (desired); \ __sync_synchronize(); \ } while (0) #endif /* * Convenience functions. */ #define atomic_compare_exchange_strong(object, expected, desired) \ atomic_compare_exchange_strong_explicit(object, expected, \ desired, memory_order_seq_cst, memory_order_seq_cst) #define atomic_compare_exchange_weak(object, expected, desired) \ atomic_compare_exchange_weak_explicit(object, expected, \ desired, memory_order_seq_cst, memory_order_seq_cst) #define atomic_exchange(object, desired) \ atomic_exchange_explicit(object, desired, memory_order_seq_cst) #define atomic_fetch_add(object, operand) \ atomic_fetch_add_explicit(object, operand, memory_order_seq_cst) #define atomic_fetch_and(object, operand) \ atomic_fetch_and_explicit(object, operand, memory_order_seq_cst) #define atomic_fetch_or(object, operand) \ atomic_fetch_or_explicit(object, operand, memory_order_seq_cst) #define atomic_fetch_sub(object, operand) \ atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst) #define atomic_fetch_xor(object, operand) \ atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst) #define atomic_load(object) \ atomic_load_explicit(object, memory_order_seq_cst) #define atomic_store(object, desired) \ atomic_store_explicit(object, desired, memory_order_seq_cst) /* * 7.17.8 Atomic flag type and operations. */ typedef atomic_bool atomic_flag; #define ATOMIC_FLAG_INIT ATOMIC_VAR_INIT(0) #define atomic_flag_clear_explicit(object, order) \ atomic_store_explicit(object, 0, order) #define atomic_flag_test_and_set_explicit(object, order) \ atomic_compare_exchange_strong_explicit(object, 0, 1, order, order) #define atomic_flag_clear(object) \ atomic_flag_clear_explicit(object, memory_order_seq_cst) #define atomic_flag_test_and_set(object) \ atomic_flag_test_and_set_explicit(object, memory_order_seq_cst) #endif /* !_STDATOMIC_H_ */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/alarm.h0000644000000000000000000000013214505005531023065 xustar000000000000000030 mtime=1695812441.998975829 30 atime=1695812445.787030082 30 ctime=1695812494.132722489 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/alarm.h0000664000374500037450000001374714505005531023043 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup alarm * @ingroup dnscore * @brief Alarm functions * * @{ */ #ifndef _ALARM_H #define _ALARM_H #include /** * Of the returned values, ALARM_REARM means to re-do the alarm on the next batch run * Any other value is mostly ignored (besides being printed in a log_debug) * * The cancel flag means that the callback should only cleanup its parameters */ typedef ya_result alarm_function_callback(void*, bool cancel); /* * Duplicates stays duplicated */ #define ALARM_DUP_NOP 0 /* * If there is a earlier duplicate it is removed, * if there is a later duplate this one is dropped. */ #define ALARM_DUP_REMOVE_EARLIER 1 /* * If there is a later duplicate it is removed, * if there is a earlier duplate this one is dropped. */ #define ALARM_DUP_REMOVE_LATEST 2 /** * You know what a mask is. It's not used yet because theer is no need (yet). */ #define ALARM_DUP_MASK 3 /* alarm handle */ typedef s32 alarm_t; #define ALARM_HANDLE_INVALID ((alarm_t)(~0)) struct alarm_event_node { struct alarm_event_node *hndl_next; struct alarm_event_node *hndl_prev; struct alarm_event_node *time_next; struct alarm_event_node *time_prev; u32 epoch; u32 key; /* typically a merge of a target ID and an operation flag * * ie: zone-alarm-id | signature-update-flag * * Id give 8 bits for the operations * assume 2 millions zones, 4 bits left ... * * key has to be unique per handle as its how duplicates are identified */ alarm_function_callback *function; /* the function can return an error code or ALARM_REARM to replace the alarm automatically */ void *args; const char *text; /* human readable for logging */ alarm_t handle; /* reserved */ u8 flags; /* how to handle DUPs */ }; typedef struct alarm_event_node alarm_event_node; void alarm_init(); void alarm_finalize(); /** * Allocates and initialises an event for the alarm. * * Function must be able to handled the cancel flag. * * key is used for collision per handle, so an event with collision handling flag has to be carefully setup with this. * * @param epoch * @param key * @param function * @param args * @param flags * @param text * @return */ alarm_event_node* alarm_event_new(u32 epoch, u32 key, alarm_function_callback *function, void *args, u8 flags, const char *text); /** * Alarm events MUST be freed with this IF AND ONLY IF THEY HAVEN'T BEEN USED IN alarm_set * * @param node a pointer to the alarm event structure. */ void alarm_event_free(alarm_event_node *node); /** * Opens an alarm handle. * * @parm owner_dnsname a dnsname to show to the owner (typically a zone name or the database) * * @return the alarm handle. */ alarm_t alarm_open(const u8 *owner_dnsname); /** * Closes an alarm handle. Releases all its events. * * @parm hndl the alarm handle */ void alarm_close(alarm_t hndl); /** * * Sets an alarm event. desc has to be properly setup (everything * * @param hndl * @param desc */ void alarm_set(alarm_t hndl, alarm_event_node *desc); /** * * Called to resolve all alarm events until a given epoch. * * DO NOT USE THIS. ITS USAGE IS RESERVED FOR THE ALARM THREAD. */ void alarm_run_tick(u32 epoch); /** * These three are harmful. Use with care. * They are only meant to be used in an independent thread (tcp, remote controller) to send the status of a zone. * * The usage is: lock, get first, process the list, unlock * * No other alarm_ function can be called between lock and unlock */ void alarm_lock(); void alarm_unlock(); alarm_event_node *alarm_get_first(alarm_t hndl); #ifdef __cplusplus } #endif #endif /* _DNSCORE_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/acl.h0000644000000000000000000000013214505005532022531 xustar000000000000000030 mtime=1695812442.000975858 30 atime=1695812445.787030082 30 ctime=1695812494.134722518 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/acl.h0000664000374500037450000002265314505005532022503 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup acl Access Control List * @ingroup yadifad * @brief * * @{ */ #ifndef _ACL_H #define _ACL_H #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define ACL_ERROR_BASE 0x80060000 #define ACL_ERROR_CODE(code_) ((s32)(ACL_ERROR_BASE+(code_))) #define ACL_TOKEN_SIZE_ERROR ACL_ERROR_CODE(1) #define ACL_UNEXPECTED_NEGATION ACL_ERROR_CODE(2) #define ACL_WRONG_V4_MASK ACL_ERROR_CODE(3) #define ACL_WRONG_V6_MASK ACL_ERROR_CODE(4) #define ACL_WRONG_MASK ACL_ERROR_CODE(5) #define ACL_DUPLICATE_ENTRY ACL_ERROR_CODE(6) #define ACL_RESERVED_KEYWORD ACL_ERROR_CODE(7) #define ACL_TOO_MANY_TOKENS ACL_ERROR_CODE(8) #define ACL_UNDEFINED_TOKEN ACL_ERROR_CODE(9) #define ACL_UPDATE_REJECTED ACL_ERROR_CODE(104) #define ACL_NOTIFY_REJECTED ACL_ERROR_CODE(105) #define ACL_NAME_PARSE_ERROR ACL_ERROR_CODE(201) #define ACL_UNKNOWN_TSIG_KEY ACL_ERROR_CODE(202) /* acl can be identified by * ipv4 (accept/reject) * ipv6 (accept/reject) * TSIG (accept only) * => 3 distinct entry points * Tests will be done first on IP (if any, and by version) then on TSIG (if any) * */ typedef struct ipv4_id ipv4_id; struct ipv4_id { addressv4 address; addressv4 mask; s8 maskbits; // needs to be signed s8 rejects; }; typedef struct ipv6_id ipv6_id; struct ipv6_id { addressv6 address; addressv6 mask; s16 maskbits; // needs to be signed s8 rejects; }; #define TSIG_SECRET_MAX_SIZE 32 typedef struct tsig_id tsig_id; struct tsig_id { u8 secret_size; u8 name_size; u8 mac_algorithm; u8 reserved; u8 *known; u8 *name; }; typedef struct ref_id ref_id; struct ref_id { const char* name; bool mark; }; /* * I've chosen these values to avoid some tests * * Basically, there are 2 tests for ACL: IP & TSIG * * First IP, then, if available in the message, TSIG * * IP will trigger a return in case of reject, but else will worth 0 or -2 * Then TSIG, if available, will worth -2,0,+2 * What we want is: * IAIAIA * RRIIAA * => RRRAAA * * With these values we can simply sum instead of doing tests * 0 +2 0 +2 0 +2 * + -4 -4 0 0 +2 +2 * = -4 -2 0 +2 +2 +4 * then remove 1 * = -3 -1 -1 +1 +1 +3 * => R R R A A A * */ #define AMIM_ACCEPT 2 #define AMIM_SKIP 0 #define AMIM_REJECT (-4) // Reject has much more weight, and in theory -2 should be enough ( 1 IPV4/6, 1 TSIG ) #define ACL_SORT_RULES 0 #define ACL_MERGE_RULES 0 #define ACL_DEFAULT_RULE AMIM_REJECT #define ACL_REJECTED(__amim_code__) ((__amim_code__) < 0) #define ACL_ACCEPTED(__amim_code__) ((__amim_code__) > 0) #define ACL_IGNORED(__amim_code__) ((__amim_code__) == 0) /** * Returns: * > 0 : Accept: matched and accepted * < 0 : Reject: matched and rejected * = 0 : Skip : not matched */ struct address_match_item; typedef int address_match_item_matcher(const struct address_match_item*, const void* ); typedef struct address_match_item address_match_item; /* Rules like the ones in the ACL named rules set */ struct address_match_item { address_match_item_matcher *match; union { ipv4_id ipv4; ipv6_id ipv6; tsig_id tsig; ref_id ref; } parameters; s32 _rc; }; typedef struct address_match_list address_match_list; #define ADDRESS_MATCH_LIST_INITIALIZER {NULL, NULL} struct address_match_list { address_match_item **items; address_match_item **limit; /* Address limit of the items ( p = items; while(p /** @brief ACL value parser * * @param[in] value * @param[in] config_command * @param[out] config * * @return an error code */ ya_result acl_config_set_item(const char *value, address_match_set *dest, anytype notused); ya_result acl_config_set_access_control_item(const char *value, access_control **acp, anytype offset); /// @note In order to use these macros, CONFIG_TYPE has to be defined // field into an access_control called ac #define CONFIG_ACL(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, ac) + offsetof(access_control,fieldname_), (config_set_field_function*)acl_config_set_item, defaultvalue_,{._intptr=0}, sizeof(address_match_set), sizeof(((access_control*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, // field into an access_control pointer called ac #define CONFIG_ACL_PTR(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, ac), (config_set_field_function*)acl_config_set_access_control_item, defaultvalue_,{._intptr=offsetof(access_control,fieldname_)}, sizeof(address_match_set), sizeof(((access_control*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_ACL_FILTER(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)acl_config_set_item, defaultvalue_,{._intptr=0}, sizeof(address_match_set), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/allocator.h0000644000000000000000000000013214505005532023752 xustar000000000000000030 mtime=1695812442.106977376 30 atime=1695812445.790030125 30 ctime=1695812494.138722575 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/allocator.h0000664000374500037450000000605514505005532023722 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @ingroup dnscore * * API for allocated memory. Meant to be used with mixed collections. * * Allows allocation on ephemeral stacks, zalloc, malloc, ... of objects * put together, without having trouble sorting them out at destruction time. * * Not used for now. * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef __ALLOCATOR_H__ #define __ALLOCATOR_H__ #include struct allocator_s; /** * allocator method signatures */ typedef void *allocate_method(struct allocator_s *allocator, u32 size); typedef void free_method(struct allocator_s *allocator, void *ptr); // for destruction /** * allocator vtbl */ struct allocator_vtbl { allocate_method *allocate_method; free_method *free_method; const char *__class__; }; typedef struct allocator_vtbl allocator_vtbl; /** * allocator common structure */ struct allocator_s { const allocator_vtbl *vtbl; }; typedef struct allocator_s allocator_s; #define aalloc(ac__,size__) (ac__)->vtbl->allocate_method(ac__,size__) #define afree(ac__,ptr__) (ac__)->vtbl->free_method((ac__),(ptr__)) #ifndef ALLOCATOR_C extern allocator_s libc_allocator; #endif #endif // __ALLOCATOR_H__ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/async.h0000644000000000000000000000013114505005532023106 xustar000000000000000030 mtime=1695812442.054976631 29 atime=1695812445.78903011 30 ctime=1695812494.140722604 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/async.h0000664000374500037450000001575014505005532023061 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #ifndef ASYNC_H #define ASYNC_H #define ASYNC_QUEUE_TYPE_RINGBUFFER 1 #define ASYNC_QUEUE_TYPE_DLL 2 #define ASYNC_QUEUE_TYPE ASYNC_QUEUE_TYPE_DLL #if ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_DLL #include #elif ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_RINGBUFFER #include #else #error "ASYNC_QUEUE_TYPE not set" #endif #include #define ASYNC_WAIT_TAG 1 #ifdef __cplusplus extern "C" { #endif /** * * Typically, the handler will be a small function that pushes the message in another processing queue, * with or without changing the id (so processors can be chained) * * The handler can also be a function that allows another function to proceed (delegation mechanism, in the .net linguo) * This would make the handling synchronous but the processing parallel * */ #define FREEBSD12_TEST 0 // used by threads to process a task then push it further in the assembly line struct async_message_s; typedef void async_done_callback(struct async_message_s *msg); struct async_wait_s { mutex_t mutex; cond_t cond_wait; volatile s32 wait_count; volatile s32 error_code; #if ASYNC_WAIT_TAG u32 tag; #endif }; typedef struct async_wait_s async_wait_s; struct async_queue_s { #if ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_DLL threaded_dll_cw queue; #elif ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_RINGBUFFER threaded_ringbuffer_cw queue; #else threaded_queue queue; #endif pace_s pace; }; typedef struct async_queue_s async_queue_s; struct async_message_s { s32 id; // the message id for the processor s32 error_code; // the error code to be set by the processor void *args; // the arguments for the processor async_done_callback *handler; // what must be called when the processor has finished working void *handler_args; // complementary arguments for the handler volatile s64 start_time; }; typedef struct async_message_s async_message_s; /** * * Initialises a synchronisation point * count is the number of releases to do before the async_wait call returns * * @param aw * @param count * @return */ void async_wait_init(async_wait_s *aw, s32 count); /** * * Destroys the synchronisation point * * @param aw * @return */ void async_wait_finalize(async_wait_s *aw); /** * * Initialises a synchronisation point * count is the number of releases to do before the async_wait call returns * * @param aw * @param count * @return */ async_wait_s *async_wait_new_instance(s32 count); void async_wait_destroy(async_wait_s *aw); async_wait_s *async_wait_create_shared(u8 id, s32 count); void async_wait_destroy_shared(async_wait_s *aw); /** * Waits until the count has be reduced to 0 (or below if something bad is going on) * * @param aw * @return */ void async_wait(async_wait_s *aw); /** * Waits until the count has be reduced to 0 (or below if something bad is going on) * OR until the amount of microseconds has elapsed. * * @param aw * @param usec * @return true if and only if the wait counter reached 0 */ bool async_wait_timeout(async_wait_s *aw, s64 usec); /** * Waits until the count has be reduced to 0 (or below if something bad is going on) * OR until the epoch in microseconds has been reached. * * @param aw * @param usec * @return true if and only if the wait counter reached 0 */ bool async_wait_timeout_absolute(async_wait_s *aw, s64 epoch_usec); /** * Returns the current value of the counter * * @param aw * @return */ s32 async_wait_get_counter(async_wait_s *aw); /** * * Decreases the count of that amount * * @param aw * @param count * @return */ void async_wait_progress(async_wait_s *aw, s32 count); void async_wait_set_first_error(async_wait_s *aw, s32 error); s32 async_wait_get_error(async_wait_s *aw); void async_queue_init(async_queue_s *q, u32 size, u64 min_us, u64 max_us, const char* name); void async_queue_finalize(async_queue_s *q); bool async_queue_empty(async_queue_s *q); u32 async_queue_size(async_queue_s *q); async_message_s *async_message_next(async_queue_s *queue); async_message_s* async_message_try_next(async_queue_s *queue); /** * * Pushes the message to the queue. * The queue is supposed to be read in another thread * * @param queue * @param msg */ void async_message_call(async_queue_s *queue, async_message_s *msg); /** * Sets the handler and handler_args fields to make the message a waiter * Restores the fields before returning * * @param msg */ int async_message_call_and_wait(async_queue_s *queue, async_message_s *msg); /** * Sets the handler and handler_args fields to ignore the result * (fire and forget) * * @param msg */ void async_message_call_and_forget(async_queue_s *queue, async_message_s *msg); /** * Sets the handler and handler_args fields to ignore the result * (fire and forget) * * @param msg */ void async_message_call_and_release(async_queue_s *queue, async_message_s *msg); void async_message_pool_init(); async_message_s *async_message_alloc(); void async_message_release(async_message_s *msg); void async_message_pool_finalize(); #ifdef __cplusplus } #endif #endif /* ASYNC_H */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/avl.c.inc0000644000000000000000000000013214505005532023317 xustar000000000000000030 mtime=1695812442.111977448 30 atime=1695812445.790030125 30 ctime=1695812494.142722632 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/avl.c.inc0000664000374500037450000015673114505005532023276 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief AVL structure and functions * * AVL structure and functions * * @{ */ /* Optimization that have an effect on some avl depths */ #include #include #include #include #include "dnscore/sys_types.h" #include "dnscore/format.h" void logger_flush(); #ifndef DUMPER_FUNCTION #define DUMPER_FUNCTION(...) formatln(__VA_ARGS__);flushout() #endif #if defined(DEBUG_DUMP) #define DUMP(...) DUMPER_FUNCTION(__VA_ARGS__) #define DUMP_NODE(...) AVL_DUMP_NODE(__VA_ARGS__) #else #define DUMP(...) #define DUMP_NODE(...) #endif /* * */ #if AVL_HAS_PARENT_POINTER #ifndef AVL_PARENT #error AVL_HAS_PARENT_POINTER enabled but parent not defined #endif #else #ifdef AVL_PARENT #error AVL_HAS_PARENT_POINTER disabled but parent defined #endif #endif #ifndef AVL_REFERENCE_IS_POINTER #define AVL_REFERENCE_IS_POINTER TRUE #endif #ifndef AVL_REFERENCE_IS_CONST #define AVL_REFERENCE_IS_CONST FALSE #endif #if AVL_REFERENCE_IS_POINTER #undef AVL_REFERENCE_MODIFIER #define AVL_REFERENCE_MODIFIER const #else #undef AVL_REFERENCE_MODIFIER #define AVL_REFERENCE_MODIFIER #endif #if AVL_REFERENCE_IS_CONST #undef AVL_REFERENCE_MODIFIER #define AVL_REFERENCE_MODIFIER #undef AVL_REFERENCE_CONST #define AVL_REFERENCE_CONST #else #undef AVL_REFERENCE_CONST #define AVL_REFERENCE_CONST const #endif #define TOOLEFT (-2) #define LEFT (-1) #define MIDDLE 0 #define RIGHT 1 #define TOORIGHT 2 #define DIR_LEFT 0 #define DIR_RIGHT 1 #define DIR_CRASH 127 static s8 DIR_TO_AVL_BALANCE_[2] = {LEFT, RIGHT}; #define DIR_TO_AVL_BALANCE(dir) DIR_TO_AVL_BALANCE_[(dir)] static s8 AVL_BALANCE_TO_DIR_[5] = {DIR_LEFT, DIR_LEFT, DIR_CRASH, DIR_RIGHT, DIR_RIGHT}; #define AVL_BALANCE_TO_DIR(bal) AVL_BALANCE_TO_DIR_[(bal)-TOOLEFT] #define NODE_AVL_BALANCED(node) (AVL_BALANCE(node)==MIDDLE) #define MUST_REAVL_BALANCE(node) ((AVL_BALANCE(node)RIGHT)) #if (defined(AVL_PARENT) && DEBUG) #define ASSERT_CHECK_CHILD_PARENT_LINK(node) \ if(node!=NULL) \ { \ AVL_NODE_TYPE *parent__ = AVL_PARENT(node); \ if(parent__ != NULL) \ { \ AVL_NODE_TYPE *l__ = AVL_LEFT_CHILD(parent__); \ AVL_NODE_TYPE *r__ = AVL_RIGHT_CHILD(parent__); \ if(!(l__==(node) || \ r__==(node)) ) \ { \ DUMP("parent->node link broken"); \ DUMP("\tparent=(%p, " AVL_REFERENCE_FORMAT_STRING")",parent__, AVL_REFERENCE_FORMAT(AVL_REFERENCE(parent__))); \ if(l__ != NULL) \ { \ DUMP("\t\tparent.lt=(%p, " AVL_REFERENCE_FORMAT_STRING")",l__, AVL_REFERENCE_FORMAT(AVL_REFERENCE(l__))); \ } \ if(r__ != NULL) \ { \ DUMP("\t\tparent.rt=(%p, " AVL_REFERENCE_FORMAT_STRING")",r__, AVL_REFERENCE_FORMAT(AVL_REFERENCE(r__))); \ } \ DUMP("\tnode=(%p, " AVL_REFERENCE_FORMAT_STRING")",node, AVL_REFERENCE_FORMAT(AVL_REFERENCE(node))); \ DUMP_NODE(parent__); \ DUMP_NODE(node); \ logger_flush(); \ flushout(); \ flusherr(); \ puts("assertion failed on a " TOSTRING(AVL_NODE_TYPE));fflush(NULL); \ abort(); \ } \ } \ } #else #define ASSERT_CHECK_CHILD_PARENT_LINK(node) #endif static AVL_NODE_TYPE* avl_node_single_rotation2(AVL_NODE_TYPE *node) { AVL_NODE_TYPE* save; assert(node != NULL); ASSERT_CHECK_CHILD_PARENT_LINK(node); if(AVL_BALANCE(node) < 0) /* balance = LEFT -> dir = RIGHT other = LEFT */ { save = AVL_LEFT_CHILD(node); assert(save != NULL); ASSERT_CHECK_CHILD_PARENT_LINK(save); #ifdef AVL_PARENT if(AVL_RIGHT_CHILD(save) != NULL) { AVL_PARENT(AVL_RIGHT_CHILD(save)) = node; } AVL_PARENT(save) = AVL_PARENT(node); AVL_PARENT(node) = save; #endif AVL_LEFT_CHILD(node) = AVL_RIGHT_CHILD(save); AVL_RIGHT_CHILD(save) = node; } else { save = AVL_RIGHT_CHILD(node); assert(save != NULL); ASSERT_CHECK_CHILD_PARENT_LINK(save); #ifdef AVL_PARENT if(AVL_LEFT_CHILD(save) != NULL) { AVL_PARENT(AVL_LEFT_CHILD(save)) = node; } AVL_PARENT(save) = AVL_PARENT(node); AVL_PARENT(node) = save; #endif AVL_RIGHT_CHILD(node) = AVL_LEFT_CHILD(save); AVL_LEFT_CHILD(save) = node; } AVL_BALANCE(node) = MIDDLE; AVL_BALANCE(save) = MIDDLE; ASSERT_CHECK_CHILD_PARENT_LINK(node); return save; } static AVL_NODE_TYPE* avl_node_double_rotation2(AVL_NODE_TYPE *node) { AVL_NODE_TYPE* save; assert(node != NULL); if(AVL_BALANCE(node) < 0) /* balance = LEFT -> dir = RIGHT other = LEFT */ { save = AVL_RIGHT_CHILD(AVL_LEFT_CHILD(node)); if(AVL_BALANCE(save) == MIDDLE) { AVL_BALANCE(AVL_LEFT_CHILD(node)) = MIDDLE; AVL_BALANCE(node) = MIDDLE; } else if(AVL_BALANCE(save) > 0) /* dir right & balance right */ { AVL_BALANCE(AVL_LEFT_CHILD(node)) = LEFT; AVL_BALANCE(node) = MIDDLE; } else /* AVL_BALANCE(save)<0 */ { AVL_BALANCE(AVL_LEFT_CHILD(node)) = MIDDLE; AVL_BALANCE(node) = RIGHT; } AVL_BALANCE(save) = MIDDLE; #ifdef AVL_PARENT if(AVL_LEFT_CHILD(node) != NULL) { AVL_PARENT(AVL_LEFT_CHILD(node)) = save; } if(AVL_LEFT_CHILD(save) != NULL) { AVL_PARENT(AVL_LEFT_CHILD(save)) = AVL_LEFT_CHILD(node); } if(AVL_RIGHT_CHILD(save) != NULL) { AVL_PARENT(AVL_RIGHT_CHILD(save)) = node; } AVL_PARENT(save) = AVL_PARENT(node); AVL_PARENT(node) = save; #endif AVL_RIGHT_CHILD(AVL_LEFT_CHILD(node)) = AVL_LEFT_CHILD(save); AVL_LEFT_CHILD(save) = AVL_LEFT_CHILD(node); AVL_LEFT_CHILD(node) = AVL_RIGHT_CHILD(save); AVL_RIGHT_CHILD(save) = node; } else /* balance = RIGHT -> dir = LEFT other = RIGHT */ { save = AVL_LEFT_CHILD(AVL_RIGHT_CHILD(node)); assert(save != NULL); if(AVL_BALANCE(save) == MIDDLE) { AVL_BALANCE(AVL_RIGHT_CHILD(node)) = MIDDLE; AVL_BALANCE(node) = MIDDLE; } else if(AVL_BALANCE(save) < 0) /* dir left & balance left */ { AVL_BALANCE(AVL_RIGHT_CHILD(node)) = RIGHT; AVL_BALANCE(node) = MIDDLE; } else /* AVL_BALANCE(save)>0 */ { AVL_BALANCE(AVL_RIGHT_CHILD(node)) = MIDDLE; AVL_BALANCE(node) = LEFT; } AVL_BALANCE(save) = MIDDLE; #ifdef AVL_PARENT if(AVL_RIGHT_CHILD(node) != NULL) { AVL_PARENT(AVL_RIGHT_CHILD(node)) = save; } if(AVL_RIGHT_CHILD(save) != NULL) { AVL_PARENT(AVL_RIGHT_CHILD(save)) = AVL_RIGHT_CHILD(node); } if(AVL_LEFT_CHILD(save) != NULL) { AVL_PARENT(AVL_LEFT_CHILD(save)) = node; } AVL_PARENT(save) = AVL_PARENT(node); AVL_PARENT(node) = save; #endif AVL_LEFT_CHILD(AVL_RIGHT_CHILD(node)) = AVL_RIGHT_CHILD(save); AVL_RIGHT_CHILD(save) = AVL_RIGHT_CHILD(node); AVL_RIGHT_CHILD(node) = AVL_LEFT_CHILD(save); AVL_LEFT_CHILD(save) = node; } ASSERT_CHECK_CHILD_PARENT_LINK(node); return save; } static AVL_NODE_TYPE* avl_create_node(AVL_REFERENCE_TYPE hash) { AVL_NODE_TYPE *node; AVL_ALLOC_NODE(node, hash); AVL_LEFT_CHILD(node) = NULL; AVL_RIGHT_CHILD(node) = NULL; AVL_INIT_NODE(node, hash); AVL_BALANCE(node) = MIDDLE; return node; } /** @brief Initializes the tree * * Initializes the tree. * Basically : *tree=NULL; * * @param[in] tree the tree to initialize * */ void AVL_PREFIXED(init)(AVL_TREE_TYPE* tree) { AVL_TREE_ROOT(tree) = NULL; } /** @brief Find a node in the tree * * Find a node in the tree matching a hash value. * * @param[in] root the tree to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node or NULL if there is no such node. */ AVL_NODE_TYPE* AVL_PREFIXED(find)(AVL_CONST_TREE_TYPE* tree, AVL_REFERENCE_CONST AVL_REFERENCE_TYPE obj_hash) { assert(tree != NULL); const AVL_NODE_TYPE *node = AVL_TREE_ROOT(tree); AVL_REFERENCE_MODIFIER AVL_REFERENCE_TYPE h; /* This is one of the parts I could try to optimize * I've checked the assembly, and it sucks ... */ /* Both the double-test while/ternary and the current one * are producing the same assembly code. */ while(node != NULL) { h = AVL_REFERENCE(node); #if !AVL_TERNARYCMP if(AVL_ISEQUAL(h, obj_hash)) { return (AVL_NODE_TYPE*)node; } node = AVL_CHILD(node, AVL_ISBIGGER(obj_hash, h)&1); #else int cmp = AVL_COMPARE(h, obj_hash); if(cmp == 0) { return (AVL_NODE_TYPE*)node; } node = AVL_CHILD(node, (cmp<0)&1); #endif } return NULL; } /** @brief Find a node in the tree or if such node does into exist, find the one after it (by key order) * * Find a node in the tree or if such node does into exist, find the one after it (by key order) * * @param[in] root the tree to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node, or if it does not exists the node after it, or NULL if there is no such node. * * L * / \ * A * * / \ * E B * / \ / \ * F G C D * / * H * / * I * / \ * J K * */ AVL_NODE_TYPE* AVL_PREFIXED(find_key_or_next)(AVL_CONST_TREE_TYPE* tree, AVL_REFERENCE_CONST AVL_REFERENCE_TYPE obj_hash) { assert(tree != NULL); AVL_NODE_TYPE *node = AVL_TREE_ROOT(tree); AVL_REFERENCE_MODIFIER AVL_REFERENCE_TYPE h; // the stack is used to find parents #if !AVL_HAS_PARENT_POINTER int stack_size = 0; AVL_NODE_TYPE *stack[48]; stack[0] = NULL; #else AVL_NODE_TYPE *prev = NULL; #endif if(node != NULL) { do { #if !AVL_HAS_PARENT_POINTER stack[stack_size++] = node; #endif h = AVL_REFERENCE(node); #if AVL_HAS_PARENT_POINTER prev = node; #endif #if !AVL_TERNARYCMP if(AVL_ISEQUAL(h, obj_hash)) { return (AVL_NODE_TYPE*)node; } node = AVL_CHILD(node, AVL_ISBIGGER(obj_hash, h)&1); #else int cmp = AVL_COMPARE(h, obj_hash); if(cmp == 0) { return (AVL_NODE_TYPE*)node; } node = AVL_CHILD(node, (cmp < 0)&1); #endif } while(node != NULL); // the node was not found, now, using the stack, find the next node from the key #if !AVL_HAS_PARENT_POINTER node = stack[--stack_size]; if(node == NULL) { return node; } #else if(prev == NULL) { return prev; } node = prev; #endif // back on the last node on the path #if !AVL_TERNARYCMP h = AVL_REFERENCE(node); if(AVL_ISBIGGER(h, obj_hash)) { return node; } #else int cmp = AVL_COMPARE(h, obj_hash); if(cmp >= 0) { return (AVL_NODE_TYPE*)node; } #endif const AVL_NODE_TYPE *right_node = AVL_CHILD(node, DIR_RIGHT); if(right_node != NULL) { // the next node is below (the left-most node from the right child) // right_node is already a valid answer for(;;) { const AVL_NODE_TYPE *left_node = AVL_CHILD(right_node, DIR_LEFT); if(left_node != NULL) { right_node = left_node; } else { return (AVL_NODE_TYPE*)right_node; } } } else { // the next node is either the first "right" parent // either nothing for(;;) { #if !AVL_HAS_PARENT_POINTER if(stack_size == 0) { return (AVL_NODE_TYPE*)NULL; } const AVL_NODE_TYPE *parent_node = stack[--stack_size]; #else const AVL_NODE_TYPE *parent_node = AVL_PARENT(node); if(parent_node == NULL) { return (AVL_NODE_TYPE*)NULL; } #endif // if the node is the left child of the parent, then return the parent if(node == AVL_CHILD(parent_node, DIR_LEFT)) { return (AVL_NODE_TYPE*)parent_node; } node = (AVL_NODE_TYPE*)parent_node; } } } else { return NULL; } } /** @brief Find a node in the tree or if such node does into exist, find the one after it (by key order) * * Find a node in the tree or if such node does into exist, find the one after it (by key order) * * @param[in] root the tree to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node, or if it does not exists the node after it, or NULL if there is no such node. */ AVL_NODE_TYPE* AVL_PREFIXED(find_key_or_prev)(AVL_CONST_TREE_TYPE* tree, AVL_REFERENCE_CONST AVL_REFERENCE_TYPE obj_hash) { assert(tree != NULL); AVL_NODE_TYPE *node = AVL_TREE_ROOT(tree); AVL_REFERENCE_MODIFIER AVL_REFERENCE_TYPE h; // the stack is used to find parents #if !AVL_HAS_PARENT_POINTER int stack_size = 0; AVL_NODE_TYPE *stack[48]; stack[0] = NULL; #else AVL_NODE_TYPE *prev = NULL; #endif if(node != NULL) { do { #if !AVL_HAS_PARENT_POINTER stack[stack_size++] = node; #endif h = AVL_REFERENCE(node); #if AVL_HAS_PARENT_POINTER prev = node; #endif #if !AVL_TERNARYCMP if(AVL_ISEQUAL(h, obj_hash)) { return (AVL_NODE_TYPE*)node; } node = AVL_CHILD(node, AVL_ISBIGGER(obj_hash, h)&1); #else int cmp = AVL_COMPARE(h, obj_hash); if(cmp == 0) { return (AVL_NODE_TYPE*)node; } node = AVL_CHILD(node, (cmp < 0)&1); #endif } while(node != NULL); // the node was not found, now, using the stack, find the next node from the key #if !AVL_HAS_PARENT_POINTER node = stack[--stack_size]; if(node == NULL) { return node; } #else if(prev == NULL) { return prev; } node = prev; #endif // back on the last node on the path #if !AVL_TERNARYCMP h = AVL_REFERENCE(node); if(AVL_ISBIGGER(obj_hash, h)) { return node; } #else int cmp = AVL_COMPARE(obj_hash, h); if(cmp >= 0) { return (AVL_NODE_TYPE*)node; } #endif const AVL_NODE_TYPE *left_node = AVL_CHILD(node, DIR_LEFT); if(left_node != NULL) { // the prev node is below (the right-most node from the left child) // left_node is already a valid answer for(;;) { const AVL_NODE_TYPE *right_node = AVL_CHILD(left_node, DIR_RIGHT); if(right_node != NULL) { left_node = right_node; } else { return (AVL_NODE_TYPE*)left_node; } } } else { // the next node is either the first "right" parent // either nothing for(;;) { #if !AVL_HAS_PARENT_POINTER if(stack_size == 0) { return (AVL_NODE_TYPE*)NULL; } const AVL_NODE_TYPE *parent_node = stack[--stack_size]; #else const AVL_NODE_TYPE *parent_node = AVL_PARENT(node); if(parent_node == NULL) { return (AVL_NODE_TYPE*)NULL; } #endif // if the node is the right child of the parent, then return the parent if(node == AVL_CHILD(parent_node, DIR_RIGHT)) { return (AVL_NODE_TYPE*)parent_node; } node = (AVL_NODE_TYPE*)parent_node; } } } else { return NULL; } } /** @brief Insert a node into the tree. * * Insert data into the tree. * Since hash can have collisions, the data will most likely be a collection * (another tree, a list, ...) * * NOTE: * If the node associated to the hash already exists, it is returned unaltered, * the caller will be responsible to manipulate the node's data. * Else a new node is created, pointing to the data. * * @param[in] root the tree where the insertion should be made * @param[in] obj_hash the hash associated to the data * @param[out] obj the data to insert * * @return The node associated to the hash */ AVL_NODE_TYPE* AVL_PREFIXED(insert)(AVL_TREE_TYPE* tree, AVL_REFERENCE_TYPE obj_hash) { assert(tree != NULL); DUMP("avl_insert(%p, " AVL_REFERENCE_FORMAT_STRING ") ------------------------------", tree, AVL_REFERENCE_FORMAT(obj_hash)); if(AVL_TREE_ROOT(tree) == NULL) { AVL_TREE_ROOT(tree) = avl_create_node(obj_hash); DUMP("First node (root) (" AVL_REFERENCE_FORMAT_STRING ")", AVL_REFERENCE_FORMAT(AVL_REFERENCE(AVL_TREE_ROOT(tree)))); assert(AVL_TREE_ROOT(tree) != NULL); return AVL_TREE_ROOT(tree); } AVL_NODE_TYPE * nodes[AVL_MAX_DEPTH]; s8 balances[AVL_MAX_DEPTH]; s8 dirs[AVL_MAX_DEPTH]; AVL_NODE_TYPE *node = AVL_TREE_ROOT(tree); AVL_REFERENCE_TYPE node_hash; int level = 0; s8 dir = MIDDLE; #if !AVL_TERNARYCMP while((node != NULL) && !AVL_ISEQUAL(obj_hash, (node_hash = AVL_REFERENCE(node)))) { nodes[level] = node; balances[level] = AVL_BALANCE(node); /* DIR_LEFT = 0, DIR_RIGHT = 1 */ dir = AVL_ISBIGGER(obj_hash, node_hash)&1; ASSERT_CHECK_CHILD_PARENT_LINK(node); node = AVL_CHILD(node, dir); dirs[level++] = dir; } #else while(node != NULL) { node_hash = AVL_REFERENCE(node); int cmp = AVL_COMPARE(obj_hash, node_hash); if(cmp == 0) { break; } nodes[level] = node; balances[level] = AVL_BALANCE(node); /* DIR_LEFT = 0, DIR_RIGHT = 1 */ dir = (cmp > 0)&1; ASSERT_CHECK_CHILD_PARENT_LINK(node); node = AVL_CHILD(node, dir); dirs[level++] = dir; } #endif DUMP("Level = %i", level); if(node != NULL) { /* match */ DUMP("Got a match"); ASSERT_CHECK_CHILD_PARENT_LINK(node); return node; } /* Add a new node to the last one (the AVL_PARENT) */ node = nodes[--level]; /* the parent is node */ AVL_NODE_TYPE* ret = avl_create_node(obj_hash); AVL_CHILD(node, dir) = ret; #ifdef AVL_PARENT AVL_PARENT(ret) = node; #endif ASSERT_CHECK_CHILD_PARENT_LINK(ret); ASSERT_CHECK_CHILD_PARENT_LINK(node); DUMP("Created a new node from " AVL_REFERENCE_FORMAT_STRING ", going %i (%p)", AVL_REFERENCE_FORMAT(AVL_REFERENCE(node)), dir, ret); if(AVL_BALANCE(node) == MIDDLE) { /* There were no AVL_CHILD, now there is one */ /* not balanced anymore */ AVL_BALANCE(node) = DIR_TO_AVL_BALANCE(dir); /* 0 or 1 => -1 or +1 */ DUMP("Parent was balanced, now it is not anymore : %i (%i)", dir, AVL_BALANCE(node)); } else { /* There was an AVL_CHILD, now there is two */ /* balance */ AVL_BALANCE(node) = MIDDLE; DUMP("Parent was not balanced, now it is"); } AVL_NODE_TYPE* parent; /* Now I have to update the balance up to the root (if needed ...) * node is m_nodes[level] * we need the parent at m_nodes[level-1] * parent -> node -> (new node/processed node) */ while(level > 0) /* level points to the parent */ { DUMP("\tUpdating balance at %i", level); if(AVL_BALANCE(node) == balances[level]) /* balance of the node */ { /* this branch will exit */ /* The node's balance has not been changed */ ASSERT_CHECK_CHILD_PARENT_LINK(ret); return ret; } /* The node's balance has been changed */ DUMP("\t\tBalance of " AVL_REFERENCE_FORMAT_STRING " was %i, now it is %i", AVL_REFERENCE_FORMAT(AVL_REFERENCE(node)), balances[level], AVL_BALANCE(node)); if(AVL_BALANCE(node) == MIDDLE) /* this branch will exit */ { /* AVL_BALANCE(node)==MIDDLE and we are balanced * balanced -> done */ ASSERT_CHECK_CHILD_PARENT_LINK(ret); DUMP("Done (E)"); return ret; } parent = nodes[level - 1]; /* not balanced (anymore) */ /* Now dir AVL_CHILD it is un balanced ... */ /* Let's update the imbalance */ dir = dirs[level - 1]; DUMP("\t\t\timbalance: dir=%i old parent balance=%i patch=%i", dir, AVL_BALANCE(parent), DIR_TO_AVL_BALANCE(dir)); AVL_BALANCE(parent) += DIR_TO_AVL_BALANCE(dir); if(MUST_REAVL_BALANCE(parent)) /* this branch will exit */ { /* parent is the "root" */ /* node is the pivot */ DUMP("\t\t\t\tREBALANCING of " AVL_REFERENCE_FORMAT_STRING "", AVL_REFERENCE_FORMAT(AVL_REFERENCE(parent))); AVL_BALANCE(parent) >>= 1; /* reset the balance to -1;1 ... */ DUMP("\t\t\t\tbalance fix -> %i", AVL_BALANCE(parent)); /* HERE THE AVL_BALANCES ARE LOST/CORRUPTED !!! */ if(AVL_BALANCE(node) == AVL_BALANCE(parent)) /* if the sign is the same ... */ { /* AVL_BALANCE(node)=0; */ node = avl_node_single_rotation2(parent); /* the parent's parent has to be updated (to node) */ DUMP("\t\t\t\tSingle rotation, new parent is " AVL_REFERENCE_FORMAT_STRING "", AVL_REFERENCE_FORMAT(AVL_REFERENCE(node))); } else { /* AVL_BALANCE(node)=0; */ node = avl_node_double_rotation2(parent); /* the parent's parent has to be updated (to node) */ DUMP("\t\t\t\tDouble rotation, new parent is " AVL_REFERENCE_FORMAT_STRING "", AVL_REFERENCE_FORMAT(AVL_REFERENCE(node))); } /* typically ... * level--; * node=parent; * parent=m_nodes[level-1]; * here I have to reset the new parent * -> I have to get the parent on level-2 (oops if level is < 2 : * it means that the parent is the root, thus that we have to fix the root) * -> I have to get the dir used on level-2 and set it to node */ if(level > 1) /* 2 or more ... */ { AVL_CHILD(nodes[level - 2], dirs[level - 2]) = node; } else /* root */ { DUMP("Root changing from " AVL_REFERENCE_FORMAT_STRING " to " AVL_REFERENCE_FORMAT_STRING "", AVL_REFERENCE_FORMAT(AVL_REFERENCE(AVL_TREE_ROOT(tree))), AVL_REFERENCE_FORMAT(AVL_REFERENCE(node))); AVL_TREE_ROOT(tree) = node; } ASSERT_CHECK_CHILD_PARENT_LINK(node); /* rebalancing -> done */ DUMP("Done (I)"); ASSERT_CHECK_CHILD_PARENT_LINK(ret); return ret; } node = parent; ASSERT_CHECK_CHILD_PARENT_LINK(node); ASSERT_CHECK_CHILD_PARENT_LINK(parent); level--; } ASSERT_CHECK_CHILD_PARENT_LINK(ret); return ret; } /** @brief Deletes a node from the tree. * * Deletes a node from the tree. * * @param[in] root the tree from which the delete will be made * @param[in] obj_hash the hash associated to the node to remove * * @return The node associated to the hash, NULL if it did not exist. */ void AVL_PREFIXED(delete)(AVL_TREE_TYPE* tree, AVL_REFERENCE_CONST AVL_REFERENCE_TYPE obj_hash) { DUMP("avl_delete(%p, " AVL_REFERENCE_FORMAT_STRING ") ------------------------------", tree, AVL_REFERENCE_FORMAT(obj_hash)); assert(tree != NULL); if(AVL_TREE_ROOT(tree) == NULL) { /* Already empty */ return; } AVL_NODE_TYPE *nodes[AVL_MAX_DEPTH]; s8 balances[AVL_MAX_DEPTH]; s8 dirs[AVL_MAX_DEPTH]; #if DEBUG memset(&nodes, 0xf0, sizeof(AVL_NODE_TYPE*) * AVL_MAX_DEPTH); memset(&balances, 0xfb, AVL_MAX_DEPTH); memset(&dirs, 0xfd, AVL_MAX_DEPTH); #endif AVL_NODE_TYPE *node = AVL_TREE_ROOT(tree); AVL_REFERENCE_TYPE node_hash; int level = 0; s8 dir = MIDDLE; /* look for the node to delete, keep the path */ #if !AVL_TERNARYCMP while((node != NULL) && !AVL_ISEQUAL(obj_hash, (node_hash = AVL_REFERENCE(node)))) { nodes[level] = node; balances[level] = AVL_BALANCE(node); /* DIR_LEFT = 0, DIR_RIGHT = 1 */ dir = AVL_ISBIGGER(obj_hash, node_hash)&1; node = AVL_CHILD(node, dir); dirs[level++] = dir; } #else while(node != NULL) { node_hash = AVL_REFERENCE(node); int cmp = AVL_COMPARE(obj_hash, node_hash); if(cmp == 0) { break; } nodes[level] = node; balances[level] = AVL_BALANCE(node); /* DIR_LEFT = 0, DIR_RIGHT = 1 */ dir = (cmp > 0)&1; node = AVL_CHILD(node, dir); dirs[level++] = dir; } #endif DUMP("Level = %i", level); assert(level < AVL_MAX_DEPTH); if(node == NULL) { /* no match : nothing to delete */ DUMP("No match"); return; } DUMP("[%2i] Victim is "AVL_REFERENCE_FORMAT_STRING, level, AVL_REFERENCE_FORMAT(AVL_REFERENCE(node))); /* keep a pointer to the parent->child pointer */ AVL_NODE_TYPE **victim_parent_link = &AVL_TREE_ROOT(tree); if(level > 0) { victim_parent_link = &(AVL_CHILD(nodes[level - 1],dirs[level - 1])); } nodes[level] = node; balances[level] = AVL_BALANCE(node); dirs[level++] = dir; /* THIS IS WRONG (?) */ /* Remove "node" from the parent */ /* Keep the pointer for the find & destroy operation */ AVL_NODE_TYPE* victim = node; #ifdef AVL_NODE_DELETE_CALLBACK AVL_NODE_DELETE_CALLBACK(victim); #endif AVL_NODE_TYPE* victim_left = AVL_LEFT_CHILD(node); AVL_NODE_TYPE* victim_right = AVL_RIGHT_CHILD(node); /** We have found the victim node. From here 3 cases can be found * * #1 : the victim has no AVL_CHILD. We just have to remove it. (and change parent balance) * * #2 : the victim has only got one AVL_CHILD. We just have to remove it and * put its children in its place. * * #3 : the victim has got two children. * * Method '1': Theoretical way: * * We move the successor of the victim instead of B, then delete using * #1 or #2. * * Actually this requires a lot of work. (5 to 10 times more than ...) * * Method '2': Fastest way: (and forbidden with the NSEC3 because I keep pointer into the nodes) * * We have to find his "successor" (left or right). * We overwrite the data of the successor into the victim. * We link the parent of the successor * We then rebalance from the node right before where successor was. * * #3 is dependent on #1 and #2 so let's handle #3 first. */ if(victim_left != NULL && victim_right != NULL) { /** Case #3: * * @note: It is recommended to switch left/right successors * between each delete for a better balancing. * * NOTE: The path has to be completed. * */ DUMP("#3"); /* Arbitraty: "<" successor */ /****************************/ /* * Look for the node that will replace this one. * Given that we are in a (L-R) case, it's the last one in the chain L->R* */ s32 victim_level = level - 1; dirs[victim_level] = DIR_LEFT; DUMP("[%2i] From "AVL_REFERENCE_FORMAT_STRING ", going LEFT", level-1, AVL_REFERENCE_FORMAT(AVL_REFERENCE(victim))); DUMP("\tUpdating balance at %i", level-1); DUMP("\t\tBalance of " AVL_REFERENCE_FORMAT_STRING " was %i, now it is %i", AVL_REFERENCE_FORMAT(AVL_REFERENCE(victim)), balances[level-1], AVL_BALANCE(victim)); AVL_NODE_TYPE* beforesuccessor = victim; /* actually it's "victim" here */ AVL_NODE_TYPE* successor = victim_left; AVL_NODE_TYPE* tmp_node; nodes[level] = successor; balances[level] = AVL_BALANCE(successor); dirs[level++] = DIR_RIGHT; while((tmp_node = AVL_RIGHT_CHILD(successor)) != NULL) { beforesuccessor = successor; DUMP("[%2i] From " AVL_REFERENCE_FORMAT_STRING ", going RIGHT", level-1, AVL_REFERENCE_FORMAT(AVL_REFERENCE(successor))); successor = tmp_node; nodes[level] = successor; DUMP("\tUpdating balance at %i", level); DUMP("\t\tBalance of " AVL_REFERENCE_FORMAT_STRING " was %i, now it is %i", AVL_REFERENCE_FORMAT(AVL_REFERENCE(successor)), balances[level], AVL_BALANCE(successor)); balances[level] = AVL_BALANCE(successor); dirs[level++] = DIR_RIGHT; } assert(level < AVL_MAX_DEPTH); /* successor has at most one left AVL_CHILD */ DUMP("[%2i] Replacement "AVL_REFERENCE_FORMAT_STRING, level-1, AVL_REFERENCE_FORMAT(AVL_REFERENCE(successor))); /* Method 2 uses 3 moves, method 1 uses 10 */ #if 1 /* * Move the parent of victim must point to successor * The parent of successor must point to nothing. */ *victim_parent_link = successor; nodes[victim_level] = successor; AVL_RIGHT_CHILD(successor) = victim_right; AVL_BALANCE(successor) = AVL_BALANCE(victim); #ifdef AVL_PARENT AVL_PARENT(successor) = AVL_PARENT(victim); AVL_PARENT(victim_right) = successor; #endif if(beforesuccessor != victim) { AVL_RIGHT_CHILD(beforesuccessor) = AVL_LEFT_CHILD(successor); #ifdef AVL_PARENT if(AVL_LEFT_CHILD(successor) != NULL) { AVL_PARENT(AVL_LEFT_CHILD(successor)) = beforesuccessor; } #endif AVL_LEFT_CHILD(successor) = victim_left; #ifdef AVL_PARENT AVL_PARENT(victim_left) = successor; #endif AVL_BALANCE(beforesuccessor)--; level -= 2; } else { AVL_BALANCE(successor)++; level -= 2; } AVL_FREE_NODE(victim); #else /* * Overwrite node successor into victim, * then delete successor, since its content is safe * * This special case does not work if the node is linked by a third party * so I disabled it to avoid misuses. */ AVL_COPY_PAYLOAD(victim, successor); if(beforesuccessor != victim) { AVL_RIGHT_CHILD(beforesuccessor) = AVL_LEFT_CHILD(successor); AVL_BALANCE(beforesuccessor)--; } else { AVL_LEFT_CHILD(beforesuccessor) = AVL_LEFT_CHILD(successor); AVL_BALANCE(beforesuccessor)++; } AVL_FREE_NODE(successor); level -= 2; #endif /*nodes[level] = successor;*/ } /* Case #3 done */ else { /* Only 2 cases could occur right now : #1 and #2 */ AVL_FREE_NODE(victim); if(level > 1) { AVL_NODE_TYPE* victim_parent = nodes[level - 2]; /* ONE or BOTH are NULL, this is the best alternative to an if/elseif/else */ AVL_CHILD(victim_parent, dir) = (AVL_NODE_TYPE*)((intptr)victim_left | (intptr)victim_right); #ifdef AVL_PARENT if(victim_left != NULL) { AVL_PARENT(victim_left) = victim_parent; } if(victim_right != NULL) { AVL_PARENT(victim_right) = victim_parent; } #endif AVL_BALANCE(victim_parent) -= DIR_TO_AVL_BALANCE(dir); /* The balance has changed */ /* At this point the victim is detached from the tree */ /* I can delete it */ level -= 2; } else /* Else we have no AVL_PARENT, so we change the root */ { /* ONE or BOTH are NULL, this is the best alternative to the if/elseif/else above */ AVL_TREE_ROOT(tree) = (AVL_NODE_TYPE*)((intptr)victim_left | (intptr)victim_right); #ifdef AVL_PARENT if(victim_left != NULL) { AVL_PARENT(victim_left) = NULL; } if(victim_right != NULL) { AVL_PARENT(victim_right) = NULL; } #endif return; } } /* Rebalance will occur either from the replacement's parent, either from * the victim's parent. */ /* NOTE: A delete-rebalance can occur many times, up to the root. */ node = nodes[level]; /* Now I have to update the balance up to the root (if needed ...) * node is m_nodes[level] * we need the parent at m_nodes[level-1] * parent -> node -> (new node/processed node) */ while(level >= 0) /* level points to the parent */ { if(AVL_BALANCE(node) == balances[level]) /* balance of the node, scan-build false positive */ { /* this branch will exit */ /* The node's balance has not been changed */ return; } /* The node's balance has been changed */ /* * balance became 0 : It was -1 or +1 : the tree's height decreased. * It is balanced but a propagation is required. * * balance became -1 or +1 : It was 0 : the tree's height didn't change. * (One of its branch is shorter but the other one's size didn't change.) * It is a valid AVL and the propagation can stop. * * balance became -2 or +2 : it was -1 or +1 : the tree is un balanced. * It needs to be rebalanced and then a propagation is required. */ if(AVL_BALANCE(node) == MIDDLE) { /* Height decreased, tell it to the parent */ level--; if(level >= 0) { DUMP("\t[%2i] " AVL_REFERENCE_FORMAT_STRING " balance changed for MIDDLE (%i) Fixing [%i] parent balance of %i (%i)", level + 1, AVL_REFERENCE_FORMAT(AVL_REFERENCE(node)), balances[level + 1], level, DIR_TO_AVL_BALANCE(dirs[level]), dirs[level]); node = nodes[level]; AVL_BALANCE(node) -= DIR_TO_AVL_BALANCE(dirs[level]); } continue; } if(AVL_BALANCE(node) == LEFT || AVL_BALANCE(node) == RIGHT) /* this branch will exit */ { DUMP("\t[%2i] " AVL_REFERENCE_FORMAT_STRING " balance changed for LEFT or RIGHT (%i)", level, AVL_REFERENCE_FORMAT(AVL_REFERENCE(node)), balances[level]); return; } DUMP("\t[%2i] " AVL_REFERENCE_FORMAT_STRING " balance changed for imbalance (%i)", level, AVL_REFERENCE_FORMAT(AVL_REFERENCE(node)), balances[level]); /* * We need to rotate in order to be AVL again. * * + cases: * * R(+) P(-) => R(0) P(0) (double rotation) * R(+) P(0) => R(+) P(-) (single rotation, delete special case) * R(+) P(+) => R(0) P(0) (single roration) * * => if node&save balance are equal => MIDDLE for both * */ AVL_BALANCE(node) >>= 1; AVL_NODE_TYPE* child = AVL_CHILD(node, AVL_BALANCE_TO_DIR(AVL_BALANCE(node))); s8 parent_balance = AVL_BALANCE(node); s8 child_balance = AVL_BALANCE(child); if(child_balance == MIDDLE) /* patched single rotation */ { DUMP("Single Rotation (delete)"); AVL_NODE_TYPE* newroot; newroot = avl_node_single_rotation2(node); assert(newroot == child); AVL_BALANCE(child) = -parent_balance; AVL_BALANCE(node) = parent_balance; node = newroot; } else if(parent_balance == child_balance) /* single rotation case */ { DUMP("Single Rotation"); node = avl_node_single_rotation2(node); assert(node == child); } else { DUMP("Double Rotation"); node = avl_node_double_rotation2(node); } if(level == 0) /* 2 or more ... */ { /* root */ DUMP("Root changing from " AVL_REFERENCE_FORMAT_STRING " to " AVL_REFERENCE_FORMAT_STRING "", AVL_REFERENCE_FORMAT(AVL_REFERENCE(AVL_TREE_ROOT(tree))), AVL_REFERENCE_FORMAT(AVL_REFERENCE(node))); AVL_TREE_ROOT(tree) = node; break; } /* link the parent to its new child */ /* level--; AVL_CHILD(nodes[level],dirs[level])=node; node=nodes[level]; */ /* The rotations could have changed something */ /* I'll process the same level again */ AVL_CHILD(nodes[level - 1], dirs[level - 1]) = node; //AVL_CHILD(nodes[level], dirs[level]) = node; ASSERT_CHECK_CHILD_PARENT_LINK(node); /* node=nodes[level]; */ } DUMP("avl_delete done level=%i", level); } static void avl_destroy_(AVL_NODE_TYPE *node) { #ifdef AVL_NODE_DELETE_CALLBACK AVL_NODE_DELETE_CALLBACK(node); #endif AVL_NODE_TYPE* AVL_CHILD = AVL_LEFT_CHILD(node); if(AVL_CHILD != NULL) { avl_destroy_(AVL_CHILD); } AVL_CHILD = AVL_RIGHT_CHILD(node); if(AVL_CHILD != NULL) { avl_destroy_(AVL_CHILD); } AVL_FREE_NODE(node); } /** @brief Releases all the nodes of a tree * * Releases all the nodes of a tree. Data is not destroyed. * * @param[in] tree the tree to empty */ void AVL_PREFIXED(destroy)(AVL_TREE_TYPE* tree) { if(AVL_TREE_ROOT(tree) != NULL) { avl_destroy_(AVL_TREE_ROOT(tree)); AVL_TREE_ROOT(tree) = NULL; } } AVL_NODE_TYPE* AVL_PREFIXED(node_last)(AVL_NODE_TYPE *node) { if(node == NULL) { return NULL; } for(;;) { AVL_NODE_TYPE *next = AVL_RIGHT_CHILD(node); if(next == NULL) { return node; } node = next; } } /* Iterators -> */ void AVL_PREFIXED(iterator_init)(AVL_CONST_TREE_TYPE *tree, AVL_PREFIXED(iterator*) iter) { /* Do we have a tree to iterate ? */ iter->stack_pointer = -1; const AVL_NODE_TYPE *node = AVL_TREE_ROOT(tree); while(node != NULL) { iter->stack[++iter->stack_pointer] = (AVL_NODE_TYPE*)node; node = AVL_LEFT_CHILD(node); } } void AVL_PREFIXED(iterator_init_from)(AVL_CONST_TREE_TYPE *tree, AVL_PREFIXED(iterator*) iter, AVL_REFERENCE_CONST AVL_REFERENCE_TYPE obj_hash) { // Do we have a tree to iterate ? iter->stack_pointer = -1; if(tree != NULL) { // Let's stack the path left path AVL_NODE_TYPE *node = AVL_TREE_ROOT(tree); AVL_REFERENCE_MODIFIER AVL_REFERENCE_TYPE h; while(node != NULL) { h = AVL_REFERENCE(node); #if !AVL_TERNARYCMP if(AVL_ISBIGGER(h, obj_hash)) { iter->stack[++iter->stack_pointer] = node; node = AVL_LEFT_CHILD(node); } else if(AVL_ISBIGGER(obj_hash, h)) { node = AVL_RIGHT_CHILD(node); } else { iter->stack[++iter->stack_pointer] = node; return; } #else int cmp = AVL_COMPARE(h, obj_hash); if(cmp > 0) { iter->stack[++iter->stack_pointer] = node; node = AVL_LEFT_CHILD(node); } else if(cmp < 0) { node = AVL_RIGHT_CHILD(node); } else { iter->stack[++iter->stack_pointer] = node; return; } #endif } } } bool AVL_PREFIXED(iterator_hasnext)(AVL_PREFIXED(iterator*) iter) { return iter->stack_pointer >= 0; } AVL_NODE_TYPE* AVL_PREFIXED(iterator_next_node)(AVL_PREFIXED(iterator*) iter) { assert(iter->stack_pointer >= 0); AVL_NODE_TYPE *node = iter->stack[iter->stack_pointer]; AVL_NODE_TYPE* current = node; /* we got the data, now let's ready the next node */ AVL_NODE_TYPE* tmp; /* let's branch right if possible */ if((tmp = AVL_RIGHT_CHILD(node)) != NULL) { iter->stack[iter->stack_pointer] = tmp; /* replace TOP */ node = tmp; while((tmp = AVL_LEFT_CHILD(node)) != NULL) { iter->stack[++iter->stack_pointer] = tmp; /* PUSH @note edf 20180102 -- overflow is unlikely: the depth of the stack allows iteration on collections of tens of billions of items */ node = tmp; } return current; } iter->stack_pointer--; return current; } /* <- Iterators */ static void avl_callback_and_destroy_(AVL_NODE_TYPE *node, void (*callback)(AVL_NODE_TYPE *)) { AVL_NODE_TYPE* AVL_CHILD = AVL_LEFT_CHILD(node); if(AVL_CHILD != NULL) { avl_callback_and_destroy_(AVL_CHILD, callback); } AVL_CHILD = AVL_RIGHT_CHILD(node); if(AVL_CHILD != NULL) { avl_callback_and_destroy_(AVL_CHILD, callback); } callback(node); AVL_FREE_NODE(node); } /** @brief Releases all the nodes of a tree * * Releases all the nodes of a tree. * Calls a function passed in parameter before destroying the data. * It's the responsibility of the callback to process (destroy) the data * in the tree. * * @param[in] tree the tree to empty */ void AVL_PREFIXED(callback_and_destroy)(AVL_TREE_TYPE *tree, void (*callback)(AVL_NODE_TYPE *)) { if(AVL_TREE_ROOT(tree) != NULL) { avl_callback_and_destroy_(AVL_TREE_ROOT(tree), callback); AVL_TREE_ROOT(tree) = NULL; } } AVL_NODE_TYPE* AVL_PREFIXED(get_first)(AVL_CONST_TREE_TYPE* tree) { assert(tree != NULL); AVL_NODE_TYPE *node = AVL_TREE_ROOT(tree); if(node != NULL) { while(node->children.lr.left != NULL) { node = node->children.lr.left; } } return node; } #ifdef AVL_PARENT AVL_NODE_TYPE* AVL_PREFIXED(node_next)(const AVL_NODE_TYPE *node) { AVL_NODE_TYPE* next; next = AVL_RIGHT_CHILD(node); if(next != NULL) { /* Not a leaf */ /* * From the (current) right, go all the way down to the left. */ while(AVL_LEFT_CHILD(next) != NULL) { next = AVL_LEFT_CHILD(next); } } else { /* Leaf */ /* * Go up until we are the left child */ next = AVL_PARENT(node); while(next != NULL) { if(AVL_LEFT_CHILD(next) == node) { break; } node = next; next = AVL_PARENT(node); } } return next; } AVL_NODE_TYPE* AVL_PREFIXED(node_prev)(const AVL_NODE_TYPE *node) { AVL_NODE_TYPE* prev; prev = AVL_LEFT_CHILD(node); if(prev != NULL) { /* Not a leaf */ /* * From the (current) left, go all the way down to the right. * If there is nothing, then the current node (prev) is the one I'm looking for. */ while(AVL_RIGHT_CHILD(prev) != NULL) { prev = AVL_RIGHT_CHILD(prev); } } else { /* Leaf */ for(;;) { prev = AVL_PARENT(node); if(prev == NULL) { break; /* no pred */ } if(AVL_RIGHT_CHILD(prev) == node) { break; } node = prev; } } return prev; } AVL_NODE_TYPE* AVL_PREFIXED(node_mod_next)(const AVL_NODE_TYPE *node) { AVL_NODE_TYPE* next; next = AVL_RIGHT_CHILD(node); if(next != NULL) { /* Not a leaf */ /* * From the (current) right, go all the way down to the left. */ while(AVL_LEFT_CHILD(next) != NULL) { next = AVL_LEFT_CHILD(next); } } else { /* Leaf */ /* * Go up until we are the left child */ next = AVL_PARENT(node); while(next != NULL) { if(AVL_LEFT_CHILD(next) == node) { break; } node = next; next = AVL_PARENT(node); } if(next == NULL) { /* Modulo */ /* We are at the root, the next one is the one most on the left * or ourself. */ next = (AVL_NODE_TYPE*)node; // node is not the starting point anymore, so casting to not-const is ok while(AVL_LEFT_CHILD(next) != NULL) { next = AVL_LEFT_CHILD(next); } } } return next; } AVL_NODE_TYPE* AVL_PREFIXED(node_mod_prev)(const AVL_NODE_TYPE *node) { AVL_NODE_TYPE* prev; prev = AVL_LEFT_CHILD(node); if(prev != NULL) { /* Not a leaf */ /* * From the (current) left, go all the way down to the right. */ while(AVL_RIGHT_CHILD(prev) != NULL) { prev = AVL_RIGHT_CHILD(prev); } } else { /* Leaf */ /* * Go up until we are the right child */ prev = AVL_PARENT(node); while(prev != NULL) { if(AVL_RIGHT_CHILD(prev) == node) { break; } node = prev; prev = AVL_PARENT(node); } if(prev == NULL) { /* Modulo */ /* We are at the root, the prev one is the one most on the right * or ourself. */ prev = (AVL_NODE_TYPE*)node; // node is not the starting point anymore, so casting to not-const is ok while(AVL_RIGHT_CHILD(prev) != NULL) { prev = AVL_RIGHT_CHILD(prev); } } } return prev; } #endif // AVL_PARENT static int AVL_PREFIXED(check_common)(AVL_NODE_TYPE *node, int depth); static int AVL_PREFIXED(check_node)(AVL_NODE_TYPE *node, int depth) { #if AVL_HAS_PARENT_POINTER == 1 if(AVL_PARENT(node) == NULL) { /* oops */ DUMP("avl_check_node: expected a parent"); logger_flush(); DUMP("avl_check_node:\tnode=(%p, " AVL_REFERENCE_FORMAT_STRING")",node, AVL_REFERENCE_FORMAT(AVL_REFERENCE(node))); logger_flush(); return -depth; } if(AVL_PARENT(node)) { AVL_NODE_TYPE *parent__ = AVL_PARENT(node); if(parent__ != NULL) { AVL_NODE_TYPE *l__ = AVL_LEFT_CHILD(parent__); AVL_NODE_TYPE *r__ = AVL_RIGHT_CHILD(parent__); if(!(l__==(node) || r__==(node)) ) { DUMP("avl_check_node: parent->node link broken"); DUMP("avl_check_node:\tparent=(%p, " AVL_REFERENCE_FORMAT_STRING")",parent__, AVL_REFERENCE_FORMAT(AVL_REFERENCE(parent__))); if(l__ != NULL) { DUMP("avl_check_node:\t\tparent.lt=(%p, " AVL_REFERENCE_FORMAT_STRING")",l__, AVL_REFERENCE_FORMAT(AVL_REFERENCE(l__))); } if(r__ != NULL) { DUMP("avl_check_node:\t\tparent.rt=(%p, " AVL_REFERENCE_FORMAT_STRING")",r__, AVL_REFERENCE_FORMAT(AVL_REFERENCE(r__))); } DUMP("avl_check_node:\tnode=(%p, " AVL_REFERENCE_FORMAT_STRING")",node, AVL_REFERENCE_FORMAT(AVL_REFERENCE(node))); DUMP_NODE(parent__); DUMP_NODE(node); logger_flush(); flushout(); flusherr(); return -depth; } } } #endif return AVL_PREFIXED(check_common)(node, depth); } static int AVL_PREFIXED(check_common)(AVL_NODE_TYPE *node, int depth) { int ld = depth; int rd = depth; AVL_NODE_TYPE *lc = AVL_LEFT_CHILD(node); AVL_NODE_TYPE *rc = AVL_RIGHT_CHILD(node); if(lc != NULL) { if((ld = AVL_PREFIXED(check_node)(lc, depth + 1)) < 0) { return ld; } } if(rc != NULL) { if((rd = AVL_PREFIXED(check_node)(rc, depth + 1)) < 0) { return rd; } } s8 b = AVL_BALANCE(node); if( ((ld == rd) && (b != MIDDLE)) || ((ld > rd) && (b != LEFT)) || ((ld < rd) && (b != RIGHT)) || (abs(ld - rd) > 1) ) { /* oops */ DUMP("avl_check_common: invalid balancing |%d - %d| = %i (b = %i)", ld, rd, rd - ld, b); logger_flush(); DUMP("avl_check_node:\tnode=(%p, " AVL_REFERENCE_FORMAT_STRING")",node, AVL_REFERENCE_FORMAT(AVL_REFERENCE(node))); logger_flush(); return -depth; } return MAX(ld, rd); } void AVL_PREFIXED(forall)(AVL_CONST_TREE_TYPE* tree, AVL_PREFIXED(forall_callback) *callback, void *callback_args) { #if AVL_HAS_PARENT_POINTER AVL_NODE_TYPE *node = AVL_PREFIXED(get_first)(tree); while(node != NULL) { if(callback(node, callback_args) <= 0) { return; } node = AVL_PREFIXED(node_next)(node); } #else AVL_PREFIXED(iterator) iter; AVL_PREFIXED(iterator_init)(tree, &iter); while(AVL_PREFIXED(iterator_hasnext)(&iter)) { AVL_NODE_TYPE *node = AVL_PREFIXED(iterator_next_node)(&iter); if(callback(node, callback_args) <= 0) { break; } } #endif } int AVL_PREFIXED(check_tree)(AVL_TREE_TYPE* tree) { if(AVL_TREE_ROOT(tree) == NULL) { return 0; } #if AVL_HAS_PARENT_POINTER == 1 if(AVL_PARENT(AVL_TREE_ROOT(tree)) != NULL) { /* oops */ DUMP("avl_check: didn't expected a parent"); logger_flush(); DUMP("avl_check:\troot=(%p, " AVL_REFERENCE_FORMAT_STRING")",AVL_TREE_ROOT(tree), AVL_REFERENCE_FORMAT(AVL_REFERENCE(AVL_TREE_ROOT(tree)))); logger_flush(); return -1; } #endif int depth = AVL_PREFIXED(check_common)(AVL_TREE_ROOT(tree), 0); return depth; } static void AVL_PREFIXED(dump_node)(AVL_NODE_TYPE *node, int level, char c) { #if defined(DEBUG_DUMP) char b; switch(AVL_BALANCE(node)) { case TOOLEFT: b = 'l'; break; case LEFT: b = 'L'; break; case MIDDLE: b = 'M'; break; case RIGHT: b = 'R'; break; case TOORIGHT: b = 'r'; break; default: b = '?'; break; } #if AVL_HAS_PARENT_POINTER == 1 DUMP("[%2i]%S %c@%p='" AVL_REFERENCE_FORMAT_STRING"' %c (%p,%p) <- %p", level, level, c, node, AVL_REFERENCE_FORMAT(AVL_REFERENCE(node)), b, AVL_LEFT_CHILD(node), AVL_RIGHT_CHILD(node), AVL_PARENT(node)); #else DUMP("[%2i]%S %c@%p='" AVL_REFERENCE_FORMAT_STRING"' %c (%p,%p)", level, level, c, node, AVL_REFERENCE_FORMAT(AVL_REFERENCE(node)), b, AVL_LEFT_CHILD(node), AVL_RIGHT_CHILD(node)); #endif if(AVL_LEFT_CHILD(node) != NULL) { AVL_PREFIXED(dump_node)(AVL_LEFT_CHILD(node), level +1, 'l'); } if(AVL_RIGHT_CHILD(node) != NULL) { AVL_PREFIXED(dump_node)(AVL_RIGHT_CHILD(node), level +1, 'r'); } #else (void)node; (void)level; (void)c; #endif } void AVL_PREFIXED(dump)(AVL_TREE_TYPE *tree) { AVL_PREFIXED(dump_node)(AVL_TREE_ROOT(tree), 0, 'r'); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/avl.h.inc0000644000000000000000000000013214505005532023324 xustar000000000000000030 mtime=1695812442.043976474 30 atime=1695812445.788030096 30 ctime=1695812494.144722661 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/avl.h.inc0000664000374500037450000002456114505005532023276 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #ifndef _AVL_H_INC #define _AVL_H_INC #include #include #ifdef __cplusplus extern "C" { #endif #ifndef AVL_PREFIX #error Expected define: AVL_PREFIX name #endif #ifndef AVL_NODE_TYPE #error Expected define: AVL_NODE_TYPE type #endif #ifndef AVL_TREE_TYPE #error Expected define: AVL_TREE_TYPE type #endif #ifndef AVL_CONST_TREE_TYPE #error Expected define: AVL_CONST_TREE_TYPE type #endif /* * Self-explanatory but not mandatory, defaulted to TRUE */ // #define AVL_REFERENCE_IS_POINTER TRUE #ifndef AVL_REFERENCE_TYPE #error Expected define: AVL_REFERENCE_TYPE type #endif #ifndef AVL_HAS_PARENT_POINTER #error Expected define: AVL_HAS_PARENT_POINTER boolean. #endif #ifndef AVL_TREE_ROOT #error Expected define: AVL_TREE_ROOT(__tree__). // #define AVL_TREE_ROOT(x) (*x) #endif #ifndef AVL_REFERENCE_IS_CONST #error Expected define: AVL_REFERENCE_IS_CONST #endif #ifndef AVL_REFERENCE_IS_POINTER #error Expected define: AVL_REFERENCE_IS_POINTER #endif #ifndef AVL_MAX_DEPTH #error Expected define: AVL_MAX_DEPTH #endif #if AVL_REFERENCE_IS_CONST #undef AVL_REFERENCE_MODIFIER #undef AVL_REFERENCE_CONST #define AVL_REFERENCE_MODIFIER #define AVL_REFERENCE_CONST #else // there is no "const" in AVL_REFERENCE_TYPE #define AVL_REFERENCE_CONST const #endif /* * Macros to set the prefix to the function name * And no : AFAIK there are no other way to do this using only one parameter in * the first call ... (ie: less than 3 lines) */ #define __AVL_PREFIXED(name_a,name_b) name_a ## name_b /* Concat */ #define _AVL_PREFIXED(name_a,name_b) __AVL_PREFIXED(name_a,name_b) /* Do the expansion */ #define AVL_PREFIXED(name) _AVL_PREFIXED( AVL_PREFIX , name) /* Call with macro */ typedef struct AVL_PREFIXED(iterator) AVL_PREFIXED(iterator); struct AVL_PREFIXED(iterator) { s32 stack_pointer; AVL_NODE_TYPE* stack[AVL_MAX_DEPTH]; /* An AVL depth of 64 is HUGE */ }; /** @brief Initializes the tree * * Initializes the tree. * Basically : *tree=NULL; * * @param[in] tree the tree to initialize * */ void AVL_PREFIXED(init)(AVL_TREE_TYPE* tree); /** @brief Find a node in the tree * * Find a node in the tree matching a hash value. * * @param[in] tree the tree to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node or NULL if there is no such node. */ AVL_NODE_TYPE* AVL_PREFIXED(find)(AVL_CONST_TREE_TYPE* tree, AVL_REFERENCE_CONST AVL_REFERENCE_TYPE obj_hash); /** @brief Find a node in the tree or if such node does into exist, find the one after it (by key order) * * Find a node in the tree or if such node does into exist, find the one after it (by key order) * * @param[in] root the tree to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node, or if it does not exists the node after it, or NULL if there is no such node. */ AVL_NODE_TYPE* AVL_PREFIXED(find_key_or_next)(AVL_CONST_TREE_TYPE* tree, AVL_REFERENCE_CONST AVL_REFERENCE_TYPE obj_hash); /** @brief Find a node in the tree or if such node does into exist, find the one before it (by key order) * * Find a node in the tree or if such node does into exist, find the one before it (by key order) * * @param[in] root the tree to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node, or if it does not exists the node before it, or NULL if there is no such node. */ AVL_NODE_TYPE* AVL_PREFIXED(find_key_or_prev)(AVL_CONST_TREE_TYPE* tree, AVL_REFERENCE_CONST AVL_REFERENCE_TYPE obj_hash); /** @brief Insert a node into the tree. * * Insert data into the tree. * Since hash can have collisions, the data will most likely be a collection * (another tree, a list, ...) * * NOTE: * If the node associated to the hazdb_icmtl_replaysh already exists, it is returned unaltered, * the caller will be responsible to manipulate the node's data. * Else a new node is created, pointing to the data. * * @param[in] tree the tree where the insertion should be made * @param[in] obj_hash the hash associated to the data * * @return The node associated to the hash */ AVL_NODE_TYPE* AVL_PREFIXED(insert)(AVL_TREE_TYPE *tree,AVL_REFERENCE_TYPE obj_hash); /** @brief Deletes a node from the tree. * * Deletes a node from the tree. * * @param[in] tree the tree from which the delete will be made * @param[in] obj_hash the hash associated to the node to remove * * @return The node associated to the hash, NULL if it did not exist. */ void AVL_PREFIXED(delete)(AVL_TREE_TYPE *tree,AVL_REFERENCE_CONST AVL_REFERENCE_TYPE obj_hash); /** @brief Releases all the nodes of a tree * * Releases all the nodes of a tree. Data is not destroyed. * Only the right and left childs are used. Everything else * is of no importance. (Useful for destroying data & keys, * then only calling this to free the container structure) * * @param[in] tree the tree to empty */ void AVL_PREFIXED(destroy)(AVL_TREE_TYPE *tree); static inline bool AVL_PREFIXED(isempty)(AVL_CONST_TREE_TYPE *tree) { return AVL_TREE_ROOT(tree) == NULL; } /** * * @brief Returns the last node of the tree * */ AVL_NODE_TYPE* AVL_PREFIXED(node_last)(AVL_NODE_TYPE *node); /** * Initialises an iterator for the AVL tree * * @param tree * @param iter */ void AVL_PREFIXED(iterator_init)(AVL_CONST_TREE_TYPE* tree,AVL_PREFIXED(iterator*) iter); /** * Initialises an iterator for the AVL tree from a key * * @param tree * @param iter * @param obj_hash */ void AVL_PREFIXED(iterator_init_from)(AVL_CONST_TREE_TYPE *tree, AVL_PREFIXED(iterator*) iter, AVL_REFERENCE_CONST AVL_REFERENCE_TYPE obj_hash); /** * Returns TRUE iff calling avl_iterator_next_node will return a node * * @param iter * @return TRUE iff calling avl_iterator_next_node will return a node */ bool AVL_PREFIXED(iterator_hasnext)(AVL_PREFIXED(iterator*) iter); /** * Returns the next node from the iterator. * XXX_iterator_hasnext MUST be called before or results are undefined. * XXX_ being the prefix of this particular version of the AVL tree. * * @param iter * @return */ AVL_NODE_TYPE* AVL_PREFIXED(iterator_next_node)(AVL_PREFIXED(iterator*) iter); /** @brief Releases all the nodes of a tree * * Releases all the nodes of a tree. * Calls a function passed in parameter before destroying the data. * It's the responsibility of the callback to process (destroy) the data * in the tree. * * @param[in] tree the tree to empty */ void AVL_PREFIXED(callback_and_destroy)(AVL_TREE_TYPE *tree, void (*callback)(AVL_NODE_TYPE*)); /** * Returns the first element in the tree (with the key having the smallest value) * If the tree is empty, NULL is returned. * * @param tree * @return the first element of the tree, or NULL if the tree is empty */ AVL_NODE_TYPE *AVL_PREFIXED(get_first)(AVL_CONST_TREE_TYPE* tree); #if AVL_HAS_PARENT_POINTER /** * Only on implementations of nodes with a pointer to the parent. * Return the node following this one or NULL if we are already on the last one. * * @param node * @return the */ AVL_NODE_TYPE* AVL_PREFIXED(node_next)(const AVL_NODE_TYPE* node); /** * Only on implementations of nodes with a pointer to the parent. * Return the node preceding this one or NULL if we are already on the first one. * * @param node * @return the */ AVL_NODE_TYPE* AVL_PREFIXED(node_prev)(const AVL_NODE_TYPE* node); /** * Only on implementations of nodes with a pointer to the parent. * Return the node following this one or the first one if we are already on the last one. * * @param node * @return the */ AVL_NODE_TYPE* AVL_PREFIXED(node_mod_next)(const AVL_NODE_TYPE* node); /** * Only on implementations of nodes with a pointer to the parent. * Return the node preceding this one or the last one if we are already on the first one. * * @param node * @return the */ AVL_NODE_TYPE* AVL_PREFIXED(node_mod_prev)(const AVL_NODE_TYPE* node); #endif // AVL_HAS_PARENT_POINTER != 0 typedef int AVL_PREFIXED(forall_callback)(AVL_NODE_TYPE*, void*); void AVL_PREFIXED(forall)(AVL_CONST_TREE_TYPE* tree, AVL_PREFIXED(forall_callback) *callback, void *callback_args); /** * DEBUG call. * * Integrity check. * * @param tree * @return an error code in case of error. */ int AVL_PREFIXED(check_tree)(AVL_TREE_TYPE *tree); /** * DEBUG call. * * Dumps the tree on stdout * DEBUG_DUMP must be defined for this to be implemented. * * @param tree */ void AVL_PREFIXED(dump)(AVL_TREE_TYPE *tree); #undef AVL_REFERENCE_CONST #ifdef __cplusplus } #endif #else #error AVL.H.INC SHOULD NOT BE INCLUDED TWICE #endif /* _AVL_H_INC */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/base16.h0000644000000000000000000000013114505005531023051 xustar000000000000000030 mtime=1695812441.991975729 30 atime=1695812445.786030067 29 ctime=1695812494.14672269 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/base16.h0000664000374500037450000000607014505005531023017 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup base Base conversion functions * @ingroup dnscore * @brief Base 16 codec * * Base 16 codec functions * * @{ * *----------------------------------------------------------------------------*/ #ifndef _BASE16_H #define _BASE16_H #include #ifdef __cplusplus extern "C" { #endif /** * Encodes bytes into base16 * The output size must be at least size_in * 2 * * @param buffer_in bytes to convert * @param size_in number of bytes * @param buffer_out output buffer of a size >= size_in * 2 * * @return output size */ u32 base16_encode(const u8 *buffer_in,u32 size_in,char *buffer_out); /** * Decodes base16 into bytes * The output size must be at least size_in / 2 * * @param buffer_in base16 text * @param size_in number of chars * @param buffer_out output buffer of a size >= size_in / 2 * * @return output size */ ya_result base16_decode(const char *buffer_in,u32 size_in,u8 *buffer_out); /** * Maps a character [0-9A-Za-z] to 0..15 * * @param nibble the character * * @return value of the character or 0xff if the character is not part of base16 */ u8 base16_decode_nibble(char nibble); #ifdef __cplusplus } #endif #endif /* _BASE16_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/base32.h0000644000000000000000000000013214505005532023051 xustar000000000000000030 mtime=1695812442.090977147 30 atime=1695812445.790030125 30 ctime=1695812494.148722718 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/base32.h0000664000374500037450000000555714505005532023027 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup base Base conversion functions * @ingroup dnscore * @brief Base 32 codec * * Base 32 codec functions * * @{ * *----------------------------------------------------------------------------*/ #ifndef _BASE32_H #define _BASE32_H #include #ifdef __cplusplus extern "C" { #endif /** * Encodes bytes into base32 * The output size must be at least size_in * 8/5 * * @param buffer_in bytes to convert * @param size_in number of bytes * @param buffer_out output buffer of a size >= size_in * 8/5 * * @return output size */ u32 base32_encode(const u8* buffer_in,u32 size_in,char* buffer_out); /** * Decodes base32 into bytes * The output size must be at least size_in * 5/8 * * @param buffer_in base32 text * @param size_in number of chars * @param buffer_out output buffer of a size >= size_in * 5/8 * * @return output size */ ya_result base32_decode(const char* buffer_in,u32 size_in,u8* buffer_out); #ifdef __cplusplus } #endif #endif /* _BASE32_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/base32hex.h0000644000000000000000000000013214505005532023556 xustar000000000000000030 mtime=1695812442.109977419 30 atime=1695812445.790030125 30 ctime=1695812494.150722747 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/base32hex.h0000664000374500037450000000757314505005532023534 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup base Base conversion functions * @ingroup dnscore * @brief Base 32 hex codec * * Base 32-hex codec functions * * @{ * *----------------------------------------------------------------------------*/ #ifndef _BASE32HEX_H #define _BASE32HEX_H #include #include #ifdef __cplusplus extern "C" { #endif #define BASE32HEX_DECODED_CHUNK 5 #define BASE32HEX_ENCODED_CHUNK 8 #define BASE32HEX_ENCODED_LEN(bin_size_) ((((bin_size_)+(BASE32HEX_DECODED_CHUNK-1))/BASE32HEX_DECODED_CHUNK)*BASE32HEX_ENCODED_CHUNK) #define BASE32HEX_DECODED_LEN(b32_size_) ((((b32_size_)/BASE32HEX_ENCODED_CHUNK))*BASE32HEX_DECODED_CHUNK) /** * Encodes bytes into lower case base32hex * The output size must be at least size_in * 8/5 * * @param buffer_in bytes to convert * @param size_in number of bytes * @param buffer_out output buffer of a size >= size_in * 8/5 * * @return output size */ u32 base32hex_lc_encode(const u8* buffer_in,u32 size_in,char* buffer_out); /** * Encodes bytes into base32hex * The output size must be at least size_in * 8/5 * * @param buffer_in bytes to convert * @param size_in number of bytes * @param buffer_out output buffer of a size >= size_in * 8/5 * * @return output size */ u32 base32hex_encode(const u8* buffer_in,u32 size_in,char* buffer_out); /** * encodes the buffer into base32hex to the output stream * * @param os output stream * @param buffer_in buffer to encode * @param size_in size of the buffer * * @return bytes written */ ya_result output_stream_write_base32hex(output_stream *os, const u8 *buffer_in, u32 size_in); /** * Decodes base32hex into bytes * The output size must be at least size_in * 5/8 * * @param buffer_in base32hex text * @param size_in number of chars * @param buffer_out output buffer of a size >= size_in * 5/8 * * @return output size */ ya_result base32hex_decode(const char *buffer_in, u32 size_in, u8 *buffer_out); #ifdef __cplusplus } #endif #endif /* _BASE32_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/base64.h0000644000000000000000000000013214505005532023056 xustar000000000000000030 mtime=1695812442.038976402 30 atime=1695812445.788030096 30 ctime=1695812494.152722776 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/base64.h0000664000374500037450000000620114505005532023017 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup base Base conversion functions * @ingroup dnscore * @brief Base 64 codec * * Base 64 codec functions * @{ * *----------------------------------------------------------------------------*/ #ifndef _BASE64_H #define _BASE64_H #include #include #ifdef __cplusplus extern "C" { #endif #define BASE64_ENCODED_SIZE(binary_size) ((((binary_size)+2)/3)*4) #define BASE64_DECODED_SIZE(text_size) ((((text_size)+3)/4)*3) bool base64_character_set_contains(char c); /** * Encodes bytes into base64 * The output size must be at least size_in * 4/3 * * @param buffer_in bytes to convert * @param size_in number of bytes * @param buffer_out output buffer of a size >= size_in * 4/3 * * @return output size */ u32 base64_encode(const u8* buffer_in,u32 size_in,char* buffer_out); u32 base64_print(const u8* buffer_in, u32 size_in, output_stream *os); /** * Decodes base64 into bytes * The output size must be at least size_in * 3/4 * * @param buffer_in base64 text * @param size_in number of chars * @param buffer_out output buffer of a size >= size_in * 3/4 * * @return output size */ ya_result base64_decode(const char* buffer_in,u32 size_in,u8* buffer_out); #ifdef __cplusplus } #endif #endif /* _BASE64_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/basic-priority-queue.h0000644000000000000000000000013214505005532026054 xustar000000000000000030 mtime=1695812442.091977161 30 atime=1695812445.790030125 30 ctime=1695812494.154722804 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/basic-priority-queue.h0000664000374500037450000000707014505005532026022 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A node-based single linked list where insertions are always sorted * * A node-based single linked list where insertions are always sorted by priority. * * @{ */ /*----------------------------------------------------------------------------*/ #pragma once /* ------------------------------------------------------------ * * INCLUDES */ #include /* ------------------------------------------------------------ * * STRUCTS */ typedef struct bpqueue_node_s bpqueue_node_s; #define BPQNODE_TAG 0x45444f4e515042 struct bpqueue_node_s { struct bpqueue_node_s *next; void *data; u32 priority; }; typedef struct bpqueue_s bpqueue_s; struct bpqueue_s { bpqueue_node_s *first; bpqueue_node_s *last; u32 size; }; #define EMPTY_BPQUEUE {NULL, NULL, 0} /* ------------------------------------------------------------ * * PROTOTYPES */ /** * Initialises a list. * * @param list */ void bpqueue_init(bpqueue_s *list); /** * Adds an item at the head of the list. * * @param list * @param data */ void bpqueue_enqueue(bpqueue_s *list, void *data, u32 priority); /** * Remove the first item from the list. * Deletes the node but not the data. * The data is returned. * * @param list * @return the data or NULL if the list is empty */ void *bpqueue_dequeue(bpqueue_s *list); /** * Remove all items from the list. * Deletes the nodes but not the data. * * @param list */ void bpqueue_clear(bpqueue_s *list); /** * * Returns the size of the list * * @param list * @return the size of the list */ static inline u32 bpqueue_size(const bpqueue_s *list) { return list->size; } yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/buffer_input_stream.h0000644000000000000000000000013214505005532026035 xustar000000000000000030 mtime=1695812442.083977046 30 atime=1695812445.790030125 30 ctime=1695812494.156722833 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/buffer_input_stream.h0000664000374500037450000000620214505005532025777 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _BUFFER_INPUT_STREAM_H #define _BUFFER_INPUT_STREAM_H #include #ifdef __cplusplus extern "C" { #endif #define BUFFER_INPUT_STREAM_DEFAULT_BUFFER_SIZE 4096 void buffer_input_stream_init(input_stream* stream, input_stream* filtered_in, int buffer_size); /* * Function specific to the buffer_input_stream to read a line up to the '\n' */ ya_result buffer_input_stream_read_line(input_stream* stream, char* buffer, u32 len); input_stream *buffer_input_stream_get_filtered(input_stream* bis); /** * Rewinds the input stream back of a given number of bytes * * @param bos * @param bytes_back * * @return bytes_back : the operation was successful * > 0 : the maximum number of bytes available for rewind at the time of the call */ ya_result buffer_input_stream_rewind(input_stream* bos, u32 bytes_back); /** * Returns true iff the input stream is a buffer input stream * * @param bos * @return */ bool is_buffer_input_stream(input_stream *bos); #ifdef __cplusplus } #endif #endif /* _BUFFER_INPUT_STREAM_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/buffer_output_stream.h0000644000000000000000000000013214505005532026236 xustar000000000000000030 mtime=1695812442.003975901 30 atime=1695812445.787030082 30 ctime=1695812494.158722862 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/buffer_output_stream.h0000664000374500037450000000542214505005532026203 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _BUFFER_OUTPUT_STREAM_H #define _BUFFER_OUTPUT_STREAM_H #include #ifdef __cplusplus extern "C" { #endif /** * * Bufferise the in_filtered output stream wrapping it in out_stream * * Can only fail if in_filtered has not been set properly * * @param in_filtered the stream to bufferise * @param out_stream the resulting stream * @param in_buffer_size the size of the buffer * * @return SUCCESS except if in_filtered has not been opened */ ya_result buffer_output_stream_init(output_stream* out_stream, output_stream* in_filtered, int in_buffer_size); /***/ output_stream *buffer_output_stream_get_filtered(output_stream *bos); bool is_buffer_output_stream(output_stream* os); #ifdef __cplusplus } #endif #endif /* _BUFFER_OUTPUT_STREAM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/buffered-file.h0000644000000000000000000000013214505005531024470 xustar000000000000000030 mtime=1695812441.785972778 30 atime=1695812445.786030067 30 ctime=1695812494.161722905 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/buffered-file.h0000664000374500037450000000727114505005531024441 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif #if !__BUFFERED_FILE_C__ struct buffered_file_cache_t_ { int dummy; }; typedef struct buffered_file_cache_t_* buffered_file_cache_t; #endif #define BUFFERED_FILE_CACHE_PAGE_SIZE_512 9 #define BUFFERED_FILE_CACHE_PAGE_SIZE_1K 10 #define BUFFERED_FILE_CACHE_PAGE_SIZE_4K 12 #define BUFFERED_FILE_CACHE_PAGE_SIZE_64K 16 #define BUFFERED_FILE_CACHE_PAGE_SIZE_1024K 20 /** * Creates a new instance of a cache meant to be used with a buffered_file. * The cache can be shared between several files and several cache can exist (depending on the needs) * * @param name the name is only for logging/tracking/debugging * @param count the number of pages in the cache * @param log2_granularity the size of the page expressed as an exponent for 2 (e.g.: 12 means 2^12 = 4096 bytes) Values range 4 to 20. * @param use_mmap the buffer that will hold the pages can be mallocated or mmapped, depending on this boolean. * * @return the cache handle or NULL if the operation failed (lack of resources) */ buffered_file_cache_t buffered_file_cache_new_instance(const char* name, u32 count, u8 log2_granularity, bool use_mmap); /** * Releases the cache. * The cache will only be destroyed once all files using it are closed. * * @param fc */ void buffered_file_cache_delete(buffered_file_cache_t fc); /** * Creates a file that caches another. * * @param fp a pointer to the file header * @param file_to_buffer the file to cache * @param fc the cache for this file * * @return an error code */ ya_result buffered_file_init(file_t *fp, file_t file_to_buffer, buffered_file_cache_t fc); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/bytearray_input_stream.h0000644000000000000000000000013114505005532026565 xustar000000000000000030 mtime=1695812442.078976975 29 atime=1695812445.78903011 30 ctime=1695812494.163722933 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/bytearray_input_stream.h0000664000374500037450000000630214505005532026531 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _BYTEARRAY_INPUT_STREAM_H #define _BYTEARRAY_INPUT_STREAM_H #include #ifdef __cplusplus extern "C" { #endif void bytearray_input_stream_init_const(input_stream* out_stream, const void* array, u32 size); void bytearray_input_stream_init(input_stream* out_stream, void* array, u32 size, bool owned); void bytearray_input_stream_reset(input_stream* stream); void bytearray_input_stream_update(input_stream* stream, void* array, u32 size, bool owned); u32 bytearray_input_stream_offset(const input_stream* stream); u32 bytearray_input_stream_set_offset(input_stream* stream, u32 offset); u32 bytearray_input_stream_size(const input_stream* stream); u32 bytearray_input_stream_remaining(const input_stream* stream); const u8* bytearray_input_stream_buffer(const input_stream* stream); u8* bytearray_input_stream_detach(input_stream* stream); bool bytearray_input_stream_is_instance_of(const input_stream* stream); /** * Z-allocate a byte array input stream matching the one passed as a parameter. * Offset is matched. * Buffer is owned. */ input_stream *bytearray_input_stream_clone(const input_stream* stream); #ifdef __cplusplus } #endif #endif /* _BYTEARRAY_INPUT_STREAM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/bytearray_output_stream.h0000644000000000000000000000013214505005532026767 xustar000000000000000030 mtime=1695812442.016976087 30 atime=1695812445.787030082 30 ctime=1695812494.165722962 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/bytearray_output_stream.h0000664000374500037450000000761714505005532026744 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif /* * The buffer will be freed (free) on close. */ #define BYTEARRAY_OWNED 1 /* * The buffer's size can be changed. */ #define BYTEARRAY_DYNAMIC 2 /* * The internal context has been allocated by a malloc (the default except if the _static variant is used) * YOU MOSTLY WILL NOT USE THAT FLAG */ #define BYTEARRAY_ZALLOC_CONTEXT 4 typedef char bytearray_output_stream_context[sizeof(void*) + 9]; void bytearray_output_stream_init(output_stream* out_stream, u8* array,u32 size); void bytearray_output_stream_init_ex(output_stream* out_stream, u8* array,u32 size, u8 flags); /* * most of bytearray_output_stream usages function-enclosed : init, work on, close * this variant of initialisation avoids an malloc */ void bytearray_output_stream_init_ex_static(output_stream* out_stream, u8* array,u32 size, u8 flags, bytearray_output_stream_context *ctx); void bytearray_output_stream_reset(output_stream* out_stream); // can only work if the buffer is owned ya_result bytearray_output_stream_ensure(output_stream* out_stream, u32 size); u32 bytearray_output_stream_size(output_stream* out_stream); u8* bytearray_output_stream_buffer(output_stream* out_stream); u8* bytearray_output_stream_detach(output_stream* out_stream); void bytearray_output_stream_set(output_stream* out_stream, u8 *buffer, u32 buffer_size, bool owned); /** * @param out_stream * @param by * @return the actual rewind_count */ u32 bytearray_output_stream_rewind(output_stream* out_stream, u32 rewind_count); u8* bytearray_output_stream_zdup(output_stream* out_stream); u8* bytearray_output_stream_dup(output_stream* out_stream); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/bytezarray_output_stream.h0000644000000000000000000000013014505005532027157 xustar000000000000000029 mtime=1695812442.04097643 30 atime=1695812445.788030096 29 ctime=1695812494.16772299 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/bytezarray_output_stream.h0000664000374500037450000000713514505005532027131 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif /* * The buffer will be freed (free) on close. */ #define BYTEARRAY_OWNED 1 /* * The buffer's size can be changed. */ #define BYTEARRAY_DYNAMIC 2 /* * The internal context has been allocated by a malloc (the default except if the _static variant is used) * YOU MOSTLY WILL NOT USE THAT FLAG */ #define BYTEARRAY_ZALLOC_CONTEXT 4 typedef char bytezarray_output_stream_context[sizeof(void*) + 9]; void bytezarray_output_stream_init(output_stream *out_stream, u8 *array, u32 size); void bytezarray_output_stream_init_ex(output_stream *out_stream, u8 *array, u32 size, u8 flags); /* * most of bytezarray_output_stream usages function-enclosed : init, work on, close * this variant of initialisation avoids an malloc */ void bytezarray_output_stream_init_ex_static(output_stream* out_stream, u8 *array,u32 size, u8 flags, bytezarray_output_stream_context *ctx); void bytezarray_output_stream_reset(output_stream *out_stream); u32 bytezarray_output_stream_size(output_stream *out_stream); u8 *bytezarray_output_stream_buffer(output_stream *out_stream); u32 bytezarray_output_stream_buffer_size(output_stream *stream); u32 bytezarray_output_stream_buffer_offset(output_stream* stream); u8 *bytezarray_output_stream_detach(output_stream *out_stream); void bytezarray_output_stream_set(output_stream* out_stream, u8 *buffer, u32 buffer_size, bool owned); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/checked_output_stream.h0000644000000000000000000000013114505005532026352 xustar000000000000000030 mtime=1695812442.055976646 29 atime=1695812445.78903011 30 ctime=1695812494.169723019 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/checked_output_stream.h0000664000374500037450000000652314505005532026323 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif #define CHECKED_OUTPUT_STREAM_STATES_COUNT 6 #define CHECKED_OUTPUT_STREAM_NOSPC 0x00000001 #define CHECKED_OUTPUT_STREAM_PERM 0x00000002 #define CHECKED_OUTPUT_STREAM_IO 0x00000004 #define CHECKED_OUTPUT_STREAM_FBIG 0x00000008 #define CHECKED_OUTPUT_STREAM_DQUOT 0x00000010 #define CHECKED_OUTPUT_STREAM_BADF 0x00000020 struct checked_output_stream_data_s { output_stream* filtered; u32 state; }; typedef struct checked_output_stream_data_s checked_output_stream_data_t; void checked_output_stream_init(output_stream* os, output_stream* filtered, checked_output_stream_data_t* checked_data); bool checked_output_stream_instance(output_stream *stream); ya_result checked_output_stream_error(output_stream* os); /** * Every single of the kept states are show-breakers. */ static inline bool checked_output_stream_failed(output_stream* os) { assert(checked_output_stream_instance(os)); checked_output_stream_data_t* data = (checked_output_stream_data_t*)os->data; return data->state != 0; } static inline void checked_output_stream_state_clear(output_stream* os) { assert(checked_output_stream_instance(os)); checked_output_stream_data_t* data = (checked_output_stream_data_t*)os->data; data->state = 0; } #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/chroot.h0000644000000000000000000000013214505005532023270 xustar000000000000000030 mtime=1695812442.095977218 30 atime=1695812445.790030125 30 ctime=1695812494.171723048 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/chroot.h0000664000374500037450000000507214505005532023236 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup chroot * @ingroup dnscore * @brief Chroot functions * * @{ */ #pragma once #include /** * * Returns the base path by taking into account the chroot path. * * This is seldom used because it's usually more efficient to update paths * with the right prefix once at initialisation. * * @return if the chroot jail is on, returns "/", else returns the last value set by: chroot_set_path(const char*) * */ const char *chroot_get_path(); ya_result chroot_set_path(const char *path); ya_result chroot_jail(); ya_result chroot_manage_path(char **managed_location, const char *path, bool chroot_relative); ya_result chroot_unmanage_path(char **managed_location); void chroot_unmanage_all(); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/circular-file.h0000644000000000000000000000013114505005532024512 xustar000000000000000030 mtime=1695812442.069976846 29 atime=1695812445.78903011 30 ctime=1695812494.173723076 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/circular-file.h0000664000374500037450000001001214505005532024447 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup acl Access Control List * @ingroup yadifad * @brief * * @{ */ #pragma once #include #ifndef CIRCULAR_FILE_C struct circular_file_s; typedef struct circular_file_s circular_file_s; #endif typedef struct circular_file_s* circular_file_t; ya_result circular_file_create(circular_file_t *cfp, file_pool_t fp, const u8 magic[4], const char* path, s64 size_max, u32 reserved_header_size); ya_result circular_file_open(circular_file_t *cfp, file_pool_t fp, const u8 magic[4], const char *path); ya_result circular_file_close(circular_file_t cf); u64 circular_file_tell(circular_file_t cf); const char *circular_file_name(circular_file_t cf); ya_result circular_file_unlink(circular_file_t cf); u64 circular_file_absolute_tell(circular_file_t cf); void circular_file_absolute_seek(circular_file_t cf, u64 position); ssize_t circular_file_seek_relative(circular_file_t cf, ssize_t relative_offset); ssize_t circular_file_seek(circular_file_t cf, ssize_t absolute_offset); ya_result circular_file_read(circular_file_t cf, void* buffer_, u32 n); ya_result circular_file_write(circular_file_t cf, const void* buffer_, u32 n); u64 circular_file_get_used_space(circular_file_t cf); u64 circular_file_get_maximum_size(circular_file_t cf); u64 circular_file_get_pending_size(circular_file_t cf); u64 circular_file_get_size(circular_file_t cf); void circular_file_set_size(circular_file_t cf, u64 size); s64 circular_file_get_read_available(circular_file_t cf); s64 circular_file_get_write_available(circular_file_t cf); ya_result circular_file_grow(circular_file_t cf, s64 new_maximum_size); ya_result circular_file_get_reserved_header_size(circular_file_t cf, s32 *reserved_size); ya_result circular_file_read_reserved_header(circular_file_t cf, void *buffer, u32 buffer_size); ya_result circular_file_write_reserved_header(circular_file_t cf, void *buffer, u32 buffer_size); ya_result circular_file_flush(circular_file_t cf); ya_result circular_file_shift(circular_file_t cf, s64 bytes); void circular_file_dump(circular_file_t cf); void circular_file_input_stream_init(input_stream *is, circular_file_t cf); void circular_file_input_stream_noclose_init(input_stream *is, circular_file_t cf); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/clone_input_output_stream.h0000644000000000000000000000013214505005532027304 xustar000000000000000030 mtime=1695812442.006975944 30 atime=1695812445.787030082 30 ctime=1695812494.175723105 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/clone_input_output_stream.h0000664000374500037450000000517314505005532027254 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _CLONE_INPUT_OUTPUT_STREAM_H #define _CLONE_INPUT_OUTPUT_STREAM_H #include #include #ifdef __cplusplus extern "C" { #endif /** * Can only fail if in_filtered has not been set */ ya_result clone_input_output_stream_init(input_stream *cis, input_stream* in_cloned, output_stream* out_copy); input_stream *clone_input_output_stream_get_cloned(input_stream* cis); output_stream *clone_input_output_stream_get_copy(input_stream* cis); #ifdef __cplusplus } #endif #endif /* _clone_OUTPUT_STREAM_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/cmdline.h0000644000000000000000000000013214505005531023404 xustar000000000000000030 mtime=1695812441.986975657 30 atime=1695812445.786030067 30 ctime=1695812494.177723134 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/cmdline.h0000664000374500037450000002057114505005531023353 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #include #include #define CMDLINE_FLAG_SECTION 0 #define CMDLINE_FLAG_ALIAS 1 #define CMDLINE_FLAG_TRANSLATOR 2 #define CMDLINE_FLAG_TERMINATOR 4 #define CMDLINE_FLAG_FILTER_SET 8 #define CMDLINE_FLAG_HELP_CALLBACK 16 #define CMDLINE_FLAG_HELP_MESSAGE 32 #define CMDLINE_FLAG_HELP_LINE 64 #define CMDLINE_FLAG_ARGUMENTS 128 #define CMDLINE_FLAG_OBFUSCATE 256 #define CMDLINE_FLAG_INDENTED 512 #define CMDLINE_FLAG_SEPARATOR 1024 #define CMDLINE_ARG_STOP_PROCESSING_FLAG_OPTIONS 1 #define CMDLINE_ERROR_BASE 0x800E0000 #define CMDLINE_ERROR_CODE(code_) ((s32)(CMDLINE_ERROR_BASE+(code_))) #define CMDLINE_PROCESSING_SECTION_AS_ARGUMENT CMDLINE_ERROR_CODE(0xff01) #define CMDLINE_PROCESSING_INVALID_DESCRIPTOR CMDLINE_ERROR_CODE(0xff02) #define CMDLINE_LONG_OPT_UNDEFINED CMDLINE_ERROR_CODE(0x0001) #define CMDLINE_SHORT_OPT_UNDEFINED CMDLINE_ERROR_CODE(0x0002) #define CMDLINE_OPT_EXPECTS_ARGUMENT CMDLINE_ERROR_CODE(0x0003) struct cmdline_desc_s; typedef ya_result cmdline_translator_callback(const struct cmdline_desc_s *desc, output_stream *os, const char *section_name, const char *arg_name); typedef ya_result cmdline_filter_callback(const struct cmdline_desc_s *desc, const char *arg_name, void *callback_owned); // desc->name is used to store the args typedef ya_result cmdline_printer_callback(const struct cmdline_desc_s *desc, output_stream *os); struct cmdline_desc_s { u16 flags; char letter; const char *name; const char *value; union { const char *alias; cmdline_translator_callback *translator; cmdline_printer_callback *printer; cmdline_filter_callback *filter; int integer_value; } target; }; typedef struct cmdline_desc_s cmdline_desc_s; /** * Definition of a command-line * The command line is handled as a table of aliases to configuration settings. * It means that each entry has to be linked to a section/container as well as a variable. * * The table must be put between CMDLINE_BEGIN and CMDLINE_END * * The parameter of CMDLINE_BEGIN and CMDLINE_END is the name of the table (a variable name) * * The section is set using CMDLINE_SECTION(section name). Each configuration alias refers * to the section named by the last CMDLINE_SECTION entry above it. * * CMDLINE_BOOL CMDLINE_BOOL_NOT CMDLINE_OPT are taking 3 parameters * The first one is the name of the parameter on the command line. (long option) * The second one is the letter of the parameter on the command line. (short option) * The third one is the name of the variable in the configuration section. * * NOTE: there is no "underscore" filtering for the argument name. * "long_opt" only matches "--long_opt" and * "long-opt" only matches "--long-opt" * * "underscore" filtering is enabled for the alias argument * */ #define CMDLINE_BEGIN(name_) static const cmdline_desc_s name_[] = { /** * The filter gets all words not taken by the rest of the CMDLINE struct * * Only active is placed right after CMDLINE_BEGIN */ #define CMDLINE_FILTER(function_, arg_) {CMDLINE_FLAG_FILTER_SET , '\0', (arg_), NULL, {.filter = (function_)} }, #define CMDLINE_SECTION(name_) { 0, '\0', (name_), NULL, {.alias = NULL}}, #define CMDLINE_BOOL(name_,letter_,alias_) {CMDLINE_FLAG_ALIAS , (letter_), (name_), "on", {.alias = (alias_)}}, #define CMDLINE_BOOL_NOT(name_,letter_,alias_) {CMDLINE_FLAG_ALIAS , (letter_), (name_), "off", {.alias = (alias_)}}, #define CMDLINE_OPT(name_,letter_,alias_) {CMDLINE_FLAG_ALIAS|CMDLINE_FLAG_ARGUMENTS, (letter_), (name_), NULL, {.alias = (alias_)}}, #define CMDLINE_OPT_OBFUSCATE(name_,letter_,alias_) {CMDLINE_FLAG_ALIAS|CMDLINE_FLAG_ARGUMENTS|CMDLINE_FLAG_OBFUSCATE, (letter_), (name_), NULL, {.alias = (alias_)}}, #define CMDLINE_HELP(argparm_, helptext_) {CMDLINE_FLAG_HELP_LINE , '\0', (argparm_),(helptext_), {.alias = NULL} }, #define CMDLINE_MSG(argparm_, helptext_) {CMDLINE_FLAG_HELP_MESSAGE , '\0', (argparm_),(helptext_), {.alias = NULL} }, #define CMDLINE_IMSG(argparm_, helptext_) {CMDLINE_FLAG_HELP_MESSAGE|CMDLINE_FLAG_INDENTED, '\0', (argparm_),(helptext_), {.alias = NULL} }, #define CMDLINE_IMSGS(argparm_, helptext_) {CMDLINE_FLAG_HELP_MESSAGE|CMDLINE_FLAG_INDENTED|CMDLINE_FLAG_SEPARATOR, '\0', (argparm_),(helptext_), {.alias = NULL} }, #define CMDLINE_CALLBACK(function_, arg_) {CMDLINE_FLAG_HELP_CALLBACK , '\0', (arg_), NULL, {.printer = (function_)} }, #define CMDLINE_INDENT(value_) {CMDLINE_FLAG_INDENTED , '\0', NULL, NULL, {.integer_value = (value_)} }, #define CMDLINE_BLANK() {CMDLINE_FLAG_HELP_MESSAGE , '\0', "", "", {.alias = NULL} }, #define CMDLINE_END(name_) {CMDLINE_FLAG_TERMINATOR , '\0', NULL, NULL, {.alias = NULL}} }; #define CMDLINE_CALLBACK_ARG_GET(_desc_) ((void*)((_desc_)->name)) static inline bool cmdline_desc_not_end(const cmdline_desc_s *table) { return (table->flags & CMDLINE_FLAG_TERMINATOR) == 0; } /** * Parses a command line and returns an input stream ready to be parsed by a configuration reader. * * The function works by generating a configuration file in a stream using the command line table as a map. * * @param table the name of a table defined using CMDLINE_BEGIN * @param argc the argc of main() * @param argv the argv of main() * @param filter a callback function that will be called for unhandled command line parameters (file names, "--", ...) * @param filter_arg a pointer given to the filter callback * @param is the input stream to initialise with the command line * @return */ ya_result cmdline_parse(const cmdline_desc_s *table, int argc, char **argv, cmdline_filter_callback *filter, void *filter_arg, input_stream *is, int *argc_errorp); /** * Registers command line error codes. */ void cmdline_init_error_codes(); ya_result cmdline_get_opt_long(const cmdline_desc_s *table, const char *name, const char *arg); ya_result cmdline_get_opt_short(const cmdline_desc_s *table, const char *name, const char *arg); ya_result cmdline_print_help(const cmdline_desc_s *table, int arg_column_prefix, int arg_width, const char *column_separator, int text_width, output_stream *os); yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/concat_input_stream.h0000644000000000000000000000013214505005532026033 xustar000000000000000030 mtime=1695812442.031976302 30 atime=1695812445.788030096 30 ctime=1695812494.179723162 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/concat_input_stream.h0000664000374500037450000000474514505005532026007 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _CONCAT_INPUT_STREAM_H #define _CONCAT_INPUT_STREAM_H #include #ifdef __cplusplus extern "C" { #endif /** * * @param cis */ void concat_input_stream_init(input_stream *cis); /** * * @param cis * @param added_stream */ void concat_input_stream_add(input_stream *cis, input_stream *added_stream); #ifdef __cplusplus } #endif #endif /* _CONCAT_INPUT_STREAM_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/config-cmdline.h0000644000000000000000000000013214505005531024647 xustar000000000000000030 mtime=1695812441.987975672 30 atime=1695812445.786030067 30 ctime=1695812494.181723191 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/config-cmdline.h0000664000374500037450000000675714505005531024630 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifndef CONFIG_CMDLINE_C extern const char CMDLINE_CONTAINER[]; #endif /** * This define has to be put in a CMDLINE table so the help can be handled * automatically. * * Requires registration of the command line using config_register_cmdline */ #define CMDLINE_VERSION_HELP(cmdline)\ CMDLINE_SECTION( CMDLINE_CONTAINER)\ CMDLINE_BOOL( "help", 'h', "help")\ CMDLINE_HELP("","shows this help")\ CMDLINE_BOOL( "help", '?', "help") /* not adding CMDLINE_HELP here is not an oversight */ \ CMDLINE_BOOL( "version", 'V', "version")\ CMDLINE_HELP("","prints the version of the software") /** * * Registers the command line section/container with the configuration mechanism. * Allows handling of help and version command line parameters. * * @param priority * @return */ ya_result config_register_cmdline(u8 priority); /** * Returns if the CMDLINE_VERSION_HELP(main_cmdline) command line help hook detected a --help * Needs to have config_register_cmdline(priority++) called in the configuration registration code. * * @return TRUE iff a help parameter was found in the command line */ bool cmdline_help_get(); /** * Returns if the CMDLINE_VERSION_HELP(main_cmdline) command line help hook detected a --version * Needs to have config_register_cmdline(priority++) called in the configuration registration code. * * @return the number of times a version parameter was found on the command line */ u8 cmdline_version_get(); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/config_file_reader.h0000644000000000000000000000013114505005532025557 xustar000000000000000030 mtime=1695812442.014976058 30 atime=1695812445.787030082 29 ctime=1695812494.18372322 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/config_file_reader.h0000664000374500037450000000561514505005532025531 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #include /** * * Parses an input stream for a section/container defined by its config sectiondescriptor. * The input stream will be closed by the function. * * @param stream_name a name to identify the stream in case of error * @param ins the input stream to parse * @param csd the descriptor of the section to parse * @param cfgerr if not NULL, the error reporting structure to fill in case of error * * @return an error code */ ya_result config_file_reader_parse_stream(const char* stream_name, input_stream *ins, struct config_section_descriptor_s *csd, config_error_s *cfgerr); /** * * Parses a file for a section/container defined by its config sectiondescriptor. * * @param fullpath the file path * @param csd the descriptor of the section to parse * @param cfgerr if not NULL, the error reporting structure to fill in case of error * * @return an error code */ ya_result config_file_reader_open(const char* fullpath, struct config_section_descriptor_s *csd, config_error_s *cfgerr); yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/config_settings.h0000644000000000000000000000013114505005532025156 xustar000000000000000030 mtime=1695812442.074976918 29 atime=1695812445.78903011 30 ctime=1695812494.185723248 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/config_settings.h0000664000374500037450000011016214505005532025122 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * @{ */ #pragma once #include #include #include #include #include #include /* Each section/container descriptor is registered. config section descriptor -------> target base (ie: g_config) | V config table descriptor vtbl -----> callbacks (init, start, stop, finalise, ...) | V table descriptor (BEGIN/END, names, offsets in target base, setters) */ #define CONFIG_ERROR_BASE 0x800C0000 #define CONFIG_ERROR_CODE(code_) ((s32)(CONFIG_ERROR_BASE+(code_))) // Bugs in the program #define CONFIG_SECTION_ALREADY_REGISTERED CONFIG_ERROR_CODE(0xff01) #define CONFIG_ALIAS_CHAIN_TOO_BIG CONFIG_ERROR_CODE(0xff02) // Parsing issues #define CONFIG_PARSE_SECTION_TAG_NOT_CLOSED CONFIG_ERROR_CODE(0x0001) #define CONFIG_PARSE_UNEXPECTED_SECTION_OPEN CONFIG_ERROR_CODE(0x0002) #define CONFIG_PARSE_UNEXPECTED_SECTION_CLOSE CONFIG_ERROR_CODE(0x0003) #define CONFIG_PARSE_CLOSED_WRONG_SECTION CONFIG_ERROR_CODE(0x0004) #define CONFIG_PARSE_SECTION_TAG_TOO_SMALL CONFIG_ERROR_CODE(0x0005) #define CONFIG_PARSE_INCLUDE_EXPECTED_FILE_PATH CONFIG_ERROR_CODE(0x0006) #define CONFIG_PARSE_UNKNOWN_KEYWORD CONFIG_ERROR_CODE(0x0007) #define CONFIG_PARSE_EXPECTED_VALUE CONFIG_ERROR_CODE(0x0008) // Content issues #define CONFIG_UNKNOWN_SETTING CONFIG_ERROR_CODE(0x0011) #define CONFIG_VALUE_OUT_OF_RANGE CONFIG_ERROR_CODE(0x0012) #define CONFIG_FILE_PATH_TOO_BIG CONFIG_ERROR_CODE(0x0013) #define CONFIG_BAD_UID CONFIG_ERROR_CODE(0x0014) #define CONFIG_BAD_GID CONFIG_ERROR_CODE(0x0015) #define CONFIG_TEXT_LENGTH_TOO_BIG CONFIG_ERROR_CODE(0x0016) #define CONFIG_ARRAY_SIZE_TOO_BIG CONFIG_ERROR_CODE(0x0017) // Logger config specific issues #define CONFIG_LOGGER_HANDLE_ALREADY_DEFINED CONFIG_ERROR_CODE(0x1001) #define CONFIG_LOGGER_INVALID_DEBUGLEVEL CONFIG_ERROR_CODE(0x1002) // TSIG key config specific issues #define CONFIG_KEY_INCOMPLETE_KEY CONFIG_ERROR_CODE(0x2001) #define CONFIG_KEY_UNSUPPORTED_ALGORITHM CONFIG_ERROR_CODE(0x2002) /* #define CONFIG_LOGGER_INVALID_DEBUGLEVEL CONFIG_ERROR_CODE(0x0001) */ #define CONFIG_TABLE_SOURCE_NONE 0 #define CONFIG_TABLE_SOURCE_DEFAULT 1 #define CONFIG_TABLE_SOURCE_CONFIGURATION_FILE 2 #define CONFIG_TABLE_SOURCE_COMMAND_LINE 3 #define CONFIG_HOST_LIST_FLAGS_IPV4 0x01 #define CONFIG_HOST_LIST_FLAGS_IPV6 0x02 #define CONFIG_HOST_LIST_FLAGS_FQDN 0x04 #define CONFIG_HOST_LIST_FLAGS_PORT 0x08 #define CONFIG_HOST_LIST_FLAGS_TSIG 0x10 #define CONFIG_HOST_LIST_FLAGS_APPEND 0x20 #define CONFIG_HOST_LIST_FLAGS_DEFAULT (CONFIG_HOST_LIST_FLAGS_IPV4 | CONFIG_HOST_LIST_FLAGS_IPV6 | CONFIG_HOST_LIST_FLAGS_PORT | CONFIG_HOST_LIST_FLAGS_TSIG) #define CONFIG_FLAG_ON "1" #define CONFIG_FLAG_OFF "0" #define CONFIG_SOURCE_NONE 0 #define CONFIG_SOURCE_DEFAULT 1 #define CONFIG_SOURCE_FILE 128 #define CONFIG_SOURCE_CMDLINE 250 #define CONFIG_SOURCE_HIGHEST 255 #define CONFIG_SETTINGS_DEBUG 0 #define CONFIG_FIELD_ALLOCATION_DIRECT 0 // direct value #define CONFIG_FIELD_ALLOCATION_MALLOC 1 // mallocated value #define CONFIG_FIELD_ALLOCATION_ZALLOC 2 // zallocated value /** * This union covers 64 bits * Meant to be used to store different parameters */ #if BYTE_ORDER == LITTLE_ENDIAN union anytype_u { /* DO NOT ADD THIS : bool _bool; */ u8 _u8; u16 _u16; u32 _u32; u64 _u64; u8 _8u8[8]; u16 _4u16[4]; u32 _2u32[2]; s8 _s8; s16 _s16; s32 _s32; s64 _s64; s8 _8s8[8]; s16 _4s16[4]; s32 _2s32[2]; intptr _intptr; callback_function *void_callback; result_callback_function *result_callback; void* _voidp; char* _charp; u8* _u8p; }; #elif BYTE_ORDER == BIG_ENDIAN union anytype_u { /* DO NOT ADD THIS : bool _bool; */ struct { u8 _u8_0, _u8_1, _u8_2, _u8_3, _u8_4, _u8_5, _u8_6,_u8; }; struct { u16 _u16_0, _u16_1, _u16_2, _u16; }; struct { u32 _u32_0, _u32; }; u64 _u64; u8 _8u8[8]; u16 _4u16[4]; u32 _2u32[2]; struct { s8 _s8_0, _s8_1, _s8_2, _s8_3, _s8_4, _s8_5, _s8_6,_s8; }; struct { s16 _s16_0, _s16_1, _s16_2, _s16; }; struct { s32 _s32_0, _s32; }; s64 _s64; s8 _8s8[8]; s16 _4s16[4]; s32 _2s32[2]; #if __SIZEOF_POINTER__ == 8 intptr _intptr; callback_function *void_callback; result_callback_function *result_callback; void* _voidp; char* _charp; u8* _u8p; #else struct { intptr _intptr_0, _intptr; }; struct { callback_function *_void_callback_0, *void_callback; }; struct { result_callback_function *_result_callback_0, *result_callback; }; struct { void *_voidp_0, *_voidp; }; struct { char *_charp_0, *_charp; }; struct { u8 *_u8p_0, *_u8p; }; #endif }; #else #error "BYTE_ORDER value not expected" #endif typedef union anytype_u anytype; typedef ya_result config_set_field_function(const char*, void*, const anytype); struct config_section_descriptor_s; /** * name is the name of the key, expected in the config file * field_offset is the offset of the value from the beginning of the target struct * setter is the function able to parse the value of the key and store it at target + offset * default_value_string is the string containing the default value for the key * function_specific is a parameter given to the setter. The meaning is different for each setter. * source is the level that wrote the current value in the table */ struct config_table_descriptor_item_s { const char *name; size_t field_offset; config_set_field_function *setter; const char *default_value_string; anytype function_specific; size_t expected_size; size_t field_size; u8 source; u8 allocation_mode; // help text }; typedef struct config_table_descriptor_item_s config_table_descriptor_item_s; typedef ya_result config_section_set_wild_method(struct config_section_descriptor_s *, const char *key, const char *value); typedef ya_result config_section_print_wild_method(const struct config_section_descriptor_s *, output_stream *os, const char *key, void **iterator_context); typedef ya_result config_section_init_method(struct config_section_descriptor_s *); typedef ya_result config_section_start_method(struct config_section_descriptor_s *); typedef ya_result config_section_stop_method(struct config_section_descriptor_s *); typedef ya_result config_section_postprocess_method(struct config_section_descriptor_s *); typedef ya_result config_section_finalize_method(struct config_section_descriptor_s *); #define CFGSVTBL_TAG 0x42545653474643 struct config_section_descriptor_vtbl_s { /// section name const char *name; // the table name config_table_descriptor_item_s *table; // the descriptor for the table (static fields) config_section_set_wild_method *set_wild; // sets an undefined (dynamic) field config_section_print_wild_method *print_wild; // prints an undefined (dynamic) field // note: never stop iterating before the updated context value after a call to print_wild is NULL config_section_init_method *init; // initialises config_section_start_method *start; // called when a section starts config_section_stop_method *stop; // called when a section stops config_section_postprocess_method *postprocess; // called after the section has been processed config_section_finalize_method *finalise; // finishes, deletes all memory for this section, this vtbl included (if needed) }; typedef struct config_section_descriptor_vtbl_s config_section_descriptor_vtbl_s; #define CFGSDESC_TAG 0x4353454453474643 struct config_section_descriptor_s { void *base; // base of the structure to fill up const config_section_descriptor_vtbl_s *vtbl; }; typedef struct config_section_descriptor_s config_section_descriptor_s; /** * Here are the helper macro used to define the fields in the structure * * The definition of the table always be done like this: * * struct my_struct_type * { * u32 field_name_in_my_struct_type; * }; * * typedef struct my_struct_type my_struct_type; * * #define CONFIG_TYPE my_struct_type * CONFIG_BEGIN(my_struct_type_table_desc) * CONFIG_U32(field_name_in_my_struct_type,default_value_in_text_form) * CONFIG_END(my_struct_type_table_desc) * #undef CONFIG_TYPE * * */ #undef CONFIG_TYPE /* please_define_me */ #define CONFIG_BEGIN(name_) static /* DO NOT const */ config_table_descriptor_item_s name_[] = { #define CONFIG_BOOL(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_bool, defaultvalue_,{._intptr=0}, sizeof(bool), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_FLAG8(fieldname_,defaultvalue_, realfieldname_, mask_) {#fieldname_,offsetof(CONFIG_TYPE, realfieldname_), (config_set_field_function*)config_set_flag8, defaultvalue_,{._u8=(u8)(mask_)}, sizeof(u8), sizeof(u8), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_FLAG16(fieldname_,defaultvalue_, realfieldname_,mask_) {#fieldname_,offsetof(CONFIG_TYPE, realfieldname_), (config_set_field_function*)config_set_flag16, defaultvalue_,{._u16=(u16)(mask_)}, sizeof(u16), sizeof(u16), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_FLAG32(fieldname_,defaultvalue_, realfieldname_,mask_) {#fieldname_,offsetof(CONFIG_TYPE, realfieldname_), (config_set_field_function*)config_set_flag32, defaultvalue_,{._u32=(u32)(mask_)}, sizeof(u32), sizeof(u32), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_FLAG64(fieldname_,defaultvalue_, realfieldname_,mask_) {#fieldname_,offsetof(CONFIG_TYPE, realfieldname_), (config_set_field_function*)config_set_flag64, defaultvalue_,{._u64=(u64)(mask_)}, sizeof(u64), sizeof(u64), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_U64(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u64, defaultvalue_,{._intptr=0}, sizeof(u64), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_U32(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u32, defaultvalue_,{._intptr=0}, sizeof(u32), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_S32(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_s32, defaultvalue_,{._intptr=0}, sizeof(u32), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_U32_RANGE(fieldname_,defaultvalue_,min_,max_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u32_range, defaultvalue_,{._2u32={(min_),(max_)}}, sizeof(u32), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_U32_CLAMP(fieldname_,defaultvalue_,min_,max_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u32_clamp, defaultvalue_,{._2u32={(min_),(max_)}}, sizeof(u32), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_U16(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u16, defaultvalue_,{._intptr=0}, sizeof(u16), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_DNS_TYPE(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_dnstype, defaultvalue_,{._intptr=0}, sizeof(u16), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_DNS_CLASS(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_dnsclass, defaultvalue_,{._intptr=0}, sizeof(u16), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_U8(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_u8, defaultvalue_,{._intptr=0}, sizeof(u8), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_DNSKEY_ALGORITHM(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_dnskey_algorithm, defaultvalue_,{._intptr=0}, sizeof(u8), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_U8_INC(fieldname_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_inc_u8, 0,{._intptr=0}, sizeof(u8), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_STRING(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_string, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_STRING_COPY(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_string_copy, defaultvalue_,{._u32=(sizeof(((CONFIG_TYPE*)NULL)->fieldname_))}, sizeof(((CONFIG_TYPE*)NULL)->fieldname_), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_STRING_ARRAY(fieldname_,default_value_,max_size_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_append_string_array_item, default_value_,{._u32=(max_size_)}, sizeof(ptr_vector), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_PASSWORD(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_password, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_FQDN(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_fqdn, defaultvalue_,{._intptr=0}, sizeof(u8*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_MALLOC }, #define CONFIG_PATH(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_path, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_CHROOT(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_chroot, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_LOGPATH(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_logpath, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_FILE(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_file, defaultvalue_,{._intptr=0}, sizeof(char*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_UID(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_uid_t, defaultvalue_,{._intptr=0}, sizeof(uid_t), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_GID(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_gid_t, defaultvalue_,{._intptr=0}, sizeof(gid_t), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, //#define CONFIG_ACL(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, ac) + offsetof(access_control,fieldname_), (config_set_field_function*)config_set_acl_item, defaultvalue_,{._intptr=0}, sizeof(), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, //#define CONFIG_ACL_FILTER(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_acl_item, defaultvalue_,{._intptr=0}, sizeof(), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, //#define CONFIG_LIST_ITEM(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_add_list_item, defaultvalue_,{._intptr=0}, sizeof(), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_ENUM(fieldname_,defaultvalue_,enumtable_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_enum_value, defaultvalue_, {._intptr=(intptr)(enumtable_)}, sizeof(u32), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, //#define CONFIG_ENUM8(fieldname_,defaultvalue_,enumtable_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_enum8_value, defaultvalue_, {(intptr)enumtable_}, sizeof(u8), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_HOST_LIST(fieldname_,defaultvalue_) {#fieldname_, offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_host_list, defaultvalue_,{._8u8={CONFIG_HOST_LIST_FLAGS_DEFAULT,255,0,0,0,0,0,0}}, sizeof(host_address*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_HOST_LIST_EX(fieldname_,defaultvalue_,flags_,host_list_max_) {#fieldname_, offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_host_list, defaultvalue_,{._8u8={(flags_),(host_list_max_),0,0,0,0,0,0}}, sizeof(host_address*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_BYTES(fieldname_,defaultvalue_,maxsize_) {#fieldname_, offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_bytes, defaultvalue_, {maxsize_}, maxsize_, sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, //#define CONFIG_DNSSEC(fieldname_,defaultvalue_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_dnssec, defaultvalue_,{._intptr=0}, sizeof(), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_TSIG_ITEM(fieldname_,defaultvalue_) {#fieldname_, offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)config_set_tsig_item, defaultvalue_, {._intptr=0}, sizeof(struct tsig_item*), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_OBSOLETE(fieldname_) {#fieldname_,0, (config_set_field_function*)config_set_obsolete, NULL,{._intptr=0}, 0, 0, CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, #define CONFIG_ALIAS(fieldname_, aliasedname_) {#fieldname_, 0, NULL, #aliasedname_, {._intptr=0}, 0, 0, CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT}, /*#define CONFIG_CATEGORY(fieldname_, category_) {#fieldname_, 0, NULL, NULL, #category},*/ #define CONFIG_END(name_) {NULL,0,NULL,NULL, {._intptr=0}, 0, 0, CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT} }; // name_ struct tsig_item; ya_result config_set_bool(const char *value, bool *dest, const anytype notused); ya_result config_set_flag8(const char *value, u8 *dest, const anytype mask8); ya_result config_set_flag16(const char *value, u16 *dest, const anytype mask16); ya_result config_set_flag32(const char *value, u32 *dest, const anytype mask32); ya_result config_set_flag64(const char *value, u64 *dest, const anytype mask64); ya_result config_set_u64(const char *value,u64 *dest, const anytype notused); ya_result config_set_u32(const char *value,u32 *dest, const anytype notused); ya_result config_set_s32(const char *value,s32 *dest, const anytype notused); ya_result config_set_u32_range(const char *value,u32 *dest, const anytype min_max); ya_result config_set_u16(const char *value,u16 *dest, const anytype notused); ya_result config_set_u8(const char *value,u8 *dest, const anytype notused); ya_result config_inc_u8(const char *value_notused,u8 *dest, const anytype notused); ya_result config_set_dnskey_algorithm(const char *value, u8 *dest, const anytype notused); ya_result config_set_string(const char *value, char **dest, const anytype notused); ya_result config_set_string_copy(const char *value, char *dest, const anytype maxlen); ya_result config_append_string_array_item(const char *value, ptr_vector *dest, const anytype maxsize); ya_result config_set_password(const char *value, char **dest, const anytype notused); ya_result config_set_fqdn(const char *value, u8 **dest, const anytype notused); ya_result config_set_path(const char *value, char **dest, const anytype notused); ya_result config_set_chroot(const char *value, char **dest, const anytype notused); ya_result config_set_logpath(const char *value, char **dest, const anytype notused); ya_result config_set_file(const char *value, char **dest, const anytype notused); ya_result config_set_uid_t(const char *value, uid_t *dest, const anytype notused); ya_result config_set_gid_t(const char *value, gid_t *dest, const anytype notused); ya_result config_set_dnstype(const char *value, u16 *dest, const anytype notused); ya_result config_set_dnsclass(const char *value, u16 *dest, const anytype notused); ya_result config_set_enum_value(const char *value, u32 *dest, const anytype enum_value_name_table); ya_result config_set_enum8_value(const char *value, u8 *dest, const anytype enum_value_name_table); ya_result config_set_host_list(const char *value, host_address **dest, const anytype notused); ya_result config_set_bytes(const char *value, void *dest, const anytype sizeoftarget); ya_result config_set_tsig_item(const char *value, struct tsig_item **dest, const anytype notused); ya_result config_set_obsolete(const char *value, void *dest, const anytype sizeoftarget); // life of the config processing void config_init_error_codes(); struct config_error_s { const char *variable_name; u32 line_number; bool has_content; char line[256]; char file[PATH_MAX]; }; typedef struct config_error_s config_error_s; static inline void config_error_reset(config_error_s* cfgerr) { if(cfgerr != NULL) { cfgerr->variable_name = ""; cfgerr->line_number = 0; cfgerr->has_content = FALSE; cfgerr->line[0] = '\0'; cfgerr->file[0] = '\0'; } } #define CONFIG_ERROR_INITIALISER { NULL, 0, "?", "?"} struct config_source_s; typedef ya_result config_source_provider_callback_function(struct config_source_s *source, input_stream *out_source, config_error_s *cfgerr); struct config_source_file_name_s { const char* name; }; struct config_source_buffer_s { const char* text; u32 size; }; /** * An help tool to register many sources at once */ struct config_source_s { config_source_provider_callback_function *get_source; const char *name; const char *__class__; union { struct config_source_file_name_s file_name; struct config_source_buffer_s buffer; } source; u8 level; }; #ifdef TODO struct config_s { u32_set section_descriptor_set = U32_SET_EMPTY; }: #endif ya_result config_init(); /** * Configuration: * * priority : the lowest value, the fastest to be parsed * negative value : choose * * level : ex: 0 for none, 1 for default, 2 for config, 3 for command line * command line has priority on everything else */ /** * Gets the current source level * @return the current source level */ u8 config_get_source(); /** * Sets the current source level * * @param l the current source level */ void config_set_source(u8 l); /** * If the source level has been parsed, automatically fill the default values * for fields that are not set yet. * * @return after what level do we automatically set the default values in the container */ u8 config_get_autodefault_after_source(); /** * If the source level has been parsed, automatically fill the default values * for fields that are not set yet. * * @param l after what level do we automatically set the default values in the container ? */ void config_set_autodefault_after_source(u8 l); // if a configuration is read at this level, the default is automatically applied after /** * Gets the default source level * * @return the default source level */ u8 config_get_default_source(); /** * Sets the default source level (default = 1) * * @param l the default source level */ void config_set_default_source(u8 l); // this level is meant for default (1) #define CONFIG_CALLBACK_RESULT_CONTINUE 0 #define CONFIG_CALLBACK_RESULT_STOP 1 typedef ya_result config_callback_function(const char *section_name, int section_index); /** * Adds a callback called when a section has been read * * @param section_name the name of the section * @param on_section_read the function to call * * * @return continue, stop or an error code to fail */ ya_result config_add_on_section_read_callback(const char *section_name, config_callback_function *on_section_read); /** * Removes a callback called when a section has been read * * @param section_name the name of the section * @param on_section_read the function to call * * @return continue, stop or an error code to fail */ ya_result config_remove_on_section_read_callback(const char *section_name, config_callback_function *on_section_read); /** * Registers a descriptor at the given priority * * @param section_descritor config descriptor * @param priority config priority * * @return an error code */ ya_result config_register(config_section_descriptor_s *section_descritor, s32 priority); ya_result config_register_const(const config_section_descriptor_s *section_descriptor, s32 priority); ya_result config_unregister(config_section_descriptor_s *section_descriptor); config_section_descriptor_s *config_unregister_by_name(const char *name); /** * * Reads matching section/containers from a file on disk * * @param configuration_file_path the file path * @param cfgerr error handling structure (can be NULL) * @param section_name the name to match, or if NULL : all sections * * @return an error code */ ya_result config_read_section(const char *configuration_file_path, config_error_s *cfgerr, const char *section_name); /** * Reads all sections/containers from a file * * @param configuration_file_path the file path * @param cfgerr if not NULL, the error reporting structure * * @return an error code */ ya_result config_read(const char *configuration_file_path, config_error_s *cfgerr); /** * Reads all sections/containers from a buffer * * @param buffer the text buffer * @param buffer_len the text buffer length * @param buffer_name the name of the buffer for error reporting * @param cfgerr if not NULL, the error reporting structure * * @return an error code */ ya_result config_read_from_buffer(const char *buffer, u32 buffer_len, const char *buffer_name, config_error_s *cfgerr); /** * Sets a text buffer in a source * * @param source the source struct to initialise * @param name the name of the source * @param level the level of the source * @param buffer text for the source * @param buffer_len text length for the source */ void config_source_set_buffer(struct config_source_s *source, const char *name, u8 level, const char *buffer, u32 buffer_len); /** * Sets a file in a source * * @param source the source struct to initialise * @param name the name of the file * @param level the level of the source */ void config_source_set_file(struct config_source_s *source, const char *name, u8 level); ya_result config_source_set_commandline(struct config_source_s *source, const cmdline_desc_s *cmdline, int argc, char **argv); /** * Read all sources from a table * * @param sources a pointer to the first source * @param sources_count the number of sources * @param cfgerr if not NULL, the error reporting structure * * @return an error code */ ya_result config_read_from_sources(struct config_source_s *sources, u32 sources_count, config_error_s *cfgerr); /** * Applies default values to uninitialised fields. * @param cfgerr * * @param cfgerr if not NULL, the error reporting structure * * @return an error code */ ya_result config_set_default(config_error_s *cfgerr); /** * Gets the section descriptor for the section/container name * * @param name the name of the section descriptor * * @return a pointer to the section descriptor or NULL if not found */ config_section_descriptor_s *config_section_get_descriptor(const char *name); /** * Sets the table default values * * @param section_descriptor the descriptor to use (points to the table) * @param cfgerr if not NULL, the error reporting structure * * @return an error code */ ya_result config_set_section_default(config_section_descriptor_s *section_descriptor, config_error_s *cfgerr); /** * Sets the key to a value * Source level is taken into account. * ie: config_value_set(&yadifa_config_main_desc, "daemon", "on"); * * @param section_descriptor the descriptor pointing to the table * @param key the key to set * @param value to value to set it to * @param cfgerr a structure that contains details about an error * * @return an error code */ ya_result config_value_set(config_section_descriptor_s *section_descriptor, const char *key, const char *value, config_error_s *cfgerr); ya_result config_source_set_by_target(config_section_descriptor_s *section_descriptor, void *target_ptr); /** * * Sets the key of the section/container to its default value * * @param section_name name of the section * @param name key of the value * @param cfgerr if not NULL, the error reporting structure * * @return an error code */ ya_result config_value_set_to_default(const char *section_name, const char *name, config_error_s *cfgerr); /** * * Returns the source of a value from the given section/container * * Look at CONFIG_SOURCE_* defines above for the predefined sources. * * @param section_name name of the section * @param name key of the value * * @return the source index or an error code */ ya_result config_value_get_source(const char *section_name, const char *name); typedef bool config_section_struct_type_handler(output_stream *os, const char *name, void *ptr); bool config_section_struct_register_type_handler(config_set_field_function* setter, config_section_struct_type_handler *handler); /** * * Prints the content of every supported types of the table using the descriptor * * @param section_descriptor the descriptor * @param os where to print to */ void config_section_print(const config_section_descriptor_s *section_descriptor, output_stream *os); /** * * Prints the content of every supported types of the table using the given descriptor on the given struct * * @param section_descriptor the descriptor * @param a pointer to the config struct base * @param os where to print to */ void config_section_struct_print(const config_section_descriptor_s *section_descriptor, const void* configbase, output_stream *os); /** * * Gets the index of the key on the table * * @param table a config table * @param name the field key name * * @return an error code */ ya_result config_item_index_get(const config_table_descriptor_item_s *table, const char *name); /** * Prints the config to the output stream * * @param os the output stream */ void config_print(output_stream *os); /** * Call the postproces callback on the registered tables */ ya_result config_postprocess(); /** * Call the finalise callback on the registered tables * */ ya_result config_finalize(); // helpers typedef void *config_section_struct_collection_get_next_method(void *previous_data_struct); /** * * Registers a struct with its descriptor and name, for configuration. * * @param name name of the struct * @param table table describing the struct * @param data_struct pointer to the struct * @param priority priority level (order of read) * * @return an error code */ ya_result config_register_struct(const char *name, config_table_descriptor_item_s *table, void *data_struct, s32 priority); void* config_unregister_struct(const char *name, const config_table_descriptor_item_s *table); /** * * Registers the logger configuration. * * @note logger_handle_create("handle-name",logger_handle_for_handle_name_ptr_ptr) MUST be called * before the config_read is done * * @param null_or_channels_name * @param null_or_loggers_name * @param priority * * @return an error code */ ya_result config_register_logger(const char *null_or_channels_name, const char *null_or_loggers_name, s32 priority); /** * Returns TRUE iff any logging section has been found. * * @return TRUE iff any logging section has been found. */ bool config_logger_isconfigured(); /** * Clears the logger-configured flag */ void config_logger_clearconfigured(); /** * Sets the base path for the logger * * @param null_or_key_name * @param priority * @return */ void config_set_log_base_path(const char *path); /** * Registers the key configuration (TSIG) * * @param null_or_key_name * @param priority * @return */ ya_result config_register_key(const char *null_or_key_name, s32 priority); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/counter_output_stream.h0000644000000000000000000000013214505005532026444 xustar000000000000000030 mtime=1695812442.051976588 30 atime=1695812445.788030096 30 ctime=1695812494.187723277 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/counter_output_stream.h0000664000374500037450000000523614505005532026414 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _COUNTER_OUTPUT_STREAM_H #define _COUNTER_OUTPUT_STREAM_H #include #ifdef __cplusplus extern "C" { #endif typedef struct counter_output_stream_data counter_output_stream_data; struct counter_output_stream_data { output_stream* filtered; u64 write_count; u64 written_count; ya_result result; u8 flags; }; void counter_output_stream_init(output_stream* filtered, output_stream* stream,counter_output_stream_data* counter_data); #ifdef __cplusplus } #endif #endif /* _counter_output_stream_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/ctrl-rfc.h0000644000000000000000000000013114505005532023505 xustar000000000000000030 mtime=1695812442.067976817 29 atime=1695812445.78903011 30 ctime=1695812494.189723306 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/ctrl-rfc.h0000664000374500037450000003310614505005532023453 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #define HAS_DYNAMIC_PROVISIONING 0 #define OPCODE_CTRL (9<15 (4 higher bits reserved) ... or don't we set a limit ? */ #define TYPE_CTRL_SRVLOGLEVEL NU16(0x2b05) /* * Q: . ZONEFREEZE CTRL * C: . ZONEFREEZE [fqdn class view] * * if rdata size > 0, rdata is FQDN [2 bytes] [0->n utf8/asciiz? bytes] */ #define TYPE_CTRL_ZONEFREEZE NU16(0x2b06) /* * Q: . ZONEUNFREEZE CTRL * C: . ZONEUNFREEZE [fqdn class view] * * if rdata size > 0, rdata is FQDN [2 bytes] [0->n utf8/asciiz? bytes] */ #define TYPE_CTRL_ZONEUNFREEZE NU16(0x2b07) /* * Q: . ZONESYNC CTRL * C: . ZONESYNC clean [fqdn class view] * * clean is one byte, values 0->1 (7 higher bits reserved) * if rdata size > 0, rdata is FQDN [2 bytes] [0->n utf8/asciiz? bytes] */ #define TYPE_CTRL_ZONESYNC NU16(0x2b08) /* * Q: . ZONENOTIFY CTRL * C: . ZONENOTIFY fqdn [class view] * * rdata is FQDN [2 bytes] [0->n utf8/asciiz? bytes] */ #define TYPE_CTRL_ZONENOTIFY NU16(0x2b09) /* * Q: . ZONERELOAD CTRL * C: . ZONERELOAD fqdn class view * * rdata is FQDN [2 bytes] [0->n utf8/asciiz? bytes] */ #define TYPE_CTRL_ZONERELOAD NU16(0x2b0a) /* * Q: . ZONECFGRELOAD CTRL * C: . ZONECFGRELOAD [fqdn [class [view]]] * * rdata is FQDN [2 bytes] [0->n utf8/asciiz? bytes] */ #define TYPE_CTRL_ZONECFGRELOAD NU16(0x2b0b) #define TYPE_CTRL_ZONECFGRELOADALL NU16(0x2b0c) /* DOMAIN NAME = zone */ /* RDATASIZE = 0 */ #define TYPE_CTRL_ZONEFREEZEALL NU16(0x2b0d) /* DOMAIN NAME = zone */ /* RDATASIZE = 0 */ #define TYPE_CTRL_ZONEUNFREEZEALL NU16(0x2b0e) /* DOMAIN NAME = . */ /* RDATASIZE = 0 */ /** * @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/debug.h0000644000000000000000000000013214505005531023057 xustar000000000000000030 mtime=1695812441.994975772 30 atime=1695812445.787030082 30 ctime=1695812494.191723334 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/debug.h0000664000374500037450000002421714505005531023027 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup debug Debug functions * @ingroup dnscore * @brief Debug functions. * * Definitions of debug functions/hooks, mainly memory related. * * THIS MEMORY DEBUGGER MUST BE INCLUDED WITH EVERY SINGLE (C) FILE. * IF DEBUGGING MEMORY ALLOCATION IS USED, IT HAS TO BE ENABLED EVERYWHERE OR NOWHERE. * * @{ */ #ifndef _DEBUG_H #define _DEBUG_H #include #ifndef _SYSTYPES_H #error PLEASE DO NOT INCLUDE debug.h DIRECTLY. USE sys_types.h. #endif #define DEBUG_STAT_SIZES 1 // Common #define DEBUG_STAT_TAGS 2 // Usefull #define DEBUG_STAT_DUMP 4 // USE WITH CARE #define DEBUG_STAT_WALK 8 #define DEBUG_STAT_MMAP 16 #include #include #include /** @note : DO NOT INCLUDE THIS HERE WITHOUT SOME KIND OF PROTECTION #include */ #include #if DNSCORE_HAS_MMAP_DEBUG_SUPPORT // MUST be included before else the defines will break the build #include //#pragma message("MMAP REROUTED") void* debug_mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); int debug_munmap(void *addr, size_t len); void debug_mmap_stat(); #define mmap(addr__,len__,prot__,flags__,fildes__,off__) debug_mmap((addr__),(len__),(prot__),(flags__),(fildes__),(off__)) #define munmap(addr__,len__) debug_munmap((addr__),(len__)) #endif #if DEBUG #include #endif #if !DEBUG #define yassert(x) #else void log_assert__(bool b, const char *txt, const char *file, int line); #if !__clang_analyzer__ #define yassert(cond__) log_assert__((cond__), #cond__, __FILE__, __LINE__);assert((cond__)) #else #define yassert(cond__) assert(cond__) #endif #endif #ifdef __cplusplus extern "C" { #endif #define GENERIC_TAG 0x434952454e4547 /* GENERIC */ #define ZDB_STRDUP_TAG 0x505544525453 /* "STRDUP" */ void debug_dump(void* data_pointer_,size_t size,size_t line_size,bool hex,bool text); void debug_dump_ex(void* data_pointer_, size_t size_, size_t line_size, bool hex, bool text, bool address); struct logger_handle; bool debug_log_stacktrace(struct logger_handle *handle, u32 level, const char *prefix); #if DEBUG /* * DO NOT FORGET THAT THE "L" FUNCTIONS DO REQUIRE A DEBUG_LEVEL #define * BEFORE THE "debug.h" INCLUDE ! */ #define DEBUGLNF(...) osformatln(termerr,__VA_ARGS__) #define DEBUGF(...) osformat(termerr,__VA_ARGS__) #define OSDEBUG(term, ...) osformat((term),__VA_ARGS__) #define LDEBUG(level, ...) if(DEBUG_LEVEL>=(level)) osformat(termerr,__VA_ARGS__) #define OSLDEBUG(term, level, ...) if(DEBUG_LEVEL>=(level)) osformat((term),__VA_ARGS__) #else #define DEBUGLNF(...) #define DEBUGF(...) #define OSDEBUG(...) #define LDEBUG(...) #define OSLDEBUG(...) #endif #ifndef DNSCORE_HAS_MALLOC_DEBUG_SUPPORT #error "bogus include sequence" #endif void debug_stat(int mask); #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT #ifndef MALLOC_OR_DIE #error "something fishy is happening. MALLOC_OR_DIE has not been defined yet." #endif #ifndef REALLOC_OR_DIE #error "something fishy is happening. REALLOC_OR_DIE has not been defined yet." #endif #undef MALLOC_OR_DIE #undef REALLOC_OR_DIE void* debug_malloc( size_t size_,const char* file, int line #if DNSCORE_DEBUG_HAS_BLOCK_TAG ,u64 tag #endif ); void* debug_calloc( size_t size_,const char* file, int line #if DNSCORE_DEBUG_HAS_BLOCK_TAG ,u64 tag #endif ); void* debug_realloc( void* ptr_, size_t size_, const char* file, int line ); bool debug_mallocated(void* ptr); #define assert_mallocated(ptr) yassert(debug_mallocated(ptr)) void debug_free(void* ptr,const char* file, int line); void debug_mtest(void* ptr); char* debug_strdup(const char*); u32 debug_get_block_count(); #ifdef strdup #undef strdup #endif #define strdup debug_strdup #if !DNSCORE_DEBUG_HAS_BLOCK_TAG #define malloc(len__) debug_malloc((len__),__FILE__,__LINE__) #define calloc(len__) debug_calloc((len__),__FILE__,__LINE__) #define free(p__) debug_free((p__),__FILE__,__LINE__) #define realloc(p__,len__) debug_realloc((p__),(len__),__FILE__,__LINE__) #define MALLOC_OR_DIE(cast,target,size,tag) if(((target)=(cast)debug_malloc(size,__FILE__,__LINE__))==NULL){perror(__FILE__);abort(); /* NOT TAGGED*/ } #define REALLOC_OR_DIE(cast,src_and_target,newsize,tag) if(((src_and_target)=(cast)debug_realloc((src_and_target),(newsize),__FILE__,__LINE__))==NULL){perror(__FILE__);abort(); /* NOT TAGGED */ } #else #define DBGALLOC_TAG 0x434f4c4c41474244 #define malloc(len__) debug_malloc((len__),__FILE__,__LINE__,DBGALLOC_TAG) #define free(p__) debug_free((p__),__FILE__,__LINE__) #define realloc(p__,len__) debug_realloc((p__),(len__),__FILE__,__LINE__) #define MALLOC_OR_DIE(cast,target,size,tag) if(((target)=(cast)debug_malloc(size,__FILE__,__LINE__,(tag)))==NULL){perror(__FILE__);abort(); /* TAGGED */} #define REALLOC_OR_DIE(cast,src_and_target,newsize,tag) if(((src_and_target)=(cast)debug_realloc((src_and_target),(newsize),__FILE__,__LINE__))==NULL){perror(__FILE__);abort(); /* NOT TAGGED */ } #endif #else #define debug_mtest(x) #define debug_mallocated(x) TRUE #define assert_mallocated(x) #if !(DNSCORE_HAS_MALLOC_DEBUG_SUPPORT || DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT || DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT || DNSCORE_HAS_MMAP_DEBUG_SUPPORT) #define debug_stat(x) #endif /* * MALLOC_OR_DIE and REALLOC_OR_DIE have already been defined in sys_types.h */ #endif struct debug_bench_s { struct debug_bench_s *next; const char *name; u64 time_min; u64 time_max; u64 time_total; u64 time_count; }; typedef struct debug_bench_s debug_bench_s; struct output_stream; struct logger_handle; // declares timeus() s64 timeus(); void debug_bench_init(); void debug_bench_register(debug_bench_s *bench, const char *name); #define debug_bench_start(bench__) timeus() #define debug_bench_stop(bench__, from__) debug_bench_commit((bench__), timeus() - (from__)); void debug_bench_commit(debug_bench_s *bench, u64 delta); void debug_bench_logdump_all(); void debug_bench_print_all(struct output_stream *os); void debug_bench_unregister_all(); typedef intptr* stacktrace; stacktrace debug_stacktrace_get_ex(int index); stacktrace debug_stacktrace_get(); // debug_stacktrace_get_ex(1) void debug_stacktrace_log(struct logger_handle *handle, u32 level, stacktrace trace); void debug_stacktrace_log_with_prefix(struct logger_handle* handle, u32 level, stacktrace trace, const char *prefix); void debug_stacktrace_try_log(struct logger_handle *handle, u32 level, stacktrace trace); void debug_stacktrace_print(struct output_stream *os, stacktrace trace); /** * clears all stacktraces from memory * should only be called at shutdown */ void debug_stacktrace_clear(); #define UNICITY_DEFINE(x) #define UNICITY_ACQUIRE(x) #define UNICITY_RELEASE(x) #if DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT extern volatile size_t malloc_hook_total; extern volatile size_t malloc_hook_malloc; extern volatile size_t malloc_hook_free; extern volatile size_t malloc_hook_realloc; extern volatile size_t malloc_hook_memalign; #endif void debug_malloc_hooks_init(); void debug_malloc_hooks_finalize(); void *debug_malloc_unmonitored(size_t size); void *debug_realloc_unmonitored(void* ptr, size_t size); void debug_free_unmonitored(void* ptr); void *debug_memalign_unmonitored(size_t alignment, size_t size); void debug_malloc_hook_tracked_dump(); void debug_malloc_hook_caller_dump(); void *debug_mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); void debug_dump_page(void* ptr); struct debug_memory_by_tag_context_s; typedef struct debug_memory_by_tag_context_s debug_memory_by_tag_context_t; #if DNSCORE_DEBUG_HAS_BLOCK_TAG debug_memory_by_tag_context_t* debug_memory_by_tag_new_instance(const char* name); void debug_memory_by_tag_delete(debug_memory_by_tag_context_t *ctx); void debug_memory_by_tag_init(debug_memory_by_tag_context_t *ctx, const char* name); void debug_memory_by_tag_finalize(debug_memory_by_tag_context_t *ctx); void debug_memory_by_tag_alloc_notify(debug_memory_by_tag_context_t *ctx, u64 tag, s64 size); void debug_memory_by_tag_free_notify(debug_memory_by_tag_context_t *ctx, u64 tag, s64 size); void debug_memory_by_tag_print(debug_memory_by_tag_context_t *ctx, struct output_stream *os); #endif void debug_memory_stat(int mask); #ifdef __cplusplus } #endif #endif /* _DEBUG_H */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/debug_config.h0000644000000000000000000000013214505005532024405 xustar000000000000000030 mtime=1695812442.088977118 30 atime=1695812445.790030125 30 ctime=1695812494.194723377 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/debug_config.h0000664000374500037450000000775414505005532024364 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup debug Debug functions * @ingroup dnscore * @brief Debug functions settings * * @{ */ #ifndef _DEBUG_CONFIG_H #define _DEBUG_CONFIG_H /** * * DEBUG: Enables (1) or disables (0) dumping each time a malloc of a free * is called. * Recommende value: FALSE */ #define DNSCORE_DEBUG_SHOW_ALLOCS FALSE #if DEBUG #ifdef __cplusplus extern "C" { #endif /** * These settings COULD be set by the configure * But given the nature of these flags, I don't think it would be a good idea. * */ /** * * DEBUG: Enables (1) or disables (0) the internal memory debugging. * * Recommended value: 0 * */ /** * Freed memory is trashed */ #define DNSCORE_DEBUG_MALLOC_TRASHMEMORY 1 /** * * DEBUG: Enables (1) or disables (0) the additional memory debugging. * This feature has been used to configure the ZMALLOC page sizes for * each line size. * * Recommended value: 1 */ #define DNSCORE_DEBUG_ENHANCED_STATISTICS 1 /** * * DEBUG: Sets the maximum block size (8 bytes granularity) that is taken * in account in the DNSCORE_DEBUG_ENHANCED_STATISTICS==1 mode. * Blocks bigger than this are all grouped in a "+++" group. * * Recommended value: 256 */ #define DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE 8192 /** * DEBUG: Sets a limit on the memory available for the database. * Debug overhead is not taken in account here. * * 1GB should be enough. * * Recommended value: 0x40000000 * */ #define DNSCORE_DEBUG_ALLOC_MAX 0x200000000LL // 8GB /** * DEBUG: Enables block chaining (RECOMMENDED) * * Recommended value: 1 */ #define DNSCORE_DEBUG_CHAIN_ALLOCATED_BLOCKS 1 /** * DEBUG: Enable memory block tagging * * Recommended value: 1 */ #define DNSCORE_DEBUG_HAS_BLOCK_TAG 1 /** * DEBUG: Each block has got an "unique" serial id of 64 bits. * * Recommended value: 1 */ #define DNSCORE_DEBUG_SERIALNUMBERIZE_BLOCKS 1 /** * DEBUG: measure timings on open/close/... */ #define DNSCORE_DEBUG_KEEP_STACKTRACE 1 #if DEBUG #define DEBUG_BENCH_FD 1 #else // !DEBUG #define DEBUG_BENCH_FD 0 #endif // DEBUG #ifdef __cplusplus } #endif #else // !DEBUG #define DEBUG_BENCH_FD 0 #endif // DEBUG #endif /* _DEBUG_CONFIG_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/digest.h0000644000000000000000000000013014505005531023246 xustar000000000000000028 mtime=1695812441.9899757 30 atime=1695812445.786030067 30 ctime=1695812494.196723406 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/digest.h0000664000374500037450000001221214505005531023210 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup digest Cryptographic digest functions. * @ingroup dnscore * @brief Cryptographic digest functions. * * Cryptographic digest functions: SHA0, SHA1, SHA256, SHA384 SHA512 * * They are very simple and self-explanatory wrappers around the cryptographic * library (currently : openssl) * Hence the small specific C-files are not documented. * * Adding more would be trivial but these are the only ones needed for DNS at * this point. * * @{ */ #pragma once #include #include #include #include #define DIGEST_BUFFER_SIZE 128 struct digest_s; typedef s32 digest_update_method(struct digest_s*,const void*, u32); typedef s32 digest_final_method(struct digest_s*); // finishes computing the digest typedef s32 digest_sha1_final_copy_bytes_method(struct digest_s*, void*, u32); typedef s32 digest_get_size_method(struct digest_s*); typedef s32 digest_get_digest_method(struct digest_s*, void**); typedef void digest_finalise_method(struct digest_s*); // destroys the object, frees resources struct digest_vtbl { digest_update_method* update; digest_final_method* final; digest_sha1_final_copy_bytes_method* final_copy_bytes; digest_get_size_method* get_size; digest_get_digest_method* get_digest; digest_finalise_method *finalise; const char * __class__; }; struct digest_rawdata_ctx { bytearray_output_stream_context baos_ctx; output_stream baos; // accumulates bytes (EDDSA) // total: about 11 pointers u8 data[sizeof(SHA512_CTX) - sizeof(output_stream) - sizeof(bytearray_output_stream_context)]; }; struct digest_s { const struct digest_vtbl *vtbl; union { SHA_CTX sha0; SHA_CTX sha1; SHA256_CTX sha256; SHA512_CTX sha384; /// @note 20160202 edf -- there is no SHA384_CTX, SHA512_CTX must be used SHA512_CTX sha512; struct digest_rawdata_ctx rawdata; } ctx; u8 digest[DIGEST_BUFFER_SIZE]; // used so the caller does not need to keep a copy of the digest. }; typedef struct digest_s digest_s; #define digest_class(is_) ((is_)->vtbl) #define digest_class_name(is_) ((is_)->vtbl->__class__) #define digest_update(ctx_,buffer_,len_) (ctx_)->vtbl->update(ctx_,buffer_,len_) #define digest_final(ctx_) (ctx_)->vtbl->final(ctx_) #define digest_final_copy_bytes(ctx_,buffer_,buffer_size_) (ctx_)->vtbl->final_copy_bytes((ctx_),(buffer_),(buffer_size_)) #define digest_get_size(ctx_) (ctx_)->vtbl->get_size(ctx_) #define digest_get_digest(ctx_,ptr_) (ctx_)->vtbl->get_digest((ctx_),(ptr_)) #define digest_finalise(ctx_) (ctx_)->vtbl->finalise(ctx_) static inline void digest_copy_bytes(digest_s *ctx, void *buffer) { void *digest_bytes; s32 size = digest_get_digest(ctx, &digest_bytes); memcpy(buffer, digest_bytes, size); } static inline void* digest_get_digest_ptr(digest_s *ctx) { void *digest_bytes; digest_get_digest(ctx, &digest_bytes); return digest_bytes; } #ifndef OPENSSL_NO_SHA1 void digest_sha1_init(digest_s *ctx); #endif #ifndef OPENSSL_NO_SHA256 void digest_sha256_init(digest_s *ctx); #endif #ifndef OPENSSL_NO_SHA512 void digest_sha384_init(digest_s *ctx); void digest_sha512_init(digest_s *ctx); #endif void digest_rawdata_init(digest_s *ctx); #ifndef OPENSSL_NO_SHA0 void digest_sha0_init(digest_s *ctx); #endif yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dns-udp.h0000644000000000000000000000013114505005532023343 xustar000000000000000030 mtime=1695812442.065976789 29 atime=1695812445.78903011 30 ctime=1695812494.198723435 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dns-udp.h0000664000374500037450000002210614505005532023307 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #ifndef DNS_UDP_H #define DNS_UDP_H #include #include #include #include // error codes #define DNS_UDP_TIMEOUT ((s32)0x81000001) #define DNS_UDP_INTERNAL ((s32)0x81000002) #define DNS_UDP_CANCEL ((s32)0x81000003) // #define DNS_UDP_TIMEOUT_US 3000000 // 3s #define DNS_UDP_TIMEOUT_US_MIN 1000000 // 1s #define DNS_UDP_TIMEOUT_US_MAX 3600000000// 1h #define DNS_UDP_SEND_RATE 1000 // 1000 queries/s #define DNS_UDP_SEND_BANDWIDTH 1000000 // 1MB/s #define DNS_UDP_RECV_BANDWIDTH 1000000 // 1MB/s #define DNS_UDP_SEND_RATE_MIN 1 // q/s #define DNS_UDP_SEND_RATE_MAX 1000000 // q/s #define DNS_UDP_SEND_BANDWIDTH_MIN 512 // 512B/s #define DNS_UDP_SEND_BANDWIDTH_MAX 100000000 // 100MB/s #define DNS_UDP_RECV_BANDWIDTH_MIN 512 // 512B/s #define DNS_UDP_RECV_BANDWIDTH_MAX 100000000 // 100MB/s #define DNS_UDP_SEND_QUEUE 200000 // 200000 messages #define DNS_UDP_SEND_QUEUE_MIN 1 #define DNS_UDP_SEND_QUEUE_MAX 0x1000000 // 16.7M messages #define DNS_UDP_PORT_COUNT 256 // A.K.A workers #define DNS_UDP_PORT_COUNT_MIN 1 #define DNS_UDP_PORT_COUNT_MAX 4000 #define DNS_UDP_RETRY_COUNT 2 // tries after the first failure #define DNS_UDP_RETRY_COUNT_MIN 0 #define DNS_UDP_RETRY_COUNT_MAX 16 #define DNS_UDP_PER_DNS_RATE 5 // packets per second #define DNS_UDP_PER_DNS_RATE_MIN 1 #define DNS_UDP_PER_DNS_RATE_MAX 65536 #define DNS_UDP_PER_DNS_BANDWIDTH 4096 // bytes per second #define DNS_UDP_PER_DNS_BANDWIDTH_MIN 512 #define DNS_UDP_PER_DNS_BANDWIDTH_MAX 65536 #define DNS_UDP_PER_DNS_FREQ_MIN 10000 // us between two queries #define DNS_UDP_PER_DNS_FREQ_MIN_MIN 0 #define DNS_UDP_PER_DNS_FREQ_MIN_MAX 1000000 #define DNS_UDP_READ_BUFFER_COUNT 4096 #define DNS_UDP_READ_BUFFER_COUNT_MIN 1 #define DNS_UDP_READ_BUFFER_COUNT_MAX 8192 #define DNS_UDP_TCP_THREAD_POOL_SIZE 1 #define DNS_UDP_TCP_THREAD_POOL_MIN 1 #define DNS_UDP_TCP_THREAD_POOL_MAX 64 #define DNS_UDP_TCP_FALLBACK_ON_TIMEOUT 0 #define DNS_UDP_CALLBACK_THREAD_COUNT 4 #define DNS_UDP_CALLBACK_THREAD_COUNT_MIN 1 #define DNS_UDP_CALLBACK_THREAD_COUNT_MAX 8 #define DNS_UDP_CALLBACK_QUEUE_SIZE 0x100000 #define DNS_UDP_CALLBACK_QUEUE_SIZE_MIN 0x1000 #define DNS_UDP_CALLBACK_QUEUE_SIZE_MAX 0x1000000 #define DNS_SIMPLE_MESSAGE_HAS_WAIT_COND 0 #define DNS_SIMPLE_MESSAGE_FLAGS_DNSSEC MESSAGE_EDNS0_DNSSEC #define DNS_SIMPLE_MESSAGE_STATUS_QUEUED 0x01 #define DNS_SIMPLE_MESSAGE_STATUS_COLLECTED 0x02 #define DNS_SIMPLE_MESSAGE_STATUS_SENT 0x04 #define DNS_SIMPLE_MESSAGE_STATUS_AGGREGATED 0x08 #define DNS_SIMPLE_MESSAGE_STATUS_RECEIVED 0x10 #define DNS_SIMPLE_MESSAGE_STATUS_TIMEDOUT 0x20 #define DNS_SIMPLE_MESSAGE_STATUS_FAILURE 0x40 #define DNS_SIMPLE_MESSAGE_STATUS_INVALID 0x80 struct dns_udp_settings_s { s64 timeout; u32 send_rate; u32 send_bandwidth; u32 recv_bandwidth; u32 queue_size; u32 port_count; u32 retry_count; u32 per_dns_rate; u32 per_dns_bandwidth; u32 per_dns_freq_min; u32 udp_read_buffer_count; u32 callback_queue_size; u8 callback_thread_count; u8 tcp_thread_pool_size; bool tcp_fallback_on_timeout; }; typedef struct dns_udp_settings_s dns_udp_settings_s; // reference count common to all dns_simple_message (aggregation of answer for same query) struct dns_simple_message_async_node_s { struct dns_simple_message_async_node_s *next; async_message_s *async; }; typedef struct dns_simple_message_async_node_s dns_simple_message_async_node_s; /* * This is basically a DNS query descriptor (retries and all) */ struct dns_simple_message_s { host_address *name_server; message_data *answer; // answer, can be shared dns_simple_message_async_node_s async_node; volatile s64 queued_time_us; volatile s64 sent_time_us; volatile s64 received_time_us; smp_int rc; // number of references for this message group_mutex_t mtx; volatile thread_t owner; int sender_socket; // used so a repeated message will be sent from the same address:port u32 worker_index; // seems to be only useful to get the priority queue index u16 qtype; u16 qclass; u16 flags; u16 source_port; // seems useless u16 dns_id; s8 retries_left; volatile u8 status; u8 recurse:1,tcp:1,tcp_used:1,tcp_replied:1; //bool recurse; //bool tcp; // try TCP u8 fqdn[MAX_DOMAIN_LENGTH]; }; typedef struct dns_simple_message_s dns_simple_message_s; /** * This needs to be called before dns_udp_handler_init() or some settings will not be taken * into account * * @param settings that will be used by the dns_udp handler */ void dns_udp_handler_configure(const dns_udp_settings_s *settings); void dns_udp_handler_host_limit_set(const host_address* name_server, u32 rate, u32 bandwidth, u32 freq_min); int dns_udp_handler_init(); int dns_udp_handler_start(); int dns_udp_handler_stop(); int dns_udp_handler_finalize(); /** * Cancels all pending queries. * Their handlers will be called with the error message DNS_UDP_CANCEL * The purpose is cleaning up before shutdown. */ void dns_udp_cancel_all_queries(); void dns_udp_send_simple_message(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass, u16 flags, async_done_callback *cb, void* cbargs); void dns_udp_send_recursive_message(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass, u16 flags, async_done_callback *cb, void* cbargs); ya_result dns_udp_send_simple_message_sync(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass,u16 flags, dns_simple_message_s **to_release); ya_result dns_udp_send_recursive_message_sync(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass,u16 flags, dns_simple_message_s **to_release); bool dns_udp_simple_message_trylock(dns_simple_message_s *simple_message); void dns_udp_simple_message_lock(dns_simple_message_s *simple_message); void dns_udp_simple_message_unlock(dns_simple_message_s *simple_message); void dns_udp_simple_message_retain(dns_simple_message_s *simple_message); void dns_udp_simple_message_release(dns_simple_message_s *simple_message); static inline const message_data *dns_udp_simple_message_get_answer(const dns_simple_message_s *simple_message) { return simple_message->answer; } u32 dns_udp_send_queue_size(); u32 dns_udp_pending_queries_count(); u32 dns_udp_pending_feedback_count(); /** */ typedef bool dns_udp_query_hook(dns_simple_message_s *simple_message, message_data *mesg); /** * Sets a hook for queries. * * The hook is called by the service on each messages and is expected to answer * TRUE if it wrote an answer on it * FALSE if it did not * * Every use of the dns_udp service is affected by this. * Only one hook is possible at a given time. * * @param hook a function or NULL to reset to no HOOK. */ void dns_udp_set_query_hook(dns_udp_query_hook *hook); /** * * Mark a simple message as being timed-out * Meant for use in hooks. * Use with care. * * @param simple_message */ void dns_udp_mark_as_timedout(dns_simple_message_s *simple_message); #endif // DNS_UDP_H yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dns_resource_record.h0000644000000000000000000000013214505005532026023 xustar000000000000000030 mtime=1695812442.028976259 30 atime=1695812445.788030096 30 ctime=1695812494.200723463 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dns_resource_record.h0000664000374500037450000001276214505005532025775 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore * @ingroup dnscore * @brief Wire resource record reader * * Wire resource record reader * * @{ */ #pragma once #include #include #include #include #define DNSRREC_TAG 0x5f43455252534e44 #define DNSRRDAT_TAG 0x5441445252534e44 typedef struct dns_resource_record dns_resource_record; struct dns_resource_record { u8 *rdata; /* allocated, grows */ struct type_class_ttl_rdlen tctr; /* I used this already known structure to make passing theses values easier */ u16 rdata_size; u16 rdata_buffer_size; u8 name_len; /* dnsname_len(name) */ u8 name[MAX_DOMAIN_LENGTH]; }; void dns_resource_record_init(dns_resource_record *rr); ya_result dns_resource_record_init_record(dns_resource_record *rr, const u8* fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size, const u8 *rdata); ya_result dns_resource_init_from_record(dns_resource_record *rr, const dns_resource_record *src); ya_result dns_resource_set_from_record(dns_resource_record *rr, const dns_resource_record *src); void dns_resource_record_clear(dns_resource_record *rr); static inline void dns_resource_record_finalize(dns_resource_record *rr) { dns_resource_record_clear(rr); } ya_result dns_resource_record_set_fqdn(dns_resource_record *rr, const u8* fqdn); ya_result dns_resource_record_set_record(dns_resource_record *rr, const u8* fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size, const u8 *rdata); /** * * This utility function reads an uncompressed record from a stream. * Compression has to be handled by the underlying input_stream * If an error code is returned, then most likely the stream is broken. * * @param is * @param rr * * @return an error code or the number of bytes read */ ya_result dns_resource_record_read(dns_resource_record *rr, input_stream *is); /** * * This utility function writes an uncompressed record to a stream. * Compression has to be handled by the underlying output_stream * If an error code is returned, then most likely the stream is broken. * * @param os * @param rr * * @return an error code or the number of bytes written */ ya_result dns_resource_record_write(const dns_resource_record *rr, output_stream *os); bool dns_resource_record_equals(const dns_resource_record *a, const dns_resource_record *b); bool dns_resource_record_match(const dns_resource_record *a, const dns_resource_record *b); int dns_resource_record_compare(const dns_resource_record *a, const dns_resource_record *b); int ptr_set_dns_resource_record_node_compare(const void *node_a, const void *node_b); /** * WARNING, this function does not preserve the content of the buffer. */ static inline void dns_resource_record_ensure_size(dns_resource_record *a, u16 size) // does not preserve buffer content { if(a->rdata_buffer_size < size) { free(a->rdata); a->rdata_buffer_size = (size + 7) & ~7; MALLOC_OBJECT_ARRAY_OR_DIE(a->rdata, u8, a->rdata_buffer_size, DNSRRDAT_TAG); //a->rdata = (u8*)malloc(a->rdata_buffer_size); } } static inline dns_resource_record *dns_resource_record_new_instance() { dns_resource_record *rr; ZALLOC_OBJECT_OR_DIE(rr, dns_resource_record, DNSRREC_TAG); dns_resource_record_init(rr); return rr; } static inline void dns_resource_record_free(dns_resource_record *rr) { dns_resource_record_finalize(rr); ZFREE_OBJECT(rr); } struct resource_record_view; void dns_resource_record_resource_record_view_init(struct resource_record_view *rrv); void dns_resource_record_resource_record_view_finalise(struct resource_record_view *rrv); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnscore.h0000644000000000000000000000013214505005531023426 xustar000000000000000030 mtime=1695812441.999975843 30 atime=1695812445.787030082 30 ctime=1695812494.202723492 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnscore.h0000664000374500037450000001435114505005531023374 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore System core functions * @brief System core functions * * @{ */ #ifndef _DNSCORE_H #define _DNSCORE_H #include #ifndef __DNSCORE_C__ #ifdef __cplusplus extern "C" output_stream __termout__; extern "C" output_stream __termerr__; extern "C" logger_handle *g_system_logger; #else extern output_stream __termout__; extern output_stream __termerr__; struct logger_handle; extern struct logger_handle *g_system_logger; #endif static inline void flushout() { output_stream_flush(&__termout__); } static inline void flusherr() { output_stream_flush(&__termerr__); } #define termout &__termout__ #define termerr &__termerr__ #endif #ifdef __cplusplus extern "C" { #endif /* * This fingerprint feature has been added so libraries could check they are compatible */ typedef enum { DNSCORE_TSIG=1, DNSCORE_ACL=2, DNSCORE_NSEC=4, DNSCORE_NSEC3=8, DNSCORE_ZALLOC=16, DNSCORE_DEBUG=32 } dnscore_fingerprint; u32 dnscore_fingerprint_mask(); static inline dnscore_fingerprint dnscore_getmyfingerprint() { dnscore_fingerprint ret = (dnscore_fingerprint)(0 #if DNSCORE_HAS_TSIG_SUPPORT | DNSCORE_TSIG #endif #if DNSCORE_HAS_ACL_SUPPORT | DNSCORE_ACL #endif #if DNSCORE_HAS_NSEC_SUPPORT | DNSCORE_NSEC #endif #if DNSCORE_HAS_NSEC3_SUPPORT | DNSCORE_NSEC3 #endif #if DNSCORE_HAS_ZALLOC_SUPPORT | DNSCORE_ZALLOC #endif #if DEBUG | DNSCORE_DEBUG #endif ) ; return ret; } dnscore_fingerprint dnscore_getfingerprint(); // Required by DNSCORE_TTY_BUFFERED and DNSCORE_LOGGER: a thread will periodically // do some tasks. Required by the alarm mechanism. #define DNSCORE_TIMER_THREAD 0x02000000 // default: 5 seconds #define DNSCORE_TIMER_PERIOD(seconds__) (((u32)((seconds__)&0x3f)) << (32 - 6)) // The logging system will be initialised. Default points to the TTY. #define DNSCORE_LOGGER 0x00000001 // logging mechanism // Enables initialisation of SSL, dns keys, digests, ... #define DNSCORE_CRYPTO 0x00000002 // Enables initialisation of DNS-related structures (RFC, dns format class for the *format*() calls, ...) #define DNSCORE_DNS 0x00000004 // DNS specific initialisation (specific formats, keyrings, ...) // Enables the use of ZALLOC calls. Without this calling a ZALLOC call will give undefined results (a.k.a: crash) #define DNSCORE_ZALLOC 0x00000008 #define DNSCORE_ALARM 0x00000010 // The TTY output will be flushed every timer tick // else the TTY output will be buffered by line ('\r' or '\n') // default: on #define DNSCORE_TTY_BUFFERED 0x00000020 #define DNSCORE_SOCKET_SERVER 0x00000040 #define DNSCORE_SHARED_HEAP 0x00000080 #define DNSCORE_TCP_MANAGER 0x00000100 #define DNSCORE_MOST (DNSCORE_TIMER_THREAD|DNSCORE_TIMER_PERIOD(5)|DNSCORE_LOGGER|DNSCORE_CRYPTO|DNSCORE_DNS|DNSCORE_ZALLOC|DNSCORE_ALARM|DNSCORE_TTY_BUFFERED|DNSCORE_SHARED_HEAP) #define DNSCORE_TINYRUN (DNSCORE_DNS|DNSCORE_ZALLOC) #define DNSCORE_ALL (DNSCORE_MOST|DNSCORE_SOCKET_SERVER|DNSCORE_TCP_MANAGER) /** * * argc can be 0 and argv can be NULL */ void dnscore_init_ex(u32 features, int argc, char **argv); void dnscore_init(); u32 dnscore_get_active_features(); u32 dnscore_timer_get_tick(); void dnscore_reset_timer(); void dnscore_stop_timer(); void dnscore_finalize(); void dnscore_shutdown(); bool dnscore_shuttingdown(); void dnscore_signature_check(int so_mutex_t, int so_group_mutex_t); size_t dnscore_ipc_make_name(const char *suffix, char *out_buffer, size_t out_buffer_size); void stdstream_detach_fds(); /** * Will try to find a FD in MT(BUFFER(FILE(fd))) * Returns true if it has been found (valid or invalid) * * @param os * @return true iff there is an fd at the bottom. */ bool stdstream_is_tty(output_stream *os); #define DNSCORE_API_CHECK() dnscore_signature_check(sizeof(mutex_t), sizeof(group_mutex_t)) void dnscore_hookme(); // debugging tool : this function can be used as a single breakpoint struct dnscore_meminfo_s { s64 page_size; s64 page_count; s64 total_memory; s64 rss_current; s64 rss_max; s64 program_memory_limit; }; typedef struct dnscore_meminfo_s dnscore_meminfo_t; const dnscore_meminfo_t* dnscore_meminfo_get(dnscore_meminfo_t *mi); #ifdef __cplusplus } #endif #endif /* _DNSCORE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnscore-release-date.h0000644000000000000000000000013114505005532025757 xustar000000000000000030 mtime=1695812442.112977462 30 atime=1695812445.790030125 29 ctime=1695812494.20472352 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnscore-release-date.h0000664000374500037450000000007114505005532025720 0ustar00signersigner00000000000000#pragma #define YADIFA_DNSCORE_RELEASE_DATE "2023-09-06" yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnsformat.h0000644000000000000000000000013214505005532023767 xustar000000000000000030 mtime=1695812442.044976488 30 atime=1695812445.788030096 30 ctime=1695812494.206723549 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnsformat.h0000664000374500037450000000503214505005532023731 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup format C-string formatting * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _DNSFORMAT_H #define _DNSFORMAT_H /* * Format extensions related to dns * * dnsname : u8* dns name * dnslabel : u8* dns label (pascal string) * class : u16* zone class * type : u16* record type */ #ifdef __cplusplus extern "C" { #endif void netformat_class_init(); void dnsformat_class_init(); void dnsname_format_handler_method(const void *val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters); #ifdef __cplusplus } #endif #endif /* _DNSFORMAT_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnskey.h0000644000000000000000000000013214505005532023267 xustar000000000000000030 mtime=1695812442.029976273 30 atime=1695812445.788030096 30 ctime=1695812494.208723578 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnskey.h0000664000374500037450000005332714505005532023243 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnscore * @brief * * * @{ */ #pragma once #include #include #include #include #include #include #include #include #include #define DNSSEC_MINIMUM_KEY_SIZE 512 // bits #define DNSSEC_MAXIMUM_KEY_SIZE (8192 + 128) // bits #define DNSSEC_DEFAULT_KEYSTORE_PATH "." #define DNSSEC_MINIMUM_KEY_SIZE_BYTES ((DNSSEC_MINIMUM_KEY_SIZE+7)/8) #define DNSSEC_MAXIMUM_KEY_SIZE_BYTES ((DNSSEC_MAXIMUM_KEY_SIZE+7)/8) #if WORDS_BIGENDIAN #define DNSKEY_FLAGS_KSK 0x0101 // NATIVE #define DNSKEY_FLAGS_ZSK 0x0100 // NATIVE #else #define DNSKEY_FLAGS_KSK 0x0101 // NATIVE #define DNSKEY_FLAGS_ZSK 0x0001 // NATIVE #endif /* * Extract fields from a packed record * */ #define DNSKEY_FLAGS_FROM_RDATA(x__) (GET_U16_AT(((u8*)(x__))[0])) #define DNSKEY_FLAGS(x__) (GET_U16_AT((x__).rdata_start[0])) #define DNSKEY_PROTOCOL(x__) ((x__).rdata_start[2]) #define DNSKEY_ALGORITHM(x__) ((x__).rdata_start[3]) /* * Computes the key tag from a packed record */ #define DNSKEY_TAG(x__) (dnskey_get_tag_from_rdata(&(x__).rdata_start[0],(x__).rdata_size)) #ifdef __cplusplus extern "C" { #endif #define DNSKEY_RDATA_TAG 0x445259454b534e44 /* DNSKEYRD */ #define DNSKEY_FEATURE_NSEC_CAPABLE 1 #define DNSKEY_FEATURE_NSEC3_CAPABLE 2 #define DNSKEY_FEATURE_ZONE_SIGNATURE 16 #define DNSKEY_FEATURE_ZONE_NSEC (DNSKEY_FEATURE_NSEC_CAPABLE|DNSKEY_FEATURE_ZONE_SIGNATURE) #define DNSKEY_FEATURE_ZONE_NSEC3 (DNSKEY_FEATURE_NSEC3_CAPABLE|DNSKEY_FEATURE_ZONE_SIGNATURE) #define DNSKEY_FEATURE_ZONE_MODERN (DNSKEY_FEATURE_NSEC_CAPABLE|DNSKEY_FEATURE_NSEC3_CAPABLE|DNSKEY_FEATURE_ZONE_SIGNATURE) struct dnskey_features { const char **names; u16 size_bits_min; u16 size_bits_max; u16 size_bits_ksk_default; u16 size_bits_zsk_default; u16 size_multiple; u8 algorithm; u8 usage; }; typedef struct dnskey_features dnskey_features; struct dnskey_raw_field_s { u8 *buffer; u32 size; }; typedef struct dnskey_raw_field_s dnskey_raw_field_t; #define STRUCTDESCRIPTOR_NONE 0 #define STRUCTDESCRIPTOR_BN 1 #define STRUCTDESCRIPTOR_U16 2 #define STRUCTDESCRIPTOR_RAW 3 struct dnskey_field_access { //const char* name; const char name[24]; size_t relative; int type; }; typedef struct dnskey_field_access dnskey_field_access; struct parser_s; ya_result dnskey_field_access_parse(const struct dnskey_field_access *sd, void *base, struct parser_s *p); ya_result dnskey_field_access_print(const struct dnskey_field_access *sd, const void *base, output_stream *os); struct dnssec_key_vtbl; typedef struct dnssec_key_vtbl dnssec_key_vtbl; typedef struct dnssec_key_contextmethods dnssec_key_contextmethods; #ifdef SSL_API union dnssec_key_data { void* any; RSA* rsa; DSA* dsa; #if DNSCORE_HAS_ECDSA_SUPPORT EC_KEY* ec; #endif #if DNSCORE_HAS_EDDSA_SUPPORT EVP_PKEY* ed; #endif }; #else union dnssec_key_data { void* any; }; #endif typedef union dnssec_key_data dnssec_key_data; typedef struct dnssec_key dnssec_key; typedef ya_result dnskey_algorithm_newinstance(u32 size, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key); #define DNSKEY_KEY_IS_PRIVATE 0x0001 #define DNSKEY_KEY_TAG_SET 0x0002 // not always needed #define DNSKEY_KEY_IS_FROM_DISK 0x0004 // for generated keys #define DNSKEY_KEY_IS_MARKED 0x0008 // for marking a key (key manager update algorithm) #define DNSKEY_KEY_IS_VALID 0x0010 // the key is public with all its fields set #define DNSKEY_KEY_IS_IN_ZONE 0x0020 // the key is at the apex of its zone #define DNSKEY_KEY_IS_ACTIVE 0x0040 // the key is already used for signature #define DNSKEY_KEY_PUBLISH_ARMED 0x0080 #define DNSKEY_KEY_ACTIVATE_ARMED 0x0100 #define DNSKEY_KEY_DEACTIVATE_ARMED 0x0200 #define DNSKEY_KEY_DELETE_ARMED 0x0400 #define DNSKEY_KEY_HAS_SMART_FIELD_CREATED 0x0800 #define DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH 0x1000 #define DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE 0x2000 #define DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE 0x4000 #define DNSKEY_KEY_HAS_SMART_FIELD_DELETE 0x8000 /* Hash should be tag<<8 | algorithm */ struct dnssec_key { struct dnssec_key *next; const dnssec_key_vtbl *vtbl; char *origin; u8 *owner_name; // = zone origin dnssec_key_data key; // RSA* or DSA* or any crypto-lib specific pointer s64 timestamp; // the file modification time of the private key (to avoid reloading) int nid; // NID_sha1, NID_md5 volatile int rc; time_t epoch_created; time_t epoch_publish; // if not published yet, at that time, it needs to be added in the zone time_t epoch_activate; // if not activated yet, at that time, it needs to be used for signatures time_t epoch_inactive; // if active, at that time, it needs to stop being used for signatures time_t epoch_delete; // if still in the zone, at that time, it needs to be removed from the zone u16 flags; u16 tag; u8 algorithm; u32 status; // Is the key "private", has the tag been computed, ... /* * Later, add a list of (wannabe) signers and for each of these * if said signature has been verified, not verified or is wrong */ }; typedef struct dnssec_key_sll dnssec_key_sll; struct dnssec_key_sll { struct dnssec_key_sll* next; dnssec_key* key; }; typedef void dnssec_key_free_method(dnssec_key *key); typedef u32 dnssec_key_rdatasize_method(const dnssec_key *key); typedef u32 dnssec_key_writerdata_method(const dnssec_key *key, u8 *output, size_t output_size); typedef ya_result dnssec_key_sign_digest_method(const dnssec_key *key, const u8 *digest, u32 digest_len, u8 *output); typedef bool dnssec_key_verify_digest_method(const dnssec_key *key, const u8 *digest, u32 digest_len, const u8 *signature, u32 signature_len); typedef bool dnssec_key_equals_method(const dnssec_key *key_a, const dnssec_key *key_b); typedef ya_result dnssec_key_private_print_fields_method(dnssec_key *key, output_stream *os); typedef u32 dnssec_key_size_method(const dnssec_key *key); struct dnssec_key_vtbl { dnssec_key_sign_digest_method *dnssec_key_sign_digest; dnssec_key_verify_digest_method *dnssec_key_verify_digest; dnssec_key_rdatasize_method *dnssec_key_rdatasize; dnssec_key_writerdata_method *dnssec_key_writerdata; dnssec_key_free_method *dnssec_key_free; dnssec_key_equals_method *dnssec_key_equals; dnssec_key_private_print_fields_method *dnssec_key_print_fields; dnssec_key_size_method *dnssec_key_size; const char *__class__; }; struct dnskey_field_parser; typedef ya_result dnskey_field_parser_parse_field_method(struct dnskey_field_parser *, struct parser_s *); typedef ya_result dnskey_field_parser_set_key_method(struct dnskey_field_parser *, dnssec_key *); typedef void dnskey_field_parser_finalize_method(struct dnskey_field_parser *); struct dnskey_field_parser_vtbl { dnskey_field_parser_parse_field_method *parse_field; dnskey_field_parser_set_key_method *set_key; dnskey_field_parser_finalize_method *finalise; const char *__class__; }; struct dnskey_field_parser { void *data; const struct dnskey_field_parser_vtbl *vtbl; }; typedef struct dnskey_field_parser dnskey_field_parser; /** * Initialises internal structures */ void dnskey_init(); /** * Initialises an empty instance of a DNSKEY * No cryptographic content is put in the key. * Needs further setup. * * @param algorithm the algorithm of the key. * @param flags the flags of the key * @param origin the origin of the key * * @return a pointer to an empty instance (no real key attached) of a key. */ dnssec_key *dnskey_newemptyinstance(u8 algorithm,u16 flags,const char *origin); /** * Generate a (public) key using the RDATA * * @param rdata * @param rdata_size * @param origin * @param out_key points to a pointer for the instantiated key * * @return an error code (success or error) */ ya_result dnskey_new_from_rdata(const u8 *rdata, u16 rdata_size, const u8 *origin, dnssec_key **out_key); /** * Increases the reference count on a dnssec_key * * @param key */ void dnskey_acquire(dnssec_key *key); /** * Releases the reference count on a dnssec_key. * Uses the tag, flags, algorithm, origin and key content. * * @param a * @param b */ void dnskey_release(dnssec_key *key); /** * * Compares two keys for equality on a cryptographic point of view * Uses the tag, flags, algorithm and origin. * * @param a * @param b * * @return TRUE iff the keys are the same. */ bool dnskey_equals(const dnssec_key *a, const dnssec_key *b); /** * * Compares two keys for equality on a cryptographic point of view * Uses the tag, flags, algorithm, origin and public key content. * * @param a * @param b * * @return TRUE iff the keys are the same. */ bool dnskey_public_equals(const dnssec_key *a, const dnssec_key *b); /** * Returns TRUE if the tag and algorithm of the rdata are matching the ones of the key. * * @param key * @param rdata * @param rdata_size * @return */ bool dnskey_matches_rdata(const dnssec_key *key, const u8 *rdata, u16 rdata_size); /** * Returns TRUE if an only if the tag has already been computed and * stored in the dnssec key. * * @param key * @return TRUE iff the tag is already known */ static inline bool dnssec_key_tag_field_set(const dnssec_key *key) { return (key->status & DNSKEY_KEY_TAG_SET) != 0; } /** * Returns the key tag. * The key tag generated by this function is stored in the dnssec key to * make further calls instant. This is why the parameter is not "const". * * @param key * @return */ u16 dnskey_get_tag(dnssec_key *key); /** * Returns the key tag. * If the key tag is not cached in the key, computes it. * The tag is not cached in the key after this call. * * @param key * @return */ u16 dnskey_get_tag_const(const dnssec_key *key); /** * Returns the algorithm of the key. * * @param key * @param keyp */ u8 dnskey_get_algorithm(const dnssec_key *key); /** * Returns a pointer to the domain of the key. * * @param key * @return */ const u8 *dnskey_get_domain(const dnssec_key *key); /** * Returns TRUE if and only if the key is a private key. * * @return TRUE iff the key is private. */ bool dnskey_is_private(const dnssec_key *key); /** * Adds/Remove a key from a key chain. * The 'next' field of the key is used. * A key can only be in one chain at a time. * This is meant to be used in the keystore. * * RC ok * * @param keyp */ void dnskey_add_to_chain(dnssec_key *key, dnssec_key **keyp); /** * Adds/Remove a key from a key chain. * The 'next' field of the key is used. * A key can only be in one chain at a time. * This is meant to be used in the keystore. * * RC ok * * @param keyp */ void dnskey_remove_from_chain(dnssec_key *key, dnssec_key **keyp); /** * Generates a key tag from the DNSKEY RDATA wire * * @param dnskey_rdata * @param dnskey_rdata_size * @return */ u16 dnskey_get_tag_from_rdata(const u8 *dnskey_rdata, u32 dnskey_rdata_size); /** * Returns the flag of a dnskey from its rdata * * @param dnskey rdata * * @return */ static inline u16 dnskey_get_flags_from_rdata(const u8 *dnskey_rdata) { return GET_U16_AT_P(dnskey_rdata); } /** * Returns the protocol of a dnskey from its rdata * * @param dnskey rdata * * @return */ static inline u8 dnskey_get_protocol_from_rdata(const u8 *dnskey_rdata) { return dnskey_rdata[2]; } /** * Returns the algorithm of a dnskey from its rdata * * @param dnskey rdata * * @return */ static inline u8 dnskey_get_algorithm_from_rdata(const u8 *dnskey_rdata) { return dnskey_rdata[3]; } /** * Reference implementation function to generate a key tag from the DNSKEY RDATA wire * * @param dnskey_rdata * @param dnskey_rdata_size * @return */ unsigned int dnskey_get_tag_from_rdata_reference(unsigned char key[], /* the RDATA part of the DNSKEY RR */ unsigned int keysize /* the RDLENGTH */ ); /** * Generate the RDATA of a DS records using the RDATA from a DSNKEY record * * @param digest_type the type of DS * @param dnskey_fqdn the domain of the record * @param dnskey_rdata the rdata of the DNSKEY * @param dnskey_rdata_size the size of the rdata of the DNSKEY * @param out_rdata the output buffer that has to be the right size (known given digest_type) * @return */ ya_result dnskey_generate_ds_rdata(u8 digest_type, const u8 *dnskey_fqdn, const u8 *dnskey_rdata,u16 dnskey_rdata_size, u8 *out_rdata); /** * Initialises the context for a key algorithm. * * @param ctx * @param algorithm * @return */ ya_result dnskey_digest_init(digest_s *ctx, u8 algorithm); /** * * @param os output stream * @param num the number to write * @return */ ya_result dnskey_write_bignum_as_base64_to_stream(const BIGNUM *num, output_stream *os); void dnskey_set_created_epoch(dnssec_key *key, time_t t); /** * Returns the most relevant publication time. * * publish > activate > created > now * * @param key * @return */ time_t dnskey_get_publish_epoch(const dnssec_key *key); void dnskey_set_publish_epoch(dnssec_key *key, time_t t); /** * Returns the most relevant activation time. * * activate > publish > created > now * * @param key * @return */ time_t dnskey_get_activate_epoch(const dnssec_key *key); void dnskey_set_activate_epoch(dnssec_key *key, time_t t); /** * Returns the most relevant revocation time. * * revoke > never * * @param key * @return */ time_t dnskey_get_revoke_epoch(const dnssec_key *key); void dnskey_set_revoke_epoch(dnssec_key *key, time_t t); /** * Returns the most relevant inactivation time. * * inactive > delete > never * * @param key * @return */ time_t dnskey_get_inactive_epoch(const dnssec_key *key); void dnskey_set_inactive_epoch(dnssec_key *key, time_t t); /** * Returns the most relevant delete time. * * delete > inactive > never * * @param key * @return */ time_t dnskey_get_delete_epoch(const dnssec_key *key); void dnskey_set_delete_epoch(dnssec_key *key, time_t t); ya_result dnskey_new_public_key_from_stream(input_stream *is, dnssec_key** keyp); /** * Loads a public key from a file. * * ie: Keu.+007+12345.key * * RC ok * * @param filename * @param keyp * @return */ ya_result dnskey_new_public_key_from_file(const char *filename, dnssec_key **keyp); ya_result dnskey_add_private_key_from_stream(input_stream *is, dnssec_key *key, const char* path, u8 algorithm); /** * Loads a private key from a file. * * ie: Keu.+007+12345.private * * The public key must be in the same folder as the private key. * * ie: Keu.+007+12345.key * * RC ok * * @param filename * @param keyp * @return */ ya_result dnskey_new_private_key_from_file(const char *filename, dnssec_key **keyp); /** * Returns the keytag from its DS rdata in network order * * @param rdata * @return */ static inline u16 ds_get_wire_keytag_from_rdata(const u8 *rdata) { u16 ds_keytag = GET_U16_AT_P(rdata); return ds_keytag; } /** * Returns the keytag from its DS rdata * * @param rdata * @return */ static inline u16 ds_get_keytag_from_rdata(const u8 *rdata) { u16 ds_keytag = ntohs(ds_get_wire_keytag_from_rdata(rdata)); return ds_keytag; } /** * Returns the algorithm from its DS rdata * * @param rdata * @return */ static inline u8 ds_get_algorithm_from_rdata(const u8 *rdata) { u8 ds_algorithm = rdata[2]; return ds_algorithm; } /** * Returns the digest algorithm from its DS rdata * * @param rdata * @return */ static inline u8 ds_get_digesttype_from_rdata(const u8 *rdata) { u8 ds_digesttype = rdata[3]; return ds_digesttype; } /** * * Save the private part of a key to a stream * * @param key * @param filename * @return */ ya_result dnskey_store_private_key_to_stream(dnssec_key *key, output_stream *os); /** * * Save the private part of a key to a file with the given name * * @param key * @param filename * @return */ ya_result dnskey_store_private_key_to_file(dnssec_key *key, const char *filename); /** * * Save the public part of a key to a stream * * @param key * @param filename * @return */ ya_result dnskey_store_public_key_to_stream(dnssec_key *key, output_stream *os); /** * * Save the public part of a key to a file with the given name * * @param key * @param filename * @return */ ya_result dnskey_store_public_key_to_file(dnssec_key *key, const char *filename); /** * Save the private part of a key to a dir * * @param key * @param dirname * @return */ ya_result dnskey_store_private_key_to_dir(dnssec_key *key, const char *dirname); /** * * Saves the public part of the key in a dir * * @param key * @param dirname * @return */ ya_result dnskey_store_public_key_to_dir(dnssec_key *key, const char *dirname); /** * Save both parts of the key to the directory. * * @param key * @param dir * * @return an error code */ ya_result dnskey_store_keypair_to_dir(dnssec_key *key, const char *dir); ya_result dnskey_delete_public_key_from_dir(dnssec_key *key, const char *dirname); ya_result dnskey_delete_private_key_from_dir(dnssec_key *key, const char *dirname); ya_result dnskey_delete_keypair_from_dir(dnssec_key *key, const char *dirname); bool dnskey_is_expired(const dnssec_key *key, time_t now); bool dnskey_is_expired_now(const dnssec_key *key); bool dnskey_is_revoked(const dnssec_key *key); int dnskey_get_size(const dnssec_key *key); u16 dnskey_get_flags(const dnssec_key *key); void dnskey_state_enable(dnssec_key *key, u32 status); void dnskey_state_disable(dnssec_key *key, u32 status); u32 dnskey_state_get(const dnssec_key *key); /** * Returns true if the key is supposed to have been added in the zone at the chosen time already. * * @param key * @param t * @return */ bool dnskey_is_published(const dnssec_key *key, time_t t); /** * Returns true if the key is supposed to have been removed from the zone at the chosen time already. * * @param key * @param t * @return */ bool dnskey_is_unpublished(const dnssec_key *key, time_t t); /** * Returns true if the key is supposed to be used for signatures. * * @param key * @param t * @return */ bool dnskey_is_activated(const dnssec_key *key, time_t t); /** * Assumes we are in 'leniency' seconds in the future for activation (and in the present for deactivation) */ bool dnskey_is_activated_lenient(const dnssec_key *key, time_t t, u32 leniency); /** * Returns true if the key must not be used for signatures anymore. * * @param key * @param t * @return */ bool dnskey_is_deactivated(const dnssec_key *key, time_t t); static inline time_t dnskey_get_created_epoch(const dnssec_key *key) { return key->epoch_created; } bool dnskey_has_explicit_publish(const dnssec_key *key); bool dnskey_has_explicit_delete(const dnssec_key *key); bool dnskey_has_explicit_activate(const dnssec_key *key); bool dnskey_has_explicit_deactivate(const dnssec_key *key); bool dnskey_has_explicit_publish_or_delete(const dnssec_key *key); bool dnskey_has_explicit_publish_and_delete(const dnssec_key *key); bool dnskey_has_activate_and_deactivate(const dnssec_key *key); bool dnskey_has_explicit_publish_or_delete(const dnssec_key *key); bool dnskey_has_activate_or_deactivate(const dnssec_key *key); ya_result dnskey_newinstance(u32 size, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key); u8 dnskey_supported_algorithm_count(); const dnskey_features* dnskey_supported_algorithm_by_index(u8 index); const dnskey_features* dnskey_supported_algorithm(u8 algorithm); void dnskey_init_dns_resource_record(dnssec_key *key, s32 ttl, dns_resource_record *rr); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnskey-keyring.h0000644000000000000000000000013214505005531024734 xustar000000000000000030 mtime=1695812441.786972793 30 atime=1695812445.786030067 30 ctime=1695812494.210723606 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnskey-keyring.h0000664000374500037450000000701114505005531024675 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keyring functions * @ingroup dnsdbdnssec * @brief * * * @{ */ #pragma once #include #include struct dnskey_keyring { mutex_t mtx; u32_set tag_to_key; }; typedef struct dnskey_keyring dnskey_keyring; #define EMPTY_DNSKEY_KEYRING {MUTEX_INITIALIZER, U32_SET_EMPTY } /** * Collection of keys. * Uses RC mechanisms. * * @param ks * @return */ ya_result dnskey_keyring_init(dnskey_keyring *ks); void dnskey_keyring_finalize(dnskey_keyring *ks); ya_result dnskey_keyring_add(dnskey_keyring *ks, dnssec_key *key); ya_result dnskey_keyring_add_from_nameserver(dnskey_keyring *ks, const host_address *ha, const u8 *domain); bool dnskey_keyring_remove(dnskey_keyring *ks, u8 algorithm, u16 tag, const u8 *domain); #define KEYRING_TAG 0x00474e4952494548 static inline dnskey_keyring *dnskey_keyring_new() { dnskey_keyring *ks; ZALLOC_OBJECT_OR_DIE(ks, dnskey_keyring, KEYRING_TAG); dnskey_keyring_init(ks); return ks; } static inline void dnskey_keyring_free(dnskey_keyring *ks) { if(ks != NULL) { dnskey_keyring_finalize(ks); ZFREE_OBJECT(ks); } } /** * * Returns TRUE iff the keyring contains a key matching the parameters * * @param ks * @param algorithm * @param tag * @param domain * @return */ bool dnskey_keyring_has_key(dnskey_keyring *ks, u8 algorithm, u16 tag, const u8 *domain); dnssec_key *dnskey_keyring_acquire(dnskey_keyring *ks, u8 algorithm, u16 tag, const u8 *domain); void dnskey_keyring_destroy(dnskey_keyring *ks); bool dnskey_keyring_isempty(dnskey_keyring *ks); dnssec_key * dnskey_keyring_acquire_key_at_index(dnskey_keyring *ks, int index); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnskey_dsa.h0000644000000000000000000000013114505005532024115 xustar000000000000000030 mtime=1695812442.073976903 29 atime=1695812445.78903011 30 ctime=1695812494.212723635 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnskey_dsa.h0000664000374500037450000000513414505005532024063 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef _DNSSEC_DSA_H #define _DNSSEC_DSA_H /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include #include #include #ifdef __cplusplus extern "C" { #endif ya_result dnskey_dsa_loadpublic(const u8 *rdata, u16 rdata_size, const char *origin, dnssec_key** out_key); ya_result dnskey_dsa_newinstance(u32 size, u8 algorithm,u16 flags,const char* origin, dnssec_key** out_key); void dnskey_dsa_parse_init(dnskey_field_parser *fp); #ifdef __cplusplus } #endif #endif /* _DNSSEC_DSA_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnskey_ecdsa.h0000644000000000000000000000013214505005532024426 xustar000000000000000030 mtime=1695812442.028976259 30 atime=1695812445.788030096 30 ctime=1695812494.214723663 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnskey_ecdsa.h0000664000374500037450000000514614505005532024376 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef _DNSSEC_ECDSA_H #define _DNSSEC_ECDSA_H /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include #include #include #ifdef __cplusplus extern "C" { #endif ya_result dnskey_ecdsa_loadpublic(const u8 *rdata, u16 rdata_size, const char *origin, dnssec_key** out_key); ya_result dnskey_ecdsa_newinstance(u32 size, u8 algorithm,u16 flags, const char *origin, dnssec_key** out_key); void dnskey_ecdsa_parse_init(dnskey_field_parser *fp); #ifdef __cplusplus } #endif #endif /* _DNSSEC_RSA_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnskey_eddsa.h0000644000000000000000000000013214505005531024426 xustar000000000000000030 mtime=1695812441.784972764 30 atime=1695812445.786030067 30 ctime=1695812494.216723692 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnskey_eddsa.h0000664000374500037450000000545514505005531024401 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @brief * * @{ */ #pragma once /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include #include #include #ifdef __cplusplus extern "C" { #endif #ifndef HAS_EDDSA_SUPPORT #define HAS_EDDSA_SUPPORT 1 #endif #ifndef DNSCORE_HAS_EDDSA_SUPPORT #define DNSCORE_HAS_EDDSA_SUPPORT 1 #endif #if /**/ HAS_EDDSA_SUPPORT != DNSCORE_HAS_EDDSA_SUPPORT // the comment is to avoid breaking with a search & replace #error "EDDSA configuration mismatch" #endif #if !DNSCORE_HAS_EDDSA_SUPPORT #endif ya_result dnskey_eddsa_loadpublic(const u8 *rdata, u16 rdata_size, const char *origin, dnssec_key** out_key); ya_result dnskey_eddsa_newinstance(u32 size, u8 algorithm,u16 flags, const char *origin, dnssec_key** out_key); void dnskey_eddsa_parse_init(dnskey_field_parser *fp); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnskey_rsa.h0000644000000000000000000000013214505005532024134 xustar000000000000000030 mtime=1695812442.082977032 30 atime=1695812445.790030125 30 ctime=1695812494.218723721 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnskey_rsa.h0000664000374500037450000000504114505005532024076 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #pragma once /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include #include #include #ifdef __cplusplus extern "C" { #endif ya_result dnskey_rsa_loadpublic(const u8 *rdata, u16 rdata_size, const char *origin, dnssec_key** out_key); ya_result dnskey_rsa_newinstance(u32 size, u8 algorithm,u16 flags,const char* origin, dnssec_key** out_key); void dnskey_rsa_parse_init(dnskey_field_parser *fp); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnskey-signature.h0000644000000000000000000000013014505005532025264 xustar000000000000000030 mtime=1695812442.059976702 29 atime=1695812445.78903011 29 ctime=1695812494.22072375 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnskey-signature.h0000664000374500037450000001044314505005532025232 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup dnskey DNSSEC keys functions * @ingroup dnscorednssec * @addtogroup dnskey DNSKEY functions * @brief * * * @{ */ #pragma once #include #include #include struct resource_record_view_vtbl { const u8* (*get_fqdn)(void*, const void*); u16 (*get_type)(void*, const void*); u16 (*get_class)(void*, const void*); s32 (*get_ttl)(void*, const void*); u16 (*get_rdata_size)(void*, const void*); const u8* (*get_rdata)(void*, const void*); void *(*new_instance)(void*, const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size, const u8 *rdata); }; typedef struct resource_record_view_vtbl resource_record_view_vtbl; struct resource_record_view { void *data; // passed as first parameter of the vtbl methods const struct resource_record_view_vtbl *vtbl; }; typedef struct resource_record_view resource_record_view; struct dnskey_signature { ptr_vector *rrset_reference; resource_record_view *rr_view; u32 inception; u32 expiration; u32 digest_size; /// @note 20211202 edf -- MUST be 32 bits to accomodate EDDSA unsigned int is_canonised:1, has_digest:1, inception_set:1, expiration_set:1, reserved:4, key_algorithm:8; //u8 digest_buffer[DIGEST_BUFFER_SIZE]; digest_s digest_ctx; }; typedef struct dnskey_signature dnskey_signature; void dnskey_signature_init(dnskey_signature *ds); void dnskey_signature_set_validity(dnskey_signature *ds, time_t from, time_t to); /** * Sets the view that translates the content of the rrset ptr_vector. * The view is also responsible for generating rrsig records. */ void dnskey_signature_set_view(dnskey_signature *ds, resource_record_view *view); void dnskey_signature_set_rrset_reference(dnskey_signature *ds, ptr_vector *rrset); void dnskey_signature_set_canonised(dnskey_signature *ds, bool canonised); ya_result dnskey_signature_sign(dnskey_signature *ds, const dnssec_key *key, void **out_rrsig_rr); ya_result dnskey_signature_verify(dnskey_signature *ds, const dnssec_key *key, void *in_rrsig_rr); void dnskey_signature_finalize(dnskey_signature *ds); ya_result dnskey_sign_rrset_with_maxinterval(const dnssec_key *key, ptr_vector *rrset, bool canonize, resource_record_view *view, s32 maxinterval, void **out_rrsig); //ya_result dnskey_signature_rrset_verify(dnskey_signature *ds, const dnssec_key *key, ptr_vector *rrset, resource_record_view *view); /** * @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnsname.h0000644000000000000000000000013214505005531023416 xustar000000000000000030 mtime=1695812441.993975758 30 atime=1695812445.787030082 30 ctime=1695812494.222723778 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnsname.h0000664000374500037450000005041514505005531023365 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore * @ingroup dnscore * @brief Functions used to manipulate dns formatted names and labels * * DNS names are stored in many ways: * _ C string : ASCII with a '\0' sentinel * _ DNS wire : label_length_byte + label_bytes) ending with a label_length_byte with a value of 0 * _ simple array of pointers to labels * _ simple stack of pointers to labels (so the same as above, but with the order reversed) * _ sized array of pointers to labels * _ sized stack of pointers to labels (so the same as above, but with the order reversed) * * @{ */ #pragma once #include #include #if DNSCORE_HAS_FULL_ASCII7 #include #endif /** * The maximum number of domains-subdomains handled by the database. * This should not be set to a value greater than 128 (128 covers (\001 'a') * 255 ) * * Recommended value: 128 * */ #define SRV_UNDERSCORE_SUPPORT 1 #define DNSNAME_MAX_SECTIONS ((MAX_DOMAIN_LENGTH + 1) / 2) #if !DNSNAME_C_ extern const u8 __LOCASE_TABLE__[256]; #endif // dns equal chars comparison should give 0x00 or 0x20 // the '_' breaks this so there is a slightly different (slightly slower) way to handle it // IMPORTANT NOTE 1 : MACROS ARE WRITTEN TO USE THEIR PARAMETERS EXACTLY ONCE // IMPORTANT NOTE 2 : LOCASEEQUAL only works on the DNS chars AND with the first parameter being a lo-case string (like in the database) #if !DNSCORE_HAS_FULL_ASCII7 #define dnsname_equals_ignorecase dnsname_equals_ignorecase3 #define dnslabel_equals_ignorecase_left dnslabel_equals_ignorecase_left1 #if !SRV_UNDERSCORE_SUPPORT #define LOCASE(c__) ((char)(c__)|(char)0x20) static inline bool LOCASEEQUALS(char ca__,char cb__) { return ((((char)(ca__)-(char)(cb__))&0xdf) == 0); } static inline bool LOCASEEQUALSBY2(const u8* name_a, const u8* name_b) { return (((GET_U16_AT(name_a[0]) - GET_U16_AT(name_b[0])) & ((u16)0xdfdf)) == 0); } static inline bool LOCASEEQUALSBY3(const u8* name_a, const u8* name_b) { return LOCASEEQUALSBY2(name_a, name_b) && LOCASEEQUALS(name_a[2], name_b[2]); } static inline bool LOCASEEQUALSBY4(const u8* name_a, const u8* name_b) { return (((GET_U32_AT(name_a[0]) - GET_U32_AT(name_b[0])) & ((u16)0xdfdfdfdf)) == 0); } #else // slightly modified to take '_' into account #define LOCASE(c__) (((((char)(c__)+(char)0x01)|(char)0x20))-(char)0x01) static inline bool LOCASEEQUALS(u8 a, u8 b) { return ((((u8)(a+0x01)-(u8)(b+0x01))&0xdf) == 0); } static inline bool LOCASEEQUALSBY2(const u8* name_a, const u8* name_b) { return (( ( (GET_U16_AT(name_a[0]) + 0x0101) - (GET_U16_AT(name_b[0]) + 0x0101)) & ((u16)0xdfdf)) == 0); } static inline bool LOCASEEQUALSBY3(const u8* name_a, const u8* name_b) { return LOCASEEQUALSBY2(name_a, name_b) && LOCASEEQUALS(name_a[2], name_b[2]); } static inline bool LOCASEEQUALSBY4(const u8* name_a, const u8* name_b) { return (( ( (GET_U32_AT(name_a[0]) + 0x01010101) - (GET_U32_AT(name_b[0]) + 0x01010101)) & ((u32)0xdfdfdfdf)) == 0); } #endif #else // DNSCORE_HAS_FULL_ASCII7 #define dnsname_equals_ignorecase dnsname_equals_ignorecase3 #define dnslabel_equals_ignorecase_left dnslabel_equals_ignorecase_left4 #define LOCASE(c__) __LOCASE_TABLE__[(c__)] static inline bool LOCASEEQUALS(u8 a, u8 b) { return LOCASE(a) == LOCASE(b); } static inline bool LOCASEEQUALSBY2(const u8* name_a, const u8* name_b) { return LOCASEEQUALS(name_a[0], name_b[0]) && LOCASEEQUALS(name_a[1], name_b[1]); } static inline bool LOCASEEQUALSBY3(const u8* name_a, const u8* name_b) { return LOCASEEQUALSBY2(name_a, name_b) && LOCASEEQUALS(name_a[2], name_b[2]); } static inline bool LOCASEEQUALSBY4(const u8* name_a, const u8* name_b) { return LOCASEEQUALSBY3(name_a, name_b) && LOCASEEQUALS(name_a[3], name_b[3]); } #endif #define ZDB_NAME_TAG 0x454d414e42445a /* "ZDBNAME" */ #define ZDB_LABEL_TAG 0x4c424c42445a /* "ZDBLBL" */ #ifdef __cplusplus extern "C" { #endif /* * A dnslabel_array is basically a dnslabel*[] * There are two kind of arrays : * * dnslabel_stack: * * [0000] "." label * [0001] "tdl" label * [0002] "domain" label <- top * * dnslabel_vector: * * [0000] "domain" label * [0001] "tdl" label * [0002] "." label <- top * */ /* * The plan was to typedef an array into a stack or a vector. * But in order to help the compiler complaining about mixing both, * I have to define them separatly * */ typedef const u8* dnslabel_stack[DNSNAME_MAX_SECTIONS]; /* This + 1 is just to make sure both are different to the compiler's eyes */ typedef const u8* dnslabel_vector[DNSNAME_MAX_SECTIONS + 1]; typedef const u8** dnslabel_stack_reference; typedef const u8** dnslabel_vector_reference; typedef const u8*const* const_dnslabel_stack_reference; typedef const u8*const* const_dnslabel_vector_reference; #if DEBUG #define DEBUG_RESET_dnsname(name) memset(&(name),0x5b,sizeof(dnsname_stack)) #else #define DEBUG_RESET_dnsname(name) #endif typedef struct dnsname_stack dnsname_stack; struct dnsname_stack { s32 size; dnslabel_stack labels; }; typedef struct dnsname_vector dnsname_vector; struct dnsname_vector { s32 size; dnslabel_vector labels; }; /***************************************************************************** * * BUFFER * *****************************************************************************/ /** @brief Converts a C string to a dns name. * * Converts a C string to a dns name. * * @param[in] name_parm a pointer to a buffer that will get the full dns name * @param[in] str a pointer to the source c-string * * @return Returns the length of the string up to the last '\0' */ /* TWO use */ ya_result cstr_to_dnsname(u8* name_parm, const char* str); /** @brief Converts a C string to a lower-case dns name. * * Converts a C string to a lower-case dns name. * * @param[in] name_parm a pointer to a buffer that will get the full dns name * @param[in] str a pointer to the source c-string * * @return Returns the length of the string up to the last '\0' */ ya_result cstr_to_locase_dnsname(u8* name_parm, const char* str); /** @brief Converts a text buffer to a dns name. * * Converts a text buffer to a dns name. * * @param[in] name_parm a pointer to a buffer that will get the full dns name * @param[in] str a pointer to the source buffer * @param[in] str_len the length of the source buffer * * @return Returns the length of the string up to the last '\0' */ ya_result charp_to_dnsname(u8* name_parm, const char* str, u32 str_len); /** @brief Converts a text buffer to a lower-case dns name. * * Converts a text buffer to a lower-case dns name. * * @param[in] name_parm a pointer to a buffer that will get the full dns name * @param[in] str a pointer to the source buffer * @param[in] str_len the length of the source buffer * * @return Returns the length of the string up to the last '\0' */ ya_result charp_to_locase_dnsname(u8* name_parm, const char* str, u32 str_len); /** @brief Converts a text buffer to a lower-case dns name and checks for validity * * Converts a text buffer to a lower-case dns name. * * @param[in] name_parm a pointer to a buffer that will get the full dns name * @param[in] str a pointer to the source buffer * @param[in] str_len the length of the source buffer * * @return Returns the length of the string up to the last '\0' */ ya_result charp_to_locase_dnsname_with_check(u8* name_parm, const char* str, u32 str_len); /** * @brief Converts a C string to a dns name and checks for validity * * Converts a C string to a dns name. * * @param[in] name_parm a pointer to a buffer that will get the full dns name * @param[in] str a pointer to the source c-string * * @return Returns the length of the string up to the last '\0' */ ya_result cstr_to_dnsname_with_check(u8* name_parm, const char* str); /** * @brief Converts a C string to a dns rname and checks for validity * * Converts a C string to a dns rname. * * @param[in] name_parm a pointer to a buffer that will get the full dns name * @param[in] str a pointer to the source c-string * * @return Returns the length of the string up to the last '\0' */ ya_result cstr_to_dnsrname_with_check(u8* name_parm, const char* str); ya_result cstr_to_dnsname_with_check_len(u8* name_parm, const char* text, u32 text_len); ya_result cstr_to_locase_dnsname_with_check_len(u8* name_parm, const char* text, u32 text_len); ya_result cstr_to_dnsname_with_check_len_with_origin(u8* name_parm, const char* text, u32 text_len, const u8 *origin); ya_result cstr_to_locase_dnsname_with_check_len_with_origin(u8* name_parm, const char* text, u32 text_len, const u8 *origin); /* ONE use */ ya_result cstr_get_dnsname_len(const char* str); /** @brief Converts a dns name to a C string * * Converts a dns name to a C string * * @param[in] name a pointer to the source dns name * @param[in] str a pointer to a buffer that will get the c-string * * @return Returns the length of the string */ /* SIX uses */ u32 dnsname_to_cstr(char* str, const u8* name); /** @brief Tests if two DNS labels are equals * * Tests if two DNS labels are equals * * @param[in] name_a a pointer to a dnsname to compare * @param[in] name_b a pointer to a dnsname to compare * * @return Returns TRUE if names are equal, else FALSE. */ /* ELEVEN uses */ bool dnslabel_equals(const u8* name_a, const u8* name_b); int dnsname_compare(const u8* name_a, const u8* name_b); bool dnsname_is_subdomain(const u8* subdomain, const u8* domain); /** @brief Tests if two DNS labels are (case-insensitive) equals * * Tests if two DNS labels are (case-insensitive) equals * * @param[in] name_a a pointer to a lo-case dnsname to compare * @param[in] name_b a pointer to a any-case dnsname to compare * * @return Returns TRUE if names are equal, else FALSE. */ bool dnslabel_equals_ignorecase_left1(const u8* name_a, const u8* name_b); bool dnslabel_equals_ignorecase_left2(const u8* name_a, const u8* name_b); bool dnslabel_equals_ignorecase_left3(const u8* name_a, const u8* name_b); bool dnslabel_equals_ignorecase_left4(const u8* name_a, const u8* name_b); bool dnslabel_equals_ignorecase_left5(const u8* name_a, const u8* name_b); /** @brief Tests if two DNS names are equals * * Tests if two DNS labels are equals * * @param[in] name_a a pointer to a dnsname to compare * @param[in] name_b a pointer to a dnsname to compare * * @return Returns TRUE if names are equal, else FALSE. */ /* TWO uses */ bool dnsname_equals(const u8* name_a, const u8* name_b); /** @brief Tests if two DNS names are (ignore case) equals * * Tests if two DNS labels are (ignore case) equals * * @param[in] name_a a pointer to a dnsname to compare * @param[in] name_b a pointer to a dnsname to compare * * @return Returns TRUE if names are equal, else FALSE. */ /* TWO uses */ bool dnsname_equals_ignorecase1(const u8* name_a, const u8* name_b); bool dnsname_equals_ignorecase2(const u8* name_a, const u8* name_b); bool dnsname_equals_ignorecase3(const u8* name_a, const u8* name_b); /** @brief Returns the full length of a dns name * * Returns the full length of a dns name * * @param[in] name a pointer to the dnsname * * @return The length of the dnsname, "." ( zero ) included */ /* SEVENTEEN uses (more or less) */ u32 dnsname_len(const u8* name); s32 dnsname_len_with_size(const u8 *name, size_t name_buffer_size); s32 dnsname_len_checked_with_size(const u8 *name, size_t name_buffer_size); ya_result dnsname_len_checked(const u8 *name); /* ONE use */ u32 dnsname_getdepth(const u8* name); /* ONE use */ u32 dnsname_copy(u8* dst, const u8* src); ya_result dnsname_copy_checked(u8* dst, const u8* src); /* malloc & copies a dnsname */ u8* dnsname_dup(const u8* src); void dnsname_free(u8* ptr); /** @brief Canonizes a dns name. * * Canonizes a dns name. (Lo-case) * * @param[in] src a pointer to the dns name * @param[out] dst a pointer to a buffer that will hold the canonized dns name * * @return The length of the dns name */ /* TWELVE uses */ u32 dnsname_canonize(const u8* src, u8* dst); /** * char DNS charset test * * @param c * @return TRUE iff c in in the DNS charset * */ bool dnsname_is_charspace(u8 c); s32 dnslabel_compare(const u8 *a, const u8 *b); /** * label DNS charset test * * @param label * @return TRUE iff each char in the label in in the DNS charset * */ bool dnslabel_verify_charspace(const u8 *label); /** * dns name DNS charset test * * @param name_wire * @return TRUE if each char in the name is in the DNS charset * */ bool dnsname_verify_charspace(const u8 *name_wire); /** * label DNS charset test and set to lower case * * @param label * @return TRUE iff each char in the label in in the DNS charset * */ bool dnslabel_locase_verify_charspace(u8 *label); /** * dns name DNS charset test and set to lower case * * LOCASE is done using |32 * * @param name_wire * @return TRUE iff each char in the name in in the DNS charset * */ bool dnsname_locase_verify_charspace(u8 *name_wire); /** * dns name DNS charset test and set to lower case * * LOCASE is done using tolower(c) * * @param name_wire * @return TRUE iff each char in the name in in the DNS charset * */ bool dnsname_locase_verify_extended_charspace(u8 *name_wire); /***************************************************************************** * * VECTOR * *****************************************************************************/ /* ONE use */ u32 dnslabel_vector_to_cstr(const_dnslabel_vector_reference name, s32 top, char *str); /* TWO use */ u32 dnslabel_vector_to_dnsname(const_dnslabel_vector_reference name, s32 top, u8 *str_start); /* ONE use */ u32 dnslabel_vector_dnslabel_to_dnsname(const u8 *prefix, const dnsname_vector *namestack, s32 bottom, u8 *str); static inline u32 dnslabel_copy(u8 *target, const u8 *src) { u32 len = src[0] + 1; memcpy(target, src, len); return len; } u32 dnslabel_vector_len(const_dnslabel_vector_reference name, s32 top); /* ONE use */ u32 dnsname_vector_sub_to_dnsname(const dnsname_vector *name, s32 from, u8 *name_start); /** @brief Divides a name into sections * * Divides a name into sections. * Writes a pointer to each label of the dnsname into an array * "." is never put in there. * * @param[in] name a pointer to the dnsname * @param[out] sections a pointer to the target array of pointers * * @return The index of the top-level label ("." is never put in there) */ /* TWO uses */ s32 dnsname_to_dnslabel_vector(const u8* dns_name, dnslabel_vector_reference labels); s32 dnsname_to_dnslabel_stack(const u8* dns_name, dnslabel_stack_reference labels); /** @brief Divides a name into sections * * Divides a name into sections. * Writes a pointer to each label of the dnsname into an array * "." is never put in there. * * @param[in] name a pointer to the dnsname * @param[out] sections a pointer to the target array of pointers * * @return The index of the top-level label ("." is never put in there) */ /* TWENTY-ONE uses */ s32 dnsname_to_dnsname_vector(const u8* dns_name, dnsname_vector* name); u32 dnsname_vector_copy(dnsname_vector *dst, const dnsname_vector* src); u32 dnsname_vector_len(dnsname_vector *name_vector); /***************************************************************************** * * STACK * *****************************************************************************/ /** @brief Converts a stack of dns labels to a C string * * Converts a stack of dns labels to a C string * * @param[in] name a pointer to the dnslabel stack * @param[in] top the index of the top of the stack * @param[in] str a pointer to a buffer that will get the c-string * * @return Returns the length of the string */ /* ONE use */ u32 dnslabel_stack_to_cstr(const const_dnslabel_stack_reference name, s32 top, char* str); /* ONE use */ u32 dnslabel_stack_to_dnsname(const const_dnslabel_stack_reference name, s32 top, u8* str_start); /* ONE use */ u32 dnsname_stack_to_dnsname(const dnsname_stack* name_stack, u8* name_start); /* ONE use, returns the fqdn len */ u32 dnsname_stack_len(const dnsname_stack* name_stack); /* TWO uses (debug) */ u32 dnsname_stack_to_cstr(const dnsname_stack* name, char* str); /* ONE use */ bool dnsname_equals_dnsname_stack(const u8* str, const dnsname_stack* name); bool dnsname_under_dnsname_stack(const u8* str, const dnsname_stack* name); /* FOUR uses */ s32 dnsname_stack_push_label(dnsname_stack* dns_name, const u8* dns_label); /* FOUR uses */ s32 dnsname_stack_pop_label(dnsname_stack* name); s32 dnsname_to_dnsname_stack(const u8* dns_name, dnsname_stack* name); /** @brief Allocates and duplicates a name with ZALLOC. * * Allocates and duplicates a name ZALLOC. * * @param[in] name a pointer to the dnsname * * @return A new instance of the dnsname. */ u8 *dnsname_zdup(const u8 *name); /** @brief Converts a name to a newly allocated dns name with ZALLOC. * * Converts a name to a newly allocated dns name with ZALLOC. * * @param domainname a pointer to the name * * @return a new instance of the name converted to a dnsname */ u8 *dnsname_zdup_from_name(const char* domainname); void dnsname_zfree(u8 *name); /** @brief Allocates and duplicates a label with ZALLOC. * * Allocates and duplicates a label with ZALLOC. * * @param[in] name a pointer to the label * * @return A new instance of the label */ u8 *dnslabel_zdup(const u8 *name); void dnslabel_zfree(u8 *name); /** * * Expands a compressed FQDN from a wire. * * @param wire_base_ the address of the wire buffer * @param wire_size the size of the wire buffer * @param compressed_fqdn the address, in the wire buffer, of the FQDN to expand * @param output_fqdn the address of the buffer that will get a copy of the expanded FQDN * @param output_fqdn_size the size of the buffer that will get a a copy of the expanded FQDN * * @return a pointer to the next byte after the expanded FQDN (ie: points to a type) or NULL if an error occurred */ const u8* dnsname_expand_compressed(const void *wire_base_, size_t wire_size, const void *compressed_fqdn, u8 *output_fqdn, u32 output_fqdn_size); /** * * Skip a compressed FQDN from a wire. * * @param wire_base_ the address of the wire buffer * @param wire_size the size of the wire buffer * @param compressed_fqdn the address, in the wire buffer, of the FQDN to expand * * @return a pointer to the next byte after the FQDN (ie: points to a type) or NULL if an error occurred */ const u8* dnsname_skip_compressed(const void *wire_base_, size_t wire_size, const void *compressed_fqdn); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnsname_set.h0000644000000000000000000000013214505005532024272 xustar000000000000000030 mtime=1695812442.045976502 30 atime=1695812445.788030096 30 ctime=1695812494.224723807 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnsname_set.h0000664000374500037450000001064614505005532024243 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _DNSNAME_SET_H #define _DNSNAME_SET_H #include #ifdef __cplusplus extern "C" { #endif #define DNSNAME_SET_MEMORY_POOL_SIZE 512 /* * A structure to hold both children with direct access */ typedef struct dnsname_node dnsname_node; struct dnsname_children { struct dnsname_node* left; struct dnsname_node* right; }; /* * An union to have access to the children with direct or indexed access */ typedef union dnsname_children_union dnsname_children_union; union dnsname_children_union { struct dnsname_children lr; struct dnsname_node * child[2]; }; /* * The node structure CANNOT have a varying size on a given collection * This means that the digest size is a constant in the whole tree */ struct dnsname_node { union dnsname_children_union children; const u8* key; }; typedef struct dnsname_set dnsname_set; struct dnsname_set { dnsname_node pool[DNSNAME_SET_MEMORY_POOL_SIZE]; dnsname_node *next_free; dnsname_node *head; }; typedef struct dnsname_set_iterator dnsname_set_iterator; struct dnsname_set_iterator { dnsname_node* next; dnsname_node* limit; }; static inline void dnsname_set_init(dnsname_set* set) { set->next_free = set->pool; set->head = NULL; } static inline bool dnsname_set_insert(dnsname_set* set, const u8 *name) { if(set->next_free >= &set->pool[DNSNAME_SET_MEMORY_POOL_SIZE]) { return FALSE; } dnsname_node** nodep; dnsname_node* node; nodep = &set->head; node = *nodep; while(node != NULL) { int cmp = dnsname_compare(name, node->key); if(cmp == 0) { return TRUE; } nodep = &node->children.child[(cmp > 0) & 1]; node = *nodep; } *nodep = set->next_free++; node = *nodep; node->children.lr.left = NULL; node->children.lr.right = NULL; node->key = (u8*)name; return TRUE; } static inline void dnsname_set_iterator_init(dnsname_set* set, dnsname_set_iterator* iter) { iter->next = set->pool; iter->limit = set->next_free; } static inline bool dnsname_set_iterator_hasnext(dnsname_set_iterator* iter) { return iter->next < iter->limit; } static inline dnsname_node* dnsname_set_iterator_next_node(dnsname_set_iterator* iter) { return iter->next++; } #ifdef __cplusplus } #endif #endif /* _DNSNAME_SET_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/dnssec_errors.h0000644000000000000000000000013214505005532024645 xustar000000000000000030 mtime=1695812442.102977318 30 atime=1695812445.790030125 30 ctime=1695812494.226723836 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/dnssec_errors.h0000664000374500037450000001213414505005532024610 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup error dnssec * @ingroup dnscore * @brief DNSSEC error codes * * @{ */ #ifndef _DNSSEC_ERROR_H #define _DNSSEC_ERROR_H #define DNSSEC_ERROR_BASE 0x80050000 #define DNSSEC_ERROR_CODE(code_) ((s32)(DNSSEC_ERROR_BASE+(code_))) #define DNSSEC_ERROR_NOENGINE DNSSEC_ERROR_CODE( 1) #define DNSSEC_ERROR_INVALIDENGINE DNSSEC_ERROR_CODE( 2) #define DNSSEC_ERROR_CANTPOOLTHREAD DNSSEC_ERROR_CODE( 4) #define DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM DNSSEC_ERROR_CODE( 10) #define DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM DNSSEC_ERROR_CODE( 11) #define DNSSEC_ERROR_FILE_FORMAT_VERSION DNSSEC_ERROR_CODE( 12) #define DNSSEC_ERROR_EXPECTED_CLASS_IN DNSSEC_ERROR_CODE( 13) #define DNSSEC_ERROR_EXPECTED_TYPE_DNSKEY DNSSEC_ERROR_CODE( 14) #define DNSSEC_ERROR_DUPLICATEKEY DNSSEC_ERROR_CODE( 64) #define DNSSEC_ERROR_INCOMPLETEKEY DNSSEC_ERROR_CODE( 65) #define DNSSEC_ERROR_KEYSTOREPATHISTOOLONG DNSSEC_ERROR_CODE( 66) #define DNSSEC_ERROR_UNABLETOCREATEKEYFILES DNSSEC_ERROR_CODE( 67) #define DNSSEC_ERROR_KEYWRITEERROR DNSSEC_ERROR_CODE( 68) #define DNSSEC_ERROR_BNISNULL DNSSEC_ERROR_CODE( 69) #define DNSSEC_ERROR_BNISBIGGERTHANBUFFER DNSSEC_ERROR_CODE( 70) #define DNSSEC_ERROR_UNEXPECTEDKEYSIZE DNSSEC_ERROR_CODE( 71) #define DNSSEC_ERROR_KEYISTOOBIG DNSSEC_ERROR_CODE( 72) #define DNSSEC_ERROR_KEYRING_ALGOTAG_COLLISION DNSSEC_ERROR_CODE( 73) #define DNSSEC_ERROR_KEYRING_KEY_IS_INVALID DNSSEC_ERROR_CODE( 74) #define DNSSEC_ERROR_KEYRING_KEY_IS_NOT_PRIVATE DNSSEC_ERROR_CODE( 75) //#define DNSSEC_ERROR_KEY_INITIALISATION_FAILED DNSSEC_ERROR_CODE( 76) #define DNSSEC_ERROR_KEY_GENERATION_FAILED DNSSEC_ERROR_CODE( 77) #define DNSSEC_ERROR_NO_KEY_FOR_DOMAIN DNSSEC_ERROR_CODE( 78) #define DNSSEC_ERROR_CANNOT_WRITE_NEW_FILE DNSSEC_ERROR_CODE( 79) // would overwrite #define DNSSEC_ERROR_FIELD_NOT_HANDLED DNSSEC_ERROR_CODE( 80) #define DNSSEC_ERROR_CANNOT_READ_KEY_FROM_RDATA DNSSEC_ERROR_CODE( 81) #define DNSSEC_ERROR_RSASIGNATUREFAILED DNSSEC_ERROR_CODE(128) #define DNSSEC_ERROR_DSASIGNATUREFAILED DNSSEC_ERROR_CODE(129) #define DNSSEC_ERROR_ECDSASIGNATUREFAILED DNSSEC_ERROR_CODE(130) #define DNSSEC_ERROR_EDDSASIGNATUREFAILED DNSSEC_ERROR_CODE(131) #define DNSSEC_ERROR_SIGNATUREFAILED DNSSEC_ERROR_CODE(132) //#define DNSSEC_ERROR_RSAVERIFICATIONFAILED DNSSEC_ERROR_CODE(131) //#define DNSSEC_ERROR_DSAVERIFICATIONFAILED DNSSEC_ERROR_CODE(132) //#define DNSSEC_ERROR_ECDSAVERIFICATIONFAILED DNSSEC_ERROR_CODE(133) #define DNSSEC_ERROR_NSEC3_INVALIDZONESTATE DNSSEC_ERROR_CODE(256) #define DNSSEC_ERROR_NSEC3_LABELTODIGESTFAILED DNSSEC_ERROR_CODE(257) #define DNSSEC_ERROR_NSEC3_DIGESTORIGINOVERFLOW DNSSEC_ERROR_CODE(258) #define DNSSEC_ERROR_NSEC3_LABELNOTFOUND DNSSEC_ERROR_CODE(259) #define DNSSEC_ERROR_NSEC_INVALIDZONESTATE DNSSEC_ERROR_CODE(384) #define DNSSEC_ERROR_RRSIG_NOENGINE DNSSEC_ERROR_CODE(512) #define DNSSEC_ERROR_RRSIG_NOZONEKEYS DNSSEC_ERROR_CODE(513) #define DNSSEC_ERROR_RRSIG_NOUSABLEKEYS DNSSEC_ERROR_CODE(514) #define DNSSEC_ERROR_RRSIG_NOSOA DNSSEC_ERROR_CODE(515) #define DNSSEC_ERROR_RRSIG_NOSIGNINGKEY DNSSEC_ERROR_CODE(516) #define DNSSEC_ERROR_RRSIG_UNSUPPORTEDRECORD DNSSEC_ERROR_CODE(517) #define SSL_ERROR_BASE 0x800f0000 #define SSL_ERROR_CODE(code_) ((s32)(SSL_ERROR_BASE+(code_))) #endif // _DNSSEC_ERROR_H yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/empty-input-stream.h0000644000000000000000000000013114505005532025555 xustar000000000000000030 mtime=1695812442.072976889 29 atime=1695812445.78903011 30 ctime=1695812494.229723878 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/empty-input-stream.h0000664000374500037450000000436714505005532025532 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif void empty_input_stream_init(input_stream *stream); #ifdef __cplusplus } #endif /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/error_state.h0000644000000000000000000000013114505005532024322 xustar000000000000000030 mtime=1695812442.076976946 29 atime=1695812445.78903011 30 ctime=1695812494.231723907 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/error_state.h0000664000374500037450000000500114505005532024261 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #include #define ERROR_STATE_FAILURE_LOG_PERIOD (ONE_SECOND_US * 60) struct error_state_s { mutex_t mtx; s64 first_epoch; s64 last_epoch; s64 count; int error; }; typedef struct error_state_s error_state_t; #define ERROR_STATE_INITIALIZER {MUTEX_INITIALIZER, 0, 0, 0, 0} bool error_state_log(error_state_t *es, ya_result err); void error_state_clear(error_state_t *es, logger_handle *log_handle, int level, const char *notice_message); bool error_state_log_locked(error_state_t *es, ya_result err); void error_state_clear_locked(error_state_t *es, logger_handle *log_handle, int level, const char *notice_message); yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/fdtools.h0000644000000000000000000000013214505005532023444 xustar000000000000000030 mtime=1695812442.101977304 30 atime=1695812445.790030125 30 ctime=1695812494.233723936 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/fdtools.h0000664000374500037450000002317214505005532023413 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoretools Generic Tools * @ingroup dnscore * @brief * * @{ */ #pragma once #include #include #include #ifdef __cplusplus extern "C" { #endif #define US_RATE(x) (0.000001 * (x)) #ifndef _DIRENT_HAVE_D_TYPE #ifndef DT_UNKNOWN #define DT_UNKNOWN 0 #endif #ifndef DT_REG #define DT_REG 8 #endif #ifndef DT_DIR #define DT_DIR 4 #endif #endif #ifndef O_CLOEXEC #if __linux__ || __OpenBSD__ #define O_CLOEXEC 0200000 #elif __FreeBSD__ #define O_CLOEXEC 04000000 #elif __APPLE__ #if __DARWIN_C_LEVEL >= 200809L #define O_CLOEXEC 0x1000000 #endif #elif defined(WIN32) #define O_CLOEXEC 0200000 #else #error "O_CLOEXEC not available and I don't know what placeholder value to use for this system" #endif #define DNSCORE_FDTOOLS_CLOEXEC 1 #endif /** * When stored statically, use dirent_storage to mitigate very long names issues. * Note also than on some architectures (ie: Solaris) the space reserved for the * name is only 1 byte. * */ union dirent_storage { struct dirent _dirent; char _reserved[PATH_MAX]; }; typedef union dirent_storage dirent_storage; /** * Writes fully the buffer to the fd * It will only return a short count for system errors. * ie: fs full, non-block would block, fd invalid/closed, ... */ ssize_t writefully(int fd, const void *buf, size_t count); /** * Reads fully the buffer from the fd * It will only return a short count for system errors. * ie: fs full, non-block would block, fd invalid/closed, ... */ ssize_t readfully(int fd, void *buf, size_t count); ssize_t writefully_limited(int fd, const void *buf, size_t count, double minimum_rate); ssize_t readfully_limited(int fd, void *buf, size_t count, double minimum_rate_us); ssize_t readfully_limited_ex(int fd, void *buf, size_t count, s64 timeout_us, double minimum_rate_us); /** * Reads an ASCII text line from fd, stops at EOF or '\n' */ ssize_t readtextline(int fd, char *buf, size_t count); /** * Deletes a file (see man 2 unlink). * Handles EINTR and other retry errors. * * @param fd * @return */ int unlink_ex(const char *folder, const char *filename); /** * Copies the absolute path of a file into a buffer. * * @param filename the file name * @param buffer the output buffer * @param buffer_size the size of the output buffer * @return the string length (without the terminator) */ ya_result file_get_absolute_path(const char *filename, char *buffer, size_t buffer_size); /** * Opens a file. (see man 2 open) * Handles EINTR and other retry errors. * Safe to use in the logger thread as it only logs (debug) if the current * thread is not the logger's * * @param fd * @return */ ya_result open_ex(const char *pathname, int flags); /** * Opens a file, create if it does not exist. (see man 2 open with O_CREAT) * Handles EINTR and other retry errors. * * @param fd * @return */ ya_result open_create_ex(const char *pathname, int flags, mode_t mode); /** * Wrapper * * @param template * @return */ int mkstemp_ex(char *tmp_name_template); /** * Opens a file, create if it does not exist. (see man 2 open with O_CREAT) * Handles EINTR and other retry errors. * This version of open_create_ex does NOT log anything, which is very important sometimes in the logger thread * * @param fd * @return */ ya_result open_create_ex_nolog(const char *pathname, int flags, mode_t mode); /** * Closes a file descriptor (see man 2 close) * Handles EINTR and other retry errors. * At return the file will be closed or not closable. * * @param fd * @return */ #if !DNSCORE_HAS_CLOSE_EX_REF ya_result close_ex(int fd); #else ya_result close_ex_ref(int* fdp); #define close_ex(fd_) close_ex_ref((int*)&(fd_)) #endif /** * Closes a file descriptor (see man 2 close) * Handles EINTR and other retry errors. * At return the file will be closed or not closable. * * @param fd * @return */ #if !DNSCORE_HAS_CLOSE_EX_REF ya_result close_ex_nolog(int fd); #else ya_result close_ex_nolog_ref(int* fdp); #define close_ex_nolog(fd_) close_ex_nolog_ref((int*)&(fd_)) #endif int fsync_ex(int fd); int fdatasync_ex(int fd); int dup_ex(int fd); int dup2_ex(int old_fd, int new_fd); int truncate_ex(const char *path, off_t len); int ftruncate_ex(int fd, off_t len); /** * Returns the type of socket. * * @param fd the file descriptor of the socket * @return SOCK_STREAM, SOCK_DGRAM, SOCK_RAW or an errno error code like MAKE_ERRON_ERROR(EBADF) or MAKE_ERRON_ERROR(ENOTSOCK) */ ya_result fd_getsockettype(int fd); /** * Returns the size of a file * * @param name * @return */ s64 filesize(const char *name); /** * Checks for existence of a file/dir/link * * @param name the file name * * @return 1 if the file exists, 0 if the file does not exists, or an error code (access rights & cie) */ ya_result file_exists(const char *name); /** * * Checks if a file exists and is a link * * @param name the file name * * @return 0 : not a link * 1 : a link * < 0 : error */ ya_result file_is_link(const char *name); /** * * Checks if a file exists and is a directory * * @param name the file name * * @return 0 : not a link * 1 : a link * < 0 : error */ ya_result file_is_directory(const char *name); /** * * @param pathname * @param mode * @return */ #define MKDIR_EX_PATH_TO_FILE 1 // ie: pathname points to a file, so skip the file part int mkdir_ex(const char *pathname, mode_t mode, u32 flags); /** * Returns the modification time of the file in microseconds * This does not mean the precision of the time is that high. * This is only to simplify reading the time on a file. * * @param name the file name * @param timestamp a pointer to the timestamp * @return an error code */ ya_result file_mtime(const char *name, s64 *timestamp); /** * Returns the modification time of the file in microseconds * This does not mean the precision of the time is that high. * This is only to simplify reading the time on a file. * * @param fd the file descriptor * @param timestamp a pointer to the timestamp * @return an error code */ ya_result fd_mtime(int fd, s64 *timestamp); ya_result fd_setcloseonexec(int fd); ya_result fd_setnonblocking(int fd); /** * Fixes an issue with the dirent not always set as expected. * * The type can be set to DT_UNKNOWN instead of file or directory. * In that case the function will call stats to get the type. */ u8 dirent_get_file_type(const char* folder, const char *name); u8 dirent_get_type_from_fullpath(const char *fullpath); #define READDIR_CALLBACK_CONTINUE 0 #define READDIR_CALLBACK_ENTER 1 #define READDIR_CALLBACK_EXIT 2 typedef ya_result readdir_callback(const char *basedir, const char* file, u8 filetype, void *args); ya_result readdir_forall(const char *basedir, readdir_callback *func, void *args); struct file_mtime_set_s; #if !FDTOOLS_C_ typedef struct file_mtime_set_s file_mtime_set_t; file_mtime_set_t* file_mtime_set_get_for_file(const char *filename); void file_mtime_set_add_file(file_mtime_set_t *ctx, const char *filename); bool file_mtime_set_modified(file_mtime_set_t *ctx); void file_mtime_set_clear(file_mtime_set_t *ctx); void file_mtime_set_delete(file_mtime_set_t *ctx); #else struct file_mtime_set_s* file_mtime_set_get_for_file(const char *filename); void file_mtime_set_add_file(struct file_mtime_set_s *ctx, const char *filename); bool file_mtime_set_modified(struct file_mtime_set_s *ctx); void file_mtime_set_clear(struct file_mtime_set_s *ctx); void file_mtime_set_delete(struct file_mtime_set_s *ctx); #endif #define ACCESS_CHECK_READ R_OK #define ACCESS_CHECK_WRITE W_OK #define ACCESS_CHECK_EXECUTE X_OK #define ACCESS_CHECK_EXISTS F_OK #define ACCESS_CHECK_READWRITE (ACCESS_CHECK_READ|ACCESS_CHECK_WRITE) ya_result access_check(const char* path, int mode); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/file.h0000644000000000000000000000013214505005532022711 xustar000000000000000030 mtime=1695812442.104977347 30 atime=1695812445.790030125 30 ctime=1695812494.235723964 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/file.h0000664000374500037450000000664514505005532022666 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif struct file_t_; typedef struct file_t_* file_t; struct file_vtbl { ssize_t (*read)(file_t f, void *buffer, ssize_t size); ssize_t (*write)(file_t f, const void *buffer, ssize_t size); ssize_t (*seek)(file_t f, ssize_t position, int from); ssize_t (*tell)(file_t f); int (*flush)(file_t f); int (*close)(file_t f); ssize_t (*size)(file_t f); int (*resize)(file_t f, ssize_t size); // add unlink // add a copy of the path ? // add flags, starting with "is slow" meaning it would benefit from caching }; struct file_t_ { const struct file_vtbl *vtbl; }; static inline ssize_t file_read(file_t f, void *buffer, ssize_t size) { return f->vtbl->read(f, buffer, size); } static inline ssize_t file_write(file_t f, const void *buffer, ssize_t size) { return f->vtbl->write( f, buffer, size); } static inline ssize_t file_seek(file_t f, ssize_t position, int from) { return f->vtbl->seek(f, position, from); } static inline ssize_t file_tell(file_t f) { return f->vtbl->tell(f); } static inline int file_flush(file_t f) { return f->vtbl->flush(f); } static inline int file_close(file_t f) { return f->vtbl->close(f); } static inline ssize_t file_size(file_t f) { return f->vtbl->size(f); } static inline int file_resize(file_t f, ssize_t size) { return f->vtbl->resize(f, size); } #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/file_input_stream.h0000644000000000000000000000013214505005531025502 xustar000000000000000030 mtime=1695812441.984975629 30 atime=1695812445.786030067 30 ctime=1695812494.237723993 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/file_input_stream.h0000664000374500037450000000563314505005531025453 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _FILE_INPUT_STREAM_H #define _FILE_INPUT_STREAM_H #include #ifdef __cplusplus extern "C" { #endif ya_result file_input_stream_open(input_stream *stream, const char *filename); ya_result file_input_stream_open_ex(input_stream *stream, const char *filename, int flags); /* Create an input stream and assigns the fd to it. */ ya_result fd_input_stream_attach(input_stream *stream, int fd); ya_result fd_input_stream_attach_noclose(input_stream *stream, int fd); void fd_input_stream_detach(input_stream *stream); ya_result fd_input_stream_get_filedescriptor(input_stream* stream); ya_result fd_input_stream_seek(input_stream* stream, u64 offset); bool is_fd_input_stream(input_stream* stream); void file_input_steam_advise_sequential(input_stream* stream); #ifdef __cplusplus } #endif #endif /* _FILE_INPUT_STREAM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/file_output_stream.h0000644000000000000000000000013214505005532025704 xustar000000000000000030 mtime=1695812442.007975958 30 atime=1695812445.787030082 30 ctime=1695812494.239724022 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/file_output_stream.h0000664000374500037450000000756414505005532025662 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _FILE_OUTPUT_STREAM_H #define _FILE_OUTPUT_STREAM_H #include #ifdef __cplusplus extern "C" { #endif ya_result file_output_stream_open(output_stream *os, const char *filename); /** * man 2 open */ ya_result file_output_stream_open_ex(output_stream *os, const char *filename,int flags, mode_t mode); /* * This version of open_create_ex does NOT log anything, which is very important sometimes in the logger thread */ ya_result file_output_stream_open_ex_nolog(output_stream *os, const char *filename,int flags, mode_t mode); void file_output_stream_close_nolog(output_stream* os); ya_result file_output_stream_create(output_stream *stream, const char *filename,mode_t mode); /** * Returns MAKE_ERRNO_ERROR(EEXIST) if the file exists already. */ ya_result file_output_stream_create_excl(output_stream* stream, const char* filename, mode_t mode); /** * Enables or disables the write mode of the steam as "full" * In "full" mode, the stream will stay blocked on a write if a recoverable * error occurs. (ie: there is no space left). * * Do NOT use this for the loggers as it would make it impossible to act on HUP * * Main target: journal * * @param stream * @param full_writes * @return */ ya_result file_output_stream_set_full_writes(output_stream* stream, bool full_writes); ya_result fd_output_stream_attach(output_stream *os, int fd); ya_result fd_output_stream_attach_noclose(output_stream *os, int fd); void fd_output_stream_detach(output_stream *os); ya_result fd_output_stream_get_filedescriptor(output_stream *os); s64 fd_output_stream_get_size(output_stream *os); bool is_fd_output_stream(output_stream *os); void file_output_steam_advise_sequential(output_stream* os); #ifdef __cplusplus } #endif #endif /* _FILE_OUTPUT_STREAM_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/file-pool.h0000644000000000000000000000013014505005532023656 xustar000000000000000030 mtime=1695812442.075976932 29 atime=1695812445.78903011 29 ctime=1695812494.24172405 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/file-pool.h0000664000374500037450000001071314505005532023624 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #ifdef __cplusplus extern "C" { #endif #ifndef __FILE_POOL_C__ struct file_pool_t_anon { const int hidden; }; typedef struct file_pool_t_anon* file_pool_t; struct file_pool_file_t_anon { const int hidden; }; typedef struct file_pool_file_t_anon* file_pool_file_t; #endif file_pool_t file_pool_init_ex(const char * const pool_name, int opened_file_count_max, u32 cache_entries); // name is for logging file_pool_t file_pool_init(const char * const pool_name, int fd_max); // name is for logging file_pool_file_t file_pool_open(file_pool_t fp, const char *filename); file_pool_file_t file_pool_open_ex(file_pool_t fp, const char *filename, int flags, mode_t mode); file_pool_file_t file_pool_create(file_pool_t fp, const char *filename, mode_t mode); file_pool_file_t file_pool_create_excl(file_pool_t fp, const char *filename, mode_t mode); void file_pool_finalize(file_pool_t fp); file_pool_file_t file_dup(file_pool_file_t file); ya_result file_pool_unlink_from_pool_and_filename(file_pool_t fp, const char * filename); ya_result file_pool_read(file_pool_file_t f, void *buffer, size_t bytes); ya_result file_pool_readfully(file_pool_file_t f, void *buffer, size_t bytes); ya_result file_pool_write(file_pool_file_t f, const void *buffer, size_t bytes); ya_result file_pool_writefully(file_pool_file_t f, const void *buffer, size_t bytes); ya_result file_pool_flush(file_pool_file_t f); ssize_t file_pool_seek(file_pool_file_t f, ssize_t position, int from); ya_result file_pool_tell(file_pool_file_t f, size_t *position); ya_result file_pool_resize(file_pool_file_t f, size_t size); ya_result file_pool_get_size(file_pool_file_t f, size_t *size); ya_result file_pool_close(file_pool_file_t f); // flushes, but only closes the file when fd are needed ya_result file_pool_unlink(file_pool_file_t f); // no reference will be kept for that inode as soon as the last reference is lost const char *file_pool_filename(const file_pool_file_t f); void file_pool_file_output_stream_init(output_stream *os, file_pool_file_t f); void file_pool_file_output_stream_set_full_writes(output_stream *os, bool full_writes); void file_pool_file_output_stream_detach(output_stream *os); void file_pool_file_input_stream_init(input_stream *is, file_pool_file_t f); void file_pool_file_input_stream_detach(input_stream *is); void file_pool_file_input_stream_set_full_reads(input_stream *is, bool full_writes); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/filesystem-file.h0000644000000000000000000000013014505005532025071 xustar000000000000000029 mtime=1695812442.06397676 29 atime=1695812445.78903011 30 ctime=1695812494.243724079 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/filesystem-file.h0000664000374500037450000000450514505005532025041 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #include #ifdef __cplusplus extern "C" { #endif ya_result filesystem_file_open_ex(file_t *fp, const char *filename, int flags); ya_result filesystem_file_create_ex(file_t *fp, const char *filename, int flags, mode_t mode); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/fingerprint.h0000644000000000000000000000013214505005532024321 xustar000000000000000030 mtime=1695812442.039976416 30 atime=1695812445.788030096 30 ctime=1695812494.245724108 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/fingerprint.h0000664000374500037450000002403014505005532024262 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore * @ingroup dnscore * @brief fingerprints, mapping between answer code and dns code * * @{ * *----------------------------------------------------------------------------*/ #ifndef _FINGERPRINT_H #define _FINGERPRINT_H #include #ifdef __cplusplus extern "C" { #endif /* This makes the finger print of the name server */ enum finger_print { /* * */ FP_RCODE_NOERROR = RCODE_NOERROR, FP_RCODE_FORMERR = RCODE_FORMERR, FP_RCODE_SERVFAIL = RCODE_SERVFAIL, FP_RCODE_NXDOMAIN = RCODE_NXDOMAIN, FP_RCODE_NOTIMP = RCODE_NOTIMP, FP_RCODE_REFUSED = RCODE_REFUSED, FP_RCODE_YXDOMAIN = RCODE_YXDOMAIN, FP_RCODE_YXRRSET = RCODE_YXRRSET, FP_RCODE_NXRRSET = RCODE_NXRRSET, FP_RCODE_NOTAUTH = RCODE_NOTAUTH, FP_RCODE_NOTZONE = RCODE_NOTZONE, /* * Obsolete */ FP_DATABASE_ERR = RCODE_SERVFAIL, /* NOT USED */ FP_ANCOUNT_NOT_0 = RCODE_FORMERR, /* NOT USED */ FP_TC_BIT_SET = RCODE_FORMERR, /* NOT USED */ FP_QR_BIT_SET = RCODE_FORMERR, FP_Z_BITS_SET = RCODE_FORMERR, /* NOT USED */ FP_RCODE_BITS_SET = RCODE_FORMERR, /* NOT USED */ FP_ZOCOUNT_NOT_1 = RCODE_FORMERR, /* NOT USED */ FP_CH_REFUSED = RCODE_FORMERR, /* NOT USED */ FP_NOT_SUPP_CLASS = RCODE_NOTIMP, /* NOT USED, same remark as for FP_NOT_SUPP_TYPE */ FP_NSCOUNT_NOT_0 = RCODE_FORMERR, /* Message processing. Not used anymore (conflicts with updates) */ /* * Message processing */ FP_PACKET_DROPPED = RCODE_FORMERR, /* */ FP_MESG_OK = RCODE_NOERROR, /* The message processing didn't found anything wrong with * the query. */ FP_QDCOUNT_BIG_1 = RCODE_FORMERR, /* The message processing rejected the query because #QD>1 * which is not supported by yadifa */ FP_QDCOUNT_IS_0 = RCODE_FORMERR, /* The message processing rejected the query because #QD==0 */ FP_ARCOUNT_NOT_0 = RCODE_FORMERR, /* The message processing rejected the query because #AR>0 * This only makes sense if there is no TSIG nor EDNS support * implemented. And even then : is there no conflict with updates ? */ FP_QNAME_COMPRESSED = RCODE_NOTIMP, /* The message processing found out that the queried name was * too long (labels too big or name too big) */ FP_NAME_TOO_LARGE = RCODE_FORMERR, /* The message processing found out that the queried name was * too long (labels too big or name too big) */ FP_NAME_FORMAT_ERROR = RCODE_FORMERR, /* Bad compression of a NAME */ FP_INCORR_PROTO = RCODE_FORMERR, /* The message processing found out that something "wrong" * was queried (ie: AXFR/IXFR on UDP). * THIS NEEDS TO BE CHECKED (xXFR on UDP is not always wrong) */ FP_NOT_SUPP_OPC = RCODE_NOTIMP, /* The message processing found an unsupported opcode in the * query */ FP_XFR_REFUSED = RCODE_NOTAUTH, /* The transfer (AXFR/IXFR) has been refused by ACL */ FP_XFR_UP_TO_DATE = RCODE_NOERROR, /* no XFR necessary */ FP_XFR_BROKENZONE = RCODE_SERVFAIL, /* the zone is in an invalid state */ FP_XFR_QUERYERROR = RCODE_FORMERR, FP_TSIG_ERROR = RCODE_NOTAUTH, /* The message processing handled the included TSIG but rejected * it. MUST be NOTAUTH. */ FP_TSIG_UNEXPECTED = RCODE_FORMERR, /* The message processing did not expect the included TSIG */ FP_TSIG_BROKEN = RCODE_FORMERR, /* The TSIG cannot be read properly */ FP_TSIG_IS_NOT_LAST = RCODE_FORMERR, /* There is a record after the TSIG */ FP_EDNS_BAD_VERSION = RCODE_BADVERS, /* Found an EDNS version that is not 0 * */ FP_NOT_SUPP_TYPE = RCODE_FORMERR, /* AXFR udp query, OPT query */ FP_SLAVE_NOTIFIES_MASTER = RCODE_REFUSED, FP_NONMASTER_NOTIFIES_SLAVE = RCODE_REFUSED, /* notify from something not in the masters list */ FP_NOTIFY_UNKNOWN_ZONE = RCODE_NOTAUTH, FP_UNEXPECTED_RR_IN_QUERY = RCODE_FORMERR, /* trash in the packet */ FP_ERROR_READING_QUERY = RCODE_FORMERR, /* * Database */ FP_ACCESS_REJECTED = RCODE_REFUSED, /* access to the database has been rejected */ FP_NOTIFY_REJECTED = RCODE_REFUSED, /* access to the database has been rejected */ FP_NOTIFY_QUERYERROR = RCODE_FORMERR, FP_CLASS_NOTFOUND = RCODE_REFUSED, /* class not supported/not in the database */ FP_BASIC_LABEL_NOTFOUND = RCODE_NXDOMAIN, /* The label has not been found inside the zone database */ FP_BASIC_LABEL_DELEGATION = RCODE_NOERROR, /* The label was part of a delegation */ FP_BASIC_RECORD_NOTFOUND = RCODE_NOERROR, /* we didn't found a resource record */ FP_BASIC_RECORD_FOUND = RCODE_NOERROR, /* we found a resource record */ FP_CNAME_LOOP = RCODE_NOERROR, /* we detected a loop in the CNAMEs */ FP_CNAME_BROKEN = RCODE_SERVFAIL, /* we detected an issue in the database */ FP_CNAME_MAXIMUM_DEPTH = RCODE_NOERROR, /* we reached the maximum allowed depth on a CNAME chain */ FP_NSEC3_RECORD_NOTFOUND = RCODE_NOERROR, /* we didn't found a record and we can prove it with nsec3 */ FP_NSEC3_LABEL_NOTFOUND = RCODE_NXDOMAIN, /* we didn't found a domain and we can prove it with nsec3 */ FP_NSEC_RECORD_NOTFOUND = RCODE_NOERROR, /* we didn't found a record and we can prove it with nsec3 */ FP_NSEC_LABEL_NOTFOUND = RCODE_NXDOMAIN, /* we didn't found a domain and we can prove it with nsec3 */ FP_CANNOT_DYNUPDATE = RCODE_REFUSED, /* the zone has been frozen (maintenance or admin) and cannot * accept an update until being unfrozen */ FP_UPDATE_UNKNOWN_ZONE = RCODE_NOTZONE, /* dynupdate on a zone we are not AA of */ FP_NOZONE_FOUND = RCODE_REFUSED, /* When a dynamic update does not find the zone it's supposed * to update. */ FP_INVALID_ZONE = RCODE_SERVFAIL, FP_IXFR_UDP = RCODE_NOTIMP, FP_FEATURE_DISABLED = RCODE_NOTIMP, FP_CANNOT_HOLD_AXFR_DATA = RCODE_SERVFAIL }; typedef enum finger_print finger_print; #ifdef __cplusplus } #endif #endif /* _FINGERPRINT_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/format.h0000644000000000000000000000013214505005532023262 xustar000000000000000030 mtime=1695812442.041976445 30 atime=1695812445.788030096 30 ctime=1695812494.247724136 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/format.h0000664000374500037450000002667114505005532023240 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup format C-string formatting * @ingroup dnscore * @brief * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #include #include #include #define OSPRINT_DUMP_LAYOUT_GROUP_MASK 0x0000ff00U #define OSPRINT_DUMP_LAYOUT_GROUP_SHIFT 0x00000008U #define OSPRINT_DUMP_LAYOUT_SEPARATOR_MASK 0x000000ffU #define OSPRINT_DUMP_LAYOUT_SEPARATOR_SHIFT 0x00000000U #define OSPRINT_DUMP_OFFSET 0x80000000U #define OSPRINT_DUMP_ADDRESS 0x40000000U #define OSPRINT_DUMP_HEX 0x20000000U #define OSPRINT_DUMP_TEXT 0x10000000U #define OSPRINT_DUMP_SQUEEZE_ZEROES 0x08000000U // predefined layouts #define OSPRINT_DUMP_LAYOUT_DENSE 0x0000ffffU #define OSPRINT_DUMP_LAYOUT_ERIC 0x000003ffU #define OSPRINT_DUMP_LAYOUT_GERY 0x00000003U #define OSPRINT_DUMP_ALL (OSPRINT_DUMP_ADDRESS|OSPRINT_DUMP_HEX|OSPRINT_DUMP_TEXT) #define OSPRINT_DUMP_BUFFER (OSPRINT_DUMP_OFFSET|OSPRINT_DUMP_HEX|OSPRINT_DUMP_TEXT) #define OSPRINT_DUMP_HEXTEXT (OSPRINT_DUMP_HEX|OSPRINT_DUMP_TEXT) #define OSPRINT_DUMP_BASE16 (OSPRINT_DUMP_LAYOUT_DENSE|OSPRINT_DUMP_HEX) /** * * Formats: * * modifier : restrict : * : to : * - : : change justification * 123456789 : : padding space * 0 : : use '0' char for padding * .12345789 : f : for float types, precision to use * hh : iudXxo : half half : 8 bits * h : iudXxo : half : 16 bits * l : iudXxo : long : 32 bits * ll : iudXxo : long long : 64 bits * L : f : long double * * formats : * : * %t : integer, prints the number of tabs on the output * %S : integer, prints the number of spaces on the output * %T : integer, prints the 32/64 bits UTC time on the output * %T : 32 bits = YYYY-MM-DD HH:mm:SS * %lT : 64 bits = YYYY-MM-DD HH:mm:SS * %llT : 64 bits = YYYY-MM-DD HH:mm:SS.NNNNNN * %i : integer, prints the signed 8/16/32/64 bits integer in base 10 on the output * %r : integer, prints the ya_result registered message on the output or the hexadecimal code * %u : integer, prints the unsigned 8/16/32/64 bits integer in base 10 on the output * %d : integer, prints the unsigned 8/16/32/64 bits integer in base 10 on the output * %X : integer, prints the unsigned 8/16/32/64 bits integer in base 16 uppercase on the output * %x : integer, prints the unsigned 8/16/32/64 bits integer in base 16 lowercase on the output * %o : integer, prints the unsigned 8/16/32/64 bits integer in base 8 on the output * %p : void* , prints the pointer in hexadecimal on the output * %P : void* , prints the name of the pointer if possible, else the hexadecimal on the output * %f : double , prints the long double/double/float on the output * %s : char* , prints the ASCIIZ string on the output * %c : char , prints the 8-bits char on the output * %w : format_writer, calls the format_writer callback to print on the output * * Format extension mechanism: * * "%{registeredformatname}" : void*, prints the pointed value on the output * : use ya_result format_registerclass(format_handler_descriptor* fhd) for registration */ /* void* value, output_stream*, s32 padding, char pad_char, bool left_justified, void* reserved */ typedef void format_handler_method(const void*, output_stream*, s32, char, bool, void* reserved_for_method_parameters); typedef struct format_handler_descriptor format_handler_descriptor; // About the %w format: // // a pointer to this can be given as a 'w' parameter ie: "%w" // the writer callback get's called with // void* value as first parameter, what to print // output_stream *os as second parameter, where to write the chars to // s32 padding the number of chars it's supposed to take on the output (minimum) // char padchar the character to use for padding // bool left_justified where to justify the text // void* don't use that one // // ex: // // format_writer temp_fw_0 = {my_complex_or_rare_type_printer_callback, &my_complex_or_rare_type}; // // format("So the value is : '%w'\n", &temp_fw_0); // struct format_writer { format_handler_method *callback; const void * value; }; typedef struct format_writer format_writer; struct format_handler_descriptor { const char* name; int name_len; /* Needed in order to quicken the matching */ format_handler_method* format_handler; }; void format_class_init(); ya_result format_registerclass(const format_handler_descriptor* fhd); /** * %% -> % * %-09lli right-justified 0-padded "long long integer" (s64) * %-9llu right-justified "long long unsigned integer" (u64) * %-20{class} right-justified "class" (class has to be registered) * %-20{class(a,b,c,d)} right-justified "class" called with 4 arguments (class has to be registered) * * %[-][0| ]([hh|h|l|ll]u|i|x)|([L]f)|c|s|{} * * --- * * hh 8 bits * h 16 bits * l 32 bits (The default if no length is given is 32 bits) * ll 64 bits * * i signed integer * u unsigned integer * d unsigned integer * x hexadecimal lo * X hexadecimal hi * b binary (not in yet) * * --- * * L long * * f double * * --- * * c char * * --- * * s asciiz string * * --- * * {class name} pointer to something that will be interpreted by the handler * */ ya_result vosformat(output_stream* os_, const char* fmt, va_list args); ya_result osprint(output_stream* stream,const char* text); ya_result osprintln(output_stream* stream,const char* text); ya_result osformat(output_stream* stream,const char* fmt,...); ya_result osformatln(output_stream* stream,const char* fmt,...); ya_result print(const char* text); ya_result println(const char* text); ya_result format(const char* fmt,...); ya_result formatln(const char* fmt,...); // prefixes time | pid | pthread_self ya_result debug_osformatln(output_stream* stream, const char* fmt, ...); ya_result debug_println(const char* text); int vsnformat(char* out_, size_t out_size, const char* fmt, va_list args); int snformat(char* out, size_t out_size, const char* fmt, ...); /** * This formatter will return an allocated (malloc) string as a result of the format * * @param outp * @param out_size * @param fmt * @param args * @return */ int vasnformat(char** outp, size_t out_size, const char* fmt, va_list args); /** * This formatter will return an allocated (malloc) string as a result of the format * * @param outp * @param out_size * @param fmt * @param ... * @return */ int asnformat(char** outp, size_t out_size, const char* fmt, ...); /** * This formatter will return an allocated (malloc) string as a result of the format * * @param outp * @param fmt * @param ... * @return */ int asformat(char** outp, const char* fmt, ...); /* Used by extensions */ void format_dec_u64(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified); void format_dec_s64(s64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified); void format_hex_u64_lo(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified); void format_hex_u64_hi(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified); void format_oct_u64(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified); void format_asciiz(const char* val, output_stream* stream, s32 padding, char pad_char, bool left_justified); /**/ int osprint_base16(output_stream* os, const u8* rdata, u32 rdata_size); int osprint_base64(output_stream* os, const u8* rdata, u32 rdata_size); void osprint_u32(output_stream* os, u32 value); void osprint_u16(output_stream* os, u16 value); void osprint_u32_hex(output_stream* os, u32 value); void print_char(char value); void osprint_char(output_stream *os, char value); void osprint_char_times(output_stream *os, char value, int times); void osprint_dump_with_base(output_stream *os, const void* data_pointer_, size_t size_, size_t line_size, u32 flags, const void* base_pointer_); void osprint_dump(output_stream *os, const void* data_pointer_, size_t size_, size_t line_size, u32 flags); ya_result osprint_type_bitmap(output_stream *os, const u8 *rdata_pointer, u16 rdata_size); ya_result osprint_rdata(output_stream *os, u16 type, const u8 *rdata_pointer, u16 rdata_size); ya_result osprint_rdata_escaped(output_stream *os, u16 type, const u8 *rdata_pointer, u16 rdata_size); ya_result print_rdata(u16 type, u8 *rdata, u16 rdata_size); void osprint_question(output_stream *os, u8 *qname, u16 qclass, u16 qtype); void print_question(u8 *qname, u16 qclass, u16 qtype); #if 0 /* fix */ #else #define FORMAT_BREAK_ON_INVALID(address__, len__) #endif /* * This is just a tool function used to test vsnformat. * It is not meant for the logger. * It has an output length limitation of 4096 bytes. * * Please use the other functions if possible. */ int fformat(FILE *out, const char *fmt, ...); /** * This tool struct is used so the RDATA part of a record can be printed/formatted * * we would have: * * rdata_desc myrdata={TYPE_SOA, rdata_len, rdata}; * format("bla bla bla %{rdatadesc}", &myrdata); * * */ struct rdata_desc_s { u16 type; u16 len; const u8 * rdata; }; typedef struct rdata_desc_s rdata_desc; yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/hash.h0000644000000000000000000000013014505005532022713 xustar000000000000000029 mtime=1695812442.05697666 29 atime=1695812445.78903011 30 ctime=1695812494.249724165 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/hash.h0000664000374500037450000001236014505005532022661 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Functions used to hash a dns formatted string * * Implements the functions used to hash a dns formatted string. * There functions require the call to an initialization function (hash_init); * * @{ */ #ifndef _HASH_H #define _HASH_H #include typedef u32 hashcode; #include #ifdef __cplusplus extern "C" { #endif #define DNSCORE_HASH_TABLE_CHAR_SET_SIZE 37 // the result of hash_dnslabel((const u8*)"\001*"); #define WILD_LABEL_HASH 3479673052 extern const u32 DNSCORE_HASH_TABLE[256][DNSCORE_HASH_TABLE_CHAR_SET_SIZE]; extern const u32 DNSCORE_HASH_TABLE_MAP[256]; extern const u8* WILD_LABEL; extern const hashcode WILD_HASH; /** @brief Initializes the hash functions * * Initializes the hash function. This MUST be called at least one before * calling any other hash function. * */ void hash_init(); /** @brief Compute the hash code of a dns name (concatenation of pascal strings ending with an empty one.) * * Compute the hash code of a dns name (concatenation of pascal strings ending with an empty one.) * The function hash_init() MUST be called once first. (This requirement will be lifted later) * * @param[in] dns_name the name in its DNS form * * @return the hash code as a 32 bits integer */ hashcode hash_dnsname(const u8* dns_name); /** @brief Compute the hash code of a dns label (one pascal string) * * Compute the hash code of a dns name (a pascal string) * The function hash_init() MUST be called once first. * * This is one of the most-called functions in the ZDB. Its speed is critical. * * @param[in] dns_name the name in its DNS form * * @return the hash code as a 32 bits integer */ static inline hashcode hash_dnslabel(const u8 *dns_label) { u32 len = *dns_label++; u32 hash = DNSCORE_HASH_TABLE[len][0]; const u32 *hash_line = (const u32*) & DNSCORE_HASH_TABLE[1][0]; const u8 * const limit = &dns_label[len]; while(dns_label != limit) { hash += hash_line[DNSCORE_HASH_TABLE_MAP[*dns_label++]]; hash_line += DNSCORE_HASH_TABLE_CHAR_SET_SIZE; } return hash; } /** @brief Compute the hash code of a pascal name * * Compute the hash code of a pascal name. * The function hash_init() MUST be called once first. (This requirement will be lifted later) * An interesting thing about a dnsname label : it's a pascal string. * * @param[in] pascal_name the name in pascal form * * @return the hash code as a 32 bits integer */ hashcode hash_pascalname(const u8* pascal_name); /** @brief Compute the hash code of an asciiz name * * Compute the hash code of a pascal name from its asciiz form. * The function hash_init() MUST be called once first. (This requirement will be lifted later) * * @param[in] asciiz_name the name in asciiz form * * @return the hash code as a 32 bits integer */ hashcode hash_asciizname(const char* asciiz_name); /** @brief Compute the hash code of a char array * * Compute the hash code of a pascal name from its asciiz form. * The function hash_init() MUST be called once first. (This requirement will be lifted later) * * @param[in] ascii char array * @param[in] len number of chars in the array * * @return the hash code as a 32 bits integer */ hashcode hash_chararray(const char* ascii, size_t len); #ifdef __cplusplus #endif #endif /* _HASH_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/hmac.h0000644000000000000000000000013214505005532022702 xustar000000000000000030 mtime=1695812442.050976574 30 atime=1695812445.788030096 30 ctime=1695812494.251724193 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/hmac.h0000664000374500037450000000661114505005532022650 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup hmac * @ingroup dnscore * @brief * * @{ */ #pragma once #include #define HMAC_UNKNOWN 0 #define HMAC_MD5 157 #define HMAC_SHA1 161 #define HMAC_SHA224 162 #define HMAC_SHA256 163 #define HMAC_SHA384 164 #define HMAC_SHA512 165 #ifdef __cplusplus extern "C" { #endif struct hmac_vtbl; struct tsig_hmac_t { const struct hmac_vtbl *vtbl; // ideally, implementations will append their fields on their opaque type // so only one allocation is used }; typedef struct tsig_hmac_t* tsig_hmac_t; struct hmac_vtbl { int (*hmac_update)(tsig_hmac_t hmac, const void *data, size_t len); int (*hmac_final)(tsig_hmac_t hmac, void *out_data, unsigned int *out_len); void (*hmac_reset)(tsig_hmac_t t); ya_result (*hmac_init)(tsig_hmac_t t, const void *key, int len, u8 algorithm); void (*hmac_free)(tsig_hmac_t t); }; typedef struct hmac_vtbl hmac_vtbl; tsig_hmac_t tsig_hmac_allocate(); static inline void hmac_free(tsig_hmac_t t) { t->vtbl->hmac_free(t); } static inline ya_result hmac_init(tsig_hmac_t t, const void *key, int len, u8 algorithm) { return t->vtbl->hmac_init(t, key, len, algorithm); } static inline int hmac_update(tsig_hmac_t t, const void *data, size_t len) { return t->vtbl->hmac_update(t, data, len); } static inline int hmac_final(tsig_hmac_t t, void *out_data, unsigned int *out_len) { return t->vtbl->hmac_final(t, out_data, out_len); } static inline void hmac_reset(tsig_hmac_t t) { t->vtbl->hmac_reset(t); } #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/host_address.h0000644000000000000000000000013114505005532024453 xustar000000000000000029 mtime=1695812442.10797739 30 atime=1695812445.790030125 30 ctime=1695812494.253724222 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/host_address.h0000664000374500037450000002056314505005532024424 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoretools Generic Tools * @ingroup dnscore * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef HOST_ADDRESS_H #define HOST_ADDRESS_H #include #include #include #include #define HOSTADDR_TAG 0x5244444154534f48 #define SOCKADD4_TAG 0x344444414b434f53 #define SOCKADD6_TAG 0x364444414b434f53 #define ADDRINFO_TAG 0x4f464e4952444441 struct addrinfo; struct sockaddr; #define HOST_ADDRESS_IPV4 0x04 #define HOST_ADDRESS_IPV6 0x06 #define HOST_ADDRESS_DNAME 0xfe #define HOST_ADDRESS_NONE 0x00 typedef union addressv4 addressv4; union addressv4 { u8 bytes[4]; u32 value; }; /* * Returns true if all the address bits are set respectively to 0 */ #define IPV6_ADDRESS_ALL0(_a_) (((_a_).lohi[0] == 0) && ((_a_).lohi[1] == 0)) /* * Returns true if all the address bits are set respectively to 1 */ #define IPV6_ADDRESS_ALL1(_a_) (((_a_).lohi[0] == ~0) && ((_a_).lohi[1] == ~0)) /* * Flag values for the host_address_to_str(...) function */ #define HOST_ADDRESS_TO_STR_PORT 1U // "1.2.3.4:1234" #define HOST_ADDRESS_TO_STR_FULLPORT 2U // "1.2.3.4 port 1234" #define HOST_ADDRESS_TO_STR_TSIG 4U // "1.2.3.4*mykey." #define HOST_ADDRESS_TO_STR_FULLTSIG 8U // "1.2.3.4 key mykey." #define HOST_ADDRESS_TO_STR_SHOW_PORT_ZERO 16U // else hides it typedef union addressv6 addressv6; union addressv6 { u8 bytes[16]; u32 dwords[4]; u64 lohi[2]; }; /* * The host_address is also used for notify. * It needs to be able to store names as well */ typedef union addressdname addressdname; union addressdname { u8 *dname; }; /* * Represents an ip:port. Linkable. * First made for the notification list. */ //typedef struct tsig_item tsig_item; #if DNSCORE_HAS_TSIG_SUPPORT struct tsig_item; #endif typedef struct host_address host_address; struct host_address { struct host_address *next; #if DNSCORE_HAS_TSIG_SUPPORT const struct tsig_item *tsig; /* pointer to the structure used for TSIG, to be used in relevant cases */ #endif union { addressv4 v4; addressv6 v6; addressdname dname; } ip; u16 port; // network order u8 version; }; #define HOST_ADDRESS_EMPTY {NULL, NULL, .ip.v4.value=0, 0, HOST_ADDRESS_NONE} host_address *host_address_alloc(); host_address *host_address_copy(const host_address *address); host_address *host_address_copy_list(const host_address *address); /** * Clears the content of a host_address (mostly : deletes the dname if it's * what it contains. * * @param the host address */ void host_address_clear(host_address *address); /** * Deletes a single host addresse * * @param the host address */ void host_address_delete(host_address *address); /** * Deletes a list of host addresses * * @param the first host address from the list */ void host_address_delete_list(host_address *address); // sets the port value to port for all addresses in that list where port is set to 0 void host_address_set_default_port_value(host_address *address, u16 port); // sets the port value to port for all addresses in that list void host_address_set_port_value(host_address *address, u16 port); u32 host_address_count(const host_address *address); static inline bool host_address_empty(host_address *address) { return (address == NULL); } ya_result host_address2addrinfo(const host_address *address, struct addrinfo **sa); ya_result host_address2allocated_sockaddr(const host_address *address, struct sockaddr **sap); ya_result host_address2sockaddr(const host_address *address, socketaddress *sap); /** * It does not set the "next" pointer, NONE of the "set" functions do. * * @param sa * @param address * @return */ ya_result host_address_set_with_sockaddr(host_address *address, const socketaddress *sa); bool host_address_list_contains_ip(const host_address *address_list, const socketaddress *sa); #if DNSCORE_HAS_TSIG_SUPPORT bool host_address_list_contains_ip_tsig(const host_address *address_list, const socketaddress *sa, const struct tsig_item *tsig); #endif bool host_address_list_contains_host(const host_address *address_list, const host_address *ha); bool host_address_list_equals(const host_address *a, const host_address *b); /** * Moves the first item at the end of the list. * * @param firstp pointer to pointer to the first item of the list */ void host_address_list_roll(host_address **firstp); bool host_address_equals(const host_address *a, const host_address *b); s32 host_address_compare(const host_address *a, const host_address *b); bool host_address_is_any(const host_address *ha); bool host_address_match(const host_address *a, const host_address *b); void host_address_set_ipv4(host_address *address, const u8 *ipv4, u16 port); void host_address_set_ipv6(host_address *address, const u8 *ipv6, u16 port); /** * It does not set the "next" pointer, NONE of the "set" functions do. * An address set like this will need to be freed with host_address_clear() * or deleted with host_address_delete or host_address_delete_list * * @param address * @param dname * @param port */ void host_address_set_dname(host_address *address, const u8 *dname, u16 port); ya_result host_address_append_ipv4(host_address *address, const u8 *ipv4, u16 port); ya_result host_address_append_ipv6(host_address *address, const u8 *ipv6, u16 port); ya_result host_address_append_dname(host_address *address, const u8 *dname, u16 port); ya_result host_address_append_host_address(host_address *address, const host_address *ha); ya_result host_address_append_hostent(host_address *address, struct hostent *he, u16 port); ya_result host_address_append_sockaddr(host_address *address, const socketaddress *sa); ya_result host_address_append_sockaddr_with_port(host_address *address, const socketaddress *sa, u16 port); host_address *host_address_remove_host_address(host_address **address, host_address *ha_match); bool host_address_update_host_address_list(host_address **dp, const host_address *s); static inline const host_address *host_address_get_at_index(const host_address *ha_list, u32 idx) { while((idx > 0) && (ha_list != NULL)) { ha_list = ha_list->next; idx--; } return ha_list; } /** * * host_address_to_str * * writes an address to a string, with optional details * * @param address * @param str * @param len * @param flags * @return */ ya_result host_address_to_str(const host_address *address, char *str, int len, u8 flags); #endif /* HOST_ADDRESS_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/hsdllist.h0000644000000000000000000000013214505005532023620 xustar000000000000000030 mtime=1695812442.024976202 30 atime=1695812445.788030096 30 ctime=1695812494.255724251 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/hsdllist.h0000664000374500037450000000605414505005532023567 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief * * A header/sentiel/double-linked list * * @{ * *----------------------------------------------------------------------------*/ #ifndef __HSDLLIST_H__ #define __HSDLLIST_H__ #include #include struct hsdllist_node_s { struct hsdllist_node_s *next; struct hsdllist_node_s *prev; void *data; }; typedef struct hsdllist_node_s hsdllist_node_s; struct hsdllist_s { struct hsdllist_node_s first; // first node struct hsdllist_node_s last; // last node allocator_s *node_allocator; // what to use to allocate/delete nodes (default: malloc/free a.k.a &libc_allocator) callback_function *data_free_callback; // what to use to free data (can be NULL) u32 size; }; typedef struct hsdllist_s hsdllist_s; void hsdllist_init(hsdllist_s *lst); void hsdllist_destroy(hsdllist_s *lst); void hsdllist_append(hsdllist_s *lst, void *data); void hsdllist_insert(hsdllist_s *lst, void *data); u32 hsdllist_size(hsdllist_s *lst); void* hsdllist_remove_last(hsdllist_s *lst); void* hsdllist_remove_first(hsdllist_s *lst); #endif // __HSDLLIST_H__ /** * @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/identity.h0000644000000000000000000000013214505005532023623 xustar000000000000000030 mtime=1695812442.043976474 30 atime=1695812445.788030096 30 ctime=1695812494.257724279 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/identity.h0000664000374500037450000000404614505005532023571 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once ya_result identity_change(uid_t new_uid, gid_t new_gid); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/input_stream.h0000644000000000000000000000013214505005532024504 xustar000000000000000030 mtime=1695812442.086977089 30 atime=1695812445.790030125 30 ctime=1695812494.259724308 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/input_stream.h0000664000374500037450000001200314505005532024442 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif typedef struct input_stream input_stream; typedef ya_result input_stream_read_method(input_stream *stream,void *in_buffer,u32 in_len); typedef void input_stream_close_method(input_stream *stream); typedef ya_result input_stream_skip_method(input_stream *stream,u32 byte_count); typedef struct input_stream_vtbl input_stream_vtbl; struct input_stream_vtbl { input_stream_read_method* read; input_stream_skip_method* skip; input_stream_close_method* close; const char* __class__; /* MUST BE A UNIQUE POINTER, ie: One defined in the class's .c file */ /* The name should be unique in order to avoid compiler tricks */ /* Add your inheritable methods here */ }; struct input_stream { void* data; const input_stream_vtbl* vtbl; }; #define input_stream_class(is_) ((is_)->vtbl) #define input_stream_class_name(is_) ((is_)->vtbl->__class__) #define input_stream_read(is_,buffer_,len_) (is_)->vtbl->read(is_,buffer_,len_) #define input_stream_close(is_) (is_)->vtbl->close(is_) #define input_stream_skip(is_,len_) (is_)->vtbl->skip(is_,len_) #define input_stream_valid(is_) ((is_)->vtbl != NULL) ya_result input_stream_read_fully(input_stream *stream, void *buffer, u32 len); ya_result input_stream_skip_fully(input_stream *stream, u32 len_start); ya_result input_stream_read_nu32(input_stream *stream, u32 *output); ya_result input_stream_read_nu16(input_stream *stream, u16 *output); ya_result input_stream_read_u32(input_stream *stream, u32 *output); ya_result input_stream_read_s32(input_stream *stream, s32 *output); ya_result input_stream_read_u16(input_stream *stream, u16 *output); static inline ya_result input_stream_read_u8(input_stream* stream, u8* output) { return input_stream_read_fully(stream, output, 1); } static inline ya_result input_stream_read_s8(input_stream* stream, s8* output) { return input_stream_read_fully(stream, output, 1); } ya_result input_stream_read_pu32(input_stream *stream, u32 *output); ya_result input_stream_read_pu64(input_stream *stream, u64 *output); ya_result input_stream_read_dnsname(input_stream *stream,u8 *output); ya_result input_stream_read_rname(input_stream *stream, u8 *output_buffer); ya_result input_stream_read_line(input_stream *stream, char *output, int max_len); /** * This tools allows a safer misuse (and detection) of closed streams * It sets the stream to a sink that warns abouts its usage and for which every call that can fail fails. * * @param is the stream to set as a void. It needs to have been closed already. */ void input_stream_set_void(input_stream *is); /** * Used to temporarily initialise a stream with a sink that can be closed safely. * Typically used as pre-init so the stream can be closed even if the function * setup failed before reaching stream initialisation. * * @param is */ void input_stream_set_sink(input_stream* is); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/io_stream.h0000644000000000000000000000013214505005532023754 xustar000000000000000030 mtime=1695812442.011976015 30 atime=1695812445.787030082 30 ctime=1695812494.261724337 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/io_stream.h0000664000374500037450000000617114505005532023723 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * @{ */ #ifndef _IO_STREAM_H #define _IO_STREAM_H #include #include #ifdef __cplusplus extern "C" { #endif typedef struct io_stream io_stream; struct io_stream { input_stream in; output_stream out; }; static inline void io_stream_link(io_stream *ios, input_stream *is, output_stream *os) { ios->in.data = is->data; // scan-build false-positive (it assumes an error is returned, but still goes through 'ISOK') ios->in.vtbl = is->vtbl; ios->out.data = os->data; ios->out.vtbl = os->vtbl; } static inline ya_result io_stream_read(io_stream *ios, u8 *buffer, u32 len) { return ios->in.vtbl->read(&ios->in, buffer, len); } static inline ya_result io_stream_skip(io_stream *ios, u32 len) { return ios->in.vtbl->skip(&ios->in, len); } static inline ya_result io_stream_write(io_stream *ios, u8 *buffer, u32 len) { return ios->out.vtbl->write(&ios->out, buffer, len); } static inline ya_result io_stream_flush(io_stream *ios) { return ios->out.vtbl->flush(&ios->out); } static inline void io_stream_close(io_stream *ios) { ios->in.vtbl->close(&ios->in); ios->out.vtbl->close(&ios->out); } #ifdef __cplusplus } #endif #endif /* _IO_STREAM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/json.h0000644000000000000000000000013214505005532022743 xustar000000000000000030 mtime=1695812442.101977304 30 atime=1695812445.790030125 30 ctime=1695812494.263724366 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/json.h0000664000374500037450000001051714505005532022711 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnspacket DNS Messages * @ingroup dnscore * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #pragma once #include #include #include #include #include #if !JSON_C_ union json {intptr type;}; #endif typedef union json* json; enum json_type { JSON_ARRAY = 0, JSON_OBJECT, JSON_STRING, JSON_NUMBER, JSON_BOOLEAN }; json json_object_new_instance(); json json_array_new_instance(); json json_string_new_instance(); json json_number_new_instance(); json json_boolean_new_instance(); enum json_type json_type_get(const json j); bool json_boolean_get(const json j); void json_boolean_set(json j, bool value); double json_number_get(const json j); void json_number_set(json j, double value); const char * json_string_get(const json j); size_t json_string_size_get(const json j); void json_string_set(json j, const char *text); json json_array_get(json j, size_t index); void json_array_add(const json j, json item); static inline void json_array_add_boolean(const json j, bool value) { json boolean = json_boolean_new_instance(); json_boolean_set(boolean, value); json_array_add(j, boolean); } static inline void json_array_add_number(const json j, double value) { json number = json_number_new_instance(); json_number_set(number, value); json_array_add(j, number); } static inline void json_array_add_string(const json j, const char *text) { json string = json_string_new_instance(); json_string_set(string, text); json_array_add(j, string); } json json_object_get(json j, const char *name); bool json_object_add(const json j, const char *key, json item); static inline void json_object_add_boolean(const json j, const char* key, bool value) { json boolean = json_boolean_new_instance(); json_boolean_set(boolean, value); json_object_add(j, key, boolean); } static inline void json_object_add_number(const json j, const char* key, double value) { json number = json_number_new_instance(); json_number_set(number, value); json_object_add(j, key, number); } static inline void json_object_add_string(const json j, const char* key, const char *text) { json string = json_string_new_instance(); json_string_set(string, text); json_object_add(j, key, string); } ya_result json_write_to(json j, output_stream *os); ya_result json_size(json j); void json_delete(json j); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/limited_input_stream.h0000644000000000000000000000013214505005532026213 xustar000000000000000030 mtime=1695812442.035976359 30 atime=1695812445.788030096 30 ctime=1695812494.266724408 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/limited_input_stream.h0000664000374500037450000000536614505005532026167 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _LIMITED_INPUT_STREAM_H #define _LIMITED_INPUT_STREAM_H #include #ifdef __cplusplus extern "C" { #endif /** * * Puts a filter around a stream in order to limit the number of bytes that can be read from it. * * @param filtered the input stream that will be filtered (and it's content unusable after filtering) * @param stream the input stream that'll contain the filter * @param buffer_size the maximum number of bytes that can be read from the filtered input stream * */ void limited_input_stream_init(input_stream* filtered,input_stream *stream, u64 stream_size); #ifdef __cplusplus } #endif #endif /* _LIMITED_INPUT_STREAM_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/limiter.h0000644000000000000000000000013214505005532023437 xustar000000000000000030 mtime=1695812442.097977247 30 atime=1695812445.790030125 30 ctime=1695812494.268724437 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/limiter.h0000664000374500037450000000646714505005532023416 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #if 0 /* fix */ #else #define LIMITER_WINDOW_COUNT 1 #define LIMITER_WINDOW_DURATION 1000000 // 1s #endif typedef u32 limiter_count_t; struct limiter_t { u64 time_base; u64 last_time; u64 wait_time; u32 window_current; limiter_count_t rate_max; limiter_count_t window[LIMITER_WINDOW_COUNT]; }; typedef struct limiter_t limiter_t; void limiter_init(limiter_t *r, limiter_count_t amount_max); void limiter_set_wait_time(limiter_t *r, u64 time_to_wait_between_two); void limiter_finalize(limiter_t *r); /** * Computes the quota for adding a given amount * Sends the result back in two variables. * * @param r the limiter * @param amount_to_add the amount to add * @param quota_available_now a pointer to a variable to hold how much can be added right now (can be NULL) * @param time_to_wait_for_more a pointer to a variable to hold how much time (us) needs to be waited before probing again (can be NULL) * * Returns timeus() at the time of the call (not at the return of the call) */ u64 limiter_quota(limiter_t *r, limiter_count_t amount_to_add, limiter_count_t* quota_available_now, u64* time_to_wait_for_more); void limiter_add(limiter_t *r, limiter_count_t amount_to_add, limiter_count_t* amount_added, u64* time_to_wait_for_more); void limiter_add_anyway(limiter_t *r, limiter_count_t amount_to_add, limiter_count_t* amount_added, u64* time_to_wait_for_more); void limiter_wait(limiter_t *r, limiter_count_t amount_to_add); yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/list-dl.h0000644000000000000000000000013114505005532023341 xustar000000000000000030 mtime=1695812442.065976789 29 atime=1695812445.78903011 30 ctime=1695812494.270724466 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/list-dl.h0000664000374500037450000004254514505005532023316 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A node-based single linked list * * A node-based single linked list * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef LIST_DL_H_ #define LIST_DL_H_ /* ------------------------------------------------------------ * * INCLUDES */ #include #include /** * Linked list for interface data * * (looks like a no-header no-sentinel single-linked list of strings) * * * head : the base structure of the list * item : the concept of what is being stored in the list * node : holds the item * data : the reference to the item (which can be called data because it's type-less) * */ #define LISTDL_TAG 0x4c445453494c #define LISTDLND_TAG 0x444e4c445453494c typedef struct list_dl_node_s list_dl_node_s; // 24 bytes struct list_dl_node_s { struct list_dl_node_s *next; struct list_dl_node_s *prev; void *data; }; typedef struct list_dl_node_sentiel_s list_dl_node_sentiel_s; // 16 bytes struct list_dl_node_sentiel_s { struct list_dl_node_s *next; struct list_dl_node_s *prev; }; typedef struct list_dl_s list_dl_s; // 36 bytes struct list_dl_s { list_dl_node_sentiel_s head_sentinel; list_dl_node_sentiel_s tail_sentinel; u32 size; }; typedef struct list_dl_iterator_s list_dl_iterator_s; struct list_dl_iterator_s { list_dl_s *list; list_dl_node_s *current_node; }; /* ------------------------------------------------------------ * * PROTOTYPES */ static inline void list_dl_iterator_init(list_dl_iterator_s *iter, list_dl_s *list) { iter->list = list; iter->current_node = (list_dl_node_s*)&list->head_sentinel; } static inline bool list_dl_iterator_has_next(list_dl_iterator_s *iter) { return iter->current_node->next != (list_dl_node_s*)&iter->list->tail_sentinel; } static inline void* list_dl_iterator_next(list_dl_iterator_s *iter) { iter->current_node = iter->current_node->next; return iter->current_node->data; } /** * Removes the node from the list, the node is not freed * * @param list * @param node */ void list_dl_remove_node(list_dl_s *list, list_dl_node_s *node); static inline void* list_dl_iterator_remove(list_dl_iterator_s *iter) { list_dl_node_s *current = iter->current_node; iter->current_node = current->prev; void *data = current->data; list_dl_remove_node(iter->list, current); return data; } /** * Inserts data BEFORE the current node * * @param iter * @param data * @return */ bool list_dl_iterator_insert(list_dl_iterator_s *iter, void *data); /** * Inserts data BEFORE the current node * * @param iter * @param data * @return */ bool list_dl_iterator_append(list_dl_iterator_s *iter, void *data); static inline list_dl_node_s * list_dl_node_alloc() { list_dl_node_s *node; ZALLOC_OBJECT_OR_DIE( node, list_dl_node_s, LISTDLND_TAG); return node; } static inline void list_dl_node_free(list_dl_node_s *node) { ZFREE_OBJECT(node); } /** * Initialises a list. * * @param list */ static inline void list_dl_init(list_dl_s *list) { ZEROMEMORY(list, sizeof(list_dl_s)); list->head_sentinel.next = (list_dl_node_s*)&list->tail_sentinel; list->tail_sentinel.prev = (list_dl_node_s*)&list->head_sentinel; } static inline list_dl_s* list_dl_new_instance() { list_dl_s *list; ZALLOC_OBJECT_OR_DIE(list, list_dl_s, LISTDL_TAG); list_dl_init(list); return list; } /** * Adds an item at the head of the list. * * @param list * @param data */ static inline void list_dl_insert(list_dl_s *list, void *data) { list_dl_node_s *node; ZALLOC_OBJECT_OR_DIE( node, list_dl_node_s, LISTDLND_TAG); node->next = list->head_sentinel.next; node->prev = (list_dl_node_s*)&list->head_sentinel; list->head_sentinel.next->prev = node; list->head_sentinel.next = node; #if DEBUG assert(list->head_sentinel.next->prev == (list_dl_node_s*)&list->head_sentinel); #endif node->data = data; list->size++; } void list_dl_move_to_first_position(list_dl_s *list, void *data); static inline void list_dl_insert_node(list_dl_s *list, list_dl_node_s *node) { node->next = list->head_sentinel.next; node->prev = (list_dl_node_s*)&list->head_sentinel; list->head_sentinel.next->prev = node; list->head_sentinel.next = node; #if DEBUG assert(list->head_sentinel.next->prev == (list_dl_node_s*)&list->head_sentinel); #endif list->size++; } /** * Adds an item at the tail of the list. * * @param list * @param data */ static inline void list_dl_append(list_dl_s *list, void *data) { list_dl_node_s *node; ZALLOC_OBJECT_OR_DIE( node, list_dl_node_s, LISTDLND_TAG); node->next = (list_dl_node_s*)&list->tail_sentinel; node->prev = list->tail_sentinel.prev; list->tail_sentinel.prev->next = node; list->tail_sentinel.prev = node; #if DEBUG assert(list->tail_sentinel.prev->next == (list_dl_node_s*)&list->tail_sentinel); #endif node->data = data; list->size++; } static inline void list_dl_append_node(list_dl_s *list, list_dl_node_s *node) { node->next = (list_dl_node_s*)&list->tail_sentinel; node->prev = list->tail_sentinel.prev; list->tail_sentinel.prev->next = node; list->tail_sentinel.prev = node; #if DEBUG assert(list->tail_sentinel.prev->next == (list_dl_node_s*)&list->tail_sentinel); #endif list->size++; } static inline void list_dl_append_list(list_dl_s *list, list_dl_s *list_to_add) { if(list_to_add->size > 0) { list_dl_node_s *node; node = list_to_add->head_sentinel.next; node->prev = list->tail_sentinel.prev; list->tail_sentinel.prev->next = node; node = list_to_add->tail_sentinel.prev; node->next = (list_dl_node_s*)&list->tail_sentinel; list->tail_sentinel.prev = node; list->size += list_to_add->size; list_to_add->head_sentinel.next = (list_dl_node_s*)&list_to_add->tail_sentinel; list_to_add->tail_sentinel.prev = (list_dl_node_s*)&list_to_add->head_sentinel; list_to_add->size = 0; } } /** * * Adds an item to the list. * Effectively inserts the item. * * @param list * @param data */ static inline void list_dl_add(list_dl_s *list, void *data) { list_dl_append(list, data); } /** * Remove the first item from the list. * Deletes the node but not the data. * The data is returned. * * @param list * @return the data or NULL if the list is empty */ static inline void* list_dl_remove_first(list_dl_s *list) { if(list->size > 0) { #if DEBUG assert(list->head_sentinel.next != (list_dl_node_s*)&list->tail_sentinel); assert(list->tail_sentinel.prev != (list_dl_node_s*)&list->head_sentinel); assert(list->head_sentinel.next != NULL); assert(list->tail_sentinel.prev != NULL); #endif list_dl_node_s *node = list->head_sentinel.next; list->head_sentinel.next = node->next; node->next->prev = (list_dl_node_s*)&list->head_sentinel; list->size--; void *data = node->data; ZFREE_OBJECT(node); #if DEBUG assert(list->head_sentinel.next->prev == (list_dl_node_s*)&list->head_sentinel); #endif return data; } else { return NULL; } } /** * Returns the data of the first item on the list * * @param list * @return the data or NULL if the list is empty */ static inline void* list_dl_peek_first(list_dl_s *list) { if(list->size > 0) { #if DEBUG assert(list->head_sentinel.next != (list_dl_node_s*)&list->tail_sentinel); assert(list->tail_sentinel.prev != (list_dl_node_s*)&list->head_sentinel); assert(list->head_sentinel.next != NULL); assert(list->tail_sentinel.prev != NULL); #endif list_dl_node_s *node = list->head_sentinel.next; void *data = node->data; return data; } else { return NULL; } } static inline list_dl_node_s* list_dl_first_node(list_dl_s *list) { if(list->size > 0) { #if DEBUG assert(list->head_sentinel.next != (list_dl_node_s*)&list->tail_sentinel); assert(list->tail_sentinel.prev != (list_dl_node_s*)&list->head_sentinel); assert(list->head_sentinel.next != NULL); assert(list->tail_sentinel.prev != NULL); #endif return list->head_sentinel.next; } else { return NULL; } } static inline list_dl_node_s* list_dl_remove_first_node(list_dl_s *list) { if(list->size > 0) { #if DEBUG assert(list->head_sentinel.next != (list_dl_node_s*)&list->tail_sentinel); assert(list->tail_sentinel.prev != (list_dl_node_s*)&list->head_sentinel); assert(list->head_sentinel.next != NULL); assert(list->tail_sentinel.prev != NULL); #endif list_dl_node_s *node = list->head_sentinel.next; list->head_sentinel.next = node->next; node->next->prev = (list_dl_node_s*)&list->head_sentinel; list->size--; #if DEBUG assert(list->head_sentinel.next->prev == (list_dl_node_s*)&list->head_sentinel); #endif return node; } else { return NULL; } } /** * Remove the last item from the list. * Deletes the node but not the data. * The data is returned. * * @param list * @return the data or NULL if the list is empty */ static inline void* list_dl_remove_last(list_dl_s *list) { if(list->size > 0) { #if DEBUG assert(list->head_sentinel.next != (list_dl_node_s*)&list->tail_sentinel); assert(list->tail_sentinel.prev != (list_dl_node_s*)&list->head_sentinel); assert(list->head_sentinel.next != NULL); assert(list->tail_sentinel.prev != NULL); #endif list_dl_node_s *node = list->tail_sentinel.prev; list->tail_sentinel.prev = node->prev; node->prev->next = (list_dl_node_s*)&list->tail_sentinel; list->size--; void *data = node->data; ZFREE_OBJECT(node); #if DEBUG assert(list->tail_sentinel.prev->next == (list_dl_node_s*)&list->tail_sentinel); #endif return data; } else { return NULL; } } static inline void list_dl_move_last_to_first(list_dl_s *list) { if(list->size > 1) { #if DEBUG assert(list->head_sentinel.next != (list_dl_node_s*)&list->tail_sentinel); assert(list->tail_sentinel.prev != (list_dl_node_s*)&list->head_sentinel); assert(list->head_sentinel.next != NULL); assert(list->tail_sentinel.prev != NULL); #endif // remove last node list_dl_node_s *node = list->tail_sentinel.prev; list->tail_sentinel.prev = node->prev; node->prev->next = (list_dl_node_s*)&list->tail_sentinel; // insert node node->next = list->head_sentinel.next; node->prev = (list_dl_node_s*)&list->head_sentinel; list->head_sentinel.next->prev = node; list->head_sentinel.next = node; #if DEBUG assert(list->tail_sentinel.prev->next == (list_dl_node_s*)&list->tail_sentinel); #endif } } /** * Returns the data of the last item on the list * * @param list * @return the data or NULL if the list is empty */ static inline void* list_dl_peek_last(list_dl_s *list) { if(list->size > 0) { #if DEBUG assert(list->head_sentinel.next != (list_dl_node_s*)&list->tail_sentinel); assert(list->tail_sentinel.prev != (list_dl_node_s*)&list->head_sentinel); assert(list->head_sentinel.next != NULL); assert(list->tail_sentinel.prev != NULL); #endif list_dl_node_s *node = list->tail_sentinel.prev; void *data = node->data; return data; } else { return NULL; } } static inline list_dl_node_s* list_dl_last_node(list_dl_s *list) { if(list->size > 0) { #if DEBUG assert(list->head_sentinel.next != (list_dl_node_s*)&list->tail_sentinel); assert(list->tail_sentinel.prev != (list_dl_node_s*)&list->head_sentinel); assert(list->head_sentinel.next != NULL); assert(list->tail_sentinel.prev != NULL); #endif return list->tail_sentinel.prev; } else { return NULL; } } static inline list_dl_node_s * list_dl_remove_last_node(list_dl_s *list) { if(list->size > 0) { #if DEBUG assert(list->head_sentinel.next != (list_dl_node_s*)&list->tail_sentinel); assert(list->tail_sentinel.prev != (list_dl_node_s*)&list->head_sentinel); assert(list->head_sentinel.next != NULL); assert(list->tail_sentinel.prev != NULL); #endif list_dl_node_s *node = list->tail_sentinel.prev; list->tail_sentinel.prev = node->prev; node->prev->next = (list_dl_node_s*)&list->tail_sentinel; list->size--; #if DEBUG assert(list->tail_sentinel.prev->next == (list_dl_node_s*)&list->tail_sentinel); #endif return node; } else { return NULL; } } /** * Enqueues the item in the list, seen as a queue. * * @param list * @param data */ static inline void list_dl_enqueue(list_dl_s *list, void *data) { list_dl_insert(list, data); } /** * Dequeues the item from the list, seen as a queue. * * @param list * @return an item or NULL if the list/queue is empty */ static inline void* list_dl_dequeue(list_dl_s *list) { void *data = list_dl_remove_last(list); return data; } /** * Remove the first item that points to data; * * @param list * @param data * @return TRUE if an item has been deleted */ bool list_dl_remove(list_dl_s *list, const void *data); /** * Removes the node from the list, the node is not freed * * @param list * @param node */ void list_dl_remove_node(list_dl_s *list, list_dl_node_s *node); /** * Remove the first item for which the match does not returns 0. * * @param list * @param match a callback function called with the data and args * @param args * @return */ bool list_dl_remove_matching(list_dl_s *list, result_callback_function *match, void *args); /** * Remove all the items for which the match does not returns 0. * * @param list * @param match a callback function called with the data and args * @param args * @return */ bool list_dl_remove_all_matching(list_dl_s *list, result_callback_function *match, void *args); /** * Remove all items from the list. * Deletes the nodes but not the data. * * @param list */ void list_dl_clear(list_dl_s *list); /** * Iterates through the items of the function, calling the comparator. * * The comparator must return: * * COLLECTION_ITEM_SKIP : go to next item * COLLECTION_ITEM_STOP : stop processing, return NULL * COLLECTION_ITEM_PROCESS_THEN_STOP : stop processing, return node data * * @param list * @param comparator * * @return a matching node or NULL */ void *list_dl_search(list_dl_s *list, result_callback_function *comparator, void *parm); /** * * Returns the index of that specific pointer into the list * Linear search (slow) * * @param list * @param comparator * @return */ ya_result list_dl_indexof(list_dl_s *list, void *data); void *list_dl_get(list_dl_s *list, int index); ya_result list_dl_foreach(list_dl_s *list, result_callback_function *callback, void *caller_data); bool list_dl_remove_matching_ptr(list_dl_s *list, void *ptr); /** * * Returns the size of the list * * @param list * @return the size of the list */ static inline u32 list_dl_size(const list_dl_s *list) { return list->size; } #endif /* LIST_DL_H_ */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/list-sl.h0000644000000000000000000000013114505005532023360 xustar000000000000000029 mtime=1695812442.02697623 30 atime=1695812445.788030096 30 ctime=1695812494.272724494 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/list-sl.h0000664000374500037450000001610614505005532023327 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A node-based single linked list * * A node-based single linked list * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef LIST_SL_H_ #define LIST_SL_H_ /* ------------------------------------------------------------ * * INCLUDES */ #include #include /* ------------------------------------------------------------ * * STRUCTS */ /** * Linked list for interface data * * (looks like a no-header no-sentinel single-linked list of strings) * * head : the base structure of the list * item : the concept of what is being stored in the list * node : holds the item * data : the reference to the item (which can be called data because it's type-less) * */ typedef struct list_sl_node_s list_sl_node_s; #define LISTSL_TAG 0x4c535453494c #define LISTSLND_TAG 0x444e4c535453494c struct list_sl_node_s { struct list_sl_node_s *next; void *data; }; /// The sentinel is a butchered node, meant to avoid the (useless) data field. typedef struct list_sl_node_sentiel_s list_sl_node_sentiel_s; struct list_sl_node_sentiel_s { struct list_sl_node_s *next; }; typedef struct list_sl_s list_sl_s; struct list_sl_s { list_sl_node_s *first; list_sl_node_sentiel_s sentinel; u32 size; }; /* ------------------------------------------------------------ * * PROTOTYPES */ /** * Initialises a list. * * @param list */ static inline void list_sl_init(list_sl_s *list) { list->first = (list_sl_node_s*)&list->sentinel; list->sentinel.next = NULL; list->size = 0; } static inline list_sl_s* list_sl_new_instance() { list_sl_s *list; ZALLOC_OBJECT_OR_DIE(list, list_sl_s, LISTSL_TAG); list_sl_init(list); return list; } static inline bool list_sl_hasnext(const list_sl_s *list, const list_sl_node_s *node) { return (node->next != (const list_sl_node_s *)&list->sentinel); } /** * Adds an item at the head of the list. * * @param list * @param data */ static inline void list_sl_insert(list_sl_s *list, void *data) { list_sl_node_s *node; ZALLOC_OBJECT_OR_DIE( node, list_sl_node_s, LISTSLND_TAG); node->next = list->first; node->data = data; list->first = node; list->size++; } /** * * Adds an item to the list. * Effectively inserts the item. * * @param list * @param data */ static inline void list_sl_add(list_sl_s *list, void *data) { list_sl_insert(list, data); } /* static inline void list_sl_add_list(list_sl_s *list, list_sl_s *list_to_append) { } */ /** * Remove the first item from the list. * Deletes the node but not the data. * The data is returned. * * @param list * @return the data or NULL if the list is empty */ static inline void* list_sl_remove_first(list_sl_s *list) { if(list->size > 0) { list_sl_node_s *node = list->first; void *data = node->data; list->first = node->next; list->size--; ZFREE_OBJECT(node); return data; } else { return NULL; } } /** * * Adds an item to the list, seen as a stack. * Effectively inserts the item. * * @param list * @param data */ static inline void list_sl_push(list_sl_s *list, void *data) { list_sl_insert(list, data); } /** * * Adds an item to the list, seen as a stack. * Effectively inserts the item. * * @param list * @param data */ static inline void* list_sl_pop(list_sl_s *list) { void *data = list_sl_remove_first(list); return data; } /** * Remove the first item that points to data; * * @param list * @param data * @return TRUE if an item has been deleted */ bool list_sl_remove(list_sl_s *list, void *data); /** * Remove all items from the list. * Deletes the nodes but not the data. * * @param list */ void list_sl_clear(list_sl_s *list); static inline void list_sl_delete_instance(list_sl_s *list) { list_sl_clear(list); ZFREE_OBJECT(list); } /** * Iterates through the items of the function, calling the comparator. * * The comparator must return: * * COLLECTION_ITEM_SKIP : go to next item * COLLECTION_ITEM_STOP : stop processing, return NULL * COLLECTION_ITEM_PROCESS_THEN_STOP : stop processing, return node data * * @param list * @param comparator * * @return a matching node or NULL */ void *list_sl_search(list_sl_s *list, result_callback_function *comparator, void *parm); /** * Iterates through the items of the function, calling the comparator. * * The comparator must return: * * COLLECTION_ITEM_SKIP : go to next item * COLLECTION_ITEM_PROCESS : delete, then go to next item * COLLECTION_ITEM_STOP : stop processing * COLLECTION_ITEM_PROCESS_THEN_STOP : delete, then stop processing * * @param list * @param comparator * * @return TRUE if at least one item has been deleted, FALSE otherwise. */ bool list_sl_remove_match(list_sl_s *list, result_callback_function *comparator, void *parm); /** * * Returns the size of the list * * @param list * @return the size of the list */ static inline u32 list_sl_size(const list_sl_s *list) { return list->size; } #endif /* LIST_SL_H_ */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/list-sl-debug.h0000644000000000000000000000013114505005532024444 xustar000000000000000030 mtime=1695812442.066976803 29 atime=1695812445.78903011 30 ctime=1695812494.274724523 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/list-sl-debug.h0000664000374500037450000001453514505005532024417 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A node-based single linked list * * A node-based single linked list * * @{ */ /*----------------------------------------------------------------------------*/ #pragma once /* ------------------------------------------------------------ * * INCLUDES */ #include #include /* ------------------------------------------------------------ * * STRUCTS */ /** * Linked list for interface data * * (looks like a no-header no-sentinel single-linked list of strings) * * head : the base structure of the list * item : the concept of what is being stored in the list * node : holds the item * data : the reference to the item (which can be called data because it's type-less) * */ typedef struct list_sl_debug_node_s list_sl_debug_node_s; #define LISTSLND_TAG 0x444e4c535453494c struct list_sl_debug_node_s { struct list_sl_debug_node_s *next; void *data; }; /// The sentiel is a butchered node, meant to avoid the (useless) data field. typedef struct list_sl_debug_node_sentiel_s list_sl_debug_node_sentiel_s; struct list_sl_debug_node_sentiel_s { struct list_sl_debug_node_s *next; }; typedef struct list_sl_debug_s list_sl_debug_s; struct list_sl_debug_s { list_sl_debug_node_s *first; list_sl_debug_node_sentiel_s sentinel; u32 size; }; /* ------------------------------------------------------------ * * PROTOTYPES */ /** * Initialises a list. * * @param list */ static inline void list_sl_debug_init(list_sl_debug_s *list) { list->first = (list_sl_debug_node_s*)&list->sentinel; list->sentinel.next = NULL; list->size = 0; } /** * Adds an item at the head of the list. * * @param list * @param data */ void list_sl_debug_insert(list_sl_debug_s *list, void *data); /** * * Adds an item to the list. * Effectively inserts the item. * * @param list * @param data */ static inline void list_sl_debug_add(list_sl_debug_s *list, void *data) { list_sl_debug_insert(list, data); } /* static inline void list_sl_debug_add_list(list_sl_debug_s *list, list_sl_debug_s *list_to_append) { } */ /** * Remove the first item from the list. * Deletes the node but not the data. * The data is returned. * * @param list * @return the data or NULL if the list is empty */ void* list_sl_debug_remove_first(list_sl_debug_s *list); /** * * Adds an item to the list, seen as a stack. * Effectively inserts the item. * * @param list * @param data */ static inline void list_sl_debug_push(list_sl_debug_s *list, void *data) { list_sl_debug_insert(list, data); } /** * * Adds an item to the list, seen as a stack. * Effectively inserts the item. * * @param list * @param data */ static inline void* list_sl_debug_pop(list_sl_debug_s *list) { void *data = list_sl_debug_remove_first(list); return data; } /** * Remove the first item that points to data; * * @param list * @param data * @return TRUE if an item has been deleted */ bool list_sl_debug_remove(list_sl_debug_s *list, void *data); /** * Remove all items from the list. * Deletes the nodes but not the data. * * @param list */ void list_sl_debug_clear(list_sl_debug_s *list); /** * Iterates through the items of the function, calling the comparator. * * The comparator must return: * * COLLECTION_ITEM_SKIP : go to next item * COLLECTION_ITEM_STOP : stop processing, return NULL * COLLECTION_ITEM_PROCESS_THEN_STOP : stop processing, return node data * * @param list * @param comparator * * @return a matching node or NULL */ void *list_sl_debug_search(list_sl_debug_s *list, result_callback_function *comparator, void *parm); /** * Iterates through the items of the function, calling the comparator. * * The comparator must return: * * COLLECTION_ITEM_SKIP : go to next item * COLLECTION_ITEM_PROCESS : delete, then go to next item * COLLECTION_ITEM_STOP : stop processing * COLLECTION_ITEM_PROCESS_THEN_STOP : delete, then stop processing * * @param list * @param comparator * * @return TRUE if at least one item has been deleted, FALSE otherwise. */ bool list_sl_debug_remove_match(list_sl_debug_s *list, result_callback_function *comparator, void *parm); /** * * Returns the size of the list * * @param list * @return the size of the list */ static inline u32 list_sl_debug_size(const list_sl_debug_s *list) { return list->size; } yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/logger.h0000644000000000000000000000013214505005532023251 xustar000000000000000030 mtime=1695812442.089977133 30 atime=1695812445.790030125 30 ctime=1695812494.276724551 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/logger.h0000664000374500037450000000413514505005532023216 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _LOGGER_H #define _LOGGER_H #include #endif /* _LOGGER_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/logger_channel_file.h0000644000000000000000000000013114505005532025737 xustar000000000000000030 mtime=1695812442.048976545 30 atime=1695812445.788030096 29 ctime=1695812494.27872458 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/logger_channel_file.h0000664000374500037450000000507414505005532025710 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _LOGGER_CHANNEL_FILE_H #define _LOGGER_CHANNEL_FILE_H #include #include #ifdef __cplusplus extern "C" { #endif ya_result logger_channel_file_open(const char *fullpath, uid_t uid, gid_t gid, u16 mode, bool forceflush, logger_channel *chan); /** * * changes the name after a reopen, does not rename the file itself * * @param chan * @param newpath * @return */ ya_result logger_channel_file_rename(logger_channel *chan, const char *newpath); #ifdef __cplusplus } #endif #endif /* _LOGGER_CHANNEL_STREAM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/logger_channel_pipe.h0000644000000000000000000000013214505005532025756 xustar000000000000000030 mtime=1695812442.023976187 30 atime=1695812445.788030096 30 ctime=1695812494.280724609 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/logger_channel_pipe.h0000664000374500037450000000451014505005532025720 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _LOGGER_CHANNEL_PIPE_H #define _LOGGER_CHANNEL_PIPE_H #include #include #ifdef __cplusplus extern "C" { #endif ya_result logger_channel_pipe_open(const char *command, bool forceflush, logger_channel *chan); #ifdef __cplusplus } #endif #endif /* _LOGGER_CHANNEL_STREAM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/logger_channel_stream.h0000644000000000000000000000013214505005532026314 xustar000000000000000030 mtime=1695812442.010976001 30 atime=1695812445.787030082 30 ctime=1695812494.282724638 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/logger_channel_stream.h0000664000374500037450000000452214505005532026261 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _LOGGER_CHANNEL_STREAM_H #define _LOGGER_CHANNEL_STREAM_H #include #ifdef __cplusplus extern "C" { #endif struct logger_channel; void logger_channel_stream_open(output_stream* os, bool forceflush, struct logger_channel *chan); #ifdef __cplusplus } #endif #endif /* _LOGGER_CHANNEL_STREAM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/logger_channel_syslog.h0000644000000000000000000000013214505005532026341 xustar000000000000000030 mtime=1695812442.099977275 30 atime=1695812445.790030125 30 ctime=1695812494.284724666 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/logger_channel_syslog.h0000664000374500037450000000467414505005532026316 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _LOGGER_CHANNEL_SYSLOG_H #define _LOGGER_CHANNEL_SYSLOG_H #include #ifdef __cplusplus extern "C" { #endif /* * NOTE: ONLY ONE SYSLOG CHANNEL SHOULD BE OPEN !!! */ void logger_channel_syslog_open(const char* ident, int options, int facility, logger_channel *chan); #ifdef __cplusplus } #endif #endif /* _LOGGER_CHANNEL_SYSLOG_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/logger_handle.h0000644000000000000000000000013214505005532024564 xustar000000000000000030 mtime=1695812442.094977204 30 atime=1695812445.790030125 30 ctime=1695812494.286724695 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/logger_handle.h0000664000374500037450000005753614505005532024546 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _LOGGER_HANDLE_H #define _LOGGER_HANDLE_H #include #include #define LOGGER_EARLY_CULL 1 #include #include #include #include /* * Basically a copy from syslog */ #define MSG_EMERG 0 /* system is unusable */ #define MSG_ALERT 1 /* action must be taken immediately */ #define MSG_CRIT 2 /* critical conditions */ #define MSG_ERR 3 /* error conditions */ #define MSG_WARNING 4 /* warning conditions */ #define MSG_NOTICE 5 /* normal, but significant, condition */ #define MSG_INFO 6 /* informational message */ #define MSG_DEBUG 7 /* debug-level message */ #define MSG_DEBUG1 8 /* debug-level message */ #define MSG_DEBUG2 9 /* debug-level message */ #define MSG_DEBUG3 10 /* debug-level message */ #define MSG_DEBUG4 11 /* debug-level message */ #define MSG_DEBUG5 12 /* debug-level message */ #define MSG_DEBUG6 13 /* debug-level message */ #define MSG_DEBUG7 14 /* debug-level message */ #define MSG_ALL 15 /* all message levels */ #define MSG_ALL_MASK 0xffff /// all message levels as a bitmap #define MSG_PROD_MASK 0x007f /// non-debug message levels as a bitmap #define MSG_WARN_MASK 0x001f /// warnings and worse messages levels as a bitmap #define MSG_LEVEL_COUNT 16 /** * The default buffer size (0-cost) made available for each line. * If the line is bigger the buffer's size is raised at a certain (non-nul) * cost. * */ #define DEFAULT_MAX_LINE_SIZE 128 #define LOG_QUEUE_MIN_SIZE 0x00000400 // 1K #define LOG_QUEUE_MAX_SIZE 0x01000000 // 16M #define LOG_QUEUE_DEFAULT_SIZE 0x00100000 // 1M #define DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED 1 // must be 1 #ifdef __cplusplus extern "C" { #endif /** * Handle */ typedef ptr_vector logger_channel_array; struct logger_channel; typedef struct logger_handle logger_handle; #if DEBUG #define LOGGER_HANDLE_MAGIC_CHECK 0x11332244 #endif #define LOGGER_HANDLE_NAME_SIZE_MAX 16 #define LOGGER_HANDLE_FORMATTED_NAME_SIZE_MAX 8 #define LOGGER_REPEAT_COMPRESSION 1 struct logger_handle // ~ 5 * 64 { u8 active[MSG_LEVEL_COUNT]; // 16 /// @note 20200818 edf -- I know what I always say about layout. This is an exception. Keep it first. logger_channel_array channels[MSG_LEVEL_COUNT]; // 256 char name[LOGGER_HANDLE_NAME_SIZE_MAX]; // 16 char formatted_name[LOGGER_HANDLE_FORMATTED_NAME_SIZE_MAX + 1]; // 8 + 1 bool enabled; // 1 // I expect 6 padding bytes here struct logger_handle **global_reference; // 8 #if DEBUG u32 magic_check; #endif }; #if LOGGER_EARLY_CULL extern struct logger_handle LOGGER_HANDLE_SINK_; #define LOGGER_HANDLE_SINK (&LOGGER_HANDLE_SINK_) #else #define LOGGER_HANDLE_SINK NULL #endif /** * Channel */ struct logger_channel_vtbl; struct logger_message; struct logger_channel { void *data; const struct logger_channel_vtbl *vtbl; #if LOGGER_REPEAT_COMPRESSION struct logger_message *last_message; u32 last_message_count; #endif s32 linked_handles; }; typedef struct logger_channel logger_channel; typedef ya_result logger_channel_constmsg_method(logger_channel* chan, int level, char* text, u32 text_len, u32 date_offset); typedef ya_result logger_channel_msg_method(logger_channel* chan, int level, char* text, ...); typedef ya_result logger_channel_vmsg_method(logger_channel* chan, int level, char* text, va_list args); typedef void logger_channel_flush_method(logger_channel* chan); typedef void logger_channel_close_method(logger_channel* chan); typedef ya_result logger_channel_reopen_method(logger_channel* chan); typedef void logger_channel_sink_method(logger_channel* chan); typedef struct logger_channel_vtbl logger_channel_vtbl; struct logger_channel_vtbl { logger_channel_constmsg_method *constmsg; logger_channel_msg_method *msg; logger_channel_vmsg_method *vmsg; logger_channel_flush_method *flush; logger_channel_close_method *close; logger_channel_reopen_method *reopen; // so a HUP will flush, close then reopen/create the log files again logger_channel_sink_method *sink; // the channel will verify its output make sense and if not act on it (ie: junk all until next reopen) const char *__class__; }; #define logger_channel_msg(channel_,level_,text_, text_len_, date_offs_) (channel_)->vtbl->constmsg((channel_),(level_),(text_),(text_len_),(date_offs_)) #define logger_channel_msgf(channel_,level_,text_, ...) (channel_)->vtbl->msg((channel_),(level_),(text_),__VA_ARGS__) #define logger_channel_vmsgf(channel_,level_,text_, args_) (channel_)->vtbl->msg((channel_),(level_),(text_),(args_)) #define logger_channel_flush(channel_) (channel_)->vtbl->flush(channel_) #define logger_channel_reopen(channel_) (channel_)->vtbl->reopen(channel_) #define logger_channel_close(channel_) (channel_)->vtbl->close(channel_) #define logger_channel_sink(channel_) (channel_)->vtbl->sink(channel_) /** * Message flags */ #define LOGGER_MESSAGE_STD 0 #define LOGGER_MESSAGE_TIMEMS 1 #define LOGGER_MESSAGE_PREFIX 2 /** * Allocates an empty channel * Meant to be used by channels implementation */ logger_channel* logger_channel_alloc(); /** * Returns true iff the current thread is the logger. * * @return true iff the current thread is the logger. */ bool logger_is_self(); /** * Returns TRUE if the queue is half full * * @param channel_name * @return */ bool logger_queue_fill_critical(); s32 logger_channel_get_usage_count(const char* channel_name); void logger_channel_register(const char* channel_name, struct logger_channel *channel); void logger_channel_unregister(const char* channel_name); void logger_channel_close_all(); void logger_handle_create(const char *logger_name, logger_handle **handle_holder); void logger_handle_add_channel(const char* logger_name, int level, const char* channel_name); void logger_handle_remove_channel(const char *logger_name, const char *channel_name); s32 logger_handle_count_channels(const char *logger_name); void logger_handle_close(const char *logger_name); /** * * Helper function. * Creates a logger for the given file descriptor (typically 1/stdout or 2/stderr) * * ie: logger_handle_create_to_fd("system", MSG_ALL_MASK, 1); * * @param logger_name name of the logger * @param mask the mask to use (ie: MSG_ALL_MASK) * @param fd the file descriptor */ void logger_handle_create_to_fd(const char *logger_name, int mask, int fd); static inline void logger_handle_create_to_stdout(const char *logger_name, int mask) { logger_handle_create_to_fd(logger_name, mask, 1); } /** * * Sends a formatted text to the logger * * @param handle handle to use, can be NULL * @param level level of the message * @param fmt format string * @param args parameters for the format */ void logger_handle_vmsg(logger_handle* handle, u32 level, const char* fmt, va_list args); /** * * Sends a formatted text to the logger * * @param handle handle to use, can be NULL * @param level level of the message * @param fmt format string * @param ... parameters for the format */ void logger_handle_msg(logger_handle* handle, u32 level, const char* fmt, ...); void logger_handle_msg_nocull(logger_handle* handle, u32 level, const char* fmt, ...); /** * * Sends a text to the logger * * @param handle handle to use, can be NULL * @param level level of the message * @param text text to send * @param text_len length of the text to send */ void logger_handle_msg_text(logger_handle *handle, u32 level, const char* text, u32 text_len); /** * * Sends a text to the logger with a prefix * * @param handle handle to use, can be NULL * @param level level of the message * @param text text to send * @param text_len text length * @param prefix prefix * @param prefix_len prefix length * @param flags LOGGER_MESSAGE_* flags */ void logger_handle_msg_text_ext(logger_handle *handle, u32 level, const char* text, u32 text_len, const char* prefix, u32 prefix_len, u16 flags); /** * Try to send a formatted text to the logger. * If the logging queue is full, drop the line. * This is to be used only in parts of code that would be dead-locked with the * logger in case of a full disk. * * ie: anything on the path of the HUP signal handling. * * @param handle handle to use, can be NULL * @param level level of the message * @param fmt format string * @param ... parameters for the format */ void logger_handle_try_msg(logger_handle* handle, u32 level, const char* fmt, ...); /** * Try to send a formatted text to the logger. * If the logging queue is full, drop the line. * This is to be used only in parts of code that would be dead-locked with the * logger in case of a full disk. * * ie: anything on the path of the HUP signal handling. * * @param handle handle to use, can be NULL * @param level level of the message * @param text text to send * @param text_len length of the text to send */ void logger_handle_try_msg_text(logger_handle *handle, u32 level, const char* text, u32 text_len); /** * Sets the layout for the logged memory dumps * Values MUST be set to (2^n)-1 with n >= 0 * Values MUST be < 256 * * @param group_mask The mask to group the bytes together (ie: 3 for making groups of 4) * @param separator_mask the mask to put a space separator every few bytes (ie: 3 for every 4 bytes) * */ void log_memdump_set_layout(u32 group_mask, u32 separator_mask); /** * Dumps memory in to the logger * * @param hndl handle to use, can be NULL * @param level level of the message * @param data_pointer memory to dump * @param size size of the memory to dump * @param line_size length of a line * @param flags see osprint_dump for details: OSPRINT_DUMP_ADDRESS, OSPRINT_DUMP_HEX, OSPRINT_DUMP_TEXT */ void log_memdump_ex(logger_handle* hndl, u32 level, const void* data_pointer, ssize_t size, ssize_t line_size, u32 flags); void log_memdump(logger_handle* hndl, u32 level, const void* data_pointer, ssize_t size, ssize_t line_size); void log_msghdr(logger_handle* hndl, u32 level, struct msghdr *hdr); void logger_handle_exit_level(u32 level); void logger_handle_finalize(); void logger_set_level(u8 level); #if DNSCORE_HAS_LOG_THREAD_TAG void logger_handle_set_thread_tag_with_pid_and_tid(pid_t pid, thread_t tid, const char tag[THREAD_TAG_SIZE]); void logger_handle_clear_thread_tag_with_pid_and_tid(pid_t pid, thread_t tid); void logger_handle_set_thread_tag(const char tag[THREAD_TAG_SIZE]); void logger_handle_clear_thread_tag(); #else static inline void logger_handle_set_thread_tag_with_pid_and_tid(pid_t pid, thread_t tid, const char tag[1]) { (void)pid; (void)tid; (void)tag; } static inline void logger_handle_clear_thread_tag_with_pid_and_tid(pid_t pid, thread_t tid) { (void)pid; (void)tid; } static inline void logger_handle_set_thread_tag(const char tag[1]) { (void)tag; } static inline void logger_handle_clear_thread_tag() { } #endif #define LOG_MEMDUMP_LAYOUT_DENSE 0xff,0xff #define LOG_MEMDUMP_LAYOUT_ERIC 3,0xff #define LOG_MEMDUMP_LAYOUT_GERY 0,3 /* * GCC style : * * #define debug(vararg...) logger_handle_msg(NULL,MSG_DEBUG,vararg) * * C99 style : * * #define debug(...) logger_handle_msg(NULL,MSG_DEBUG,__VA_ARGS__) * */ #if defined(MODULE_MSG_HANDLE) #define debug(...) logger_handle_msg((MODULE_MSG_HANDLE),MSG_DEBUG,__VA_ARGS__) #else #define debug(...) logger_handle_msg(NULL,MSG_DEBUG,__VA_ARGS__) #endif /** * LOG_TEXT_PREFIX is a text constant that will be prefixed to every text logged in the current source file. * It is a constant that MUST be set before including logger_handle.h (or any logger header) */ #if !defined(LOG_TEXT_PREFIX) #define LOG_TEXT_PREFIX #endif #if LOGGER_EARLY_CULL // #define LOGGER_EARLY_CULL_PREFIX(__MSGLEVEL__) if(MODULE_MSG_HANDLE->channels[__MSGLEVEL__].offset >= 0) // if(MODULE_MSG_HANDLE->channels[__MSGLEVEL__].offset >= 0) // ptr + k1 + level * k2 + k3 // if(table[MODULE_MSG_INDEX].channel[__MSGLEVEL__].offset >= 0 // ptr + index * k0 + k1 + level * k2 + k3 // // proposed optimisation: // ptr + level <- choosen one (obviously) // ptr + index * k0 + level // note: k0 = 64, k1 = 0, k2 = 16 // if index = index * k0, it's still one addition that could be removed // if channel cannot be destroyed once created but only disabled, setting the ptr once is enough // it still means children must be spawned after the channels are setup // I don't see this as a problem as channel names are hard-coded in the binaries // #define LOGGER_EARLY_CULL_PREFIX(__MSGLEVEL__) if(MODULE_MSG_HANDLE->active[__MSGLEVEL__] != 0) static inline bool log_is_set(logger_handle* handle, int level) { return (handle != NULL) && (handle->channels[level].offset >= 0); } #define log_debug7(...) LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG7) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_DEBUG7,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug6(...) LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG6) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_DEBUG6,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug5(...) LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG5) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_DEBUG5,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug4(...) LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG4) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_DEBUG4,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug3(...) LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG3) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_DEBUG3,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug2(...) LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG2) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_DEBUG2,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug1(...) LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG1) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_DEBUG1,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug(...) LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_DEBUG,LOG_TEXT_PREFIX __VA_ARGS__) #define log_notice(...) LOGGER_EARLY_CULL_PREFIX(MSG_NOTICE) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_NOTICE,LOG_TEXT_PREFIX __VA_ARGS__) #define log_info(...) LOGGER_EARLY_CULL_PREFIX(MSG_INFO) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_INFO,LOG_TEXT_PREFIX __VA_ARGS__) #define log_warn(...) LOGGER_EARLY_CULL_PREFIX(MSG_WARNING) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_WARNING,LOG_TEXT_PREFIX __VA_ARGS__) #define log_err(...) LOGGER_EARLY_CULL_PREFIX(MSG_ERR) logger_handle_msg_nocull(MODULE_MSG_HANDLE,MSG_ERR,LOG_TEXT_PREFIX __VA_ARGS__) #define log_to_level(level_,...) LOGGER_EARLY_CULL_PREFIX((level_)) logger_handle_msg_nocull(MODULE_MSG_HANDLE,(level_),LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug7(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG7,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug6(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG6,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug5(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG5,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug4(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG4,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug3(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG3,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug2(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG2,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug1(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG1,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_notice(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_NOTICE,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_info(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_INFO,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_warn(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_WARNING,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_err(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_ERR,LOG_TEXT_PREFIX __VA_ARGS__) /* Obsolete, Critical error: quit */ #define log_try_quit(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_CRIT,LOG_TEXT_PREFIX __VA_ARGS__) /* Critical error: quit */ #define log_try_crit(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_CRIT,LOG_TEXT_PREFIX __VA_ARGS__) /* Emergency: quit */ #define log_try_emerg(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_EMERG,LOG_TEXT_PREFIX __VA_ARGS__) #else #define log_debug7(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_DEBUG7,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug6(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_DEBUG6,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug5(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_DEBUG5,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug4(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_DEBUG4,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug3(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_DEBUG3,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug2(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_DEBUG2,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug1(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_DEBUG1,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_DEBUG,LOG_TEXT_PREFIX __VA_ARGS__) #define log_notice(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_NOTICE,LOG_TEXT_PREFIX __VA_ARGS__) #define log_info(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_INFO,LOG_TEXT_PREFIX __VA_ARGS__) #define log_warn(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_WARNING,LOG_TEXT_PREFIX __VA_ARGS__) #define log_err(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_ERR,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug7(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG7,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug6(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG6,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug5(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG5,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug4(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG4,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug3(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG3,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug2(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG2,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug1(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG1,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_DEBUG,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_notice(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_NOTICE,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_info(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_INFO,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_warn(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_WARNING,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_err(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_ERR,LOG_TEXT_PREFIX __VA_ARGS__) #endif /* Obsolete, Critical error: quit */ #define log_quit(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_CRIT,LOG_TEXT_PREFIX __VA_ARGS__) /* Critical error: quit */ #define log_crit(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_CRIT,LOG_TEXT_PREFIX __VA_ARGS__) /* Emergency: quit */ #define log_emerg(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_EMERG,LOG_TEXT_PREFIX __VA_ARGS__) /* Obsolete, Critical error: quit */ #define log_try_quit(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_CRIT,LOG_TEXT_PREFIX __VA_ARGS__) /* Critical error: quit */ #define log_try_crit(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_CRIT,LOG_TEXT_PREFIX __VA_ARGS__) /* Emergency: quit */ #define log_try_emerg(...) logger_handle_try_msg(MODULE_MSG_HANDLE,MSG_EMERG,LOG_TEXT_PREFIX __VA_ARGS__) /* -7---------------------------------------------------------------------------- * * MACROS */ #if DEBUG #define DERROR_MSG(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_ERR,__VA_ARGS__) #else #define DERROR_MSG(...) /* nothing */ #endif /* DEBUG */ /** * For practical reasons, the code for logger_init() is in logger_handle.c */ void logger_init(); void logger_init_ex(u32 queue_size, size_t shared_heap_size); /** * For practical reasons, the code for logger_start() is in logger_handle.c */ void logger_start(); void logger_start_server(); void logger_stop_server(); void logger_start_client(); void logger_stop_client(); u8 logger_set_shared_heap(u8 id); /** * For practical reasons, the code for logger_stop() is in logger_handle.c */ void logger_stop(); /** * For practical reasons, the code for logger_finalize() is in logger_handle.c */ void logger_finalize(); /** * For practical reasons, the code for logger_flush() is in logger_handle.c */ void logger_flush(); /** * The next message seen by the logger will trigger a sink. */ void logger_sink_noblock(); /** * Asks all channels to verify their output is valid and if not, to discard * all content to a sink until reopen is called. */ void logger_sink(); /** * For practical reasons, the code for logger_reopen() is in logger_handle.c */ void logger_reopen(); bool logger_is_running(); /** * Sets the logger queue size */ u32 logger_set_queue_size(u32 n); void logger_set_path(const char *path); const char* logger_get_path(); void logger_release_ownership(); void logger_take_ownership(pid_t new_owner); void logger_set_uid(uid_t uid); uid_t logger_get_uid(); void logger_set_gid(uid_t gid); gid_t logger_get_gid(); /** * Polls for the state of the logger. * Made for a specific task. * Use with care, or not at all. */ bool logger_wait_started(); #ifdef __cplusplus } #endif #endif /* _LOGGER_HANDLE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/logger-output-stream.h0000644000000000000000000000013214505005532026100 xustar000000000000000030 mtime=1695812442.098977261 30 atime=1695812445.790030125 30 ctime=1695812494.288724724 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/logger-output-stream.h0000664000374500037450000000446314505005532026051 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif ya_result logger_output_stream_open(output_stream* stream, logger_handle *handle, u16 level, u32 max_line_size); #ifdef __cplusplus } #endif /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/mapped-file.h0000644000000000000000000000013014505005532024153 xustar000000000000000029 mtime=1695812442.07097686 29 atime=1695812445.78903011 30 ctime=1695812494.290724752 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/mapped-file.h0000664000374500037450000000537614505005532024132 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #include #ifdef __cplusplus extern "C" { #endif /** * Opens a file. * * @param fp a pointer to a file_t that will hold the file object * @param * @param flags the typical posix flags. (O_RDWR, O_RDONLY, ...) Not all flags are valid. */ ya_result mapped_file_open_ex(file_t *fp, const char *filename, int flags); ya_result mapped_file_create_ex(file_t *fp, const char *filename, int flags, mode_t mode); ya_result mapped_file_create_volatile(file_t *fp, const char *filename, size_t base_size); ya_result mapped_file_get_buffer(file_t f, void **address, ssize_t *size); ya_result mapped_file_get_buffer_const(file_t f, const void **address, ssize_t *size); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/message-buffer.h0000644000000000000000000000013014505005532024663 xustar000000000000000029 mtime=1695812442.07797696 29 atime=1695812445.78903011 30 ctime=1695812494.292724781 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/message-buffer.h0000664000374500037450000000435114505005532024632 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * *----------------------------------------------------------------------------*/ #pragma once #include ya_result message_buffer_processor(message_viewer *mv, const u8 *buffer, u16 length); /* ------------------------------------------------------------ */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/message-viewer.h0000644000000000000000000000013114505005532024714 xustar000000000000000029 mtime=1695812442.01297603 30 atime=1695812445.787030082 30 ctime=1695812494.294724809 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/message-viewer.h0000664000374500037450000001446414505005532024670 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #include #include #define MESSAGE_VIEWER_WITH_QUESTION 0x01 #define MESSAGE_VIEWER_WITH_ANSWER 0x02 #define MESSAGE_VIEWER_WITH_AUTHORITY 0x04 #define MESSAGE_VIEWER_WITH_ADDITIONAL 0x08 #define MESSAGE_VIEWER_WITH_HEADER 0x10 #define MESSAGE_VIEWER_WITH_XFR 0x20 #define MESSAGE_VIEWER_SIMPLE_QUERY (MESSAGE_VIEWER_WITH_HEADER|MESSAGE_VIEWER_WITH_QUESTION|MESSAGE_VIEWER_WITH_ANSWER|MESSAGE_VIEWER_WITH_AUTHORITY|MESSAGE_VIEWER_WITH_ADDITIONAL) #define MESSAGE_VIEWER_XFR_QUERY (MESSAGE_VIEWER_WITH_HEADER|MESSAGE_VIEWER_WITH_QUESTION|MESSAGE_VIEWER_WITH_ANSWER|MESSAGE_VIEWER_WITH_XFR) typedef struct message_viewer message_viewer; typedef void message_viewer_header_method(message_viewer *mv, const u8 *buffer); typedef void message_viewer_start_method(message_viewer *mv); typedef void message_viewer_end_method(message_viewer *mv, long time_duration); typedef void message_viewer_section_header_method(message_viewer *mv, u32 section_idx, u16 count); typedef void message_viewer_section_footer_method(message_viewer *mv, u32 section_idx, u16 count); typedef void message_viewer_question_record_method(message_viewer *mv, const u8 *record_wire, u16 rclass, u16 rtype); typedef void message_viewer_section_record_method(message_viewer *mv, const u8 *record_wire, u8 sectionidx); typedef ya_result message_viewer_pseudosection_record_method(message_viewer *mv, const u8 *record_wire); typedef struct message_viewer_vtbl message_viewer_vtbl; struct message_viewer_vtbl { message_viewer_header_method *three; message_viewer_start_method *four; message_viewer_end_method *five; message_viewer_section_header_method *six; message_viewer_section_footer_method *seven; message_viewer_question_record_method *eight; message_viewer_section_record_method *nine; message_viewer_pseudosection_record_method *print_pseudosection_record; const char *__class__; /* MUST BE A UNIQUE POINTER, ie: One defined in the class's .c file The name should be unique in order to avoid compiler tricks */ /* Add your inheritable methods here */ }; struct message_viewer { u64 bytes; u32 messages; u32 resource_records_total[4]; void *data; output_stream *os; const message_viewer_vtbl *vtbl; char **section_name; const host_address *host; // if set, will be used to count the servers found and in some messages. (default is NULL) u16 view_mode_with; }; #define message_viewer_class(mv_) ((mv_)->vtbl) #define message_viewer_class_name(mv_) ((mv_)->vtbl->__class__) #define message_viewer_header(mv_,buffer_) (mv_)->vtbl->three((mv_),(const u8*)(buffer_)) #define message_viewer_start(mv_) (mv_)->vtbl->four(mv_) #define message_viewer_end(mv_,time_duration_) (mv_)->vtbl->five((mv_),(time_duration_)) #define message_viewer_section_header(mv_,section_idx_,count_) (mv_)->vtbl->six((mv_),(section_idx_),(count_)) #define message_viewer_section_footer(mv_,section_idx_,count_) (mv_)->vtbl->seven((mv_),(section_idx_),(count_)) #define message_viewer_question_record(mv_,record_wire_,rclass_,rtype_) (mv_)->vtbl->eight((mv_),(record_wire_),(rclass_),(rtype_)) #define message_viewer_section_record(mv_,record_wire_,sectionidx_) (mv_)->vtbl->nine((mv_),(record_wire_),(sectionidx_)) #define message_viewer_pseudosection_record(mv_,record_wire_) (mv_)->vtbl->print_pseudosection_record((mv_),(record_wire_)) #define message_viewer_bytes_and_message_update(mv_,bytes_, messages_) {(mv_)->bytes+=(bytes_);(mv_)->messages+=(messages_);}; #define message_viewer_resource_record_total_update(mv_,count_) { \ mv->resource_records_total[0]+=count_[0]; \ mv->resource_records_total[1]+=count_[1]; \ mv->resource_records_total[2]+=count_[2]; \ mv->resource_records_total[3]+=count_[3];}; bool message_viewer_requires_section(int section, int view_with_mode); void message_viewer_set_default(message_viewer *mv); void message_viewer_init(message_viewer *mv); yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/message.h0000644000000000000000000000013214505005531023415 xustar000000000000000030 mtime=1695812441.992975743 30 atime=1695812445.787030082 30 ctime=1695812494.296724838 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/message.h0000664000374500037450000015532314505005531023370 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnspacket DNS Messages * @ingroup dnscore * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #pragma once #ifdef __cplusplus extern "C" { #endif /* ------------------------------------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Processing flags #define PROCESS_FL_ADDITIONAL_AUTH 0x01 #define PROCESS_FL_AUTHORITY_AUTH 0x02 #define PROCESS_FL_ADDITIONAL_CACHE 0x04 #define PROCESS_FL_AUTHORITY_CACHE 0x08 #define PROCESS_FL_RECURSION 0x20 #define PROCESS_FL_TCP 0x80 #define NETWORK_BUFFER_SIZE 65536 #define MESSAGE_PAYLOAD_IS_POINTER 1 /** * @note buffer MUST be aligned on 16 bits */ #define MESSAGE_HIFLAGS(buffer_) ((buffer_)[ 2]) #define MESSAGE_LOFLAGS(buffer_) ((buffer_)[ 3]) #define MESSAGE_FLAGS(buffer_) GET_U16_AT((buffer_)[ 2]) #if DNSCORE_HAS_TSIG_SUPPORT #define TSIGOTHR_TAG 0x5248544f47495354 #endif /* Only use constants with this */ #if AVOID_ANTIALIASING static inline void MESSAGE_FLAGS_OR_P(void* address, u16 f) { u16 *p = (u16*)address; *p |= f; } static inline void MESSAGE_FLAGS_AND_P(void* address, u16 f) { u16 *p = (u16*)address; *p &= f; } struct packet_writer; struct dns_resource_record; #ifdef WORDS_BIGENDIAN #define MESSAGE_FLAGS_OR(buffer_, hi_, lo_) MESSAGE_FLAGS_OR_P(&(buffer_)[2], (u16)((u16)((lo_) & 0xff) | ((u16)(hi_) << 8))) #define MESSAGE_FLAGS_AND(buffer_, hi_, lo_) MESSAGE_FLAGS_AND_P(&(buffer_)[2], (u16)((u16)((lo_) & 0xff) | ((u16)(hi_) << 8))) #define MESSAGE_FLAGS_SET(buffer_, hi_, lo_) SET_U16_AT_P(&(buffer_)[2], (u16)((u16)((lo_) & 0xff) | ((u16)hi_ << 8))) #else #define MESSAGE_FLAGS_OR(buffer_, hi_, lo_) MESSAGE_FLAGS_OR_P(&(buffer_)[2], (u16)(((u16)((hi_) & 0xff)) | (((u16)(lo_)) << 8))) #define MESSAGE_FLAGS_AND(buffer_, hi_, lo_) MESSAGE_FLAGS_AND_P(&(buffer_)[2], (u16)(((u16)((hi_) & 0xff)) | (((u16)(lo_)) << 8))) #define MESSAGE_FLAGS_SET(buffer_, hi_, lo_) SET_U16_AT_P(&(buffer_)[2], (u16)(((u16)((hi_) & 0xff)) | (((u16)(lo_)) << 8))) #endif #define MESSAGE_ID(buffer_) GET_U16_AT_P(&(buffer_)[0]) #define MESSAGE_SET_ID(buffer_,id_) SET_U16_AT_P(&(buffer_)[0],(id_)) #else #ifdef WORDS_BIGENDIAN #define MESSAGE_FLAGS_OR(buffer_, hi_, lo_) *((u16*)&(buffer_[2])) |= (lo_ | ((u16)hi_ << 8)) #define MESSAGE_FLAGS_AND(buffer_, hi_, lo_) *((u16*)&(buffer_[2])) &= (lo_ | ((u16)hi_ << 8)) #define MESSAGE_FLAGS_SET(buffer_, hi_, lo_) *((u16*)&(buffer_[2])) = (lo_ | ((u16)hi_ << 8)) #else #define MESSAGE_FLAGS_OR(buffer_, hi_, lo_) *((u16*)&(buffer_[2])) |= (hi_ | ((u16)lo_ << 8)) #define MESSAGE_FLAGS_AND(buffer_, hi_, lo_) *((u16*)&(buffer_[2])) &= (hi_ | ((u16)lo_ << 8)) #define MESSAGE_FLAGS_SET(buffer_, hi_, lo_) *((u16*)&(buffer_[2])) = (hi_ | ((u16)lo_ << 8)) #endif #define MESSAGE_ID(buffer) (*((u16*)&(buffer)[ 0])) #define MESSAGE_SET_ID(buffer_,id_) (*((u16*)&(buffer)[ 0])) = (id_) #endif #define MESSAGE_QR(buffer_) (MESSAGE_HIFLAGS(buffer_) & QR_BITS) #define MESSAGE_OP(buffer_) (MESSAGE_HIFLAGS(buffer_) & OPCODE_BITS) #define MESSAGE_AA(buffer_) (MESSAGE_HIFLAGS(buffer_) & AA_BITS) #define MESSAGE_TC(buffer_) (MESSAGE_HIFLAGS(buffer_) & TC_BITS) #define MESSAGE_RD(buffer_) (MESSAGE_HIFLAGS(buffer_) & RD_BITS) #define MESSAGE_RA(buffer_) (MESSAGE_LOFLAGS(buffer_) & RA_BITS) #define MESSAGE_ZF(buffer_) (MESSAGE_LOFLAGS(buffer_) & Z_BITS) #define MESSAGE_AD(buffer_) (MESSAGE_LOFLAGS(buffer_) & AD_BITS) #define MESSAGE_CD(buffer_) (MESSAGE_LOFLAGS(buffer_) & CD_BITS) #define MESSAGE_RCODE(buffer_) (MESSAGE_LOFLAGS(buffer_) & RCODE_BITS) // the size of the section by index [0;3] #define MESSAGE_SECTION_COUNT(buffer_,index_) GET_U16_AT(((buffer_)[4 + ((index_)<< 1)])) #define MESSAGE_QD(buffer_) GET_U16_AT((buffer_)[4]) #define MESSAGE_AN(buffer_) GET_U16_AT((buffer_)[6]) #define MESSAGE_NS(buffer_) GET_U16_AT((buffer_)[8]) #define MESSAGE_AR(buffer_) GET_U16_AT((buffer_)[10]) #define MESSAGE_NSAR(buffer_) GET_U32_AT((buffer_)[8]) #define MESSAGE_SET_OP(buffer_, val_) (MESSAGE_HIFLAGS(buffer_) = (MESSAGE_HIFLAGS(buffer_) & ~OPCODE_BITS) | (val_)) #define MESSAGE_SET_QD(buffer_,val_) SET_U16_AT((buffer_)[4],(val_)) #define MESSAGE_SET_AN(buffer_,val_) SET_U16_AT((buffer_)[6],(val_)) #define MESSAGE_SET_NS(buffer_,val_) SET_U16_AT((buffer_)[8],(val_)) #define MESSAGE_SET_AR(buffer_,val_) SET_U16_AT((buffer_)[10],(val_)) #define MESSAGE_SET_NSAR(buffer_,val_) SET_U32_AT((buffer_)[8],(val_)) /* DYNUPDATE rfc 2136 */ #define MESSAGE_ZO(buffer_) GET_U16_AT((buffer_)[4]) #define MESSAGE_PR(buffer_) GET_U16_AT((buffer_)[6]) #define MESSAGE_UP(buffer_) GET_U16_AT((buffer_)[8]) #define MESSAGE_SET_ZO(buffer_, val_) SET_U16_AT((buffer_)[4],(val_)) #define MESSAGE_SET_PR(buffer_, val_) SET_U16_AT((buffer_)[6],(val_)) #define MESSAGE_SET_UP(buffer_, val_) SET_U16_AT((buffer_)[8],(val_)) //#define MESSAGE_AD(buffer) (*((u16*)&(buffer)[10])) #define MESGDATA_TAG 0x415441444753454d #if DNSCORE_HAS_TSIG_SUPPORT typedef struct message_tsig message_tsig; struct message_tsig { const tsig_item *tsig; u16 reserved_0; /* ALIGN32 */ u16 timehi; /* NETWORK */ u32 timelo; /* NETWORK */ u16 fudge; /* NETWORK */ u16 mac_size; /* NATIVE */ u16 original_id;/* NETWORK */ u16 error; /* NETWORK */ u16 other_len; /* NETWORK */ u16 tsig_offset;// keeps the tsig_offset in the message for internal processing, do not use directly u32 reserved_2; /* ALIGN64 */ u8 mac[64]; u8 *other; tsig_hmac_t hmac; /* only used for tcp */ s8 tcp_tsig_countdown; /* maximum value is supposed to be 100 */ u8 mac_algorithm; }; #endif /* A memory pool for the lookup's benefit */ #define MESSAGE_POOL_SIZE 0x20000 // flags for MESSAGE_MAKE_QUERY_EX #define MESSAGE_EDNS0_SIZE 0x4000 // any bit that is not set in EDNS0 #define MESSAGE_EDNS0_DNSSEC 0x8000 #define MESSAGE_BUFFER_SIZE 0x10500 #define MESSAGE_DATA_CONTROL_BUFFER_SIZE 64 struct message_data { struct msghdr _msghdr; struct iovec _iovec; socketaddress _sender; // who the sender is u8 *_ar_start; // for the TSIG // THIS CROUP IS COPIED USING A MEMCPY IN message_dup() -> u32 _rcode_ext; // network endian finger_print _status; // contains an RCODE, why is it separated from the buffer ? #if MESSAGE_PAYLOAD_IS_POINTER u32 _message_data_size; // the size of the allocated message structure #endif u16 _query_type; u16 _query_class; bool _edns; bool _nsid; u8 _referral; u8 _control_buffer_size; u8 _tcp_serial; /* bool is_delegation; for quick referral : later */ u32 _buffer_size; // 32 bits aligned // the maximum number of bytes we are ready to fill (can be changed) u32 _buffer_size_limit; // // the maximum number of bytes we can ever fill (as the buffer size is limited and ) void *_pool; // a pool to be used as a quick memory for the message int _pool_size; // a zdb query will store some temporary records in it. Consider size to be from 64K to 128K. #if DNSCORE_HAS_TSIG_SUPPORT message_tsig _tsig; #endif volatile u64 recv_us; volatile u64 pushed_us; volatile u64 popped_us; // <- THIS GROUP IS COPIED USING A MEMCPY IN message_dup() u8 _msghdr_control_buffer[(MESSAGE_DATA_CONTROL_BUFFER_SIZE + 7) & ~7]; // receives the destination address, IF MOVED, YOU NEED TO LOOK AT message_new_instance() ZEROMEMORY call u8 _canonised_fqdn[(MAX_DOMAIN_LENGTH + 7) & ~7]; /* Ensure (buffer - buffer_tcp_len) is equal to 2 ! */ #if MESSAGE_PAYLOAD_IS_POINTER u8 *_buffer; #else u64 __reserved_force_align__1; // 64 bits aligned u16 __reserved_force_align__2; // 32 bits aligned u8 _buffer_tcp_len[2]; // DON'T SEPARATE THESE TWO (FIRST) u8 _buffer[NETWORK_BUFFER_SIZE]; // DON'T SEPARATE THESE TWO (SECOND) #endif }; typedef struct message_data message_data; struct message_data_with_buffer { message_data message; #if MESSAGE_PAYLOAD_IS_POINTER u64 __reserved_force_align__1; // 64 bits aligned u8 _buffer[NETWORK_BUFFER_SIZE]; // DON'T SEPARATE THESE TWO (SECOND) u8 _buffer_limit[1]; #endif }; typedef struct message_data_with_buffer message_data_with_buffer; struct message_dnsupdate_data { struct message_dnsupdate_data *next; u32 zttl; u16 ztype; u16 zclass; u8 zname[MAX_DOMAIN_LENGTH]; output_stream zrdata[RDATA_MAX_LENGTH +1]; u8 *zrdata2; u16 zrdata_len; }; typedef struct message_dnsupdate_data message_dnsupdate_data; /** * A message_map is a message_data wrapper that got the records indexed * Each vector entry points to the FQDN of a record in the message. */ struct message_map { const message_data *mesg; ptr_vector records; u16 section_base[4]; }; typedef struct message_map message_map; /* ------------------------------------------------------------ */ /** * This sets a default, global, rate for functions supporting it. * Rate is used in TCP streaming so that if the other end reads or writes * too slowly then the connection is severed, harshly. * * @param rate */ void message_set_minimum_troughput_default(double rate); /* ------------------------------------------------------------ */ static inline void message_set_protocol(message_data *mesg, u8 protocol) { // THIS SEEMS POINTLESS AS IT'S ONLY USED FOR LOGGING (void)mesg; (void)protocol; } static inline u8 message_get_protocol(const message_data *mesg) { // THIS SEEMS POINTLESS AS IT'S ONLY USED FOR LOGGING (void)mesg; return 0; } /** * * The hope here is that the compiler will be smart enough to translates this as * one move. (mov) * * @param mesg * @param qd * @param an * @param ns * @param ar */ static inline void message_set_query_answer_authority_additional_counts_ne(message_data *mesg, u16 qd, u16 an, u16 ns, u16 ar) { #ifdef WORDS_BIGENDIAN u64 value = (((u64)qd) << 48) | (((u64)an) << 32) | (((u64)ns) << 16) | (((u64)ar) ); #else u64 value = (((u64)qd) ) | (((u64)an) << 16) | (((u64)ns) << 32) | (((u64)ar) << 48); #endif SET_U64_AT(mesg->_buffer[4], value); } static inline void message_set_query_answer_authority_additional_counts(message_data *mesg, u16 qd, u16 an, u16 ns, u16 ar) { #ifdef WORDS_BIGENDIAN u64 value = (((u64)ntohs(qd)) << 48) | (((u64)ntohs(an)) << 32) | (((u64)ntohs(ns)) << 16) | (((u64)ntohs(ar)) ); #else u64 value = (((u64)ntohs(qd)) ) | (((u64)ntohs(an)) << 16) | (((u64)ntohs(ns)) << 32) | (((u64)ntohs(ar)) << 48); #endif SET_U64_AT(mesg->_buffer[4], value); } static inline void message_set_authority_additional_counts(message_data *mesg, u16 ns, u16 ar) { #ifdef WORDS_BIGENDIAN u32 value = (((u32)ns) << 16) | (((u32)ar) ); #else u32 value = (((u32)ns) ) | (((u32)ar) << 16); #endif MESSAGE_SET_NSAR(mesg->_buffer, value); } static inline void message_set_pool_buffer(message_data *mesg, void *p, int size) { mesg->_pool = p; mesg->_pool_size = size; } static inline void* message_get_pool_buffer(const message_data *mesg) { return mesg->_pool; } static inline int message_get_pool_size(const message_data *mesg) { return mesg->_pool_size; } static inline u8 message_get_opcode(const message_data *mesg) { return MESSAGE_OP(mesg->_buffer); } static inline void message_set_opcode(message_data *mesg, u8 opcode) { MESSAGE_SET_OP(mesg->_buffer, opcode); } static inline void message_set_referral(message_data *mesg, u8 referral) { mesg->_referral = referral; } static inline u8 message_get_referral(const message_data *mesg) { return mesg->_referral; } // Network Endian operations static inline u16 message_get_query_count_ne(const message_data *mesg) { return MESSAGE_QD(mesg->_buffer); } static inline void message_set_answer_count_ne(message_data *mesg, u16 network_endian_value) { MESSAGE_SET_AN(mesg->_buffer, network_endian_value); } static inline u16 message_get_answer_count_ne(const message_data *mesg) { return MESSAGE_AN(mesg->_buffer); } static inline void message_set_authority_count_ne(message_data *mesg, u16 network_endian_value) { MESSAGE_SET_NS(mesg->_buffer, network_endian_value); } static inline u16 message_get_authority_count_ne(const message_data *mesg) { return MESSAGE_NS(mesg->_buffer); } static inline void message_set_additional_count_ne(message_data *mesg, u16 network_endian_value) { MESSAGE_SET_AR(mesg->_buffer, network_endian_value); } static inline u16 message_get_additional_count_ne(const message_data *mesg) { return MESSAGE_AR(mesg->_buffer); } static inline void message_set_update_count_ne(message_data *mesg, u16 network_endian_value) { MESSAGE_SET_UP(mesg->_buffer, network_endian_value); } static inline u16 message_get_update_count_ne(const message_data *mesg) { return MESSAGE_UP(mesg->_buffer); } static inline u16 message_get_prerequisite_count_ne(const message_data *mesg) { return MESSAGE_PR(mesg->_buffer); } static inline u16 message_get_section_count_ne(const message_data *mesg, int section) { return MESSAGE_SECTION_COUNT(mesg->_buffer, section); } // Host endian static inline u16 message_get_query_count(const message_data *mesg) { return ntohs(message_get_query_count_ne(mesg)); } static inline void message_set_answer_count(message_data *mesg, u16 host_endian_value) { message_set_answer_count_ne(mesg, htons(host_endian_value)); } static inline u16 message_get_answer_count(const message_data *mesg) { return ntohs(message_get_answer_count_ne(mesg)); } static inline void message_set_authority_count(message_data *mesg, u16 host_endian_value) { message_set_authority_count_ne(mesg, htons(host_endian_value)); } static inline u16 message_get_authority_count(const message_data *mesg) { return ntohs(message_get_authority_count_ne(mesg)); } static inline void message_set_additional_count(message_data *mesg, u16 host_endian_value) { message_set_additional_count_ne(mesg, htons(host_endian_value)); } static inline u16 message_get_additional_count(const message_data *mesg) { return ntohs(message_get_additional_count_ne(mesg)); } static inline void message_add_additional_count(message_data *mesg, u16 value) { message_set_additional_count(mesg, message_get_additional_count(mesg) + value); } static inline void message_sub_additional_count(message_data *mesg, u16 value) { message_set_additional_count(mesg, message_get_additional_count(mesg) - value); } static inline void message_set_update_count(message_data *mesg, u16 host_endian_value) { message_set_update_count_ne(mesg, htons(host_endian_value)); } static inline u16 message_get_update_count(const message_data *mesg) { return ntohs(message_get_update_count_ne(mesg)); } static inline void message_add_update_count(message_data *mesg, u16 host_endian_value) { message_set_update_count(mesg, message_get_update_count(mesg) + host_endian_value); } static inline u16 message_get_prerequisite_count(const message_data *mesg) { return ntohs(message_get_prerequisite_count_ne(mesg)); } static inline u16 message_get_section_count(const message_data *mesg, int section) { return ntohs(message_get_section_count_ne(mesg, section)); } // static inline bool message_isquery(const message_data *mesg) { return MESSAGE_QR(mesg->_buffer) == 0; } static inline bool message_isanswer(const message_data *mesg) { return MESSAGE_QR(mesg->_buffer) != 0; } static inline bool message_istruncated(const message_data *mesg) { return MESSAGE_TC(mesg->_buffer) != 0; } static inline void message_set_truncated(message_data *mesg, bool truncated) { if(truncated) { MESSAGE_HIFLAGS(mesg->_buffer) |= TC_BITS; } else { MESSAGE_HIFLAGS(mesg->_buffer) &= ~TC_BITS; } } static inline void message_set_answer(message_data *mesg) { MESSAGE_HIFLAGS(mesg->_buffer) |= QR_BITS; } static inline void message_clear_answer(message_data *mesg) { MESSAGE_HIFLAGS(mesg->_buffer) &= ~QR_BITS; } static inline bool message_has_recursion_desired(const message_data *mesg) { return MESSAGE_RD(mesg->_buffer) != 0; } static inline bool message_has_recursion_available(const message_data *mesg) { return MESSAGE_RA(mesg->_buffer) != 0; } static inline bool message_has_authenticated_data(const message_data *mesg) { return MESSAGE_AD(mesg->_buffer) != 0; } static inline bool message_has_checking_disabled(const message_data *mesg) { return MESSAGE_CD(mesg->_buffer) != 0; } static inline u8 message_get_rcode(const message_data *mesg) { return MESSAGE_RCODE(mesg->_buffer); } static inline void message_or_rcode(message_data *mesg, u8 rcode) { MESSAGE_LOFLAGS(mesg->_buffer) |= rcode; } static inline void message_set_rcode(message_data *mesg, u8 rcode) { MESSAGE_LOFLAGS(mesg->_buffer) = (MESSAGE_LOFLAGS(mesg->_buffer) & ~RCODE_BITS) | rcode; } static inline u32 message_get_rcode_ext(const message_data *mesg) { return mesg->_rcode_ext; } static inline bool message_has_rcode_ext_dnssec(const message_data *mesg) { return (mesg->_rcode_ext & RCODE_EXT_DNSSEC) != 0; } static inline void message_set_authoritative_answer(message_data *mesg) { MESSAGE_HIFLAGS(mesg->_buffer) |= AA_BITS|QR_BITS; } static inline void message_set_truncated_answer(message_data *mesg) { MESSAGE_HIFLAGS(mesg->_buffer) |= TC_BITS|QR_BITS; } static inline bool message_is_truncated(message_data *mesg) { return (MESSAGE_HIFLAGS(mesg->_buffer) & TC_BITS) != 0; } static inline void message_set_authoritative(message_data *mesg) { MESSAGE_HIFLAGS(mesg->_buffer) |= AA_BITS; } static inline void message_disable_authoritative(message_data *mesg) { MESSAGE_HIFLAGS(mesg->_buffer) &= ~AA_BITS; } static inline void message_set_recursion_desired(message_data *mesg) { MESSAGE_HIFLAGS(mesg->_buffer) |= RD_BITS; } static inline void message_set_authenticated_data(message_data *mesg) { MESSAGE_LOFLAGS(mesg->_buffer) |= AD_BITS; } static inline bool message_isauthoritative(const message_data *mesg) { return (MESSAGE_HIFLAGS(mesg->_buffer) & AA_BITS) != 0; } static inline void message_apply_mask(message_data *mesg, int hi, int lo) { MESSAGE_FLAGS_AND(mesg->_buffer, (u8)hi, (u8)lo); } static inline void message_apply_lo_mask(message_data *mesg, u8 lo) { MESSAGE_LOFLAGS(mesg->_buffer) &= lo; } static inline u16 message_get_query_type(const message_data *mesg) { return mesg->_query_type; } static inline const u16* message_get_query_type_ptr(const message_data *mesg) { return &mesg->_query_type; } static inline void message_set_query_type(message_data *mesg, u16 qtype) { mesg->_query_type = qtype; } static inline u16 message_get_query_class(const message_data *mesg) { return mesg->_query_class; } // mostly for printing with format static inline const u16* message_get_query_class_ptr(const message_data *mesg) { return &mesg->_query_class; } static inline void message_set_query_class(message_data *mesg, u16 qclass) { mesg->_query_class = qclass; } static inline u16 message_get_size_u16(const message_data *mesg) { return (u16)mesg->_msghdr.msg_iov[0].iov_len; } static inline size_t message_get_size(const message_data *mesg) { return mesg->_msghdr.msg_iov[0].iov_len; } static inline void message_set_size(message_data *mesg, size_t size) { mesg->_msghdr.msg_iov[0].iov_len = size; } static inline void message_increase_size(message_data *mesg, size_t size) { mesg->_msghdr.msg_iov[0].iov_len += size; } static inline const u8 *message_get_buffer_const(const message_data *mesg) { return mesg->_buffer; } static inline u8 *message_get_buffer(message_data *mesg) { return mesg->_buffer; } static inline u16 message_get_flags(const message_data *mesg) { return MESSAGE_FLAGS(mesg->_buffer); } static inline u8 message_get_flags_hi(const message_data *mesg) { return MESSAGE_HIFLAGS(mesg->_buffer); } static inline u8 message_get_flags_lo(const message_data *mesg) { return MESSAGE_LOFLAGS(mesg->_buffer); } static inline void message_set_flags_hi(message_data *mesg, u8 hi) { MESSAGE_HIFLAGS(mesg->_buffer) = hi; } static inline void message_set_flags_lo(message_data *mesg, u8 lo) { MESSAGE_LOFLAGS(mesg->_buffer) = lo; } static inline u8 message_get_op(message_data *mesg) { return MESSAGE_OP(mesg->_buffer); } /** * Returns a pointer to the first byte not set in the buffer (&buffer[size]) * WILL BE RENAMED INTO message_get_buffer_end(mesg) * @param mesg * @return */ static inline u8 *message_get_buffer_limit(message_data *mesg) { return &mesg->_buffer[message_get_size(mesg)]; } static inline const u8 *message_get_buffer_limit_const(const message_data *mesg) { return &mesg->_buffer[message_get_size(mesg)]; } /** * The maximum size of the buffer is, of course, a constant. * This value is the one used to artificially limit the writing in the buffer. * This is mostly used to reserve room for additional records (EDNS, TSIG) * * @param * @return */ static inline void message_set_buffer_size(message_data *mesg, u32 size) { assert(size <= mesg->_buffer_size_limit); mesg->_buffer_size = size; } static inline void message_reserve_buffer_size(message_data *mesg, u32 size) { assert(size <= mesg->_buffer_size); mesg->_buffer_size -= size; } static inline void message_increase_buffer_size(message_data *mesg, u32 size) { assert(size + mesg->_buffer_size <= mesg->_buffer_size_limit); mesg->_buffer_size += size; } static inline u32 message_get_buffer_size(const message_data *mesg) { return mesg->_buffer_size; } static inline void message_reset_buffer_size(message_data *mesg) { mesg->_buffer_size = mesg->_buffer_size_limit; } static inline u32 message_get_buffer_size_max(const message_data *mesg) { return mesg->_buffer_size_limit; } /** * Copies the data content into the buffer */ static inline void message_copy_buffer(const message_data *mesg, void *out_data, size_t data_size) { yassert(data_size >= message_get_size(mesg)); (void)data_size; memcpy(out_data, message_get_buffer_const(mesg), message_get_size(mesg)); } static inline void message_copy_into_buffer(message_data *mesg, const void *in_data, size_t data_size) { if(data_size > message_get_buffer_size(mesg)) { formatln("message_copy_into_buffer: %p data_size=%llu <= buffer_size=%u", mesg, data_size, message_get_buffer_size(mesg)); } yassert(data_size <= message_get_buffer_size(mesg)); memcpy(message_get_buffer(mesg), in_data, data_size); message_set_size(mesg, data_size); } /** * Copies the control content into the buffer */ static inline u8 message_copy_control(const message_data *mesg, void *out_data, size_t data_size) { #if __unix__ yassert(data_size >= mesg->_msghdr.msg_controllen); (void)data_size; memcpy(out_data, mesg->_msghdr.msg_control, mesg->_msghdr.msg_controllen); return mesg->_msghdr.msg_controllen; #else return 0; #endif } static inline u8 message_control_size(const message_data *mesg) { return mesg->_msghdr.msg_controllen; } static inline void message_set_control(message_data *mesg, const void *data, size_t data_size) { #if __unix__ yassert(data_size <= sizeof(mesg->_msghdr_control_buffer)); memcpy(mesg->_msghdr_control_buffer, data, data_size); mesg->_msghdr.msg_controllen = data_size; #if __FreeBSD__ || __OpenBSD__ if(data_size != 0) { mesg->_msghdr.msg_control = mesg->_msghdr_control_buffer; } else { mesg->_msghdr.msg_control = NULL; } #endif #else #endif } static inline void message_reset_control_size(message_data *mesg) { #if __unix__ #if __FreeBSD__ || __OpenBSD__ mesg->_msghdr.msg_control = mesg->_msghdr_control_buffer; #endif mesg->_msghdr.msg_controllen = sizeof(mesg->_msghdr_control_buffer); #else #endif } static inline void message_reset_control(message_data *mesg) { #if __unix__ mesg->_msghdr.msg_control = mesg->_msghdr_control_buffer; mesg->_msghdr.msg_controllen = sizeof(mesg->_msghdr_control_buffer); #else #endif } static inline void message_clear_control(message_data *mesg) { #if __unix__ mesg->_msghdr.msg_control = NULL; mesg->_msghdr.msg_controllen = 0; #else #endif } static inline void message_set_edns0(message_data *mesg, bool enabled) { mesg->_edns = enabled; } static inline bool message_is_edns0(const message_data *mesg) { return mesg->_edns; } static inline bool message_has_nsid(const message_data *mesg) { return mesg->_nsid; } static inline bool message_has_tsig(const message_data *mesg) { return mesg->_tsig.tsig != NULL; } static inline void message_clear_hmac(message_data *mesg) { if(mesg->_tsig.hmac != NULL) { hmac_free(mesg->_tsig.hmac); mesg->_tsig.hmac = NULL; } } static inline const u8 *message_tsig_get_name(const message_data *mesg) { return mesg->_tsig.tsig->name; } static inline s64 message_tsig_get_epoch(const message_data *mesg) { u64 then = (u64)ntohs(mesg->_tsig.timehi); then <<= 32; then |= (u64)ntohl(mesg->_tsig.timelo); return (s64)then; } static inline s64 message_tsig_get_fudge(const message_data *mesg) { u64 then = (u64)ntohs(mesg->_tsig.fudge); return (s64)then; } static inline int message_tsig_mac_get_size(const message_data *mesg) { return mesg->_tsig.mac_size; } static inline void message_tsig_set_error(message_data *mesg, u16 err) { mesg->_tsig.error = err; } static inline u16 message_tsig_get_error(message_data *mesg) { return mesg->_tsig.error; } static inline void message_tsig_mac_copy(const message_data *mesg, u8 *to) { memcpy(to, mesg->_tsig.mac, message_tsig_mac_get_size(mesg)); } static inline const u8* message_tsig_mac_get_const(const message_data *mesg) { return mesg->_tsig.mac; } static inline void message_tsig_copy_from(message_data *mesg, const message_data *source) { message_tsig *d = &mesg->_tsig; const message_tsig *s = &source->_tsig; memcpy(d, s, offsetof(message_tsig, mac)); memcpy(d->mac, s->mac, s->mac_size); if((s->other != NULL) && (s->other_len > 0)) { MALLOC_OR_DIE(u8*, d->other, s->other_len, TSIGOTHR_TAG); memcpy(d->other, s->other, s->other_len); } else { d->other = NULL; } d->hmac = s->hmac; d->tcp_tsig_countdown = s->tcp_tsig_countdown; d->mac_algorithm = s->mac_algorithm; } static inline void message_tsig_set_key(message_data *mesg, const tsig_item *key) { mesg->_tsig.tsig = key; mesg->_tsig.mac_algorithm = key->mac_algorithm; } static inline const tsig_item *message_tsig_get_key(const message_data *mesg) { return mesg->_tsig.tsig; } static inline void message_tsig_clear_key(message_data *mesg) { mesg->_tsig.tsig = NULL ; } static inline const u8 *message_tsig_get_key_bytes(const message_data *mesg) { return mesg->_tsig.tsig->mac; } static inline u16 message_tsig_get_key_size(const message_data *mesg) { return mesg->_tsig.tsig->mac_size; } static inline message_header *message_get_header(message_data *mesg) { return (message_header*)message_get_buffer(mesg); } #if DEBUG static inline void message_debug_trash_buffer(message_data *mesg) { memset(message_get_buffer(mesg), 0xee, message_get_buffer_size_max(mesg)); } #else static inline void message_debug_trash_buffer(message_data *mesg) { (void)mesg; } #endif static inline void message_copy_msghdr(const message_data *mesg, struct msghdr *copyto) { memcpy(copyto, &mesg->_msghdr, sizeof(mesg->_msghdr)); } ya_result message_process_query(message_data *mesg); int message_process(message_data *); int message_process_lenient(message_data *mesg); void message_transform_to_error(message_data *mesg); void message_transform_to_signed_error(message_data *mesg); /* global */ void message_edns0_setmaxsize(u16 maxsize); static inline void message_edns0_clear_undefined_flags(message_data *mesg) // all but DO { mesg->_rcode_ext &= RCODE_EXT_DNSSEC; } /** * * @param mesg * @param qname * @param qtype * @param qclass * @param id */ void message_make_query(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass); void message_make_query_ex(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass, u16 flags); void message_make_query_ex_with_edns0(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass, u32 edns0_ttl); struct packet_writer; void message_make_message(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass, struct packet_writer* uninitialised_packet_writer); void message_make_dnsupdate_init(message_data *mesg, u16 id, const u8 *zzone, u16 zclass, u32 max_size, struct packet_writer *uninitialised_pw); ya_result message_make_dnsupdate_delete_all_rrsets(message_data *mesg, struct packet_writer *pw, const u8 *fqdn); ya_result message_make_dnsupdate_delete_rrset(message_data *mesg, struct packet_writer *pw, const u8 *fqdn, u16 rtype); ya_result message_make_dnsupdate_delete_record(message_data *mesg, struct packet_writer *pw, const u8 *fqdn, u16 rtype, u16 rdata_size, const u8 *rdata); ya_result message_make_dnsupdate_delete_dns_resource_record(message_data *mesg, struct packet_writer *pw, const struct dns_resource_record *rr); ya_result message_make_dnsupdate_delete_dnskey(message_data *mesg, struct packet_writer *pw, dnssec_key *key); ya_result message_make_dnsupdate_add_record(message_data *mesg, struct packet_writer *pw, const u8 *fqdn, u16 rtype, u16 rclass, s32 rttl, u16 rdata_size, const u8 *rdata); ya_result message_make_dnsupdate_add_dns_resource_record(message_data *mesg, struct packet_writer *pw, const struct dns_resource_record *rr); ya_result message_make_dnsupdate_add_dnskey(message_data *mesg, struct packet_writer *pw, dnssec_key *key, s32 ttl); ya_result message_make_dnsupdate_finalize(message_data *mesg, struct packet_writer *pw); /** * * @param mesg * @param qname * @param qtype * @param qclass * @param id */ void message_make_notify(message_data *mesg, u16 id, const u8 *qname, u16 qtype /* TYPE_SOA */, u16 qclass /* CLASS_IN */); void message_make_ixfr_query(message_data *mesg, u16 id, const u8 *qname, u32 soa_ttl, u16 soa_rdata_size, const u8 *soa_rdata); #if DNSCORE_HAS_TSIG_SUPPORT ya_result message_sign_query_by_name(message_data *mesg, const u8 *tsig_name); ya_result message_sign_query_by_name_with_epoch_and_fudge(message_data *mesg, const u8 *tsig_name, s64 epoch, u16 fudge); ya_result message_sign_query(message_data *mesg, const tsig_item *key); ya_result message_sign_query_with_epoch_and_fudge(message_data *mesg, const tsig_item *key, s64 epoch, u16 fudge); ya_result message_sign_answer(message_data *mesg); #endif /** * Creates an empty answer with an error code * * @param mesg * @param error_code */ void message_make_error(message_data *mesg, u16 error_code); /** * Creates an empty answer with an error code and TSIG signs it if needed * * @param mesg * @param error_code */ void message_make_signed_error(message_data *mesg, u16 error_code); ya_result message_make_error_and_reply_tcp(message_data *mesg, u16 error_code, int tcpfd); ssize_t message_make_error_and_reply_tcp_with_default_minimum_throughput(message_data *mesg, u16 error_code, int tcpfd); /** * Creates an answer with an OPT error code */ void message_make_error_ext(message_data *mesg, u32 error_code); static inline ya_result message_set_sender_from_host_address(message_data *mesg, const host_address *ha) { ya_result ret = host_address2sockaddr(ha, &mesg->_sender); if(ISOK(ret)) { mesg->_msghdr.msg_namelen = ret; } return ret; } static inline int message_get_sender_size(const message_data *mesg) { return mesg->_msghdr.msg_namelen; } static inline const socketaddress *message_get_sender(const message_data *mesg) { return &mesg->_sender; } static inline ya_result message_set_sender_port(message_data *mesg, u16 port) { switch(mesg->_sender.sa.sa_family) { case AF_INET: { mesg->_sender.sa4.sin_port = port; return port; } case AF_INET6: { mesg->_sender.sa6.sin6_port = port; return port; } default: { return INVALID_STATE_ERROR; } } } static inline const struct sockaddr *message_get_sender_sa(const message_data *mesg) { return &mesg->_sender.sa; } static inline sa_family_t message_get_sender_sa_family(const message_data *mesg) { return mesg->_sender.sa.sa_family; } static inline size_t message_get_sender_sa_family_size(const message_data *mesg) { switch(mesg->_sender.sa.sa_family) { case AF_INET: { return sizeof(struct sockaddr_in); } case AF_INET6: { return sizeof(struct sockaddr_in6); } default: { return 0; } } } static inline const struct sockaddr_in *message_get_sender_sa4(const message_data *mesg) { return &mesg->_sender.sa4; } static inline const struct sockaddr_in6 *message_get_sender_sa6(const message_data *mesg) { return &mesg->_sender.sa6; } static inline void message_copy_sender_from(message_data *mesg, const message_data *original) { memcpy(&mesg->_sender, &original->_sender, message_get_sender_size(original)); mesg->_msghdr.msg_name = &mesg->_sender.sa; mesg->_msghdr.msg_namelen = original->_msghdr.msg_namelen; } static inline void message_copy_sender_from_sa(message_data *mesg, const struct sockaddr *sa, socklen_t sa_len) { memcpy(&mesg->_sender, sa, sa_len); mesg->_msghdr.msg_namelen = sa_len; } static inline ya_result message_copy_sender_from_socket(message_data *mesg, int client_sockfd) { mesg->_msghdr.msg_namelen = sizeof(mesg->_sender); if(getpeername(client_sockfd, (struct sockaddr*)&mesg->_sender, &mesg->_msghdr.msg_namelen) >= 0) { mesg->_msghdr.msg_name = &mesg->_sender.sa; return SUCCESS; } else { return ERRNO_ERROR; } } static inline void message_copy_sender_to_sa(const message_data *mesg, struct sockaddr *bigenoughforipv6) { memcpy(bigenoughforipv6, message_get_sender_sa(mesg), message_get_sender_size(mesg)); } static inline u16 message_get_u16_at(const message_data *mesg, int offset) { return GET_U16_AT(mesg->_buffer[offset]); } static inline void message_send_udp_reset(message_data *mesg) { mesg->_msghdr.msg_namelen = sizeof(mesg->_sender); mesg->_iovec.iov_len = mesg->_buffer_size; } #if !DEBUG static inline s32 message_send_udp(const message_data *mesg, int sockfd) { s32 n; while((n = sendmsg(sockfd, &mesg->_msghdr, 0)) < 0) { int err = errno; if(err != EINTR) { return MAKE_ERRNO_ERROR(err); } } return n; } #else s32 message_send_udp_debug(const message_data *mesg, int sockfd); static inline s32 message_send_udp(const message_data *mesg, int sockfd) { s32 ret = message_send_udp_debug(mesg, sockfd); return ret; } #endif static inline void message_recv_udp_reset(message_data *mesg) { mesg->_msghdr.msg_namelen = sizeof(mesg->_sender); mesg->_iovec.iov_len = mesg->_buffer_size; } static inline ssize_t message_recv_udp(message_data *mesg, int sockfd) { ssize_t ret = recvmsg(sockfd, &mesg->_msghdr, 0); if(ret >= 0) { message_set_size(mesg, ret); #if __FreeBSD__ || __OpenBSD__ if(mesg->_msghdr.msg_controllen == 0) { mesg->_msghdr.msg_control = NULL; } #endif } return ret; } /* static inline ssize_t message_send_udp(message_data *mesg, int sockfd) { mesg->_iovec.iov_len = message_get_size(mesg); ssize_t ret = sendmsg(sockfd, &mesg->_msghdr, 0); return ret; } */ static inline const u8 *message_parse_query_fqdn(const message_data *mesg) { if(message_get_query_count_ne(mesg) != 0) { return &mesg->_buffer[DNS_HEADER_LENGTH]; } else { return NULL; } } static inline u16 message_parse_query_type(const message_data *mesg) { if(message_get_query_count_ne(mesg) != 0) { const u8 *fqdn = &mesg->_buffer[DNS_HEADER_LENGTH]; fqdn += dnsname_len(fqdn); return GET_U16_AT_P(fqdn); } else { return TYPE_NONE; } } static inline u16 message_parse_query_class(const message_data *mesg) { if(message_get_query_count_ne(mesg) != 0) { const u8 *fqdn = &mesg->_buffer[DNS_HEADER_LENGTH]; fqdn += (intptr)dnsname_len(fqdn) + 2; return GET_U16_AT_P(fqdn); } else { return TYPE_NONE; } } static inline const u8 *message_get_canonised_fqdn(const message_data *mesg) { return mesg->_canonised_fqdn; } static inline void message_set_canonised_fqdn(message_data *mesg, const u8 *canonised_fqdn) { dnsname_copy(mesg->_canonised_fqdn, canonised_fqdn); } static inline int message_get_maximum_size(const message_data *mesg) { return mesg->_buffer_size; } static inline u8* message_get_query_section_ptr(message_data *mesg) { return &mesg->_buffer[DNS_HEADER_LENGTH]; } static inline u8* message_get_additional_section_ptr(message_data *mesg) { return mesg->_ar_start; } static inline const u8* message_get_additional_section_ptr_const(const message_data *mesg) { return mesg->_ar_start; } static inline bool message_is_additional_section_ptr_set(const message_data *mesg) { return mesg->_ar_start != NULL; } static inline void message_set_additional_section_ptr(message_data *mesg, void *ptr) { mesg->_ar_start = (u8*)ptr; } static inline finger_print message_get_status(const message_data *mesg) { return mesg->_status; } static inline void message_set_status(message_data *mesg, finger_print fp) { mesg->_status = fp; } static inline void message_set_error_status_from_result(message_data *mesg, ya_result error_code) { finger_print fp; if(YA_ERROR_BASE(error_code) == RCODE_ERROR_BASE) { fp = RCODE_ERROR_GETCODE(error_code); } else { fp = FP_RCODE_SERVFAIL; } message_set_status(mesg, fp); } static inline void message_set_status_from_result(message_data *mesg, ya_result error_code) { finger_print fp; if(ISOK(error_code)) { fp = RCODE_NOERROR; } else if(YA_ERROR_BASE(error_code) == RCODE_ERROR_BASE) { fp = RCODE_ERROR_GETCODE(error_code); } else { fp = FP_RCODE_SERVFAIL; } message_set_status(mesg, fp); } static inline void message_clear_status(message_data *mesg) { MESSAGE_FLAGS_AND(mesg->_buffer, 0xff, 0xf0); } static inline void message_update_answer_status(message_data *mesg) { MESSAGE_FLAGS_OR(mesg->_buffer, QR_BITS, mesg->_status); } static inline void message_update_truncated_answer_status(message_data *mesg) { MESSAGE_FLAGS_OR(mesg->_buffer, QR_BITS|TC_BITS, mesg->_status); } static inline u16 message_get_id(const message_data *mesg) { return MESSAGE_ID(mesg->_buffer); } #if MESSAGE_PAYLOAD_IS_POINTER static inline ssize_t message_recv_tcp(message_data *mesg, int sockfd) { u16 tcp_len; ssize_t ret = readfully(sockfd, &tcp_len, 2); if(ret < 0) { return ret; } tcp_len = ntohs(tcp_len); if(tcp_len < message_get_maximum_size(mesg)) { ret = readfully(sockfd, mesg->_buffer, tcp_len); if(ISOK(ret)) { message_set_size(mesg, ret); } return ret; } else { return BUFFER_WOULD_OVERFLOW; } } static inline ssize_t message_write_tcp(const message_data *mesg, output_stream *os) { ssize_t ret; u16 tcp_len = htons(message_get_size_u16(mesg)); if(ISOK(ret = output_stream_write_fully(os, &tcp_len, 2))) { ret = output_stream_write_fully(os, message_get_buffer_const(mesg), message_get_size(mesg)); } return ret; } static inline ssize_t message_read_tcp(message_data *mesg, input_stream *is) { u16 tcp_len; ssize_t ret = input_stream_read_fully(is, &tcp_len, 2); if(ret < 0) { return ret; } tcp_len = ntohs(tcp_len); if(tcp_len < message_get_maximum_size(mesg)) { ret = input_stream_read_fully(is, mesg->_buffer, tcp_len); if(ISOK(ret)) { message_set_size(mesg, ret); } return ret; } else { return BUFFER_WOULD_OVERFLOW; } } #if 0 static inline ssize_t message_send_tcp(const message_data *mesg, int sockfd) { ssize_t ret; u16 tcp_len = htons(message_get_size_u16(mesg)); if(ISOK(ret = writefully(sockfd, &tcp_len, 2))) { if(ISOK(ret = writefully(sockfd, message_get_buffer_const(mesg), message_get_size(mesg)))) { ret += 2; } } return ret; } #else ssize_t message_send_tcp(const message_data *mesg, int sockfd); #endif static inline ssize_t message_send_tcp_with_minimum_throughput(const message_data *mesg, int sockfd, double minimum_rate) { ssize_t ret; u16 tcp_len = htons(message_get_size_u16(mesg)); if(ISOK(ret = writefully_limited(sockfd, &tcp_len, 2, minimum_rate))) { assert(ret == 2); if(ISOK(ret = writefully_limited(sockfd, message_get_buffer_const(mesg), message_get_size(mesg), minimum_rate))) { assert(ret == (ssize_t)message_get_size(mesg)); return ret + 2; } } return ret; } static inline ssize_t message_update_length_send_tcp_with_minimum_throughput(message_data *mesg, int sockfd, double minimum_rate) { ssize_t ret = message_send_tcp_with_minimum_throughput(mesg, sockfd, minimum_rate); return ret; } extern double g_message_data_minimum_troughput_default; static inline ssize_t message_update_length_send_tcp_with_default_minimum_throughput(message_data *mesg, int sockfd) { ssize_t ret = message_send_tcp_with_minimum_throughput(mesg, sockfd, g_message_data_minimum_troughput_default); return ret; } #else static inline void message_update_tcp_length(message_data *mesg) { u16 len = message_get_size_u16(mesg); SET_U16_AT(mesg->_buffer_tcp_len[0], htons(len)); } static inline u32 message_get_tcp_length(const message_data *mesg) { u16 len = GET_U16_AT(mesg->_buffer_tcp_len[0]); return ntohs(len); } static inline const u8 *message_get_tcp_buffer_const(const message_data *mesg) { return mesg->_buffer_tcp_len; } static inline u8 *message_get_tcp_buffer(message_data *mesg) { return mesg->_buffer_tcp_len; } static inline ssize_t message_recv_tcp(message_data *mesg, int sockfd) { ssize_t ret = readfully(sockfd, mesg->_buffer_tcp_len, 2); if(ret < 0) { return ret; } ret = message_get_tcp_length(mesg); if(ret > 0) { ret = readfully(sockfd, mesg->_buffer, ret); if(ISOK(ret)) { message_set_size(mesg, ret); } } return ret; } static inline ssize_t message_write_tcp(const message_data *mesg, output_stream *os) { message_update_tcp_length(mesg); ssize_t ret = output_stream_write(os, message_get_tcp_buffer_const(mesg), message_get_size_u16(mesg) + 2); return ret; } static inline ssize_t message_read_tcp(message_data *mesg, input_stream *is) { ssize_t ret = input_stream_read(is, mesg->_buffer_tcp_len, 2); if(ret < 0) { return ret; } ret = message_get_tcp_length(mesg); if(ret > 0) { ret = input_stream_read(is, message_get_buffer(mesg), ret); if(ISOK(ret)) { message_set_size(mesg, ret); } } return ret; } static inline ssize_t message_send_tcp(const message_data *mesg, int sockfd) { ssize_t ret = writefully(sockfd, message_get_tcp_buffer_const(mesg), message_get_size_u16(mesg) + 2); return ret; } static inline ssize_t message_send_tcp_with_minimum_throughput(const message_data *mesg, int sockfd, double minimum_rate) { ssize_t ret = writefully_limited(sockfd, message_get_tcp_buffer_const(mesg), message_get_size_u16(mesg) + 2, minimum_rate); return ret; } static inline ssize_t message_update_length_send_tcp_with_minimum_throughput(message_data *mesg, int sockfd, double minimum_rate) { message_update_tcp_length(mesg); ssize_t ret = message_send_tcp_with_minimum_throughput(mesg, sockfd, minimum_rate); return ret; } extern double g_message_data_minimum_troughput_default; static inline ssize_t message_update_length_send_tcp_with_default_minimum_throughput(message_data *mesg, int sockfd) { message_update_tcp_length(mesg); ssize_t ret = message_send_tcp_with_minimum_throughput(mesg, sockfd, g_message_data_minimum_troughput_default); return ret; } #endif static inline void message_set_id(message_data *mesg, u16 id) { MESSAGE_SET_ID(mesg->_buffer, id); } static inline void message_make_truncated_empty_answer(message_data *mesg) { message_set_truncated_answer(mesg); message_set_query_answer_authority_additional_counts_ne(mesg, 0, 0, 0, 0); message_set_size(mesg, DNS_HEADER_LENGTH); } /** * To be called on a message at the beginning of a TCP stream * * @param mesg */ static inline void message_tcp_serial_reset(message_data *mesg) { mesg->_tcp_serial = 0; } /** * To be called on a message when reading a following TCP stream message * * @param mesg */ static inline void message_tcp_serial_increment(message_data *mesg) { ++mesg->_tcp_serial; } ya_result message_query_tcp_with_timeout(message_data *mesg, const host_address *server, u8 to_sec); ya_result message_query_tcp_with_timeout_ex(message_data *mesg, const host_address *server, message_data *answer, u8 to_sec); ya_result message_query_tcp(message_data *mesg, const host_address *server); ya_result message_query_tcp_ex(message_data *mesg, const host_address *bindto, const host_address *server, message_data *answer); ya_result message_query_udp(message_data *mesg, const host_address *server); ya_result message_query_udp_with_timeout(message_data *mesg, const host_address *server, int seconds, int useconds); #define MESSAGE_QUERY_UDP_FLAG_RESET_ID 1 ya_result message_query_udp_with_timeout_and_retries(message_data *mesg, const host_address *server, int seconds, int useconds, u8 retries, u8 flags); ya_result message_query(message_data *mesg, const host_address *server); ya_result message_query_serial(const u8 *origin, const host_address *server, u32 *serial_out); ya_result message_get_ixfr_query_serial(message_data *mesg, u32 *serialp); /** * Writes the edns0 (if present), * applies the TSIG for the right position in the stream (if needed), * * Write the message to the (tcp) stream. * * @param mesg * @param tcpos * @param pos * @return */ #if ZDB_HAS_TSIG_SUPPORT ya_result message_terminate_then_write(message_data *mesg, output_stream *tcpos, tsig_tcp_message_position pos); #else ya_result message_terminate_then_write(message_data *mesg, output_stream *tcpos, int unused); #endif #if MESSAGE_PAYLOAD_IS_POINTER void message_init_ex(message_data* mesg, u32 mesg_size, void *buffer, size_t buffer_size); static inline message_data *message_data_with_buffer_init(message_data_with_buffer *mesg_buff) { message_init_ex(&mesg_buff->message, sizeof(struct message_data_with_buffer), mesg_buff->_buffer, mesg_buff->_buffer_limit - mesg_buff->_buffer); return &mesg_buff->message; } #else void message_init(message_data* mesg); static inline message_data *message_data_with_buffer_init(message_data_with_buffer *mesg_buff) { message_init(&mesg_buff->message); return &mesg_buff->message; } #endif /** * If pointer is NULL, the structure and buffer will be allocated together * Note that in the current implementation, 8 bytes are reserved for TCP */ message_data* message_new_instance_ex(void *ptr, u32 message_size); // should be size of edns0 or 64K for TCP message_data* message_new_instance(); // message_new_instance_ex(64K) void message_finalize(message_data *mesg); void message_free(message_data *mesg); /* * Does not clone the pool. */ message_data* message_dup(const message_data *mesg); ya_result message_ixfr_query_get_serial(const message_data *mesg, u32 *serial); /** * Maps records in a message to easily access them afterward. * * @param map the message map to initialise * @param mesg the message to map * * @return an error code */ ya_result message_map_init(message_map *map, const message_data *mesg); /** * Gets the fqdn of the record at index * * @param map * @param index * @param fqdn * @param fqdn_size * * @return an error code */ ya_result message_map_get_fqdn(const message_map *map, int index, u8 *fqdn, int fqdn_size); /** * Gets the type class ttl rdata_size of the record at index * * @param map * @param index * @param tctr * * @return an error code */ ya_result message_map_get_tctr(const message_map *map, int index, struct type_class_ttl_rdlen *tctr); /** * Gets the rdata of the record at index * * @param map * @param index * @param rdata * @param rdata_size * * @return the rdata size or an error code */ ya_result message_map_get_rdata(const message_map *map, int index, u8 *rdata, int rdata_size); /** * Gets the type of the record at index * * @param map * @param index * * @return the record type or an error code */ ya_result message_map_get_type(const message_map *map, int index); /** * * @param map * * @return the number of records mapped */ int message_map_record_count(const message_map *map); /** * Returns the index of the next record with the given type * from, and including, a given index. * * @param map * @param index * @param type * @return */ int message_map_get_next_record_from(const message_map *map, int index, u16 type); /** * Returns the index of the next record with the given type * from, and including, a given index in a given section (0 to 3). * * @param map * @param index * @param type * @return */ int message_map_get_next_record_from_section(const message_map *map, int section, int index, u16 type); /** * Returns the base index of a section * * @param map * @param section * @return */ static inline int message_map_get_section_base(const message_map *map, int section) { return map->section_base[section]; } /** * Sorts records by section so that: * _ SOA is first, * _ NSEC is last, * _ NSEC3 labels are at the end, * _ RRSIG follows its RRSET * * @param map */ void message_map_reorder(message_map *map); void message_map_print(const message_map *map, output_stream *os); /** * Releases the memory used by the map * * @param map */ void message_map_finalize(message_map *map); /** * Gets the global edns0 maximum size * * @return */ u16 message_edns0_getmaxsize(); static inline void message_set_rd_flag(message_data *mesg) { MESSAGE_HIFLAGS(mesg->_buffer) |= RD_BITS; } struct logger_handle; void message_log(struct logger_handle *logger, int level, const message_data *mesg); ya_result message_print_format_multiline(output_stream *os_, const u8 *buffer, u16 length, u16 view_mode_with, long time_duration); ya_result message_print_format_short(output_stream *os_, const u8 *buffer, u16 length, u16 view_mode_with, long time_duration); ya_result message_print_format_wire(output_stream *os_, const u8 *buffer, u16 length, u16 view_mode_with, long time_duration); ya_result message_print_format_wire_ext(output_stream *os_, const u8 *buffer, u16 length, u16 view_mode_with, long time_duration); ya_result message_print_format_dig(output_stream *os_, const u8 *buffer, u32 length, u16 view_mode_with, long time_duration); ya_result message_print_format_dig_buffer(output_stream *os_, const u8 *buffer, u32 length, u16 view_mode_with); ya_result message_print_format_json(output_stream *os_, const u8 *buffer, u16 length, u16 view_mode_with, long time_duration); ya_result message_print_format_json_buffer(output_stream *os_, const u8 *buffer, u16 length, u16 view_mode_with); ya_result message_print_format_parse(output_stream *os_, const u8 *buffer, u16 length, u16 view_mode_with, long time_duration); ya_result message_print_buffer_format_parse(output_stream *os_, const u8 *buffer, u16 length, u16 view_mode_with); ya_result message_print_format_xml(output_stream *os_, const u8 *buffer, u16 length, u16 view_mode_with, long time_duration); ya_result message_print_format_xml_buffer(output_stream *os_, const u8 *buffer, u16 length, u16 view_mode_with); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/message_verify_rrsig.h0000644000000000000000000000013214505005532026210 xustar000000000000000030 mtime=1695812442.034976344 30 atime=1695812445.788030096 30 ctime=1695812494.298724867 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/message_verify_rrsig.h0000664000374500037450000001066214505005532026157 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #ifndef __MESSAGE_VERIFY_H__ #define __MESSAGE_VERIFY_H__ #include #include #define MESSAGE_VERIFY_RRSIG_NOTSIGNED 1 #define MESSAGE_VERIFY_RRSIG_WRONG 2 #define MESSAGE_VERIFY_RRSIG_VERIFIED 4 #define MESSAGE_VERIFY_RRSIG_TIMEFRAME 8 #define MESSAGE_VERIFY_RRSIG_NOKEY 16 // CANNOT BE BIGGER THAN 32 BITS struct message_verify_rrsig_type_summary_s { u8 verifiable_count; // verified + wrong u8 unverifiable_count; // unknown key u8 verified_count; u8 wrong_count; }; typedef struct message_verify_rrsig_type_summary_s message_verify_rrsig_type_summary_s; struct message_verify_rrsig_detail_s { // this part MUST match the 18 bytes of wire image of an RRSIG u16 type_covered; u8 algorithm; u8 labels; u32 original_ttl; u32 expiration; u32 inception; // 16 bytes u16 tag; // 18 // u16 signature_size; // 20 u8 result; // 21 u8 section; // 22 // 23 24 are currently lost to memory alignment const u8 *signer_name; const u8 *signature; const u8 *fqdn; }; typedef struct message_verify_rrsig_detail_s message_verify_rrsig_detail_s; #define MESSAGE_VERIFY_RRSIG_RESULT_TYPE_SUMMARY 0 #define MESSAGE_VERIFY_RRSIG_RESULT_TYPE_VERIFY 1 #define MESSAGE_VERIFY_RRSIG_FEEDBACK_CONTINUE 0 #define MESSAGE_VERIFY_RRSIG_FEEDBACK_STOP 1 #define MESSAGE_VERIFY_RRSIG_FEEDBACK_ERROR 2 struct message_verify_rrsig_result_s { union { message_verify_rrsig_type_summary_s *summary; message_verify_rrsig_detail_s *detail; void *any; } data; u8 result_type; u8 section; u16 ctype; }; typedef struct message_verify_rrsig_result_s message_verify_rrsig_result_s; void message_verify_rrsig_format_handler(const void *result_u8_ptr, output_stream *os, s32, char, bool, void* reserved_for_method_parameters); /** * The feedback function is called while the message signature are verified. * It can return a feedback to continue or stop processing, or to give an error * to the original caller. * * MESSAGE_VERIFY_RRSIG_FEEDBACK_CONTINUE * MESSAGE_VERIFY_RRSIG_FEEDBACK_STOP * MESSAGE_VERIFY_RRSIG_FEEDBACK_ERROR * */ typedef ya_result message_verify_rrsig_result(const message_data *mesg, const struct dnskey_keyring *keyring, const message_verify_rrsig_result_s *result, void *args); ya_result message_verify_rrsig(const message_data *mesg, struct dnskey_keyring *keyring, message_verify_rrsig_result *feedback, void *args); #endif // __MESSAGE_VERIFY_H__ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/message_dnsupdate.h0000644000000000000000000000013014505005531025462 xustar000000000000000029 mtime=1695812441.78397275 30 atime=1695812445.786030067 29 ctime=1695812494.30172491 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/message_dnsupdate.h0000664000374500037450000000542514505005531025434 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef MESSAGE_DNSUPDATE_H_ #define MESSAGE_DNSUPDATE_H_ #ifdef __cplusplus extern "C" { #endif #if 1 #include #include #include #include #include #include #include #include #include #include #include #include #include void message_dnsupdate_data_append_message_dnsupdate_data(message_dnsupdate_data *entry, message_dnsupdate_data *new_entry); void message_dnsupdate_data_create(message_dnsupdate_data* entry, u32 zttl, u16 ztype, u16 zclass, const u8 *zname, u16 zrdata_len, char *zrdata); #endif #ifdef __cplusplus } #endif #endif /* MESSAGE_DNSUPDATE_H_ */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/mt_output_stream.h0000644000000000000000000000013214505005531025404 xustar000000000000000030 mtime=1695812441.986975657 30 atime=1695812445.786030067 30 ctime=1695812494.303724938 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/mt_output_stream.h0000664000374500037450000000523614505005531025354 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _MT_OUTPUT_STREAM_H #define _MT_OUTPUT_STREAM_H #include #include #ifdef __cplusplus extern "C" { #endif /** * Can only fail if in_filtered has not been set */ ya_result mt_output_stream_init(output_stream *out_stream, output_stream *in_filtered); output_stream *mt_output_stream_get_filtered(output_stream *bos); void mt_output_stream_detach_filtered(output_stream *bos, output_stream *detached_filtered); void mt_output_stream_set_filtered(output_stream *bos, output_stream *new_os, bool also_close); bool is_mt_output_stream(const output_stream *bos); #ifdef __cplusplus } #endif #endif /* _MT_OUTPUT_STREAM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/mutex.h0000644000000000000000000000013214505005532023134 xustar000000000000000030 mtime=1695812442.018976115 30 atime=1695812445.787030082 30 ctime=1695812494.305724967 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/mutex.h0000664000374500037450000004522314505005532023104 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once /** * This helper header allows to chose the kind of mutex used. * This is part of the sendto queue experiment. */ #include #include #include #define SEMAPHORE_SUPPORT 0 #if SEMAPHORE_SUPPORT #include #endif #include #include #if defined(__MACH__) #include #endif #ifdef __cplusplus extern "C" { #endif #ifndef DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #error "DNSCORE_HAS_MUTEX_DEBUG_SUPPORT must be set to either 0 or 1" #endif #ifndef MUTEX_USE_SPINLOCK #define MUTEX_USE_SPINLOCK 0 // keep it that way #endif #if MUTEX_USE_SPINLOCK && DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #error "Cannot mix spinlock and mutex debug support" #endif // these two are for error reporting in debug builds #define MUTEX_LOCKED_TOO_MUCH_TIME_US 5000000 #define MUTEX_WAITED_TOO_MUCH_TIME_US 2000000 typedef pthread_cond_t cond_t; #define COND_INITIALIZER PTHREAD_COND_INITIALIZER // DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if !MUTEX_USE_SPINLOCK // do not use SPINLOCK #if !DNSCORE_HAS_MUTEX_DEBUG_SUPPORT typedef pthread_mutex_t mutex_t; #define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER static inline int mutex_lock_unchecked(mutex_t* mtx) { int ret = pthread_mutex_lock(mtx); return ret; } static inline int mutex_unlock_unchecked(mutex_t* mtx) { int ret = pthread_mutex_unlock(mtx); return ret; } #if !DEBUG #define mutex_lock(mtx__) pthread_mutex_lock(mtx__) #define mutex_trylock(mtx__) (pthread_mutex_trylock(mtx__)==0) #define mutex_unlock(mtx__) pthread_mutex_unlock(mtx__) #else static inline void mutex_lock(mutex_t* mtx) { int ret = pthread_mutex_lock(mtx); if(ret != 0) { abort(); } } static inline bool mutex_trylock(mutex_t* mtx) { int ret = pthread_mutex_trylock(mtx); if((ret != 0) && (ret != EBUSY)) { abort(); } return ret == 0; } static inline void mutex_unlock(mutex_t* mtx) { int ret = pthread_mutex_unlock(mtx); if(ret != 0) { abort(); } } #if SEMAPHORE_SUPPORT typedef sem_t semaphore_t; static inline int semaphone_init(semaphore_t *sem) { int ret = sem_init(sem, 0, 0); return ret; } static inline int semaphone_init_process_shared(semaphore_t *sem) { int ret = sem_init(sem, 1, 1); return ret; } static inline void semaphore_finalize(semaphore_t *sem) { sem_destroy(sem); } static inline void semaphore_lock(semaphore_t *sem) { for(;;) { if(sem_wait(sem) == 0) { return; } int err = errno; if(err != EINTR) { abort(); } } } static inline bool semaphore_trylock(semaphore_t *sem) { int ret = sem_trywait(sem); // fails if return ret == 0; } static inline void semaphore_unlock(semaphore_t *sem) { sem_post(sem); } #endif #endif #else // #if !DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #define MUTEX_CONTENTION_MONITOR 0 #if MUTEX_CONTENTION_MONITOR #pragma message("***********************************************************") #pragma message("***********************************************************") #pragma message("MUTEX_CONTENTION_MONITOR 1") #pragma message("***********************************************************") #pragma message("***********************************************************") #endif #if MUTEX_CONTENTION_MONITOR struct mutex_contention_monitor_s; void mutex_contention_object_create(void *mutex_ptr, bool recursive); void mutex_contention_object_destroy(void *mutex_ptr); struct mutex_contention_monitor_s * mutex_contention_lock_begin(thread_t thread, void *mutex_ptr, stacktrace st, const char *type_name); void mutex_contention_lock_wait(struct mutex_contention_monitor_s *mcm); void mutex_contention_lock_wait_with_mutex(thread_t thread, void *mutex_ptr); void mutex_contention_lock_resume(struct mutex_contention_monitor_s *mcm); void mutex_contention_lock_resume_with_mutex(thread_t thread, void *mutex_ptr); void mutex_contention_lock_end(struct mutex_contention_monitor_s *mcm); void mutex_contention_lock_fail(struct mutex_contention_monitor_s *mcm); void mutex_contention_unlock(thread_t thread, void *mutex_ptr); void mutex_contention_unlock_with_monitor(struct mutex_contention_monitor_s *mcm); void mutex_contention_monitor_start(); void mutex_contention_monitor_stop(); #endif typedef pthread_mutex_t mutex_t; #define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER void mutex_lock(mutex_t *mtx); bool mutex_trylock(mutex_t *mtx); void mutex_unlock(mutex_t *mtx); int mutex_lock_unchecked(mutex_t* mtx); int mutex_unlock_unchecked(mutex_t* mtx); #ifdef UNDEF_MSG_ERR #undef MSG_ERR #undef UNDEF_MSG_ERR #endif #endif // DNSCORE_HAS_MUTEX_DEBUG_SUPPORT void mutex_init_recursive(mutex_t *mtx); int mutex_init_process_shared(mutex_t *mtx); void mutex_init(mutex_t *mtx); void mutex_destroy(mutex_t *mtx); /** * Wrapper for mutex_destroy, with a more appropriate name. */ static inline void mutex_finalize(mutex_t *mtx) { mutex_destroy(mtx); } #if __APPLE__ typedef mutex_t spinlock_t; static inline void spinlock_init(spinlock_t *spin) { mutex_init(spin); } static inline void spinlock_destroy(spinlock_t *spin) { mutex_destroy(spin); } static inline void spinlock_lock(spinlock_t *spin) { mutex_lock(spin); } static inline void spinlock_unlock(spinlock_t *spin) { mutex_unlock(spin); } #else typedef pthread_spinlock_t spinlock_t; static inline void spinlock_init(spinlock_t *spin) { pthread_spin_init(spin, 0); } static inline void spinlock_destroy(spinlock_t *spin) { pthread_spin_destroy(spin); } static inline void spinlock_lock(spinlock_t *spin) { pthread_spin_lock(spin); } static inline void spinlock_unlock(spinlock_t *spin) { pthread_spin_unlock(spin); } #endif static inline void cond_wait(cond_t *cond, mutex_t *mtx) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_wait_with_mutex(thread_self(), mtx); #endif #endif int ret = pthread_cond_wait(cond, mtx); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_resume_with_mutex(thread_self(), mtx); #endif #endif if(ret != 0) { perror("cond_wait"); fflush(stderr); } } extern struct timespec __alarm__approximate_time_10s; static inline void cond_wait_auto_time_out(cond_t *cond, mutex_t *mtx) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_wait_with_mutex(thread_self(), mtx); #endif #endif int ret = pthread_cond_timedwait(cond, mtx, &__alarm__approximate_time_10s); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_resume_with_mutex(thread_self(), mtx); #endif #endif #if __unix__ if(ret != 0) { #if DEBUG fprintf(stderr, "cond_wait_auto_time_out: %s\n", strerror(ret)); fflush(stderr); #endif time_t now = time(NULL); __alarm__approximate_time_10s.tv_sec = now + 10; } #endif } #else typedef pthread_spinlock_t mutex_t; #define MUTEX_INITIALIZER 0 #define mutex_init(mtx) pthread_spin_init((mtx), 0) #define mutex_destroy(mtx) pthread_spin_destroy(mtx) #define mutex_lock(mtx) pthread_spin_lock(mtx) #define mutex_trylock(mtx) (pthread_spin_trylock(mtx)==0) #define mutex_unlock(mtx) pthread_spin_unlock(mtx) static inline void cond_wait(cond_t *cond, mutex_t *mtx) { pthread_cond_wait(cond, mtx); } #endif int cond_init_process_shared(cond_t *cond); static inline void cond_init(cond_t *cond) { pthread_cond_init(cond, NULL); } #if !_POSIX_TIMERS #ifndef _TIMEMS_H u64 timeus(); #endif #endif static inline int cond_timedwait(cond_t *cond, mutex_t *mtx, u64 usec) { struct timespec ts; #if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)) || defined(__MACH__) clock_gettime(CLOCK_REALTIME, &ts); usec *= 1000; ts.tv_nsec += usec; if(ts.tv_nsec > 1000000000LL) { ts.tv_sec += ts.tv_nsec / 1000000000LL; ts.tv_nsec = ts.tv_nsec % 1000000000LL; } #else usec += timeus(); usec *= 1000ULL; ts.tv_nsec = usec % 1000000000LL; ts.tv_sec = usec / 1000000000LL; #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_wait_with_mutex(thread_self(), mtx); #endif #endif int ret = pthread_cond_timedwait(cond, mtx, &ts); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_resume_with_mutex(thread_self(), mtx); #endif #endif return ret; } static inline int cond_timedwait_absolute(cond_t *cond, mutex_t *mtx, u64 usec_epoch) { struct timespec ts; ts.tv_sec = usec_epoch / ONE_SECOND_US; ts.tv_nsec = (usec_epoch % ONE_SECOND_US) * 1000LL; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_wait_with_mutex(thread_self(), mtx); #endif #endif int ret = pthread_cond_timedwait(cond, mtx, &ts); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_resume_with_mutex(thread_self(), mtx); #endif #endif return ret; } static inline int cond_timedwait_absolute_ts(cond_t *cond, mutex_t *mtx, struct timespec *ts) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_wait_with_mutex(thread_self(), mtx); #endif #endif int ret = pthread_cond_timedwait(cond, mtx, ts); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_resume_with_mutex(thread_self(), mtx); #endif #endif return ret; } // Only use this if there is only one possible thread waiting on // the condition. static inline void cond_notify_one(cond_t *cond) { pthread_cond_signal(cond); } static inline void cond_notify(cond_t *cond) { pthread_cond_broadcast(cond); } static inline void cond_finalize(cond_t *cond) { for(;;) { int ret = pthread_cond_destroy(cond); if(ret == 0) { break; } if(ret != EBUSY) { //osformat(termerr, "async_wait_finalize: pthread_cond_destroy returned another error than EBUSY: %r", MAKE_ERRNO_ERROR(ret)); //flusherr(); break; } usleep(5000); } } struct smp_int { pthread_mutex_t mutex; volatile int value; }; #define SMP_INT_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0} #define SMP_INT_INITIALIZER_AT(value_) {PTHREAD_MUTEX_INITIALIZER, (value_)} typedef struct smp_int smp_int; static inline void smp_int_init(smp_int *v) { pthread_mutex_init(&v->mutex, NULL); v->value = 0; } static inline void smp_int_init_set(smp_int *v, int value) { pthread_mutex_init(&v->mutex, NULL); v->value = value; } static inline void smp_int_set(smp_int *v, int i) { pthread_mutex_lock(&v->mutex); v->value = i; pthread_mutex_unlock(&v->mutex); } static inline void smp_int_inc(smp_int *v) { pthread_mutex_lock(&v->mutex); v->value++; pthread_mutex_unlock(&v->mutex); } static inline void smp_int_add(smp_int *v, int value) { pthread_mutex_lock(&v->mutex); v->value += value; pthread_mutex_unlock(&v->mutex); } static inline void smp_int_or(smp_int *v, int value) { pthread_mutex_lock(&v->mutex); v->value |= value; pthread_mutex_unlock(&v->mutex); } static inline void smp_int_and(smp_int *v, int value) { pthread_mutex_lock(&v->mutex); v->value &= value; pthread_mutex_unlock(&v->mutex); } static inline int smp_int_inc_get(smp_int *v) { u32 ret; pthread_mutex_lock(&v->mutex); ret = ++v->value; pthread_mutex_unlock(&v->mutex); return ret; } static inline void smp_int_dec(smp_int *v) { pthread_mutex_lock(&v->mutex); v->value--; pthread_mutex_unlock(&v->mutex); } static inline void smp_int_sub(smp_int *v, int value) { pthread_mutex_lock(&v->mutex); v->value -= value; pthread_mutex_unlock(&v->mutex); } static inline int smp_int_dec_get(smp_int *v) { int ret; pthread_mutex_lock(&v->mutex); ret = --v->value; pthread_mutex_unlock(&v->mutex); return ret; } static inline int smp_int_get_dec(smp_int *v) { int ret; pthread_mutex_lock(&v->mutex); ret = v->value--; pthread_mutex_unlock(&v->mutex); return ret; } static inline bool smp_int_setifequal(smp_int *v, int from, int to) { bool didit = FALSE; pthread_mutex_lock(&v->mutex); if(v->value == from) { v->value = to; didit = TRUE; } pthread_mutex_unlock(&v->mutex); return didit; } static inline int smp_int_get(smp_int *v) { int ret; pthread_mutex_lock(&v->mutex); ret = v->value; pthread_mutex_unlock(&v->mutex); return ret; } static inline int smp_int_get_set(smp_int *v, int newvalue) { int ret; pthread_mutex_lock(&v->mutex); ret = v->value; v->value = newvalue; pthread_mutex_unlock(&v->mutex); return ret; } static inline void smp_int_destroy(smp_int *v) { pthread_mutex_destroy(&v->mutex); } /** * A group mutex is a mutex that can be used by a group with or without exclusive access. * A mutex is private if the msb is set, it means only one of that group can own it * A mutex is shared if the msb is not set, it means many owner of the same type can own it */ #define GROUP_MUTEX_NOBODY 0x00 #define GROUP_MUTEX_READ 0x01 // default #define GROUP_MUTEX_WRITE 0x82 // default #define GROUP_MUTEX_PRIVATE 0x80 // THIS IS A MASK, ADD IT TO THE OWNER ID #define GROUP_MUTEX_DESTROY 0xfe #define GROUP_MUTEX_LOCKMASK_FLAG 0x7f #define GROUP_MUTEX_EXCLUSIVE_FLAG 0x80 typedef struct group_mutex_t group_mutex_t; struct group_mutex_t { cond_t cond; mutex_t mutex; volatile s32 count; volatile u8 owner; volatile u8 reserved_owner; }; #define GROUP_MUTEX_INITIALIZER {COND_INITIALIZER, MUTEX_INITIALIZER, 0, 0, 0} void group_mutex_init(group_mutex_t* mtx); void group_mutex_lock(group_mutex_t *mtx, u8 owner); bool group_mutex_trylock(group_mutex_t *mtx, u8 owner); void group_mutex_unlock(group_mutex_t *mtx, u8 owner); bool group_mutex_transferlock(group_mutex_t *mtx, u8 owner, u8 newowner); void group_mutex_destroy(group_mutex_t* mtx); bool group_mutex_islocked(group_mutex_t* mtx); void group_mutex_double_lock(group_mutex_t *mtx, u8 owner, u8 secondary_owner); void group_mutex_double_unlock(group_mutex_t *mtx, u8 owner, u8 secondary_owner); void group_mutex_exchange_locks(group_mutex_t *mtx, u8 owner, u8 secondary_owner); static inline void group_mutex_read_lock(group_mutex_t *mtx) { group_mutex_lock(mtx, GROUP_MUTEX_READ); } static inline void group_mutex_read_unlock(group_mutex_t *mtx) { group_mutex_unlock(mtx, GROUP_MUTEX_READ); } static inline void group_mutex_write_lock(group_mutex_t *mtx) { group_mutex_lock(mtx, GROUP_MUTEX_WRITE); } static inline void group_mutex_write_unlock(group_mutex_t *mtx) { group_mutex_unlock(mtx, GROUP_MUTEX_WRITE); } /** * The shared group mutex is a group mutex that only uses N mutex(es) and N condition(s). * This is especially useful when millions of instances are required. * The mutex is used commonly by each structure as its own. * The downside is that every waiting task on the same mutex will be woken up each time one of them broadcasts the condition. * * The current implementation uses N=1 */ struct shared_group_shared_mutex_t { mutex_t mutex; cond_t cond; volatile s32 rc; }; typedef struct shared_group_shared_mutex_t shared_group_shared_mutex_t; #define SHARED_GROUP_SHARED_MUTEX_INTIALIZER {MUTEX_INITIALIZER, COND_INITIALIZER, 0} struct shared_group_mutex_t { shared_group_shared_mutex_t *shared_mutex; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR struct mutex_contention_monitor_s *mcm; #else stacktrace trace; volatile thread_t id; volatile u64 timestamp; #endif #endif volatile s32 count; volatile u8 owner; }; #define SHARED_GROUP_MUTEX_INTIALIZER THIS_CANNOT_WORK typedef struct shared_group_mutex_t shared_group_mutex_t; void shared_group_shared_mutex_init(shared_group_shared_mutex_t* smtx); void shared_group_shared_mutex_init_recursive(shared_group_shared_mutex_t* smtx); void shared_group_shared_mutex_destroy(shared_group_shared_mutex_t* smtx); void shared_group_mutex_init(shared_group_mutex_t* mtx, shared_group_shared_mutex_t* smtx, const char *name); void shared_group_mutex_lock(shared_group_mutex_t *mtx, u8 owner); bool shared_group_mutex_trylock(shared_group_mutex_t *mtx, u8 owner); void shared_group_mutex_unlock(shared_group_mutex_t *mtx, u8 owner); bool shared_group_mutex_transferlock(shared_group_mutex_t *mtx, u8 owner, u8 newowner); void shared_group_mutex_destroy(shared_group_mutex_t* mtx); bool shared_group_mutex_islocked(shared_group_mutex_t* mtx); bool shared_group_mutex_islocked_by(shared_group_mutex_t *mtx, u8 owner); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/network.h0000644000000000000000000000013014505005531023460 xustar000000000000000028 mtime=1695812441.9969758 30 atime=1695812445.787030082 30 ctime=1695812494.307724996 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/network.h0000664000374500037450000001243514505005531023431 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup network Network functions * @ingroup dnscore * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef NETWORK_H #define NETWORK_H #include /* Required for BSD */ #include #include #include #include #include #define SOCKADD4_TAG 0x344444414b434f53 #define SOCKADD6_TAG 0x364444414b434f53 /* * In order to avoid casting, this is the type that should be used to store sockaddr */ typedef union socketaddress socketaddress; union socketaddress { /// @note 20200629 edf -- In order to avoid a potential issue with the sockaddr structure in FreeBSD and possibly other OSes, I've removed the ss_* fields. // Every access must be done through "sa". struct sockaddr sa; struct sockaddr_in sa4; struct sockaddr_in6 sa6; struct sockaddr_storage ss; }; // minimal storage for IPv4 & IPv6 union socketaddress_46 { struct sockaddr sa; struct sockaddr_in sa4; struct sockaddr_in6 sa6; }; static inline bool sockaddr_equals(const struct sockaddr *a, const struct sockaddr *b) { if(a->sa_family == b->sa_family) { switch (a->sa_family) { case AF_INET: { const struct sockaddr_in *sa4 = (const struct sockaddr_in *)a; const struct sockaddr_in *sb4 = (const struct sockaddr_in *)b; return memcmp(&sa4->sin_addr.s_addr, &sb4->sin_addr.s_addr, 4) == 0; } case AF_INET6: { const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *)a; const struct sockaddr_in6 *sb6 = (const struct sockaddr_in6 *)b; return memcmp(&sa6->sin6_addr, &sb6->sin6_addr, 16) == 0; } } } return FALSE; } int sockaddr_compare_addr_port(const struct sockaddr *a, const struct sockaddr *b); int socketaddress_compare_ip(const void *a, const void *b); int sockaddr_storage_compare_ip(const void *key_a, const void *key_b); void sockaddr_storage_copy(struct sockaddr_storage *dest, const struct sockaddr_storage *src); static inline u16 sockaddr_port_ne(socketaddress *sa) { switch(sa->sa.sa_family) { case AF_INET: { return sa->sa4.sin_port; } case AF_INET6: { return sa->sa6.sin6_port; } default: { return 0; } } } static inline u16 sockaddr_port(socketaddress *sa) { return ntohs(sockaddr_port_ne(sa)); } static inline s32 sockaddr_inet_port(const struct sockaddr* sa) { switch(sa->sa_family) { case AF_INET: { struct sockaddr_in *ipv4 = (struct sockaddr_in*)sa; return (u32)ipv4->sin_port; } case AF_INET6: { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6*)sa; return (u32)ipv6->sin6_port; } default: { return ERROR; } } } /** * Tool function to tell if a (listening) address is ANY */ bool addr_info_is_any(struct addrinfo* addr); /** * Enumerates all network interfaces. */ typedef ya_result (network_interfaces_forall_callback)(const char* itf_name, const socketaddress* ss, void* data); ya_result network_interfaces_forall(network_interfaces_forall_callback *cb, void *data); #endif /* HOST_ADDRESS_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/nsec3-hash.h0000644000000000000000000000013114505005532023725 xustar000000000000000030 mtime=1695812442.060976717 29 atime=1695812445.78903011 30 ctime=1695812494.309725024 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/nsec3-hash.h0000664000374500037450000000614614505005532023677 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * The low level digest functions * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif /** * Hashing function signature */ typedef ya_result nsec3_hash_function(const u8*, u32, const u8*, u32, u32, u8*, bool); /** * * Returns the (NSEC3) hashing function for an algorithm * * If the algorithm is not supported, the returned function will * always return DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM. * * A typical usage for this is : * * get_nsec3_hash_function(NSEC3_ZONE_ALGORITHM(n3))(name, ...... ) * |_______________________________________________||_____________| * Get the digest function pointer Call the returned function * * @param algorithm the algorithm id * @return the hashing function * * 8 uses */ nsec3_hash_function* nsec3_hash_get_function(u8 algorithm); /** * Returns the size in bytes of the hash computed by hashing function algorithm * * @param algorithm the algorithm id * @return size in bytes of the computed hash or 0 if the function is not supported * * 10 uses */ u8 nsec3_hash_len(u8 algorithm); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/openssl.h0000644000000000000000000000013214505005532023455 xustar000000000000000030 mtime=1695812442.036976373 30 atime=1695812445.788030096 30 ctime=1695812494.311725053 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/openssl.h0000664000374500037450000000624614505005532023427 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup dnscore * @brief * * @{ */ #pragma once #include #define SSL_TOSTRING(s) TOSTRING_(s) #define SSL_TOSTRING_(s) #s #if LIBRESSL_VERSION_NUMBER // Cannot trust LIBRESSL's OPENSSL_VERSION_NUMBER value #define SSL_API 1 #if (LIBRESSL_VERSION_NUMBER >= 0x20000000L) && (LIBRESSL_VERSION_NUMBER < 0x40000000L) //#pragma message "LIBRESSL [v2; v4[" #define SSL_API_LT_111 1 #define SSL_API_LT_110 0 #define SSL_API_LT_100 0 #else #pragma message("Unsupported LibreSSL version " SSL_TOSTRING(LIBRESSL_VERSION_NUMBER)) #error "Unsupported LibreSSL version" #endif #elif OPENSSL_VERSION_NUMBER #define SSL_API 1 // warning: this use of "defined" may not be portable [-Wexpansion-to-defined] // // #define SSL_API_LT_110 ((OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)) // // hence: // #if OPENSSL_VERSION_NUMBER < 0x10101000L #define SSL_API_LT_111 1 #endif #if OPENSSL_VERSION_NUMBER < 0x10100000L #define SSL_API_LT_110 1 #else #define SSL_API_LT_110 0 #endif #if OPENSSL_VERSION_MAJOR >= 3 #define SSL_API_LT_300 0 #define SSL_API_GE_300 1 #else #define SSL_API_LT_300 1 #define SSL_API_GE_300 0 #endif #define SSL_API_LT_100 (OPENSSL_VERSION_NUMBER < 0x10000000L) #else #define SSL_API 0 #endif #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/output_stream.h0000644000000000000000000000013214505005531024704 xustar000000000000000030 mtime=1695812441.985975643 30 atime=1695812445.786030067 30 ctime=1695812494.313725082 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/output_stream.h0000664000374500037450000001436414505005531024656 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @ingroup dnscore * */ /*----------------------------------------------------------------------------*/ #ifndef _OUTPUT_STREAM_H #define _OUTPUT_STREAM_H #include #include #ifdef __cplusplus extern "C" { #endif typedef struct output_stream output_stream; typedef ya_result output_stream_write_method(output_stream* stream, const u8* buffer, u32 len); typedef ya_result output_stream_flush_method(output_stream* stream); typedef void output_stream_close_method(output_stream* stream); typedef ya_result output_stream_skip_method(output_stream* stream, u32 byte_count); typedef struct output_stream_vtbl output_stream_vtbl; struct output_stream_vtbl { output_stream_write_method* write; output_stream_flush_method* flush; output_stream_close_method* close; const char* __class__; /* MUST BE A UNIQUE POINTER, ie: One defined in the class's .c file The name should be unique in order to avoid compiler tricks */ /* Add your inheritable methods here */ }; struct output_stream { void* data; const output_stream_vtbl* vtbl; }; #define output_stream_class(os__) ((os__)->vtbl) #define output_stream_class_name(os__) ((os__)->vtbl->__class__) #define output_stream_write(os__,buffer__,len__) (os__)->vtbl->write((os__),(const u8*)(buffer__),(len__)) #define output_stream_flush(os__) (os__)->vtbl->flush(os__) #define output_stream_close(os__) (os__)->vtbl->close(os__) #define output_stream_skip(os__,len__) (os__)->vtbl->skip((os__),(len__)) #define output_stream_valid(os__) ((os__)->vtbl != NULL) ya_result output_stream_write_nu32(output_stream* os, u32 value); ya_result output_stream_write_nu16(output_stream* os, u16 value); /* * ya_result output_stream_write_u8(output_stream* os, u8 value); */ static inline ya_result output_stream_write_u8(output_stream* os, u8 value) { return output_stream_write(os, &value, 1); } static inline ya_result output_stream_write_u16(output_stream* os, u16 value) { return output_stream_write(os, (u8*) & value, 2); } static inline ya_result output_stream_write_u32(output_stream* os, u32 value) { return output_stream_write(os, (u8*) & value, 4); } /* * PACKED unsigned 32 bits * * The integer is divided into 7 bits packets (lsb -> msb) * The 8th bit is set until the end is reached * * [ 0.. 127] => [ 0x00 .. 0x7f] * [128..16384] => [0x80 0x01 .. 0xff 0x7f] * */ ya_result output_stream_write_pu16(output_stream* os, u16 value); ya_result output_stream_write_pu32(output_stream* os, u32 value); ya_result output_stream_write_pu64(output_stream* os, u64 value); // wire ya_result output_stream_write_dnsname(output_stream* os, const u8* name); // ascii ya_result output_stream_write_dnsname_text(output_stream* os, const u8 *name); ya_result output_stream_write_dnslabel_text_escaped(output_stream* os, const u8 *label); ya_result output_stream_write_dnsname_text_escaped(output_stream* os, const u8 *name); ya_result output_stream_write_dnslabel_vector(output_stream* os, dnslabel_vector_reference labels, s32 top); ya_result output_stream_write_dnslabel_stack(output_stream* os, dnslabel_stack_reference labels, s32 top); ya_result output_stream_decode_base64(output_stream* os, const char * string, u32 length); ya_result output_stream_decode_base32(output_stream* os, const char * string, u32 length); ya_result output_stream_decode_base32hex(output_stream* os, const char * string, u32 length); ya_result output_stream_decode_base16(output_stream* os, const char * string, u32 length); /** * Note: the typebitmap.h file declares a type_bit_maps_output_stream_write function */ output_stream *output_stream_alloc(); /** * This tools allows a safer misuse (and detection) of closed streams * It sets the stream to a sink that warns abouts its usage and for which every call that can fail fails. */ void output_stream_set_void(output_stream *stream); /** * Used to temporarily initialise a stream with a sink that can be closed safely. * Typically used as pre-init so the stream can be closed even if the function * setup failed before reaching stream initialisation. * * @param os */ void output_stream_set_sink(output_stream *os); ya_result output_stream_write_fully(output_stream *stream, const void *buffer_start, u32 len_start); #ifdef __cplusplus } #endif #endif /* _OUTPUT_STREAM_H */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/pace.h0000644000000000000000000000013114505005532022701 xustar000000000000000030 mtime=1695812442.085977075 30 atime=1695812445.790030125 29 ctime=1695812494.31572511 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/pace.h0000664000374500037450000000455014505005532022650 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #ifndef PACE_H #define PACE_H #include struct pace_s { u64 min_us; u64 max_us; u64 current_us; u64 counter; u64 wait_start; u64 wait_end; const char *name; }; typedef struct pace_s pace_s; /** * initialises the pace * * @param pace */ void pace_init(pace_s *pace, u64 min_us, u64 max_us, const char* name); /** * Will pause for a while */ void pace_wait(pace_s *pace); /** * Will update the pace taking the fact that now we have work to do */ void pace_work(pace_s *pace); #endif yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/packet_reader.h0000644000000000000000000000013214505005531024562 xustar000000000000000030 mtime=1695812441.997975815 30 atime=1695812445.787030082 30 ctime=1695812494.317725139 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/packet_reader.h0000664000374500037450000001760614505005531024536 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnspacket DNS Messages * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _PACKET_READER_H #define _PACKET_READER_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* dynupdate */ /* reads and unpack */ typedef struct packet_unpack_reader_data packet_unpack_reader_data; struct packet_unpack_reader_data { const u8* packet; u32 packet_size; u32 offset; }; static inline void packet_reader_init_at(packet_unpack_reader_data* reader, const u8* buffer, u32 buffer_size, u32 position) { reader->packet = buffer; reader->packet_size = buffer_size; reader->offset = position; } static inline void packet_reader_init(packet_unpack_reader_data* reader, const u8* buffer, u32 buffer_size) { packet_reader_init_at(reader, buffer, buffer_size, 0); } static inline void packet_reader_init_from_message_at(packet_unpack_reader_data* reader, const message_data *mesg, u32 position) { packet_reader_init_at(reader, message_get_buffer_const(mesg), message_get_size(mesg), position); } static inline void packet_reader_init_from_message(packet_unpack_reader_data* reader, const message_data *mesg) { packet_reader_init_from_message_at(reader, mesg, DNS_HEADER_LENGTH); } static inline ya_result packet_reader_opcode(packet_unpack_reader_data* reader) { if(reader->packet_size >= DNS_HEADER_LENGTH) { return MESSAGE_OP(reader->packet) >> OPCODE_SHIFT; } else { return UNEXPECTED_EOF; } } static inline bool packet_reader_eof(packet_unpack_reader_data* reader) { return reader->offset >= reader->packet_size; } /* fqdn + type + class */ ya_result packet_reader_read_zone_record(packet_unpack_reader_data* reader, u8* output_buffer, u32 len); ya_result packet_reader_skip_zone_record(packet_unpack_reader_data* reader); ya_result packet_reader_skip_query_section(packet_unpack_reader_data* reader); ya_result packet_reader_skip_section(packet_unpack_reader_data* reader, int section); /* fqdn + type + class + ttl + size + rdata */ ya_result packet_reader_read_record(packet_unpack_reader_data* reader, u8 *output_buffer, u32 len); ya_result packet_reader_read_dns_resource_record(packet_unpack_reader_data* reader, dns_resource_record *rr); /** * Note that the last parameter is the buffer size and the data size to be read is right after the type. */ ya_result packet_reader_read_rdata(packet_unpack_reader_data* reader, u16 type, s32 rdata_size, u8 *buffer, s32 buffer_size); ya_result packet_reader_read_fqdn(packet_unpack_reader_data* reader, u8 *output_buffer, u32 len); ya_result packet_reader_read(packet_unpack_reader_data* reader, void *output_buffer, u32 len); static inline void packet_reader_read_unchecked(packet_unpack_reader_data* reader, void *output_buffer, u32 len) { MEMCOPY(output_buffer, &reader->packet[reader->offset], len); reader->offset += len; } static inline const void *packet_reader_get_current_ptr_const(const packet_unpack_reader_data* reader, u16 size) { if(reader->offset + size <= reader->packet_size) { return &reader->packet[reader->offset]; } else { return NULL; } } ya_result packet_reader_read_u16(packet_unpack_reader_data* reader, u16 *val); ya_result packet_reader_read_dnstype(packet_unpack_reader_data* reader); ya_result packet_reader_read_dnsclass(packet_unpack_reader_data* reader); ya_result packet_reader_skip_query(packet_unpack_reader_data* reader, const u8 *domain, u16 dnstype, u16 dnsclass); ya_result packet_reader_skip_bytes(packet_unpack_reader_data* reader, u16 count); ya_result packet_reader_read_u32(packet_unpack_reader_data* reader, u32 *val); static inline void packet_reader_read_u16_unchecked(packet_unpack_reader_data* reader, u16 *val) { *val = GET_U16_AT(reader->packet[reader->offset]); reader->offset += 2; } static inline void packet_reader_read_u32_unchecked(packet_unpack_reader_data* reader, u32 *val) { *val = GET_U32_AT(reader->packet[reader->offset]); reader->offset += 4; } static inline ya_result packet_reader_read_s32(packet_unpack_reader_data* reader, s32 *val) { return packet_reader_read_u32(reader, (u32*)val); } static inline void packet_reader_read_s32_unchecked(packet_unpack_reader_data* reader, s32 *val) { packet_reader_read_u32_unchecked(reader, (u32*)val); // wrapped } static inline ya_result packet_reader_skip(packet_unpack_reader_data* reader, u32 len) { if((reader->offset += len) > reader->packet_size) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; /* unexpected EOF */ } return len; } static inline void packet_reader_skip_unchecked(packet_unpack_reader_data* reader, u32 len) { reader->offset += len; } static inline s32 packet_reader_available(packet_unpack_reader_data* reader) { return (s32)reader->packet_size - (s32)reader->offset; } void packet_reader_rewind(packet_unpack_reader_data* reader); ya_result packet_reader_skip_fqdn(packet_unpack_reader_data* reader); ya_result packet_reader_skip_record(packet_unpack_reader_data* reader); /* two tools functions for the controller */ ya_result packet_reader_read_utf8(packet_unpack_reader_data *reader, u16 rdatasize, u16 rclass, char **txt, bool dryrun); ya_result packet_reader_read_remote_server(packet_unpack_reader_data *reader, u16 rdatasize, u16 rclass, host_address **ha, bool dryrun); /* static inline u8* packet_reader_get_next_u8_ptr(packet_unpack_reader_data *reader) { return &reader->packet[reader->offset]; } */ static inline const u8* packet_reader_get_next_u8_ptr_const(const packet_unpack_reader_data *reader) { return &reader->packet[reader->offset]; } static inline void packet_reader_set_position(packet_unpack_reader_data *reader, u32 position) { reader->offset = position; } static inline u32 packet_reader_position(packet_unpack_reader_data *reader) { return reader->offset; } #ifdef __cplusplus } #endif #endif /* _PACKET_READER_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/packet_writer.h0000644000000000000000000000013214505005532024635 xustar000000000000000030 mtime=1695812442.032976316 30 atime=1695812445.788030096 30 ctime=1695812494.319725167 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/packet_writer.h0000664000374500037450000001662114505005532024605 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnspacket DNS Messages * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _PACKET_WRITER_H #define _PACKET_WRITER_H #include #include #include #include #define PW_MESSAGE_BUFFER_SIZE 0x10500 #ifdef __cplusplus extern "C" { #endif typedef struct packet_dictionary_node packet_dictionary_node; struct packet_dictionary_node // 16 / 28 { packet_dictionary_node* next; packet_dictionary_node* child; u8* label; u32 offset; }; typedef struct packet_writer packet_writer; struct packet_writer { packet_dictionary_node* head; // 4 8 packet_dictionary_node* pool_head; // 8 16 u8* packet; // 12 24 u32 packet_offset; // 16 28 u32 packet_limit; // 20 32 packet_dictionary_node pool[4096]; // 65556 114720 or 131104 (depending on struct alignment) }; /** * * creates an new packet * * @param pw * @param packet * @param limit */ void packet_writer_create(packet_writer *pw, u8* packet, u32 limit); /** * * initialises a writer based on an existing message * * @param pw * @param packet a packet containing a valid message * @param packet_offset * @param size_limit * @return */ ya_result packet_writer_init(packet_writer *pw, u8* packet, u32 packet_offset, u32 size_limit); static inline ya_result packet_writer_init_append_to_message(packet_writer* pw, message_data *mesg) { // do not use the logical max return packet_writer_init(pw, message_get_buffer(mesg), message_get_size(mesg), message_get_buffer_size_max(mesg)); } /** * * initialises a writer based on an existing message * * @param pw * @param packet a packet containing a valid message * @param packet_offset * @param size_limit * @return */ static inline ya_result packet_writer_init_from_message(packet_writer* pw, message_data *mesg) { // do not use the logical max return packet_writer_init(pw, message_get_buffer(mesg), message_get_size(mesg), message_get_buffer_size_max(mesg)); } /** * * initialises a writer into an existing message, does not parse the message * * @param pw * @param packet a packet containing a valid message * @param packet_offset * @param size_limit * @return */ static inline void packet_writer_init_into_message(packet_writer* pw, message_data *mesg) { // do not use the logical max packet_writer_create(pw, message_get_buffer(mesg), message_get_buffer_size_max(mesg)); } /** * @note uncompressed names will not be compressed, of course *** BUT *** * they will not be used in the compression dictionnary either */ ya_result packet_writer_add_fqdn_uncompressed(packet_writer *pw, const u8 *fqdn); ya_result packet_writer_add_fqdn(packet_writer *pw, const u8* fqdn); ya_result packet_writer_add_rdata(packet_writer *pw, u16 rr_type, const u8 *rdata, u16 rdata_len); ya_result packet_writer_add_record(packet_writer *pw, const u8* fqdn, u16 rr_type, u16 rr_class, u32 ttl, const u8* rdata, u16 rdata_len); ya_result packet_writer_add_dnsrr(packet_writer *pw, dns_resource_record* dns_rr); static inline void packet_writer_set_truncated(packet_writer *pw) { MESSAGE_HIFLAGS(pw->packet) |= TC_BITS|QR_BITS; } static inline void packet_writer_forward(packet_writer *pw, u32 bytes) { assert(pw->packet_offset + bytes <= pw->packet_limit); pw->packet_offset += bytes; } static inline void packet_writer_set_u8(packet_writer *pw, u16 value, u32 offset) { assert(pw->packet_offset <= pw->packet_limit); pw->packet[offset] = value; } static inline void packet_writer_add_u8(packet_writer *pw, u16 value) { assert(pw->packet_offset + 1 <= pw->packet_limit); pw->packet[pw->packet_offset++] = value; } static inline void packet_writer_set_u16(packet_writer *pw, u16 value, u32 offset) { SET_U16_AT(pw->packet[offset], value); } static inline void packet_writer_add_u16(packet_writer *pw, u16 value) { assert(pw->packet_offset + 2 <= pw->packet_limit); SET_U16_AT(pw->packet[pw->packet_offset], value); pw->packet_offset += 2; } static inline void packet_writer_add_u32(packet_writer *pw, u32 value) { assert(pw->packet_offset + 4 <= pw->packet_limit); SET_U32_AT(pw->packet[pw->packet_offset], value); pw->packet_offset += 4; } static inline void packet_writer_set_u32(packet_writer *pw, u32 value, u32 offset) { assert(offset + 4 <= pw->packet_limit); SET_U32_AT(pw->packet[offset], value); } static inline void packet_writer_add_bytes(packet_writer *pw, const u8 *buffer, u32 len) { assert(pw->packet_offset + len <= pw->packet_limit); MEMCOPY(&pw->packet[pw->packet_offset], buffer, len); pw->packet_offset += len; } static inline u32 packet_writer_get_offset(const packet_writer *pw) { return pw->packet_offset; } static inline void packet_writer_set_offset(packet_writer *pw, u32 offset) { yassert(offset <= pw->packet_limit); pw->packet_offset = offset; } static inline u32 packet_writer_get_limit(const packet_writer *pw) { return pw->packet_limit; } static inline s32 packet_writer_get_remaining_capacity(const packet_writer *pw) { assert(pw->packet_offset <= pw->packet_limit); return (s32)pw->packet_limit - (s32)pw->packet_offset; } static inline u8* packet_writer_get_next_u8_ptr(const packet_writer *pw) { return &pw->packet[pw->packet_offset]; } ya_result write_tcp_packet(packet_writer *pw, output_stream *tcpos); #ifdef __cplusplus } #endif #endif /* _PACKET_WRITER_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/parser.h0000644000000000000000000000013114505005532023265 xustar000000000000000030 mtime=1695812442.079976989 29 atime=1695812445.78903011 30 ctime=1695812494.321725196 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/parser.h0000664000374500037450000004333414505005532023237 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #ifndef PARSER_H #define PARSER_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif struct parser_delimiter_s { char begin; // " ' < char end; // " ' > u8 id; u8 reserved; }; typedef struct parser_delimiter_s parser_delimiter_s; #define PARSER_INCLUDE_DEPTH_MAX 256 #define PARSER_LINE_LENGTH_MAX 65535 #define PARSER_CHAR_TYPE_NORMAL 0 #define PARSER_CHAR_TYPE_ESCAPE_CHARACTER 1 #define PARSER_CHAR_TYPE_COMMENT_MARKER 2 #define PARSER_CHAR_TYPE_STRING_DELIMITER 3 #define PARSER_CHAR_TYPE_MULTILINE_DELIMITER 4 #define PARSER_CHAR_TYPE_MULTILINE_DELIMITER_END 5 #define PARSER_CHAR_TYPE_BLANK_MARKER 6 #define PARSER_CHAR_TYPE_EOL 7 #if DNSCORE_HAS_FULL_ASCII7 #define PARSER_CHAR_TYPE_TO_TRANSLATE 8 #endif #define PARSER_CHAR_TYPE_IGNORE 255 #define PARSER_STATUS_NORMAL 0 #define PARSER_STATUS_STRING 1 #define PARSER_STATUS_MULTILINE 2 #define PARSER_EOF 1 #define PARSER_EOL 2 #define PARSER_COMMENT 4 #define PARSER_WORD 8 #define PARSER_BLANK_START 16 #define PARSER_ERROR_BASE 0x800D0000 #define PARSER_ERROR_CODE(code_) ((s32)(PARSER_ERROR_BASE+(code_))) #define PARSER_SYNTAX_ERROR_MULTILINE PARSER_ERROR_CODE(0x0001) #define PARSER_SYNTAX_ERROR_EXPECTED_EOL PARSER_ERROR_CODE(0x0002) #define PARSER_SYNTAX_ERROR_LINE_TOO_BIG PARSER_ERROR_CODE(0x0003) #define PARSER_BUFFER_TOO_SMALL PARSER_ERROR_CODE(0x0004) #define PARSER_NO_INPUT PARSER_ERROR_CODE(0x0005) #define PARSER_ODD_CHAR_NUMBER PARSER_ERROR_CODE(0x0006) #define PARSER_LINE_ENDED_WITH_ESCAPE PARSER_ERROR_CODE(0x0007) #define PARSER_UNEXPECTED_STRING_DELIMITER PARSER_ERROR_CODE(0x0008) #define PARSER_EXPECTED_STRING_END_DELIMITER PARSER_ERROR_CODE(0x0009) #define PARSER_INCLUDE_DEPTH_TOO_BIG PARSER_ERROR_CODE(0x000A) #define PARSER_UNKNOWN_TIME_UNIT PARSER_ERROR_CODE(0x000B) #define PARSER_NO_MARK_SET PARSER_ERROR_CODE(0x000C) #define PARSER_REACHED_END_OF_LINE PARSER_ERROR_CODE(0x000D) #define PARSER_FOUND_WORD PARSER_ERROR_CODE(0x000E) #define PARSER_REACHED_END_OF_FILE PARSER_ERROR_CODE(0x000F) #define PARSER_INVALID_ESCAPED_FORMAT PARSER_ERROR_CODE(0x0010) struct parser_token_s { const char *word; u32 word_len; }; typedef struct parser_token_s parser_token_s; struct parser_s { // SETTINGS // ie: "" '' <> [] parser_delimiter_s *string_delimiters; // ie: () parser_delimiter_s *multiline_delimiters; // ie: # ; const char *comment_marker; // ie: SPACE TAB const char *blank_marker; // ie: BACKSLASH const char *escape_characters; // STATE MACHINE char *needle; char *needle_mark; char *limit; char *text; u32 text_length; u32 string_delimiters_count; u32 multiline_delimiters_count; u32 comment_marker_count; u32 blank_marker_count; u32 escape_characters_count; u32 line_number; u32 input_stream_stack_size; char multiline; // TODO: stack of multilines char cutchar; // bool tokenize_on_string; bool close_last_stream; input_stream *input_stream_stack[PARSER_INCLUDE_DEPTH_MAX]; u32 line_number_stack[PARSER_INCLUDE_DEPTH_MAX]; char char_type[256]; char delimiter_close[256]; #if DNSCORE_HAS_FULL_ASCII7 char translation_table[256]; #endif char line_buffer[PARSER_LINE_LENGTH_MAX]; char line_buffer_zero; char extra_buffer[PARSER_LINE_LENGTH_MAX]; char extra_buffer_zero; char additional_buffer[PARSER_LINE_LENGTH_MAX]; char additional_buffer_zero; }; typedef struct parser_s parser_s; void parser_init_error_codes(); ya_result parser_init(parser_s *parser, const char *string_delimiters, // by 2 const char *multiline_delimiters, // by 2 const char *comment_markers, // by 1 const char *blank_makers, // by 1 const char *escape_characters // by 1 ); ya_result parser_finalize(parser_s *parser); ya_result parser_next_token(parser_s *parser); ya_result parser_next_characters(parser_s *parser); ya_result parser_next_characters_nospace(parser_s *parser); ya_result parser_concat_next_tokens(parser_s *parser); ya_result parser_concat_next_tokens_nospace(parser_s *parser); ya_result parser_concat_current_and_next_tokens_nospace(parser_s *parser); void parser_set_eol(parser_s *parser); #if DNSCORE_HAS_FULL_ASCII7 void parser_add_translation(parser_s *parser, u8 character, u8 translates_into); void parser_del_translation(parser_s *parser, u8 character); #endif static inline u32 parser_text_length(const parser_s *parser) { return parser->text_length; } static inline const char * parser_text(const parser_s *parser) { return parser->text; } /** * * sets a terminating zero at the end of the current text returned by parser_text(parser) * can only work once * parser_text_unasciiz(parser) MUST be called before parsing the remaining of the input * * @param parser * @return */ static inline bool parser_text_asciiz(parser_s *parser) { if(parser->cutchar == '\0') { parser->cutchar = parser->text[parser->text_length]; parser->text[parser->text_length] = '\0'; return TRUE; } return FALSE; } /** * * see parser_text_unasciiz * * @param parser * @return */ static inline bool parser_text_unasciiz(parser_s *parser) { if(parser->cutchar != '\0') { parser->text[parser->text_length] = parser->cutchar; parser->cutchar = '\0'; return TRUE; } return FALSE; } static inline u8 parser_text_delimiter(const parser_s *parser) { (void)parser; return 0; // not implemented } ya_result parser_push_stream(parser_s *p, input_stream *is); input_stream *parser_pop_stream(parser_s *p); static inline u32 parser_stream_count(const parser_s *p) { return p->input_stream_stack_size; } /** * * Set the rewind position in the parser * * @param p */ static inline void parser_mark(parser_s *p) { p->needle_mark = p->needle; } static inline ya_result parser_rewind(parser_s *p) { if(p->needle_mark != NULL) { p->needle = p->needle_mark; return SUCCESS; } else { return PARSER_NO_MARK_SET; } } static inline u32 parser_get_line_number(const parser_s *p) { return p->line_number; } /////////////////////////////////////////////////////////////////////////////// static inline ya_result parser_next_word(parser_s *p) { ya_result ret; for(;;) { if(FAIL(ret = parser_next_token(p))) { return ret; } if(ret & PARSER_WORD) { return 1; } if(ret & (PARSER_EOL|PARSER_EOF)) { if(ret & PARSER_EOL) { return PARSER_REACHED_END_OF_LINE; } else { return PARSER_REACHED_END_OF_FILE; } } } } static inline ya_result parser_get_u16(const char *text, u32 text_len, u16 *out_value) { u32 tmp_u32; ya_result return_code = parse_u32_check_range_len_base10(text, text_len, &tmp_u32, 0, MAX_U16); *out_value = (u16)tmp_u32; return return_code; } static inline ya_result parser_copy_next_u16(parser_s *p, u16 *out_value) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); u32 tmp_u32; return_code = parse_u32_check_range_len_base10(text, text_len, &tmp_u32, 0, MAX_U16); *out_value = (u16)tmp_u32; } return return_code; } static inline ya_result parser_copy_next_u8(parser_s *p, u8 *out_value) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); u32 tmp_u32; return_code = parse_u32_check_range_len_base10(text, text_len, &tmp_u32, 0, MAX_U8); *out_value = (u8)tmp_u32; } return return_code; } static inline ya_result parser_get_u8(const char *text, u32 text_len, u8 *out_value) { u32 tmp_u32; ya_result return_code = parse_u32_check_range_len_base10(text, text_len, &tmp_u32, 0, MAX_U8); *out_value = (u8)tmp_u32; return return_code; } static inline ya_result parser_get_s8(const char *text, u32 text_len, s8 *out_value) { s32 tmp_s32; ya_result return_code = parse_s32_check_range_len_base10(text, text_len, &tmp_s32, (s32)MIN_S8, (s32)MAX_S8); *out_value = (s8)tmp_s32; return return_code; } static inline ya_result parser_expect_eol(parser_s *p) { ya_result return_code; for(;;) { return_code = parser_next_token(p); if(return_code & PARSER_WORD) { return PARSER_FOUND_WORD; } if(return_code & (PARSER_EOL|PARSER_EOF)) { return SUCCESS; } } } static inline bool parse_word_match(const char *text, u32 text_len, const char *match, u32 match_len) { if(text_len == match_len) { bool ret = (memcmp(text, match, text_len) == 0); return ret; } return FALSE; } static inline bool parse_word_case_match(const char *text, u32 text_len, const char *match, u32 match_len) { if(text_len == match_len) { for(u32 i = 0; i < text_len; ++i) { if(tolower(text[i]) != tolower(match[i])) { return FALSE; } } return TRUE; } return FALSE; } static inline ya_result parser_copy_word(parser_s *p, char *out_text, u32 out_text_len) { u32 len = parser_text_length(p); if(len < out_text_len) { memcpy(out_text, parser_text(p), len); out_text[len] = '\0'; return len; } else { return PARSER_BUFFER_TOO_SMALL; } } static inline ya_result parser_copy_next_word(parser_s *p, char *out_text, u32 out_text_len) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { u32 len = parser_text_length(p); if(len < out_text_len) { memcpy(out_text, parser_text(p), len); out_text[len] = '\0'; return_code = len; } else { return_code = PARSER_BUFFER_TOO_SMALL; } } return return_code; } static inline ya_result parser_copy_next_class(parser_s *p, u16 *out_value) { ya_result return_code; char text[32]; if(ISOK(return_code = parser_copy_next_word(p, text, sizeof(text)))) { return_code = dns_class_from_name(text, out_value); } return return_code; } static inline ya_result parser_copy_next_type(parser_s *p, u16 *out_value) { ya_result return_code; char text[32]; if(ISOK(return_code = parser_copy_next_word(p, text, sizeof(text)))) { return_code = dns_type_from_name(text, out_value); } return return_code; } ya_result parser_copy_next_ttl(parser_s *p, s32 *out_value); static inline ya_result parser_copy_next_fqdn(parser_s *p, u8 *out_value) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); return_code = cstr_to_dnsname_with_check_len(out_value, text, text_len); } return return_code; } static inline ya_result parser_copy_next_fqdn_with_origin(parser_s *p, u8 *out_value, const u8 *origin) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); return_code = cstr_to_dnsname_with_check_len_with_origin(out_value, text, text_len, origin); } return return_code; } static inline ya_result parser_copy_next_fqdn_locase_with_origin(parser_s *p, u8 *out_value, const u8 *origin) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); return_code = cstr_to_locase_dnsname_with_check_len_with_origin(out_value, text, text_len, origin); } return return_code; } static inline ya_result parser_copy_next_yyyymmddhhmmss(parser_s *p, u32 *out_value) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); time_t t; return_code = parse_yyyymmddhhmmss_check_range_len(text, text_len, &t); *out_value = (u32)t; } return return_code; } static inline ya_result parser_get_s16(const char *text, u32 text_len, s16 *out_value) { s32 tmp_s32; ya_result return_code = parse_s32_check_range_len_base10(text, text_len, &tmp_s32, MIN_S16, MAX_S16); *out_value = (s16)tmp_s32; return return_code; } static inline ya_result parser_copy_next_s16(parser_s *p, s16 *out_value) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); s32 tmp_s32; return_code = parse_s32_check_range_len_base10(text, text_len, &tmp_s32, MIN_S16, MAX_S16); *out_value = (s16)tmp_s32; } return return_code; } static inline ya_result parser_get_u32(const char *text, u32 text_len, u32 *out_value) { ya_result return_code = parse_u32_check_range_len_base10(text, text_len, out_value, 0, MAX_U32); return return_code; } static inline ya_result parser_get_s32(const char *text, u32 text_len, s32 *out_value) { ya_result return_code = parse_s32_check_range_len_base10(text, text_len, out_value, MIN_S32, MAX_S32); return return_code; } static inline ya_result parser_copy_next_s32(parser_s *p, s32 *out_value) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); return_code = parse_s32_check_range_len_base10(text, text_len, out_value, MIN_S32, MAX_S32); } return return_code; } static inline ya_result parser_copy_next_u32(parser_s *p, u32 *out_value) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); return_code = parse_u32_check_range_len_base10(text, text_len, out_value, 0, MAX_U32); } return return_code; } static inline ya_result parser_get_u64(const char *text, u32 text_len, u64 *out_value) { ya_result return_code = parse_u64_check_range_len_base10(text, text_len, out_value, 0, MAX_U64); return return_code; } static inline ya_result parser_copy_next_u64(parser_s *p, u64 *out_value) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); return_code = parse_u64_check_range_len_base10(text, text_len, out_value, 0, MAX_U64); } return return_code; } ya_result parser_get_network_protocol_from_next_word(parser_s *p, int *out_value); ya_result parser_get_network_service_port_from_next_word(parser_s *p, int *out_value); ya_result parser_type_bit_maps_initialise(parser_s *p, type_bit_maps_context* context); #ifdef __cplusplus } #endif #endif /* PARSER_H */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/parsing.h0000644000000000000000000000013214505005531023434 xustar000000000000000030 mtime=1695812441.786972793 30 atime=1695812445.786030067 30 ctime=1695812494.323725225 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/parsing.h0000664000374500037450000002156714505005531023411 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoretools Generic Tools * @ingroup dnscore * @brief * * @{ */ #ifndef _PARSING_H #define _PARSING_H #include #include #define BASE_10 10 #ifdef __cplusplus extern "C" { #endif /** \brief A string will be checked * * The number will be extracted from the string if present. This number can * be 10-based, or hex-based, or...\n * The base must be between 2 and 36 and the number must be be between the min * values and max value * * @param[in] src string with number part in it * @param[out] dst number found * @param[in] min * @param[in] max * @param[in] base * * @retval OK * @retval NOK, if no digits found, or number not in the range */ ya_result parse_u32_check_range(const char *src, u32 *dst, u32 min, u32 max, u8 base); ya_result parse_u32_check_range_len_base10(const char *src, u32 src_len, u32 *dst, u32 min, u32 max); ya_result parse_s32_check_range_len_base10(const char *src, u32 src_len, s32 *dst, s32 min, s32 max); /** \brief A string will be extracted and checked * * The number will be extracted from the string if present. * * @param[in] src string with number part in it * @param[in] src_len string length * @param[out] dst number found * @param[in] min * @param[in] max * * @retval OK * @retval PARSEINT_ERROR, if no digits found, or number not in the range */ ya_result parse_u64_check_range_len_base10(const char *src, u32 src_len, u64 *dst, u64 min, u64 max); /** \brief Converts a chain of pascal strings to a string * * Converts a chain of pascal strings to a string * * @param[in] src string in the form [len+chars]* * @param[out] dst string * * @retval OK * @retval NOK, if something is broken */ ya_result parse_pstring(char **srcp_in_out, size_t src_len, u8 *dst, size_t dst_len); /** \brief Converts a string to an epoch * * Converts a string to an epoch * * @param[in] src string in the form YYYYMMDDhhmmss * @param[out] dst value of the source converted into GMT epoch * * @retval OK * @retval NOK, if no digits found, or number not in the range */ ya_result parse_yyyymmddhhmmss_check_range_len(const char *src, u32 src_len, time_t *dst); ya_result parse_yyyymmddhhmmss_check_range(const char *src, time_t *dst); /** \brief Copies and trim a string * * Copies a string while remove head & tail spaces and reducing any blank run to a single space * The source does not need to be asciiz * The destination will be asciiz * * @param[in] src string * @param[in] src_len size of the string (the zero sentinel is not checked) * @param[in] dst buffer that will receive the output string * @param[in] dst_len size of the buffer * * @retval >= 0, the length of the dst string * @retval ERROR, dst_len was too small */ ya_result parse_copy_trim_spaces(const char *src, u32 src_len, char *dst, u32 dst_len); ya_result parse_remove_spaces(char *inout_txt); /** \brief Skips a specific keyword from a string, case insensitive * * Skips a specific keyword from a string, case insensitive, skips white spaces before and after the match * * @param[in] src string * @param[in] src_len size of the string (the zero sentinel is not checked) * @param[in] words array of strings that will be looked for * @param[in] word_count the size of the array * @param[in] matched_word a pointer to an integer that will hold the matched word index or -1 (can be NULL) * * @retval >= 0, the number of bytes until the next word * @retval ERROR, dst_len was too small */ ya_result parse_skip_word_specific(const char *src, u32 src_len, const char **words, u32 word_count, s32 *matched_word); const char * parse_skip_until_chars(const char *src, const char *chars, u32 chars_len); /** \brief Skips a specific keyword from a string, case insensitive * * Skips a specific keyword from a string, case insensitive, skips white spaces before and after the match * * @param[in] src string * @param[in] src_len size of the string (the zero sentinel is not checked) * @param[in] dst buffer that will receive the binary version of the ip * @param[in] dst_len the size of the buffer, minimum 4 for ipv4 and minimum 16 for ipv6 * * @retval >= 0, the number of bytes written (4 for ipv4 and 16 for ipv6) * @retval ERROR, dst_len was too small or the src was not a valid ip */ ya_result parse_ip_address(const char *src, u32 src_len, u8 *dst, u32 dst_len); /** * Returns a pointer to the first non-blank character on an ASCIIZ string * blank = space-char & tab * space = space-char & tab & form feed & cr & lf * * @param txt * @return */ static inline const char *parse_skip_spaces(const char *txt) { while(isspace(*txt) && (*txt != '\0')) { txt++; } return txt; } /** * Returns a pointer to the first non-digit character on an ASCIIZ string * * @param txt * @return */ static inline const char *parse_skip_digits(const char *txt) { while(isdigit(*txt) && (*txt != '\0')) { txt++; } return txt; } /** * Returns a pointer to the first digit character on an ASCIIZ string * * @param txt * @return */ static inline const char *parse_skip_nondigits(const char *txt) { while(!isdigit(*txt) && (*txt != '\0')) { txt++; } return txt; } /** * Returns a pointer to the first blank character on an ASCIIZ string * blank = space-char & tab * space = space-char & tab & form feed & cr & lf * * @param txt * @return */ static inline const char *parse_next_blank(const char *txt) { while(!isblank(*txt) && (*txt != '\0')) { txt++; } return txt; } /** * Returns a pointer to the first space character on an ASCIIZ string * blank = space-char & tab * space = space-char & tab & form feed & cr & lf * * @param txt * @return */ static inline const char *parse_next_space(const char *txt) { while(!isspace(*txt) && (*txt != '\0')) { txt++; } return txt; } /** * Copies the next word into dst * * @param txt * @return strlen(dst) */ static inline s32 parse_copy_word(char *dst, size_t dst_size, const char *txt) { char *base = dst; const char * const limit = &txt[MIN(strlen(txt), dst_size)]; while(!isspace(*txt) && (txt < limit)) { *dst++ = *txt++; } *dst = '\0'; return (s32)(dst - base); } static inline s32 parse_copy_next_word(char *dst, size_t dst_size, const char *txt) { const char *non_blank_txt = parse_skip_spaces(txt); s32 n = parse_copy_word(dst, dst_size, non_blank_txt); if(n >= 0) { n += (s32)(non_blank_txt - txt); } return n; } s32 parse_next_token(char *dest, size_t dest_size, const char *from, const char *delim); /** * * now * tomorrow * yesterday * +1y +1year +1years (months,weeks,days,seconds) * -1y -1year -1years (months,weeks,days,seconds) * 2019-04-16 * 2019-04-16_12:00:00.123456 * 20190416 * 20190416120000123456 * */ s64 parse_timeus_from_smarttime(const char *text); #ifdef __cplusplus } #endif #endif /* _PARSING_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/pid.h0000644000000000000000000000013214505005532022546 xustar000000000000000030 mtime=1695812442.103977333 30 atime=1695812445.790030125 30 ctime=1695812494.325725254 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/pid.h0000664000374500037450000000524114505005532022512 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #include /** \brief Read \b pid \b file, program quits on log_quit * * Made available again for a project still using it. * * @param[in] path * @param[in] file_name * * @retval pid * @retval NOK (negative number), * @return otherwise log_quit will stop the program with correct exit code */ pid_t pid_file_read(const char *pid_file_path); ya_result pid_file_create(pid_t *pid, const char *pid_file_path, uid_t uid, gid_t gid); // pid_t pid_file_read(const char *pid_file_path); ya_result pid_check_running_program(const char *pid_file_path, pid_t* out_pid); void pid_file_destroy(const char *pid_file_path); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/pipe_stream.h0000644000000000000000000000013114505005532024301 xustar000000000000000029 mtime=1695812442.10097729 30 atime=1695812445.790030125 30 ctime=1695812494.327725282 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/pipe_stream.h0000664000374500037450000000610314505005532024244 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef PIPE_STREAM_H_ #define PIPE_STREAM_H_ #ifdef __cplusplus extern "C" { #endif #include #include /** * Creates both output and input stream * Writing in the output stream makes it available for the input stream * This is not thread-safe. * * This is used in the XFR input stream. The internal processing of the XFR stream * writes the available bytes to the output so the reader can get them from the * input. * * @param output * @param input */ void pipe_stream_init(output_stream *output, input_stream *input, u32 buffer_size); /** * * Number of available bytes in the input stream * * @param input * @return */ ya_result pipe_stream_read_available(input_stream *input); /** * * Room for bytes in the output stream * * @param input * @return */ ya_result pipe_stream_write_available(output_stream *input); #ifdef __cplusplus } #endif #endif /* PIPE_STREAM_H_ */ /* ------------------------------------------------------------ */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/pool.h0000644000000000000000000000013214505005532022743 xustar000000000000000030 mtime=1695812442.005975929 30 atime=1695812445.787030082 30 ctime=1695812494.329725311 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/pool.h0000664000374500037450000000674714505005532022723 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #ifndef POOL_H #define POOL_H #include #include struct pool_s; typedef void *pool_allocate_callback(void *args); typedef void pool_reset_callback(void *ptr, void *args); typedef void pool_free_callback(void *ptr, void* args); // for destruction struct pool_s { ptr_vector pool; pool_allocate_callback *allocate_method; pool_free_callback *free_method; pool_reset_callback *reset_method; mutex_t mtx; void *allocate_args; volatile u64 allocated_count; volatile u64 released_count; const char* name; s32 max_size; // do not retain more than this, stored as "max_size - 1" volatile s32 current_count; volatile s32 peak_count; struct pool_s *next; bool hard_limit; bool maxed; }; typedef struct pool_s pool_s; struct logger_handle; /** * * @param pool * @param allocate * @param free * @param reset a method to make the pre-used allocated object like new * @param allocate_args * @param name */ void pool_init_ex(pool_s *pool, pool_allocate_callback *allocate, pool_free_callback *free, pool_reset_callback *reset, void *allocate_args, const char* name); void pool_init(pool_s *pool, pool_allocate_callback *allocate, pool_free_callback *free, void *allocate_args, const char* name); void pool_finalize(pool_s *pool); void pool_log_stats(pool_s *pool); void pool_log_all_stats(); void pool_log_stats_ex(pool_s *pool, struct logger_handle* handle, u32 level); void pool_log_all_stats_ex(struct logger_handle* handle, u32 level); void *pool_alloc(pool_s *pool); void pool_release(pool_s *pool, void *p); void pool_set_size(pool_s *pool, s32 max_size); #endif yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/popen-output-stream.h0000644000000000000000000000013214505005532025742 xustar000000000000000030 mtime=1695812442.086977089 30 atime=1695812445.790030125 30 ctime=1695812494.331725339 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/popen-output-stream.h0000664000374500037450000000446114505005532025711 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore * @ingroup dnscore * @brief popen is not enough * * * @{ */ #pragma once #include #include #include struct popen_output_stream_parameters { uid_t uid; gid_t gid; }; typedef struct popen_output_stream_parameters popen_output_stream_parameters; int popen_output_stream_ex(output_stream* os, const char* command, struct popen_output_stream_parameters* parms); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/print_stream.h0000644000000000000000000000013214505005532024501 xustar000000000000000030 mtime=1695812442.084977061 30 atime=1695812445.790030125 30 ctime=1695812494.333725368 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/print_stream.h0000664000374500037450000000503314505005532024444 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _PRINT_STREAM_H #define _PRINT_STREAM_H #include #ifdef __cplusplus extern "C" { #endif ya_result os_print(output_stream_ptr stream,const char* text); ya_result os_println(output_stream_ptr stream,const char* text); ya_result os_format(output_stream_ptr stream,const char* text,...); ya_result os_formatln(output_stream_ptr stream,const char* text,...); #ifdef __cplusplus } #endif #endif /* _OUTPUT_STREAM_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/process.h0000644000000000000000000000013114505005532023447 xustar000000000000000030 mtime=1695812442.055976646 29 atime=1695812445.78903011 30 ctime=1695812494.335725397 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/process.h0000664000374500037450000000431014505005532023410 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #include extern pid_t g_pid; static inline pid_t getpid_ex() { return g_pid; } pid_t fork_ex(); int waitpid_ex(pid_t pid, int *wstatus, int options); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/ptr_set.h0000644000000000000000000000013214505005531023451 xustar000000000000000030 mtime=1695812441.990975715 30 atime=1695812445.786030067 30 ctime=1695812494.338725439 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/ptr_set.h0000664000374500037450000002467014505005531023424 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A dictionary (map, hash, ...) ptr->ptr implemented as an AVL balanced tree * * A dictionary (map, hash, ...) implemented as an AVL balanced tree * The key is a pointer and is compated with other keys using a used-defined, * per-collection comparison function. * * Pre-defined comparators include: * * PTR_SET_EMPTY (ptr_set_default_node_compare) pointer addresses * PTR_SET_ASCIIZ_EMPTY (ptr_set_asciizp_node_compare) C-strings * PTR_SET_DNSNAME_EMPTY (ptr_set_dnsname_node_compare) FQDNs * PTR_SET_NULLABLE_ASCIIZ_EMPTY (ptr_set_nullable_asciizp_node_compare) C-strings AND NULL * PTR_SET_NULLABLE_DNSNAME_EMPTY (ptr_set_nullable_dnsname_node_compare) FQDNs AND NULL * PTR_SET_PTR_EMPTY (ptr_set_ptr_node_compare) pointer addresses * PTR_SET_HOST_ADDRESS_EMPTY (ptr_set_host_address_node_compare) host_address * * @{ */ #pragma once #ifdef __cplusplus extern "C" { #endif #include /* * A digest is stored prefixed with its length ([1;255]) */ /* * A structure to hold both children with direct access */ typedef int ptr_node_compare(const void *node_a, const void *node_b); typedef struct ptr_set ptr_set; typedef struct ptr_node ptr_node; struct ptr_set { struct ptr_node *root; ptr_node_compare *compare; // compares nodes by passing pointers to the keys (and not the full node) }; struct ptr_set_children { struct ptr_node* left; struct ptr_node* right; }; /* * An union to have access to the children with direct or indexed access */ typedef union ptr_set_children_union ptr_set_children_union; union ptr_set_children_union { struct ptr_set_children lr; struct ptr_node * child[2]; }; /* * The node structure CANNOT have a varying size on a given collection * This means that the digest size is a constant in the whole tree */ struct ptr_node { union ptr_set_children_union children; // 16 /**/ struct ptr_node* parent; // 8 /**/ void *key; /* ie: nsec3 item */ union { void *value; /* ie: label linked to the nsec3 item */ intptr value_intptr; void (*void_function_void)(); s64 value_s64; u64 value_u64; s32 value_s32; u32 value_u32; }; s8 balance; }; #define PTR_SET_NODE_SIZE(node) sizeof(ptr_node) /* * AVL definition part begins here */ /* * The maximum depth of a tree. * 40 is enough for storing 433494436 items (worst case) * * Depth 0 is one node. * * Worst case : N is enough for sum[n = 0,N](Fn) where Fn is Fibonacci(n+1) * Best case : N is enough for (2^(N+1))-1 */ #define AVL_MAX_DEPTH 52 // 139*10^9 items max (worst case) /* * The previx that will be put in front of each function name */ #define AVL_PREFIX ptr_set_ /* * The type that hold the node */ #define AVL_NODE_TYPE ptr_node /* * The tag for the node */ #define PTR_NODE_TAG 0x45444f4e525450 // PTRNODE /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_TREE_TYPE ptr_set /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_CONST_TREE_TYPE const ptr_set /* * */ #define AVL_TREE_ROOT(__tree__) (__tree__)->root /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE void* #define AVL_REFERENCE_IS_POINTER TRUE #define AVL_REFERENCE_IS_CONST FALSE /* * The node has got a pointer to its parent * * 0 : disable * !=0 : enable */ #define AVL_HAS_PARENT_POINTER 1 #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif /* * I recommend setting a define to identify the C part of the template * So it can be used to undefine what is not required anymore for every * C file but that one. * */ #ifndef _PTR_SET_COLLECTION_C #undef AVL_MAX_DEPTH #undef AVL_PREFIX #undef AVL_NODE_TYPE #undef AVL_NODE_TAG #undef AVL_TREE_TYPE #undef AVL_CONST_TREE_TYPE #undef AVL_TREE_ROOT #undef AVL_REFERENCE_TYPE #undef AVL_HAS_PARENT_POINTER #undef AVL_REFERENCE_IS_POINTER #undef AVL_REFERENCE_IS_CONST #undef _AVL_H_INC #endif /* _PTR_SET_COLLECTION_C */ #ifdef __cplusplus } #endif #define ptr_set_default_node_compare ptr_set_ptr_node_compare /** * ptr_set comparator function. * Compares pointer values. * * @param key_a * @param key_b * @return */ int ptr_set_ptr_node_compare(const void *key_a, const void *key_b); /** * ptr_set comparator function. * Compares C-string values. * * @param key_a * @param key_b * @return */ int ptr_set_asciizp_node_compare(const void *key_a, const void *key_b); /** * ptr_set comparator function. * Compares C-string values, case-insensitive * * @param key_a * @param key_b * @return */ int ptr_set_asciizcasep_node_compare(const void *key_a, const void *key_b); /** * ptr_set comparator function. * Compares dnsname values, taking depth into account. * * @param key_a * @param key_b * @return */ int ptr_set_fqdn_node_compare(const void *key_a, const void *key_b); /** * ptr_set comparator function. * Compares dnsname values. * * @param key_a * @param key_b * @return */ int ptr_set_dnsname_node_compare(const void *key_a, const void *key_b); /** * ptr_set comparator function. * Compares dnslabel values. * * @param key_a * @param key_b * @return */ int ptr_set_dnslabel_node_compare(const void *key_a, const void *key_b); // key = asciiz (can be NULL) /** * ptr_set comparator function. * Compares C-strings values, NULL is allowed. * * @param key_a * @param key_b * @return */ int ptr_set_nullable_asciizp_node_compare(const void *key_a, const void *key_b); /** * ptr_set comparator function. * Compares dnsname values, NULL is allowed. * * @param key_a * @param key_b * @return */ int ptr_set_nullable_dnsname_node_compare(const void *key_a, const void *key_b); /** * ptr_set comparator function. * Compares host_address values. * * @param key_a * @param key_b * @return */ int ptr_set_host_address_node_compare(const void *key_a, const void *key_b); #define PTR_SET_EMPTY {NULL, ptr_set_default_node_compare} #define PTR_SET_ASCIIZ_EMPTY {NULL, ptr_set_asciizp_node_compare} #define PTR_SET_ASCIIZCASE_EMPTY {NULL, ptr_set_asciizcasep_node_compare} #define PTR_SET_DNSNAME_EMPTY {NULL, ptr_set_dnsname_node_compare} #define PTR_SET_NULLABLE_ASCIIZ_EMPTY {NULL, ptr_set_nullable_asciizp_node_compare} #define PTR_SET_NULLABLE_DNSNAME_EMPTY {NULL, ptr_set_nullable_dnsname_node_compare} #define PTR_SET_PTR_EMPTY {NULL, ptr_set_ptr_node_compare} #define PTR_SET_CUSTOM(comparator___) {NULL, (comparator___)} #define PTR_SET_HOST_ADDRESS_EMPTY {NULL, ptr_set_host_address_node_compare} #define PTR_SET_EMPTY_WITH_COMPARATOR(cmp_func___) {NULL, (cmp_func___)} void *ptr_set_iterator_hasnext_next_value(ptr_set_iterator *iterp); #define FOREACH_PTR_SET(cast__,var__,ptr_set__) ptr_set_iterator PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_iter,__LINE__); ptr_set_iterator_init((ptr_set__), &PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_iter,__LINE__)); for(cast__ var__;((var__) = (cast__)ptr_set_iterator_hasnext_next_value(&PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_iter,__LINE__))) != NULL;) //#define FOREACH_PTR_SET_KEY_VALUE(castk__,vark__,castv__,varv__,ptr_set__) ptr_set_iterator PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_iter,__LINE__); ptr_set_iterator_init((ptr_set__), &PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_iter,__LINE__)); for(varv__ varv__;((varc__) = (cast__)ptr_set_iterator_hasnext_next_key_value(&PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_iter,__LINE__))) != NULL;) struct const_ptr_set_of_one { ptr_set set; ptr_node one; }; typedef struct const_ptr_set_of_one const_ptr_set_of_one; /** * * For these cases you need a set of a single element that is to be used a simple, constant, input, * this is an efficient way to do so. * * Can only be used for reading (find, iterate) * The above implies : cannot be destroyed (as it is supposed to be on the stack and die winding up) * * Any other usage WILL crash the program. * * @param cpsoo * @param key * @param value * @param cmp * * example usage: * * const_ptr_set_of_one fqdn_set; * const_ptr_set_of_one_init(&fqdn_set, fqdn, fqdn, ptr_set_dnsname_node_compare); * my_function_expecting_a_read_only_fqdn_set(&fqdn_set.set); * * // do whatever I want with the fqdn and forget the fqdn_set */ static inline void const_ptr_set_of_one_init(const_ptr_set_of_one *cpsoo, void *key, void *value, ptr_node_compare *cmp) { cpsoo->set.root = &cpsoo->one; cpsoo->set.compare = cmp; ZEROMEMORY(&cpsoo->one, sizeof(ptr_node)); cpsoo->one.key = key; cpsoo->one.value = value; } /* * AVL definition part ends here */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/ptr_set_debug.h0000644000000000000000000000013214505005531024617 xustar000000000000000030 mtime=1695812441.995975786 30 atime=1695812445.787030082 30 ctime=1695812494.340725468 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/ptr_set_debug.h0000664000374500037450000001654214505005531024571 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief * * * * @{ */ #pragma once #ifdef __cplusplus extern "C" { #endif #include /* * A digest is stored prefixed with its length ([1;255]) */ /* * A structure to hold both children with direct access */ typedef int ptr_node_debug_compare(const void *node_a, const void *node_b); typedef struct ptr_set_debug ptr_set_debug; typedef struct ptr_node_debug ptr_node_debug; struct ptr_set_debug { struct ptr_node_debug *root; ptr_node_debug_compare *compare; }; struct ptr_set_debug_children { struct ptr_node_debug* left; struct ptr_node_debug* right; }; /* * An union to have access to the children with direct or indexed access */ typedef union ptr_set_debug_children_union ptr_set_debug_children_union; union ptr_set_debug_children_union { struct ptr_set_debug_children lr; struct ptr_node_debug * child[2]; }; /* * The node structure CANNOT have a varying size on a given collection * This means that the digest size is a constant in the whole tree */ struct ptr_node_debug { union ptr_set_debug_children_union children; // 16 /**/ struct ptr_node_debug* parent; // 8 /**/ void *key; /* ie: nsec3 item */ void *value; /* ie: label linked to the nsec3 item */ s8 balance; }; #define PTR_SET_NODE_SIZE(node) sizeof(ptr_node_debug) /* * AVL definition part begins here */ /* * The maximum depth of a tree. * 40 is enough for storing 433494436 items (worst case) * * Depth 0 is one node. * * Worst case : N is enough for sum[n = 0,N](Fn) where Fn is Fibonacci(n+1) * Best case : N is enough for (2^(N+1))-1 */ #define AVL_MAX_DEPTH 52 // 139*10^9 items max (worst case)64 /* * The previx that will be put in front of each function name */ #define AVL_PREFIX ptr_set_debug_ /* * The type that hold the node */ #define AVL_NODE_TYPE ptr_node_debug /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_TREE_TYPE ptr_set_debug /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_CONST_TREE_TYPE const ptr_set_debug /* * */ #define AVL_TREE_ROOT(__tree__) (__tree__)->root /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE void* #define AVL_REFERENCE_IS_POINTER TRUE #define AVL_REFERENCE_IS_CONST FALSE /* * The node has got a pointer to its parent * * 0 : disable * !=0 : enable */ #define AVL_HAS_PARENT_POINTER 1 #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif /* * I recommend setting a define to identify the C part of the template * So it can be used to undefine what is not required anymore for every * C file but that one. * */ #ifndef _PTR_SET_COLLECTION_C #undef AVL_MAX_DEPTH #undef AVL_PREFIX #undef AVL_NODE_TYPE #undef AVL_TREE_TYPE #undef AVL_CONST_TREE_TYPE #undef AVL_TREE_ROOT #undef AVL_REFERENCE_TYPE #undef AVL_HAS_PARENT_POINTER #undef AVL_REFERENCE_IS_POINTER #undef AVL_REFERENCE_IS_CONST #undef _AVL_H_INC #endif /* _PTR_SET_COLLECTION_C */ #ifdef __cplusplus } #endif #define ptr_set_debug_default_node_compare ptr_set_debug_ptr_node_compare // key = ptr int ptr_set_debug_ptr_node_compare(const void *node_a, const void *node_b); // key = asciiz (cannot be NULL) int ptr_set_debug_asciizp_node_compare(const void *node_a, const void *node_b); // key = fqdn (cannot be NULL) int ptr_set_debug_dnsname_node_compare(const void *node_a, const void *node_b); // key = fqdn (cannot be NULL) int ptr_set_debug_dnslabel_node_compare(const void *node_a, const void *node_b); // key = asciiz (can be NULL) int ptr_set_debug_nullable_asciizp_node_compare(const void *node_a, const void *node_b); // key = fqdn (can be NULL) int ptr_set_debug_nullable_dnsname_node_compare(const void *node_a, const void *node_b); int ptr_set_debug_host_address_node_compare(const void *node_a, const void *node_b); #define PTR_SET_DEBUG_EMPTY {NULL, ptr_set_debug_default_node_compare} #define PTR_SET_DEBUG_ASCIIZ_EMPTY {NULL, ptr_set_debug_asciizp_node_compare} #define PTR_SET_DEBUG_DNSNAME_EMPTY {NULL, ptr_set_debug_dnsname_node_compare} #define PTR_SET_DEBUG_NULLABLE_ASCIIZ_EMPTY {NULL, ptr_set_debug_nullable_asciizp_node_compare} #define PTR_SET_DEBUG_NULLABLE_DNSNAME_EMPTY {NULL, ptr_set_debug_nullable_dnsname_node_compare} #define PTR_SET_DEBUG_PTR_EMPTY {NULL, ptr_set_debug_ptr_node_compare} #define PTR_SET_DEBUG_CUSTOM(comparator___) {NULL, (comparator___)} #define PTR_SET_DEBUG_HOST_ADDRESS_EMPTY {NULL, ptr_set_debug_host_address_node_compare} void *ptr_set_debug_iterator_hasnext_next_value(ptr_set_debug_iterator *iterp); #define FOREACH_PTR_SET_DEBUG(cast__,var__,ptr_set_debug__) ptr_set_debug_iterator PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_debug_iter,__LINE__); ptr_set_debug_iterator_init((ptr_set_debug__), &PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_debug_iter,__LINE__)); for(cast__ var__;((var__) = (cast__)ptr_set_debug_iterator_hasnext_next_value(&PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_debug_iter,__LINE__))) != NULL;) //#define FOREACH_PTR_SET_KEY_VALUE(castk__,vark__,castv__,varv__,ptr_set_debug__) ptr_set_debug_iterator PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_debug_iter,__LINE__); ptr_set_debug_iterator_init((ptr_set_debug__), &PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_debug_iter,__LINE__)); for(varv__ varv__;((varc__) = (cast__)ptr_set_debug_iterator_hasnext_next_key_value(&PREPROCESSOR_CONCAT_EVAL(foreach_ptr_set_debug_iter,__LINE__))) != NULL;) /* * AVL definition part ends here */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/ptr_vector.h0000644000000000000000000000013214505005532024161 xustar000000000000000030 mtime=1695812442.091977161 30 atime=1695812445.790030125 30 ctime=1695812494.342725497 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/ptr_vector.h0000664000374500037450000003530014505005532024124 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A dynamic-sized array of pointers * * A dynamic-sized array of pointers * * Used for resource record canonization and such. * * @{ */ #ifndef _PTR_VECTOR_H #define _PTR_VECTOR_H #ifdef __cplusplus extern "C" { #endif #include #define PTR_VECTOR_TAG 0x52544356525450 // PTRVCTR #define PTR_VECTOR_DEFAULT_SIZE 32 #define PTR_VECTOR_EMPTY {NULL, -1, 0} #define EMPTY_PTR_VECTOR {NULL, -1, 0} // obsolete typedef struct ptr_vector ptr_vector; struct ptr_vector { void** data; s32 offset; s32 size; }; static inline void ptr_vector_init_empty(ptr_vector *v) { v->data = NULL; v->offset = -1; v->size = 0; } /** * This tool function wraps an existing (const) array * This is meant as a helper to use ptr_vector functions like search & sort to on statically allocated data. * * @param v * @param data * @param size */ static inline void ptr_vector_wrap_const_array(ptr_vector *v, void *data, s32 size) { v->data = data; v->offset = size - 1; v->size = size; } /** * Initialises a vector structure with a size of PTR_VECTOR_DEFAULT_SIZE entries * * @param v a pointer to the ptr_vector structure to initialise */ void ptr_vector_init(ptr_vector *v); /** * Initialises a vector structure with a size of PTR_VECTOR_DEFAULT_SIZE entries * * @param v a pointer to the ptr_vector structure to initialise * @param initial_capacity the size to allocate to start with */ void ptr_vector_init_ex(ptr_vector *v, u32 initial_capacity); /** * Initialises a vector as a copy as another vector. * The reserved size is the size of the original plus the extra size. * * @param v a pointer to the ptr_vector structure to initialise * @param original the vector to copy * @param extra_size the amount of reserved slots to allocate */ void ptr_vector_init_copy(ptr_vector *v, const ptr_vector *original, u32 extra_size); /** * Initialises a vector as a copy as another vector plus onz item added * The reserved size is the size of the original plus one * * @param v a pointer to the ptr_vector structure to initialise * @param original the vector to copy * @param data an item to add */ void ptr_vector_init_copy_append(ptr_vector *v, const ptr_vector *original, void *data); /** * Initialises a vector as a copy as another vector plus a few items added * The reserved size is the size of the original plus the data size. * * @param v a pointer to the ptr_vector structure to initialise * @param original the vector to copy * @param data is an array of pointers * @param data_size the size of the data array */ void ptr_vector_init_copy_append_array(ptr_vector *v, const ptr_vector *original, void *data, u32 data_size); /** * Calls the callback on every pointer stored in the vector. * Frees the memory used by a vector structure * * @param v a pointer to the ptr_vector structure */ void ptr_vector_callback_and_destroy(ptr_vector *v, callback_function free_memory); /** * Frees the memory used by a vector structure * * @param v a pointer to the ptr_vector structure */ void ptr_vector_destroy(ptr_vector *v); /** * Empties the vector (does not release memory) * * @param v a pointer to the ptr_vector structure */ void ptr_vector_clear(ptr_vector *v); /** * Cuts lose all indexes from the first bad one. * Allows to resize down without tripping an assert. */ void ptr_vector_remove_from(ptr_vector *v, s32 first_bad_index); /** * Cuts lose all indexes after the last good one. * Allows to resize down without tripping an assert. */ void ptr_vector_remove_after(ptr_vector *v, s32 last_good_index); /** * Changes the capacity of a vector to the specified size * The new size MUST be enough to keep the current content * of the vector. Failing to do so will most likely result * into a crash. * * @param v a pointer to the ptr_vector structure * @param newsize the new size of the vector */ void ptr_vector_resize(ptr_vector *v, s32 newsize); /** * Ensures the vector has enough capacity to accommodate a * specified number of items * * @param v a pointer to the ptr_vector structure * @param reqsize the minimum size of the vector */ void ptr_vector_ensures(ptr_vector *v, s32 reqsize); /** * Resizes the capacity so it can at most contain its * current size. * * @param v a pointer to the ptr_vector structure */ void ptr_vector_shrink(ptr_vector *v); /** * Appends the item (pointer) to the vector * * @param v a pointer to the ptr_vector structure * @param data a pointer to the item */ void ptr_vector_append(ptr_vector *v, void* data); /** * Appends the item (pointer) to the vector * * @param v a pointer to the ptr_vector structure * @param datap a pointer to the items * @param data_size the number of items to append */ void ptr_vector_append_array(ptr_vector *v, void** datap, u32 data_size); /** * Appends the item (pointer) to the vector * * @param v a pointer to the ptr_vector structure * @param datap a pointer to the items * @param data_size the number of items to append */ void ptr_vector_append_vector(ptr_vector *v, ptr_vector *toappend); /** * Appends the item (pointer) to the vector and try to keep the buffer size at at most * restrictedlimit. * The goal is to avoid a growth of *2 that would go far beyond the restrictedlimit. * The performance is extremely poor when the number of items in the buffer is restrictedlimit or more. * * @param v a pointer to the ptr_vector structure * @param data a pointer to the item * @param restrictedlimit a guideline limit on the size of the vector */ void ptr_vector_append_restrict_size(ptr_vector *v, void* data, u32 restrictedlimit); /** * Removes an item from the back of the vector and returns its reference * * @param v a pointer to the ptr_vector structure * @return a pointer to the removed item */ void* ptr_vector_pop(ptr_vector *v); /** * IMPORTANT NOTE: the callbacks are called with a pointer from the array */ typedef int ptr_vector_qsort_callback(const void*, const void*); /** * IMPORTANT NOTE: the callbacks are called with a pointer from the array */ typedef int ptr_vector_qsort_r_callback(const void*, const void*, void*); /** * Sort the content of the vector using the compare callback * * @param v a pointer to the ptr_vector structure * @param compare comparison callback */ void ptr_vector_qsort(ptr_vector *v, ptr_vector_qsort_callback compare); void ptr_vector_qsort_r(ptr_vector *v, ptr_vector_qsort_r_callback compare, void *compare_context); void ptr_vector_insertionsort_r(ptr_vector *v, ptr_vector_qsort_r_callback compare, void *compare_context); /** * Empties the vector releasing the item memory first * * @param v a pointer to the ptr_vector structure * @param free_memory item free callback */ void ptr_vector_callback_and_clear(ptr_vector *v, callback_function free_memory); /* * First argument is the key, second one is the item to match with the key * */ typedef int ptr_vector_search_callback(const void*, const void*); /** * Look sequentially in the vector for an item using a key and a comparison function * The callback only needs to tell equal (0) or not equal (anything else) * * @param v a pointer to the ptr_vector structure * @param what the key * @param compare the comparison function * * @return the first matching item or NULL if none has been found */ void* ptr_vector_linear_search(const ptr_vector *v, const void* what, ptr_vector_search_callback compare); s32 ptr_vector_search_ptr_index(const ptr_vector* v, const void* what); /** * Look sequentially in the vector for an item using a key and a comparison function, returns the index of the first matching item * * @param v a pointer to the ptr_vector structure * @param what the key * @param compare the comparison function * * @return the first matching item index or -1 if none has been found */ s32 ptr_vector_index_of(const ptr_vector *v, const void* what, ptr_vector_search_callback compare); /** * Look in the vector for an item using a key and a comparison function * The callback needs to tell equal (0) smaller (<0) or bigger (>0) * * @param v a pointer to the ptr_vector structure * @param what the key * @param compare the comparison function * * @return the first matching item or NULL if none has been found */ void* ptr_vector_search(const ptr_vector *v, const void* what,ptr_vector_search_callback compare); s32 ptr_vector_search_index(const ptr_vector* v, const void* what, ptr_vector_search_callback compare); /** * Returns a pointer to the item at index * Does NOT checks for the index range. * * @param v * @param idx * @return a pointer to the item at index */ static inline void* ptr_vector_get(const ptr_vector *v, s32 idx) { yassert(idx >= 0 && idx <= v->offset); return v->data[idx]; } /** * Returns a pointer to the item at index, in a circular fashion * Does NOT checks for the index range. * The array must NOT be empty (div0). * * @param v * @param idx * @return a pointer to the item at index */ static inline void* ptr_vector_get_mod(const ptr_vector *v, s32 idx) { assert(v->offset >= 0); int m = idx % (v->offset + 1); if(m < 0) { m += v->offset + 1; } // modulo fix return v->data[m]; } /** * Sets the item at index to value. * Does NOT checks for the index range. * Does NOT grows the vector. * * @param v * @param idx * @param val */ static inline void ptr_vector_set(ptr_vector *v, s32 idx, void* val) { v->data[idx] = val; } /** * Returns a pointer to the last item in the vector or NULL if the vector is empty. * * @param v * @return a pointer to the last item or NULL if the vector is empty */ static inline void *ptr_vector_last(const ptr_vector *v) { void *r = NULL; if(v->offset >= 0) { r = v->data[v->offset]; } return r; } /** * Returns the size of the vector * * @param pv * @param idx */ static inline s32 ptr_vector_size(const ptr_vector *v) { return v->offset + 1; } /** * Returns the index of the last item in the vector * This is useful because of an implementaiton detail : * obtaining the last index is faster than the size. * * @param pv * @param idx * @param val */ static inline s32 ptr_vector_last_index(const ptr_vector *v) { return v->offset; } /** * Returns the capacity of the vector, that is : the number of items it can hold * without growing. * * @param pv * @param idx * @param valp * @param n */ static inline s32 ptr_vector_capacity(const ptr_vector *v) { return v->size; } static inline bool ptr_vector_isempty(const ptr_vector *v) { return (v->offset < 0); } /** * Swap the last item of the vector with the one at index idx. * * One typical use of this function is to remove an item and shrink: * If the vector does not need to keep the order of its content, the * item that is not wanted is exchanged with the end, then the size is * shrank of one slot. * * This is certainly much faster than the insert and remove families * that can be found here below. * * @param pv * @param idx */ static inline void ptr_vector_end_swap(ptr_vector *pv,s32 idx) { void* tmp = pv->data[idx]; pv->data[idx] = pv->data[pv->offset]; pv->data[pv->offset] = tmp; } /** * Reverse the content * * e.g. * 'I' 'I' 'S' 'G' * becomes * 'G' 'S' 'I' 'I' * * @param pv */ static inline void ptr_vector_reverse(ptr_vector *v) { void *temp; void **start = v->data; void **end = &v->data[v->offset]; while (start < end) { temp = *start; *start = *end; *end = temp; start++; end--; } } /** * Inserts a value at position, pushing items from this position up * Potentially very slow. * * @param pv * @param idx */ void ptr_vector_insert_at(ptr_vector *pv, s32 idx, void *val); /** * Inserts multiple values at position, pushing items from this position up * Potentially very slow. * * @param pv * @param idx * @param valp an array of pointers that will be inserted * @param n the size of the array of pointers */ void ptr_vector_insert_array_at(ptr_vector *pv, s32 idx, void **valp, u32 n); /** * * Removes a value at position, pulling items above this position down * Potentially very slow * * @param pv * @param idx * @return the removed value */ void* ptr_vector_remove_at(ptr_vector *pv, s32 idx); typedef int ptr_vector_forall_callback(void*, void*); static inline void ptr_vector_forall(ptr_vector *pv, ptr_vector_forall_callback callback, void *args) { intptr *limit = (intptr*)&pv->data[pv->offset]; for(intptr *p = (intptr*)pv->data; p <= limit; ++p) { if(callback((void*)*p, args) <= 0) { break; } } } int ptr_vector_compare_pointers_callback(const void *a, const void *b); #ifdef __cplusplus } #endif #endif /* _RR_VECTOR_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/queue-sl.h0000644000000000000000000000013214505005532023532 xustar000000000000000030 mtime=1695812442.046976517 30 atime=1695812445.788030096 30 ctime=1695812494.344725526 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/queue-sl.h0000664000374500037450000001241514505005532023477 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A queue based on single-linked nodes. * * A queue based on single-linked nodes. * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef QUEUE_SL_H_ #define QUEUE_SL_H_ /* ------------------------------------------------------------ * * INCLUDES */ #include #include /* ------------------------------------------------------------ * * STRUCTS */ /** * queue implemented as a linked list * * (looks like a no-header no-sentinel single-linked list of strings) * * head : the base structure of the list * item : the concept of what is being stored in the list * node : holds the item * data : the reference to the item (which can be called data because it's type-less) * */ #define QUSLNODE_TAG 0x45444f4e4c535551 struct queue_sl_node_s { struct queue_sl_node_s *next; void *data; }; typedef struct queue_sl_node_s queue_sl_node_s; /// The sentiel is a butchered node, meant to avoid the (useless) data field. /* typedef struct queue_sl_node_sentiel_s queue_sl_node_sentiel_s; struct queue_sl_node_sentiel_s { struct queue_sl_node_s *next; }; */ struct queue_sl_s { queue_sl_node_s *first; queue_sl_node_s *last; u32 size; }; typedef struct queue_sl_s queue_sl_s; /* ------------------------------------------------------------ * * PROTOTYPES */ /** * Initialises a list. * * @param list */ static inline void queue_sl_init(queue_sl_s *list) { ZEROMEMORY(list, sizeof(queue_sl_s)); } /** * Adds an item at the head of the list. * * @param list * @param data */ static inline void queue_sl_enqueue(queue_sl_s *list, void *data) { queue_sl_node_s *node; ZALLOC_OBJECT_OR_DIE( node, queue_sl_node_s, QUSLNODE_TAG); node->data = data; if(list->size > 0) { list->last->next = node; list->last = node; list->size++; } else { list->first = node; list->last = node; list->size = 1; } } static inline void* queue_sl_dequeue(queue_sl_s *list) { if(list->size > 0) { queue_sl_node_s *node = list->first; list->first = list->first->next; list->size--; void *data = node->data; ZFREE_OBJECT(node); return data; } else { return NULL; } } static inline void queue_sl_enqueue_node(queue_sl_s *list, queue_sl_node_s *node) { if(list->size > 0) { list->last->next = node; list->last = node; list->size++; } else { list->first = node; list->last = node; list->size = 1; } } static inline queue_sl_node_s* queue_sl_dequeue_node(queue_sl_s *list) { if(list->size > 0) { queue_sl_node_s *node = list->first; list->first = list->first->next; list->size--; return node; } else { return NULL; } } /** * * Returns the size of the list * * @param list * @return the size of the list */ static inline u32 queue_sl_size(const queue_sl_s *list) { return list->size; } static inline queue_sl_node_s * queue_sl_node_alloc() { queue_sl_node_s *node; ZALLOC_OBJECT_OR_DIE( node, queue_sl_node_s, QUSLNODE_TAG); return node; } static inline void queue_sl_node_free(queue_sl_node_s *node) { ZFREE_OBJECT(node); } #endif /* LIST_SL_H_ */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/random.h0000644000000000000000000000013214505005532023252 xustar000000000000000030 mtime=1695812442.105977361 30 atime=1695812445.790030125 30 ctime=1695812494.346725554 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/random.h0000664000374500037450000000504014505005532023213 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoretools Generic Tools * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _RANDOM_H #define _RANDOM_H #include #include #include #ifdef __cplusplus extern "C" { #endif typedef void* random_ctx; /** * For IDs ensure that seed is enough randomised. * * @param seed * @return */ random_ctx random_init(u32 seed); /** * Chooses a seed with little change of collision. * @return */ random_ctx random_init_auto(); u32 random_next(random_ctx ctx); void random_finalize(random_ctx ctx); #ifdef __cplusplus } #endif #endif /* _RANDOM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/rc.h0000644000000000000000000000013114505005532022375 xustar000000000000000030 mtime=1695812442.064976774 29 atime=1695812445.78903011 30 ctime=1695812494.348725583 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/rc.h0000664000374500037450000000745714505005532022355 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once /** * * The RC struct helps having a structure referenced by multiple concurrent threads * released when nobody uses it anymore. * */ #include #ifdef __cplusplus extern "C" { #endif typedef void rc_free_method(void*); struct rc_vtbl { rc_free_method *free_callback; mutex_t *mtx; }; typedef struct rc_vtbl rc_vtbl; /** * Initialises an RC vtbl. * The callback is called to free the struct when its last reference is released. * The mutex is meant to be shared trough a struct type. * * @param spvtbl * @param free_callback * @param mtx */ void rc_init_vtbl(rc_vtbl *spvtbl, rc_free_method *free_callback, mutex_t *mtx); void rc_finalize_vtbl(rc_vtbl *spvtbl); struct rc_s { rc_vtbl *vtbl; s32 count; }; typedef struct rc_s rc_s; /** * struct whatever * { * RC_COUNTER; * int brol; * }; * * alloc: * struct whatever *w = malloc & create & cie; * rc_acquire(w); * return w; * * get: * rc_acquire(w); * return w; * * * rc_release(w); * w = NULL; * */ #define RC_COUNTER struct rc_s __reference_counter void rc_set_internal(rc_s *rc, rc_vtbl *vtbl); void rc_aquire_internal(rc_s *rc); void rc_release_internal(rc_s *rc, void *data); #define rc_set(__structptr__, spvtbl) \ rc_set_internal((__structptr__), &((__structptr__)->__reference_counter)); /** * The typical place of an rc_acquire is before returning the variable. */ #define rc_aquire(__structptr__, spvtbl) \ rc_aquire_internal(&((__struct_ptr__)->__reference_counter)) /** * An rc_release SHOULD be followed by the variable being set to NULL. */ #define rc_release(__struct_ptr__) \ rc_release_internal(&((__struct_ptr__)->__reference_counter), (__struct_ptr__)) #ifdef __cplusplus } #endif /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/rewind-input-stream.h0000644000000000000000000000013214505005532025710 xustar000000000000000030 mtime=1695812442.020976144 30 atime=1695812445.787030082 30 ctime=1695812494.350725612 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/rewind-input-stream.h0000664000374500037450000000607714505005532025664 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif #define BUFFER_INPUT_STREAM_DEFAULT_BUFFER_SIZE 4096 void rewind_input_stream_init(input_stream *filtered_in, input_stream *stream_out, int rewind_size); void rewind_input_stream_mark(input_stream *stream); void rewind_input_stream_rewind(input_stream *stream, s32 how_much); input_stream *rewind_input_stream_get_filtered(input_stream *bis); /** * Rewinds the input stream back of a given number of bytes * * @param bos * @param bytes_back * * @return bytes_back : the operation was successful * > 0 : the maximum number of bytes available for rewind at the time of the call */ void rewind_input_stream_rewind(input_stream *stream, s32 bytes_back); void rewind_input_stream_rewind_to_mark(input_stream *stream); /** * Returns true iff the input stream is a rewind input stream * * @param bos * @return */ bool is_rewind_input_stream(input_stream *bos); #ifdef __cplusplus } #endif /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/rfc.h0000644000000000000000000000013114505005532022543 xustar000000000000000030 mtime=1695812442.052976603 30 atime=1695812445.788030096 29 ctime=1695812494.35272564 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/rfc.h0000664000374500037450000024033014505005532022510 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef RFC_H_ #define RFC_H_ #include #include /* ------------------------------------------------------------ * * INCLUDES */ /* ------------------------------------------------------------ * * VALUES */ /* http://en.wikipedia.org/wiki/List_of_DNS_record_types */ /* dns */ #define DNS_HEADER_LENGTH 12 /* rfc 1035 */ #define MAX_LABEL_LENGTH 63 /* rfc 1034 */ #define MAX_DOMAIN_TEXT_LENGTH (MAX_DOMAIN_LENGTH - 1) /* rfc 1034 */ #define MAX_DOMAIN_LENGTH 255 /* rfc 1034 */ #define MAX_LABEL_COUNT ((MAX_DOMAIN_LENGTH + 1) / 2) #define MAX_SOA_RDATA_LENGTH (255 + 255 + 20) #define DNS_DEFAULT_PORT 53 /* edns0 */ #define EDNS0_MAX_LENGTH 65535 /* See 4.5.5 in RFC rfc 2671 */ #define EDNS0_MIN_LENGTH 512 /* rfc 2671 */ #define EDNS0_DO 0 /* DNSSEC OK flag */ #define EDNS0_OPT_0 0 /* Reserverd rfc 2671 */ #define EDNS0_OPT_3 3 /* NSID rfc 5001 */ #define DNSPACKET_MAX_LENGTH 0xffff #define UDPPACKET_MAX_LENGTH 512 #define RDATA_MAX_LENGTH 0xffff /* dnssec (dns & bind) */ #define DNSSEC_AD 0x20 /* Authenticated Data flag */ #define DNSSEC_CD 0x10 /* Checking Disabled flag */ #define RRSIG_RDATA_HEADER_LEN 18 /* The length of an RRSIG rdata without the * signer_name and the signature: MUST BE 18 ! */ #define ID_BITS 0xFF /* rfc 1035 */ // HIGH flags #define QR_BITS 0x80U /* rfc 1035 */ #define OPCODE_BITS 0x78U /* rfc 1035 */ #define OPCODE_SHIFT 3U #define AA_BITS 0x04U /* rfc 1035 */ #define TC_BITS 0x02U /* rfc 1035 */ #define RD_BITS 0x01U /* rfc 1035 */ // LOW flags #define RA_BITS 0x80U /* rfc 1035 */ #define Z_BITS 0x40U /* rfc 1035 */ #define AD_BITS 0x20U /* rfc 2065 */ #define CD_BITS 0x10U /* rfc 2065 */ #define RCODE_BITS 0x0FU /* rfc 1035 */ #ifdef WORDS_BIGENDIAN // BIG endian #define DNS_FLAGS_HAS_QR(f_) (f_ & ((u16)QR_BITS << 8)) #define DNS_FLAGS_GET_OPCODE(f_) ((f_ >> (OPCODE_SHIFT + 8)) & OPCODE_BITS) #define DNS_FLAGS_HAS_AA(f_) (f_ & ((u16)AA_BITS << 8)) #define DNS_FLAGS_HAS_TC(f_) (f_ & ((u16)TC_BITS << 8)) #define DNS_FLAGS_HAS_RD(f_) (f_ & ((u16)RD_BITS << 8)) #define DNS_FLAGS_HAS_RA(f_) (f_ & ((u16)RA_BITS)) #define DNS_FLAGS_HAS_Z(f_) (f_ & ((u16)Z_BITS)) #define DNS_FLAGS_HAS_AD(f_) (f_ & ((u16)AD_BITS)) #define DNS_FLAGS_HAS_CD(f_) (f_ & ((u16)CD_BITS)) #define DNS_FLAGS_GET_RCODE(f_) (f_ & RCODE_BITS) #else #define DNS_FLAGS_HAS_QR(f_) (f_ & ((u16)QR_BITS)) #define DNS_FLAGS_GET_OPCODE(f_) ((f_ >> OPCODE_SHIFT) & OPCODE_BITS) #define DNS_FLAGS_HAS_AA(f_) (f_ & ((u16)AA_BITS)) #define DNS_FLAGS_HAS_TC(f_) (f_ & ((u16)TC_BITS)) #define DNS_FLAGS_HAS_RD(f_) (f_ & ((u16)RD_BITS)) #define DNS_FLAGS_HAS_RA(f_) (f_ & ((u16)RA_BITS << 8)) #define DNS_FLAGS_HAS_Z(f_) (f_ & ((u16)Z_BITS << 8)) #define DNS_FLAGS_HAS_AD(f_) (f_ & ((u16)AD_BITS << 8)) #define DNS_FLAGS_HAS_CD(f_) (f_ & ((u16)CD_BITS << 8)) #define DNS_FLAGS_GET_RCODE(f_) ((f_ >> 8) & RCODE_BITS) #endif #define QDCOUNT_BITS 0xFFFF /* number of questions rfc 1035 */ #define ANCOUNT_BITS 0xFFFF /* number of resource records rfc 1035 */ #define NSCOUNT_BITS 0xFFFF /* name servers in the author.rec. rfc 1035 */ #define ARCOUNT_BITS 0xFFFF /* additional records rfc 1035 */ #define ZOCOUNT_BITS 0xFFFF /* Number of RRs in the Zone Sect. rfc 2136 */ #define PRCOUNT_BITS 0xFFFF /* Number of RRs in the Prereq. Sect. rfc 2136 */ #define UPCOUNT_BITS 0xFFFF /* Number of RRs in the Upd. Sect. rfc 2136 */ #define ADCOUNT_BITS 0xFFFF /* Number of RRs in the Add Sect. rfc 2136 */ #define OPCODE_QUERY (0< / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_NULL NU16(10) /* a null RR - EXPERIMENTAL rfc 1035 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ADDRESS | 32 bit address ARPA Internet address | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PROTOCOL | | PROTOCOL: 8 bit IP protocol number +--+--+--+--+--+--+--+--+ | / / BIT MAP: variable length bit map. The bit map +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ must be a multiple of 8 bits long. */ #define TYPE_WKS NU16(11) /* a well known service description rfc 1035 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / PTRNAME / dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_PTR NU16(12) /* a domain name pointer rfc 1035 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / CPU / character-string +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / OS / character-string +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_HINFO NU16(13) /* host information rfc 1035 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / RMAILBX / character-string +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / EMAILBX / character-string +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_MINFO NU16(14) /* mailbox or mail list information rfc 1035 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFERENCE | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / EXCHANGE / dns formatted domain name / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_MX NU16(15) /* mail exchange rfc 1035 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TXT-DATA / one or more s (pascal string) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_TXT NU16(16) /* text strings rfc 1035 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / MBOX-DNAME / dns formatted domain name local-part. Can have '\'before . +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TXT-DNAME / dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_RP NU16(17) /* For Responsible Person rfc 1183 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SUBTYPE | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / HOSTNAME / dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_AFSDB NU16(18) /* AFS Data Base location rfc 1183 rfc 5864 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / PSDN-ADDRESS / pascal string (numeric only) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_X25 NU16(19) /* X.25 PSDN address rfc 1183 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / ISDN-ADDRESS / pascal string (IA5 allowed) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / SA / pascal string (numeric BCD) (OPTIONAL) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_ISDN NU16(20) /* ISDN address rfc 1183 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFERENCE | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / INTERMEDIATE-HOST / dns formatted domain name / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_RT NU16(21) /* Route Through rfc 1183 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / NSAP (in hex) / binary encoding of NSAP in hex +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ /* |--------------| | <-- IDP --> | |--------------|-------------------------------------| | AFI | IDI | <-- DSP --> | |-----|--------|-------------------------------------| | 47 | 0005 | DFI | AA |Rsvd | RD |Area | ID |Sel | |-----|--------|-----|----|-----|----|-----|----|----| octets | 1 | 2 | 1 | 3 | 2 | 2 | 2 | 6 | 1 | |-----|--------|-----|----|-----|----|-----|----|----| IDP Initial Domain Part AFI Authority and Format Identifier IDI Initial Domain Identifier DSP Domain Specific Part DFI DSP Format Identifier AA Administrative Authority Rsvd Reserved RD Routing Domain Identifier Area Area Identifier ID System Identifier SEL NSAP Selector */ #define TYPE_NSAP NU16(22) /* NSAP address, NSAP style A record rfc 1706 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / PTRNAME / dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_NSAP_PTR NU16(23) /* domain name pointer, NSAP style rfc 1348 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE COVERED | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ALGORITHM | LABELS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ORIGINAL TTL | 32 bit | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SIGNATURE EXPIRATION | 32 bit | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SIGNATURE INCEPTION | 32 bit | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | KEY TAG | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / SIGNER'S NAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / SIGNATURE / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_SIG NU16(24) /* for security signature rfc 4034 rfc 3755 rfc 2535 rfc 2536 rfc 2537 rfc 2931 rfc 3110 rfc 3008 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | FLAGS | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PROTOCOL | ALGORITHM | PROTOCOL: 8 bit, ALGORITHM: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / PUBLIC KEY / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ /* flags 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | A/C | Z | XT| Z | Z | NAMTYP| Z | Z | Z | Z | SIG | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ #define TYPE_KEY NU16(25) /* for security key rfc 4034 rfc 3755 rfc 2535 rfc 2536 rfc 2537 rfc 2539 rfc 3008 rfc 3110 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFERENCE | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / MAP822 / dns formatted domain name / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / MAPX400 / dns formatted domain name / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_PX NU16(26) /* X.400 mail mapping information rfc 2163 */ /* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / LONGITUDE / c-string (representing a real number) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / LATITUDE / c-string (representing a real number) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / ALTITUDE / c-string (representing a real number) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_GPOS NU16(27) /* Geographical Position rfc 1712 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ADDRESS | 32 bit address address | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ADDRESS | 32 bit address address | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ADDRESS | 32 bit address address | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ADDRESS | 32 bit address address | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_AAAA NU16(28) /* IP6 Address rfc 3596 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | VERSION | SIZE | VERSION: 8 bit int, SIZE: 8 bit int +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | HORIZ PRE | VERT PRE | HORIZ PRE: 8 bit int, VERT PRE: 8 bit int +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | LATITUDE | 32 bit integer | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | LONGITUDE | 32 bit integer | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ALTITUDE | 32 bit integer | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_LOC NU16(29) /* Location information rfc 1876 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / NEXT DOMAIN NAME / dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TYPE BIT MAPS / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_NXT NU16(30) /* Next Domain - OBSOLETE rfc 3755 rfc 2535 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / ENDPOINT IDENTIFIER / string of octets. (Binary encoding of the Identifier, / / meaningful only to the system utilizing it) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_EID NU16(31) /* Endpoint Identifier @note undocumented see draft-ietf-nimrod-dns-01.txt */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / NIMROD LOCATOR / variable string of octets. (Binary encoding of the Locator / / specified in the Nimrod protocol) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_NIMLOC NU16(32) /* Nimrod Locator @note undocumented see draft-ietf-nimrod-dns-01.txt */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PRIORITY | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | WEIGHT | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PORT | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TARGET / dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_SRV NU16(33) /* Server selection rfc 2782 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | FORMAT | | FORMAT: 8 bit +--+--+--+--+--+--+--+--+ | ADDRESS: c-string / ADDRESS / | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_ATMA NU16(34) /* ATM Address @note undocumented see ATM Name System V2.0 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ORDER | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFERENCE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / FLAGS / character-string (a-z0-9) can be empty +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / SERVICES / character-string (a-z0-9) can be empty +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / REGEXP / character-string +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / REPLACEMENT / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_NAPTR NU16(35) /* Naming Authority Pointer rfc 2915 rfc 2168 rfc 3403 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFERENCE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / EXCHANGER / dns formatted domain name / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_KX NU16(36) /* Key Exchanger rfc 2230 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | KEY TAG | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ALGORITHM | / +--+--+--+--+--+--+--+--+ / / / / CERTIFICATE OR CRL / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_CERT NU16(37) /* CERT rfc 4398 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFIX | / 8 bit unsigned integer +--+--+--+--+--+--+--+--+ / / / / ADDRESS SUFFIX / 0..16 octets / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / PREFIX NAME / uncompressed domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_A6 NU16(38) /* A6 rfc 3226 rfc 2874 rfc 6563 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / DNAME / dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_DNAME NU16(39) /* DNAME rfc 6672 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CODING | SUBCODING | CODING: 8 bit, SUBCODING: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | / c-string / DATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_SINK NU16(40) /* SINK @note undocumented see The Kitchen Sink Resource Record */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | OPTION-CODE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | OPTION-LENGTH | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / OPTION-DATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ /* * The TTL field of an OPT record has a different meaning: * * 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | VERSION | EXTENDED-RCODE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | Z |DO| +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_OPT NU16(41) /* edns0 flag rfc 6891 rfc 3225 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ADDRESSFAMILY | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFIX | N| AFDLENGTH | PREFIX: 8 bit unsigned binary coded, N: 1 bit, +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ ADFLENGTH: 7 bit unsigned / / / AFDPART / address family dependent | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_APL NU16(42) /* APL rfc 3123 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | KEY TAG | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ALGORITHM | DIGEST TYPE | ALGORITHM: 8 bit, DIGEST TYPE: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / DIGEST / digest dependent / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_DS NU16(43) /* Delegation Signer rfc 4034 rfc 3658 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ALGORITHM | FP TYPE | ALGORITHM: 8 bit, FP TYPE: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / FINGERPRINT / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_SSHFP NU16(44) /* SSH Key Fingerprint rfc 4255 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PRECEDENCE | GATEWAY TYPE | PRECEDENCE: 8 bit, GATEWAY TYPE: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ALGORITHM | | ALGORITHM: 8 bit +--+--+--+--+--+--+--+--+ | | GATEWAY | GATEWAY: 32 bit IPv4 / 128 bit IPv6 / uncompressed domain name / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / PUBLIC KEY / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_IPSECKEY NU16(45) /* IPSECKEY rfc 4025 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE COVERED | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ALGORITHM | LABELS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ORIGINAL TTL | 32 bit | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SIGNATURE EXPIRATION | 32 bit | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SIGNATURE INCEPTION | 32 bit | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | KEY TAG | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / SIGNER'S NAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / SIGNATURE / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_RRSIG NU16(46) /* RRSIG rfc 4034 rfc 3755 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / NEXT DOMAIN NAME / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TYPE NIT MAPS / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_NSEC NU16(47) /* NSEC rfc 4034 rfc 3755 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | FLAGS | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PROTOCOL | ALGORITHM | PROTOCOL: 8 bit, ALGORITHM: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / PUBLIC KEY / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_DNSKEY NU16(48) /* DNSKEY rfc 4034 rfc 3755 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | IDENTIFIER TYPE | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | DIGEST TYPE | / 8 bit +--+--+--+--+--+--+--+--+ / / DIGEST / dependent on the digest type +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_DHCID NU16(49) /* DHCID rfc 4701 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | HASH ALGORITHM | FLAGS | HASH ALGORITHM: 8 bit, FLAGS: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ITERATIONS | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SALT LENGTH | / 8 bit unsigned integer +--+--+--+--+--+--+--+--+ / / SALT / Can be zero length +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | HASH LENGTH | / 8 bit unsigned integer +--+--+--+--+--+--+--+--+ / / NEXT HASHED OWNER NAME / unmodified binary hash value. +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TYPE BIT MAPS / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ /* Flags 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ | |O| +-+-+-+-+-+-+-+-+ ^ OPT-OUT flag */ #define TYPE_NSEC3 NU16(50) /* NSEC3 rfc 5155 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | HASH ALGORITHM | FLAGS | HASH ALGORITHM: 8 bit, FLAGS: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ITERATIONS | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SALT LENGTH | / 8 bit unsigned integer +--+--+--+--+--+--+--+--+ / / SALT / Can be zero length +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_NSEC3PARAM NU16(51) /* NSEC3PARAM rfc 5155 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CERTIFICATE USAGE | SELECTOR | CERTIFICATE USAGE: 8 bit, SELECTOR: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / MATCHING TYPE | / +--+--+--+--+--+--+--+--+ / / / / CERTIFICATE ASSOCIATION DATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_TLSA NU16(52) /* TLSA rfc 6698 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | HIT LENGTH | PK ALGORITHM | HIT LENGTH: 8 bit unsigned integer, +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ PK ALGORITHM: 8 bit unsigned integer | PK LENGTH | PK LENTH: 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / HIT / binary value in network order / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / PUBLIC KEY / dependent on the type / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / RENDEZVOUS SERVERS / dns formatted domain name / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_HIP NU16(55) /* Host Identity Protocol rfc 5205 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / NINFO-DATA / one or more c-strings +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_NINFO NU16(56) /* NINFO @note undocumented see draft-reid-dnsext-zs-01.txt */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | FLAGS | 16 bit: (value 0) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PROTOCOL | ALGORITHM | PROTOCOL: 8 bit (value 1), ALGORITHM: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / PUBLIC KEY / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_RKEY NU16(57) /* RKEY @note undocumented see draft-reid-dnsext-rkey-00.txt */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TALINK START/PREVIOUS / dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TALINK NEXT/END / dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_TALINK NU16(58) /* Trust Anchor LINK @note undocumented see talink-completed-template */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | KEY TAG | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ALGORITHM | DIGEST TYPE | ALGORITHM: 8 bit, DIGEST TYPE: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / DIGEST / digest dependent / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_CDS NU16(59) /* Child DS rfc 7344 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | FLAGS | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PROTOCOL | ALGORITHM | PROTOCOL: 8 bit, ALGORITHM: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / PUBLIC KEY / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_CDNSKEY NU16(60) /* DNSKEY(s) the Child wants reflected in DS rfc 7344 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / OPENPGP PUBLIC KEY / single OpenPGP public key as defined in Section 5.5.1.1 of [RFC4880]. / / without ASCII armor or base64 encoding / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_OPENPGPKEY NU16(61) /* OpenPGP Key @note undocumented see draft-ietf-dane-openpgpkey-03 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | SOA SERIAL | 32 bit | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | FLAGS | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TYPE BIT MAP / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_CSYNC NU16(62) /* Child-To-Parent Synchronization rfc 7477 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / SPF-DATA / one or more c-strings +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_SPF NU16(99) /* SPF rfc7208 */ #define TYPE_UINFO NU16(100) /* IANA-Reserved */ #define TYPE_UID NU16(101) /* IANA-Reserved */ #define TYPE_GID NU16(102) /* IANA-Reserved */ #define TYPE_UNSPEC NU16(103) /* IANA-Reserved */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFERENCE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | | NODEID | 64 bit | | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_NID NU16(104) /* NODE ID rfc 6742 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFERENCE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | LOCATOR32 | 32 bit unsigned integer | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_L32 NU16(105) /* LOCATOR 32 rfc 6742 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFERENCE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | | LOCATOR64 | 64 bit unsigned integer | | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_L64 NU16(106) /* LOCATOR 64 rfc 6742 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFERENCE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / FQDN / dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_LP NU16(107) /* LOCATOR POINTER rfc 6742 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | | EUI-48 ADDRESS | 48 bit (MUST be represented as six two-digit hexadecimal | | numbers separated by hyphens) +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_EUI48 NU16(108) /* EUI-48 address rfc 7043 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | | EUI-64 ADDRESS | 64 bit (MUST be represented as six two-digit hexadecimal | | numbers separated by hyphens) | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_EUI64 NU16(109) /* EUI-64 address rfc 7043 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / ALGORITHM / algorithm in dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | INCEPTION | 32 bit unsigned integer | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | EXPIRATION | 32 bit unsigned integer | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | MODE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ERROR | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | KEY SIZE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / KEY DATA / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | OTHER SIZE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / OTHER DATA / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_TKEY NU16(249) /* Transaction Key rfc 2930 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / ALGORITHM / algorithm in dns formatted domain name +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | | INCEPTION | 48 bit unsigned integer | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | FUDGE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | MAC SIZE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / MAC / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ORIGINAL ID | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ERROR | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | OTHER SIZE | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / OTHER DATA / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_TSIG NU16(250) /* Transaction Signature rfc 2845 */ #define TYPE_IXFR NU16(251) /* Incremental Transfer rfc 1995 */ #define TYPE_AXFR NU16(252) /* Transfer of an entire zone rfc 1035 rfc 5936 */ #define TYPE_MAILB NU16(253) /* A request for mailbox-related records (MB, MG or MR) rfc 1035 */ #define TYPE_MAILA NU16(254) /* A request for mail agent RRs (Obsolete - see MX) rfc 1035 */ #define TYPE_ANY NU16(255) /* a request for all records rfc 1035 rfc 6895 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PRIORITY | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | WEIGHT | 16 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / TARGET / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_URI NU16(256) /* URI @note undocumented see draft-faltstrom-uri-14 */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | FLAGS | TAG LENGTH | FLAGS: 8 bit, TAG LENGTH: 8 bit unsigned integer +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TAG / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / VALUE / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_CAA NU16(257) /* Certification Authority Authorization rfc 6844 */ #define TYPE_AVC NU16(258) // Visibility and control, no rfc yet /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | KEY TAG | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ALGORITHM | DIGEST TYPE | ALGORITHM: 8 bit, DIGEST TYPE: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / DIGEST / digest dependent / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_TA NU16(32768) /* DNSSEC Trust Authorities @note undocumented see Deploying DNSSEC Without a Signed Root */ /* 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | KEY TAG | 16 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ALGORITHM | DIGEST TYPE | ALGORITHM: 8 bit, DIGEST TYPE: 8 bit +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / / / DIGEST / digest dependent / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ */ #define TYPE_DLV NU16(32769) /* DNSSEC Lookaside Validation rfc 4431 */ #define TYPE_PRIVATE_FIRST NU16(65280) #define TYPE_PRIVATE_LAST NU16(65534) #define HOST_CLASS_IN 1 /* the Internet rfc 1025 */ #define CLASS_IN NU16(HOST_CLASS_IN) /* the Internet rfc 1025 */ #define CLASS_CS NU16(2) /* CSNET class rfc 1025 */ #define CLASS_CH NU16(3) /* the CHAOS class rfc 1025 */ #define CLASS_HS NU16(4) /* Hesiod rfc 1025 */ #define CLASS_CTRL NU16(0x2A) /* @note Yadifa controller class */ #if HAS_WHOIS #define CLASS_WHOIS NU16(0x2B) /* @note WHOIS class */ #endif // HAS_WHOIS #define CLASS_NONE NU16(254) /* rfc 2136 rfc 2136 */ #define CLASS_ANY NU16(255) /* rfc 1035 QCLASS ONLY rfc 1025 */ /* -----------------------------------------------------------------*/ #define AXFR_TSIG_PERIOD 100 /* -----------------------------------------------------------------*/ #ifdef WORDS_BIGENDIAN #define DNSKEY_FLAG_KEYSIGNINGKEY 0x0001 #define DNSKEY_FLAG_ZONEKEY 0x0100 #else #define DNSKEY_FLAG_KEYSIGNINGKEY 0x0100 #define DNSKEY_FLAG_ZONEKEY 0x0001 #endif #define DNSKEY_PROTOCOL_FIELD 3 /* MUST be this */ #define DNSKEY_ALGORITHM_RSAMD5 1 // DEPRECATED #define DNSKEY_ALGORITHM_DIFFIE_HELLMAN 2 // NOT USED #define DNSKEY_ALGORITHM_DSASHA1 3 #define DNSKEY_ALGORITHM_RSASHA1 5 #define DNSKEY_ALGORITHM_DSASHA1_NSEC3 6 #define DNSKEY_ALGORITHM_RSASHA1_NSEC3 7 #define DNSKEY_ALGORITHM_RSASHA256_NSEC3 8 /* RFC 5702 */ #define DNSKEY_ALGORITHM_RSASHA512_NSEC3 10 /* RFC 5702 */ #define DNSKEY_ALGORITHM_GOST 12 /* RFC 5933, not supported by YADIFA */ #define DNSKEY_ALGORITHM_ECDSAP256SHA256 13 /* RFC 6605 */ #define DNSKEY_ALGORITHM_ECDSAP384SHA384 14 /* RFC 6605 */ #define DNSKEY_ALGORITHM_ED25519 15 /* RFC 8080 */ #define DNSKEY_ALGORITHM_ED448 16 /* RFC 8080 */ #define DS_DIGEST_SHA1 1 #define DS_DIGEST_SHA256 2 #define NSEC3_FLAGS_OPTOUT 1 /* */ #define DNSKEY_ALGORITHM_RSAMD5_NAME "RSAMD5" /* RFC 4034 */ // RSA // DEPRECATED #define DNSKEY_ALGORITHM_DIFFIE_HELLMAN_NAME "DH" /* RFC 2539 */ // NOT USED #define DNSKEY_ALGORITHM_DSASHA1_NAME "DSA" /* RFC 3755 */ #define DNSKEY_ALGORITHM_RSASHA1_NAME "RSASHA1" /* RFC 4034 */ #define DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME "DSA-NSEC3-SHA1" /* RFC 5155 */ // NSEC3DSA" #define DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME "RSASHA1-NSEC3-SHA1" /* RFC 5155 */ // NSEC3RSASHA1 #define DNSKEY_ALGORITHM_RSASHA256_NSEC3_NAME "RSASHA256" /* RFC 5702 */ #define DNSKEY_ALGORITHM_RSASHA512_NSEC3_NAME "RSASHA512" /* RFC 5702 */ #define DNSKEY_ALGORITHM_GOST_NAME "ECC-GOST" // GOST /* RFC 5933 */ // not supported by YADIFA #define DNSKEY_ALGORITHM_ECDSAP256SHA256_NAME "ECDSAP256SHA256" /* RFC 6605 */ #define DNSKEY_ALGORITHM_ECDSAP384SHA384_NAME "ECDSAP384SHA384" /* RFC 6605 */ #define DNSKEY_ALGORITHM_ED25519_NAME "ED25519" /* RFC 8080 */ #define DNSKEY_ALGORITHM_ED448_NAME "ED448" /* RFC 8080 */ #define DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME2 "NSEC3DSA" #define DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME2 "NSEC3RSASHA1" #ifdef DNSKEY_ALGORITHM_DUMMY #define DNSKEY_ALGORITHM_DUMMY_NAME "DUMMY" #endif #define IS_TYPE_PRIVATE(t) (((t) >= 65280) && ( (t) <= 65534)) #define IS_TYPE_NPRIVATE(t) ((NU16(t) >= 65280) && ( NU16(t) <= 65534)) /* * STRUCTS */ #define EDNS0_RECORD_SIZE 11 /* rfc 2671 */ struct edns0_data { u8 domain_name; /* must be empty */ u16 opt; u16 payload_size; u8 extended_rcode; /* extended rcode and flags */ u8 version; /* extended rcode and flags */ u8 z_bits; /* extended rcode and flags */ u8 option_code; u16 option_length; }; typedef struct edns0_data edns0_data; /* - */ typedef struct value_name_table value_name_table; struct value_name_table { u32 id; char *data; }; typedef value_name_table class_table; typedef value_name_table type_table; typedef value_name_table dnssec_algo_table; typedef struct message_header message_header; struct message_header { u16 id; u8 opcode; u8 flags; u16 qdcount; u16 ancount; u16 nscount; u16 arcount; }; /* ------------------------------------------------------------ */ #define CLASS_IN_NAME "IN" #define CLASS_CS_NAME "CS" #define CLASS_CH_NAME "CH" #define CLASS_HS_NAME "HS" #define CLASS_CTRL_NAME "CTRL" /* @note YADIFA's personal class, maybe one day in a RFC */ #if HAS_WHOIS #define CLASS_WHOIS_NAME "WHOIS" #endif // HAS_WHOIS #define CLASS_NONE_NAME "NONE" #define CLASS_ANY_NAME "ANY" extern const class_table qclass[]; #define TYPE_A_NAME "A" #define TYPE_NS_NAME "NS" #define TYPE_MD_NAME "MD" #define TYPE_MF_NAME "MF" #define TYPE_CNAME_NAME "CNAME" #define TYPE_SOA_NAME "SOA" #define TYPE_MB_NAME "MB" #define TYPE_MG_NAME "MG" #define TYPE_MR_NAME "MR" #define TYPE_NULL_NAME "NULL" #define TYPE_WKS_NAME "WKS" #define TYPE_PTR_NAME "PTR" #define TYPE_HINFO_NAME "HINFO" #define TYPE_MINFO_NAME "MINFO" #define TYPE_MX_NAME "MX" #define TYPE_TXT_NAME "TXT" #define TYPE_RP_NAME "RP" #define TYPE_AFSDB_NAME "AFSDB" #define TYPE_X25_NAME "X25" #define TYPE_ISDN_NAME "ISDN" #define TYPE_RT_NAME "RT" #define TYPE_NSAP_NAME "NSAP" #define TYPE_NSAP_PTR_NAME "NSAP-PTR" #define TYPE_SIG_NAME "SIG" #define TYPE_KEY_NAME "KEY" #define TYPE_PX_NAME "PX" #define TYPE_GPOS_NAME "GPOS" #define TYPE_AAAA_NAME "AAAA" #define TYPE_LOC_NAME "LOC" #define TYPE_NXT_NAME "NXT" #define TYPE_EID_NAME "EID" /* @note undocumented see draft-lewis-dns-undocumented-types-01 */ #define TYPE_NIMLOC_NAME "NIMLOC" /* @note undocumented see draft-lewis-dns-undocumented-types-01 */ #define TYPE_SRV_NAME "SRV" #define TYPE_ATMA_NAME "ATMA" #define TYPE_NAPTR_NAME "NAPTR" #define TYPE_KX_NAME "KX" #define TYPE_CERT_NAME "CERT" #define TYPE_A6_NAME "A6" #define TYPE_DNAME_NAME "DNAME" #define TYPE_SINK_NAME "SINK" /* @note undocumented see draft-lewis-dns-undocumented-types-01 */ #define TYPE_OPT_NAME "OPT" #define TYPE_APL_NAME "APL" #define TYPE_DS_NAME "DS" #define TYPE_SSHFP_NAME "SSHFP" #define TYPE_IPSECKEY_NAME "IPSECKEY" #define TYPE_RRSIG_NAME "RRSIG" #define TYPE_NSEC_NAME "NSEC" #define TYPE_DNSKEY_NAME "DNSKEY" #define TYPE_DHCID_NAME "DHCID" #define TYPE_NSEC3_NAME "NSEC3" #define TYPE_NSEC3PARAM_NAME "NSEC3PARAM" #define TYPE_TLSA_NAME "TLSA" #define TYPE_HIP_NAME "HIP" #define TYPE_NINFO_NAME "NINFO" /* @note undocumented see draft-lewis-dns-undocumented-types-01 */ #define TYPE_RKEY_NAME "RKEY" /* @note undocumented see draft-lewis-dns-undocumented-types-01 */ #define TYPE_TALINK_NAME "TALINK" /* @note undocumented see draft-lewis-dns-undocumented-types-01 */ #define TYPE_CDS_NAME "CDS" #define TYPE_CDNSKEY_NAME "CDNSKEY" #define TYPE_OPENPGPKEY_NAME "OPENPGPKEY" #define TYPE_CSYNC_NAME "CSYNC" #define TYPE_SPF_NAME "SPF" #define TYPE_UINFO_NAME "UINFO" #define TYPE_UID_NAME "UID" #define TYPE_GID_NAME "GID" #define TYPE_UNSPEC_NAME "UNSPEC" #define TYPE_NID_NAME "NID" #define TYPE_L32_NAME "L32" #define TYPE_L64_NAME "L64" #define TYPE_LP_NAME "LP" #define TYPE_EUI48_NAME "EUI48" #define TYPE_EUI64_NAME "EUI64" #define TYPE_TKEY_NAME "TKEY" #define TYPE_TSIG_NAME "TSIG" #define TYPE_IXFR_NAME "IXFR" #define TYPE_AXFR_NAME "AXFR" #define TYPE_MAILB_NAME "MAILB" #define TYPE_MAILA_NAME "MAILA" #define TYPE_ANY_NAME "ANY" /** @note type ANY's string was set to '*' ? * Setting this to anything else will break * dnsformat:358 */ #define TYPE_URI_NAME "URI" /* @note undocumented see draft-lewis-dns-undocumented-types-01 */ #define TYPE_CAA_NAME "CAA" /* @note undocumented see draft-lewis-dns-undocumented-types-01 */ #define TYPE_AVC_NAME "AVC" /* visibility and control */ #define TYPE_TA_NAME "TA" /* @note undocumented see draft-lewis-dns-undocumented-types-01 */ #define TYPE_DLV_NAME "DLV" #define OPT_NSID 3 // the option value for NSID extern const type_table qtype[]; /** * Static asciiz representation of a dns class * * @param c * @return the c-string */ const char *dns_class_get_name(u16 c); /** * Static asciiz representation of a dns type * * @param c * @return the c-string */ const char *dns_type_get_name(u16 t); /** \brief Get the numeric value of a class (network order) from its name * * @param[in] src the name of the class * @param[out] dst value of the class, network order * * @retval OK * @retval NOK */ int dns_class_from_name(const char *src, u16 *dst); /** \brief Get the numeric value of a class (network order) from its name * Case insensitive * * @param[in] src the name of the class (case insensitive) * @param[out] dst value of the class, network order * * @retval OK * @retval NOK */ int dns_class_from_case_name(const char *src, u16 *dst); /** \brief Get the numeric value of a type (network order) from its name * * @param[in] src the name of the type * @param[out] dst value of the type, network order * * @retval OK * @retval NOK */ int dns_type_from_name(const char *src, u16 *dst); /** \brief Get the numeric value of a type (network order) from its name * Case insensitive * * @param[in] src the name of the type (case insensitive) * @param[out] dst value of the type, network order * * @retval OK * @retval NOK */ int dns_type_from_case_name(const char *src, u16 *dst); int dns_type_from_case_name_length(const char *src, int src_len, u16 *dst); /** * @brief Case-insensitive search for the name in the table, returns the value * * @param table the name->value table * @param name the name to look for * @param out_value a pointer to an u32 that will hold the value in case of a match * * @return SUCCESS iff the name was matched */ ya_result value_name_table_get_value_from_casename(const value_name_table *table, const char *name, u32 *out_value); ya_result value_name_table_get_name_from_value(const value_name_table *table, u32 value, const char** out_name); const char* dns_encryption_algorithm_get_name(u16 d); int dns_encryption_algorithm_from_name(const char *src, u8 *dst); int dns_encryption_algorithm_from_case_name(const char *src, u8 *dst); /** * @brief Static asciiz representation of a dns opcode * * @param c * * @return the c-string */ const char *dns_message_opcode_get_name(u16 c); /** * @brief Static asciiz representation of a dns rcode * * @param c * * @return the c-string */ const char *dns_message_rcode_get_name(u16 c); #if DNSCORE_HAS_NSID_SUPPORT #ifndef DNSCORE_RFC_C extern u32 edns0_record_size; extern u8 *edns0_rdatasize_nsid_option_wire; extern u32 edns0_rdatasize_nsid_option_wire_size; #endif void edns0_set_nsid(u8 *bytes, u16 size); #endif ya_result protocol_name_to_id(const char* name, int *out_port); ya_result protocol_id_to_name(int proto, char *name, size_t name_len); ya_result server_name_to_port(const char* name, int *out_value); ya_result server_port_to_name(int port, char *name, size_t name_len); /* * SOA */ ya_result rr_soa_get_serial(const u8* rdata, u16 rdata_size, u32* out_serial); ya_result rr_soa_increase_serial(u8* rdata, u16 rdata_size, u32 increment); ya_result rr_soa_set_serial(u8* rdata, u16 rdata_size, u32 increment); ya_result rr_soa_get_minimumttl(const u8* rdata, u16 rdata_size, s32* out_minimum_ttl); static inline u16 rrsig_get_type_covered_from_rdata(const void *rdata, u16 rdata_size) { u16 tc = TYPE_NONE; if(rdata_size >= 2) { tc = GET_U16_AT_P(rdata); } return tc; } static inline u8 rrsig_get_algorithm_from_rdata(const void *rdata, u16 rdata_size) { u8 a = 0; if(rdata_size >= 3) { a = ((const u8*)rdata)[2]; } return a; } static inline u8 rrsig_get_labels_from_rdata(const void *rdata, u16 rdata_size) { u8 l = 0; if(rdata_size >= 4) { l = ((const u8*)rdata)[3]; } return l; } static inline s32 rrsig_get_original_ttl_from_rdata_ne(const void *rdata, u16 rdata_size) { s32 ottl = 0; if(rdata_size >= 8) { ottl = GET_U32_AT(((const u8*)rdata)[4]); } return ottl; } static inline s32 rrsig_get_original_ttl_from_rdata(const void *rdata, u16 rdata_size) { s32 ttl_ne = rrsig_get_original_ttl_from_rdata_ne(rdata, rdata_size); return ntohl(ttl_ne); } static inline s32 rrsig_get_valid_until_from_rdata(const void *rdata, u16 rdata_size) { s32 t = 0; if(rdata_size >= RRSIG_RDATA_HEADER_LEN) { t = ntohl(GET_U32_AT(((const u8*)rdata)[8])); } return t; } static inline s32 rrsig_get_valid_from_from_rdata(const void *rdata, u16 rdata_size) { s32 t = 0; if(rdata_size >= RRSIG_RDATA_HEADER_LEN) { t = ntohl(GET_U32_AT(((const u8*)rdata)[12])); } return t; } static inline u16 rrsig_get_key_tag_from_rdata(const void *rdata, u16 rdata_size) { u16 tag = 0; if(rdata_size >= RRSIG_RDATA_HEADER_LEN) { tag = ntohs(GET_U16_AT(((const u8*)rdata)[16])); } return tag; } static inline const u8* rrsig_get_signer_name_from_rdata(const void *rdata, u16 rdata_size) { const u8 *signer_name = NULL; if(rdata_size >= RRSIG_RDATA_HEADER_LEN) { signer_name = &((const u8*)rdata)[18]; } return signer_name; } #endif /* RFC_H_ */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/serial.h0000644000000000000000000000013214505005532023251 xustar000000000000000030 mtime=1695812442.021976158 30 atime=1695812445.787030082 30 ctime=1695812494.354725669 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/serial.h0000664000374500037450000000643114505005532023217 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore * @ingroup dnscore * @brief serial arithmetic * * @{ * *----------------------------------------------------------------------------*/ #ifndef _SERIAL_H #define _SERIAL_H #include #ifdef __cplusplus extern "C" { #endif /* * SERIAL ARITHMETIC */ /* * Returns TRUE if a >,<,>=,<= b */ /** * * Returns TRUE iff a > b in serial arithmetic, else FALSE * * @param a * @param b * @return a > b */ bool serial_gt(u32 a, u32 b); /** * * Returns TRUE iff a < b in serial arithmetic, else FALSE * * @param a * @param b * @return a < b */ bool serial_lt(u32 a, u32 b); /** * * Returns TRUE iff a >= b in serial arithmetic, else FALSE * * @param a * @param b * @return a >= b */ bool serial_ge(u32 a, u32 b); /** * * Returns TRUE iff a <= b in serial arithmetic, else FALSE * * @param a * @param b * @return a <= b */ bool serial_le(u32 a, u32 b); static inline bool serial_eq(u32 a, u32 b) { return a == b; } static inline u32 serial_max(u32 a, u32 b) { return serial_ge(a,b) ? a : b; } static inline u32 serial_min(u32 a, u32 b) { return serial_le(a,b) ? a : b; } #ifdef __cplusplus } #endif #endif /* _SERIAL_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/server-setup.h0000644000000000000000000000013214505005532024436 xustar000000000000000030 mtime=1695812442.003975901 30 atime=1695812445.787030082 30 ctime=1695812494.356725697 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/server-setup.h0000664000374500037450000000436414505005532024407 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #define SETUP_CORE_LIMITS 1 #define SETUP_ROOT_CHANGE 2 #define SETUP_ID_CHANGE 4 #define SETUP_CREATE_PID_FILE 8 void server_setup_daemon_go(); ya_result server_setup_env(pid_t *pid, char** pid_file_pathp, uid_t uid, gid_t gid, u32 setup_flags); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/service.h0000644000000000000000000000013114505005532023431 xustar000000000000000030 mtime=1695812442.081977018 29 atime=1695812445.78903011 30 ctime=1695812494.358725726 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/service.h0000664000374500037450000002527014505005532023402 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #ifndef SERVICE_H #define SERVICE_H #include #include #include #ifdef __cplusplus extern "C" { #endif #ifdef WIN32 #undef SERVICE_START #undef SERVICE_STOP #endif #define SERVICE_OFF 0 #define SERVICE_START 1 #define SERVICE_SERVICING 2 #define SERVICE_STOP 4 #define SERVICE_STOPPING 8 #define SERVICE_RECONFIGURE 16 // tells the service should ensure its configuration matches the current one and act accordingly #define SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT 0 // this macro checks the function succeeded, // elses sends a general shutdown and returns // meant to be used in a service for the *_init() calls #define SHUTDOWN_RETURN_ON_FAIL(function__)\ { int err; if(FAIL((err = function__()))) { \ log_err( #function__ ": failed with %r", err); \ dnscore_shutdown(); \ return err; \ } } #define SHUTDOWN_RETURN_ON_FAIL_WITH_ARGS(function__,...)\ { int err; if(FAIL((err = function__(__VA_ARGS__)))) { \ log_err( #function__ "(" #__VA_ARGS__ "): failed with %r", err); \ dnscore_shutdown(); \ return err; \ } } struct service_s; struct service_worker_s; typedef int service_main(struct service_worker_s *); typedef void service_wakeup(struct service_s *); #if SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT #define UNINITIALIZED_SERVICE {MUTEX_INITIALIZER, COND_INITIALIZER, NULL, NULL, NULL, NULL, 0, 0, NULL, TRUE} #else #define UNINITIALIZED_SERVICE {MUTEX_INITIALIZER, COND_INITIALIZER, NULL, NULL, NULL, NULL, 0, NULL, TRUE} #endif #define SRVCWRKR_TAG 0x524b525743565253 struct service_worker_s { struct service_s *service; mutex_t lock; thread_t tid; u32 worker_index; #if SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT volatile u32 last_seen_alive; #endif volatile int return_code; volatile u8 flags; }; struct service_s { mutex_t wait_lock; cond_t wait_cond; service_main *entry_point; service_wakeup *wakeup_all_workers; // so they may act char *name; struct service_worker_s *worker; u32 worker_count; #if SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT volatile u32 last_seen_alive; #endif void *args; // private data for the service (initialised to NULL) bool _not_initialised; }; /** * Initialises service with an entry point, a name, and one worker * No threads are started yet after this call. * * This is basically calling service_init_ex(desc, entry_point, name, 1); * * @param desc the service * @param entry_point the function of the service, it must be of the type service_main * @param name the name of the service * @return an error code */ int service_init(struct service_s *desc, service_main *entry_point, const char* name); /** * Initialises service with an entry point, a name, and a number of workers * Each worker will know its index (from 0 to count-1). * No threads are started yet after this call. * * @param desc the service * @param entry_point the function of the service, it must be of the type service_main * @param name the name of the service * @param count the number of workers for the service * @return an error code */ int service_init_ex(struct service_s *desc, service_main *entry_point, const char* name, u32 count); /** * Initialises service with an entry point, a name, and a number of workers * Each worker will know its index (from 0 to count-1). * No threads are started yet after this call. * * @param desc the service * @param entry_point the function of the service, it must be of the type service_main * @param wakeup_function a function that will wakup-up all the workers of the service (e.g. so they can notice a reconfiguration or shutdown) * @param name the name of the service * @param count the number of workers for the service * @return an error code */ int service_init_ex2(struct service_s *desc, service_main *entry_point, service_wakeup *wakeup_function, const char* name, u32 count); /** * Set service args. * * @param desc a pointer to the service * @param args a pointer to the args */ void service_args_set(struct service_s *desc, void *args); /** * Get service args. * * @param desc a pointer to the service * * @return a pointer to the args */ void* service_args_get(struct service_s *desc); /** * Stops then waits for all workers of the service. * Then destroy the service and release its content. * * @param desc the service * @return an error code */ int service_finalize(struct service_s *desc); /** * Starts all workers of the service * If a worker is already running, it is left alone with undefined results. * A service should be fully stopped and waited on before being started again. * * @param desc the service * @return an error code */ int service_start(struct service_s *desc); /** * Starts a service and waits for its end. * This is meant for services with only one thread. * If used with such a service, no new thread will be started and the service * will be run on the current thread. * It is useful when you have a model where the main thread of the program * could change behaviour with an option. * ie: the server service (nudge nudge, wink wink ...) * * @param desc * @return */ int service_start_and_wait(struct service_s *desc); /** * Set the status of all workers of the service to "STOP" and sends SIGUSR2 to * each of them. * * The signal is meant to interrupt blocking IOs and the worker should notice * it 'in time' and finish. * * @param desc the service * @return an error code */ int service_stop(struct service_s *desc); /** * Set the status of all workers of the service to "RECONFIGURE" and sends SIGUSR2 to * each of them. * * The signal is meant to interrupt blocking IOs and the worker should notice * it 'in time' and finish. * * @param desc the service * * @return an error code */ int service_reconfigure(struct service_s *desc); /** * Waits for all threads of the service to be stopped. * * @param desc the service * @return an error code */ int service_wait(struct service_s *desc); /** * Only to be called by the worker of the service itself when it has started. * Calling it is not mandatory but give more accuracy to the status of the service. * * @param worker the worker calling this function */ int service_set_servicing(struct service_worker_s *worker); /** * Only to be called by the worker of the service itself when it is stopping. * Calling it is not mandatory but give more accuracy to the status of the service. * * @param worker the worker calling this function */ int service_set_stopping(struct service_worker_s *worker); /** * Only to be called by the worker of the service itself when it has reconfigured. * Calling it is not mandatory but give more accuracy to the status of the service. * * @param worker the worker calling this function */ int service_clear_reconfigure(struct service_worker_s *worker); int service_should_run(struct service_worker_s *worker); int service_should_reconfigure(struct service_worker_s *worker); int service_should_reconfigure_or_stop(struct service_worker_s *worker); /** * Returns TRUE if all the workers of the service have notified they are running * * @param desc the service * @return TRUE iff all the workers of the service have notified they are running */ bool service_servicing(struct service_s *desc); /** * Returns TRUE if none of the workers of the service are running * * @param desc the service * @return TRUE iff none of the workers of the service are running */ bool service_stopped(struct service_s *desc); /** * Waits until all workers have notified they were servicing. * Calling this on a service that does not call service_set_servicing will * potentially wait forever (or until the program is shutting down). * * @param desc the service * @return an error code */ ya_result service_wait_servicing(struct service_s *desc); bool service_initialised(struct service_s *desc); static inline bool service_started(struct service_s *desc) { return !service_stopped(desc); } /** * check that all services/workers are alive * logs warnings when blocked-looking workers/services are found */ int service_check_all_alive(); /** * Appends all services references to the array. * * Services are supposed to be defined statically. * Their reference will never point to an unmapped space. * * @param services a pointer to the ptr_vector to append the services to * @return the number of services added to the vector */ int service_get_all(ptr_vector *services); struct service_worker_s *service_worker_get_sibling(const struct service_worker_s *worker, u32 idx); struct service_worker_s *service_get_worker(const struct service_s *service, u32 idx); void service_stop_all(); void service_start_all(); #ifdef __cplusplus } #endif #endif /* SERVICE_H */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/shared-heap.h0000644000000000000000000000013014505005532024151 xustar000000000000000029 mtime=1695812442.07097686 29 atime=1695812445.78903011 30 ctime=1695812494.360725755 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/shared-heap.h0000664000374500037450000000605314505005532024121 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include struct shared_heap_ctx; typedef struct shared_heap_ctx shared_heap_ctx; void shared_heap_check_ptr(u8 id, void *ptr); void shared_heap_check(u8 id); ya_result shared_heap_init(); void shared_heap_finalize(); ya_result shared_heap_create(size_t size); void shared_heap_destroy(u8 id); void *shared_heap_alloc_from_ctx(struct shared_heap_ctx *ctx, size_t size); void *shared_heap_try_alloc_from_ctx(struct shared_heap_ctx *ctx, size_t size); void shared_heap_free_from_ctx(struct shared_heap_ctx *ctx, void *ptr); void *shared_heap_realloc_from_ctx(struct shared_heap_ctx *ctx, void *ptr, size_t new_size); void *shared_heap_alloc(u8 id, size_t size); void *shared_heap_try_alloc(u8 id, size_t size); void shared_heap_free(void *ptr); void *shared_heap_realloc(u8 id, void *ptr, size_t new_size); struct shared_heap_ctx *shared_heap_context_from_id(u8 id); void* shared_heap_wait_alloc(u8 id, size_t size); void shared_heap_count_allocated(u8 id, size_t* totalp, size_t* countp); void shared_heap_print_map(u8 id, size_t* totalp, size_t* countp); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/shared-circular-buffer.h0000644000000000000000000000013214505005531026310 xustar000000000000000030 mtime=1695812441.988975686 30 atime=1695812445.786030067 30 ctime=1695812494.362725783 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/shared-circular-buffer.h0000664000374500037450000000765314505005531026265 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once struct shared_circular_buffer; struct shared_circular_buffer_slot { u8 state; // allocated (building) / forward / ready / ready-forward u8 data[/*L1_DATA_LINE_SIZE - 1*/63]; }; typedef struct shared_circular_buffer shared_circular_buffer; typedef struct shared_circular_buffer_slot shared_circular_buffer_slot; struct shared_circular_buffer* shared_circular_buffer_create_ex(u8 log_2_buffer_size, u32 additional_space_bytes); struct shared_circular_buffer* shared_circular_buffer_create(u8 log_2_buffer_size); void shared_circular_buffer_destroy(struct shared_circular_buffer* buffer); struct shared_circular_buffer_slot* shared_circular_buffer_prepare_enqueue(struct shared_circular_buffer* buffer); struct shared_circular_buffer_slot* shared_circular_buffer_try_prepare_enqueue(struct shared_circular_buffer* buffer); void shared_circular_buffer_commit_enqueue(struct shared_circular_buffer* buffer, struct shared_circular_buffer_slot *slot); struct shared_circular_buffer_slot* shared_circular_buffer_prepare_dequeue(struct shared_circular_buffer* buffer); struct shared_circular_buffer_slot* shared_circular_buffer_prepare_dequeue_with_timeout(struct shared_circular_buffer* buffer, s64 timeoutus); void shared_circular_buffer_commit_dequeue(struct shared_circular_buffer* buffer); size_t shared_circular_buffer_get_index(struct shared_circular_buffer* buffer, struct shared_circular_buffer_slot* slot); bool shared_circular_buffer_empty(struct shared_circular_buffer* buffer); size_t shared_circular_buffer_size(struct shared_circular_buffer* buffer); size_t shared_circular_buffer_avail(struct shared_circular_buffer* buffer); void shared_circular_buffer_lock(struct shared_circular_buffer* buffer); void shared_circular_buffer_unlock(struct shared_circular_buffer* buffer); u8 *shared_circular_buffer_additional_space_ptr(struct shared_circular_buffer* buffer); size_t shared_circular_buffer_additional_space_size(struct shared_circular_buffer* buffer); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/shared-heap-bytearray-output-stream.h0000644000000000000000000000013214505005532031002 xustar000000000000000030 mtime=1695812442.018976115 30 atime=1695812445.787030082 30 ctime=1695812494.365725826 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/shared-heap-bytearray-output-stream.h0000664000374500037450000000663114505005532030752 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif /* * The buffer will be freed (free) on close. */ #define SHARED_HEAP_OWNED 1 /* * The buffer's size can be changed. */ #define SHARED_HEAP_DYNAMIC 2 #define SHARED_HEAP_ZALLOC_CONTEXT 4 typedef char shared_heap_output_stream_context[sizeof(void*) + 10]; void shared_heap_output_stream_init(output_stream *out_stream, u8 id, u8 *array, u32 size); void shared_heap_output_stream_init_ex(output_stream *out_stream, u8 id, u8 *array, u32 size, u8 flags); /* * most of shared_heap_output_stream usages function-enclosed : init, work on, close * this variant of initialisation avoids an malloc */ void shared_heap_output_stream_init_ex_static(output_stream* out_stream, u8 id, u8* array,u32 size, u8 flags, shared_heap_output_stream_context *ctx); void shared_heap_output_stream_reset(output_stream *out_stream); u32 shared_heap_output_stream_size(output_stream *out_stream); u8 *shared_heap_output_stream_buffer(output_stream *out_stream); u32 shared_heap_output_stream_buffer_size(output_stream *stream); u8 *shared_heap_output_stream_detach(output_stream *out_stream); void shared_heap_output_stream_set(output_stream* out_stream, u8 *buffer, u32 buffer_size, bool owned); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/signals.h0000644000000000000000000000013214505005532023432 xustar000000000000000030 mtime=1695812442.096977232 30 atime=1695812445.790030125 30 ctime=1695812494.367725855 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/signals.h0000664000374500037450000000507414505005532023402 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #pragma once /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include #ifdef WIN32 #include #endif #include #include #include typedef void (*signal_handler_cb)(u8 signum); // initalises and starts the handler ya_result signal_handler_init(); signal_handler_cb signal_handler_get(u8 signum); void signal_handler_set(u8 signum, signal_handler_cb handler); // stop the handler void signal_handler_stop(); // clears remaining data void signal_handler_finalize(); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/simple-http-server.h0000644000000000000000000000013114505005532025543 xustar000000000000000029 mtime=1695812442.03397633 30 atime=1695812445.788030096 30 ctime=1695812494.369725884 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/simple-http-server.h0000664000374500037450000002067214505005532025515 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnspacket DNS Messages * @ingroup dnscore * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #pragma once #include #include #include #include #include #include #include /** * Callback for uri_decode. * * name value are the arguments of the uri * args is the last parameter passed through uri_decode. * * The path part of the uri is a value with its name set to NULL. */ typedef void uri_decode_callback(const char *name, const char *value, void *args); /** * Unescapes and parse an URI * * @param text_ * @param text_limit_ * @param uri_callback * @param args * @return */ ya_result uri_decode(const char *text_, const char *text_limit_, uri_decode_callback *uri_callback, void *args); /** * Sends the "HTTP/1.1 [code]" header. * Where [code] is * 200 -- success * or anything else from https://en.wikipedia.org/wiki/List_of_HTTP_status_codes * @param os * @param code the * @return */ ya_result http_header_code(output_stream *os, int code); /** * Sends a header field. * * name: value\r\n * * @param os * @param name * @param name_len * @param value * @param value_len * @return */ ya_result http_header_field(output_stream *os, const char *name, size_t name_len, const char *value, size_t value_len); /** * Sends the host header field. * * @param os * @param host * @param host_len * @return */ ya_result http_header_host(output_stream *os, const char *host, size_t host_len); /** * Sends the Content-Type header field. * * @param os * @param content_type * @param content_type_len * @return */ ya_result http_header_content_type(output_stream *os, const char *content_type, size_t content_type_len); /** * Sends the application/octet-stream Content-Type header field. * * @param os * @return */ ya_result http_header_content_type_application_octet_stream(output_stream *os); /** * Sends the application/json Content-Type header field. * * @param os * @return */ ya_result http_header_content_type_application_json(output_stream *os); /** * Sends the Transfer-Encoding header field. * * @param os * @param transfer_encoding * @param transfer_encoding_len * @return */ ya_result http_header_transfer_encoding(output_stream *os, const char *transfer_encoding, size_t transfer_encoding_len); /** * Sends Transfer-Encoding as "chunked". * * @param os * @return */ ya_result http_header_transfer_encoding_chunked(output_stream *os); /** * Sends the Content-Length field. * * @param os * @param length * @return */ ya_result http_header_content_length(output_stream *os, size_t length); /** * Sends a date in RFC5322 format. * * @param os * @param date * @param date_len * @return */ ya_result http_header_date(output_stream *os, const char *date, size_t date_len); /** * Sends the current date in RFC5322 format. * * @param os * @return */ ya_result http_header_date_now(output_stream *os); /** * Closes the header. * * @param os * @return */ ya_result http_header_close(output_stream *os); /** * Sends a chunk lenght (Transfer-Encoding: chunked) * * MUST be followed by the announced amount of bytes, then * http_write_chunk_end(os) must be called * * @param os * @param data * @param size * @return */ ya_result http_write_chunk_begin(output_stream *os, size_t size); /** * Sends a chunk (Transfer-Encoding: chunked) * * Ends a block started with the http_write_chunk_begin() call * Note that the last chunk is sent using http_write_chunk_close(os) * * @param os * @param data * @param size * @return */ ya_result http_write_chunk_end(output_stream *os); /** * Sends a while chunk (Transfer-Encoding: chunked) * Begin, content and end of chunk are handled. * * Note that the last chunk must be a NULL, 0-sized chunk. * * @param os * @param data * @param size * @return */ ya_result http_write_chunk(output_stream *os, const void *data, size_t size); /** * Sends a chunk terminator * * @param os * @return */ ya_result http_write_chunk_close(output_stream *os); /** * Sends content. * * The size must match Content-Length * * @param os * @param data * @param size * @return */ ya_result http_write_content(output_stream *os, const void *data, size_t size); struct simple_rest_server_page_writer_args { ptr_set uri_name_value_set; // uri arguments ptr_set query_name_value_set; // query arguments char *path; // uri path }; typedef struct simple_rest_server_page_writer_args simple_rest_server_page_writer_args; struct simple_rest_server_page; struct simple_rest_server; typedef ya_result simple_rest_server_page_writer(const struct simple_rest_server_page *, output_stream *, const simple_rest_server_page_writer_args *); struct simple_rest_server_page { char *path; simple_rest_server_page_writer *writer; void *private; int rc; }; typedef struct simple_rest_server_page simple_rest_server_page; struct simple_rest_server { mutex_t mtx; cond_t cond; ptr_set path_page_set; struct service_s service; struct thread_pool_s *thread_pool; int client_current_count; int sockfd; }; typedef struct simple_rest_server simple_rest_server; ya_result simple_rest_server_init(simple_rest_server *srs, struct addrinfo *addr); ya_result simple_rest_server_page_register(simple_rest_server *srs, const char *path, simple_rest_server_page_writer *page_writer, void *page_private); /** * Unregistering pages while the server is started has undefined behaviour * * @param srs * @param path * @return */ ya_result simple_rest_server_page_unregister(simple_rest_server *srs, const char *path); void simple_rest_server_finalize(simple_rest_server *srs); void simple_rest_server_threadpool_set(simple_rest_server *srs, struct thread_pool_s* tp); struct thread_pool_s *simple_rest_server_threadpool_get(simple_rest_server *srs); ya_result simple_rest_server_start(simple_rest_server *srs); ya_result simple_rest_server_stop(simple_rest_server *srs); /** * * Gets the HTTP header field of the query * * @param args * @param host * @return */ const char *simple_rest_server_page_writer_args_get_header_field(const simple_rest_server_page_writer_args *args, const char *host); /** * * Gets the HTTP header field of the query * * @param args * @param host * @return */ const char *simple_rest_server_page_writer_args_get_uri_arg(const simple_rest_server_page_writer_args *args, const char *host); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/socket-server.h0000644000000000000000000000013114505005532024565 xustar000000000000000030 mtime=1695812442.060976717 29 atime=1695812445.78903011 30 ctime=1695812494.371725912 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/socket-server.h0000664000374500037450000001057714505005532024542 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup network * @ingroup dnscore * @brief * * @{ */ #pragma once #if __APPLE__ #if !defined(__APPLE_USE_RFC_3542) #error "__APPLE_USE_RFC_3542 must be defined globally for this to work on OSX" #endif #endif #include #include #include #include #include #define SERVER_CONTEXT_API_BUFFER_SIZE 256 /* * from: http://www.mombu.com/programming/c/t-how-to-get-udp-destination-address-on-incoming-packets-7784569.html */ #if defined IP_RECVDSTADDR # define DSTADDR_SOCKOPT IP_RECVDSTADDR # define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_addr))) # define dstaddr(x) (CMSG_DATA(x)) #elif defined IP_PKTINFO # define DSTADDR_SOCKOPT IP_PKTINFO # define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_pktinfo))) # define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr)) #else # error "can't determine socket option" #endif #if defined IPV6_PKTINFO # define DSTADDR6_SOCKOPT IPV6_PKTINFO # define DSTADDR6_DATASIZE (CMSG_SPACE(sizeof(struct in6_pktinfo))) # define dstaddr6(x) (&(((struct in6_pktinfo *)(CMSG_DATA(x)))->ipi_addr)) #else #error "can't determine socket v6 option" #endif struct socket_server_opensocket_noserver_s { int sockfd; ya_result error; int family; struct addrinfo addr; socketaddress ss; }; struct socket_server_opensocket_s { u8 *p; u8 buffer_out[SERVER_CONTEXT_API_BUFFER_SIZE]; }; typedef struct socket_server_opensocket_s socket_server_opensocket_s; /** * * * @param ctx the struct to initialise * @param addr the address * @param sock_type e.g.: SOCK_STREAM, SOCK_DGRAM, ... */ ya_result socket_server_opensocket_init(socket_server_opensocket_s *ctx, struct addrinfo *addr, int sock_type); void socket_server_opensocket_setopt(socket_server_opensocket_s *ctx, int level, int optname, const void* opt, socklen_t optlen); void socket_server_opensocket_setopt_ignore_result(socket_server_opensocket_s *ctx, int level, int optname, const void* opt, socklen_t optlen); void socket_server_opensocket_setopt_ignore_error(socket_server_opensocket_s *ctx, int level, int optname, const void* opt, socklen_t optlen); /** * Opens the socket and returns its file descriptor or an error code. * * @param ctx * * @return the file descriptor or an error code */ int socket_server_opensocket_open(socket_server_opensocket_s *ctx); ya_result socket_server_init(int argc, char **argv); ya_result socket_server_finalize(); /** * Returns the user id of the socket server (the user ID it had when it was started) */ uid_t socket_server_uid(); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/string_set.h0000644000000000000000000000013214505005532024153 xustar000000000000000030 mtime=1695812442.009975987 30 atime=1695812445.787030082 30 ctime=1695812494.373725941 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/string_set.h0000664000374500037450000001200214505005532024110 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A dictionary C-string => u16 based on the AVL code. * * A dictionary C-string => u16 based on the AVL code. * Mostly used for name => dns type or name => dns class * * @{ * *----------------------------------------------------------------------------*/ #ifndef _STRING_SET_H #define _STRING_SET_H #ifdef __cplusplus extern "C" { #endif /* * A digest is stored prefixed with its length ([1;255]) */ /* * A structure to hold both children with direct access */ typedef struct string_node string_node; struct string_children { struct string_node* left; struct string_node* right; }; /* * An union to have access to the children with direct or indexed access */ typedef union string_children_union string_children_union; union string_children_union { struct string_children lr; struct string_node * child[2]; }; /* * The node structure CANNOT have a varying size on a given collection * This means that the digest size is a constant in the whole tree */ struct string_node { union string_children_union children; /* 2 ptrs */ const char* key; /* 1 ptr */ u16 value; /* 2 b */ s8 balance; /* 1 b */ }; /* 27 OR 15 bytes (64/32) */ /* * AVL definition part begins here */ /* * The maximum depth of a tree. * 40 is enough for storing 433494436 items (worst case) * * Depth 0 is one node. * * Worst case : N is enough for sum[n = 0,N](Fn) where Fn is Fibonacci(n+1) * Best case : N is enough for (2^(N+1))-1 */ #define AVL_MAX_DEPTH 52 // 139*10^9 items max (worst case)64 /* * The previx that will be put in front of each function name */ #define AVL_PREFIX string_set_ typedef string_node* string_set; /* * The type that hold the node */ #define AVL_NODE_TYPE string_node /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_TREE_TYPE AVL_NODE_TYPE* /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_CONST_TREE_TYPE AVL_NODE_TYPE * const /* * How to find the root in the tree */ #define AVL_TREE_ROOT(__tree__) (*(__tree__)) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE const char* #define AVL_REFERENCE_IS_CONST TRUE #define AVL_REFERENCE_IS_POINTER TRUE /* * The node has got a pointer to its parent * * 0 : disable * !=0 : enable */ #define AVL_HAS_PARENT_POINTER 0 #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif /* * I recommend setting a define to identify the C part of the template * So it can be used to undefine what is not required anymore for every * C file but that one. * */ #define STRING_SET_EMPTY NULL #ifndef _STRING_SET_C #undef AVL_MAX_DEPTH #undef AVL_PREFIX #undef AVL_NODE_TYPE #undef AVL_TREE_TYPE #undef AVL_CONST_TREE_TYPE #undef AVL_TREE_ROOT #undef AVL_REFERENCE_TYPE #undef AVL_HAS_PARENT_POINTER #undef AVL_REFERENCE_IS_CONST #undef AVL_REFERENCE_IS_POINTER #undef _AVL_H_INC #endif /* _STRING_SET_C */ #ifdef __cplusplus } #endif #endif /* _STRING_SET_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/sys_error.h0000644000000000000000000000013114505005532024020 xustar000000000000000030 mtime=1695812442.025976216 30 atime=1695812445.788030096 29 ctime=1695812494.37572597 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/sys_error.h0000664000374500037450000004301514505005532023766 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoreerror Error * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef ERROR_H_ #define ERROR_H_ /* ------------------------------------------------------------ * * INCLUDES */ /* * Please only include "native" stuff. sys_error.h should NOT depend * on anything else (beside sys_types but sys_types.h already includes * sys_error.h) */ #include #include #include #include #include #include /* * 8000 ERRNO * 8001 SERVER * 8002 CORE * 8003 DNS * 8004 DATABASE * 8005 DNSSEC * 8006 ACL * 8007 CONFIG? * 8008 YDF * 8009 EAI * 800A ZONE FILE READ * 800B SANITY * 800C NEW CONFIG * 800D PARSER * C000 DNS RCODE */ #if !defined(_SYSTYPES_H) #error Included from a disallowed place. #endif #define SUCCESS 0 #define OK 0 // The basic error code /// @note Everywhere in the source, "return ERROR;" should be replaced by something more specific #ifdef ERROR #undef ERROR #endif #define ERROR -1 #define NOK -1 #define TRACK_RETURNED_GENERIC_ERROR 0 #define ERRNO_ERROR_BASE 0x80000000 typedef int32_t ya_result; /* Two macros to easily check an error status */ #define YA_ERROR_BASE(err_) ((err_) & 0xffff0000UL) #define YA_ERROR_CODE(err_) ((err_) & 0x0000ffffUL) #if !DEBUG #define FAIL(result__) ((result__)<0) #define ISOK(result__) ((result__)>=0) #else #if TRACK_RETURNED_GENERIC_ERROR bool dnscore_monitored_isok(ya_result ret); bool dnscore_monitored_fail(ya_result ret); #define FAIL(result__) dnscore_monitored_fail((result__)) #define ISOK(result__) dnscore_monitored_isok((result__)) #else #define FAIL(result) ((((u32)(result)) & ((u32)ERRNO_ERROR_BASE)) != 0) // trying to make scan-build understand #define ISOK(result) ((((u32)(result)) & ((u32)ERRNO_ERROR_BASE)) == 0) #endif #endif /* 16 most significant bits : GROUP, the sign bit being ALWAYS set * 16 least significant bits : ID */ #define ERRNO_ERROR ((s32)(ERRNO_ERROR_BASE+errno)) #define MAKE_ERRNO_ERROR(err_) ((s32)(ERRNO_ERROR_BASE+(err_))) #define EXITFAIL(x) if((x)<0) {DIE(ERROR);exit(EXIT_FAILURE);} #define DNSMSG_ERROR_BASE 0xc0000000 /* ----------------------------------------------------------------------------- * * STRUCTS */ #define RCODE_ERROR_BASE 0x80010000 #define RCODE_ERROR_CODE(code_) ((s32)(RCODE_ERROR_BASE+(code_))) #define RCODE_ERROR_GETCODE(error_) ((error_)&0xffff) #define MAKE_DNSMSG_ERROR(err_) RCODE_ERROR_CODE(err_) // obsolete #define MAKE_RCODE_ERROR(err_) RCODE_ERROR_CODE(err_) #define TSIG_BADSIG MAKE_RCODE_ERROR(16) /* TSIG timestamp outisde of the time window */ #define TSIG_BADKEY MAKE_RCODE_ERROR(17) /* Unknown key name in TSIG record */ #define TSIG_BADTIME MAKE_RCODE_ERROR(18) /* TSIG timestamp outisde of the time window */ #define TSIG_BADMODE MAKE_RCODE_ERROR(19) #define TSIG_BADNAME MAKE_RCODE_ERROR(20) #define TSIG_BADALG MAKE_RCODE_ERROR(21) #define TSIG_BADTRUNC MAKE_RCODE_ERROR(22) #define CORE_ERROR_BASE 0x80020000 #define CORE_ERROR_CODE(code_) ((s32)(CORE_ERROR_BASE+(code_))) #define LOGGER_INITIALISATION_ERROR CORE_ERROR_CODE(1) #define COMMAND_ARGUMENT_EXPECTED CORE_ERROR_CODE(2) #define OBJECT_NOT_INITIALIZED CORE_ERROR_CODE(3) #define FORMAT_ALREADY_REGISTERED CORE_ERROR_CODE(4) #define STOPPED_BY_APPLICATION_SHUTDOWN CORE_ERROR_CODE(5) #define INVALID_STATE_ERROR CORE_ERROR_CODE(6) #define FEATURE_NOT_IMPLEMENTED_ERROR CORE_ERROR_CODE(7) #define UNEXPECTED_NULL_ARGUMENT_ERROR CORE_ERROR_CODE(8) #define INVALID_ARGUMENT_ERROR CORE_ERROR_CODE(9) #define UNABLE_TO_COMPLETE_FULL_READ CORE_ERROR_CODE(11) #define UNEXPECTED_EOF CORE_ERROR_CODE(12) #define UNSUPPORTED_TYPE CORE_ERROR_CODE(13) #define UNKNOWN_NAME CORE_ERROR_CODE(14) /* name->value table */ #define BIGGER_THAN_PATH_MAX CORE_ERROR_CODE(15) #define UNABLE_TO_COMPLETE_FULL_WRITE CORE_ERROR_CODE(16) #define BUFFER_WOULD_OVERFLOW CORE_ERROR_CODE(17) #define CHROOT_NOT_A_DIRECTORY CORE_ERROR_CODE(18) #define CHROOT_ALREADY_JAILED CORE_ERROR_CODE(19) #define IP_VERSION_NOT_SUPPORTED CORE_ERROR_CODE(20) #define COLLECTION_DUPLICATE_ENTRY CORE_ERROR_CODE(21) #define INVALID_PATH CORE_ERROR_CODE(22) #define PID_LOCKED CORE_ERROR_CODE(23) #define ZALLOC_ERROR_MMAPFAILED CORE_ERROR_CODE(24) #define ZALLOC_ERROR_OUTOFMEMORY CORE_ERROR_CODE(25) #define DIRECTORY_NOT_WRITABLE CORE_ERROR_CODE(26) #define FEATURE_NOT_SUPPORTED CORE_ERROR_CODE(27) #define LOCK_TIMEOUT CORE_ERROR_CODE(28) #define CIRCULAR_FILE_FULL CORE_ERROR_CODE(29) #define CIRCULAR_FILE_SHORT CORE_ERROR_CODE(30) #define CIRCULAR_FILE_END CORE_ERROR_CODE(31) #define CIRCULAR_FILE_LIMIT_EXCEEDED CORE_ERROR_CODE(32) #define DATA_FORMAT_ERROR CORE_ERROR_CODE(33) #define LOCK_FAILED CORE_ERROR_CODE(34) #define UNSUPPORTED_CLASS CORE_ERROR_CODE(35) #define CANNOT_OPEN_FILE CORE_ERROR_CODE(36) #define PARSEB16_ERROR CORE_ERROR_CODE(0x1001) #define PARSEB32_ERROR CORE_ERROR_CODE(0x1002) #define PARSEB32H_ERROR CORE_ERROR_CODE(0x1003) #define PARSEB64_ERROR CORE_ERROR_CODE(0x1004) #define PARSEINT_ERROR CORE_ERROR_CODE(0x1005) #define PARSEDATE_ERROR CORE_ERROR_CODE(0x1006) #define PARSEIP_ERROR CORE_ERROR_CODE(0x1007) #define PARSEWORD_NOMATCH_ERROR CORE_ERROR_CODE(0x1081) #define PARSESTRING_ERROR CORE_ERROR_CODE(0x1082) #define PARSE_BUFFER_TOO_SMALL_ERROR CORE_ERROR_CODE(0x1083) #define PARSE_INVALID_CHARACTER CORE_ERROR_CODE(0x1084) #define PARSE_INVALID_ARGUMENT CORE_ERROR_CODE(0x1085) #define PARSE_EMPTY_ARGUMENT CORE_ERROR_CODE(0x1086) #define CONFIG_SECTION_CALLBACK_ALREADY_SET CORE_ERROR_CODE(0x1801) #define CONFIG_SECTION_CALLBACK_NOT_SET CORE_ERROR_CODE(0x1802) #define CONFIG_SECTION_CALLBACK_NOT_FOUND CORE_ERROR_CODE(0x1803) #define CONFIG_NOT_A_REGULAR_FILE CORE_ERROR_CODE(0x1804) #define CONFIG_TOO_MANY_HOSTS CORE_ERROR_CODE(0x1805) #define CONFIG_FQDN_NOT_ALLOWED CORE_ERROR_CODE(0x1806) #define CONFIG_PORT_NOT_ALLOWED CORE_ERROR_CODE(0x1807) #define CONFIG_EXPECTED_VALID_PORT_VALUE CORE_ERROR_CODE(0x1808) #define CONFIG_TSIG_NOT_ALLOWED CORE_ERROR_CODE(0x1809) #define CONFIG_INTERNAL_ERROR CORE_ERROR_CODE(0x180a) #define CONFIG_IPV4_NOT_ALLOWED CORE_ERROR_CODE(0x180b) #define CONFIG_IPV6_NOT_ALLOWED CORE_ERROR_CODE(0x180c) #define CONFIG_KEY_UNKNOWN CORE_ERROR_CODE(0x180d) #define CONFIG_KEY_PARSE_ERROR CORE_ERROR_CODE(0x180e) #define CONFIG_SECTION_ERROR CORE_ERROR_CODE(0x180f) #define CONFIG_IS_BUSY CORE_ERROR_CODE(0x1810) #define CONFIG_FILE_NOT_FOUND CORE_ERROR_CODE(0x1811) #define THREAD_CREATION_ERROR CORE_ERROR_CODE(0x2001) #define THREAD_DOUBLEDESTRUCTION_ERROR CORE_ERROR_CODE(0x2002) #define SERVICE_ID_ERROR CORE_ERROR_CODE(0x2003) #define SERVICE_WITHOUT_ENTRY_POINT CORE_ERROR_CODE(0x2004) #define SERVICE_ALREADY_INITIALISED CORE_ERROR_CODE(0x2005) #define SERVICE_ALREADY_RUNNING CORE_ERROR_CODE(0x2006) #define SERVICE_NOT_RUNNING CORE_ERROR_CODE(0x2007) #define SERVICE_NOT_INITIALISED CORE_ERROR_CODE(0x2008) #define SERVICE_HAS_RUNNING_THREADS CORE_ERROR_CODE(0x2009) #define SERVICE_ALREADY_PAUSED CORE_ERROR_CODE(0x200a) #define SERVICE_INITIALISATION_ERROR CORE_ERROR_CODE(0x200b) #define TSIG_DUPLICATE_REGISTRATION CORE_ERROR_CODE(0x3001) #define TSIG_UNABLE_TO_SIGN CORE_ERROR_CODE(0x3002) #define NET_UNABLE_TO_RESOLVE_HOST CORE_ERROR_CODE(0x4001) #define TCP_RATE_TOO_SLOW CORE_ERROR_CODE(0x4002) #define CHARON_ERROR_FILE_LOCKED CORE_ERROR_CODE(0x5001) #define CHARON_ERROR_NOT_AUTHORISED CORE_ERROR_CODE(0x5002) #define CHARON_ERROR_UNKNOWN_ID CORE_ERROR_CODE(0x5003) #define CHARON_ERROR_EXPECTED_MAGIC_HEAD CORE_ERROR_CODE(0x5004) #define CHARON_ERROR_INVALID_HEAD CORE_ERROR_CODE(0x5006) #define CHARON_ERROR_INVALID_TAIL CORE_ERROR_CODE(0x5007) #define CHARON_ERROR_INVALID_COMMAND CORE_ERROR_CODE(0x5008) #define CHARON_ERROR_COMMAND_SEQ_MISMATCHED CORE_ERROR_CODE(0x5009) #define CHARON_ERROR_UNKNOWN_MAGIC CORE_ERROR_CODE(0x500a) #define CHARON_ERROR_ALREADY_RUNNING CORE_ERROR_CODE(0x500b) #define CHARON_ERROR_ALREADY_STOPPED CORE_ERROR_CODE(0x500c) #define LOGGER_CHANNEL_ALREADY_REGISTERED CORE_ERROR_CODE(0x6001) #define LOGGER_CHANNEL_NOT_REGISTERED CORE_ERROR_CODE(0x6002) #define LOGGER_CHANNEL_HAS_LINKS CORE_ERROR_CODE(0x6003) #define ALARM_REARM CORE_ERROR_CODE(0xff00) // KEEP, used by alarm callback functions to automatically re-arm #define DNS_ERROR_BASE 0x80030000 #define DNS_ERROR_CODE(code_) ((s32)(DNS_ERROR_BASE+(code_))) #define IS_DNS_ERROR_CODE(code_) (((code_)&0xffff0000) == DNS_ERROR_BASE) #define DOMAIN_TOO_LONG DNS_ERROR_CODE(1) /* FQDN is longer than 255 */ #define INCORRECT_IPADDRESS DNS_ERROR_CODE(2) /* Incorrect ip address */ #define INCORRECT_RDATA DNS_ERROR_CODE(3) #define LABEL_TOO_LONG DNS_ERROR_CODE(10) /* label is longer than 63 */ #define INVALID_CHARSET DNS_ERROR_CODE(11) /* */ #define ZONEFILE_INVALID_TYPE DNS_ERROR_CODE(12) /* Type is unknown */ #define DOMAINNAME_INVALID DNS_ERROR_CODE(13) /* invalid dnsname usually : double dot */ #define TSIG_FORMERR DNS_ERROR_CODE(14) #define TSIG_SIZE_LIMIT_ERROR DNS_ERROR_CODE(15) #define UNPROCESSABLE_MESSAGE DNS_ERROR_CODE(23) #define INVALID_PROTOCOL DNS_ERROR_CODE(24) #define INVALID_RECORD DNS_ERROR_CODE(25) #define UNSUPPORTED_RECORD DNS_ERROR_CODE(26) #define ZONE_ALREADY_UP_TO_DATE DNS_ERROR_CODE(27) #define UNKNOWN_DNS_TYPE DNS_ERROR_CODE(28) #define UNKNOWN_DNS_CLASS DNS_ERROR_CODE(29) //#define INVALID_MESSAGE DNS_ERROR_CODE(30) #define INVALID_MESSAGE UNPROCESSABLE_MESSAGE #define MESSAGE_HAS_WRONG_ID DNS_ERROR_CODE(31) #define MESSAGE_IS_NOT_AN_ANSWER DNS_ERROR_CODE(32) #define MESSAGE_UNEXPECTED_ANSWER_DOMAIN DNS_ERROR_CODE(33) #define MESSAGE_UNEXPECTED_ANSWER_TYPE_CLASS DNS_ERROR_CODE(34) #define MESSAGE_CONTENT_OVERFLOW DNS_ERROR_CODE(35) #define MESSAGE_TRUNCATED DNS_ERROR_CODE(36) #define RRSIG_COVERED_TYPE_DIFFERS DNS_ERROR_CODE(50) #define RRSIG_OUTPUT_DIGEST_SIZE_TOO_BIG DNS_ERROR_CODE(51) #define RRSIG_UNSUPPORTED_COVERED_TYPE DNS_ERROR_CODE(52) #define RRSIG_VERIFICATION_FAILED DNS_ERROR_CODE(53) #define DNSSEC_ALGORITHM_UNKOWN DNS_ERROR_CODE(100) /// @note EAI error codes are used for getaddrinfo /// /// @note EAI_ERROR_BADFLAGS error code is used for getaddrinfo through EAI_ERROR_CODE /// @note EAI_ERROR_NONAME error code is used for getaddrinfo through EAI_ERROR_CODE /// @note EAI_ERROR_AGAIN error code is used for getaddrinfo through EAI_ERROR_CODE /// @note EAI_ERROR_FAIL error code is used for getaddrinfo through EAI_ERROR_CODE /// @note EAI_ERROR_FAMILY error code is used for getaddrinfo through EAI_ERROR_CODE /// @note EAI_ERROR_SOCKTYPE error code is used for getaddrinfo through EAI_ERROR_CODE /// @note EAI_ERROR_SERVICE error code is used for getaddrinfo through EAI_ERROR_CODE /// @note EAI_ERROR_MEMORY error code is used for getaddrinfo through EAI_ERROR_CODE /// @note EAI_ERROR_SYSTEM error code is used for getaddrinfo through EAI_ERROR_CODE /// @note EAI_ERROR_OVERFLOW error code is used for getaddrinfo through EAI_ERROR_CODE #define EAI_ERROR_BASE 0x80090000 #define EAI_ERROR_CODE(code_) ((s32)(EAI_ERROR_BASE+(code_))) #define EAI_ERROR_BADFLAGS EAI_ERROR_CODE(-EAI_BADFLAGS) /* minus because EAI_ values are < 0 */ #define EAI_ERROR_NONAME EAI_ERROR_CODE(-EAI_NONAME) #define EAI_ERROR_AGAIN EAI_ERROR_CODE(-EAI_AGAIN) #define EAI_ERROR_FAIL EAI_ERROR_CODE(-EAI_FAIL) #define EAI_ERROR_FAMILY EAI_ERROR_CODE(-EAI_FAMILY) #define EAI_ERROR_SOCKTYPE EAI_ERROR_CODE(-EAI_SOCKTYPE) #define EAI_ERROR_SERVICE EAI_ERROR_CODE(-EAI_SERVICE) #define EAI_ERROR_MEMORY EAI_ERROR_CODE(-EAI_MEMORY) #define EAI_ERROR_SYSTEM EAI_ERROR_CODE(-EAI_SYSTEM) #define EAI_ERROR_OVERFLOW EAI_ERROR_CODE(-EAI_OVERFLOW) #define EXIT_CODE_SELFCHECK_ERROR 249 #define EXIT_CODE_OUTOFMEMORY_ERROR 250 #define EXIT_CODE_THREADCREATE_ERROR 251 #define EXIT_CODE_FORMAT_ERROR 252 #define EXIT_CODE_LOGLEVEL_ERROR 253 #define EXIT_CODE_LOGQUIT_ERROR 254 /* ----------------------------------------------------------------------------- * * PROTOTYPES */ void dief(ya_result error_code, const char *format, ...); /** * * Release the memory used by the error table * */ void error_unregister_all(); void error_register(ya_result code, const char * const text); /** * @brief Returns the string associated to an error code * * Returns the string associated to an error code * * This is NOT thread-safe. Only to be used * * @param[in] err the ya_result error code * * @return a pointer to the error message */ const char* error_gettext(ya_result code); struct output_stream; void error_writetext(struct output_stream *os, ya_result code); void dnscore_register_errors(); ya_result ya_ssl_error(); #define DIE(code) dief((code), "%s:%i\n", __FILE__, __LINE__);abort() #define DIE_MSG(msg) dief(ERROR, "%s:%i %s\n", __FILE__, __LINE__, (msg));abort() #endif /* ERROR_H_ */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/sys_get_cpu_count.h0000644000000000000000000000013114505005532025525 xustar000000000000000030 mtime=1695812442.080977003 29 atime=1695812445.78903011 30 ctime=1695812494.377725998 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/sys_get_cpu_count.h0000664000374500037450000000453414505005532025476 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup cpu CPU * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _SYS_GET_CPU_COUNT_H #define _SYS_GET_CPU_COUNT_H #include #ifdef __cplusplus extern "C" { #endif u32 sys_get_cpu_count(); void sys_set_cpu_count(int count); bool sys_has_hyperthreading(); #ifdef __cplusplus } #endif #endif /* _SYS_GET_CPU_COUNT_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/sys_types.h0000644000000000000000000000013214505005532024034 xustar000000000000000030 mtime=1695812442.048976545 30 atime=1695812445.788030096 30 ctime=1695812494.379726027 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/sys_types.h0000664000374500037450000005167514505005532024014 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup systemtypes Definition of types in order to ensure architecture-independence * @ingroup dnscore * @brief Definition of types in order to ensure architecture-independence * * @{ */ #ifndef _SYSTYPES_H #define _SYSTYPES_H #include #ifdef __cplusplus #error "C++ compiler mode not supported" #endif #if !DEBUG #ifndef NDEBUG #define NDEBUG 1 #endif #endif #include #include #include #include #include #include #ifdef _MSC_VER #include #define C11_VLA_AVAILABLE 0 static void* stack_alloc(size_t size) { // VS wants to use _malloca instead which allocates on the heap if size > _ALLOCA_S_THRESHOLD (1024) // I'd rather have a bigger stack return _alloca(size); } #else #define C11_VLA_AVAILABLE 1 #endif #ifndef __has_c_attribute // Optional of course. #define __has_c_attribute(x) 0 // Compatibility with non-clang compilers. #endif #if __has_c_attribute(fallthrough) || (defined(__GNUC__) && (__GNUC__ >= 7)) || (defined(__clang__) && (__clang_major__ >= 10)) // __attribute__ ((fallthrough)); // C and C++03 // [[fallthrough]]; // C++17 and above #define FALLTHROUGH __attribute__ ((fallthrough)); #else #define FALLTHROUGH #endif #if defined __FreeBSD__ #include #ifndef __BYTE_ORDER #if defined(_BYTE_ORDER) #define __BIG_ENDIAN _BIG_ENDIAN #define __LITTLE_ENDIAN _LITTLE_ENDIAN #define __BYTE_ORDER _BYTE_ORDER #elif defined(WORDS_BIGENDIAN) #define __BIG_ENDIAN 4321 #define __LITTLE_ENDIAN 1234 #define __BYTE_ORDER __BIG_ENDIAN #else #error "endianness detection code will most likely fail" #endif #endif #elif defined __APPLE__ #include #ifndef __BYTE_ORDER #if defined(BYTE_ORDER) #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #define __BYTE_ORDER BYTE_ORDER #elif defined(WORDS_BIGENDIAN) #define __BIG_ENDIAN 4321 #define __LITTLE_ENDIAN 1234 #define __BYTE_ORDER __BIG_ENDIAN #else #error "endianness detection code will most likely fail" #endif #endif #elif defined __sun #include #ifndef __BYTE_ORDER #if defined(__BYTE_ORDER__) #define __BIG_ENDIAN __ORDER_BIG_ENDIAN__ #define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ #define __BYTE_ORDER __BYTE_ORDER__ #else // assume big endian #define __BIG_ENDIAN 4321 #define __LITTLE_ENDIAN 1234 #define __BYTE_ORDER __BIG_ENDIAN #endif #endif #elif defined __OpenBSD__ || defined __NetBSD__ #include #ifndef __BYTE_ORDER #if defined(BYTE_ORDER) #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #define __BYTE_ORDER BYTE_ORDER #else // assume big endian #define __BIG_ENDIAN 4321 #define __LITTLE_ENDIAN 1234 #define __BYTE_ORDER __BIG_ENDIAN #endif #endif #elif defined(WIN32) #define WIN32_LEAN_AND_MEAN #pragma message("windows") #include #include #include //#include //#include #undef inline #define inline typedef int uid_t; typedef int gid_t; typedef HANDLE pid_t; typedef unsigned int mode_t; #define restrict #define S_ISREG(mode__) ((mode__ & _S_IFREG) != 0) #define S_ISLNK(mode__) (0) #define S_ISDIR(mode__) ((mode__ & _S_IFDIR) != 0) #else #include #include #endif #define VERSION_2_0_0 0x020000000000LL #define VERSION_2_1_0 0x020100000000LL #define VERSION_2_2_0 0x020200000000LL #define VERSION_2_3_0 0x020300000000LL #define VERSION_2_4_0 0x020400000000LL #define VERSION_2_4_1 0x020400100000LL #define VERSION_2_4_2 0x020400200000LL #include #include #include /** @note must be used for u_char on Mac OS X */ #ifdef __cplusplus extern "C" { #endif #define SIZEOF_TIMEVAL 16 #ifndef HAS_DYNAMIC_PROVISIONING #define HAS_DYNAMIC_PROVISIONING 0 #endif #ifndef PATH_MAX #define PATH_MAX 4096 #endif #if defined(__bool_true_false_are_defined) && __bool_true_false_are_defined != 0 #ifndef TRUE #define TRUE true #endif #ifndef FALSE #define FALSE false #endif #else typedef int bool; #ifndef TRUE #define TRUE (0==0) #endif #ifndef FALSE #define FALSE (0==1) #endif #endif #define UNSIGNED_TYPE_VALUE_MAX(__type__) ((__type__)~0) #define SIGNED_TYPE_VALUE_MAX(__type__) (((__type__)~0)>>1) #define SIGNED_TYPE_VALUE_MIN(__type__) (((__type__)~0) - (((__type__)~0)>>1)) #define UNSIGNED_VAR_VALUE_MAX(__var__) ((~0ULL)>>((sizeof(~0ULL) - sizeof(__var__)) * 8LL)) #define SIGNED_VAR_VALUE_MAX(__var__) (UNSIGNED_VAR_VALUE_MAX(__var__)>>1) #define SIGNED_VAR_VALUE_MIN(__var__) (UNSIGNED_VAR_VALUE_MAX(__var__) - SIGNED_VAR_VALUE_MAX(__var__)) #define UNSIGNED_VAR_VALUE_IS_MAX(__var__) (__var__ == UNSIGNED_VAR_VALUE_MAX(__var__)) #define SIGNED_VAR_VALUE_IS_MAX(__var__) (__var__ == SIGNED_VAR_VALUE_MAX(__var__)) /* This is the basic type definition set */ /* Tweaks will be added for each setup (using the preprocessor) */ typedef unsigned char u8; typedef signed char s8; typedef unsigned short u16; typedef short s16; typedef unsigned int u32; typedef int s32; #if defined(HAVE_UINT64_T) && defined(HAVE_INT64_T) typedef uint64_t u64; typedef int64_t s64; #elif defined(HAVE_LONG_LONG) typedef unsigned long long u64; typedef signed long long s64; #elif defined(_LONGLONG) && ( _LONGLONG == 1 ) // FreeBSD 9.1 gcc 4.2.1 typedef unsigned long long u64; typedef signed long long s64; #elif defined(__SIZEOF_LONG_LONG__) && (__SIZEOF_LONG_LONG__ == 8) typedef unsigned long long u64; typedef signed long long s64; #elif defined(__LONG_LONG_MAX__) && (__LONG_LONG_MAX__ == 9223372036854775807LL) typedef unsigned long long u64; typedef signed long long s64; #elif defined(_LONGLONG_TYPE) typedef unsigned long long u64; typedef signed long long s64; #elif defined(WIN32) typedef __int8 s8; typedef unsigned __int8 u8; typedef __int16 s16; typedef unsigned __int16 u16; typedef __int32 s32; typedef unsigned __int32 u32; typedef __int64 s64; typedef unsigned __int64 u64; #else #error NO UNSIGNED 64 BITS TYPE KNOWN ON THIS 64 BITS ARCHITECTURE (u64 + s64) #endif typedef void callback_function(void*); typedef ya_result result_callback_function(void*, void*); /* AIX : __64BIT__ HP: __LP64__ SUN: __sparcv9, _LP64 SGI: _MIPS_SZLONG==64 NT: _M_IA64 */ #ifndef __SIZEOF_POINTER__ #if defined(__LP64__)||defined(__LP64)||defined(_LP64)||defined(__64BIT__)||defined(MIPS_SZLONG)||defined(_M_IA64)||defined(_WIN64) #define __SIZEOF_POINTER__ 8 #else #define __SIZEOF_POINTER__ 4 #endif #endif #if __SIZEOF_POINTER__ == 4 typedef unsigned int intptr; // an integer with the same size as a data pointer typedef float realptr; // a float with the same size as a data pointer #elif __SIZEOF_POINTER__ == 8 #if defined(HAVE_UINT64_T) typedef uint64_t intptr; #elif defined(HAVE_LONG_LONG) typedef unsigned long long intptr; #elif defined(__LONG_LONG_MAX__) && (__LONG_LONG_MAX__ == 9223372036854775807LL) typedef unsigned long long intptr; #elif defined(__SIZEOF_LONG_LONG__) && (__SIZEOF_LONG_LONG__ == 8) typedef unsigned long long intptr; #elif defined(_LONGLONG) && ( _LONGLONG == 1 ) // FreeBSD 9.1 gcc 4.2.1 typedef unsigned long long intptr; #elif defined(_LONGLONG_TYPE) typedef unsigned long long intptr; #elif defined(_WIN64) typedef u64 intptr; #else #error NO UNSIGNED 64 BITS TYPE KNOWN ON THIS 64 BITS ARCHITECTURE (intptr) #endif typedef double realptr; // a float with the same size as a data pointer #else // __SIZEOF_POINTER not 4 nor 8 #error __SIZEOF_POINTER__ value not handled (only 4 and 8 are) #endif /** * This macro returns the first address aligned to 8 bytes from the parameter * addresss. * */ #define ALIGN8(__from_address__) (((__from_address__)+7)&~7) /** * This macro returns the first address aligned to 16 bytes from the parameter * addresss. * */ #define ALIGN16(__from_address__) (((__from_address__)+15)&~15) /* * Macros used to access bytes inside a buffer. * * ie: U32_AT(packet[8]), assuming that packet is a byte buffer, will access * the 8th byte inside packet as a (native) unsigned 32bits integer. */ #define U8_AT(address__) (*((u8*)&(address__))) #define GET_U8_AT(address__) (*((u8*)&(address__))) #define SET_U8_AT(address__,value__) (*((u8*)&(address__)) = (value__)) #ifndef WORDS_BIGENDIAN #if __BYTE_ORDER == __BIG_ENDIAN #define WORDS_BIGENDIAN 1 #endif #else // WORDS_BIGENDIAN defined #if __BYTE_ORDER == __LITTLE_ENDIAN #error "confusing endianness" #endif #endif #define AVOID_ANTIALIASING 1 #ifndef DNSCORE_HAS_MEMALIGN_ISSUES #error "DNSCORE_HAS_MEMALIGN_ISSUES is not defined. Please ensure the relevant config.h is included at some level above." #endif #if !DNSCORE_HAS_MEMALIGN_ISSUES #if AVOID_ANTIALIASING static inline u16 GET_U16_AT_P(const void* address) { const u16 *p = (const u16*)address; return *p; } static inline void SET_U16_AT_P(void* address, u16 value) { u16 *p = (u16*)address; *p = value; } static inline u32 GET_U32_AT_P(const void* address) { const u32 *p = (const u32*)address; return *p; } static inline void SET_U32_AT_P(void* address, u32 value) { u32 *p = (u32*)address; *p = value; } static inline u64 GET_U64_AT_P(const void* address) { const u64 *p = (const u64*)address; return *p; } static inline void SET_U64_AT_P(void* address, u64 value) { u64 *p = (u64*)address; *p = value; } #define GET_U16_AT(address__) GET_U16_AT_P(&(address__)) #define SET_U16_AT(address__,value__) SET_U16_AT_P(&(address__),(value__)) #define GET_U32_AT(address__) GET_U32_AT_P(&(address__)) #define SET_U32_AT(address__,value__) SET_U32_AT_P(&(address__),(value__)) #define GET_U64_AT(address__) GET_U64_AT_P(&(address__)) #define SET_U64_AT(address__,value__) SET_U64_AT_P(&(address__),(value__)) #else #define GET_U16_AT(address) (*((u16*)&(address))) #define SET_U16_AT(address,value) *((u16*)&(address))=(value) #define GET_U32_AT(address) (*((u32*)&(address))) #define SET_U32_AT(address,value) *((u32*)&(address))=(value) #define GET_U64_AT(address) (*((u64*)&(address))) #define SET_U64_AT(address,value) *((u64*)&(address))=(value) #endif #else /* sparc ... */ /* * Why in caps ? Traditionnaly it was an helper macro. Macros are in caps except when they hide a virtual call. * */ static inline u16 GET_U16_AT_P(const void* p) { const u8* p8=(const u8*)p; u16 v; #ifdef WORDS_BIGENDIAN v=p8[0]; v<<=8; v|=p8[1]; #else v=p8[1]; v<<=8; v|=p8[0]; #endif return v; } #define GET_U16_AT(x) GET_U16_AT_P(&(x)) static inline void SET_U16_AT_P(void* p, u16 v) { u8* p8=(u8*)p; #ifdef WORDS_BIGENDIAN p8[0]=v>>8; p8[1]=v; #else p8[0]=v; p8[1]=v>>8; #endif } #define SET_U16_AT(x___,y___) SET_U16_AT_P(&(x___),(y___)) static inline u32 GET_U32_AT_P(const void* p) { const u8* p8=(const u8*)p; u32 v; #ifdef WORDS_BIGENDIAN v=p8[0]; v<<=8; v|=p8[1]; v<<=8; v|=p8[2]; v<<=8; v|=p8[3]; #else v=p8[3]; v<<=8; v|=p8[2]; v<<=8; v|=p8[1]; v<<=8; v|=p8[0]; #endif return v; } #define GET_U32_AT(x) GET_U32_AT_P(&(x)) static inline void SET_U32_AT_P(void* p, u32 v) { u8* p8=(u8*)p; #ifdef WORDS_BIGENDIAN p8[0]=v>>24; p8[1]=v>>16; p8[2]=v>>8; p8[3]=v; #else p8[0]=v; p8[1]=v>>8; p8[2]=v>>16; p8[3]=v>>24; #endif } #define SET_U32_AT(x___,y___) SET_U32_AT_P(&(x___),(y___)) static inline u64 GET_U64_AT_P(const void* p) { const u8* p8=(const u8*)p; u32 v; #ifdef WORDS_BIGENDIAN v=p8[0]; v<<=8; v|=p8[1]; v<<=8; v|=p8[2]; v<<=8; v|=p8[3]; v<<=8; v|=p8[4]; v<<=8; v|=p8[5]; v<<=8; v|=p8[6]; v<<=8; v|=p8[7]; #else v=p8[7]; v<<=8; v|=p8[6]; v<<=8; v|=p8[5]; v<<=8; v|=p8[4]; v<<=8; v=p8[3]; v<<=8; v|=p8[2]; v<<=8; v|=p8[1]; v<<=8; v|=p8[0]; #endif return v; } #define GET_U64_AT(x) GET_U64_AT_P(&(x)) static inline void SET_U64_AT_P(void* p, u64 v) { u8* p8=(u8*)p; #ifdef WORDS_BIGENDIAN p8[0]=v>>56; p8[1]=v>>48; p8[2]=v>>40; p8[3]=v>>32; p8[4]=v>>24; p8[5]=v>>16; p8[6]=v>>8; p8[7]=v; #else p8[0]=v; p8[1]=v>>8; p8[2]=v>>16; p8[3]=v>>24; p8[4]=v>>32; p8[5]=v>>40; p8[6]=v>>48; p8[7]=v>>56; #endif } #define SET_U64_AT(x___,y___) SET_U64_AT_P(&(x___),(y___)) #endif #if __SIZEOF_POINTER__ == 4 #define SET_PTR_AT_P SET_U32_AT_P #define SET_PTR_AT SET_U32_AT #define GET_PTR_AT_P GET_U32_AT_P #define GET_PTR_AT GET_U32_AT #elif __SIZEOF_POINTER__ == 8 #define SET_PTR_AT_P SET_U64_AT_P #define SET_PTR_AT SET_U64_AT #define GET_PTR_AT_P GET_U64_AT_P #define GET_PTR_AT GET_U64_AT #else #error "unsupported pointer size" #endif #define MAX_U8 ((u8)0xff) #define MAX_U16 ((u16)0xffff) #define MAX_U32 ((u32)0xffffffffUL) #define MAX_U64 ((u64)0xffffffffffffffffULL) #define MAX_S8 ((s8)0x7f) #define MAX_S16 ((s16)0x7fff) #define MAX_S32 ((s32)0x7fffffffL) #define MAX_S64 ((s64)0x7fffffffffffffffLL) #define MIN_S8 ((s8)0x80) #define MIN_S16 ((s16)0x8000) #define MIN_S32 ((s32)0x80000000L) #define MIN_S64 ((s64)0x8000000000000000LL) #define CLEARED_SOCKET (-1) #ifdef __GNUC__ #define GCC_VERSION ((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__) #endif #ifndef htobe64 #if defined __APPLE__ #define __bswap_16 _OSSwapInt16 #define __bswap_32 _OSSwapInt32 #define __bswap_64 _OSSwapInt64 #elif defined __sun && defined(__GNUC__) #define __bswap_16 __builtin_bswap16 #define __bswap_32 __builtin_bswap32 #define __bswap_64 __builtin_bswap64 #endif /* Conversion interfaces. */ # if __BYTE_ORDER == __LITTLE_ENDIAN # define htobe16(x) __bswap_16 (x) # define htole16(x) (x) # define be16toh(x) __bswap_16 (x) # define le16toh(x) (x) # define htobe32(x) __bswap_32 (x) # define htole32(x) (x) # define be32toh(x) __bswap_32 (x) # define le32toh(x) (x) # define htobe64(x) __bswap_64 (x) # define htole64(x) (x) # define be64toh(x) __bswap_64 (x) # define le64toh(x) (x) # else # define htobe16(x) (x) # define htole16(x) __bswap_16 (x) # define be16toh(x) (x) # define le16toh(x) __bswap_16 (x) # define htobe32(x) (x) # define htole32(x) __bswap_32 (x) # define be32toh(x) (x) # define le32toh(x) __bswap_32 (x) # define htobe64(x) (x) # define htole64(x) __bswap_64 (x) # define be64toh(x) (x) # define le64toh(x) __bswap_64 (x) # endif // __BYTE_ORDER #endif // htobe64 /**/ /// Used for collection callback processing (list) /// Their support by a collection is not guaranteed /// @note PROCESS_THEN_STOP = PROCESS|STOP #define COLLECTION_ITEM_SKIP 0 #define COLLECTION_ITEM_PROCESS 1 #define COLLECTION_ITEM_STOP 2 #define COLLECTION_ITEM_PROCESS_THEN_STOP (COLLECTION_ITEM_PROCESS|COLLECTION_ITEM_STOP) /**/ typedef u32 process_flags_t; #if WORDS_BIGENDIAN #define NU16(value) ((u16)(value)) #define NU32(value) ((u32)(value)) #else #define NU16(value) ((u16)(((((u16)(value))>>8)&0xff)|(((u16)(value))<<8))) #define NU32(value) ((u32)(( (((u32)(value)) >> 24) & 0xff) | ((((u32)(value)) >> 8) & 0xff00) | ((((u32)(value)) << 8) & 0xff0000) | (((u32)(value)) << 24))) #endif #define VERSION_U32(h__,l__) (((h__) << 16) | (l__)) #define VERSION_U16(h__,l__) (((h__) << 8) | (l__)) #define VERSION_U8(h__,l__) (((h__) << 4) | (l__)) #define NETWORK_ONE_16 NU16(0x0001) #define IS_WILD_LABEL(u8dnslabel_) ( GET_U16_AT(*(u8dnslabel_)) == NU16(0x012a)) /* 01 2a = 1 '*' */ /* sys_types.h is included everywhere. This ensure the debug hooks will be too. */ #define TMPBUFFR_TAG 0x5246465542504d54 #if !DEBUG #define MALLOC_OR_DIE(cast,target,size,tag) if(((target)=(cast)malloc(size))==NULL){perror(__FILE__);exit(EXIT_CODE_OUTOFMEMORY_ERROR);} #define MALLOC_OBJECT_OR_DIE(target__,object__,tag__) if(((target__)=(object__*)malloc(sizeof(object__)))==NULL){perror(__FILE__);exit(EXIT_CODE_OUTOFMEMORY_ERROR);} #define MALLOC_OBJECT_ARRAY_OR_DIE(target__,object__,count__,tag__) if(((target__)=(object__*)malloc(sizeof(object__)*(count__)))==NULL){perror(__FILE__);exit(EXIT_CODE_OUTOFMEMORY_ERROR);} #define MALLOC_OBJECT_ARRAY(target__,object__,count__,tag__) (target__)=(object__*)malloc(sizeof(object__)*(count__)) #else #define MALLOC_OR_DIE(cast_,target_,size_,tag_) if(((target_)=(cast_)malloc(size_))!=NULL){memset((void*)(target_),0xac,(size_));}else{perror(__FILE__);exit(EXIT_CODE_OUTOFMEMORY_ERROR);} #define MALLOC_OBJECT_OR_DIE(target__,object__,tag__) if(((target__)=(object__*)malloc(sizeof(object__)))!=NULL){memset((void*)(target__),0xac,(sizeof(object__)));}else{perror(__FILE__);exit(EXIT_CODE_OUTOFMEMORY_ERROR);} #define MALLOC_OBJECT_ARRAY_OR_DIE(target__,object__,count__,tag__) if(((target__)=(object__*)malloc(sizeof(object__)*(count__)))!=NULL){memset((void*)(target__),0xac,(sizeof(object__)*(count__)));}else{perror(__FILE__);exit(EXIT_CODE_OUTOFMEMORY_ERROR);} #define MALLOC_OBJECT_ARRAY(target__,object__,count__,tag__) if(((target__)=(object__*)malloc(sizeof(object__)*(count__)))!=NULL){memset((void*)(target__),0xac,(sizeof(object__)*(count__)));} #endif #define REALLOC_OR_DIE(cast,src_and_target,newsize,tag) if(((src_and_target)=(cast)realloc((src_and_target),(newsize)))==NULL){perror(__FILE__);abort();} // the string if not NULL, else a empty string #define STRNULL(__str__) (((__str__)!=NULL)?(__str__):"") // the fqdn if not NULL, else "." #define FQDNNULL(__str__) (((__str__)!=NULL)?(__str__):(const u8*)"") #define TOSTRING(s) TOSTRING_(s) #define TOSTRING_(s) #s #define PREPROCESSOR_INT2STR(x) #x #define PREPROCESSOR_EVAL(a__) a__ #define PREPROCESSOR_CONCAT(a__,b__) a__##b__ #define PREPROCESSOR_CONCAT_EVAL_(a__,b__) a__##b__ #define PREPROCESSOR_CONCAT_EVAL(a__,b__) PREPROCESSOR_CONCAT_EVAL_(a__,b__) /** * strcpy is not safe * strncpy is filling buffers needlessly * * This one does what we want. */ static inline void strcpy_ex(char *dest, const char *src, size_t n) { size_t src_len = strlen(src) + 1; if(src_len <= n) { memcpy(dest, src, src_len); } else { --n; memcpy(dest, src, n); dest[n] = '\0'; } } #define BOOL2INT(b_) ((b_)?1:0) #define BOOL2STR(b_) ((b_)?"true":"false") #define BOOL2CHR(b_) ((b_)?'y':'n') #include #ifdef MIN #undef MIN #endif #define MIN(a,b) (((a)<=(b))?(a):(b)) #ifdef MAX #undef MAX #endif #define MAX(a,b) (((a)>=(b))?(a):(b)) #define BOUND(a,b,c) (((b)<=(a))?(a):(((b)>=(c))?(c):(b))) #define ZEROMEMORY(buffer__,size__) memset(buffer__, 0, size__) #define MEMCOPY(target__,source__,size__) memcpy((target__),(source__),(size__)) // a magic number as 32 bits #define MAGIC4(b0_,b1_,b2_,b3_) NU32((((u32)b0_)<<24)|(((u32)b1_)<<16)|(((u32)b2_)<<8)|((u32)b3_)) struct type_class_ttl_rdlen { u16 qtype; u16 qclass; s32 ttl; u16 rdlen; }; #if USES_ICC #ifndef inline #define inline __inline #endif #else #ifndef inline #define inline __inline__ #endif #endif #ifndef _FILE_OFFSET_BITS #define _FILE_OFFSET_BITS 64 #endif #ifdef __cplusplus } #endif #endif /* _SYSTYPES_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/tcp_io_stream.h0000644000000000000000000000013214505005532024622 xustar000000000000000030 mtime=1695812442.027976245 30 atime=1695812445.788030096 30 ctime=1695812494.381726055 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/tcp_io_stream.h0000664000374500037450000001015314505005532024564 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * @{ */ #ifndef _TCP_INPUT_STREAM_H #define _TCP_INPUT_STREAM_H #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif ya_result gethostaddr(const char* host, u16 port, struct sockaddr *sa, int family); ya_result tcp_input_output_stream_connect_sockaddr(const struct sockaddr *sa, input_stream *istream_, output_stream *ostream_, struct sockaddr *bind_from, u8 to_sec); ya_result tcp_input_output_stream_connect_ex(const char *server, u16 port, input_stream *istream_, output_stream *ostream_, struct sockaddr *bind_from, u8 to_sec); ya_result tcp_input_output_stream_connect(const char *server, u16 port, input_stream *istream, output_stream *ostream); ya_result tcp_input_output_stream_connect_host_address(const host_address *ha, input_stream *istream_, output_stream *ostream_, u8 to_sec); ya_result tcp_input_output_stream_connect_host_address_ex(const host_address *ha, input_stream *istream_, output_stream *ostream_, const host_address *bind_to, u8 to_sec); ya_result tcp_io_stream_connect_ex(const char *server, u16 port, io_stream *ios, struct sockaddr *bind_from); ya_result tcp_io_stream_connect(const char *server, u16 port, io_stream *ios); void tcp_set_sendtimeout(int fd, int seconds, int useconds); void tcp_get_sendtimeout(int fd, int *seconds, int *useconds); void tcp_set_recvtimeout(int fd, int seconds, int useconds); void tcp_get_recvtimeout(int fd, int *seconds, int *useconds); void tcp_set_linger(int fd, bool enable, int seconds); /** * Nagle * * @param fd * @param enable */ void tcp_set_nodelay(int fd, bool enable); void tcp_set_cork(int fd, bool enable); static inline void tcp_set_graceful_close(int fd) // no-wait possible { tcp_set_linger(fd, FALSE, 0); } static inline void tcp_set_abortive_close(int fd) // closes now { tcp_set_linger(fd, TRUE, 0); } static inline void tcp_set_agressive_close(int fd, int seconds) // closes up to seconds after the close ... { tcp_set_linger(fd, TRUE, seconds); } void tcp_init_with_env(); #ifdef __cplusplus } #endif #endif /* _TCP_INTPUT_STREAM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/tcp_manager.h0000644000000000000000000000013114505005532024251 xustar000000000000000030 mtime=1695812442.068976832 29 atime=1695812445.78903011 30 ctime=1695812494.383726084 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/tcp_manager.h0000664000374500037450000001302714505005532024217 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #ifndef DNSCORE_HAS_TCP_MANAGER #define DNSCORE_HAS_TCP_MANAGER 0 #endif #ifndef __TCP_MANAGER_C__ #if !DNSCORE_HAS_TCP_MANAGER #error "dnscore/tcp_manager.h should not be included if the TCP manager is disabled" #endif typedef void* tcp_manager_socket_context_t; #endif #define TCP_MANAGER_HOST_CONTEXT_CONNECTION_COUNT_MAX 16 #define TCP_MANAGER_REGISTERED_HOST_CONTEXT_CONNECTION_COUNT_MAX 16 void tcp_manager_init(); void tcp_manager_finalise(); /** * Registers a hosts with its separate allowed connections. */ ya_result tcp_manager_host_register(const socketaddress *sa, socklen_t sa_len, s32 allowed_connections_max); /** * Sets the allowed connections total for all unregistered connections. */ ya_result tcp_manager_connection_max(s32 allowed_connections_max); /** * Accepts a TCP connection and manages it. */ ya_result tcp_manager_accept(int servfd, tcp_manager_socket_context_t **sctxp); /** * Acquires a TCP connection, ensuring exclusive access to the stream. */ tcp_manager_socket_context_t* tcp_manager_context_acquire_from_socket(int sockfd); tcp_manager_socket_context_t* tcp_manager_context_acquire(tcp_manager_socket_context_t *sctx); /** * Releases a TCP connection. */ void tcp_manager_context_release(tcp_manager_socket_context_t *sctx); /** * Closes then releases a TCP connection. (When the last read returned 0 bytes) */ void tcp_manager_context_close_and_release(tcp_manager_socket_context_t *sctx); /** * Updates the amount of bytes sent over an acquired connection. */ void tcp_manager_write_update(tcp_manager_socket_context_t *sctx, size_t buffer_size); /** * Updates the amount of bytes received from an acquired connection. */ void tcp_manager_read_update(tcp_manager_socket_context_t *sctx, size_t buffer_size); /** * Reports an error that occurred using the connection. */ void tcp_manager_error_report(tcp_manager_socket_context_t *sctx, size_t buffer_size); /** * Sends over an acquired connection, calls tcp_manager_write_update. */ ya_result tcp_manager_write(tcp_manager_socket_context_t *sctx, const u8 *buffer, size_t buffer_size); /** * Receives from an acquired connection, calls tcp_manager_write_update. */ ya_result tcp_manager_read(tcp_manager_socket_context_t *sctx, u8 *buffer, size_t buffer_size); /** * Receives from an acquired connection, calls tcp_manager_write_update. */ ya_result tcp_manager_read_fully(tcp_manager_socket_context_t *sctx, u8 *buffer, size_t buffer_size); /** * Marks the TCP stream as being closed. * When the last reference to the TCP stream is lost, then it will be closed and removed from the states collections. */ ya_result tcp_manager_close(tcp_manager_socket_context_t *sctx); /** * Retrieves the address of an acquired connection. */ struct sockaddr* tcp_manager_sockaddr(tcp_manager_socket_context_t *sctx); /** * Retrieves the address length of an acquired connection. */ socklen_t tcp_manager_socklen(tcp_manager_socket_context_t *sctx); /** * Retrieves a pointer to the address length of an acquired connection. * Sounds like a bad idea to use. */ socklen_t *tcp_manager_socklenp(tcp_manager_socket_context_t *sctx); /** * Gets the socket file descriptor of an acquired connection. */ int tcp_manager_socket(tcp_manager_socket_context_t *sctx); void tcp_manager_set_recvtimeout(tcp_manager_socket_context_t *sctx, int seconds, int useconds); void tcp_manager_set_sendtimeout(tcp_manager_socket_context_t *sctx, int seconds, int useconds); void tcp_manager_set_nodelay(tcp_manager_socket_context_t *sctx, bool enable); void tcp_manager_set_cork(tcp_manager_socket_context_t *sctx, bool enable); /** * Not sure it make sense anymore. */ bool tcp_manager_is_valid(tcp_manager_socket_context_t *sctx); yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/thread.h0000644000000000000000000000013114505005532023240 xustar000000000000000029 mtime=1695812442.03397633 30 atime=1695812445.788030096 30 ctime=1695812494.385726113 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/thread.h0000664000374500037450000001120414505005532023201 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #if HAVE_STDNORETURN_H #include #else #define noreturn #endif #include #if !DNSCORE_HAVE_GETTID #include #include static inline pid_t gettid() { return getpid(); } #endif #ifdef __cplusplus extern "C" { #endif typedef pthread_t thread_t; typedef pthread_key_t thread_key_t; typedef pthread_once_t thread_once_t; #if DNSCORE_HAS_LOG_THREAD_TAG /** * @note edf 20180118 -- tags are only read by the logger. Given the current direction setting a tag will likely be sent trough the logger. * */ #define THREAD_TAG_SIZE 8 /** @note edf 20180118 -- please do not change this value */ const char *thread_get_tag_with_pid_and_tid(pid_t pid, thread_t tid); char *thread_copy_tag_with_pid_and_tid(pid_t pid, thread_t tid, char *out_9_bytes); void thread_set_tag_with_pid_and_tid(pid_t pid, thread_t tid, const char *tag8chars); void thread_clear_tag_with_pid_and_tid(pid_t pid, thread_t tid); void thread_make_tag(const char *prefix, u32 index, u32 count, char *service_tag); #endif // system name (visible in top with threads enabled) void thread_set_name(const char *name, int index, int count); static inline thread_t thread_self() { return pthread_self(); } ya_result thread_create(thread_t *t, void* (*function_thread)(void*), void *function_args); ya_result thread_kill(thread_t t, int signo); static inline ya_result thread_join(thread_t t, void **thread_returnp) { int ret = pthread_join(t, thread_returnp); if(ret != 0) { ret = MAKE_ERRNO_ERROR(ret); } return ret; } static noreturn inline void thread_exit(void *parm) { pthread_exit(parm); } static inline ya_result thread_key_create(thread_key_t *k, void (*destructor) (void *)) { int ret = pthread_key_create(k, destructor); if(ret != 0) { ret = MAKE_ERRNO_ERROR(ret); } return ret; } static inline ya_result thread_key_destroy(thread_key_t k) { int ret = pthread_key_delete(k); if(ret != 0) { ret = MAKE_ERRNO_ERROR(ret); } return ret; } static inline ya_result thread_key_set(thread_key_t k, const void *ptr) { int ret = pthread_setspecific(k, ptr); if(ret != 0) { ret = MAKE_ERRNO_ERROR(ret); } return ret; } static inline void *thread_key_get(thread_key_t k) { void* ret = pthread_getspecific(k); return ret; } static inline int thread_once(thread_once_t *once, void (*function) (void)) { int ret = pthread_once(once, function); if(ret != 0) { ret = MAKE_ERRNO_ERROR(ret); } return ret; } #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/thread_pool.h0000644000000000000000000000013214505005532024272 xustar000000000000000030 mtime=1695812442.096977232 30 atime=1695812445.790030125 30 ctime=1695812494.387726141 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/thread_pool.h0000664000374500037450000001721214505005532024237 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _THREAD_POOL_H #define _THREAD_POOL_H #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * There are two ideas behind the thread_pool * * _ The thread are launched once so using * a thread is "instant" (about 0.00001 s) * * _ The tasks can be associated to a counter * so we know exactly how much of these are * running. Some thread are "irrelevant" for * our concurrence issues (axfr, ixfr) * * We just have to have a counter on relevant * threads so we know when we are able to update * * NOTE: I actually do not know how many are * scheduled so I could add this in the counter * */ #define THREAD_STATUS_STARTING 0 #define THREAD_STATUS_WAITING 1 #define THREAD_STATUS_WORKING 2 #define THREAD_STATUS_TERMINATING 3 #define THREAD_STATUS_TERMINATED 4 #define THREAD_POOL_SIZE_LIMIT_MIN 1 #define THREAD_POOL_SIZE_LIMIT_DEFAULT 4096 #define THREAD_POOL_SIZE_LIMIT_MAX 65536 typedef void *thread_pool_function(void*); typedef struct thread_pool_task_counter thread_pool_task_counter; struct thread_pool_task_counter { mutex_t mutex; cond_t cond; volatile s32 value; }; u32 thread_pool_get_max_thread_per_pool_limit(); u32 thread_pool_set_max_thread_per_pool_limit(u32 max_thread_per_pool_limit); void thread_pool_counter_init(thread_pool_task_counter *counter, s32 value); void thread_pool_counter_destroy(thread_pool_task_counter *counter); s32 thread_pool_counter_get_value(thread_pool_task_counter *counter); s32 thread_pool_counter_add_value(thread_pool_task_counter *counter, s32 value); s32 thread_pool_counter_wait_below_or_equal(thread_pool_task_counter *counter, s32 value); s32 thread_pool_counter_wait_equal(thread_pool_task_counter *counter, s32 value); ya_result thread_pool_counter_wait_equal_with_timeout(thread_pool_task_counter *counter, s32 value, u64 usec); struct thread_pool_s; /** * Initialises a thread pool * * @param thread_count number of threads in the pool (max 255) * @param queue_size size of the task queue (when full, enqueue will block until not full) * @param pool_name the friendly name of the thread pool * @return */ struct thread_pool_s *thread_pool_init_ex(u32 thread_count, u32 queue_size, const char* pool_name); /** * Initialises a thread pool * * @param thread_count number of threads in the pool (max 255) * @param queue_size size of the task queue (when full, enqueue will block until not full) * @return */ struct thread_pool_s *thread_pool_init(u32 thread_count, u32 queue_size); /** * Enqueues a function to be executed by a thread pool * Do NOT use this function for concurrent producer-consumer spawning on the same pool as * you will end up with a situation where no slots are available for consumers and everybody is waiting. * Instead, when spawning a group, use thread_pool_enqueue_calls * * @param tp the thread pool * @param func the function * @param parm the parameter for the function * @param counter an optional counter that will be incremented just before the function is called, and decremented just after * @param categoryname an optional string that will be along the thread, mostly for debugging * * @return SUCCESS */ ya_result thread_pool_enqueue_call(struct thread_pool_s *tp, thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char *categoryname); /** * Tries to enqueue a function to be executed by a thread pool * If the queue is not available (high concurrency or full), the function will give up and return ERROR. * * @param tp the thread pool * @param func the function * @param parm the parameter for the function * @param counter an optional counter that will be incremented just before the function is called, and decremented just after * @param categoryname an optional string that will be along the thread, mostly for debugging * * @return SUCCESS if the call has been queued, ERROR if the queue was not available for pushing */ ya_result thread_pool_try_enqueue_call(struct thread_pool_s* tp, thread_pool_function func, void* parm, thread_pool_task_counter *counter, const char* categoryname); struct thread_pool_enqueue_call_item { thread_pool_function *func; void *parm; thread_pool_task_counter *counter; const char *categoryname; }; typedef struct thread_pool_enqueue_call_item thread_pool_enqueue_call_item; ya_result thread_pool_stop(struct thread_pool_s* tp); ya_result thread_pool_destroy(struct thread_pool_s *tp); /** * Waits until all threads in the pool are up and ready * * @param tp * @return */ ya_result thread_pool_wait_all_running(struct thread_pool_s *tp); /** * Returns the new size of the pool or an error. * * @param tp * @param new_size * @return */ ya_result thread_pool_resize(struct thread_pool_s* tp, u32 new_size); random_ctx thread_pool_get_random_ctx(); void thread_pool_setup_random_ctx(); void thread_pool_destroy_random_ctx(); u32 thread_pool_get_size(struct thread_pool_s *tp); /** * * Returns the current size of the thread pool * * @param tp * @return */ int thread_pool_queue_size(struct thread_pool_s *tp); void thread_pool_wait_queue_empty(struct thread_pool_s *tp); /** * Returns the index of the thread in the thread-pool. */ u32 thread_pool_thread_index_get(); // before and after a fork ya_result thread_pool_stop_all(); // fork ya_result thread_pool_start_all(); #ifdef __cplusplus } #endif #endif /* _THREAD_POOL_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/thread-tag.h0000644000000000000000000000013114505005531024010 xustar000000000000000030 mtime=1695812441.991975729 30 atime=1695812445.786030067 29 ctime=1695812494.38972617 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/thread-tag.h0000664000374500037450000000562014505005531023756 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif #if DNSCORE_HAS_LOG_THREAD_TAG /** * @note edf 20180118 -- tags are only read by the logger. Given the current direction setting a tag will likely be sent trough the logger. * */ #define THREAD_TAG_SIZE 8 /** @note edf 20180118 -- please do not change this value */ const char *thread_get_tag_with_pid_and_tid(pid_t pid, thread_t tid); char *thread_copy_tag_with_pid_and_tid(pid_t pid, thread_t tid, char *out_9_bytes); void thread_set_tag_with_pid_and_tid(pid_t pid, thread_t tid, const char *tag8chars); void thread_clear_tag_with_pid_and_tid(pid_t pid, thread_t tid); void thread_make_tag(const char *prefix, u32 index, u32 count, char *service_tag); // system name (visible in top with threads enabled) void thread_set_name(const char *name, int index, int count); #endif #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/threaded-qsl-cw.h0000644000000000000000000000013214505005532024756 xustar000000000000000030 mtime=1695812442.037976387 30 atime=1695812445.788030096 30 ctime=1695812494.391726199 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/threaded-qsl-cw.h0000664000374500037450000000714614505005532024730 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * This version of the ring buffer uses the condition-wait mechanism instead of the 3-mutex one. * I'll have to bench both versions but the main incentive is to get rid of complains from helgrind * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #include #ifdef __cplusplus extern "C" { #endif struct threaded_qsl_cw { queue_sl_s queue; queue_sl_node_s *pool; mutex_t mutex; cond_t cond_read; cond_t cond_write; u32 max_size; }; typedef struct threaded_qsl_cw threaded_qsl_cw; #define THREADED_SLL_CW_EMPTY {{NULL,NULL},{NULL,NULL},0}, NULL, MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER,MAX_U32} void threaded_qsl_cw_init(threaded_qsl_cw *queue, int max_size); void threaded_qsl_cw_finalize(threaded_qsl_cw *queue); void threaded_qsl_cw_enqueue(threaded_qsl_cw *queue,void* constant_pointer); bool threaded_qsl_cw_try_enqueue(threaded_qsl_cw *queue,void* constant_pointer); void* threaded_qsl_cw_dequeue(threaded_qsl_cw *queue); void* threaded_qsl_cw_try_dequeue(threaded_qsl_cw *queue); void threaded_qsl_cw_wait_empty(threaded_qsl_cw *queue); int threaded_qsl_cw_size(threaded_qsl_cw *queue); int threaded_qsl_cw_room(threaded_qsl_cw *queue); /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ ya_result threaded_qsl_cw_set_maxsize(threaded_qsl_cw *queue, int max_size); #ifdef __cplusplus } #endif /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/threaded_dll_cw.h0000644000000000000000000000013214505005532025076 xustar000000000000000030 mtime=1695812442.002975886 30 atime=1695812445.787030082 30 ctime=1695812494.393726227 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/threaded_dll_cw.h0000664000374500037450000000714414505005532025046 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * This version of the ring buffer uses the condition-wait mechanism instead of the 3-mutex one. * I'll have to bench both versions but the main incentive is to get rid of complains from helgrind * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #include #ifdef __cplusplus extern "C" { #endif struct threaded_dll_cw { list_dl_s queue; list_dl_node_s *pool; mutex_t mutex; cond_t cond_read; cond_t cond_write; u32 max_size; }; typedef struct threaded_dll_cw threaded_dll_cw; #define THREADED_SLL_CW_EMPTY {{NULL,NULL},{NULL,NULL},0}, NULL, MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER,MAX_U32} void threaded_dll_cw_init(threaded_dll_cw *queue, int max_size); void threaded_dll_cw_finalize(threaded_dll_cw *queue); void threaded_dll_cw_enqueue(threaded_dll_cw *queue,void* constant_pointer); bool threaded_dll_cw_try_enqueue(threaded_dll_cw *queue,void* constant_pointer); void* threaded_dll_cw_dequeue(threaded_dll_cw *queue); void* threaded_dll_cw_try_dequeue(threaded_dll_cw *queue); void* threaded_dll_cw_dequeue_with_timeout(threaded_dll_cw *queue, s64 timeout_us); void threaded_dll_cw_wait_empty(threaded_dll_cw *queue); int threaded_dll_cw_size(threaded_dll_cw *queue); int threaded_dll_cw_room(threaded_dll_cw *queue); /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ ya_result threaded_dll_cw_set_maxsize(threaded_dll_cw *queue, int max_size); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/threaded_nb_mm.h0000644000000000000000000000013114505005532024721 xustar000000000000000030 mtime=1695812442.076976946 29 atime=1695812445.78903011 30 ctime=1695812494.395726256 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/threaded_nb_mm.h0000664000374500037450000000510514505005532024665 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief "no-wait" stack allocator * meant to be used with the "no-wait" queue * * @{ * *----------------------------------------------------------------------------*/ #ifndef __THREADED_NB_MM_H__ #define __THREADED_NB_MM_H__ #include typedef struct threaded_nb_mm threaded_nb_mm; struct threaded_nb_mm { u8 * volatile items; volatile void **item_head; u32 item_size; u32 item_count; }; void threaded_nb_mm_init(threaded_nb_mm *mm, u32 count, u32 size); void* threaded_nb_mm_alloc(threaded_nb_mm *mm); void threaded_nb_mm_free(threaded_nb_mm *mm, void *p); void threaded_nb_mm_finalize(threaded_nb_mm *mm); #endif /** * @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/threaded_nbrb.h0000644000000000000000000000013214505005532024555 xustar000000000000000030 mtime=1695812442.108977405 30 atime=1695812445.790030125 30 ctime=1695812494.398726299 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/threaded_nbrb.h0000664000374500037450000000424414505005532024523 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * @{ * *----------------------------------------------------------------------------*/ #ifndef _THREADED_NB_RINGBUFFER_H #define _THREADED_NB_RINGBUFFER_H #include #include #endif /* _THREADED_QUEUE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/threaded_queue.h0000644000000000000000000000013214505005532024756 xustar000000000000000030 mtime=1695812442.110977433 30 atime=1695812445.790030125 30 ctime=1695812494.400726327 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/threaded_queue.h0000664000374500037450000003067414505005532024732 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _THREADED_QUEUE_H #define _THREADED_QUEUE_H /* * Four implementations of the threaded queue can be used ... */ #define THREADED_QUEUE_RINGLIST 1 #define THREADED_QUEUE_RINGBUFFER 2 #define THREADED_QUEUE_RINGBUFFER_CW 3 #define THREADED_QUEUE_NBRB 4 #define THREADED_QUEUE_DLL_CW 5 #define THREADED_QUEUE_SLG 6 /* typedef void threaded_queue_init_method(threaded_queue *queue, int max_size); typedef void threaded_queue_finalize_method(threaded_queue *queue); typedef void threaded_queue_enqueue_method(threaded_queue *queue,void* constant_pointer); typedef bool threaded_queue_try_enqueue_method(threaded_queue *queue,void* constant_pointer); typedef void* threaded_queue_peek_method(threaded_queue *queue); typedef void* threaded_queue_try_peek_method(threaded_queue *queue); typedef void* threaded_queue_dequeue_method(threaded_queue *queue); typedef void* threaded_queue_try_dequeue_method(threaded_queue *queue); typedef u32 threaded_queue_dequeue_set_method(threaded_queue *queue, void** array, u32 array_size); typedef void threaded_queue_wait_empty_method(threaded_queue *queue); typedef int threaded_queue_size_method(threaded_queue *queue); struct threaded_queue_vtbl { threaded_queue_enqueue_method *enqueue; threaded_queue_dequeue_method *dequeue; threaded_queue_peek_method *peek; threaded_queue_try_enqueue_method *try_enqueue; threaded_queue_try_dequeue_method *try_dequeue; threaded_queue_try_peek_method *try_peek; threaded_queue_dequeue_set_method *dequeue_set; threaded_queue_wait_empty_method *wait_empty; threaded_queue_size_method *size; threaded_queue_finalize_method *finalize; }; struct threaded_queue_wrapper { struct threaded_queue_vtbl *vtbl; void *data; }; */ #ifndef THREADED_QUEUE_MODE #define THREADED_QUEUE_MODE THREADED_QUEUE_RINGBUFFER_CW #else // THREADED_QUEUE_MODE should be set globally #endif #if THREADED_QUEUE_MODE == THREADED_QUEUE_RINGLIST #define THREADED_QUEUE ringlist #include typedef struct threaded_ringlist threaded_queue; #define THREADED_QUEUE_EMPTY THREADED_RINGLIST_EMPTY #define threaded_queue_init(queue_,max_size_) threaded_ringlist_init((queue_),(max_size_)) #define threaded_queue_finalize(queue_) threaded_ringlist_finalize((queue_)) #define threaded_queue_enqueue(queue_,constant_pointer_) threaded_ringlist_enqueue((queue_),(constant_pointer_)) #define threaded_queue_try_enqueue(queue_,constant_pointer_) threaded_ringlist_try_enqueue((queue_),(constant_pointer_)) #define threaded_queue_dequeue(queue_) threaded_ringlist_dequeue((queue_)) #define threaded_queue_try_dequeue(queue_) threaded_ringlist_try_dequeue((queue_)) #define threaded_queue_dequeue_set(queue_, array_, size_) threaded_ringlist_dequeue_set((queue_),(array_),(size_)) #define threaded_queue_wait_empty(queue_) threaded_ringlist_wait_empty((queue_)) #define threaded_queue_size(queue_) threaded_ringlist_size((queue_)) /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ #define threaded_queue_set_maxsize(queue_, max_size_) threaded_ringlist_set_maxsize((queue_), (max_size_)) #elif THREADED_QUEUE_MODE == THREADED_QUEUE_RINGBUFFER #define THREADED_QUEUE ringbuffer #include typedef struct threaded_ringbuffer threaded_queue; #define THREADED_QUEUE_EMPTY THREADED_RINGBUFFER_NULL #define threaded_queue_init(queue_,max_size_) threaded_ringbuffer_init((queue_),(max_size_)) #define threaded_queue_finalize(queue_) threaded_ringbuffer_finalize((queue_)) #define threaded_queue_enqueue(queue_,constant_pointer_) threaded_ringbuffer_enqueue((queue_),(constant_pointer_)) #define threaded_queue_try_enqueue(queue_,constant_pointer_) threaded_ringbuffer_try_enqueue((queue_),(constant_pointer_)) #define threaded_queue_dequeue(queue_) threaded_ringbuffer_dequeue((queue_)) #define threaded_queue_try_dequeue(queue_) threaded_ringbuffer_try_dequeue((queue_)) #define threaded_queue_dequeue_set(queue_, array_, size_) threaded_ringbuffer_dequeue_set((queue_),(array_),(size_)) #define threaded_queue_wait_empty(queue_) threaded_ringbuffer_wait_empty((queue_)) #define threaded_queue_size(queue_) threaded_ringbuffer_size((queue_)) /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ #define threaded_queue_set_maxsize(queue_, max_size_) threaded_ringbuffer_set_maxsize((queue_), (max_size_)) #elif THREADED_QUEUE_MODE == THREADED_QUEUE_RINGBUFFER_CW #define THREADED_QUEUE ringbuffer_cw #include typedef struct threaded_ringbuffer_cw threaded_queue; #define THREADED_QUEUE_EMPTY THREADED_RINGBUFFER_CW_EMPTY #define threaded_queue_init(queue_,max_size_) threaded_ringbuffer_cw_init((queue_),(max_size_)) #define threaded_queue_finalize(queue_) threaded_ringbuffer_cw_finalize((queue_)) #define threaded_queue_enqueue(queue_,constant_pointer_) threaded_ringbuffer_cw_enqueue((queue_),(constant_pointer_)) #define threaded_queue_try_enqueue(queue_,constant_pointer_) threaded_ringbuffer_cw_try_enqueue((queue_),(constant_pointer_)) #define threaded_queue_peek(queue_) threaded_ringbuffer_cw_peek((queue_)) #define threaded_queue_try_peek(queue_) threaded_ringbuffer_cw_try_peek((queue_)) #define threaded_queue_dequeue(queue_) threaded_ringbuffer_cw_dequeue((queue_)) #define threaded_queue_try_dequeue(queue_) threaded_ringbuffer_cw_try_dequeue((queue_)) #define threaded_queue_dequeue_set(queue_, array_, size_) threaded_ringbuffer_cw_dequeue_set((queue_),(array_),(size_)) #define threaded_queue_wait_empty(queue_) threaded_ringbuffer_cw_wait_empty((queue_)) #define threaded_queue_size(queue_) threaded_ringbuffer_cw_size((queue_)) /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ #define threaded_queue_set_maxsize(queue_, max_size_) threaded_ringbuffer_cw_set_maxsize((queue_), (max_size_)) #elif THREADED_QUEUE_MODE == THREADED_QUEUE_NBRB #define THREADED_QUEUE nbrb #include typedef struct threaded_nbrb threaded_queue; #define THREADED_QUEUE_EMPTY THREADED_NBRB_EMPTY #define threaded_queue_init(queue_,max_size_) threaded_nbrb_init((queue_),(max_size_)) #define threaded_queue_finalize(queue_) threaded_nbrb_finalize((queue_)) #define threaded_queue_enqueue(queue_,constant_pointer_) threaded_nbrb_enqueue((queue_),(constant_pointer_)) #define threaded_queue_try_enqueue(queue_,constant_pointer_) threaded_nbrb_try_enqueue((queue_),(constant_pointer_)) #define threaded_queue_peek(queue_) threaded_nbrb_peek((queue_)) #define threaded_queue_try_peek(queue_) threaded_nbrb_try_peek((queue_)) #define threaded_queue_dequeue(queue_) threaded_nbrb_dequeue((queue_)) #define threaded_queue_try_dequeue(queue_) threaded_nbrb_try_dequeue((queue_)) #define threaded_queue_dequeue_set(queue_, array_, size_) threaded_nbrb_dequeue_set((queue_),(array_),(size_)) #define threaded_queue_wait_empty(queue_) threaded_nbrb_wait_empty((queue_)) #define threaded_queue_size(queue_) threaded_nbrb_size((queue_)) /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ #define threaded_queue_set_maxsize(queue_, max_size_) threaded_nbrb_set_maxsize((queue_), (max_size_)) #elif THREADED_QUEUE_MODE == THREADED_QUEUE_DLL_CW #define THREADED_QUEUE dll_cw #include typedef struct threaded_dll_cw threaded_queue; #define THREADED_QUEUE_EMPTY THREADED_SLL_CW_EMPTY #define threaded_queue_init(queue_,max_size_) threaded_dll_cw_init((queue_),(max_size_)) #define threaded_queue_finalize(queue_) threaded_dll_cw_finalize((queue_)) #define threaded_queue_enqueue(queue_,constant_pointer_) threaded_dll_cw_enqueue((queue_),(constant_pointer_)) #define threaded_queue_try_enqueue(queue_,constant_pointer_) threaded_dll_cw_try_enqueue((queue_),(constant_pointer_)) #define threaded_queue_peek(queue_) threaded_dll_cw_peek((queue_)) #define threaded_queue_try_peek(queue_) threaded_dll_cw_try_peek((queue_)) #define threaded_queue_dequeue(queue_) threaded_dll_cw_dequeue((queue_)) #define threaded_queue_try_dequeue(queue_) threaded_dll_cw_try_dequeue((queue_)) #define threaded_queue_dequeue_set(queue_, array_, size_) threaded_dll_cw_dequeue_set((queue_),(array_),(size_)) #define threaded_queue_wait_empty(queue_) threaded_dll_cw_wait_empty((queue_)) #define threaded_queue_size(queue_) threaded_dll_cw_size((queue_)) /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ #define threaded_queue_set_maxsize(queue_, max_size_) threaded_dll_cw_set_maxsize((queue_), (max_size_)) #elif THREADED_QUEUE_MODE == THREADED_QUEUE_SLG #define THREADED_QUEUE slg #include typedef threaded_queue_slg_t threaded_queue; #define THREADED_QUEUE_EMPTY THREADED_SLL_CW_EMPTY #define threaded_queue_init(queue_,max_size_) threaded_queue_slg_init((queue_),(max_size_)) #define threaded_queue_finalize(queue_) threaded_queue_slg_finalize((queue_)) #define threaded_queue_enqueue(queue_,constant_pointer_) threaded_queue_slg_enqueue((queue_),(constant_pointer_)) #define threaded_queue_try_enqueue(queue_,constant_pointer_) threaded_queue_slg_try_enqueue((queue_),(constant_pointer_)) #define threaded_queue_peek(queue_) threaded_queue_slg_peek((queue_)) #define threaded_queue_try_peek(queue_) threaded_queue_slg_try_peek((queue_)) #define threaded_queue_dequeue(queue_) threaded_queue_slg_dequeue((queue_)) #define threaded_queue_try_dequeue(queue_) threaded_queue_slg_try_dequeue((queue_)) #define threaded_queue_dequeue_set(queue_, array_, size_) threaded_queue_slg_dequeue_set((queue_),(array_),(size_)) #define threaded_queue_wait_empty(queue_) threaded_queue_slg_wait_empty((queue_)) #define threaded_queue_size(queue_) threaded_queue_slg_size((queue_)) /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ #define threaded_queue_set_maxsize(queue_, max_size_) threaded_slg_set_maxsize((queue_), (max_size_)) #else #error THREADED_QUEUE_MODE has not been set to a supported value #endif #endif /* _THREADED_QUEUE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/threaded_queue_slg.h0000644000000000000000000000013214505005532025623 xustar000000000000000030 mtime=1695812442.015976072 30 atime=1695812445.787030082 30 ctime=1695812494.402726356 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/threaded_queue_slg.h0000664000374500037450000001057014505005532025570 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * This version of the ring buffer uses the condition-wait mechanism instead of the 3-mutex one. * I'll have to bench both versions but the main incentive is to get rid of complains from helgrind * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #include #define L1_DATA_LINE_SIZE 0x40 #ifdef __cplusplus extern "C" { #endif #define THREADED_QUEUE_PAGE_SIZE 4096 #define THREADED_QUEUE_SQL_SLOTS ((THREADED_QUEUE_PAGE_SIZE / __SIZEOF_POINTER__) - 2) struct threaded_queue_slg_page_s { intptr size; void *data[THREADED_QUEUE_SQL_SLOTS]; struct threaded_queue_slg_page_s *next; }; typedef struct threaded_queue_slg_page_s threaded_queue_slg_page_t; struct threaded_queue_slg_s { mutex_t mtx; cond_t read_cond; intptr read_index; threaded_queue_slg_page_t *page_pool; #if __unix__ threaded_queue_slg_page_t *read_page __attribute__ ((aligned (L1_DATA_LINE_SIZE))); threaded_queue_slg_page_t *write_page __attribute__ ((aligned (L1_DATA_LINE_SIZE))); #else threaded_queue_slg_page_t* read_page; threaded_queue_slg_page_t* write_page; #endif }; typedef struct threaded_queue_slg_s threaded_queue_slg_t; #define THREADED_QUEUE_SLG_EMPTY {MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, NULL, NULL, NULL} void threaded_queue_slg_init(threaded_queue_slg_t *q, int ignored_size); void threaded_queue_slg_finalize(threaded_queue_slg_t *q); void threaded_queue_slg_enqueue(threaded_queue_slg_t *q, void *data); static inline bool threaded_queue_slg_try_enqueue(threaded_queue_slg_t *q, void *data) { threaded_queue_slg_enqueue(q, data); return TRUE; } void* threaded_queue_slg_dequeue(threaded_queue_slg_t *q); void threaded_queue_slg_wait_empty(threaded_queue_slg_t *q); bool threaded_queue_slg_try_enqueue(threaded_queue_slg_t *queue,void* constant_pointer); void* threaded_queue_slg_try_dequeue(threaded_queue_slg_t *queue); void* threaded_queue_slg_dequeue_with_timeout(threaded_queue_slg_t *queue, s64 timeout_us); int threaded_queue_slg_size(threaded_queue_slg_t *q); int threaded_queue_slg_room(threaded_queue_slg_t *q); /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ ya_result threaded_queue_slg_set_maxsize(threaded_queue_slg_t *q, int max_size); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/threaded_ringbuffer.h0000644000000000000000000000013214505005532025763 xustar000000000000000030 mtime=1695812442.092977176 30 atime=1695812445.790030125 30 ctime=1695812494.404726385 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/threaded_ringbuffer.h0000664000374500037450000000740314505005532025731 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _THREADED_RINGBUFFER_H #define _THREADED_RINGBUFFER_H #include #include #ifdef __cplusplus extern "C" { #endif typedef struct threaded_ringbuffer threaded_ringbuffer; struct threaded_ringbuffer_node; /* NOTE: The algorithm does not need these to be volatile */ struct threaded_ringbuffer { void** buffer; void** buffer_limit; void** write_slot; void** read_slot; mutex_t mutex; mutex_t mutex_enqueue; mutex_t mutex_dequeue; u32 max_size; u32 size; }; #define THREADED_RINGBUFFER_NULL {0,0,0,0,MUTEX_INITIALIZER,MUTEX_INITIALIZER,MUTEX_INITIALIZER,0,0} void threaded_ringbuffer_init(threaded_ringbuffer* queue, int max_size); void threaded_ringbuffer_finalize(threaded_ringbuffer* queue); void threaded_ringbuffer_enqueue(threaded_ringbuffer* queue,void* constant_pointer); bool threaded_ringbuffer_try_enqueue(threaded_ringbuffer* queue,void* constant_pointer); void* threaded_ringbuffer_peek(threaded_ringbuffer* queue); void* threaded_ringbuffer_try_peek(threaded_ringbuffer* queue); void* threaded_ringbuffer_dequeue(threaded_ringbuffer* queue); void* threaded_ringbuffer_try_dequeue(threaded_ringbuffer *queue); u32 threaded_ringbuffer_dequeue_set(threaded_ringbuffer* queue, void** array, u32 array_size); void threaded_ringbuffer_wait_empty(threaded_ringbuffer* queue); int threaded_ringbuffer_size(threaded_ringbuffer* queue); /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ ya_result threaded_ringbuffer_set_maxsize(threaded_ringbuffer *queue, int max_size); #ifdef __cplusplus } #endif #endif /* _THREADED_QUEUE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/threaded_ringbuffer_cw.h0000644000000000000000000000013114505005532026453 xustar000000000000000029 mtime=1695812442.01297603 30 atime=1695812445.787030082 30 ctime=1695812494.406726414 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/threaded_ringbuffer_cw.h0000664000374500037450000001045014505005532026416 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * This version of the ring buffer uses the condition-wait mechanism instead of the 3-mutex one. * I'll have to bench both versions but the main incentive is to get rid of complains from helgrind * * @{ * *----------------------------------------------------------------------------*/ #ifndef _THREADED_RINGBUFFER_CW_H #define _THREADED_RINGBUFFER_CW_H #include #include #ifdef __cplusplus extern "C" { #endif typedef struct threaded_ringbuffer_cw threaded_ringbuffer_cw; struct threaded_ringbuffer_cw_node; /* NOTE: The algorithm does not need these to be volatile */ struct threaded_ringbuffer_cw { void** buffer; void** buffer_limit; void** write_slot; void** read_slot; mutex_t mutex; cond_t cond_read; cond_t cond_write; u32 max_size; u32 size; }; #define THREADED_RINGBUFFER_CW_EMPTY {0,0,0,0,MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,PTHREAD_COND_INITIALIZER,0,0} void threaded_ringbuffer_cw_init(threaded_ringbuffer_cw *queue, int max_size); void threaded_ringbuffer_cw_finalize(threaded_ringbuffer_cw *queue); void threaded_ringbuffer_cw_enqueue(threaded_ringbuffer_cw *queue,void* constant_pointer); void threaded_ringbuffer_cw_enqueue_set(threaded_ringbuffer_cw *queue, void **constant_pointer_array, u32 count); bool threaded_ringbuffer_cw_try_enqueue(threaded_ringbuffer_cw *queue,void* constant_pointer); void* threaded_ringbuffer_cw_peek(threaded_ringbuffer_cw *queue); void* threaded_ringbuffer_cw_try_peek(threaded_ringbuffer_cw *queue); void* threaded_ringbuffer_cw_dequeue(threaded_ringbuffer_cw *queue); void* threaded_ringbuffer_cw_dequeue_with_timeout(threaded_ringbuffer_cw *queue, s64 timeout_us); void* threaded_ringbuffer_cw_try_dequeue(threaded_ringbuffer_cw *queue); u32 threaded_ringbuffer_cw_dequeue_set(threaded_ringbuffer_cw *queue, void** array, u32 array_size); void threaded_ringbuffer_cw_wait_empty(threaded_ringbuffer_cw *queue); u32 threaded_ringbuffer_cw_size(threaded_ringbuffer_cw *queue); int threaded_ringbuffer_cw_room(threaded_ringbuffer_cw *queue); /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ ya_result threaded_ringbuffer_cw_set_maxsize(threaded_ringbuffer_cw *queue, int max_size); #ifdef __cplusplus } #endif #endif /* _THREADED_QUEUE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/threaded_ringlist.h0000644000000000000000000000013114505005532025464 xustar000000000000000030 mtime=1695812442.058976688 29 atime=1695812445.78903011 30 ctime=1695812494.408726442 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/threaded_ringlist.h0000664000374500037450000001013414505005532025426 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _THREADED_RINGLIST_H #define _THREADED_RINGLIST_H #include #include #ifdef MUTEX_USE_SPINLOCK #error "Cascaded MUTEX_USE_SPINLOCK definition. Please remove the potential definition mistmatch (#undef ?)" #endif #define MUTEX_USE_SPINLOCK 0 #include #include #ifdef __cplusplus extern "C" { #endif typedef struct threaded_ringlist threaded_ringlist; struct threaded_ringlist_node; struct threaded_ringlist { /* DO NOT MOVE THESE POINTERS */ struct threaded_ringlist_node *next; struct threaded_ringlist_node *prev; /* -------------------------- */ struct threaded_ringlist_node *pool; mutex_t mutex; mutex_t mutex_enqueue; mutex_t mutex_dequeue; volatile u32 max_size; /* DO NOT CACHE THIS INTO REGISTERS */ volatile u32 size; /* DO NOT CACHE THIS INTO REGISTERS */ }; #define THREADED_RINGLIST_EMPTY {0,0,0,MUTEX_INITIALIZER,MUTEX_INITIALIZER,MUTEX_INITIALIZER,0,0} void threaded_ringlist_init(threaded_ringlist* queue, int max_size); void threaded_ringlist_finalize(threaded_ringlist* queue); void threaded_ringlist_enqueue(threaded_ringlist* queue,void* constant_pointer); bool threaded_ringlist_try_enqueue(threaded_ringlist* queue,void* constant_pointer); void* threaded_ringlist_peek(threaded_ringlist* queue); void* threaded_ringlist_try_peek(threaded_ringlist* queue); void* threaded_ringlist_dequeue(threaded_ringlist* queue); void* threaded_ringlist_try_dequeue(threaded_ringlist *queue); u32 threaded_ringlist_dequeue_set(threaded_ringlist* queue, void** array, u32 array_size); void threaded_ringlist_wait_empty(threaded_ringlist* queue); int threaded_ringlist_size(threaded_ringlist* queue); /* * The queue will block (write) if bigger than this. * Note that if the key is already bigger it will blocked (write) until * the content is emptied by the readers. */ ya_result threaded_ringlist_set_maxsize(threaded_ringlist *queue, int max_size); #undef MUTEX_USE_SPINLOCK #ifdef __cplusplus } #endif #endif /* _THREADED_QUEUE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/timeformat.h0000644000000000000000000000013114505005532024140 xustar000000000000000029 mtime=1695812442.04997656 30 atime=1695812445.788030096 30 ctime=1695812494.410726471 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/timeformat.h0000664000374500037450000001611014505005532024102 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup format C-string formatting * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _TIMEFORMAT_H #define _TIMEFORMAT_H /* * Format extensions related to dns * * dnsname : u8* dns name * dnslabel : u8* dns label (pascal string) * class : u16* zone class * type : u16* record type */ #include #ifdef __cplusplus extern "C" { #endif /** * writers of formats * * */ // dtus 0000-00-00 00:00:00.000000U void datetimeus_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); // 0000-00-00 00:00:00.000000 void localdatetimeus_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); // dtms 0000-00-00 00:00:00.000 void datetimems_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); // dts 0000-00-00 00:00:00 void datetime_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); // ldts 0000-00-00 00:00:00 void localdatetime_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); // date 0000-00-00 void date_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); // time 00:00:00 void time_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); // epoch 0000-00-00 00:00:00U void epoch_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); // epoch 0000-00-00 00:00:00 void localepoch_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); // epoch 0000-00-00 00:00:00 or "" void epochz_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); // epoch 00000000000000 void packedepoch_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters); /** * Macros for use with the %w format * */ #define DATETIMEUS_DEF2(variable,realvariable) format_writer variable##_format_writer = {datetimeus_format_handler_method, (void*)(intptr)realvariable} #define DATETIMEUS_DEF(variable) format_writer variable##_format_writer = {datetimeus_format_handler_method, (void*)(intptr)variable} #define DATETIMEUS_REF(variable) &variable##_format_writer #define DATETIMEMS_DEF2(variable,realvariable) format_writer variable##_format_writer = {datetimems_format_handler_method, (void*)(intptr)realvariable} #define DATETIMEMS_DEF(variable) format_writer variable##_format_writer = {datetimems_format_handler_method, (void*)(intptr)variable} #define DATETIMEMS_REF(variable) &variable##_format_writer #define DATETIME_DEF2(variable,realvariable) format_writer variable##_format_writer = {datetime_format_handler_method, (void*)(intptr)realvariable} #define DATETIME_DEF(variable) format_writer variable##_format_writer = {datetime_format_handler_method, (void*)(intptr)variable} #define DATETIME_REF(variable) &variable##_format_writer #define DATE_DEF2(variable,realvariable) format_writer variable##_format_writer = {date_format_handler_method, (void*)(intptr)realvariable} #define DATE_DEF(variable) format_writer variable##_format_writer = {date_format_handler_method, (void*)(intptr)variable} #define DATE_REF(variable) &variable##_format_writer #define TIME_DEF2(variable,realvariable) format_writer variable##_format_writer = {time_format_handler_method, (void*)(intptr)realvariable} #define TIME_DEF(variable) format_writer variable##_format_writer = {time_format_handler_method, (void*)(intptr)variable} #define TIME_REF(variable) &variable##_format_writer #define EPOCH_DEF2(variable,realvariable) format_writer variable##_format_writer = {epoch_format_handler_method, (void*)(intptr)realvariable} #define EPOCH_DEF(variable) format_writer variable##_format_writer = {epoch_format_handler_method, (void*)(intptr)variable} #define EPOCH_REF(variable) &variable##_format_writer #define EPOCHZ_DEF2(variable,realvariable) format_writer variable##_format_writer = {epochz_format_handler_method, (void*)(intptr)realvariable} #define EPOCHZ_DEF(variable) format_writer variable##_format_writer = {epochz_format_handler_method, (void*)(intptr)variable} #define EPOCHZ_REF(variable) &variable##_format_writer void timeformat_class_init(); #ifdef __cplusplus } #endif #endif /* _DNSFORMAT_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/timems.h0000644000000000000000000000013014505005532023266 xustar000000000000000030 mtime=1695812442.030976288 30 atime=1695812445.788030096 28 ctime=1695812494.4127265 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/timems.h0000664000374500037450000001331614505005532023236 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoretools Generic Tools * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _TIMEMS_H #define _TIMEMS_H #include #include #include #ifdef __cplusplus extern "C" { #endif #define ONE_SECOND_US 1000000LL #define ONE_SECOND_US_F 1000000.0 /** * A local implementation of struct tm *t * * @param tv * @return */ time_t timegm_internal(struct tm *tv); /* * Returns the time in us */ s64 timeus(); /* * Returns the time in us and sets the pointed s32 to the time in s */ s64 timeus_and_s(s32 *seconds_ptr); /* * Returns the time in ms */ s64 timems(); /* * Waits until the ms is incremented, then returns the time in ms */ s64 timems_new(); /** * usleep only support a limited range of time (sometimes 2^32 us, sometimes < 1 s) * This wrapper ensures time supported is up to 4294967295.000000 seconds * * @param us the number of microseconds to wait for, can range from 0 to 4294967295000000 micro seconds */ void usleep_ex(u64 us_); void usleep_until(s64 epoch_us); time_t mkgmtime(const struct tm *tm); bool time_is_leap_year(int y); int time_days_in_month(int y, int m); /** * Retrieves the first day of the month. * * 0 is Sunday * * @param year 0-based * @param month 0-based * @return the number of the day of the month or an error code */ int time_first_day_of_month(int year, int month); /** * Sun to Sat * * @param day * * @return A 3 letters name followed by a zero */ const char * time_get_day_of_week_name(int day); /** * Jan to Dec * * @param month * @return A 3 letters name followed by a zero */ const char * time_get_month_of_year_name(int month); /** * Convert time structure into the text format defined by RFC5322 (GMT) * Does put a '\0' at the end of the buffer. * Requires a buffer of at least 29 bytes. * * @param epoch * @param buffer * @param buffer_size * * @return the number of chars written or an error */ ya_result time_tm_as_rfc5322(const struct tm *t, char *buffer, size_t buffer_size); /** * Convert epoch into the text format defined by RFC5322 (GMT) * Does put a '\0' at the end of the buffer. * Requires a buffer of at least 29 bytes. * * @param epoch * @param buffer * @param buffer_size * * @return the number of chars written or an error */ ya_result time_epoch_as_rfc5322(time_t epoch, char *buffer, size_t buffer_size); /** * Returns timeus() - offset * Used to fake the current time. */ s64 timeus_with_offset(); /** * Sets the offset of the time returned by timeus_with_offset() */ void timeus_set_offset(s64 us); /** * Parses a text as a date/time and converts it to an epoch in microseconds. * * yesterday * now * tomorrow * +1y +1year +1years (months,weeks,days,seconds) * -1y -1year -1years (months,weeks,days,seconds) * 2019-04-16 * 2019-04-16_12:00:00.123456 * 20190416 * 20190416120000123456 * */ s64 timeus_from_smarttime_ex(const char *text, s64 now); /** * Parses a text as a date/time and converts it to an epoch in microseconds. * * yesterday * now * tomorrow * +1y +1year +1years (months,weeks,days,seconds) * -1y -1year -1years (months,weeks,days,seconds) * 2019-04-16 * 2019-04-16_12:00:00.123456 * 20190416 * 20190416120000123456 * */ s64 timeus_from_smarttime(const char *text); static inline double timeus_diff_seconds_double(s64 from, s64 to) { double ret = (double)(to - from); ret /= ONE_SECOND_US_F; return ret; } static inline double timeus_diff_ms_double(s64 from, s64 to) { double ret = (double)(to - from); ret /= 1000.0; return ret; } static inline s64 timeus_diff_ms(s64 from, s64 to) { s64 ret = (to - from); ret /= 1000LL; return ret; } static inline s64 time_to_timeus(time_t t) { return (ONE_SECOND_US * t); } #ifdef __cplusplus } #endif #endif /* _TIMEMS_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/typebitmap.h0000644000000000000000000000013214505005532024150 xustar000000000000000030 mtime=1695812442.008975972 30 atime=1695812445.787030082 30 ctime=1695812494.414726528 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/typebitmap.h0000664000374500037450000001012214505005532024106 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _TYPEBITMAP_H #define _TYPEBITMAP_H #include #include #ifdef __cplusplus extern "C" { #endif typedef struct type_bit_maps_context type_bit_maps_context; /* * Maximum type bitmap size = * * (1+1+32) * 256 = 8704 * */ #define TYPE_BIT_MAPS_MAX_RDATA_SIZE 8704 struct type_bit_maps_context { u32 type_bit_maps_size; s32 last_type_window; u8 window_size[256]; u8 type_bitmap_field[8192]; }; void type_bit_maps_init(type_bit_maps_context *context); static inline void type_bit_maps_finalize(type_bit_maps_context *context) { (void)context; } void type_bit_maps_set_type(type_bit_maps_context *context, u16 rtype); void type_bit_maps_clear_type(type_bit_maps_context *context, u16 rtype); u16 type_bit_maps_update_size(type_bit_maps_context *context); /** * Compares two types bit maps. * * type_bit_maps_update_size(a) must have been called before. * type_bit_maps_update_size(b) must have been called before. * * @param a * @param b * @return */ int type_bit_maps_compare(const type_bit_maps_context *a, const type_bit_maps_context *b); /* * Once initialized properly, a bitmap context can be written as an (NSEC, NSEC3) bitmap using this function */ void type_bit_maps_write(const type_bit_maps_context* context, u8* output); /* * Converts a (compressed) bitmap to its bit field (expanded) */ s32 type_bit_maps_expand(type_bit_maps_context* context, u8* type_bitmap, u32 size); /* * Takes two (compressed) bitmaps and merge them. * Used for DNSSEC */ bool type_bit_maps_merge(type_bit_maps_context* context, u8* type_bitmap_a, u32 a_size, u8* type_bitmap_b, u32 b_size); /* * Takes two bitmaps and merge them into a stream * Used by the zone reader */ void type_bit_maps_output_stream_write(const type_bit_maps_context* context, output_stream* os); /* * Returns TRUE if the type is enabled in the packed_type_bitmap * (The buffer format matches the type bitmap in the NSEC/NSEC3 wire format) */ bool type_bit_maps_gettypestatus(u8* packed_type_bitmap, u32 size, u16 type); #ifdef __cplusplus } #endif #endif /* _NSEC_COMMON_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/u32_set.h0000644000000000000000000000013114505005532023255 xustar000000000000000030 mtime=1695812442.071976875 29 atime=1695812445.78903011 30 ctime=1695812494.416726557 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/u32_set.h0000664000374500037450000001171614505005532023226 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A dictionary u32 => ptr based on the AVL code. * * A dictionary u32 => ptr based on the AVL code. * Mostly used for accessing hash => value * * @{ * *----------------------------------------------------------------------------*/ #ifndef _U32_SET_H #define _U32_SET_H #include #ifdef __cplusplus extern "C" { #endif /* * A digest is stored prefixed with its length ([1;255]) */ /* * A structure to hold both children with direct access */ typedef struct u32_node u32_node; struct u32_children { struct u32_node* left; struct u32_node* right; }; /* * An union to have access to the children with direct or indexed access */ typedef union u32_children_union u32_children_union; union u32_children_union { struct u32_children lr; struct u32_node * child[2]; }; /* * The node structure CANNOT have a varying size on a given collection * This means that the digest size is a constant in the whole tree */ struct u32_node { union u32_children_union children; /* 2 ptrs */ void* value; /* 1 ptr */ u32 key; /* 4 b */ s8 balance; /* 1 b */ }; /* 29 OR 17 bytes (64/32) */ /* * AVL definition part begins here */ /* * The maximum depth of a tree. * 40 is enough for storing 433494436 items (worst case) * * Depth 0 is one node. * * Worst case : N is enough for sum[n = 0,N](Fn) where Fn is Fibonacci(n+1) * Best case : N is enough for (2^(N+1))-1 */ #define AVL_MAX_DEPTH 52 // 139*10^9 items max (worst case)64 /* * The previx that will be put in front of each function name */ #define AVL_PREFIX u32_set_ /* * The type that hold the node */ #define AVL_NODE_TYPE u32_node /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_TREE_TYPE AVL_NODE_TYPE* typedef AVL_TREE_TYPE u32_set; /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_CONST_TREE_TYPE AVL_NODE_TYPE * const /* * How to find the root in the tree */ #define AVL_TREE_ROOT(__tree__) (*(__tree__)) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u32 #define AVL_REFERENCE_IS_POINTER FALSE #define AVL_REFERENCE_IS_CONST FALSE /* * The node has got a pointer to its parent * * 0 : disable * !=0 : enable */ #define AVL_HAS_PARENT_POINTER 0 #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif /* * I recommend setting a define to identify the C part of the template * So it can be used to undefine what is not required anymore for every * C file but that one. * */ #ifndef _U32_SET_C #undef AVL_MAX_DEPTH #undef AVL_PREFIX #undef AVL_NODE_TYPE #undef AVL_TREE_TYPE #undef AVL_CONST_TREE_TYPE #undef AVL_TREE_ROOT #undef AVL_REFERENCE_TYPE #undef AVL_HAS_PARENT_POINTER #undef AVL_REFERENCE_IS_POINTER #undef AVL_REFERENCE_IS_CONST #undef _AVL_H_INC #endif /* _U32_SET_C */ #define U32_SET_EMPTY NULL #ifdef __cplusplus } #endif #endif /* _U32_SET_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/u64_set.h0000644000000000000000000000013114505005532023262 xustar000000000000000029 mtime=1695812442.09397719 30 atime=1695812445.790030125 30 ctime=1695812494.418726585 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/u64_set.h0000664000374500037450000001262014505005532023226 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A dictionary u64 => ptr based on the AVL code. * * A dictionary u64 => ptr based on the AVL code. * Mostly used for accessing hash => value * * @{ * *----------------------------------------------------------------------------*/ #ifndef _U64_SET_H #define _U64_SET_H #include #ifdef __cplusplus extern "C" { #endif /* * A digest is stored prefixed with its length ([1;255]) */ /* * A structure to hold both children with direct access */ typedef struct u64_node u64_node; struct u64_children { struct u64_node* left; struct u64_node* right; }; /* * An union to have access to the children with direct or indexed access */ typedef union u64_children_union u64_children_union; union u64_children_union { struct u64_children lr; struct u64_node * child[2]; }; /* * The node structure CANNOT have a varying size on a given collection * This means that the digest size is a constant in the whole tree */ struct u64_node { union u64_children_union children; /* 2 ptrs */ void* value; /* 1 ptr */ u64 key; /* 4 b */ s8 balance; /* 1 b */ }; /* 29 OR 17 bytes (64/32) */ /* * AVL definition part begins here */ /* * The maximum depth of a tree. * 40 is enough for storing 433494436 items (worst case) * * Depth 0 is one node. * * Worst case : N is enough for sum[n = 0,N](Fn) where Fn is Fibonacci(n+1) * Best case : N is enough for (2^(N+1))-1 */ #define AVL_MAX_DEPTH 52 // 139*10^9 items max (worst case)64 /* * The previx that will be put in front of each function name */ #define AVL_PREFIX u64_set_ /* * The type that hold the node */ #define AVL_NODE_TYPE u64_node /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_TREE_TYPE AVL_NODE_TYPE* typedef AVL_TREE_TYPE u64_set; /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_CONST_TREE_TYPE AVL_NODE_TYPE * const /* * How to find the root in the tree */ #define AVL_TREE_ROOT(__tree__) (*(__tree__)) /* * Self explanatory */ /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u64 #define AVL_REFERENCE_IS_POINTER FALSE #define AVL_REFERENCE_IS_CONST FALSE /* * The node has got a pointer to its parent * * 0 : disable * !=0 : enable */ #define AVL_HAS_PARENT_POINTER 0 #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif /* * I recommend setting a define to identify the C part of the template * So it can be used to undefine what is not required anymore for every * C file but that one. * */ #ifndef _U64_SET_C #undef AVL_MAX_DEPTH #undef AVL_PREFIX #undef AVL_NODE_TYPE #undef AVL_TREE_TYPE #undef AVL_CONST_TREE_TYPE #undef AVL_TREE_ROOT #undef AVL_REFERENCE_TYPE #undef AVL_HAS_PARENT_POINTER #undef AVL_REFERENCE_IS_POINTER #undef AVL_REFERENCE_IS_CONST #undef _AVL_H_INC #endif /* _U64_SET_C */ #define U64_SET_EMPTY NULL void *u64_set_iterator_hasnext_next_value(u64_set_iterator *iterp); #define FOREACH_U64_SET(cast__,var__,u64_set__) u64_set_iterator PREPROCESSOR_CONCAT_EVAL(foreach_u64_set_iter,__LINE__); u64_set_iterator_init((u64_set__), &PREPROCESSOR_CONCAT_EVAL(foreach_u64_set_iter,__LINE__)); for(cast__ var__;((var__) = (cast__)u64_set_iterator_hasnext_next_value(&PREPROCESSOR_CONCAT_EVAL(foreach_u64_set_iter,__LINE__))) != NULL;) #ifdef __cplusplus } #endif #endif /* _U64_SET_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/u64_set_debug.h0000644000000000000000000000013114505005532024430 xustar000000000000000030 mtime=1695812442.062976746 29 atime=1695812445.78903011 30 ctime=1695812494.420726614 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/u64_set_debug.h0000664000374500037450000001267314505005532024404 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief * * A collection of strings based on the AVL * * @{ * *----------------------------------------------------------------------------*/ #ifndef _U64_SET_H #define _U64_SET_H #ifdef __cplusplus extern "C" { #endif /* * A digest is stored prefixed with its length ([1;255]) */ /* * A structure to hold both children with direct access */ typedef struct u64_node_debug u64_node_debug; struct u64_children_debug { struct u64_node_debug* left; struct u64_node_debug* right; }; /* * An union to have access to the children with direct or indexed access */ typedef union u64_children_debug_union u64_children_debug_union; union u64_children_debug_union { struct u64_children_debug lr; struct u64_node_debug * child[2]; }; /* * The node structure CANNOT have a varying size on a given collection * This means that the digest size is a constant in the whole tree */ struct u64_node_debug { union u64_children_debug_union children; /* 2 ptrs */ void* value; /* 1 ptr */ u64 key; /* 4 b */ s8 balance; /* 1 b */ }; /* 29 OR 17 bytes (64/32) */ /* * AVL definition part begins here */ /* * The maximum depth of a tree. * 40 is enough for storing 433494436 items (worst case) * * Depth 0 is one node. * * Worst case : N is enough for sum[n = 0,N](Fn) where Fn is Fibonacci(n+1) * Best case : N is enough for (2^(N+1))-1 */ #define AVL_MAX_DEPTH 52 // 139*10^9 items max (worst case)64 /* * The previx that will be put in front of each function name */ #define AVL_PREFIX u64_set_debug_ /* * The type that hold the node */ #define AVL_NODE_TYPE u64_node_debug /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_TREE_TYPE AVL_NODE_TYPE* typedef AVL_TREE_TYPE u64_set_debug; /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_CONST_TREE_TYPE AVL_NODE_TYPE * const /* * How to find the root in the tree */ #define AVL_TREE_ROOT(__tree__) (*(__tree__)) /* * Self explanatory */ /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u64 #define AVL_REFERENCE_IS_POINTER FALSE #define AVL_REFERENCE_IS_CONST FALSE /* * The node has got a pointer to its parent * * 0 : disable * !=0 : enable */ #define AVL_HAS_PARENT_POINTER 0 #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif /* * I recommend setting a define to identify the C part of the template * So it can be used to undefine what is not required anymore for every * C file but that one. * */ #ifndef _U64_SET_C #undef AVL_MAX_DEPTH #undef AVL_PREFIX #undef AVL_NODE_TYPE #undef AVL_TREE_TYPE #undef AVL_CONST_TREE_TYPE #undef AVL_TREE_ROOT #undef AVL_REFERENCE_TYPE #undef AVL_HAS_PARENT_POINTER #undef AVL_REFERENCE_IS_POINTER #undef AVL_REFERENCE_IS_CONST #undef _AVL_H_INC #endif /* _U64_SET_C */ #define U64_SET_EMPTY {NULL} void *u64_set_debug_iterator_hasnext_next_value(u64_set_debug_iterator *iterp); #define FOREACH_U64_SET(cast__,var__,u64_set_debug__) u64_set_debug_iterator PREPROCESSOR_CONCAT_EVAL(foreach_u64_set_debug_iter,__LINE__); u64_set_debug_iterator_init((u64_set_debug__), &PREPROCESSOR_CONCAT_EVAL(foreach_u64_set_debug_iter,__LINE__)); for(cast__ var__;((var__) = (cast__)u64_set_debug_iterator_hasnext_next_value(&PREPROCESSOR_CONCAT_EVAL(foreach_u64_set_debug_iter,__LINE__))) != NULL;) #ifdef __cplusplus } #endif #endif /* _U64_SET_H */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/xfr_input_stream.h0000644000000000000000000000013214505005532025363 xustar000000000000000030 mtime=1695812442.042976459 30 atime=1695812445.788030096 30 ctime=1695812494.422726643 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/xfr_input_stream.h0000664000374500037450000001044514505005532025331 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup dnscore * @brief * * @{ */ #ifndef XFR_INPUT_STREAM_H_ #define XFR_INPUT_STREAM_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif typedef enum { XFR_ALLOW_AXFR=1, XFR_ALLOW_IXFR=2, XFR_ALLOW_BOTH=3, XFR_CURRENT_SERIAL_SET=4, // tells the serial parameter is valid XFR_LOOSE_AUTHORITY=8 // ignores missing AA flag } xfr_copy_flags; /* typedef struct xfr_copy_args xfr_copy_args; struct xfr_copy_args { input_stream *is; // TCP stream const u8 *origin; // origin of the zone message_data *message; // message (first set to the head XFR message by the init) u32 current_serial; // the current serial for the zone (if XFR_CURRENT_SERIAL_SET in flags) u32 out_loaded_serial; // the target serial of the stream xfr_copy_flags flags; // what is allowed in the stream }; */ /** * * The XFR input stream is meant to give record by record the payload of an XFR * transfer. It verifies the TSIGs. It knows its type after two read records. * * @param args see xfr_copy_args * @param filtering_stream * @return */ ya_result xfr_input_stream_init(input_stream* filtering_stream, const u8 *origin, input_stream *xfr_source_stream, message_data *message, u32 current_serial, xfr_copy_flags flags); /** * * Queries the server with origin IXFR with the given SOA. * * @param xfris * @param server * @param origin * @param ttl * @param soa_rdata * @param soa_rdata_size * @param flags * @return */ ya_result xfr_input_stream_init_with_query(input_stream* xfris, const host_address *server, const u8 *origin, s32 ttl, const u8 *soa_rdata, int soa_rdata_size, xfr_copy_flags flags); ya_result xfr_input_stream_get_type(input_stream* in_xfr_input_stream); const u8* xfr_input_stream_get_origin(input_stream* in_xfr_input_stream); /** * Returns the serial of the SOA at the end of the stream. * * @param in_xfr_input_stream * @return the last SOA serial number */ u32 xfr_input_stream_get_serial(input_stream* in_xfr_input_stream); u32 xfr_input_stream_get_refresh(input_stream *in_xfr_input_stream); void xfr_input_stream_finalize(); #ifdef __cplusplus } #endif #endif /* XFR_INPUT_STREAM_H_ */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/zalloc.h0000644000000000000000000000013214505005532023256 xustar000000000000000030 mtime=1695812442.013976044 30 atime=1695812445.787030082 30 ctime=1695812494.425726686 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/zalloc.h0000664000374500037450000003310414505005532023221 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup zalloc very fast, no-overhead specialised memory allocation functions * @ingroup dnscore * @brief no-overhead specialised allocation functions * * These memory allocations are using memory mapping to allocate blocks. * * One difficulty is that to free a block, its size has to be known first. * Which is not an issue for most of our uses. * * One drawback is that once allocated, the memory is never released to the system * (but is still available to be allocated again by the program) * * Much faster than malloc, and no overhead. * * Allocated memory is always aligned to at least 64 bits * * The granularity of the size of a block is 8 bytes * * The base alignment is always 4096 + real size of the block * * @{ */ #pragma once #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #ifndef DNSCORE_HAS_ZALLOC_SUPPORT #error "DNSCORE_HAS_ZALLOC_SUPPORT should be set to 1 or 0" #endif #if !DNSCORE_HAS_ZALLOC_SUPPORT /** * Uses malloc to mimmick zalloc_unaligned. Source is in zalloc.c. * * @param len * @param tag * @return */ void *malloc_string_or_die(size_t len, u64 tag); /** * Uses malloc to mimmick zfree_unaligned. Source is in zalloc.c. * * @param ptr */ void mfree_string(void *ptr); /* 8 bytes aligned */ static inline size_t zalloc_memory_block_size(size_t size) { return size; } static inline void free_erases(void *ptr, size_t size) { if(ptr != NULL) { memset(ptr, 0xfe, size); } free(ptr); } #if DEBUG #define ZFREE(label,object) free_erases(label, sizeof(object)) #else #define ZFREE(label,object) free(label) #endif #define ZALLOC_ARRAY_OR_DIE(cast_,label_,size_,tag_) MALLOC_OR_DIE(cast_,label_,size_,tag_);assert((label_) != NULL) #if DEBUG #define ZFREE_ARRAY(ptr_,size_) free_erases((ptr_),(size_)) #else #define ZFREE_ARRAY(ptr_,size_) free(ptr_) #endif // preferred way of allocating one instance of a type (struct, ...) #define ZALLOC_OBJECT_OR_DIE(label__,object__,tag__) MALLOC_OBJECT_OR_DIE(label__, object__, tag__);assert((label__) != NULL) #define ZALLOC_OBJECT_ARRAY_OR_DIE(label__,object__, count__,tag__) MALLOC_OBJECT_ARRAY_OR_DIE(label__, object__, count__, tag__);assert((label__) != NULL) #define ZALLOC_ARRAY_RESIZE(type_,array_,count_,newcount_) \ { \ int zalloc_new_count = (newcount_); \ (array_) = (type_*)realloc((array_),zalloc_new_count*sizeof(type_));\ (count_) = zalloc_new_count; \ } #define ZFREE_OBJECT(label__) free((label__)) #define ZFREE_OBJECT_OF_TYPE(label__,type__) free(label__) #else /** * ZALLOC_PG_SIZE_COUNT tells how many memory sizes are supported, with 8 bytes increments. * Setting this up involves some computation and bigger numbers may lead to unmanagable amounts of memory. * The current setting (256 = 2K) should be enough for most structures. * Exceptions like message_data should be on stack or mallocated any maybe in a pool too. * * I feel more and more that this allocator could and should be put in the core. * The logger could benefit greatly from it. (although I don't know if I'd use * it like this or by forcing an higher granularity like 32 or 64 to avoid mapping too many slots.) * */ #define ZALLOC_PG_SIZE_COUNT 256 // 2K #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT #if DNSCORE_DEBUG_HAS_BLOCK_TAG #define ZALLOC_PG_SIZE_COUNT_EFFECTIVE (ZALLOC_PG_SIZE_COUNT - 2) #else #define ZALLOC_PG_SIZE_COUNT_EFFECTIVE (ZALLOC_PG_SIZE_COUNT - 1) #endif #else #define ZALLOC_PG_SIZE_COUNT_EFFECTIVE ZALLOC_PG_SIZE_COUNT #endif #define ZALLOC_PG_PAGEABLE_MAXSIZE (ZALLOC_PG_SIZE_COUNT_EFFECTIVE * 8) /* x 8 because we are going by 8 increments */ #define ZALLOC_SIZE_TO_PAGE(size_) ((s32)(((size_)-1)>>3)) #define ZALLOC_CANHANDLE(size_) (((s32)(size_))<=ZALLOC_PG_PAGEABLE_MAXSIZE) // prepares the zalloc tables int zalloc_init(); // actually does nothing, just there for symmetry void zalloc_finalize(); /** * @brief Allocates one slot in a memory set * * Allocates one slot in a memory set. * * The size of a slot is page_index*8 * * @param[in] page_index the index of the memory set * * @return a pointer to the allocated memory */ void* zalloc_line(u32 page_index #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_HAS_BLOCK_TAG ,u64 tag #endif ); /** * @brief Frees one slot in a memory set * * Frees one slot in a memory set * * The size of a slot is page_index*8 * * @param[in] ptr a pointer to the memory to free * @param[in] page_index the index of the memory set * */ void zfree_line(void* ptr, u32 page_index); /** * DEBUG */ u64 zheap_line_total(u32 page); u64 zheap_line_avail(u32 page); /** * zalloc_set_owner_thread made sense when it was not thread-safe. * Now this does nothing */ static inline void zalloc_set_owner_thread(thread_t owner) {(void)owner;} static inline void* zalloc(s32 size #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_HAS_BLOCK_TAG ,u64 tag #endif ) { u32 page = ZALLOC_SIZE_TO_PAGE(size); void* ptr; if(page < ZALLOC_PG_SIZE_COUNT_EFFECTIVE) { ptr = zalloc_line(ZALLOC_SIZE_TO_PAGE(size) #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_HAS_BLOCK_TAG ,tag #endif ); } else { ptr = malloc(size); } return ptr; } static inline void zfree(void* ptr, s32 size) { u32 page = ZALLOC_SIZE_TO_PAGE(size); #if DEBUG #if DNSCORE_DEBUG_MALLOC_TRASHMEMORY memset(ptr, 0xfe, size); #endif #endif if(page < ZALLOC_PG_SIZE_COUNT_EFFECTIVE) { zfree_line(ptr,ZALLOC_SIZE_TO_PAGE(size)); } else { free(ptr); } } /** * * Only works if --enable-zalloc-statistics has been set with ./configure * * @return the number of bytes allocated in the zalloc memory system, or -1 if the statistics are not enabled */ s64 zallocatedtotal(); /** * @brief Allocates unaligned memory of an arbitrary size using zalloc_line and malloc * * Allocates unaligned memory of an arbitrary size using zalloc_line and malloc * * @param[in] size the size to allocated * * @return a pointer to the allocated memory */ void* zalloc_unaligned(u32 size #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_HAS_BLOCK_TAG ,u64 tag #endif ); /** * @brief Frees unaligned memory of an arbitrary size using zfree_line and free * * Allocates unaligned memory of an arbitrary size using zalloc_line and malloc * * @param[in] ptr a pointer to the memory to free * */ void zfree_unaligned(void* ptr); /* * THIS SHOULD BE OPTIMIZED BY THE COMPILER AS ONE AND ONLY ONE CALL */ static inline size_t zalloc_memory_block_size(size_t size) { return (size + 7) & ~7; } #define ZALLOC_SIZE_TO_LINE(size__) ((((size__) + 7) >> 3)-1) #define ZALLOC_TYPE_TO_LINE(object__) ZALLOC_SIZE_TO_LINE(sizeof(object__)) #define ZALLOC_TYPE_HAS_LINE(object__) (ZALLOC_TYPE_TO_LINE(object__) < ZALLOC_PG_SIZE_COUNT_EFFECTIVE) #define ZALLOC_SIZE_HAS_LINE(size__) (ZALLOC_SIZE_TO_LINE((size__)) < ZALLOC_PG_SIZE_COUNT_EFFECTIVE) #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_HAS_BLOCK_TAG #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT void* debug_malloc(size_t size_,const char* file, int line, u64 tag); #define ZALLOC_OBJECT(object__,tag__) ZALLOC_TYPE_HAS_LINE(object__)?zalloc_line(ZALLOC_TYPE_TO_LINE(object__), (tag__)):debug_malloc(sizeof(object__), __FILE__, __LINE__, (tag__)) #define ZALLOC_BYTES(size__,tag__) (ZALLOC_SIZE_HAS_LINE(size__)?zalloc_line(ZALLOC_SIZE_TO_LINE(size__), (tag__)):debug_malloc((size__), __FILE__, __LINE__, (tag__))) #define ZFREE_BYTES(ptr__,size__) {if(ZALLOC_SIZE_HAS_LINE(size__)) zfree_line((ptr__),ZALLOC_SIZE_TO_LINE(size__)); else debug_free((ptr__), __FILE__, __LINE__);} #else // DNSCORE_HAS_MALLOC_DEBUG_SUPPORT #define ZALLOC_OBJECT(object__,tag__) ZALLOC_TYPE_HAS_LINE(object__)?zalloc_line(ZALLOC_TYPE_TO_LINE(object__), (tag__)):malloc(sizeof(object__)) #define ZALLOC_BYTES(size__,tag__) (ZALLOC_SIZE_HAS_LINE(size__)?zalloc_line(ZALLOC_SIZE_TO_LINE(size__), (tag__)):malloc((size__))) #define ZFREE_BYTES(ptr__,size__) {if(ZALLOC_SIZE_HAS_LINE(size__)) zfree_line((ptr__),ZALLOC_SIZE_TO_LINE(size__)); else free((ptr__));} #endif // DNSCORE_HAS_MALLOC_DEBUG_SUPPORT #define ZALLOC_ARRAY_OR_DIE(cast__,label__,size__,tag__) if((label__ = (cast__)zalloc((size__),(tag__))) == NULL) {DIE(ZALLOC_ERROR_OUTOFMEMORY); } assert((label__) != NULL) // preferred way of allocating one instance of a type (struct, ...) #define ZALLOC_OBJECT_OR_DIE(label__,object__,tag__) if((label__=(object__*)ZALLOC_OBJECT(object__,(tag__)))==NULL) {DIE(ZALLOC_ERROR_OUTOFMEMORY); } assert((label__) != NULL) #define ZALLOC_OBJECT_ARRAY_OR_DIE(label__,object__,count__,tag__) if((label__=(object__*)ZALLOC_BYTES(sizeof(object__)*(count__), (tag__)))==NULL) {DIE(ZALLOC_ERROR_OUTOFMEMORY); } assert((label__) != NULL) #else // HAS_ZALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_HAS_BLOCK_TAG #define ZALLOC_OBJECT(object__,tag__) ZALLOC_TYPE_HAS_LINE(object__)?zalloc_line(ZALLOC_TYPE_TO_LINE(object__)):malloc(sizeof(object__)) #define ZALLOC_BYTES(size__,tag__) (ZALLOC_SIZE_HAS_LINE(size__)?zalloc_line(ZALLOC_SIZE_TO_LINE(size__)):malloc((size__))) #define ZFREE_BYTES(ptr__,size__) {if(ZALLOC_SIZE_HAS_LINE(size__)) zfree_line((ptr__),ZALLOC_SIZE_TO_LINE(size__)); else free((ptr__));} #define ZALLOC_ARRAY_OR_DIE(cast,label,size_,tag__) if((label = (cast)zalloc(size_)) == NULL) {DIE(ZALLOC_ERROR_OUTOFMEMORY); } assert((label) != NULL) // preferred way of allocating one instance of a type (struct, ...) #define ZALLOC_OBJECT_OR_DIE(label__,object__,tag__) if((label__=(object__*)ZALLOC_OBJECT(object__,tag__))==NULL) {DIE(ZALLOC_ERROR_OUTOFMEMORY); } assert((label__) != NULL) #define ZALLOC_OBJECT_ARRAY_OR_DIE(label__,object__,count__,tag__) if((label__=(object__*)ZALLOC_BYTES(sizeof(object__)*(count__),(tag__)))==NULL) {DIE(ZALLOC_ERROR_OUTOFMEMORY); } assert((label__) != NULL) #endif #define ZFREE(ptr,object__) ZALLOC_TYPE_HAS_LINE(object__)?zfree_line(ptr,ZALLOC_TYPE_TO_LINE(object__)):free(ptr) #define ZFREE_ARRAY(ptr,size_) zfree(ptr,size_) #define ZFREE_OBJECT(label__) zfree((label__), sizeof(*(label__))) #define ZFREE_OBJECT_OF_TYPE(label__,type__) zfree((label__), sizeof(type__)) /** * (Z)Allocates a new array of count type elements so it can hold * newcount type elements. (It takes granularity into account to avoid * unnecessary work) * * If the array is smaller, the end is truncated * If the new count is zero the array is deleted. * * After the macro, array_ and count_ are changed so don't use consts. * * This helper is meant to be used by NSEC3 structures */ #define ZALLOC_ARRAY_RESIZE_TAG 0x44455a49534552 /* RESIZED */ #define ZALLOC_ARRAY_RESIZE(type_,array_,count_,newcount_) \ { \ u32 zalloc_new_count = (u32)(newcount_); \ if(((u32)(count_)) != zalloc_new_count) \ { \ if( ZALLOC_SIZE_TO_PAGE(sizeof(type_)*((u32)(count_))) != \ ZALLOC_SIZE_TO_PAGE(sizeof(type_)*zalloc_new_count)) \ { \ type_* __tmp__; \ \ if(zalloc_new_count > 0) \ { \ ZALLOC_ARRAY_OR_DIE(type_*,__tmp__,sizeof(type_)*zalloc_new_count, ZALLOC_ARRAY_RESIZE_TAG); \ MEMCOPY(__tmp__,(array_),sizeof(type_)*MIN((u32)(count_),zalloc_new_count)); \ } \ else \ { \ __tmp__ = NULL; \ } \ \ ZFREE_ARRAY((array_),sizeof(type_)*((u32)(count_))); \ array_ = __tmp__; \ count_ = newcount_; \ } \ } \ assert(array_ != NULL); \ } #endif struct output_stream; void zalloc_print_stats(struct output_stream *os); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/zone_reader.h0000644000000000000000000000013214505005531024266 xustar000000000000000030 mtime=1695812441.998975829 30 atime=1695812445.787030082 30 ctime=1695812494.427726714 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/zone_reader.h0000664000374500037450000001723614505005531024241 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #pragma once #include #include #ifdef __cplusplus extern "C" { #endif #define ZONEFILE_ERROR_BASE 0x800a0000 #define ZONEFILE_ERROR_CODE(code_) ((s32)(ZONEFILE_ERROR_BASE+(code_))) #define ZONEFILE_FEATURE_NOT_SUPPORTED ZONEFILE_ERROR_CODE(0x0001) #define ZONEFILE_EXPECTED_FILE_PATH ZONEFILE_ERROR_CODE(0x0002) #define ZONEFILE_SOA_WITHOUT_CLASS ZONEFILE_ERROR_CODE(0x0003) #define ZONEFILE_SALT_TOO_BIG ZONEFILE_ERROR_CODE(0x0011) #define ZONEFILE_TEXT_TOO_BIG ZONEFILE_ERROR_CODE(0x0012) #define ZONEFILE_FLAGS_TOO_BIG ZONEFILE_ERROR_CODE(0x0013) #define ZONEFILE_SERVICE_TOO_BIG ZONEFILE_ERROR_CODE(0x0014) #define ZONEFILE_REGEX_TOO_BIG ZONEFILE_ERROR_CODE(0x0015) #define ZONEFILE_RDATA_PARSE_ERROR ZONEFILE_ERROR_CODE(0x0016) #define ZONEFILE_RDATA_BUFFER_TOO_SMALL ZONEFILE_ERROR_CODE(0x0017) #define ZONEFILE_RDATA_SIZE_MISMATCH ZONEFILE_ERROR_CODE(0x0018) /** * Structure used to describe a resource record from a zone. * * Meant to be used by the zone reader modules : * * TEXT FILE * AXFR FILE * */ #define DNSRR_TAG 0x5252534e44 typedef struct resource_record resource_record; struct resource_record { /* Next resource record */ resource_record *next; s32 ttl; /* Contains one of the RR TYPE codes */ u16 type; /* Contains one of the RR CLASS codes */ u16 class; /* should be renamed to something else */ u16 rdata_size; /* The name of the node to which this resource record pertains */ u8 name[MAX_DOMAIN_LENGTH]; u8 rdata[RDATA_MAX_LENGTH]; }; #if MAX_DOMAIN_LENGTH < 255 #error "MAX_DOMAIN_LENGTH must be 255 at least" #endif static inline void resource_record_init(resource_record* entry) { memset(entry, 0, (offsetof(resource_record, name) + 7) & ~7); /* entry->next = NULL; entry->ttl = 0; entry->type = 0; entry->class = 0; entry->rdata_size = 0; entry->name[0] = 0; entry->name[1] = 0; */ } static inline void resource_record_copy(resource_record* entry, const resource_record* source) { memcpy(entry, source, offsetof(resource_record, name)); dnsname_copy(entry->name, source->name); memcpy(entry->rdata, source->rdata, source->rdata_size); } static inline bool resource_record_equals(resource_record* entry, const resource_record* source) { if(memcmp(entry, source, offsetof(resource_record, name)) == 0) { if(dnsname_equals(entry->name, source->name)) { if(memcmp(entry->rdata, source->rdata, source->rdata_size) == 0) { return TRUE; } } } return FALSE; } static inline void resource_record_init_from(resource_record* entry, const resource_record* source) { resource_record_copy(entry, source); entry->next = NULL; } static inline void resource_record_freecontent(resource_record* entry) { yassert(entry != NULL); (void)entry; } static inline void resource_record_resetcontent(resource_record* entry) { yassert(entry != NULL); /* Resets the RDATA output stream so we can fill it again */ entry->rdata_size = 0; } static inline s32 resource_record_size(resource_record* entry) { return entry->rdata_size + 10 + dnsname_len(entry->name); } struct zone_reader_vtbl; typedef struct zone_reader zone_reader; struct zone_reader { void *data; const struct zone_reader_vtbl *vtbl; }; typedef ya_result zone_reader_read_record_method(zone_reader *, resource_record *); typedef ya_result zone_reader_unread_record_method(zone_reader *, resource_record *); typedef ya_result zone_reader_free_record_method(zone_reader *, resource_record *); typedef void zone_reader_close_method(zone_reader *); typedef void zone_reader_handle_error_method(zone_reader *zr, ya_result error_code); // used for cleaning up after an error (AXFR feedback) typedef const char* zone_reader_get_last_error_message_method(zone_reader *zr); typedef bool zone_reader_canwriteback_method(zone_reader *); typedef struct zone_reader_vtbl zone_reader_vtbl; struct zone_reader_vtbl { zone_reader_read_record_method *read_record; zone_reader_unread_record_method *unread_record; zone_reader_free_record_method *free_record; zone_reader_close_method *close; zone_reader_handle_error_method *handle_error; zone_reader_canwriteback_method *can_write_back; zone_reader_get_last_error_message_method *get_last_error_message; const char* __class__; }; #define zone_reader_read_record(zr__,rr__) (zr__)->vtbl->read_record((zr__),(rr__)) #define zone_reader_free_record(zr__,rr__) (zr__)->vtbl->free_record((zr__),(rr__)) #define zone_reader_handle_error(zr__,rr__) (zr__)->vtbl->handle_error((zr__),(rr__)) #define zone_reader_close(zr__) (zr__)->vtbl->close((zr__)) #define zone_reader_canwriteback(zr__) (zr__)->vtbl->can_write_back((zr__)) #define zone_reader_get_last_error_message(zr__) (zr__)->vtbl->get_last_error_message((zr__)) #define zone_reader_unread_record(zr__,rr__) (zr__)->vtbl->unread_record((zr__),(rr__)) #define zone_reader_rdata(zr__) ((zr__).rdata) #define zone_reader_rdata_size(zr__) ((zr__).rdata_size) #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/zone_reader_axfr.h0000644000000000000000000000013114505005532025306 xustar000000000000000030 mtime=1695812442.053976617 29 atime=1695812445.78903011 30 ctime=1695812494.429726743 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/zone_reader_axfr.h0000664000374500037450000000514214505005532025253 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup zoneaxfr AXFR file loader module * @ingroup dnscore * @brief * * @{ */ /*----------------------------------------------------------------------------*/ /* * File: zone_reader_axfr.h * Author: ericdf * * Created on June 16, 2011, 12:03 PM */ #pragma once #include /** @brief Opens an axfr file * * Opens an axfr file * * @param[in] fullpath the path and name of the file to open * @param[out] zone a pointer to a structure that will be used by the function * to hold the zone-file information * * @return A result code * @retval OK : the file has been opened successfully * @retval else : an error occurred */ ya_result zone_reader_axfr_open(zone_reader *dst, const char *file_path); /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/zone_reader_text.h0000644000000000000000000000013214505005532025333 xustar000000000000000030 mtime=1695812442.017976101 30 atime=1695812445.787030082 30 ctime=1695812494.431726772 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/zone_reader_text.h0000664000374500037450000000471614505005532025305 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #include void zone_reader_text_init_error_codes(); ya_result zone_reader_text_parse_stream(input_stream *ins, zone_reader *zr); ya_result zone_reader_text_open(const char *fullpath, zone_reader *zr); ya_result zone_reader_text_set_origin(zone_reader *zr, const u8* origin); void zone_reader_text_ignore_missing_soa(zone_reader *zr); ya_result zone_reader_text_copy_rdata(const char *text, u16 rtype, u8 *rdata, u32 rdata_size, const u8 *origin); ya_result zone_reader_text_len_copy_rdata(const char *text, u32 n, u16 rtype, u8 *rdata, u32 rdata_size, const u8 *origin); yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/zonefile_reader.h0000644000000000000000000000012714505005532025133 xustar000000000000000030 mtime=1695812442.081977018 29 atime=1695812445.78903011 28 ctime=1695812494.4337268 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/zonefile_reader.h0000664000374500037450000001374314505005532025101 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ /* It's a suggestion for a common interface for stored files. * I'd add an "add" and "remove" status on a record in order to * accommodate dynupdate features. * */ #ifndef _ZONEFILE_READER_H #define _ZONEFILE_READER_H #error DONT USE YET #include #define ZONEFILE_OPERATION_ADD 0x00 /* The next record is meant to be added */ #define ZONEFILE_OPERATION_REMOVE 0x01 /* The next record is meant to be removed */ #define ZONEFILE_OPERATION_LABELCHANGED 0x02 /* The caller should reload the label */ #define ZONEFILE_OPERATION_TYPECHANGED 0x04 /* The caller should reload the type */ #define ZONEFILE_OPERATION_EOF 0x80 /* End of file */ #ifdef __cplusplus extern "C" { #endif typedef struct zonefile_reader zonefile_reader; /* * Opens a zone file using the filename (mostly used for TXT zone files) * The next dnsname is made ready */ typedef ya_result zonefile_openfile_method(zonefile_reader* reader, const char* filename); /* * Opens a zone file using the origin (used for any internal file) * The next dnsname is made ready */ typedef ya_result zonefile_openzone_method(zonefile_reader* reader,const u8* origin,u16 zclass); /* * Go to the next dnrecord if any * * return the operation */ typedef ya_result zonefile_nextrecord_method(zonefile_reader* reader); /* * Closes the file(s) */ typedef ya_result zonefile_close_method(zonefile_reader* reader); /* * Returns true if the format name is supported by the current implementation */ typedef bool zonefile_supports_method(zonefile_reader* reader,const char* format); /* * Returns the current operation */ typedef ya_result zonefile_getcurrenoperation_method(zonefile_reader* reader); /* * Returns the current class (should be constant for the whole zone */ typedef u16 zonefile_getcurrentclass_method(zonefile_reader* reader); /* * Returns the current type */ typedef u16 zonefile_getcurrenttype_method(zonefile_reader* reader); /* * Returns the current ttl */ typedef u32 zonefile_getcurrentttl_method(zonefile_reader* reader); /* * Returns the current rdata_size */ typedef u16 zonefile_getcurrentrdatasize_method(zonefile_reader* reader); /* * Returns the current rdata */ typedef const u8* zonefile_getcurrentrdata_method(zonefile_reader* reader); struct zonefile_reader { void* data; zonefile_openfile_method* openfile; zonefile_openzone_method* openzone; zonefile_nextrecord_method* nextrecord; zonefile_getcurrentclass_method* getcurrentclass; zonefile_getcurrenttype_method* getcurrenttype; zonefile_getcurrentttl_method* getcurrentttl; zonefile_getcurrentrdatasize_method* getcurrentrdatasize; zonefile_getcurrentrdata_method* getcurrentrdata; zonefile_close_method* close; zonefile_supports_method* supports; }; #define zonefile_openfile(zf,filename) (zf)->openfile_method(zf,filename) #define zonefile_openzone(zf,origin) (zf)->openzone_method(zf,origin) #define zonefile_close(zf) (zf)->close_method(zf) #define zonefile_supports(zf) (zf)->zonefile_supports_method_method(zf) #define zonefile_nextrecord(zf) (zf)->zonefile_nextrecord_method(zf) #define zonefile_getcurrentclass(zf) (zf)->zonefile_getcurrentclass_method(zf) #define zonefile_getcurrenttype(zf) (zf)->zonefile_getcurrenttype_method(zf) #define zonefile_getcurrentttl(zf) (zf)->zonefile_getcurrentttl_method(zf) #define zonefile_getcurrentrdatasize(zf) (zf)->zonefile_getcurrentrdatasize_method(zf) #define zonefile_getcurrentrdata(zf) (zf)->zonefile_getcurrentrdata_method(zf) #ifdef __cplusplus } #endif #endif /* _ZONEFILE_READER_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/osx_clock_gettime.h0000644000000000000000000000013214505005532025474 xustar000000000000000030 mtime=1695812442.001975872 30 atime=1695812445.787030082 30 ctime=1695812494.435726829 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/osx_clock_gettime.h0000664000374500037450000000443214505005532025441 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #include #if !(defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)) && defined(__MACH__) #if !defined(CLOCK_REALTIME) typedef int clockid_t; int clock_gettime(clockid_t clk_id, struct timespec *tp); #define CLOCK_REALTIME 0 #endif #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/tsig.h0000644000000000000000000000013214505005532022740 xustar000000000000000030 mtime=1695812442.004975915 30 atime=1695812445.787030082 30 ctime=1695812494.437726857 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/tsig.h0000664000374500037450000001603014505005532022702 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup dnscore * @brief * * @{ */ #ifndef TSIG_H_ #define TSIG_H_ #include #include #include #include #if DNSCORE_HAS_TSIG_SUPPORT #ifdef __cplusplus extern "C" { #endif #define HMAC_UNKNOWN 0 #define HMAC_MD5 157 #define HMAC_SHA1 161 #define HMAC_SHA224 162 #define HMAC_SHA256 163 #define HMAC_SHA384 164 #define HMAC_SHA512 165 struct packet_unpack_reader_data; /* * A digest is stored prefixed with its length ([1;255]) */ /* * A structure to hold both children with direct access */ typedef struct tsig_node tsig_node; struct tsig_children { struct tsig_node* left; struct tsig_node* right; }; /* * An union to have access to the children with direct or indexed access */ typedef union tsig_children_union tsig_children_union; union tsig_children_union { struct tsig_children lr; struct tsig_node * child[2]; }; typedef struct tsig_item tsig_item; struct tsig_item { const u8 *name; const u8 *mac; const u8 *mac_algorithm_name; u16 name_len; u16 mac_algorithm_name_len; u16 mac_size; u8 mac_algorithm; u8 load_serial; }; /* * The node structure CANNOT have a varying size on a given collection * This means that the digest size is a constant in the whole tree */ struct tsig_node { union tsig_children_union children; tsig_item item; s8 balance; }; /** * Call this before a config reload */ void tsig_serial_next(); /* * I recommend setting a define to identify the C part of the template * So it can be used to undefine what is not required anymore for every * C file but that one. * */ ya_result tsig_register(const u8 *name, const u8 *mac, u16 mac_size, u8 mac_algorithm); void tsig_finalize(); tsig_item *tsig_get(const u8 *name); u32 tsig_get_count(); tsig_item *tsig_get_at_index(s32 index); struct message_data; typedef enum { TSIG_NOWHERE = -1, TSIG_START = 0, TSIG_MIDDLE = 1, TSIG_END = 2, TSIG_WHOLE = 3 } tsig_tcp_message_position; /** * Sign the first message_data of a tcp answer */ ya_result tsig_sign_tcp_first_message(struct message_data *mesg); /** * Sign one of the "middle" message_data of a tcp answer */ ya_result tsig_sign_tcp_next_message(struct message_data *mesg); /** * Sign the 100*Nth last message_data of a tcp answer */ ya_result tsig_sign_tcp_last_message(struct message_data *mesg); /** * Calls the relevant sign tcp function */ ya_result tsig_sign_tcp_message(struct message_data *mesg, tsig_tcp_message_position pos); /** * Sign the first message_data of a tcp answer */ ya_result tsig_sign_tcp_first_message(struct message_data *mesg); /** * Sign one of the "middle" message_data of a tcp answer */ ya_result tsig_sign_tcp_next_message(struct message_data *mesg); /** * Sign the 100*Nth last message_data of a tcp answer */ ya_result tsig_sign_tcp_last_message(struct message_data *mesg); /** * Calls the relevant verify tcp function */ ya_result tsig_verify_tcp_first_message(struct message_data *mesg, const u8 *mac, u16 mac_size); ya_result tsig_verify_tcp_next_message(struct message_data *mesg); void tsig_verify_tcp_last_message(struct message_data *mesg); void tsig_register_algorithms(); ya_result tsig_get_hmac_algorithm_from_friendly_name(const char *hmacname); const char* tsig_get_friendly_name_from_hmac_algorithm(u32 algorithm); u8 tsig_get_algorithm(const u8 *name); const u8* tsig_get_algorithm_name(u8 algorithm); /* * Called by tsig_extract_and_process * Processes the TSIG of the message, remove the TSIG from the message * *mesg the message * *purd the packet reader pointing to be start of the RDATA of the TSIG * tsigname the dname of the TSIG * tctr the TYPE-CLASS-TTL-RDATALEN of the TSIG */ // no verification whatsoever, use with care ya_result tsig_process(struct message_data *mesg, struct packet_unpack_reader_data *purd, u32 tsig_offset, const tsig_item *tsig, struct type_class_ttl_rdlen *tctr); ya_result tsig_process_query(struct message_data *mesg, struct packet_unpack_reader_data *purd, u32 tsig_offset, u8 tsigname[MAX_DOMAIN_LENGTH], struct type_class_ttl_rdlen *tctr); ya_result tsig_process_answer(struct message_data *mesg, struct packet_unpack_reader_data *purd, u32 tsig_offset, struct type_class_ttl_rdlen *tctr); /* * Search for the last * */ ya_result tsig_extract_and_process(struct message_data *mesg); /** * signs the message * the tsig.tsig should be set * the tsig fields must be set * */ ya_result tsig_sign_answer(struct message_data *mesg); /** * signs the message * the tsig.tsig should be set * the tsig fields should be clear * */ ya_result tsig_sign_query(struct message_data *mesg); ya_result tsig_verify_answer(struct message_data *mesg, const u8 *mac, u16 mac_size); ya_result tsig_append_unsigned_error(struct message_data *mesg); ya_result tsig_append_error(struct message_data *mesg); /** * Removes the TSIG if any, setups the tsig fields of the message. * * Returns 1 if a TSIG has been processed. * Returns 0 if none were found. */ ya_result tsig_message_extract(struct message_data *mesg); #ifdef __cplusplus } #endif #endif /* TSIG support */ #endif /* TSIG_H_ */ /** @} */ yadifa-2.6.5-11201/lib/dnscore/include/dnscore/PaxHeaders.1636/nsid.h0000644000000000000000000000013114505005532022726 xustar000000000000000030 mtime=1695812442.061976731 29 atime=1695812445.78903011 30 ctime=1695812494.439726886 yadifa-2.6.5-11201/lib/dnscore/include/dnscore/nsid.h0000664000374500037450000000453514505005532022700 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #define EDNS0_NSID_SIZE_MAX 512 #ifndef DNSCORE_NSID_C extern u32 edns0_record_size; extern u8 *edns0_rdatasize_nsid_option_wire; extern u32 edns0_rdatasize_nsid_option_wire_size; #endif void edns0_set_nsid(u8 *bytes, u16 size); /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/src0000644000000000000000000000013214505005616017256 xustar000000000000000030 mtime=1695812494.758731455 30 atime=1695812499.080793355 30 ctime=1695812494.758731455 yadifa-2.6.5-11201/lib/dnscore/src/0000775000374500037450000000000014505005616017275 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/tcp_manager.c0000644000000000000000000000013014505005532021752 xustar000000000000000029 mtime=1695812442.46198246 30 atime=1695812445.795030196 29 ctime=1695812494.13072246 yadifa-2.6.5-11201/lib/dnscore/src/tcp_manager.c0000664000374500037450000013017614505005532021726 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #define __TCP_MANAGER_C__ 1 #include "dnscore/dnscore-config.h" #include "dnscore/mutex.h" #include "dnscore/network.h" #include "dnscore/ptr_set.h" #include "dnscore/u32_set.h" #if HAVE_STDATOMIC_H #include #else #include "dnscore/thirdparty/stdatomic.h" #endif #include #include #include #include #include #include #include #define TCPMHCTX_TAG 0x585443484d504354 #define TCPMSCTX_TAG 0x585443534d504354 typedef struct tcp_manager_socket_context_s tcp_manager_socket_context_t; #include "dnscore/tcp_manager.h" #define MODULE_MSG_HANDLE g_system_logger // Host struct tcp_manager_host_context_s { mutex_t connection_list_mtx; list_dl_s connection_list; // should be a set, I just don't know the key yet. atomic_int _rc; // so it's not destroyed mid-use socketaddress addr; // the host socklen_t addr_len; u16 connection_count_max; bool persistent; #if DEBUG ptr_set debug_owners; mutex_t debug_owners_mtx; #endif }; typedef struct tcp_manager_host_context_s tcp_manager_host_context_t; struct tcp_manager_socket_context_s { tcp_manager_host_context_t *_host; int _sockfd; atomic_int _rc; spinlock_t _spinlock; s64 _bytes_read; s64 _bytes_written; s64 _read_time; s64 _write_time; s64 _accept_time; s64 _close_time; #if DEBUG ptr_set debug_owners; mutex_t debug_owners_mtx; #endif }; typedef struct tcp_manager_socket_context_s tcp_manager_socket_context_t; static void tcp_manager_host_context_acquire(tcp_manager_host_context_t *ctx); static inline tcp_manager_host_context_t *tcp_manager_socket_context_host_get(tcp_manager_socket_context_t *sctx) { tcp_manager_host_context_t *host; spinlock_lock(&sctx->_spinlock); host = sctx->_host; spinlock_unlock(&sctx->_spinlock); return host; } static inline tcp_manager_host_context_t *tcp_manager_socket_context_host_acquire(tcp_manager_socket_context_t *sctx) { tcp_manager_host_context_t *host; spinlock_lock(&sctx->_spinlock); host = sctx->_host; tcp_manager_host_context_acquire(host); spinlock_unlock(&sctx->_spinlock); return host; } static inline struct sockaddr *tcp_manager_socket_context_sockaddr_get(tcp_manager_socket_context_t *sctx) { struct sockaddr *sa; spinlock_lock(&sctx->_spinlock); sa = &sctx->_host->addr.sa; spinlock_unlock(&sctx->_spinlock); return sa; } static inline socklen_t tcp_manager_socket_context_sockaddr_length_get(tcp_manager_socket_context_t *sctx) { socklen_t addr_len; spinlock_lock(&sctx->_spinlock); addr_len = sctx->_host->addr_len; spinlock_unlock(&sctx->_spinlock); return addr_len; } static inline socklen_t* tcp_manager_socket_context_sockaddr_length_get_ptr(tcp_manager_socket_context_t *sctx) { socklen_t *addr_lenp; spinlock_lock(&sctx->_spinlock); addr_lenp = &sctx->_host->addr_len; spinlock_unlock(&sctx->_spinlock); return addr_lenp; } static inline tcp_manager_host_context_t *tcp_manager_socket_context_host_get_set(tcp_manager_socket_context_t *sctx, tcp_manager_host_context_t *newvalue) { tcp_manager_host_context_t *host; spinlock_lock(&sctx->_spinlock); host = sctx->_host; sctx->_host = newvalue; spinlock_unlock(&sctx->_spinlock); return host; } static inline int tcp_manager_socket_context_socket_get(tcp_manager_socket_context_t *sctx) { int sockfd; spinlock_lock(&sctx->_spinlock); sockfd = sctx->_sockfd; spinlock_unlock(&sctx->_spinlock); return sockfd; } static inline int tcp_manager_socket_context_socket_get_set(tcp_manager_socket_context_t *sctx, int newvalue) { int sockfd; spinlock_lock(&sctx->_spinlock); sockfd = sctx->_sockfd; sctx->_sockfd = newvalue; spinlock_unlock(&sctx->_spinlock); return sockfd; } static inline s64 tcp_manager_socket_context_close_time_get(tcp_manager_socket_context_t *sctx) { s64 close_time; spinlock_lock(&sctx->_spinlock); close_time = sctx->_close_time; spinlock_unlock(&sctx->_spinlock); return close_time; } static inline void tcp_manager_socket_context_close_time_set(tcp_manager_socket_context_t *sctx, s64 t) { spinlock_lock(&sctx->_spinlock); sctx->_close_time = t; spinlock_unlock(&sctx->_spinlock); } static inline bool tcp_manager_socket_context_close_time_set_if_zero(tcp_manager_socket_context_t *sctx, s64 t) { bool zero; spinlock_lock(&sctx->_spinlock); zero = (sctx->_close_time == 0); if(zero) { sctx->_close_time = t; } spinlock_unlock(&sctx->_spinlock); return zero; } static inline s64 tcp_manager_socket_context_read_time_get(tcp_manager_socket_context_t *sctx) { s64 read_time; spinlock_lock(&sctx->_spinlock); read_time = sctx->_read_time; spinlock_unlock(&sctx->_spinlock); return read_time; } static inline s64 tcp_manager_socket_context_write_time_get(tcp_manager_socket_context_t *sctx) { s64 write_time; spinlock_lock(&sctx->_spinlock); write_time = sctx->_write_time; spinlock_unlock(&sctx->_spinlock); return write_time; } static inline void tcp_manager_socket_context_times_get(tcp_manager_socket_context_t *sctx, s64 *read_timep, s64 *write_timep, s64 *accept_timep, s64 *close_timep) { spinlock_lock(&sctx->_spinlock); if(read_timep != NULL) { *read_timep = sctx->_read_time; } if(write_timep != NULL) { *write_timep = sctx->_write_time; } if(accept_timep != NULL) { *accept_timep = sctx->_accept_time; } if(close_timep != NULL) { *close_timep = sctx->_close_time; } spinlock_unlock(&sctx->_spinlock); } static inline s64 tcp_manager_socket_context_accept_time_get(tcp_manager_socket_context_t *sctx) { s64 accept_time; spinlock_lock(&sctx->_spinlock); accept_time = sctx->_accept_time; spinlock_unlock(&sctx->_spinlock); return accept_time; } static inline void tcp_manager_socket_context_accept_time_set(tcp_manager_socket_context_t *sctx, s64 t) { spinlock_lock(&sctx->_spinlock); sctx->_accept_time = t; spinlock_unlock(&sctx->_spinlock); } static inline void tcp_manager_socket_context_mark_closed(tcp_manager_socket_context_t *sctx) { s64 now = timeus(); spinlock_lock(&sctx->_spinlock); sctx->_sockfd = -1; sctx->_close_time = now; spinlock_unlock(&sctx->_spinlock); } static inline void tcp_manager_socket_context_bytes_written_add(tcp_manager_socket_context_t *sctx, s64 n) { s64 now = timeus(); spinlock_lock(&sctx->_spinlock); sctx->_bytes_written += n; sctx->_read_time = now; spinlock_unlock(&sctx->_spinlock); } static inline void tcp_manager_socket_context_bytes_read_add(tcp_manager_socket_context_t *sctx, s64 n) { s64 now = timeus(); spinlock_lock(&sctx->_spinlock); sctx->_bytes_read += n; sctx->_read_time = now; spinlock_unlock(&sctx->_spinlock); } static ptr_set tcp_manager_host_context_set; static mutex_t tcp_manager_host_context_set_mtx; static u32_set tcp_manager_socket_context_set = U32_SET_EMPTY; static mutex_t tcp_manager_socket_context_set_mtx = MUTEX_INITIALIZER; static int tcp_manager_unregistered_host_connection_max = 1; static bool tcp_manager_sockfd_eof(int sockfd) { if(sockfd >= 0) { u8 tmp[1]; int n = recv(sockfd, tmp, 1, MSG_PEEK|MSG_DONTWAIT); return n == 0; } else { return TRUE; } } static bool tcp_manager_socket_context_eof(tcp_manager_socket_context_t *sctx); static struct service_s tcp_manager_socket_handler = UNINITIALIZED_SERVICE; static int tcp_manager_socket_handler_service(struct service_worker_s *worker) { ptr_vector clean_list; ptr_vector_init_empty(&clean_list); while(service_should_run(worker)) { if(mutex_trylock(&tcp_manager_socket_context_set_mtx)) { u32_set_iterator iter; u32_set_iterator_init(&tcp_manager_socket_context_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); tcp_manager_socket_context_t *sctx = (tcp_manager_socket_context_t*)node->value; int fd = tcp_manager_socket_context_socket_get(sctx); if(fd >= 0) { if(tcp_manager_sockfd_eof(fd)) { ptr_vector_append(&clean_list, sctx); } } } for(int i = 0; i <= ptr_vector_last_index(&clean_list); ++i) { tcp_manager_socket_context_t *sctx = (tcp_manager_socket_context_t*)ptr_vector_get(&clean_list, i); int fd = tcp_manager_socket_context_socket_get_set(sctx, -1); if(fd >= 0) { u32_set_delete(&tcp_manager_socket_context_set, fd); tcp_manager_socket_context_mark_closed(sctx); close_ex(fd); #if DEBUG log_debug2("tcp-manager: connection %p/%i removed from socket context set", sctx, fd); #endif } } ptr_vector_clear(&clean_list); mutex_unlock(&tcp_manager_socket_context_set_mtx); } usleep(ONE_SECOND_US); } ptr_vector_destroy(&clean_list); return 0; } static void tcp_manager_host_context_release(tcp_manager_host_context_t *ctx); /* static int tcp_manager_host_context_init_ptr_set_forall_callback(ptr_node *node, void *args_) { (void)args_; tcp_manager_host_context_t *ctx = (tcp_manager_host_context_t*)node->value; tcp_manager_host_context_release(ctx); return SUCCESS; } */ static void tcp_manager_host_context_init(tcp_manager_host_context_t *ctx, const socketaddress *addr, socklen_t addr_len, u16 connection_count_max, bool persistent); static void tcp_manager_host_context_class_init() { ptr_set_init(&tcp_manager_host_context_set); tcp_manager_host_context_set.compare = socketaddress_compare_ip; mutex_init_recursive(&tcp_manager_host_context_set_mtx); } static void tcp_manager_host_context_class_finalize() { mutex_lock(&tcp_manager_host_context_set_mtx); u32 count = 0; ptr_set_iterator iter; ptr_set_iterator_init(&tcp_manager_host_context_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_set_iterator_next_node(&iter); ++count; } if(count > 0) { tcp_manager_host_context_t **contextes; MALLOC_OBJECT_ARRAY_OR_DIE(contextes, tcp_manager_host_context_t*, count, TCPMHCTX_TAG); ptr_set_iterator_init(&tcp_manager_host_context_set, &iter); count = 0; while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); tcp_manager_host_context_t *ctx = (tcp_manager_host_context_t*)node->value; contextes[count++] = ctx; } for(u32 i = 0; i < count; ++i) { tcp_manager_host_context_t *ctx = (tcp_manager_host_context_t*)contextes[i]; if(ctx->persistent) { #if HAVE_STDATOMIC_H assert(ctx->_rc >= 2); #else assert(atomic_load(&ctx->_rc) >= 2); #endif tcp_manager_host_context_release(ctx); // doesn't free the ctx } #if HAVE_STDATOMIC if(ctx->_rc > 1) // scan-build false positive: ctx hasn't been freed #else if(atomic_load(&ctx->_rc) > 1) // scan-build false positive: ctx hasn't been freed #endif { log_err("host context: %{sockaddr} is still referenced %i times", &ctx->addr.sa, ctx->_rc); } tcp_manager_host_context_release(ctx); } free(contextes); } ptr_set_destroy(&tcp_manager_host_context_set); mutex_unlock(&tcp_manager_host_context_set_mtx); mutex_destroy(&tcp_manager_host_context_set_mtx); } static void tcp_manager_host_context_init(tcp_manager_host_context_t *ctx, const socketaddress *addr, socklen_t addr_len, u16 allowed_connections_max, bool persistent) { if(allowed_connections_max <= 0) { allowed_connections_max = TCP_MANAGER_HOST_CONTEXT_CONNECTION_COUNT_MAX; } mutex_init_recursive(&ctx->connection_list_mtx); list_dl_init(&ctx->connection_list); #if HAVE_STDATOMIC_H ctx->_rc = 1; #else atomic_store(&ctx->_rc, 1); #endif memcpy(&ctx->addr, addr, addr_len); ctx->addr_len = addr_len; ctx->connection_count_max = allowed_connections_max; ctx->persistent = persistent; #if DEBUG ptr_set_init(&ctx->debug_owners); mutex_init(&ctx->debug_owners_mtx); ctx->debug_owners.compare = ptr_set_ptr_node_compare; ptr_node *debug_owners_node = ptr_set_insert(&ctx->debug_owners, (void*)thread_self()); ++debug_owners_node->value_s64; #endif if(persistent) { #if HAVE_STDATOMIC_H ++ctx->_rc; /// @todo 20210303 edf -- when persistence is fully implemented, persistent nodes can only be destroyed with the system #else atomic_fetch_add(&ctx->_rc, 1); #endif #if DEBUG ++debug_owners_node->value_s64; #endif } #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_init(%p, %{sockaddr}, %u, %u, %i) : initialised", ctx, addr, addr_len, allowed_connections_max, persistent); #endif } static tcp_manager_host_context_t* tcp_manager_host_context_new_instance_nolock(const socketaddress *addr, socklen_t addr_len, u16 connection_count_max, bool persistent) { tcp_manager_host_context_t *ctx; /* socketaddress *addr_copy; ZALLOC_OBJECT_OR_DIE(addr_copy, socketaddress, G ENERIC_TAG); *addr_copy = *addr; ptr_node *node = ptr_set_insert(&tcp_manager_host_context_set, addr_copy); */ ptr_node *node = ptr_set_insert(&tcp_manager_host_context_set, (socketaddress*)addr); if(node->value == NULL) { #if DEBUG if(persistent) { log_debug1("tcp-manager: registering %{sockaddr} with %hu connections", &addr->sa, connection_count_max); } #endif ZALLOC_OBJECT_OR_DIE(ctx, tcp_manager_host_context_t, TCPMHCTX_TAG); tcp_manager_host_context_init(ctx, addr, addr_len, connection_count_max, persistent); node->key = &ctx->addr; /// @note it NEEDS to be the one from the node node->value = ctx; #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_new_instance_nolock(%{sockaddr}, %u, %u, %i) : node created", addr, addr_len, connection_count_max, persistent); #endif } else { #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_new_instance_nolock(%{sockaddr}, %u, %u, %i) : node exists already", addr, addr_len, connection_count_max, persistent); #endif /* ZFREE_OBJECT(addr_copy); */ ctx = (tcp_manager_host_context_t*)node->value; } #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_new_instance_nolock(%{sockaddr}, %u, %u, %i) = %p", addr, addr_len, connection_count_max, persistent, ctx); #endif return ctx; } static tcp_manager_host_context_t* tcp_manager_host_context_new_instance(const socketaddress *addr, socklen_t addr_len, u16 connection_count_max, bool persistent) { tcp_manager_host_context_t *ctx; mutex_lock(&tcp_manager_host_context_set_mtx); ctx = tcp_manager_host_context_new_instance_nolock(addr, addr_len, connection_count_max, persistent); mutex_unlock(&tcp_manager_host_context_set_mtx); return ctx; } static void tcp_manager_host_context_acquire(tcp_manager_host_context_t *ctx) { #if !DEBUG #if HAVE_STDATOMIC_H ++ctx->_rc; #else atomic_fetch_add(&ctx->_rc, 1); #endif #else #if HAVE_STDATOMIC_H int rc = ++ctx->_rc; #else int rc = atomic_fetch_add(&ctx->_rc, 1) + 1; #endif #endif #if DEBUG mutex_lock(&ctx->debug_owners_mtx); ptr_node *debug_owner_node = ptr_set_insert(&ctx->debug_owners, (void*)pthread_self()); ++debug_owner_node->value_s64; mutex_unlock(&ctx->debug_owners_mtx); #endif #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_acquire(%p) : rc=%i", ctx, rc); #endif } static tcp_manager_host_context_t* tcp_manager_host_context_acquire_or_create(socketaddress *addr, socklen_t addr_len, u16 connection_count_max, bool persistent) { tcp_manager_host_context_t *ctx; mutex_lock(&tcp_manager_host_context_set_mtx); ptr_node *node = ptr_set_find(&tcp_manager_host_context_set, addr); if(node == NULL) { #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_acquire_or_create(%{sockaddr}, %u, %u, %i) : creating node", addr, addr_len, connection_count_max, persistent); #endif ctx = tcp_manager_host_context_new_instance_nolock(addr, addr_len, connection_count_max, persistent); } else { #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_acquire_or_create(%{sockaddr}, %u, %u, %i) : acquiring node", addr, addr_len, connection_count_max, persistent); #endif ctx = (tcp_manager_host_context_t*)node->value; #if HAVE_STDATOMIC_H ++ctx->_rc; #else atomic_fetch_add(&ctx->_rc, 1); #endif #if DEBUG mutex_lock(&ctx->debug_owners_mtx); ptr_node *debug_owner_node = ptr_set_insert(&ctx->debug_owners, (void*)pthread_self()); ++debug_owner_node->value_s64; mutex_unlock(&ctx->debug_owners_mtx); #endif } #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_acquire_or_create(%{sockaddr}, %u, %u, %i) = %p", addr, addr_len, connection_count_max, persistent, ctx); #endif mutex_unlock(&tcp_manager_host_context_set_mtx); return ctx; } static void tcp_manager_host_context_delete(tcp_manager_host_context_t *ctx) { #if HAVE_STDATOMIC_H assert(ctx->_rc == 0); #else assert(atomic_load(&ctx->_rc) == 0); #endif #ifndef NDEBUG mutex_lock(&ctx->connection_list_mtx); assert(list_dl_size(&ctx->connection_list) == 0); mutex_unlock(&ctx->connection_list_mtx); #endif mutex_lock(&tcp_manager_host_context_set_mtx); ptr_set_delete(&tcp_manager_host_context_set, &ctx->addr); mutex_unlock(&tcp_manager_host_context_set_mtx); mutex_destroy(&ctx->connection_list_mtx); #if DEBUG mutex_lock(&ctx->debug_owners_mtx); ptr_set_destroy(&ctx->debug_owners); mutex_unlock(&ctx->debug_owners_mtx); mutex_destroy(&ctx->debug_owners_mtx); #endif #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_delete(%p)", ctx); #endif ZFREE_OBJECT(ctx); } static void tcp_manager_host_context_release(tcp_manager_host_context_t *ctx) { #if DEBUG mutex_lock(&ctx->debug_owners_mtx); ptr_node *debug_owner_node = ptr_set_insert(&ctx->debug_owners, (void*)pthread_self()); --debug_owner_node->value_s64; mutex_unlock(&ctx->debug_owners_mtx); #endif #if !DEBUG #if HAVE_STDATOMIC_H if(--ctx->_rc == 0) #else if(atomic_fetch_sub(&ctx->_rc, 1) == 0) #endif { tcp_manager_host_context_delete(ctx); } #else #if HAVE_STDATOMIC_H int rc = --ctx->_rc; #else int rc = atomic_fetch_sub(&ctx->_rc, 1) - 1; #endif if(rc == 0) { log_debug3("tcp-manager: tcp_manager_host_context_release(%p) : not referenced anymore", ctx); tcp_manager_host_context_delete(ctx); } else { log_debug3("tcp-manager: tcp_manager_host_context_release(%p) : rc=%i", ctx, rc); } #endif } static void tcp_manager_socket_context_class_init() { u32_set_init(&tcp_manager_socket_context_set); mutex_init(&tcp_manager_socket_context_set_mtx); } static void tcp_manager_socket_context_class_finalize() { mutex_lock(&tcp_manager_socket_context_set_mtx); // u32_set_callback_and_destroy(&tcp_manager_socket_context_set, ...) u32_set_iterator iter; u32_set_iterator_init(&tcp_manager_socket_context_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); tcp_manager_socket_context_t *sctx = (tcp_manager_socket_context_t*)node->value; int fd = tcp_manager_socket_context_socket_get(sctx); if(fd >= 0) { if(tcp_manager_sockfd_eof(fd)) { tcp_manager_socket_context_mark_closed(sctx); close_ex(fd); } } } mutex_unlock(&tcp_manager_socket_context_set_mtx); u32_set_destroy(&tcp_manager_socket_context_set); mutex_destroy(&tcp_manager_socket_context_set_mtx); } static tcp_manager_socket_context_t* tcp_manager_socket_context_new_instance_nolock(tcp_manager_host_context_t *ctx, int sockfd) { u32_node *node = u32_set_insert(&tcp_manager_socket_context_set, sockfd); tcp_manager_socket_context_t *old_sctx = (tcp_manager_socket_context_t*)node->value; if(old_sctx != NULL) { tcp_manager_socket_context_mark_closed(old_sctx); } tcp_manager_socket_context_t *sctx; ZALLOC_OBJECT_OR_DIE(sctx, tcp_manager_socket_context_t, TCPMSCTX_TAG); tcp_manager_host_context_acquire(ctx); sctx->_host = ctx; sctx->_sockfd = sockfd; #if HAVE_STDATOMIC_H sctx->_rc = 1; #else atomic_store(&sctx->_rc, 1); #endif spinlock_init(&sctx->_spinlock); sctx->_bytes_read = 0; sctx->_bytes_written = 0; sctx->_read_time = 0; sctx->_write_time = 0; sctx->_accept_time = 0; sctx->_close_time = 0; #if DEBUG ptr_set_init(&sctx->debug_owners); mutex_init(&sctx->debug_owners_mtx); sctx->debug_owners.compare = ptr_set_ptr_node_compare; ptr_node *debug_owners_node = ptr_set_insert(&sctx->debug_owners, (void*)thread_self()); ++debug_owners_node->value_s64; log_debug2("tcp-manager: connection %p/%i, +owner=%p,%lli (new)", sctx, tcp_manager_socket_context_socket_get(sctx), (void*)thread_self(), debug_owners_node->value_s64); log_debug3("tcp-manager: tcp_manager_socket_context_new_instance_nolock(%p, %i) = %p", ctx, sockfd, sctx); #endif node->value = sctx; return sctx; } static tcp_manager_socket_context_t* tcp_manager_socket_context_new_instance(tcp_manager_host_context_t *ctx, int sockfd) { tcp_manager_socket_context_t *sctx; mutex_lock(&tcp_manager_socket_context_set_mtx); sctx = tcp_manager_socket_context_new_instance_nolock(ctx, sockfd); mutex_unlock(&tcp_manager_socket_context_set_mtx); return sctx; } static void tcp_manager_socket_context_mru_remove(tcp_manager_socket_context_t *sctx); static void tcp_manager_socket_context_delete(tcp_manager_socket_context_t *sctx) { #if DEBUG log_debug3("tcp-manager: tcp_manager_socket_context_delete(%p)", sctx); #endif tcp_manager_socket_context_mru_remove(sctx); mutex_lock(&tcp_manager_socket_context_set_mtx); int fd = tcp_manager_socket_context_socket_get(sctx); if(fd >= 0) { u32_set_delete(&tcp_manager_socket_context_set, fd); tcp_manager_socket_context_mark_closed(sctx); close_ex(fd); #if DEBUG log_debug2("tcp-manager: connection %p/%i removed from socket context set", sctx, fd); log_debug3("tcp-manager: tcp_manager_socket_context_delete(%p) : sockfd=%i", sctx, fd); #endif } #if DEBUG mutex_lock(&sctx->debug_owners_mtx); ptr_set_destroy(&sctx->debug_owners); mutex_unlock(&sctx->debug_owners_mtx); mutex_destroy(&sctx->debug_owners_mtx); #endif spinlock_destroy(&sctx->_spinlock); mutex_unlock(&tcp_manager_socket_context_set_mtx); ZFREE_OBJECT(sctx); } static void tcp_manager_socket_context_acquire(tcp_manager_socket_context_t *sctx) { #if !DEBUG #if HAVE_STDATOMIC_H ++sctx->_rc; #else atomic_fetch_add(&sctx->_rc, 1); #endif #else #if HAVE_STDATOMIC_H int rc = ++sctx->_rc; #else int rc = atomic_fetch_add(&sctx->_rc, 1) + 1; #endif #endif #if DEBUG mutex_lock(&sctx->debug_owners_mtx); ptr_node *debug_owners_node = ptr_set_insert(&sctx->debug_owners, (void*)pthread_self()); ++debug_owners_node->value_s64; log_debug2("tcp-manager: connection %p/%i, +owner=%p,%lli", sctx, tcp_manager_socket_context_socket_get(sctx), (void*)thread_self(), debug_owners_node->value_s64); mutex_unlock(&sctx->debug_owners_mtx); #endif #if DEBUG log_debug3("tcp-manager: tcp_manager_socket_context_acquire(%p) : rc=%i", sctx, rc); #endif #if DEBUG //log_debug1("tcp-manager: %{sockaddr} acquire connection %p/%i, accept=%llT write=%llT read=%llT rc=%i", tcp_manager_socket_context_sockaddr_get(sctx), sctx, tcp_manager_socket_context_socket_get(sctx), tcp_manager_socket_context_accept_time_get(sctx), tcp_manager_socket_context_write_time_get(sctx), tcp_manager_socket_context_read_time_get(sctx), sctx->_rc); #endif } static void tcp_manager_socket_context_release(tcp_manager_socket_context_t *sctx) { tcp_manager_host_context_t *host = tcp_manager_socket_context_host_acquire(sctx); mutex_lock(&host->connection_list_mtx); #if DEBUG mutex_lock(&sctx->debug_owners_mtx); ptr_node *debug_owners_node = ptr_set_insert(&sctx->debug_owners, (void*)pthread_self()); --debug_owners_node->value_s64; log_debug2("tcp-manager: connection %p/%i, -owner=%p,%lli", sctx, tcp_manager_socket_context_socket_get(sctx), (void*)thread_self(), debug_owners_node->value_s64); mutex_unlock(&sctx->debug_owners_mtx); #endif #if !DEBUG #if HAVE_STDATOMIC_H if(--sctx->_rc == 0) #else if(atomic_fetch_sub(&sctx->_rc, 1) == 0) #endif { if(tcp_manager_socket_context_close_time_get(sctx) > 0) // really closed { tcp_manager_socket_context_delete(sctx); } } #else // DEBUG #if HAVE_STDATOMIC_H int rc = --sctx->_rc; #else int rc = atomic_fetch_sub(&sctx->_rc, 1) - 1; #endif if(rc == 0) { log_debug3("tcp-manager: tcp_manager_socket_context_release(%p) : not referenced anymore", sctx, rc); if(tcp_manager_socket_context_close_time_get(sctx) > 0) // really closed { log_debug3("tcp-manager: tcp_manager_socket_context_release(%p) : has been closed", sctx, rc); log_debug1("tcp-manager: %{sockaddr} release connection %p/%i, accept=%llT write=%llT read=%llT close=%llT", tcp_manager_socket_context_sockaddr_get(sctx), sctx, tcp_manager_socket_context_socket_get(sctx), tcp_manager_socket_context_accept_time_get(sctx), tcp_manager_socket_context_write_time_get(sctx), tcp_manager_socket_context_read_time_get(sctx), tcp_manager_socket_context_close_time_get(sctx)); tcp_manager_socket_context_delete(sctx); } else { log_debug1("tcp-manager: %{sockaddr} connection %p/%i, accept=%llT write=%llT read=%llT", tcp_manager_socket_context_sockaddr_get(sctx), sctx, tcp_manager_socket_context_socket_get(sctx), tcp_manager_socket_context_accept_time_get(sctx), tcp_manager_socket_context_write_time_get(sctx), tcp_manager_socket_context_read_time_get(sctx)); } } else { log_debug1("tcp-manager: %{sockaddr} connection %p/%i, accept=%llT write=%llT read=%llT rc=%i", tcp_manager_socket_context_sockaddr_get(sctx), sctx, tcp_manager_socket_context_socket_get(sctx), tcp_manager_socket_context_accept_time_get(sctx), tcp_manager_socket_context_write_time_get(sctx), tcp_manager_socket_context_read_time_get(sctx), rc); log_debug3("tcp-manager: tcp_manager_socket_context_release(%p) : rc=%i", sctx, rc); } #endif mutex_unlock(&host->connection_list_mtx); tcp_manager_host_context_release(host); } static void tcp_manager_socket_context_mru_to_head(tcp_manager_socket_context_t *sctx) { tcp_manager_host_context_t *host = tcp_manager_socket_context_host_get(sctx); mutex_lock(&host->connection_list_mtx); #if DEBUG log_debug3("tcp-manager: tcp_manager_socket_context_mru_to_head(%p)", sctx); #endif list_dl_move_to_first_position(&host->connection_list, sctx); mutex_unlock(&host->connection_list_mtx); } static void tcp_manager_socket_context_mru_remove(tcp_manager_socket_context_t *sctx) { tcp_manager_host_context_t *host = tcp_manager_socket_context_host_get_set(sctx, NULL); if(host != NULL) { mutex_lock(&host->connection_list_mtx); #if DEBUG log_debug3("tcp-manager: tcp_manager_socket_context_mru_remove(%p)", sctx); #endif list_dl_remove(&host->connection_list, sctx); mutex_unlock(&host->connection_list_mtx); tcp_manager_host_context_release(host); } #if DEBUG else { log_debug3("tcp-manager: tcp_manager_socket_context_mru_remove(%p) : host is NULL", sctx); } #endif } static bool tcp_manager_socket_context_eof(tcp_manager_socket_context_t *sctx) { int fd = tcp_manager_socket_context_socket_get(sctx); if(fd < 0) { return TRUE; } // actually closed on the other side? u8 tmp[1]; int n = recv(fd, tmp, 1, MSG_PEEK|MSG_DONTWAIT); return n == 0; } static bool tcp_manager_socket_context_in_use(tcp_manager_socket_context_t *sctx) { s64 now = timeus(); // closed ? if(tcp_manager_socket_context_eof(sctx)) { return FALSE; } // check how long it has been IDLE. s64 read_time; s64 write_time; s64 accept_time; s64 close_time; tcp_manager_socket_context_times_get(sctx, &read_time, &write_time, &accept_time, &close_time); if((close_time != 0) && ( ((read_time + write_time == 0) && ((now - accept_time) < ONE_SECOND_US)) || ((read_time > 0) && ((now - read_time) < ONE_SECOND_US)) || ((write_time > 0) && ((now - write_time) < ONE_SECOND_US)) ) ) { return TRUE; } else { return FALSE; } } static ya_result tcp_manager_host_context_add(tcp_manager_host_context_t *ctx, int sockfd, tcp_manager_socket_context_t **out_sctxp) { tcp_manager_socket_context_t *oldest_sctx = NULL; mutex_lock(&ctx->connection_list_mtx); #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_add(%p, %i, %p)", ctx, sockfd, out_sctxp); #endif s32 mru_size = (s32)list_dl_size(&ctx->connection_list); if(mru_size >= ctx->connection_count_max) { list_dl_node_s* node = list_dl_last_node(&ctx->connection_list); // node->data oldest_sctx = (tcp_manager_socket_context_t*)node->data; if(tcp_manager_socket_context_in_use(oldest_sctx)) { #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_add(%p, %i, %p) : connection count max reached and oldest (%p) still in use = ERROR", ctx, sockfd, out_sctxp, oldest_sctx); #endif mutex_unlock(&ctx->connection_list_mtx); return ERROR; } #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_add(%p, %i, %p) : connection count max (%hu) reached, acquiring oldest (%p)", ctx, sockfd, out_sctxp, ctx->connection_count_max, oldest_sctx); #endif // acquire it so it will still be valid tcp_manager_socket_context_acquire(oldest_sctx); } tcp_manager_socket_context_t *sctx = tcp_manager_socket_context_new_instance(ctx, sockfd); assert(sctx != NULL); // insert //tcp_manager_socket_context_acquire(sctx); list_dl_insert(&ctx->connection_list, sctx); if(out_sctxp != NULL) { tcp_manager_socket_context_acquire(sctx); *out_sctxp = sctx; #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_add(%p, %i, %p) -> %p", ctx, sockfd, out_sctxp, sctx); #endif } tcp_manager_socket_context_release(sctx); mutex_unlock(&ctx->connection_list_mtx); if(oldest_sctx != NULL) { int fd = tcp_manager_socket_context_socket_get(oldest_sctx); if(fd >= 0) { mutex_lock(&tcp_manager_socket_context_set_mtx); u32_set_delete(&tcp_manager_socket_context_set, fd); mutex_unlock(&tcp_manager_socket_context_set_mtx); tcp_manager_socket_context_mark_closed(oldest_sctx); close_ex(fd); #if DEBUG log_debug2("tcp-manager: connection %p/%i removed from socket context set", oldest_sctx, fd); log_debug3("tcp-manager: tcp_manager_host_context_add(%p, %i, %p) closing oldest socket context", ctx, sockfd, out_sctxp); #endif } tcp_manager_socket_context_release(oldest_sctx); } #if DEBUG log_debug3("tcp-manager: tcp_manager_host_context_add(%p, %i, %p) = SUCCESS", ctx, sockfd, out_sctxp); #endif return SUCCESS; } static bool tcp_manager_initialised = FALSE; /** * Acquires a TCP connection, ensuring exclusive access to the stream. */ tcp_manager_socket_context_t* tcp_manager_context_acquire_from_socket(int sockfd) { #if DEBUG log_debug1("tcp-manager: acquire from socket %i", sockfd); #endif tcp_manager_socket_context_t* sctx = NULL; mutex_lock(&tcp_manager_socket_context_set_mtx); u32_node *node = u32_set_find(&tcp_manager_socket_context_set, sockfd); if(node != NULL) { sctx = (tcp_manager_socket_context_t*)node->value; tcp_manager_socket_context_acquire(sctx); } mutex_unlock(&tcp_manager_socket_context_set_mtx); return sctx; } /** * Acquires a TCP connection, ensuring exclusive access to the stream. */ tcp_manager_socket_context_t* tcp_manager_context_acquire(tcp_manager_socket_context_t *sctx) { tcp_manager_socket_context_acquire(sctx); return sctx; } /** * Releases a TCP connection. */ void tcp_manager_context_release(tcp_manager_socket_context_t *sctx) { #if DEBUG log_debug3("tcp-manager: tcp_manager_context_release(%p)", sctx); #endif tcp_manager_socket_context_release(sctx); } void tcp_manager_context_close_and_release(tcp_manager_socket_context_t *sctx) { #if DEBUG log_debug3("tcp-manager: tcp_manager_context_close_and_release(%p)", sctx); #endif tcp_manager_socket_context_close_time_set(sctx, timeus()); tcp_manager_socket_context_release(sctx); } ya_result tcp_manager_write(tcp_manager_socket_context_t *sctx, const u8 *buffer, size_t buffer_size) { #if DEBUG log_debug3("tcp-manager: tcp_manager_write(%p, %p, %i)", sctx, buffer, buffer_size); #endif int fd = tcp_manager_socket_context_socket_get(sctx); int n = write(fd, buffer, buffer_size); if(n > 0) { tcp_manager_socket_context_mru_to_head(sctx); tcp_manager_socket_context_bytes_written_add(sctx, n); } return n; } ya_result tcp_manager_read(tcp_manager_socket_context_t *sctx, u8 *buffer, size_t buffer_size) { #if DEBUG log_debug3("tcp-manager: tcp_manager_read(%p, %p, %i)", sctx, buffer, buffer_size); #endif int fd = tcp_manager_socket_context_socket_get(sctx); int n = read(fd, buffer, buffer_size); if(n > 0) { tcp_manager_socket_context_mru_to_head(sctx); tcp_manager_socket_context_bytes_read_add(sctx, n); } return n; } ya_result tcp_manager_read_fully(tcp_manager_socket_context_t *sctx, u8 *buffer, size_t buffer_size) { #if DEBUG log_debug3("tcp-manager: tcp_manager_read_fully(%p, %p, %i)", sctx, buffer, buffer_size); #endif const u8 *buffer_limit = &buffer[buffer_size]; const u8 *buffer_base = buffer; int fd = tcp_manager_socket_context_socket_get(sctx); while(buffer < buffer_limit) { int n = read(fd, buffer, buffer_size); if(n > 0) { tcp_manager_socket_context_mru_to_head(sctx); tcp_manager_socket_context_bytes_read_add(sctx, n); buffer += n; } else { if(n < 0) { int err = errno; if(err == EINTR) { continue; } if(dnscore_shuttingdown()) { return STOPPED_BY_APPLICATION_SHUTDOWN; } #if __FreeBSD__ if(err == EAGAIN) { continue; } #endif if(err == ETIMEDOUT) { if(buffer - buffer_base > 0) { // partial read and a timeout ... continue; } } return MAKE_ERRNO_ERROR(err); } else { // EOF return buffer - buffer_base; } } } return buffer - buffer_base; } void tcp_manager_write_update(tcp_manager_socket_context_t *sctx, size_t n) { #if DEBUG log_debug3("tcp-manager: tcp_manager_write_update(%p, %i)", sctx, n); #endif tcp_manager_socket_context_mru_to_head(sctx); tcp_manager_socket_context_bytes_written_add(sctx, n); } void tcp_manager_read_update(tcp_manager_socket_context_t *sctx, size_t n) { #if DEBUG log_debug3("tcp-manager: tcp_manager_read_update(%p, %i)", sctx, n); #endif tcp_manager_socket_context_mru_to_head(sctx); tcp_manager_socket_context_bytes_read_add(sctx, n); } ya_result tcp_manager_close(tcp_manager_socket_context_t *sctx) { #if DEBUG log_debug3("tcp-manager: tcp_manager_close(%p)", sctx); #endif ya_result ret; if(tcp_manager_socket_context_close_time_set_if_zero(sctx, timeus())) { ret = SUCCESS; } else { ret = ERROR; // already closed } return ret; } struct sockaddr* tcp_manager_sockaddr(tcp_manager_socket_context_t *sctx) { struct sockaddr *sa = tcp_manager_socket_context_sockaddr_get(sctx); return sa; } socklen_t tcp_manager_socklen(tcp_manager_socket_context_t *sctx) { socklen_t addr_len = tcp_manager_socket_context_sockaddr_length_get(sctx); return addr_len; } socklen_t* tcp_manager_socklenp(tcp_manager_socket_context_t *sctx) { socklen_t *addr_lenp = tcp_manager_socket_context_sockaddr_length_get_ptr(sctx); return addr_lenp; } int tcp_manager_socket(tcp_manager_socket_context_t *sctx) { int fd = tcp_manager_socket_context_socket_get(sctx); return fd; } bool tcp_manager_is_valid(tcp_manager_socket_context_t *sctx) { if(sctx != NULL) { int fd = tcp_manager_socket_context_socket_get(sctx); if(fd >= 0) { s64 close_time = tcp_manager_socket_context_close_time_get(sctx); return close_time == 0; } } return FALSE; } void tcp_manager_init() { if(!tcp_manager_initialised) { tcp_manager_initialised = TRUE; tcp_manager_host_context_class_init(); tcp_manager_socket_context_class_init(); ya_result ret; if(ISOK(ret = service_init(&tcp_manager_socket_handler, tcp_manager_socket_handler_service, "tcpmgr"))) { service_start(&tcp_manager_socket_handler); } } } void tcp_manager_finalise() { if(tcp_manager_initialised) { service_finalize(&tcp_manager_socket_handler); tcp_manager_socket_context_class_finalize(); tcp_manager_host_context_class_finalize(); tcp_manager_initialised = FALSE; } } ya_result tcp_manager_host_register(const socketaddress *sa, socklen_t sa_len, s32 allowed_connections_max) { if(allowed_connections_max <= 0) { allowed_connections_max = TCP_MANAGER_REGISTERED_HOST_CONTEXT_CONNECTION_COUNT_MAX; } tcp_manager_host_context_t *ctx = tcp_manager_host_context_new_instance(sa, sa_len, allowed_connections_max, TRUE); (void)ctx; return SUCCESS; } ya_result tcp_manager_connection_max(s32 allowed_connections_max) { if(allowed_connections_max <= 0) { allowed_connections_max = TCP_MANAGER_HOST_CONTEXT_CONNECTION_COUNT_MAX; } tcp_manager_unregistered_host_connection_max = allowed_connections_max; return SUCCESS; } ya_result tcp_manager_accept(int servfd, tcp_manager_socket_context_t **sctxp) { ya_result ret; socketaddress addr; socklen_t addr_len = sizeof(socketaddress); int sockfd; while((sockfd = accept(servfd, &addr.sa, &addr_len)) < 0) { int err = errno; if(err != EINTR) { return MAKE_ERRNO_ERROR(err); } } if(sockfd >= 0) { // check if the host is registered s64 now = timeus(); if(addr_len > MAX(sizeof(struct sockaddr_in),sizeof(struct sockaddr_in6))) { tcp_set_abortive_close(sockfd); close_ex(sockfd); return BUFFER_WOULD_OVERFLOW; } #if DEBUG log_debug1("tcp-manager: %{sockaddr} connected", &addr.sa); #endif tcp_manager_socket_context_t *sctx; tcp_manager_host_context_t *ctx = tcp_manager_host_context_acquire_or_create(&addr, addr_len, tcp_manager_unregistered_host_connection_max, FALSE); if(FAIL(ret = tcp_manager_host_context_add(ctx, sockfd, &sctx))) { #if DEBUG log_debug1("tcp-manager: %{sockaddr} host connection limit reached (%hu)", &addr.sa, ctx->connection_count_max); log_debug3("tcp-manager: tcp_manager_accept(%i, %p) : host connection limit reached = ERROR", servfd, sctxp); #endif tcp_manager_host_context_release(ctx); tcp_set_abortive_close(sockfd); close_ex(sockfd); return ERROR; // limit reached } #if DEBUG u32 ctx_connection_list_size = list_dl_size(&ctx->connection_list); u16 ctx_connection_count_max = ctx->connection_count_max; #endif yassert(sctx != NULL); tcp_manager_socket_context_accept_time_set(sctx, now); // scan-build false positive: 1 + 1 - 1 > 0 => not freed if(sctxp != NULL) { *sctxp = sctx; } else { tcp_manager_socket_context_release(sctx); } tcp_manager_host_context_release(ctx); #if DEBUG mutex_lock(&ctx->connection_list_mtx); log_debug1("tcp-manager: %{sockaddr} accepted (%i/%hu)", &addr.sa, ctx_connection_list_size, ctx_connection_count_max); // scan-build false positive: ctx hasn't been deleted log_debug3("tcp-manager: tcp_manager_accept(%i, %p) = %i", servfd, sctxp, sockfd); mutex_unlock(&ctx->connection_list_mtx); #endif return sockfd; } else { #if DEBUG log_debug3("tcp-manager: tcp_manager_accept(%i, %p) = ERROR", servfd, sctxp); #endif return ERRNO_ERROR; } } void tcp_manager_set_recvtimeout(tcp_manager_socket_context_t *sctx, int seconds, int useconds) { tcp_set_recvtimeout(tcp_manager_socket_context_socket_get(sctx), seconds, useconds); } void tcp_manager_set_sendtimeout(tcp_manager_socket_context_t *sctx, int seconds, int useconds) { tcp_set_sendtimeout(tcp_manager_socket_context_socket_get(sctx), seconds, useconds); } void tcp_manager_set_nodelay(tcp_manager_socket_context_t *sctx, bool enable) { tcp_set_nodelay(tcp_manager_socket_context_socket_get(sctx), enable); } void tcp_manager_set_cork(tcp_manager_socket_context_t *sctx, bool enable) { tcp_set_cork(tcp_manager_socket_context_socket_get(sctx), enable); } void tcp_manager_finalize() { } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/alarm.c0000644000000000000000000000013214505005532020570 xustar000000000000000030 mtime=1695812442.385981372 30 atime=1695812445.792030153 30 ctime=1695812494.453727087 yadifa-2.6.5-11201/lib/dnscore/src/alarm.c0000664000374500037450000010261214505005532020534 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup alarm * @ingroup dnscore * @brief Alarm functions * * @{ */ #include #include "dnscore/dnscore-config.h" #include "dnscore/logger.h" #include "dnscore/alarm.h" #include "dnscore/mutex.h" #include "dnscore/zalloc.h" #if DEBUG #include "dnscore/timeformat.h" #endif // DEBUG #define DEBUG_ALARM_DUMP 0 #define MODULE_MSG_HANDLE g_system_logger /* * List of events (double-linked), sorted by epoch (then insersion time). * Array of handles (expandable), with the list of events they hold. (so they can easily be foud by id and closed) * * The descriptions are stored in both collections. (two double-linked structures) * * TIMELIST->[TIME#0]->[TIME#1]->...->[TIME#n] * | | * v [NODE] * HNDLLIST->[NODE]--+ | * +->[NODE]-- ... */ #define ALARM_NODE_LIST_TAG 0x5453494c4d524c41 #define ALARM_NODE_DESC_TAG 0x4353444e4d524c41 #define ALARM_NODE_TIME_TAG 0x454d49544d524c41 #define ALARM_HANDLE_TAG 0x4c444e484d524c41 struct alarm_event_list { alarm_event_node *first; alarm_event_node *last; }; typedef struct alarm_event_list alarm_event_list; struct alarm_handle { alarm_event_list events; // events for that handle const u8 *owner_dnsname; }; typedef struct alarm_handle alarm_handle; struct alarm_time_node { struct alarm_time_node *next; alarm_event_list events; u32 epoch; }; typedef struct alarm_time_node alarm_time_node; static ptr_vector alarm_handles = PTR_VECTOR_EMPTY; static alarm_time_node doomsday = { NULL, {NULL, NULL}, MAX_U32 }; // nothing after this point static alarm_time_node g_alarm_time_list = {&doomsday, {NULL, NULL}, 0 }; static mutex_t alarm_mutex = MUTEX_INITIALIZER; static int alarm_handles_next_free = -1; #if DEBUG static volatile bool alarm_mutex_locked = FALSE; static volatile u32 alarm_event_in_handles_count = 0; static volatile u32 alarm_event_in_time_count = 0; static volatile u32 alarm_event_alarm_set_count = 0; static smp_int alarm_event_instanciated = SMP_INT_INITIALIZER; #endif static void alarm_handle_close(alarm_handle *handle_struct); /**/ #if DEBUG_ALARM_DUMP static void alarm_log_dump_nolock(bool check); static void alarm_log_dump(); #endif struct timespec __alarm__approximate_time_10s = { 0, 0 }; struct timespec __alarm__approximate_time_30s = { 0, 0 }; #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT||DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT||DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT||DNSCORE_HAS_MMAP_DEBUG_SUPPORT static s64 g_alarm_run_tick_stats_dump_us = 0; #endif /** * Allocates an uninitialised event node. * * @return */ static alarm_event_node * alarm_event_alloc() { alarm_event_node *node; ZALLOC_OBJECT_OR_DIE(node, alarm_event_node, ALARM_NODE_DESC_TAG); #if DEBUG memset(node, 0xac,sizeof(alarm_event_node)); int total = smp_int_inc_get(&alarm_event_instanciated); log_debug6("alarm_event_alloc(%p) (total=%d)", node, total); #endif return node; } /** * Instanciates an event node * * @param epoch * @param key * @param function * @param args * @param flags * @param text * @return */ alarm_event_node* alarm_event_new( u32 epoch, u32 key, alarm_function_callback *function, void *args, u8 flags, const char *text) { alarm_event_node *event = alarm_event_alloc(); event->epoch = epoch; event->key = key; event->function = function; event->args = args; event->flags = flags; event->text = text; #if DEBUG int total = smp_int_get(&alarm_event_instanciated); log_debug6("alarm_event_new(%p %08x '%s' %T) (total=%d)", event, event->key, event->text, event->epoch, total); #endif return event; } /** * Destroys an event node * * @param node */ void alarm_event_free(alarm_event_node *node) { #if DEBUG int total = smp_int_dec_get(&alarm_event_instanciated); log_debug6("alarm_event_free(%p %08x '%s' %T) (total=%d)", node, node->key, node->text, node->epoch, total); memset(node, 0xfe,sizeof(alarm_event_node)); #endif ZFREE_OBJECT(node); } static void alarm_event_list_init(alarm_event_list *head) { head->first = alarm_event_alloc(); head->last = head->first; ZEROMEMORY(head->first, sizeof(alarm_event_node)); #if DEBUG head->first->text = "ALARM EVENT LIST SENTINEL"; #endif } static void alarm_event_list_finalize(alarm_event_list *head) { if(head->first != NULL && head->first == head->last) { alarm_event_free(head->first); head->first = NULL; head->last = NULL; } #if DEBUG else { log_warn("alarm_event_list_finalize called on an non-empty list"); } #endif } static bool alarm_event_list_isempty(alarm_event_list *head) { assert(alarm_mutex_locked); return head->first == head->last; } static alarm_event_node * alarm_event_list_removefirst(alarm_event_list *time_event) { assert(alarm_mutex_locked); assert(!alarm_event_list_isempty(time_event)); assert((time_event->first != NULL) && (time_event->last != NULL)); // prerequisite: (time node) list is not empty // detach from the (time node) list alarm_event_node *time_node = time_event->first; time_event->first = time_node->time_next; time_event->first->time_prev = NULL; #if DEBUG --alarm_event_in_time_count; #endif assert(time_node->hndl_next != NULL); // detach from the handle list if(time_node->hndl_prev != NULL) { // in the middle of the list : easy time_node->hndl_prev->hndl_next = time_node->hndl_next; } else { // at the beginning of the list : have to find the list first alarm_event_list *handler_list = ptr_vector_get(&alarm_handles, time_node->handle); handler_list->first = time_node->hndl_next; } /* if(node->hndl_next != NULL) There is at least the sentinel */ time_node->hndl_next->hndl_prev = time_node->hndl_prev; #if DEBUG time_node->hndl_next = (alarm_event_node*)~0; time_node->hndl_prev = (alarm_event_node*)~0; time_node->time_next = (alarm_event_node*)~0; time_node->time_prev = (alarm_event_node*)~0; --alarm_event_in_handles_count; #endif #if DEBUG log_debug6("alarm_event_list_removefirst(%p %08x '%s' %T)", time_node, time_node->key, time_node->text, time_node->epoch); #endif return time_node; } /* * Append at end. */ static void alarm_event_append(alarm_event_list *handle_list, alarm_event_list *time_list, alarm_event_node *node) { assert(alarm_mutex_locked); /* * List not empty ? */ #if DEBUG log_debug6("alarm_event_append(%p,%p,%p %08x '%s' %T)", handle_list, time_list, node, node->key, node->text, node->epoch); #endif if(handle_list->first != handle_list->last) { /* * Insert the node before the last one. */ handle_list->last->hndl_prev->hndl_next = node; // BL ->N L node->hndl_prev = handle_list->last->hndl_prev; // BL<->N L handle_list->last->hndl_prev = node; // BL<->N<- L node->hndl_next = handle_list->last; // BL<->N<->L } else { handle_list->first = node; // F = N L node->hndl_next = handle_list->last; // ->F ->L handle_list->last->hndl_prev = node; // ->F<->L node->hndl_prev = NULL; // 0<->F<->L } #if DEBUG ++alarm_event_in_handles_count; #endif if(time_list->first != time_list->last) { time_list->last->time_prev->time_next = node; node->time_prev = time_list->last->time_prev; time_list->last->time_prev = node; node->time_next = time_list->last; } else { time_list->first = node; node->time_next = time_list->last; time_list->last->time_prev = node; node->time_prev = NULL; } #if DEBUG ++alarm_event_in_time_count; #endif } /** * Removes the node from both the handle list and the time list. * Does not releases memory. * * @param handle_list * @param time_list * @param node */ static void alarm_event_remove(alarm_event_list *handle_list, alarm_event_list *time_list, alarm_event_node *node) { assert(alarm_mutex_locked); assert(time_list != NULL); assert(node != NULL); #if DEBUG log_debug6("alarm_event_remove(%p,%p,%p %08x '%s' %T)", handle_list, time_list, node, node->key, node->text, node->epoch); #endif if(node->hndl_prev != NULL) // A<- N<->B ? { node->hndl_prev->hndl_next = node->hndl_next; // N<--N<->B } else { handle_list->first = node->hndl_next; // F = N<->B } node->hndl_next->hndl_prev = node->hndl_prev; // 0/A<-?B #if DEBUG --alarm_event_in_handles_count; #endif if(node->time_prev != NULL) { node->time_prev->time_next = node->time_next; } else { time_list->first = node->time_next; // scan-build false positive : time cannot be null because the call // that provides the value only gives a null for non-existing nodes // AND the call is made using an existing node (not null). } node->time_next->time_prev = node->time_prev; #if DEBUG node->hndl_next = (alarm_event_node*)~0; node->hndl_prev = (alarm_event_node*)~0; node->time_next = (alarm_event_node*)~0; node->time_prev = (alarm_event_node*)~0; --alarm_event_in_time_count; #endif } static alarm_time_node * alarm_time_alloc() { alarm_time_node *time_node; ZALLOC_OBJECT_OR_DIE(time_node, alarm_time_node, ALARM_NODE_TIME_TAG); #if DEBUG memset(time_node, 0xf0,sizeof(alarm_time_node)); log_debug6("alarm_time_alloc() = %p", time_node); #endif assert(alarm_mutex_locked); alarm_event_list_init(&time_node->events); /* newly allocated : NO LOCK */ /* node->next : for the caller */ return time_node; } static void alarm_time_free(alarm_time_node *time_node) { assert(alarm_mutex_locked); assert(time_node->events.first == time_node->events.last); #if DEBUG log_debug6("alarm_time_free(%p)", time_node); alarm_event_list_finalize(&time_node->events); memset(time_node, 0xfe,sizeof(alarm_time_node)); #endif ZFREE_OBJECT(time_node); } /* * Get the time node for the exact epoch ... */ static alarm_time_node * alarm_time_get(u32 epoch) { assert(alarm_mutex_locked); assert(epoch != MAX_U32); alarm_time_node *time_node = g_alarm_time_list.next; while(time_node->epoch < epoch) { time_node = time_node->next; } if(time_node->epoch == epoch) { #if DEBUG log_debug6("alarm_time_get(%T) = %p", epoch, time_node); #endif return time_node; } else { #if DEBUG log_debug6("alarm_time_get(%T) = %p", epoch, NULL); #endif return NULL; } } static alarm_time_node * alarm_time_create(u32 epoch) { assert(alarm_mutex_locked); assert(epoch != MAX_U32); if(epoch == 0) { epoch = time(NULL); } alarm_time_node *time_prev = &g_alarm_time_list; alarm_time_node *time_node = g_alarm_time_list.next; // find a node at or after the one we need while(time_node->epoch < epoch) { time_prev = time_node; time_node = time_node->next; assert(time_node->epoch > time_prev->epoch); } // if it's a match, return it if(time_node->epoch == epoch) { #if DEBUG log_debug6("alarm_time_create(%T) = %p", epoch, time_node); #endif return time_node; } else // else insert a node just after it { alarm_time_node *new_time_node = alarm_time_alloc(); time_prev->next = new_time_node; new_time_node->next = time_node; new_time_node->epoch = epoch; #if DEBUG log_debug6("alarm_time_create(%T) = %p", epoch, new_time_node); #endif return new_time_node; } } void alarm_init() { if(ptr_vector_size(&alarm_handles) == 0) { ptr_vector_resize(&alarm_handles, 64); alarm_event_list_init(&g_alarm_time_list.events); /* init: NO LOCK */ s32 now_s = time(NULL); now_s += 10; __alarm__approximate_time_10s.tv_sec = now_s; now_s += 20; __alarm__approximate_time_30s.tv_sec = now_s; } } void alarm_finalize() { ptr_vector to_close = PTR_VECTOR_EMPTY; mutex_lock(&alarm_mutex); #if DEBUG alarm_mutex_locked = TRUE; log_debug("alarm: %u handles, %u times, %u sets, %i events", alarm_event_in_handles_count, alarm_event_in_time_count, alarm_event_alarm_set_count, smp_int_get(&alarm_event_instanciated)); #endif if(ptr_vector_size(&alarm_handles) > 0) // guarantees ptr_vector_last_index(&alarm_handles); is >= 0 { intptr alarm_handles_last_index = (intptr)ptr_vector_last_index(&alarm_handles); for(intptr i = 0; i <= alarm_handles_last_index; ++i) { alarm_handle *handle_struct = (alarm_handle*)ptr_vector_get(&alarm_handles, i); if(((intptr)handle_struct > alarm_handles_last_index) && ((intptr)handle_struct != (intptr)ALARM_HANDLE_INVALID)) { #if DEBUG log_err("alarm: handle %i was not closed at shutdown", i); #else log_debug("alarm: handle %i was not closed at shutdown", i); #endif ptr_vector_append(&to_close, handle_struct); } } mutex_unlock(&alarm_mutex); for(int i = 0; i <= ptr_vector_last_index(&to_close); ++i) { alarm_handle *handle_struct = (alarm_handle*)ptr_vector_get(&to_close, i); alarm_handle_close(handle_struct); } mutex_lock(&alarm_mutex); if(alarm_event_list_isempty(&g_alarm_time_list.events)) { alarm_event_list_finalize(&g_alarm_time_list.events); } else { log_debug("alarm: event list not empty"); } } ptr_vector_destroy(&alarm_handles); #if DEBUG alarm_mutex_locked = FALSE; #endif mutex_unlock(&alarm_mutex); } alarm_t alarm_open(const u8 *owner_dnsname) { alarm_handle *handle_struct; ZALLOC_OBJECT_OR_DIE(handle_struct, alarm_handle, ALARM_HANDLE_TAG); #if DEBUG memset(handle_struct, 0xac, sizeof(alarm_handle)); #endif alarm_event_list_init(&handle_struct->events); /* newly allocated: NO LOCK */ handle_struct->owner_dnsname = owner_dnsname; mutex_lock(&alarm_mutex); #if DEBUG alarm_mutex_locked = TRUE; #endif intptr h; if(alarm_handles_next_free >= 0) { h = (intptr)alarm_handles_next_free; // unsigned value // get the next one if any alarm_handles_next_free = (intptr)ptr_vector_get(&alarm_handles, h); ptr_vector_set(&alarm_handles, (intptr)h, handle_struct); } else { ptr_vector_append(&alarm_handles, handle_struct); h = (intptr)alarm_handles.offset; } #if DEBUG alarm_mutex_locked = FALSE; #endif mutex_unlock(&alarm_mutex); log_debug("alarm_open(%{dnsname}) opened alarm with handle %x", handle_struct->owner_dnsname, (int)h); return (alarm_t)h; } static alarm_handle * alarm_get_struct_from_handle(alarm_t hndl) { assert(alarm_mutex_locked); if((hndl > alarm_handles.offset) || (hndl < 0)) { /* ERROR ! */ #if DEBUG log_debug("invalid alarm handle: %x", hndl); #endif return NULL; } alarm_handle *handle_struct = ptr_vector_get(&alarm_handles, hndl); return handle_struct; } static void alarm_clear_struct_from_handle(alarm_t hndl) { assert(alarm_mutex_locked); if((hndl > alarm_handles.offset) || (hndl < 0)) { /* ERROR ! */ #if DEBUG log_debug("invalid alarm handle: %x", hndl); #endif return; } ptr_vector_set(&alarm_handles, hndl, (void*)(intptr)alarm_handles_next_free); alarm_handles_next_free = (intptr)hndl; } static void alarm_handle_close(alarm_handle *handle_struct) { alarm_event_node *node = handle_struct->events.first; #if DEBUG #if DEBUG_ALARM_DUMP alarm_log_dump_nolock(FALSE); #endif u32 removed_events = 0; #endif bool obsolete_times = FALSE; while(node != NULL) { alarm_event_node *node_next = node->hndl_next; alarm_time_node *time_node = alarm_time_get(node->epoch); if(time_node != NULL) { alarm_event_list *time_list = &time_node->events; alarm_event_remove(&handle_struct->events, time_list, node); if(alarm_event_list_isempty(&time_node->events)) { obsolete_times = TRUE; } #if DEBUG ++removed_events; #endif } if(node->function != NULL) { node->function(node->args, TRUE); } alarm_event_free(node); node = node_next; } // clear the obsolete times #if DEBUG #if DEBUG_ALARM_DUMP alarm_log_dump_nolock(FALSE); #endif #endif if(obsolete_times) { alarm_time_node *time_node_prev = &g_alarm_time_list; alarm_time_node *time_node = time_node_prev->next; while(time_node->next != NULL) { if(!alarm_event_list_isempty(&time_node->events)) { time_node_prev = time_node; time_node = time_node->next; } else { time_node_prev->next = time_node->next; alarm_time_free(time_node); time_node = time_node_prev->next; } } } #if DEBUG log_debug("alarm_handle_close(%p) removed %u events for %{dnsname}", handle_struct, removed_events, handle_struct->owner_dnsname); memset(handle_struct, 0xe4, sizeof(alarm_event_list)); #if DEBUG_ALARM_DUMP alarm_log_dump_nolock(FALSE); #endif #endif ZFREE_OBJECT(handle_struct); } void alarm_close(alarm_t hndl) { if(hndl == ALARM_HANDLE_INVALID) { return; } mutex_lock(&alarm_mutex); #if DEBUG alarm_mutex_locked = TRUE; #endif alarm_handle *handle_struct = alarm_get_struct_from_handle(hndl); if(handle_struct == NULL) { #if DEBUG alarm_mutex_locked = FALSE; #endif mutex_unlock(&alarm_mutex); log_err("alarm_close(%x) invalid alarm handle", hndl); return; } log_debug("alarm_close(%x) closing alarm for %{dnsname}", hndl, handle_struct->owner_dnsname); alarm_handle_close(handle_struct); alarm_clear_struct_from_handle(hndl); #if DEBUG alarm_mutex_locked = FALSE; #endif mutex_unlock(&alarm_mutex); } void alarm_set(alarm_t hndl, alarm_event_node *desc) { mutex_lock(&alarm_mutex); #if DEBUG alarm_mutex_locked = TRUE; ++alarm_event_alarm_set_count; #endif // get the handle struct, if it exists alarm_handle *handle_struct = alarm_get_struct_from_handle(hndl); if(handle_struct == NULL) { #if DEBUG alarm_mutex_locked = FALSE; #endif mutex_unlock(&alarm_mutex); log_err("alarm_set(%p,%x = '%s') invalid alarm handle", hndl, desc, STRNULL(desc->text)); return; } if(desc->epoch == MAX_U32) { #if DEBUG alarm_mutex_locked = FALSE; #endif mutex_unlock(&alarm_mutex); log_debug("alarm_set(%p,%x = '%s') alarm set for doomsday.", hndl, desc, STRNULL(desc->text)); return; } alarm_event_list *head = &handle_struct->events; #if DEBUG log_debug("alarm_set: %p: at %T, for '%{dnsname}' call key=%x '%s', %p(%p) (call #%i)", desc, desc->epoch, handle_struct->owner_dnsname, desc->key, STRNULL(desc->text), desc->function, desc->args, alarm_event_alarm_set_count); #endif if(desc->flags != ALARM_DUP_NOP) { /* Cleanup first */ if(desc->flags == ALARM_DUP_REMOVE_EARLIER) { alarm_event_node* node = head->first; while(node != head->last) { /// the list is not sorted by time, as in practice there are relatively few events registered by handle if(node->key == desc->key) { log_debug("alarm_set: %p: dropping earliest dup", desc); if(desc->epoch < node->epoch) { /* desc is earlier : cancel and destroy */ if(desc->function != NULL) { desc->function(desc->args, TRUE); } alarm_event_free(desc); #if DEBUG alarm_mutex_locked = FALSE; #endif mutex_unlock(&alarm_mutex); return; } alarm_event_node *node_next = node->hndl_next; alarm_time_node *events_node_at_epoch = alarm_time_get(node->epoch); #if DEBUG log_debug6("about to alarm_event_remove(%p,%p,%p %08x '%s' %T) (earlier)", hndl, &events_node_at_epoch->events, node, node->key, node->text, node->epoch); #endif yassert(events_node_at_epoch != NULL); alarm_event_remove(head, &events_node_at_epoch->events, node); // cancel the event node->function(node->args, TRUE); ZFREE_OBJECT(node); node = node_next; } else { node = node->hndl_next; } } } else { alarm_event_node* node = head->first; while(node != head->last) { if(node->key == desc->key) { #if DEBUG log_debug("alarm_set: %p: dropping latest dup", desc); #endif if(desc->epoch > node->epoch) { /* desc is later */ if(desc->function != NULL) { desc->function(desc->args, TRUE); } alarm_event_free(desc); #if DEBUG alarm_mutex_locked = FALSE; #endif mutex_unlock(&alarm_mutex); return; } alarm_event_node *node_next = node->hndl_next; alarm_time_node *events_node_at_epoch = alarm_time_get(node->epoch); #if DEBUG log_debug6("alarm_set: about to alarm_event_remove(%p,%p,%p %08x '%s' %T) (latest)", head, &events_node_at_epoch->events, node, node->key, node->text, node->epoch); #endif yassert(events_node_at_epoch != NULL); alarm_event_remove(head, &events_node_at_epoch->events, node); // cancel the event node->function(node->args, TRUE); ZFREE_OBJECT(node); node = node_next; } else { node = node->hndl_next; } } } } #if DEBUG log_debug("alarm_set: %p: added", desc); #endif /* Create/get the time head */ alarm_time_node *time_node = alarm_time_create(desc->epoch); /* Link desc at the end of time list and in the hndl list */ desc->handle = hndl; alarm_event_append(head, &time_node->events, desc); #if DEBUG alarm_mutex_locked = FALSE; #endif mutex_unlock(&alarm_mutex); } void alarm_run_tick(u32 epoch) { assert(epoch != MAX_U32); mutex_lock(&alarm_mutex); #if DEBUG alarm_mutex_locked = TRUE; #endif #if DEBUG #if DEBUG_ALARM_DUMP alarm_log_dump_nolock(TRUE); #endif #endif s32 now_s; s64 fetch_start = timeus_and_s(&now_s); s32 event_count = 0; now_s += 10; __alarm__approximate_time_10s.tv_sec = now_s; now_s += 20; __alarm__approximate_time_30s.tv_sec = now_s; // while the time node is in the past or the present alarm_event_node event_dummy; alarm_event_node *event_stack = &event_dummy; for(;;) { // detach the node alarm_time_node *time_node = g_alarm_time_list.next; if(time_node->epoch > epoch) { break; } g_alarm_time_list.next = time_node->next; // while there are events in the time node while(!alarm_event_list_isempty(&time_node->events)) { // process all the events at that time // take the next event of the time node alarm_event_node *event = alarm_event_list_removefirst(&time_node->events); event_stack->time_next = event; event_stack = event; ++event_count; } yassert(time_node->events.first->time_prev == NULL); yassert(time_node->events.last->time_next == NULL); yassert(time_node->events.first == time_node->events.last); #if DEBUG log_debug("alarm: releasing time node %d@%p, next time node is %d@%p", time_node->epoch, time_node, time_node->next->epoch, time_node->next ); #endif alarm_time_free(time_node); } s64 fetch_stop = timeus(); double fetch_delta_ms = (double)(fetch_stop - fetch_start); fetch_delta_ms /= 1000.0; log_debug("alarm: fetched %u events in %.3fms", event_count, fetch_delta_ms); event_stack->time_next = NULL; // event_dummy is the head of all events to execute s64 total_run = 0; #if DEBUG #if DEBUG_ALARM_DUMP alarm_log_dump_nolock(TRUE); alarm_mutex_locked = FALSE; #endif #endif mutex_unlock(&alarm_mutex); ptr_vector rearm = PTR_VECTOR_EMPTY; for(alarm_event_node *event = event_dummy.time_next; event != NULL; ) { #if 1 if(!dnscore_shuttingdown()) { #endif /* EXECUTE EVENT */ log_debug("alarm: '%s': %p: %p(%p) running (expected for %T)", event->text, event, event->function, event->args, event->epoch); s64 event_run_start = timeus(); ya_result ret = event->function(event->args, FALSE); s64 event_run_stop = timeus(); total_run += event_run_stop - event_run_start; double event_run_delta_ms = (double)(event_run_stop - event_run_start); event_run_delta_ms /= 1000.0; log_debug("alarm: '%s': %p: %p(%p) returned %r (%.3fms elapsed)", event->text, event, event->function, event->args, ret, event_run_delta_ms); alarm_event_node *event_time_next; if(ret == ALARM_REARM) { ptr_vector_append(&rearm, event); event_time_next = event->time_next; } else { event_time_next = event->time_next; alarm_event_free(event); } event = event_time_next; } else { alarm_event_node *event_time_next = event->time_next; log_debug("alarm: '%s': %p: %p(%p): cancelling (expected for %T)", event->text, event, event->function, event->args, event->epoch); s64 event_run_start = timeus(); ya_result ret = event->function(event->args, TRUE); s64 event_run_stop = timeus(); total_run += event_run_stop - event_run_start; double event_run_delta_ms = (double)(event_run_stop - event_run_start); event_run_delta_ms /= 1000.0; log_debug("alarm: '%s': %p: %p(%p) cancelled %r (%.3fms elapsed)", event->text, event, event->function, event->args, ret, event_run_delta_ms); event = event_time_next; } } for(int i = 0; i <= ptr_vector_last_index(&rearm); ++i) { alarm_event_node *event = (alarm_event_node*)ptr_vector_get(&rearm, i); event->epoch = epoch + 5; alarm_set(event->handle, event); // can use the handle as it's a re-arm } ptr_vector_destroy(&rearm); double total_run_ms = total_run; total_run_ms /= 1000.0; log_debug("alarm: tick times fetch %.3fms + run %.3fms = total %.3fms)", fetch_delta_ms, total_run_ms, fetch_delta_ms + total_run_ms); #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT||DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT||DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT||DNSCORE_HAS_MMAP_DEBUG_SUPPORT s64 now = timeus(); if(now - g_alarm_run_tick_stats_dump_us > ONE_SECOND_US * 60) { debug_stat(DEBUG_STAT_SIZES|DEBUG_STAT_TAGS|DEBUG_STAT_WALK|DEBUG_STAT_MMAP); flushout(); flusherr(); g_alarm_run_tick_stats_dump_us = now; } #endif } void alarm_lock() { mutex_lock(&alarm_mutex); #if DEBUG alarm_mutex_locked = TRUE; #endif } void alarm_unlock() { #if DEBUG alarm_mutex_locked = FALSE; #endif mutex_unlock(&alarm_mutex); } alarm_event_node * alarm_get_first(alarm_t hndl) { assert(alarm_mutex_locked); alarm_handle *handle_struct = alarm_get_struct_from_handle(hndl); return handle_struct->events.first; } #if DEBUG_ALARM_DUMP static void alarm_log_dump_nolock(bool check) { #if DEBUG u32 handles_count = 0; u32 time_count = 0; int events_count = smp_int_get(&alarm_event_instanciated); log_debug("alarm_log_dump: begin %u / %u ; %u ; instantiated=%d", alarm_event_in_handles_count, alarm_event_in_time_count, alarm_event_alarm_set_count, events_count); for(int i = 0; i <= ptr_vector_last_index(&alarm_handles); ++i) { alarm_handle *handle = (alarm_handle*)ptr_vector_get(&alarm_handles, i); intptr handle_as_index = (intptr)handle; if((handle == NULL) || (handle_as_index <= (intptr)ptr_vector_last_index(&alarm_handles)) || (handle_as_index == MAX_U64)) { continue; } log_debug("alarm_handle: %2i@%p: %{dnsname}", i, handle, handle->owner_dnsname); for(alarm_event_node *node = handle->events.first; node != handle->events.last; node = node->hndl_next) { log_debug("alarm_event: %p %08x '%s' %T", node, node->key, node->text, node->epoch); ++handles_count; } } for(alarm_time_node *time_node = &time_list; time_node != NULL; time_node = time_node->next) { log_debug("alarm_time: %T:", time_node->epoch); for(alarm_event_node *node = time_node->events.first; node != time_node->events.last; node = node->time_next) { log_debug("alarm_event: %p %08x '%s' %T", node, node->key, node->text, node->epoch); ++time_count; } yassert(time_node != time_node->next); } log_debug("alarm_log_dump: end %u / %u ; instantiated=%d", handles_count, time_count, events_count); if(check) { yassert(handles_count == alarm_event_in_handles_count); yassert(time_count == alarm_event_in_time_count); } #endif } static void alarm_log_dump() { mutex_lock(&alarm_mutex); alarm_log_dump_nolock(FALSE); mutex_unlock(&alarm_mutex); } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/acl.c0000644000000000000000000000013214505005532020233 xustar000000000000000030 mtime=1695812442.388981415 30 atime=1695812445.792030153 30 ctime=1695812494.455727115 yadifa-2.6.5-11201/lib/dnscore/src/acl.c0000664000374500037450000023377214505005532020213 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup acl Access Control List * @ingroup yadifad * @brief * * @{ */ #include "dnscore/dnscore-config.h" #include #include #include #include #include logger_handle *g_acl_logger = LOGGER_HANDLE_SINK; #define MODULE_MSG_HANDLE g_acl_logger #include #include #include #include #include #include #include #include #if !DNSCORE_HAS_ACL_SUPPORT #error "ACL support should not be compiled in" #endif #include #include #include #define ADRMITEM_TAG 0x4d4554494d524441 #define ACLENTRY_TAG 0x5952544e454c4341 #define ACLBASE_TAG 0x455341424c4341 #define ACL_DEBUG_FULL 0 #define ACL_DEBUG_FLUSH 0 // enabling this will greatly slow down the zone configuration #define ACL_DEBUG_ARC 0 #if !DEBUG #undef ACL_DEBUG_FULL #define ACL_DEBUG_FULL 0 #endif /* * 2011/10/18 : EDF: disabling the debug because it makes the legitimate error output unreadable. */ #if !ACL_DEBUG_FLUSH #define logger_flush(...) #endif #define AMITSIGK_TAG 0x4b47495354494d41 #define AMITSIGN_TAG 0x4e47495354494d41 #define STR(x) ((x)!=NULL)?(x):"NULL" #define IS_IPV4_ITEM(x_) (((x_)->match == amim_ipv4)||((x_)->match == amim_ipv4_not)) #define IS_IPV6_ITEM(x_) (((x_)->match == amim_ipv6)||((x_)->match == amim_ipv6_not)) #if DNSCORE_HAS_TSIG_SUPPORT #define IS_TSIG_ITEM(x_) (((x_)->match == amim_tsig)||((x_)->match == amim_tsig_not)) #endif #define IS_ANY_ITEM(x_) (((x_)->match == amim_any)||((x_)->match == amim_none)) #define IS_NONE_ITEM(x_) (((x_)->match == amim_any)||((x_)->match == amim_none)) #define IS_IPV4_ITEM_MATCH(x_) ((x_)->match == amim_ipv4) #define IS_IPV6_ITEM_MATCH(x_) ((x_)->match == amim_ipv6) #define IS_TSIG_ITEM_MATCH(x_) ((x_)->match == amim_tsig) #define IS_ANY_ITEM_MATCH(x_) ((x_)->match == amim_any) #define IS_NONE_ITEM_MATCH(x_) ((x_)->match == amim_none) #define IS_IPV4_ITEM_MATCH_NOT(x_) ((x_)->match == amim_ipv4_not) #define IS_IPV6_ITEM_MATCH_NOT(x_) ((x_)->match == amim_ipv6_not) #define IS_TSIG_ITEM_MATCH_NOT(x_) ((x_)->match == amim_tsig_not) #define IS_ANY_ITEM_MATCH_NOT(x_) ((x_)->match == amim_none) #define IS_NONE_ITEM_MATCH_NOT(x_) ((x_)->match == amim_any) /* * Contains all the definitions from the section */ // #if DEBUG #if ACL_DEBUG_FULL static const char* query_access_filter_type_name[18]= { "RRI", "ARI", "4RI", "RAI", "AAI", "4AI", "R6I", "A6I", "46I", "RRT", "ART", "4RT", "RAT", "AAT", "4AT", "R6T", "A6T", "46T" }; #endif static void amim_ipv4_print(ptr_vector *ipv4v) { #if ACL_DEBUG_FULL address_match_item **itemp = (address_match_item **)ipv4v->data; s32 idx = 0; #if DEBUG log_debug7("\tipv4@%p", (void*)itemp); logger_flush(); #endif while(idx <= ipv4v->offset) { u8* ip = itemp[idx]->parameters.ipv4.address.bytes; u8* mask = itemp[idx]->parameters.ipv4.mask.bytes; #if DEBUG log_debug7("\t\t[%hhu.%hhu.%hhu.%hhu/%hhu.%hhu.%hhu.%hhu (%hu) %c]", ip[0], ip[1], ip[2], ip[3], mask[0], mask[1], mask[2], mask[3], itemp[idx]->parameters.ipv4.maskbits, (itemp[idx]->parameters.ipv4.rejects == 0) ? 'a' : 'r'); logger_flush(); #endif idx++; } #else (void)ipv4v; #endif } static void amim_ipv6_print(ptr_vector *ipv6v) { #if ACL_DEBUG_FULL address_match_item **itemp = (address_match_item **)ipv6v->data; s32 idx = 0; #if DEBUG log_debug7("\tipv6@%p", (void*)itemp); logger_flush(); #endif while(idx <= ipv6v->offset) { u8* ip = itemp[idx]->parameters.ipv6.address.bytes; u8* mask = itemp[idx]->parameters.ipv6.mask.bytes; #if DEBUG log_debug7("\t\t[%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx/%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx:%2hhx%2hhx (%hi) %c]", ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15], mask[0], mask[1], mask[2], mask[3], mask[4], mask[5], mask[6], mask[7], mask[8], mask[9], mask[10], mask[11], mask[12], mask[13], mask[14], mask[15], itemp[idx]->parameters.ipv6.maskbits, (itemp[idx]->parameters.ipv6.rejects == 0) ? 'a' : 'r'); logger_flush(); #endif idx++; } #else (void)ipv6v; #endif } #if DNSCORE_HAS_TSIG_SUPPORT static void amim_tsig_print(ptr_vector *tsigv) { #if ACL_DEBUG_FULL address_match_item **itemp = (address_match_item **)tsigv->data; s32 idx = 0; #if DEBUG log_debug7("\ttsig@%p", (void*)itemp); logger_flush(); #endif while(idx <= tsigv->offset) { u8* name = itemp[idx]->parameters.tsig.name; #if DEBUG log_debug7("\t\t%{dnsname}", name); logger_flush(); #endif idx++; } #else (void)tsigv; #endif } #endif // TSIG SUPPORT #endif // int acl_address_match_item_compare(const address_match_item *a, const address_match_item *b); static int acl_address_match_item_compare_node(const void *key_a, const void *key_b) { int ret = acl_address_match_item_compare((const address_match_item*)key_a, (const address_match_item*)key_b); return ret; } static int acl_entry_compare_node(const void *key_a, const void *key_b) { const char *a = (const char*)key_a; const char *b = (const char*)key_b; int ret = strcasecmp(a, b); return ret; } static ptr_set g_amim_set = PTR_SET_EMPTY_WITH_COMPARATOR(acl_address_match_item_compare_node); static ptr_set g_acl_set = PTR_SET_EMPTY_WITH_COMPARATOR(acl_entry_compare_node); static mutex_t ami_mtx = MUTEX_INITIALIZER; static u32 g_acl_entry_count = 0; typedef int amim_function(struct address_match_item*, void*); // static int amim_none(const struct address_match_item* item, const void* data) { (void)item; (void)data; return AMIM_REJECT; } static int amim_any(const struct address_match_item* item, const void* data) { (void)item; (void)data; return AMIM_ACCEPT; } static int amim_ipv4(const struct address_match_item* item, const void* data) { const ipv4_id* items = &item->parameters.ipv4; const u32* ip = (const u32*)data; return ( (items->address.value & items->mask.value) == (*ip & items->mask.value)) ? AMIM_ACCEPT : AMIM_SKIP; } static int amim_ipv4_not(const struct address_match_item *item, const void* data) { return -amim_ipv4(item, data); } static int amim_ipv6(const struct address_match_item *item, const void* data) { const u64* ipv6_bytes = (const u64*)data; const ipv6_id* items = &item->parameters.ipv6; return ( ((items->address.lohi[0] & items->mask.lohi[0]) == (ipv6_bytes[0] & items->mask.lohi[0])) && ((items->address.lohi[1] & items->mask.lohi[1]) == (ipv6_bytes[1] & items->mask.lohi[1])) ) ? AMIM_ACCEPT : AMIM_SKIP; } static int amim_ipv6_not(const struct address_match_item *item, const void *data) { return -amim_ipv6(item, data); } #if DNSCORE_HAS_TSIG_SUPPORT static int amim_tsig(const struct address_match_item *item, const void *data) { const message_data *mesg = (const message_data*)data; /* * The TSIG has already been verified as being valid. So all we need to know if : is it allowed ? */ // mesg->tsig->tsig->name; // log_debug("tsig : %p", message_tsig_get_key(mesg)->name); const tsig_item *tsig = message_tsig_get_key(mesg); if(tsig != NULL) { if(item->parameters.tsig.mac_algorithm == tsig->mac_algorithm) { if(item->parameters.tsig.name_size == tsig->name_len) { if(dnsname_equals(item->parameters.tsig.name, tsig->name)) { return AMIM_ACCEPT; } } } } return AMIM_SKIP; /* no match */ } static int amim_tsig_not(const struct address_match_item *item, const void *data) { return -amim_tsig(item, data); } #endif static int amim_reference(const struct address_match_item *item, const void *data) { (void)item; (void)data; return AMIM_REJECT; } // static bool acl_count_bits(const u8 *bytes, int len, u32 *bit_countp) { u32 bit_count = 0; const u8 *limit = &bytes[len]; for(; bytes < limit; ++bytes) { u8 b = *bytes; if(b == 255) { bit_count += 8; } else { while(b != 0) { if((b & 0x80) != 0) { return false; } ++bit_count; b <<= 1; } for(++bytes; bytes < limit; ++bytes) { if(*bytes != 0) { return false; } } break; } } *bit_countp = bit_count; return TRUE; } void acl_match_item_print(const struct address_match_item *item, output_stream *os) { if(item == NULL) { output_stream_write(os, "NULL", 4); } else if(item->match == amim_none) { output_stream_write(os, "none", 4); } else if(item->match == amim_any) { output_stream_write(os, "any", 3); } else if(IS_IPV4_ITEM(item)) { u32 mask = item->parameters.ipv4.mask.value; u32 mask_bits = 0; bool broken_mask = FALSE; while(mask != 0) { if((mask & 1) == 0) { // broken mask broken_mask = TRUE; break; } ++mask_bits; mask >>= 1; } osformat(os,"%s%u.%u.%u.%u", IS_IPV4_ITEM_MATCH_NOT(item)?"!":"", item->parameters.ipv4.address.bytes[0], item->parameters.ipv4.address.bytes[1], item->parameters.ipv4.address.bytes[2], item->parameters.ipv4.address.bytes[3] ); if(!broken_mask) { if(mask_bits < 32) { osformat(os, "/%u", mask_bits); } } else { osformat(os,"/%u.%u.%u.%u", item->parameters.ipv4.mask.bytes[0], item->parameters.ipv4.mask.bytes[1], item->parameters.ipv4.mask.bytes[2], item->parameters.ipv4.mask.bytes[3]); } } else if(IS_IPV6_ITEM(item)) { u32 mask_bits = 0; bool broken_mask = !acl_count_bits(item->parameters.ipv6.mask.bytes, 16, &mask_bits); struct sockaddr_in6 sa6; sa6.sin6_family = AF_INET6; memcpy(&sa6.sin6_addr, item->parameters.ipv6.address.bytes, 16); osformat(os,"%s%{sockaddrip}", IS_IPV6_ITEM_MATCH_NOT(item)?"!":"", &sa6); if(!broken_mask) { if(mask_bits < 128) { osformat(os, "/%u", mask_bits); } } else { memcpy(&sa6.sin6_addr, item->parameters.ipv6.mask.bytes, 16); osformat(os,"/%{sockaddrip}", &sa6); } } else if((item->match == amim_tsig) || (item->match == amim_tsig_not)) { osformat(os, "%skey %{dnsname}", (item->match == amim_tsig_not)?"!":"", item->parameters.tsig.name); } else { output_stream_write_u8(os, '?'); } } ya_result acl_match_items_print(const address_match_item **address, const address_match_item **limit, output_stream *os) { counter_output_stream_data cosd; output_stream cos; counter_output_stream_init(os, &cos, &cosd); for(const address_match_item **itemp = address; itemp < limit; ++itemp) { const address_match_item *item = *itemp; if(itemp != address) { output_stream_write(&cos, ", ", 2); } acl_match_item_print(item, &cos); } return (ya_result)cosd.written_count; } // #if ACL_SORT_RULES static int amim_ipv4_sort_callback(const void *a, const void *b) { address_match_item *ia = (address_match_item*)a; address_match_item *ib = (address_match_item*)b; if(ia->parameters.ipv4.maskbits != ib->parameters.ipv4.maskbits) { /* Bigger value => more specific tag => before in the sort order */ return (ib->parameters.ipv4.maskbits - ia->parameters.ipv4.maskbits); } /* * rejects a = 1 & b = 0 => a rejects and b don't => a comes first */ return (ib->parameters.ipv4.rejects - ia->parameters.ipv4.rejects); } static void amim_ipv4_sort(ptr_vector *ipv4v) { ptr_vector_qsort(ipv4v, amim_ipv4_sort_callback); } static int amim_ipv6_sort_callback(const void *a, const void *b) { address_match_item *ia = (address_match_item*)a; address_match_item *ib = (address_match_item*)b; if(ia->parameters.ipv6.maskbits != ib->parameters.ipv6.maskbits) { /* Bigger value => more specific tag => before in the sort order */ return (ib->parameters.ipv6.maskbits - ia->parameters.ipv6.maskbits); } /* * rejects a = 1 & b = 0 => a rejects and b don't => a comes first */ return (ib->parameters.ipv6.rejects - ia->parameters.ipv6.rejects); } static void amim_ipv6_sort(ptr_vector *ipv6v) { ptr_vector_qsort(ipv6v, amim_ipv6_sort_callback); } #endif // #define AML_REJECT 0 /* DO NOT CHANGE THESES VALUES */ #define AML_ACCEPT 1 /* DO NOT CHANGE THESES VALUES */ #define AML_FILTER 2 /* DO NOT CHANGE THESES VALUES */ /** * Tool that gives the length of the first sequence of bits that are set to 1, from the first byte. * Stops at the end or the first bit set to 0. */ static inline u32 acl_netmask_bit_count(const u8 *bytes, u32 len) { const u8 * const limit = &bytes[len]; u32 bits = 0; while(bytes < limit) { if(*bytes != 0xff) { break; } bits += 8; bytes++; } if(bytes < limit) { u8 c = *bytes; while((c & 0x80U) != 0) { c <<= 1; bits++; } } return bits; } static bool acl_entry_exists(const char *name) { ptr_node *node = ptr_set_find(&g_acl_set, name); return node != NULL; } static acl_entry* acl_entry_get(const char *name) { ptr_node *node = ptr_set_find(&g_acl_set, name); if(node != NULL) { return (acl_entry*)node->value; } else { return NULL; } } u32 acl_entry_count() { return g_acl_entry_count; } void acl_entry_iterator_init(ptr_set_iterator *iter) { ptr_set_iterator_init(&g_acl_set, iter); } static acl_entry* acl_entry_new_instance(const char *name) { ptr_node *node = ptr_set_insert(&g_acl_set, (char*)name); if(node->value == NULL) { ++g_acl_entry_count; acl_entry *acl; MALLOC_OBJECT_OR_DIE(acl, acl_entry, ACLENTRY_TAG); ZEROMEMORY(acl, sizeof(acl_entry)); acl->name = strdup(name); node->key = (char*)acl->name; node->value = acl; return acl; } abort(); } static void acl_entry_delete(acl_entry *acl) { if(ptr_set_find(&g_acl_set, acl->name) != NULL) { --g_acl_entry_count; } ptr_set_delete(&g_acl_set, acl->name); free((char*)acl->name); free(acl); } static inline u32 acl_address_match_list_size(const address_match_list *aml) { return (aml != NULL)?(aml->limit - aml->items):0; } static u32 acl_address_match_list_get_type(const address_match_list *aml) { if(aml == NULL) { return AML_REJECT; } u32 n = acl_address_match_list_size(aml); switch(n) { case 0: { return AML_REJECT; } case 1: { if(aml->items[0]->match == amim_none) { return AML_REJECT; } else if(aml->items[0]->match == amim_any) { return AML_ACCEPT; } } FALLTHROUGH // fall through default: { return AML_FILTER; } } } static u32 acl_address_match_set_get_type(const address_match_set *ams) { /* * TSIG cannot be globally accepted nor rejected. * It can only be ignored or filtered. * So [0;1] => 0 and 2 => 1. */ u32 tsig = (acl_address_match_list_get_type(&ams->tsig) >> 1) * 9; if(tsig == 0) { /* no tsig, no modifier here */ return acl_address_match_list_get_type(&ams->ipv4) + acl_address_match_list_get_type(&ams->ipv6) * 3; } else { /* * If a tsig is defined and BOTH IPs rules have a size of zero, then both are accepted. */ if(acl_address_match_list_size(&ams->ipv4) + acl_address_match_list_size(&ams->ipv6) == 0) { return AML_ACCEPT + AML_ACCEPT * 3 + tsig; } else { return acl_address_match_list_get_type(&ams->ipv4) + acl_address_match_list_get_type(&ams->ipv6) * 3 + tsig * 9; } } } static address_match_item* acl_address_match_item_alloc() { address_match_item* ami; MALLOC_OBJECT_OR_DIE(ami, address_match_item, ADRMITEM_TAG); ami->match = NULL; ZEROMEMORY(&ami->parameters, sizeof(ami->parameters)); ami->_rc = 1; #if ACL_DEBUG_ARC log_info("acl: address_match_item@%p allocated", ami); #endif return ami; } #if ACL_EXTENDED_FEATURES static void acl_address_match_item_free(address_match_item* ami) { if(ami != NULL) { if(ami->match == amim_reference) { free((void*)ami->parameters.ref.name); } #if DNSCORE_HAS_TSIG_SUPPORT else if((ami->match == amim_tsig) || (ami->match == amim_tsig_not)) { free(ami->parameters.tsig.name); free(ami->parameters.tsig.known); } #endif #if DEBUG memset(ami, 0xfe, sizeof(address_match_item)); #endif free(ami); } } #endif static inline void acl_address_match_item_acquire(address_match_item *ami) { mutex_lock(&ami_mtx); #if ACL_DEBUG_ARC s32 rc = #endif ++ami->_rc; mutex_unlock(&ami_mtx); #if ACL_DEBUG_ARC log_info("acl: address_match_item@%p acquire: %i", ami, rc); #endif } static inline bool acl_address_match_item_release(address_match_item *ami) { assert(ami != NULL); mutex_lock(&ami_mtx); assert(ami->_rc > 0); #if !ACL_DEBUG_ARC if(--ami->_rc > 0) #else s32 rc = --ami->_rc; if(rc > 0) #endif { mutex_unlock(&ami_mtx); #if ACL_DEBUG_ARC log_info("acl: address_match_item@%p release: %i", ami, rc); #endif return FALSE; } mutex_unlock(&ami_mtx); #if ACL_DEBUG_ARC log_info("acl: address_match_item@%p release: %i", ami, rc); #endif #if DEBUG u32 txt_size; char txt[512]; txt_size = sizeof(txt); acl_address_match_item_to_string(ami, txt, &txt_size); if(txt_size <= sizeof(txt)) { log_debug7("acl: destroying '%s' (rc=%i)", txt, ami->_rc); } else { log_debug7("acl: destroying @%p (rc=%i)", ami, ami->_rc); } #endif // acl_address_match_item_free(ami); return TRUE; } static int acl_address_match_item_rc(const address_match_item *ami) { mutex_lock(&ami_mtx); int ret = ami->_rc; mutex_unlock(&ami_mtx); return ret; } static void acl_address_match_item_vector_destroy(ptr_vector *amlv) { for(int i = 0; i <= ptr_vector_last_index(amlv); ++i) { address_match_item *ami = (address_match_item*)ptr_vector_get(amlv, i); acl_address_match_item_release(ami); } ptr_vector_destroy(amlv); } /** * Appends all the address_match_item of the definition (identified by its name) * to the array. * * Returns the number of conversions (0 or 1) * * @param amlv * @param definition_name * @return */ static ya_result acl_expand_address_match_reference(ptr_vector *amlv, const char* definition_name) { ya_result return_value = 0; #if DEBUG log_debug7("acl_expand_address_match_reference(%p, %s)", (void*)amlv, definition_name); logger_flush(); #endif acl_entry *acl = acl_entry_get(definition_name); if(acl != NULL) { address_match_item **amip = acl->list.items; while(amip < acl->list.limit) { address_match_item *ami = *amip; if(ami->match == amim_reference) { /* recurse */ if(!ami->parameters.ref.mark) { ami->parameters.ref.mark = TRUE; ya_result expand = acl_expand_address_match_reference(amlv, ami->parameters.ref.name); if(expand > 0) { return_value += expand; } else { if(expand == 0) { log_err("acl: expanding '%s': '%s' is undefined", definition_name, ami->parameters.ref.name); } else { log_err("acl: expanding '%s': '%s' cannot be expanded", definition_name, ami->parameters.ref.name); } return_value = MIN_S32; // forces an error } ami->parameters.ref.mark = FALSE; } } else { acl_address_match_item_acquire(ami); ptr_vector_append(amlv, ami); return_value++; } amip++; } } return return_value; } /** * Puts the ami in a set, or returns the previous identical version of the ami, * increases its reference count and dereferences (which should destroy) the * ami passed as a parameter. * * @param ami to store (or get) * @return the ami to use */ static inline address_match_item * acl_address_match_item_collection_get(address_match_item *ami) { ptr_node *node = ptr_set_insert(&g_amim_set, ami); if(node->value == NULL) { node->value = ami; return ami; } else { acl_address_match_item_release(ami); ami = (address_match_item*)node->value; acl_address_match_item_acquire(ami); return ami; } } access_control* acl_access_control_new_instance() { access_control *ret; ZALLOC_OBJECT_OR_DIE(ret, access_control, ACLBASE_TAG); ZEROMEMORY(ret, sizeof(access_control)); ret->_rc = 1; #if ACL_DEBUG_ARC log_debug("acl_access_control_new_instance() %p", ret); #endif return ret; } /** * Used to build the acl content * * [!] (ip [/prefix] | key key_id | "acl_name" | { address_match_list } ) * * If use_definitions is TRUE, the definitions will be expanded * */ static ya_result acl_address_match_list_init_from_text(address_match_list *aml, const char *description, bool use_definitions) { #if DEBUG log_debug7("acl_address_match_list_init_from_text(%p, \"%s\", %i)", (void*)aml, STR(description), use_definitions); logger_flush(); #endif if(description == NULL) { return 0; /* successfully parsed 0 descriptors */ } yassert(aml != NULL && aml->items == NULL && aml->limit == NULL); const char *separator = description; ptr_vector list; u32 token_len; bool accept; char token[256]; ptr_vector_init(&list); /* * get each ""; token * parse the token */ while(*separator != '\0') { /* Find the first non-separator, non-space, non-zero char */ while(isspace(*separator)) { separator++; } /* EOL ? */ if(*separator == '\0') { break; } description = separator; while((*separator != ',') && (*separator != ';') && (*separator != '\0')) { separator++; } if(description[0] == '\0') { continue; } token_len = separator - description; while(((*separator == ';') || (*separator == ',')) && (*separator != '\0')) { separator++; } if(token_len > sizeof(token) - 1) { acl_address_match_item_vector_destroy(&list); return ACL_TOKEN_SIZE_ERROR; /* token is too big */ } while((token_len > 0) && isspace(description[token_len - 1])) { token_len--; } if(token_len == 0) { continue; } memcpy(token, description, token_len); token[token_len] = '\0'; description = separator; /* We have a token, we can now divide it*/ char *word = token; /* Check for a starting '!' */ accept = TRUE; if(*word == '!') { accept = FALSE; word++; word = (char*)parse_skip_spaces(word); } char *next_word = (char*)parse_next_space(word); if(*next_word != '\0') { *next_word++ = '\0'; next_word = (char*)parse_skip_spaces(next_word); } address_match_item *ami = NULL; if(strcasecmp(word, "key") == 0) { #if DNSCORE_HAS_TSIG_SUPPORT /* TSIG : key xxxxx; */ ami = acl_address_match_item_alloc(); ami->match = (accept) ? amim_tsig : amim_tsig_not; word = next_word; next_word = (char*)parse_next_space(next_word); if((next_word - word) > (ssize_t)sizeof(token)) { acl_address_match_item_release(ami); acl_address_match_item_vector_destroy(&list); return ACL_TOKEN_SIZE_ERROR; } /* * Check if the key is known */ u8 dnsname[MAX_DOMAIN_LENGTH]; ya_result dnsname_len = cstr_to_dnsname_with_check(dnsname,word); if(FAIL(dnsname_len)) { acl_address_match_item_release(ami); acl_address_match_item_vector_destroy(&list); return ACL_NAME_PARSE_ERROR; } tsig_item *key = tsig_get(dnsname); if(key == NULL) { log_err("acl: unknown key %{dnsname}", dnsname); acl_address_match_item_release(ami); acl_address_match_item_vector_destroy(&list); return ACL_UNKNOWN_TSIG_KEY; } ami->parameters.tsig.secret_size = key->mac_size; ami->parameters.tsig.name_size = dnsname_len; ami->parameters.tsig.mac_algorithm = key->mac_algorithm; MALLOC_OR_DIE(u8*, ami->parameters.tsig.known, key->mac_size, AMITSIGK_TAG); memcpy(ami->parameters.tsig.known, key->mac, key->mac_size); MALLOC_OR_DIE(u8*, ami->parameters.tsig.name, (size_t)dnsname_len, AMITSIGN_TAG); memcpy(ami->parameters.tsig.name, dnsname, (size_t)dnsname_len); ami = acl_address_match_item_collection_get(ami); #else log_err("acl: unknown key %{dnsname} (not supported)", dnsname); return ACL_UNKNOWN_TSIG_KEY; // not supported #endif } else if(strcasecmp(word, "none") == 0) { /* Reject all */ ami = acl_address_match_item_alloc(); ami->match = (accept) ? amim_none : amim_any; ami = acl_address_match_item_collection_get(ami); } else if(strcasecmp(word, "any") == 0) { /* Accept all */ ami = acl_address_match_item_alloc(); ami->match = (accept) ? amim_any : amim_none; ami = acl_address_match_item_collection_get(ami); } else /* parse an ipv4 or ipv6, with or without an ipv4, ipv6 or sized bitmask */ { u8 buffer[16]; bool mask = FALSE; u32 bits = 0; if(*next_word != '\0') { log_err("acl: unexpected %s after IP", next_word); acl_address_match_item_vector_destroy(&list); return ACL_TOO_MANY_TOKENS; } int proto = -1; char *slash = word; while(*slash != '\0') { if(*slash == '/') { *slash++ = '\0'; slash = (char*)parse_skip_spaces(slash); mask = TRUE; break; } slash++; } if(inet_pton(AF_INET, word, buffer) == 1) { /* ipv4 */ proto = AF_INET; ami = acl_address_match_item_alloc(); ami->match = (accept) ? amim_ipv4 : amim_ipv4_not; ami->parameters.ipv4.rejects = (accept) ? 0 : 1; memcpy(&ami->parameters.ipv4.address.bytes, buffer, 4); if(!mask) { memset(&ami->parameters.ipv4.mask.bytes, 0xff, 4); ami->parameters.ipv4.maskbits = 32; } ami = acl_address_match_item_collection_get(ami); } else if(inet_pton(AF_INET6, word, buffer) == 1) { /* ipv6 */ proto = AF_INET6; ami = acl_address_match_item_alloc(); ami->match = (accept) ? amim_ipv6 : amim_ipv6_not; ami->parameters.ipv6.rejects = (accept) ? 0 : 1; memcpy(&ami->parameters.ipv6.address.bytes, buffer, 16); if(!mask) { memset(&ami->parameters.ipv6.mask.bytes, 0xff, 16); ami->parameters.ipv6.maskbits = 128; } ami = acl_address_match_item_collection_get(ami); } else { /* It could be a reference: */ if(!accept || mask) /* Cannot do a 'not' reference. * Cannot get a '/' in a reference. */ { acl_address_match_item_vector_destroy(&list); return ACL_UNEXPECTED_NEGATION; } /* * If the acls have already been (fully) defined: * Look for 'word' in the acls and expand it. * Add every ACL entry */ if(use_definitions) { ya_result expand; if((expand = acl_expand_address_match_reference(&list, word)) <= 0) { acl_address_match_item_vector_destroy(&list); if(expand == 0) { log_err("acl: '%s' is undefined", word); } else { log_err("acl: '%s' cannot be expanded", word); } return ACL_UNDEFINED_TOKEN; } } else /* just store the name */ { ami = acl_address_match_item_alloc(); ami->match = amim_reference; ami->parameters.ref.name = strdup(word); ami->parameters.ref.mark = FALSE; ami = acl_address_match_item_collection_get(ami); #if DEBUG log_debug7("acl_address_match_list_init_from_text(%p, %s, %u) : adding %p (%s)", (void*)aml, STR(description), use_definitions, (void*)ami, word); #endif // acquire + release ptr_vector_append(&list, ami); } continue; } /* * If a raw value has been put in an "allow", then I have to keep track to delete it at shutdown */ if(mask) { word = slash; if(inet_pton(AF_INET, word, buffer) == 1) { /* ipv4 */ if(proto != AF_INET) { acl_address_match_item_release(ami); return ACL_WRONG_V4_MASK; } ami->match = (accept) ? amim_ipv4 : amim_ipv4_not; memcpy(&ami->parameters.ipv4.mask.bytes, buffer, 4); ami->parameters.ipv4.maskbits = acl_netmask_bit_count(ami->parameters.ipv4.mask.bytes, 4); ami = acl_address_match_item_collection_get(ami); } else if(inet_pton(AF_INET6, word, buffer) == 1) { /* ipv6 */ if(proto != AF_INET6) { /* free(ami); */ /* pointless since the cleanup will not be fully done anyway (list) */ acl_address_match_item_release(ami); return ACL_WRONG_V6_MASK; } ami->match = (accept) ? amim_ipv6 : amim_ipv6_not; memcpy(&ami->parameters.ipv6.mask.bytes, buffer, 16); ami->parameters.ipv6.maskbits = acl_netmask_bit_count(ami->parameters.ipv4.mask.bytes, 16); ami = acl_address_match_item_collection_get(ami); } else if(ISOK(parse_u32_check_range(word, &bits, 0, (proto == AF_INET) ? 32 : 128, BASE_10))) { ZEROMEMORY(buffer, sizeof(buffer)); u8 *b = buffer; u8 maskbits = bits; while(bits >= 8) { *b++ = 0xff; bits -= 8; } while(bits > 0) { *b >>= 1; *b |= 0x80; bits--; } if(proto == AF_INET) { memcpy(&ami->parameters.ipv4.mask, buffer, 4); ami->parameters.ipv4.maskbits = maskbits; } else { memcpy(&ami->parameters.ipv6.mask, buffer, 16); ami->parameters.ipv6.maskbits = maskbits; } ami = acl_address_match_item_collection_get(ami); } else { acl_address_match_item_release(ami); return ACL_WRONG_MASK; /* Wrong mask */ } } else { acl_address_match_item_release(ami); } } // end of the ipv4 / ipv6 else block yassert(ami != NULL); #if DEBUG log_debug7("acl_address_match_list_init_from_text(%p, %s, %u) : adding %p (---)", (void*)aml, STR(description), use_definitions, (void*)ami); logger_flush(); #endif ptr_vector_append(&list, ami); } /* while there is something to parse */ s32 count = ptr_vector_size(&list); if((count > 0) && (count <= 1024)) { ptr_vector_shrink(&list); #if DEBUG log_debug7("acl_address_match_list_init_from_text(%p, %s, %u) : items at %p", (void*)aml, STR(description), use_definitions, (void*)list.data); logger_flush(); #endif aml->items = (address_match_item**)list.data; aml->limit = &aml->items[count]; } else { // the list is empty acl_address_match_item_vector_destroy(&list); if(count > 1024) { return ACL_TOO_MANY_TOKENS; } } return count; } ya_result acl_definition_add(const char* name, const char *description) { #if DEBUG log_debug7("acl_add_definition(%s, %s)", STR(name), STR(description)); logger_flush(); #endif yassert(name != NULL); yassert(description != NULL); acl_entry *acl; ya_result return_code; if(acl_entry_exists(name)) { return ACL_DUPLICATE_ENTRY; } acl = acl_entry_new_instance(name); if(FAIL(return_code = acl_address_match_list_init_from_text(&acl->list, description, FALSE))) { acl_entry_delete(acl); return return_code; } #if DEBUG log_debug7("acl_add_definition(%s @ %p, %s) list %p items %p", STR(name), (void*)acl, STR(description), (void*)&acl->list, (void*)acl->list.items); logger_flush(); #endif return SUCCESS; } #if ACL_EXTENDED_FEATURES static void acl_address_match_item_free_ptr(void *ami_) { address_match_item *ami = (address_match_item*)ami_; if(!acl_address_match_item_release(ami)) { u32 txt_size; char txt[512]; txt_size = sizeof(txt); acl_address_match_item_to_string(ami, txt, &txt_size); if(txt_size <= sizeof(txt)) { log_debug7("acl: not destroying '%s' (rc=%i)", txt, ami->_rc); } else { log_debug7("acl: not destroying @%p (rc=%i)", ami, ami->_rc); } } } static void acl_definition_free_ptr(void *def) { acl_entry *entry = (acl_entry*)def; #if DEBUG log_debug7("acl_free_definition(%p) : '%s'", def, entry->name); logger_flush(); #endif free((void*)entry->name); address_match_item **amip = entry->list.items; address_match_item **limit = entry->list.limit; while(amip < limit) { address_match_item* ami = (*amip++); acl_address_match_item_release(ami); } #if DEBUG log_debug7("acl_free_definition(%p) items: %p", def, (void*)entry->list.items); logger_flush(); #endif free(entry->list.items); free(entry); } #endif void acl_definitions_free() { #if DEBUG log_debug7("acl_definitions_free()"); logger_flush(); #endif /* log_debug7("acl_definitions_free(): %u amim", ptr_vector_size(&g_amim)); ptr_vector_callback_and_clear(&g_amim, &acl_address_match_item_free_ptr); ptr_vector_destroy(&g_amim); log_debug7("acl_definitions_free(): %u acl", ptr_vector_size(&g_acl)); ptr_vector_callback_and_clear(&g_acl, &acl_definition_free_ptr); ptr_vector_destroy(&g_acl); */ } /** * Builds an access control using the text descriptors and the acl data. * Expands the access control. * */ ya_result acl_access_control_init_from_text(access_control *ac, const char *allow_query, const char *allow_update, const char *allow_update_forwarding, const char *allow_transfer, const char *allow_notify, const char *allow_control) { #if DEBUG log_debug7("acl_init_access_control_from_text(%p, %s, %s ,%s, %s, %s)", (void*)ac, STR(allow_query), STR(allow_update), STR(allow_update_forwarding), STR(allow_transfer), STR(allow_notify), STR(allow_control)); logger_flush(); #endif ya_result return_code; if(ISOK(return_code = acl_access_control_item_init_from_text(&ac->allow_query, allow_query))) { if(ISOK(return_code = acl_access_control_item_init_from_text(&ac->allow_update, allow_update))) { if(ISOK(return_code = acl_access_control_item_init_from_text(&ac->allow_update_forwarding, allow_update_forwarding))) { if(ISOK(return_code = acl_access_control_item_init_from_text(&ac->allow_transfer, allow_transfer))) { if(ISOK(return_code = acl_access_control_item_init_from_text(&ac->allow_notify, allow_notify))) { return_code = acl_access_control_item_init_from_text(&ac->allow_control, allow_control); } } } } } return return_code; } void acl_address_match_list_clear(address_match_list *aml) { #if DEBUG log_debug7("acl_empties_address_match_list(%p): %p", (void*)aml, (void*)aml->items); logger_flush(); #endif for(address_match_item **amip = aml->items; amip < aml->limit; amip++) { address_match_item *ami = *amip; if(acl_address_match_item_release(ami)) { //assert(FALSE); /* s32 amim_idx = address_match_item_collection_get_index(ami); if(amim_idx >= 0) { log_debug7("acl_empties_address_match_list(%p): %p is part of amim", (void*)aml, address_match_item_rc(ami)); ptr_vector_end_swap(&g_amim, amim_idx); g_amim.offset--; } address_match_item_release(ami); */ } } #if DEBUG if(aml->items != NULL) { size_t n = (u8*)aml->limit - (u8*)aml->items; memset(aml->items, 0xff, n); } #endif free(aml->items); aml->items = NULL; aml->limit = NULL; } void acl_address_match_set_clear(address_match_set *ams) { #if DEBUG log_debug7("acl_empties_address_match_set(%p)", (void*)ams); logger_flush(); #endif acl_address_match_list_clear(&ams->ipv4); acl_address_match_list_clear(&ams->ipv6); acl_address_match_list_clear(&ams->tsig); } void acl_access_control_clear(access_control *ac) { #if DEBUG log_debug7("acl_access_control_clear(%p)", (void*)ac); logger_flush(); #endif if(ac->_rc == 0) { return; } acl_address_match_set_clear(&ac->allow_notify); acl_address_match_set_clear(&ac->allow_query); acl_address_match_set_clear(&ac->allow_transfer); acl_address_match_set_clear(&ac->allow_update); acl_address_match_set_clear(&ac->allow_update_forwarding); acl_address_match_set_clear(&ac->allow_control); } void acl_address_match_list_copy(address_match_list *target, const address_match_list* aml) { intptr n = (intptr)(aml->limit - aml->items); if(n > 0) { MALLOC_OBJECT_ARRAY_OR_DIE(target->items, address_match_item*, n, ADRMITEM_TAG); target->limit = &target->items[n]; for(intptr i = 0; i < n; i++) { target->items[i] = acl_address_match_item_alloc(); memcpy(target->items[i], aml->items[i], sizeof(address_match_item)); if(target->items[i]->match == amim_reference) { target->items[i]->parameters.ref.name = strdup(target->items[i]->parameters.ref.name); } } } else { target->items = NULL; target->limit = NULL; } } void acl_address_match_set_copy(address_match_set *target, const address_match_set *ams) { acl_address_match_list_copy(&target->ipv4, &ams->ipv4); acl_address_match_list_copy(&target->ipv6, &ams->ipv6); acl_address_match_list_copy(&target->tsig, &ams->tsig); } void acl_access_control_copy(access_control *target, const access_control *ac) { acl_address_match_set_copy(&target->allow_query, &ac->allow_query); acl_address_match_set_copy(&target->allow_update, &ac->allow_update); acl_address_match_set_copy(&target->allow_update_forwarding, &ac->allow_update_forwarding); acl_address_match_set_copy(&target->allow_transfer, &ac->allow_transfer); acl_address_match_set_copy(&target->allow_notify, &ac->allow_notify); acl_address_match_set_copy(&target->allow_control, &ac->allow_control); } void acl_access_control_acquire(access_control *ac) { #if ACL_DEBUG_ARC s32 rc = #endif ++ac->_rc; #if ACL_DEBUG_ARC log_debug("access_control@%p acquire: %i", ac, rc); #endif } bool acl_access_control_release(access_control *ac) { #if !ACL_DEBUG_ARC if(--ac->_rc <= 0) #else s32 rc = --ac->_rc; if(rc <= 0) #endif { #if ACL_DEBUG_ARC log_debug("access_control@%p acquire: %i", ac, rc); #endif acl_unmerge_access_control(ac); acl_access_control_clear(ac); ZFREE_OBJECT(ac); return TRUE; } #if ACL_DEBUG_ARC log_debug("access_control@%p acquire: %i", ac, rc); #endif return FALSE; } ya_result acl_access_control_item_init_from_text(address_match_set *ams, const char* allow_whatever) { #if DEBUG log_debug7("acl_build_access_control_item(%p, \"%s\")", ams, STR(allow_whatever)); #endif ya_result return_code; address_match_list aml; ZEROMEMORY(&aml, sizeof(aml)); if(ISOK(return_code = acl_address_match_list_init_from_text(&aml, allow_whatever, TRUE))) { if(aml.items == NULL) { /* * Empty set */ #if DEBUG log_debug7("acl_build_access_control_item(%p, \"%s\") returning empty set", ams, STR(allow_whatever)); #endif return SUCCESS; } ptr_vector ipv4v = PTR_VECTOR_EMPTY; ptr_vector ipv6v = PTR_VECTOR_EMPTY; #if DNSCORE_HAS_TSIG_SUPPORT ptr_vector tsigv = PTR_VECTOR_EMPTY; #endif address_match_item **amip = aml.items; while(amip < aml.limit) { address_match_item *ami = *amip; if(IS_IPV4_ITEM(ami)) { if(((ami->parameters.ipv4.maskbits == 32) || (ami->parameters.ipv4.maskbits == 0)) && (ami->parameters.ipv4.address.value == 0) ) { /* A.K.A any/none IPv4 */ // ^ | & // A 0 => A 0 0 0 0 // A ~0 => R 0 1 1 0 // R 0 => R 1 0 1 0 // R ~0 => A 1 1 1 1 // REJECTS NONE bool rejects = (ami->parameters.ipv4.rejects != 0); bool none = (ami->parameters.ipv4.maskbits != 0); bool xored = (rejects || none) && !(rejects && none); //acl_free_address_match_item(item); //item = alloc_address_match_item(); ami->match = (xored) ? amim_none : amim_any; } acl_address_match_item_acquire(ami); ptr_vector_append(&ipv4v, ami); } else if(IS_IPV6_ITEM(ami)) { if(((ami->parameters.ipv6.maskbits == 128) || (ami->parameters.ipv6.maskbits == 0)) && IPV6_ADDRESS_ALL0(ami->parameters.ipv6.address)) { /* A.K.A any/none IPv6 */ // A 0 => A // A ~0 => R // R 0 => R // R ~0 => A // REJECTS NONE bool rejects = (ami->parameters.ipv6.rejects != 0); bool none = (ami->parameters.ipv6.maskbits != 0); bool xored = (rejects || none) && !(rejects && none); //acl_free_address_match_item(item); //item = alloc_address_match_item(); ami->match = (xored) ? amim_none : amim_any; } acl_address_match_item_acquire(ami); ptr_vector_append(&ipv6v, ami); } #if DNSCORE_HAS_TSIG_SUPPORT else if(IS_TSIG_ITEM(ami)) { acl_address_match_item_acquire(ami); ptr_vector_append(&tsigv, ami); } #endif else /* any or none */ { acl_address_match_item_acquire(ami); acl_address_match_item_acquire(ami); ptr_vector_append(&ipv4v, ami); ptr_vector_append(&ipv6v, ami); //ptr_vector_append(&tsigv, item); } amip++; } ptr_vector_shrink(&ipv4v); ams->ipv4.items = (address_match_item**)ipv4v.data; ams->ipv4.limit = &ams->ipv4.items[ipv4v.offset + 1]; #if ACL_SORT_RULES amim_ipv4_sort(&ipv4v); #endif #if DEBUG amim_ipv4_print(&ipv4v); #endif ptr_vector_shrink(&ipv6v); ams->ipv6.items = (address_match_item**)ipv6v.data; ams->ipv6.limit = &ams->ipv6.items[ipv6v.offset + 1]; #if ACL_SORT_RULES amim_ipv6_sort(&ipv6v); #endif #if DEBUG amim_ipv6_print(&ipv6v); #endif #if DNSCORE_HAS_TSIG_SUPPORT ptr_vector_shrink(&tsigv); ams->tsig.items = (address_match_item**)tsigv.data; ams->tsig.limit = &ams->tsig.items[tsigv.offset + 1]; #if DEBUG amim_tsig_print(&tsigv); #endif #endif } acl_address_match_list_clear(&aml); #if DEBUG output_stream baos; bytearray_output_stream_init(&baos, NULL, 0); acl_address_match_set_to_stream(&baos, ams); output_stream_write_u8(&baos,0); log_debug7("acl_build_access_control_item(%p, \"%s\"): %s", ams, STR(allow_whatever), bytearray_output_stream_buffer(&baos)); output_stream_close(&baos); #endif #if DEBUG log_debug7("acl_build_access_control_item(%p, \"%s\") returning {%p,%p,%p}", ams, STR(allow_whatever), ams->ipv4.items, ams->ipv6.items, ams->tsig.items); #endif return return_code; } // static void acl_merge_address_match_set(address_match_set *dest, const address_match_set *src) { if((dest->ipv4.items == NULL) && (dest->ipv6.items == NULL) && (dest->tsig.items == NULL)) { dest->ipv4.items = src->ipv4.items; dest->ipv4.limit = src->ipv4.limit; dest->ipv6.items = src->ipv6.items; dest->ipv6.limit = src->ipv6.limit; dest->tsig.items = src->tsig.items; dest->tsig.limit = src->tsig.limit; } } void acl_merge_access_control(access_control *dest, access_control *src) { #if ACL_DEBUG_ARC log_debug("acl_merge_access_control(%p, %p)", dest, src); #endif if(dest->based_on != src) { yassert(dest->based_on == NULL); acl_merge_address_match_set(&dest->allow_notify, &src->allow_notify); acl_merge_address_match_set(&dest->allow_query, &src->allow_query); acl_merge_address_match_set(&dest->allow_transfer, &src->allow_transfer); acl_merge_address_match_set(&dest->allow_update, &src->allow_update); acl_merge_address_match_set(&dest->allow_update_forwarding, &src->allow_update_forwarding); acl_merge_address_match_set(&dest->allow_control, &src->allow_control); dest->based_on = src; acl_access_control_acquire(src); } } static void acl_unmerge_address_match_set(address_match_set *dest, const address_match_set *src) { if(dest->ipv4.items == src->ipv4.items) { dest->ipv4.items = NULL; dest->ipv4.limit = NULL; } if(dest->ipv6.items == src->ipv6.items) { dest->ipv6.items = NULL; dest->ipv6.limit = NULL; } if(dest->tsig.items == src->tsig.items) { dest->tsig.items = NULL; dest->tsig.limit = NULL; } } void acl_unmerge_access_control(access_control *dest) { #if ACL_DEBUG_ARC log_debug("acl_unmerge_access_control(%p)", dest); #endif if(dest->based_on != NULL) { access_control *src = dest->based_on; acl_unmerge_address_match_set(&dest->allow_notify, &src->allow_notify); acl_unmerge_address_match_set(&dest->allow_query, &src->allow_query); acl_unmerge_address_match_set(&dest->allow_transfer, &src->allow_transfer); acl_unmerge_address_match_set(&dest->allow_update, &src->allow_update); acl_unmerge_address_match_set(&dest->allow_update_forwarding, &src->allow_update_forwarding); acl_unmerge_address_match_set(&dest->allow_control, &src->allow_control); acl_access_control_release(src); dest->based_on = NULL; } }// bool acl_address_match_set_isempty(const address_match_set *ams) { return (ams->ipv4.items == NULL) && (ams->ipv6.items == NULL) && (ams->tsig.items == NULL); } static ya_result acl_address_match_set_check_v4(const address_match_set *set, const struct sockaddr_in *ipv4) { ya_result return_code = 0; address_match_item **itemp = (address_match_item**)set->ipv4.items; while(itemp < set->ipv4.limit) { address_match_item *item = *itemp++; /* * < 0 : rejected (stop) * > 0 : accepted (stop) * = 0 : didn't matched (continue) */ if((return_code = item->match(item, &ipv4->sin_addr.s_addr)) != AMIM_SKIP) { break; } } return return_code; } static ya_result acl_address_match_set_check_v6(const address_match_set *set, const struct sockaddr_in6 *ipv6) { ya_result return_code = 0; address_match_item **itemp = (address_match_item**)set->ipv6.items; while(itemp < set->ipv6.limit) { address_match_item *item = *itemp++; /* * < 0 : rejected (stop) * > 0 : accepted (stop) * = 0 : didn't matched (continue) */ if((return_code = item->match(item, ipv6->sin6_addr.s6_addr)) != AMIM_SKIP) { break; } } return return_code; } static ya_result acl_address_match_set_check_tsig(const address_match_set *set, const void *message_with_tsig) { ya_result return_code = 0; address_match_item **itemp = (address_match_item**)set->tsig.items; while(itemp < set->tsig.limit) { address_match_item *item = *itemp++; /* * < 0 : rejected (stop) * > 0 : accepted (stop) * = 0 : didn't matched (continue) */ if((return_code = item->match(item, message_with_tsig)) != AMIM_SKIP) { break; } } return return_code; } /********************************************************************************************************************************/ // // RRI ARI 4RI static inline ya_result acl_check_access_filter_RRI(const message_data *mesg, const address_match_set *ams) { (void)mesg; (void)ams; return AMIM_REJECT; } static inline ya_result acl_check_access_filter_ARI(const message_data *mesg, const address_match_set *ams) { (void)ams; return (message_get_sender_sa_family(mesg) == AF_INET)?AMIM_ACCEPT:AMIM_REJECT; } static inline ya_result acl_check_access_filter_4RI(const message_data *mesg, const address_match_set *ams) { if(message_get_sender_sa_family(mesg) == AF_INET) { return acl_address_match_set_check_v4(ams, message_get_sender_sa4(mesg)) - 1; /* -1 to transform ignore to reject */ } return AMIM_REJECT; } // RAI AAI 4AI static inline ya_result acl_check_access_filter_RAI(const message_data *mesg, const address_match_set *ams) { (void)ams; return (message_get_sender_sa_family(mesg) == AF_INET6)?AMIM_ACCEPT:AMIM_REJECT; } static ya_result acl_check_access_filter_AAI(const message_data *mesg, const address_match_set *ams) { (void)mesg; (void)ams; return AMIM_ACCEPT; } static inline ya_result acl_check_access_filter_4AI(const message_data *mesg, const address_match_set *ams) { if(message_get_sender_sa_family(mesg) == AF_INET) { return acl_address_match_set_check_v4(ams, message_get_sender_sa4(mesg)) - 1; } else { return AMIM_ACCEPT; } } // R6I A6I 46I static inline ya_result acl_check_access_filter_R6I(const message_data *mesg, const address_match_set *ams) { if(message_get_sender_sa_family(mesg) == AF_INET6) { return acl_address_match_set_check_v6(ams, message_get_sender_sa6(mesg)) -1; } return AMIM_REJECT; } static inline ya_result acl_check_access_filter_A6I(const message_data *mesg, const address_match_set *ams) { if(message_get_sender_sa_family(mesg) == AF_INET6) { return acl_address_match_set_check_v6(ams, message_get_sender_sa6(mesg)) - 1; } else { return AMIM_ACCEPT; } } static inline ya_result acl_check_access_filter_46I(const message_data *mesg, const address_match_set *ams) { if(message_get_sender_sa_family(mesg) == AF_INET) { return acl_address_match_set_check_v4(ams, message_get_sender_sa4(mesg)) - 1; } else if(message_get_sender_sa_family(mesg) == AF_INET6) { return acl_address_match_set_check_v6(ams, message_get_sender_sa6(mesg)) - 1; } return AMIM_REJECT; } // TSIG // RRT ART 4RT static inline ya_result acl_check_access_filter_RRT(const message_data *mesg, const address_match_set *ams) { (void)mesg; (void)ams; return AMIM_REJECT; } static inline ya_result acl_check_access_filter_ART(const message_data *mesg, const address_match_set *ams) { if(message_is_additional_section_ptr_set(mesg) && (message_get_sender_sa_family(mesg) == AF_INET)) { return acl_address_match_set_check_tsig(ams, mesg) - 1; } return AMIM_REJECT; } static inline ya_result acl_check_access_filter_4RT(const message_data *mesg, const address_match_set *ams) { if(message_is_additional_section_ptr_set(mesg) && (message_get_sender_sa_family(mesg) == AF_INET)) { if(!ACL_REJECTED(acl_address_match_set_check_v4(ams, message_get_sender_sa4(mesg)))) { return acl_address_match_set_check_tsig(ams, mesg) - 1; } } return AMIM_REJECT; } // RAT AAT 4AT static inline ya_result acl_check_access_filter_RAT(const message_data *mesg, const address_match_set *ams) { if(message_is_additional_section_ptr_set(mesg) && (message_get_sender_sa_family(mesg) == AF_INET6)) { return acl_address_match_set_check_tsig(ams, mesg) - 1; } return AMIM_REJECT; } static inline ya_result acl_check_access_filter_AAT(const message_data *mesg, const address_match_set *ams) { if(message_is_additional_section_ptr_set(mesg)) { return acl_address_match_set_check_tsig(ams, mesg) - 1; } return AMIM_REJECT; } static inline ya_result acl_check_access_filter_4AT(const message_data *mesg, const address_match_set *ams) { if(message_is_additional_section_ptr_set(mesg)) { if(message_get_sender_sa_family(mesg) == AF_INET) { if(ACL_REJECTED(acl_address_match_set_check_v4(ams, message_get_sender_sa4(mesg)))) { return AMIM_REJECT; } } return acl_address_match_set_check_tsig(ams, mesg) - 1; } return AMIM_REJECT; } // R6T A6T 46T static inline ya_result acl_check_access_filter_R6T(const message_data *mesg, const address_match_set *ams) { if(message_is_additional_section_ptr_set(mesg)) { if(message_get_sender_sa_family(mesg) == AF_INET6) { if(!ACL_REJECTED(acl_address_match_set_check_v6(ams, message_get_sender_sa6(mesg)))) { return acl_address_match_set_check_tsig(ams, mesg) - 1; } } } return AMIM_REJECT; } static inline ya_result acl_check_access_filter_A6T(const message_data *mesg, const address_match_set *ams) { if(message_is_additional_section_ptr_set(mesg)) { if(message_get_sender_sa_family(mesg) == AF_INET6) { if(ACL_REJECTED(acl_address_match_set_check_v6(ams, message_get_sender_sa6(mesg)))) { return AMIM_REJECT; } } return acl_address_match_set_check_tsig(ams, mesg) - 1; } return AMIM_REJECT; } static inline ya_result acl_check_access_filter_46T(const message_data *mesg, const address_match_set *ams) { if(message_is_additional_section_ptr_set(mesg)) { if(message_get_sender_sa_family(mesg) == AF_INET) { if(ACL_REJECTED(acl_address_match_set_check_v4(ams, message_get_sender_sa4(mesg)))) { return AMIM_REJECT; } } else if(message_get_sender_sa_family(mesg) == AF_INET6) { if(ACL_REJECTED(acl_address_match_set_check_v6(ams, message_get_sender_sa6(mesg)))) { return AMIM_REJECT; } } return acl_address_match_set_check_tsig(ams, mesg) - 1; } return AMIM_REJECT; } ya_result acl_check_access_filter(const message_data *mesg, const address_match_set *ams) { ya_result return_code = AMIM_SKIP; /* * If there the client is on IPvX and IPvX has rules, the default is set to REJECT * then the client's address is compared to all the items in the list, returning on a match. */ if(message_get_sender_sa_family(mesg) == AF_INET) { if(ams->ipv4.items != NULL) { if(ACL_REJECTED(return_code = acl_address_match_set_check_v4(ams, message_get_sender_sa4(mesg)))) { return return_code; } } } else if(message_get_sender_sa_family(mesg) == AF_INET6) { if(ams->ipv6.items != NULL) { if(ACL_REJECTED(return_code = acl_address_match_set_check_v6(ams, message_get_sender_sa6(mesg)))) { return return_code; } } } #if DEBUG else { log_err("acl: unsupported address family %d", message_get_sender_sa_family(mesg)); return AMIM_REJECT; } #endif /* * At this point, none of the IPs have been explicitly rejected. * If they are accepted */ /* * If no address has been matched, then if the rules are holding any TSIG, ... */ if(ams->tsig.items != NULL) { if(message_is_additional_section_ptr_set(mesg)) { return_code += acl_address_match_set_check_tsig(ams, mesg); } else { --return_code; } } return_code--; return return_code; } // /* * RRI ARI FRI * RAI AAI FAI * RFI AFI FFI * RRF ARF FRF * RAF AAF FAF * RFF AFF FFF */ #define CAF(x) acl_check_access_filter_##x static acl_check_access_filter_callback* access_filter_by_type[18]= { CAF(RRI), CAF(ARI), CAF(4RI), CAF(RAI), CAF(AAI), CAF(4AI), CAF(R6I), CAF(A6I), CAF(46I), CAF(RRT), CAF(ART), CAF(4RT), CAF(RAT), CAF(AAT), CAF(4AT), CAF(R6T), CAF(A6T), CAF(46T) }; #undef CAF acl_check_access_filter_callback * acl_get_check_access_filter(const address_match_set *set) { acl_check_access_filter_callback* cb; u32 t = acl_address_match_set_get_type(set); cb = access_filter_by_type[t]; return cb; } /********************************************************************************************************************************/ // /** * This macro is a template for the hook function from the allow_query input to the generic input * The only hooks that are not using it are the most simple ones (returning ACCEPT or REJECT) */ #define CAF_HOOK(x) static inline ya_result acl_query_access_filter_##x(const message_data *mesg, const void *extension) \ { \ const access_control *ac = (const access_control*)extension; \ return acl_check_access_filter_##x(mesg, &ac->allow_query); \ } static ya_result acl_query_access_filter_AAI(const message_data *mesg, const void *extension) { (void)mesg; (void)extension; return AMIM_ACCEPT; } static ya_result acl_query_access_filter_RRI(const message_data *mesg, const void *extension) { (void)mesg; (void)extension; return AMIM_REJECT; } static ya_result acl_query_access_filter_RRT(const message_data *mesg, const void *extension) { (void)mesg; (void)extension; return AMIM_REJECT; } //CAF_HOOK(RRI) CAF_HOOK(ARI) CAF_HOOK(4RI) CAF_HOOK(RAI) //CAF_HOOK(AAI) CAF_HOOK(4AI) CAF_HOOK(R6I) CAF_HOOK(A6I) CAF_HOOK(46I) //CAF_HOOK(RRT) CAF_HOOK(ART) CAF_HOOK(4RT) CAF_HOOK(RAT) CAF_HOOK(AAT) CAF_HOOK(4AT) CAF_HOOK(R6T) CAF_HOOK(A6T) CAF_HOOK(46T) // #define QAF(x) acl_query_access_filter_##x static acl_query_access_filter_callback* query_access_filter_by_type[18]= { QAF(RRI), QAF(ARI), QAF(4RI), QAF(RAI), QAF(AAI), QAF(4AI), QAF(R6I), QAF(A6I), QAF(46I), QAF(RRT), QAF(ART), QAF(4RT), QAF(RAT), QAF(AAT), QAF(4AT), QAF(R6T), QAF(A6T), QAF(46T) }; #undef QAF acl_query_access_filter_callback * acl_get_query_access_filter(const address_match_set *set) { acl_query_access_filter_callback* cb; u32 t = acl_address_match_set_get_type(set); cb = query_access_filter_by_type[t]; return cb; } ya_result acl_address_match_item_to_stream(output_stream *os, const address_match_item *ami) { ya_result return_code; if(ami == NULL) { return 0; } else if(IS_IPV4_ITEM(ami)) { s8 b = ami->parameters.ipv4.maskbits; //s8 r = ami->parameters.ipv4.rejects; struct sockaddr_in ipv4; ipv4.sin_addr.s_addr = ami->parameters.ipv4.address.value; ipv4.sin_family = AF_INET; if(IS_IPV4_ITEM_MATCH(ami)) { return_code = osformat(os, "%{sockaddrip}/%d", &ipv4, b); } else { return_code = osformat(os, "!%{sockaddrip}/%d", &ipv4, b); } } else if(IS_IPV6_ITEM(ami)) { s16 b = ami->parameters.ipv6.maskbits; //s8 r = ami->parameters.ipv6.rejects; struct sockaddr_in6 ipv6; memcpy((u8*)&ipv6.sin6_addr, ami->parameters.ipv6.address.bytes, 16); ipv6.sin6_family = AF_INET6; if(IS_IPV6_ITEM_MATCH(ami)) { return_code = osformat(os, "%{sockaddrip}/%d", &ipv6, b); } else { return_code = osformat(os, "!%{sockaddrip}/%d", &ipv6, b); } } #if DNSCORE_HAS_TSIG_SUPPORT else if(IS_TSIG_ITEM(ami)) { if(IS_TSIG_ITEM_MATCH(ami)) { return_code = osformat(os, "key %{dnsname}", ami->parameters.tsig.name); } else { return_code = osformat(os, "!key %{dnsname}", ami->parameters.tsig.name); } } #endif else if(IS_ANY_ITEM(ami)) { if(IS_ANY_ITEM_MATCH(ami)) { osformat(os, "[%i]", acl_address_match_item_rc(ami)); return 1; } else { osformat(os, "[%i]", acl_address_match_item_rc(ami)); return 2; } } else { return_code = osformat(os, "?"); } if(ISOK(return_code)) { osformat(os, "[%i]", acl_address_match_item_rc(ami)); return_code = 0; } return return_code; } void acl_address_match_set_to_stream(output_stream *os, const address_match_set *ams) { address_match_item **item; address_match_item **limit; ya_result any_none = 0; ya_result return_code; char spc; item = ams->ipv4.items; limit = ams->ipv4.limit; spc = ' '; while(item < limit) { output_stream_write_u8(os, (u8)spc); return_code = acl_address_match_item_to_stream(os, *item); if(return_code > 0) { any_none |= return_code; break; } spc = ','; item++; } item = ams->ipv6.items; limit = ams->ipv6.limit; while(item < limit) { output_stream_write_u8(os, (u8)spc); return_code = acl_address_match_item_to_stream(os, *item); if(return_code > 0) { any_none |= return_code; break; } spc = ','; item++; } item = ams->tsig.items; limit = ams->tsig.limit; while(item < limit) { output_stream_write_u8(os, (u8)spc); return_code = acl_address_match_item_to_stream(os, *item); if(return_code > 0) { any_none |= return_code; break; } spc = ','; item++; } if(any_none != 0) { if(any_none & 1) { osformat(os, "%cany", spc); spc = ','; } if(any_none & 2) { osformat(os, "%cnone", spc); } } } ya_result acl_address_match_item_to_string(const address_match_item *ami, char *out_txt, u32 *out_txt_lenp) { ya_result return_code; u32 out_txt_len = *out_txt_lenp; if(ami == NULL) { return_code = snformat(out_txt, out_txt_len, "NULL->REJECT"); } else if(IS_IPV4_ITEM(ami)) { s8 b = ami->parameters.ipv4.maskbits; //s8 r = ami->parameters.ipv4.rejects; struct sockaddr_in ipv4; ipv4.sin_addr.s_addr = ami->parameters.ipv4.address.value; ipv4.sin_family = AF_INET; if(IS_IPV4_ITEM_MATCH(ami)) { return_code = snformat(out_txt, out_txt_len, "[%{sockaddrip}/%d]", &ipv4, b); } else { return_code = snformat(out_txt, out_txt_len, "![%{sockaddrip}/%d]", &ipv4, b); } } else if(IS_IPV6_ITEM(ami)) { s16 b = ami->parameters.ipv6.maskbits; //s8 r = ami->parameters.ipv6.rejects; struct sockaddr_in6 ipv6; memcpy((u8*)&ipv6.sin6_addr, ami->parameters.ipv6.address.bytes, 16); ipv6.sin6_family = AF_INET6; if(IS_IPV6_ITEM_MATCH(ami)) { return_code = snformat(out_txt, out_txt_len, "[%{sockaddrip}/%d]", &ipv6, b); } else { return_code = snformat(out_txt, out_txt_len, "![%{sockaddrip}/%d]", &ipv6, b); } } #if DNSCORE_HAS_TSIG_SUPPORT else if(IS_TSIG_ITEM(ami)) { if(IS_TSIG_ITEM_MATCH(ami)) { return_code = snformat(out_txt, out_txt_len, "[%{dnsname}]", ami->parameters.tsig.name); } else { return_code = snformat(out_txt, out_txt_len, "![%{dnsname}]", ami->parameters.tsig.name); } } #endif else if(IS_ANY_ITEM(ami)) { if(IS_ANY_ITEM_MATCH(ami)) { return_code = snformat(out_txt, out_txt_len, "[any]"); } else { return_code = snformat(out_txt, out_txt_len, "[none]"); } } else { return_code = snformat(out_txt, out_txt_len, "?"); } if(ISOK(return_code)) { *out_txt_lenp = (u32)return_code; } return return_code; } bool acl_address_match_item_equals(const address_match_item *a, const address_match_item *b) { if(a == b) { return TRUE; } if((a == NULL) || (b == NULL)) { return FALSE; } if(a->match == b->match) { if((a->match == amim_none) || (a->match == amim_any)) { return TRUE; } if((a->match == amim_ipv4) || (a->match == amim_ipv4_not)) { return a->parameters.ipv4.address.value == b->parameters.ipv4.address.value; } if((a->match == amim_ipv6) || (a->match == amim_ipv6_not)) { return (a->parameters.ipv6.address.lohi[0] == b->parameters.ipv6.address.lohi[0]) || (a->parameters.ipv6.address.lohi[1] == b->parameters.ipv6.address.lohi[1]); } #if DNSCORE_HAS_TSIG_SUPPORT if((a->match == amim_tsig) || (a->match == amim_tsig_not)) { return (a->parameters.tsig.mac_algorithm == b->parameters.tsig.mac_algorithm) && (a->parameters.tsig.name_size == b->parameters.tsig.name_size) && (a->parameters.tsig.secret_size == b->parameters.tsig.secret_size) && (memcmp(a->parameters.tsig.name, b->parameters.tsig.name, a->parameters.tsig.name_size) == 0) && (memcmp(a->parameters.tsig.known, b->parameters.tsig.known, a->parameters.tsig.secret_size) == 0); } #endif if(a->match == amim_reference) { return (a->parameters.ref.mark == b->parameters.ref.mark) && (strcmp(a->parameters.ref.name, b->parameters.ref.name) == 0); } } return FALSE; } int acl_address_match_item_compare(const address_match_item *a, const address_match_item *b) { if(a == b) { return 0; } if(a == NULL) { return -1; } else if(b == NULL) { return 1; } if(a->match != b->match) { intptr d = ((intptr)a->match) - ((intptr)b->match); if( d > 0) { return 1; } else { return -1; } } // same type if((a->match == amim_ipv4) || (a->match == amim_ipv4_not)) { return memcmp(&a->parameters.ipv4, &b->parameters.ipv4, sizeof(ipv4_id)); } if((a->match == amim_ipv6) || (a->match == amim_ipv6_not)) { return memcmp(&a->parameters.ipv6, &b->parameters.ipv6, sizeof(ipv6_id)); } #if DNSCORE_HAS_TSIG_SUPPORT if((a->match == amim_tsig) || (a->match == amim_tsig_not)) { int d = (int)a->parameters.tsig.mac_algorithm - (int)b->parameters.tsig.mac_algorithm; if(d == 0) { d = (int)a->parameters.tsig.name_size - (int)b->parameters.tsig.name_size; if(d == 0) { d = (int)a->parameters.tsig.secret_size - (int)b->parameters.tsig.secret_size; if(d == 0) { d = memcmp(a->parameters.tsig.name, b->parameters.tsig.name, a->parameters.tsig.name_size); if(d == 0) { d = memcmp(a->parameters.tsig.known, b->parameters.tsig.known, a->parameters.tsig.secret_size); } } } } return d; } #endif if(a->match == amim_reference) { if(a->parameters.ref.mark == b->parameters.ref.mark) { int ret = strcmp(a->parameters.ref.name, b->parameters.ref.name); return ret; } if(a->parameters.ref.mark) { return 1; } else { return -1; } } // amim_none or amim_any return 0; } bool acl_address_match_list_equals(const address_match_list *a, const address_match_list *b) { if(a == b) { return TRUE; } if((a == NULL) || (b == NULL)) { return FALSE; } u64 n = acl_address_match_list_size(a); if(n == acl_address_match_list_size(b)) { address_match_item **a_items = a->items; address_match_item **b_items = b->items; for(intptr i = 0; i < n; i++) { if(!acl_address_match_item_equals(a_items[i], b_items[i])) { return FALSE; } } return TRUE; } return FALSE; } bool acl_address_match_set_equals(const address_match_set *a, const address_match_set *b) { if(a == b) { return TRUE; } if((a == NULL) || (b == NULL)) { return FALSE; } return acl_address_match_list_equals(&a->ipv4, &b->ipv4) && acl_address_match_list_equals(&a->ipv6, &b->ipv6) && acl_address_match_list_equals(&a->tsig, &b->tsig); } bool acl_address_control_equals(const access_control *a, const access_control *b) { if(a == b) { #if ACL_DEBUG_FULL log_debug("acl_address_control_equals(%p, %p) = TRUE", a, b); #endif return TRUE; } if((a == NULL) || (b == NULL)) { #if ACL_DEBUG_FULL log_debug("acl_address_control_equals(%p, %p) = FALSE", a, b); #endif return FALSE; } bool ret = acl_address_match_set_equals(&a->allow_query, &b->allow_query) && acl_address_match_set_equals(&a->allow_update, &b->allow_update) && acl_address_match_set_equals(&a->allow_update_forwarding, &b->allow_update_forwarding) && acl_address_match_set_equals(&a->allow_transfer, &b->allow_transfer) && acl_address_match_set_equals(&a->allow_notify, &b->allow_notify) && acl_address_match_set_equals(&a->allow_control, &b->allow_control); #if ACL_DEBUG_FULL log_debug("acl_address_control_equals(%p, %p) = %s (deep)", a, b, ret?"TRUE":"FALSE"); #endif return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/acl-config.c0000644000000000000000000000013214505005532021476 xustar000000000000000030 mtime=1695812442.438982131 30 atime=1695812445.794030182 30 ctime=1695812494.458727158 yadifa-2.6.5-11201/lib/dnscore/src/acl-config.c0000664000374500037450000001501614505005532021443 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup config Configuration handling * @ingroup yadifad * @brief * * @{ */ /* * DYNAMIC SECTION */ #include "dnscore/dnscore-config.h" #include #include #include #include #include #if !DNSCORE_HAS_ACL_SUPPORT #error "ACL support should not be compiled in" #endif #include #include static bool acl_config_section_print_item(output_stream *os, const char *name, void *ptr) { address_match_set* ams = (address_match_set*)ptr; if(ams != NULL) { osformat(os, "%24s", name); acl_address_match_set_to_stream(os, ams); osprintln(os,""); } return TRUE; } /* * ACL is a dynamic section so there is no config_table * * Each processed section will just add acl lines in the named rules set */ static ya_result acl_config_section_init(struct config_section_descriptor_s *csd) { // NOP (void)csd; config_section_struct_register_type_handler((config_set_field_function*)acl_config_set_item, acl_config_section_print_item); return SUCCESS; } static ya_result acl_config_section_start(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result acl_config_section_stop(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result acl_config_section_postprocess(struct config_section_descriptor_s *csd) { (void)csd; return SUCCESS; } static ya_result acl_config_section_finalize(struct config_section_descriptor_s *csd) { (void)csd; return SUCCESS; } static ya_result acl_config_section_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; if((strcasecmp(key, "none") == 0) || strcasecmp(key, "any") == 0) { /** * Reserved keyword */ return ACL_RESERVED_KEYWORD; } ya_result result_code = acl_definition_add(key, value); return result_code; } static ya_result acl_config_section_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)key; *context = NULL; ptr_set_iterator iter; acl_entry_iterator_init(&iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); //const char *name = (const char*)node->key; acl_entry *entry = (acl_entry*)node->value; osformat(os, "%10s", entry->name); acl_match_items_print((const address_match_item **)entry->list.items, (const address_match_item **)entry->list.limit, os); output_stream_write_u8(os, '\n'); } return SUCCESS; } static const config_section_descriptor_vtbl_s acl_config_section_descriptor_vtbl = { "acl", NULL, // no table acl_config_section_set_wild, acl_config_section_print_wild, acl_config_section_init, acl_config_section_start, acl_config_section_stop, acl_config_section_postprocess, acl_config_section_finalize }; static const config_section_descriptor_s acl_config_section_descriptor = { NULL, &acl_config_section_descriptor_vtbl }; /// register the acl configuration ya_result acl_config_register(const char *null_or_acl_name, s32 priority) { //null_or_acl_name = "acl"; (void)null_or_acl_name; if(priority < 0) { priority = 0; } ya_result return_code; return_code = config_register_const(&acl_config_section_descriptor, priority + 0); return return_code; } /** @brief ACL value parser * * @param[in] value * @param[in] config_command * @param[out] config * * @return an error code */ ya_result acl_config_set_item(const char *value, address_match_set *dest, anytype notused) { (void)notused; ya_result ret; ret = acl_access_control_item_init_from_text(dest, value); return ret; } ya_result acl_config_set_access_control_item(const char *value, access_control **acp, anytype offset) { if(*acp == NULL) { // allocate a fresh one *acp = acl_access_control_new_instance(); } ya_result return_code; address_match_set tmp = ADDRESS_MATCH_SET_INITIALIZER; return_code = acl_config_set_item(value, &tmp, offset); address_match_set *old = (address_match_set*)(((u8*)*acp) + offset._intptr); if(!acl_address_match_set_equals(&tmp, old)) { // all the references to this have to be updated acl_address_match_set_clear(old); *old = tmp; } else { acl_address_match_set_clear(&tmp); } return return_code; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/allocator.c0000644000000000000000000000013214505005532021454 xustar000000000000000030 mtime=1695812442.503983062 30 atime=1695812445.797030225 30 ctime=1695812494.460727187 yadifa-2.6.5-11201/lib/dnscore/src/allocator.c0000664000374500037450000000507314505005532021423 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @ingroup dnscore * * API for allocated memory. Meant to be used with mixed collections. * * Allows allocation on ephemeral stacks, zalloc, malloc, ... of objects * put together, without having trouble sorting them out at destruction time. * * Not used for now. * * @{ */ #define ALLOCATOR_C #include "dnscore/dnscore-config.h" #include "dnscore/allocator.h" void* libc_malloc(allocator_s *unused, u32 size) { (void)unused; void *ptr = malloc(size); return ptr; } void libc_free(allocator_s *unused, void *ptr) { (void)unused; free(ptr); } static allocator_vtbl libc_allocator_vtbl = { libc_malloc, libc_free, "libc_allocator" }; allocator_s libc_allocator = { &libc_allocator_vtbl }; /** * @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/async.c0000644000000000000000000000013214505005532020611 xustar000000000000000030 mtime=1695812442.445982231 30 atime=1695812445.794030182 30 ctime=1695812494.462727215 yadifa-2.6.5-11201/lib/dnscore/src/async.c0000664000374500037450000005366514505005532020572 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include #include "dnscore/dnscore-config.h" #include "dnscore/zalloc.h" #include "dnscore/pool.h" #include "dnscore/mutex.h" #include "dnscore/format.h" #include "dnscore/shared-heap.h" #include "dnscore/format.h" #include "dnscore/logger.h" #include "dnscore/async.h" #define ASYNC_WAIT_DUMP 0 #define ASYNC_NO_TIMEOUT 0 #define ASYNC_FAKE_SHARED_HEAP 0 #if __FreeBSD__ // To avoid some funky stuff with FreeBSD #define ASYNC_WAIT_FINALIZE_DELAY_COUNT 64 #define ASYNC_WAIT_DESTROY_SHARED_DELAY_COUNT 64 #else #define ASYNC_WAIT_FINALIZE_DELAY_COUNT 0 #define ASYNC_WAIT_DESTROY_SHARED_DELAY_COUNT 0 #endif #define MODULE_MSG_HANDLE g_system_logger #define ASYNCMSG_TAG 0x47534d434e595341 #define ASYNCWAIT_TAG 0x5457434e595341 struct async_message_wait_args { mutex_t mutex; cond_t cond_wait; s32 wait_count; }; static pool_s async_message_pool; static bool async_message_pool_initialized = FALSE; void async_message_call(async_queue_s *queue, async_message_s *msg) { msg->start_time = timeus(); #if ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_DLL threaded_dll_cw_enqueue(&queue->queue, msg); #elif ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_RINGBUFFER threaded_ringbuffer_cw_enqueue(&queue->queue, msg); #else threaded_queue_enqueue(&queue->queue, msg); #endif } async_message_s* async_message_next(async_queue_s *queue) { #if ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_DLL //async_message_s* async = (async_message_s*)threaded_dll_cw_try_dequeue(&queue->queue); async_message_s* async = (async_message_s*)threaded_dll_cw_dequeue_with_timeout(&queue->queue, /*queue->pace.max_us*/1000000); #elif ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_RINGBUFFER async_message_s* async = (async_message_s*)threaded_ringbuffer_cw_try_dequeue(&queue->queue); #else async_message_s* async = (async_message_s*)threaded_queue_try_dequeue(&queue->queue); #endif if(async == NULL) { pace_wait(&queue->pace); } else { pace_work(&queue->pace); } return async; } async_message_s* async_message_try_next(async_queue_s *queue) { #if ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_DLL async_message_s* async = (async_message_s*)threaded_dll_cw_try_dequeue(&queue->queue); #elif ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_RINGBUFFER async_message_s* async = (async_message_s*)threaded_ringbuffer_cw_try_dequeue(&queue->queue); #else async_message_s* async = (async_message_s*)threaded_queue_try_dequeue(&queue->queue); #endif return async; } /** * * Initialises a synchronisation point * count is the number of releases to do before the async_wait call returns * * @param aw * @param count * @return */ void async_wait_init(async_wait_s *aw, s32 count) { #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait_init(%p, %i)", getpid_ex(), thread_self(), aw, count);flushout(); #endif mutex_init(&aw->mutex); cond_init(&aw->cond_wait); aw->wait_count = count; aw->error_code = SUCCESS; #if ASYNC_WAIT_TAG aw->tag = 0x50505050; #endif } #if ASYNC_WAIT_FINALIZE_DELAY_COUNT > 0 static mutex_t async_wait_finalize_delay_mtx = MUTEX_INITIALIZER; static async_wait_s* async_wait_finalize_delay[ASYNC_WAIT_FINALIZE_DELAY_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; static int async_wait_finalize_delay_index = 0; static mutex_t async_wait_destroy_delay_mtx = MUTEX_INITIALIZER; static async_wait_s* async_wait_destroy_delay[ASYNC_WAIT_FINALIZE_DELAY_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; static int async_wait_destroy_delay_index = 0; #endif #if ASYNC_WAIT_DESTROY_SHARED_DELAY_COUNT > 0 static mutex_t async_wait_destroy_shared_delay_mtx = MUTEX_INITIALIZER; static async_wait_s* async_wait_destroy_shared_delay[ASYNC_WAIT_DESTROY_SHARED_DELAY_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; static int async_wait_destroy_shared_delay_index = 0; #endif /** * * Destroys the synchronisation point * * @param aw * @return */ #if ASYNC_WAIT_FINALIZE_DELAY_COUNT > 0 static void async_wait_finalize_now(async_wait_s *aw); void async_wait_finalize(async_wait_s *aw) { mutex_lock(&async_wait_finalize_delay_mtx); if(async_wait_finalize_delay[async_wait_finalize_delay_index] != NULL) { async_wait_finalize_now(async_wait_finalize_delay[async_wait_finalize_delay_index]); } async_wait_finalize_delay[async_wait_finalize_delay_index] = aw; async_wait_finalize_delay_index = (async_wait_finalize_delay_index + 1) % ASYNC_WAIT_FINALIZE_DELAY_COUNT; mutex_unlock(&async_wait_finalize_delay_mtx); } static void async_wait_finalize_now(async_wait_s *aw) #else void async_wait_finalize(async_wait_s *aw) #endif { #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait_finalize(%p)", getpid_ex(), thread_self(), aw);flushout(); #endif mutex_lock(&aw->mutex); s32 wait_count = aw->wait_count; mutex_unlock(&aw->mutex); if(wait_count > 0) { osformat(termerr, "async_wait_finalize: wait_count = %i > 0: finalisation before logical end of life", wait_count); flusherr(); } cond_finalize(&aw->cond_wait); mutex_destroy(&aw->mutex); #if DEBUG memset(aw, 0x5e, sizeof(async_wait_s)); #endif #if ASYNC_WAIT_TAG aw->tag &= 0x10101010; #endif } async_wait_s * async_wait_new_instance(s32 count) { async_wait_s *ret; ZALLOC_OBJECT_OR_DIE(ret, async_wait_s, ASYNCWAIT_TAG); async_wait_init(ret, count); return ret; } #if ASYNC_WAIT_FINALIZE_DELAY_COUNT > 0 static void async_wait_destroy_now(async_wait_s *aw); void async_wait_destroy(async_wait_s *aw) { mutex_lock(&async_wait_destroy_delay_mtx); if(async_wait_destroy_delay[async_wait_destroy_delay_index] != NULL) { async_wait_destroy_now(async_wait_destroy_delay[async_wait_destroy_delay_index]); } async_wait_destroy_delay[async_wait_destroy_delay_index] = aw; async_wait_destroy_delay_index = (async_wait_destroy_delay_index + 1) % ASYNC_WAIT_FINALIZE_DELAY_COUNT; mutex_unlock(&async_wait_destroy_delay_mtx); } static void async_wait_destroy_now(async_wait_s *aw) { async_wait_finalize_now(aw); ZFREE_OBJECT(aw); } #else void async_wait_destroy(async_wait_s *aw) { async_wait_finalize(aw); ZFREE_OBJECT(aw); } #endif async_wait_s * async_wait_create_shared(u8 id, s32 count) { #if !ASYNC_FAKE_SHARED_HEAP async_wait_s *aw = (async_wait_s*)shared_heap_wait_alloc(id, sizeof(async_wait_s)); #else async_wait_s *aw = (async_wait_s*)malloc(sizeof(async_wait_s)); #endif #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait_create_shared(%i,%i) -> %p", getpid_ex(), thread_self(), id, count, aw);flushout(); #endif assert(aw != NULL); int err; err = mutex_init_process_shared(&aw->mutex); if(err != 0) { logger_handle_msg(g_system_logger,MSG_ERR, "async_wait_create_shared: init condition failed: %r", MAKE_ERRNO_ERROR(err)); logger_flush(); abort(); } err = cond_init_process_shared(&aw->cond_wait); if(err != 0) { logger_handle_msg(g_system_logger,MSG_ERR, "async_wait_create_shared: init condition failed: %r", MAKE_ERRNO_ERROR(err)); logger_flush(); abort(); } aw->wait_count = count; aw->error_code = SUCCESS; #if ASYNC_WAIT_TAG aw->tag = 0x53535353; #endif return aw; } #if ASYNC_WAIT_DESTROY_SHARED_DELAY_COUNT > 0 static void async_wait_destroy_shared_now(async_wait_s *aw); void async_wait_destroy_shared(async_wait_s *aw) { mutex_lock(&async_wait_destroy_shared_delay_mtx); if(async_wait_destroy_shared_delay[async_wait_destroy_shared_delay_index] != NULL) { async_wait_destroy_shared_now(async_wait_destroy_shared_delay[async_wait_destroy_shared_delay_index]); } async_wait_destroy_shared_delay[async_wait_destroy_shared_delay_index] = aw; async_wait_destroy_shared_delay_index = (async_wait_destroy_shared_delay_index + 1) % ASYNC_WAIT_DESTROY_SHARED_DELAY_COUNT; mutex_unlock(&async_wait_destroy_shared_delay_mtx); } static void async_wait_destroy_shared_now(async_wait_s *aw) { #else void async_wait_destroy_shared(async_wait_s *aw) { #endif #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait_destroy_shared(%p)", getpid_ex(), thread_self(), aw);flushout(); #endif #if ASYNC_WAIT_FINALIZE_DELAY_COUNT > 0 async_wait_finalize_now(aw); #else async_wait_finalize(aw); #endif #if !ASYNC_FAKE_SHARED_HEAP shared_heap_free(aw); #else free(aw); #endif } /** * Waits until the count has be reduced to 0 (or below if something bad is going on) * * @param aw * @return */ void async_wait(async_wait_s *aw) { #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait(%p)", getpid_ex(), thread_self(), aw);flushout(); #endif int err = mutex_lock_unchecked(&aw->mutex); if(err == 0) { while(aw->wait_count > 0) { #if !__FreeBSD__ cond_wait(&aw->cond_wait, &aw->mutex); #else cond_timedwait(&aw->cond_wait, &aw->mutex, ONE_SECOND_US); #endif } mutex_unlock(&aw->mutex); } else { formatln("[%5i][%p] async_wait(%p) failed to lock mutex: %r", getpid_ex(), thread_self(), aw, MAKE_ERRNO_ERROR(err)); flushout(); abort(); } } bool async_wait_timeout_absolute(async_wait_s *aw, s64 epoch_usec) { #if !ASYNC_NO_TIMEOUT struct timespec ts; int err = mutex_lock_unchecked(&aw->mutex); if(err == 0) { ts.tv_sec = epoch_usec / 1000000L; ts.tv_nsec = (epoch_usec % 1000000L) * 1000L; s32 awc; while((awc = aw->wait_count) > 0) { int err; err = cond_timedwait_absolute_ts(&aw->cond_wait, &aw->mutex, &ts); if(err == ETIMEDOUT) { #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait_timeout_absolute(%p,%llu) : TIMEOUT (awc=%i)", getpid_ex(), thread_self(), aw, epoch_usec, awc); #endif break; } if(err != 0) { log_err("async_wait_timeout: %r", MAKE_ERRNO_ERROR(err)); } } err = mutex_unlock_unchecked(&aw->mutex); if(err == 0) { return awc == 0; } else { formatln("[%5i][%p] async_wait_timeout_absolute(%p) failed to unlock mutex: %r", getpid_ex(), thread_self(), aw, MAKE_ERRNO_ERROR(err)); flushout(); abort(); } } else { formatln("[%5i][%p] async_wait_timeout_absolute(%p) failed to lock mutex: %r", getpid_ex(), thread_self(), aw, MAKE_ERRNO_ERROR(err)); flushout(); abort(); } #else // ASYNC_NO_TIMEOUT // timeout disabled async_wait(aw); return TRUE; #endif } /** * Returns TRUE if the wait is done, FALSE if it timed-out. */ bool async_wait_timeout(async_wait_s *aw, s64 relative_usec) { #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait_timeout(%p, %llu)", getpid_ex(), thread_self(), aw, usec);flushout(); #endif relative_usec += timeus(); return async_wait_timeout_absolute(aw, relative_usec); } s32 async_wait_get_counter(async_wait_s *aw) { s32 counter; mutex_lock(&aw->mutex); counter = aw->wait_count; mutex_unlock(&aw->mutex); return counter; } /** * * Decreases the count of that amount * * @param aw * @param count * @return */ void async_wait_progress(async_wait_s *aw, s32 count) { #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait_progress(%p, %i) (lock)", getpid_ex(), thread_self(), aw, count); #endif int err = mutex_lock_unchecked(&aw->mutex); if(err == 0) { if(aw->wait_count - count >= 0) { aw->wait_count -= count; cond_notify(&aw->cond_wait); #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait_progress(%p, %i) (unlock)", getpid_ex(), thread_self(), aw, count); #endif err = mutex_unlock_unchecked(&aw->mutex); #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait_progress(%p, %i) (done)", getpid_ex(), thread_self(), aw, count); #endif if(err != 0) { formatln("[%5i][%p] async_wait_progress(%p) failed to unlock mutex: %r", getpid_ex(), thread_self(), aw, MAKE_ERRNO_ERROR(err)); flushout(); abort(); } } else { log_err("async_wait_progress: count=%i, trying to add %i", aw->wait_count, count); aw->wait_count = 0; cond_notify(&aw->cond_wait); void *p = aw; err = mutex_unlock_unchecked(&aw->mutex); #if ASYNC_WAIT_DUMP formatln("[%5i][%p] async_wait_progress(%p, %i) (done)", getpid_ex(), thread_self(), p, count); #endif if(err != 0) { formatln("[%5i][%p] async_wait_progress(%p) failed to unlock mutex: %r (alt)", getpid_ex(), thread_self(), p, MAKE_ERRNO_ERROR(err)); flushout(); abort(); } } } else { formatln("[%5i][%p] async_wait_progress(%p) failed to lock mutex: %r", getpid_ex(), thread_self(), aw, MAKE_ERRNO_ERROR(err)); flushout(); abort(); } } void async_wait_set_first_error(async_wait_s *aw, s32 error) { mutex_lock(&aw->mutex); if(ISOK(aw->error_code)) { aw->error_code = error; } mutex_unlock(&aw->mutex); } s32 async_wait_get_error(async_wait_s *aw) { s32 err; mutex_lock(&aw->mutex); err = aw->error_code; mutex_unlock(&aw->mutex); return err; } void async_queue_init(async_queue_s *q, u32 size, u64 min_us, u64 max_us, const char* name) { #if ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_DLL threaded_dll_cw_init(&q->queue, size); #elif ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_RINGBUFFER threaded_ringbuffer_cw_init(&q->queue, size); #else threaded_queue_init(&q->queue, size); #endif pace_init(&q->pace, min_us, max_us, name); } void async_queue_finalize(async_queue_s *q) { s32 n; #if ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_DLL if((n = threaded_dll_cw_size(&q->queue)) > 0) { log_warn("async_dll_cw_finalize: queue still contains %i items", n); } threaded_dll_cw_finalize(&q->queue); #elif ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_RINGBUFFER if((n = threaded_ringbuffer_cw_size(&q->queue)) > 0) { log_warn("async_ringbuffer_cw_finalize: queue still contains %i items", n); } threaded_ringbuffer_cw_finalize(&q->queue); #else if((n = threaded_queue_size(&q->queue)) > 0) { log_warn("async_queue_finalize: queue still contains %i items", n); } threaded_queue_finalize(&q->queue); #endif } bool async_queue_empty(async_queue_s *q) { #if ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_DLL return threaded_dll_cw_size(&q->queue) == 0; #elif ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_RINGBUFFER return threaded_ringbuffer_cw_size(&q->queue) == 0; #else return threaded_queue_size(&q->queue) == 0; #endif } u32 async_queue_size(async_queue_s *q) { #if ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_DLL return (u32)threaded_dll_cw_size(&q->queue); #elif ASYNC_QUEUE_TYPE == ASYNC_QUEUE_TYPE_RINGBUFFER return threaded_ringbuffer_cw_size(&q->queue); #else return threaded_queue_size(&q->queue); #endif } static void async_message_wait_handler(struct async_message_s *msg) { struct async_wait_s *args = (struct async_wait_s *)msg->handler_args; async_wait_progress(args, 1); } static void async_message_nop_handler(struct async_message_s *msg) { (void)msg; } static void async_message_release_handler(struct async_message_s *msg) { async_message_release(msg); } int async_message_call_and_wait(async_queue_s *queue, async_message_s *msg) { async_done_callback *old_handler = msg->handler; void *old_handler_args = msg->handler_args; #if __FreeBSD__ struct async_wait_s* message_wait_argsp = async_wait_new_instance(1); #else struct async_wait_s message_wait_args; struct async_wait_s* message_wait_argsp = &message_wait_args; async_wait_init(message_wait_argsp, 1); #endif msg->error_code = SUCCESS; msg->handler = async_message_wait_handler; msg->handler_args = message_wait_argsp; async_message_call(queue, msg); async_wait(message_wait_argsp); msg->handler = old_handler; msg->handler_args = old_handler_args; u64 wait_time = (u64)(timeus() - msg->start_time); #if __FreeBSD__ async_wait_destroy(message_wait_argsp); #else async_wait_finalize(message_wait_argsp); // local stack #endif log_debug5("async waited %lluus on '%i@%s'", wait_time, msg->id, queue->pace.name); return msg->error_code; } void async_message_call_and_forget(async_queue_s *queue, async_message_s *msg) { msg->handler = async_message_nop_handler; msg->handler_args = NULL; async_message_call(queue, msg); } void async_message_call_and_release(async_queue_s *queue, async_message_s *msg) { msg->handler = async_message_release_handler; msg->handler_args = NULL; async_message_call(queue, msg); } static void * async_message_pool_alloc(void *_ignored_) { async_message_s *msg; (void)_ignored_; ZALLOC_OBJECT_OR_DIE( msg, async_message_s, ASYNCMSG_TAG); // POOL ZEROMEMORY(msg, sizeof(async_message_s)); // false positive: msg cannot be NULL return msg; } static void async_message_pool_free(void *msg, void *_ignored_) { (void)_ignored_; memset(msg, 0xe2, sizeof(async_message_s)); ZFREE(msg, async_message_s); // POOL } void async_message_pool_init() { if(!async_message_pool_initialized) { pool_init(&async_message_pool, async_message_pool_alloc, async_message_pool_free, NULL, "async message"); pool_set_size(&async_message_pool, 0x80000); // for valgrind #ifdef VALGRIND_FRIENDLY pool_set_size(&async_message_pool, 0); #endif async_message_pool_initialized = TRUE; } } void async_message_pool_finalize() { if(async_message_pool_initialized) { pool_finalize(&async_message_pool); #if ASYNC_WAIT_FINALIZE_DELAY_COUNT > 0 mutex_lock(&async_wait_finalize_delay_mtx); for(int i = 0; i < ASYNC_WAIT_DESTROY_SHARED_DELAY_COUNT; ++i) { if(async_wait_finalize_delay[i] != NULL) { async_wait_finalize_now(async_wait_finalize_delay[i]); async_wait_finalize_delay[i] = NULL; } } mutex_unlock(&async_wait_finalize_delay_mtx); mutex_lock(&async_wait_destroy_delay_mtx); for(int i = 0; i < ASYNC_WAIT_DESTROY_SHARED_DELAY_COUNT; ++i) { if(async_wait_destroy_delay[i] != NULL) { async_wait_destroy_now(async_wait_destroy_delay[i]); async_wait_destroy_delay[i] = NULL; } } mutex_unlock(&async_wait_destroy_delay_mtx); #endif #if ASYNC_WAIT_DESTROY_SHARED_DELAY_COUNT > 0 mutex_lock(&async_wait_destroy_shared_delay_mtx); for(int i = 0; i < ASYNC_WAIT_DESTROY_SHARED_DELAY_COUNT; ++i) { if(async_wait_destroy_shared_delay[i] != NULL) { async_wait_destroy_shared_now(async_wait_destroy_shared_delay[i]); async_wait_destroy_shared_delay[i] = NULL; } } mutex_unlock(&async_wait_destroy_shared_delay_mtx); #endif async_message_pool_initialized = FALSE; } } async_message_s* async_message_alloc() { async_message_s *msg = (async_message_s *)pool_alloc(&async_message_pool); ZEROMEMORY(msg, sizeof(async_message_s)); return msg; } void async_message_release(async_message_s *msg) { memset(msg, 0xe3, sizeof(async_message_s)); pool_release(&async_message_pool, msg); } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/base16.c0000644000000000000000000000013214505005532020555 xustar000000000000000030 mtime=1695812442.376981243 30 atime=1695812445.791030139 30 ctime=1695812494.464727244 yadifa-2.6.5-11201/lib/dnscore/src/base16.c0000664000374500037450000001301314505005532020515 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup base Base conversion functions * @ingroup dnscore * @brief Base 16 codec * * Base 16 codec functions * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include "dnscore/sys_types.h" static const u8 __BASE16__[16] ={ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /** * Encodes bytes into base16 * The output size must be at least size_in * 2 * * @param buffer_in bytes to convert * @param size_in number of bytes * @param buffer_out output buffer of a size >= size_in * 2 * * @return output size */ u32 base16_encode(const u8* buffer_in, u32 size_in, char* buffer_out) { u32 ret = size_in << 1; while(size_in > 0) { u8 c = *buffer_in++; *buffer_out++ = __BASE16__[c >> 4]; *buffer_out++ = __BASE16__[c & 0x0f]; size_in--; } return ret; } static const u8 __DEBASE16__[256] ={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0 - 7 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8 - 15 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 - 23 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24 - 31 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 - 39 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 40 - 47 ...+.../ */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89...=.. */ 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* .ABCDEFG */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* HIJKLMNO */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* PQRSTUVW */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ..... */ 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* .abcdefg */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* hijklmno */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* pqrstuvw */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* xyz..... */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /** * Decodes base16 into bytes * The output size must be at least size_in / 2 * * @param buffer_in base16 text * @param size_in number of chars * @param buffer_out output buffer of a size >= size_in / 2 * * @return output size */ ya_result base16_decode(const char *buffer_in, u32 size_in, u8 *buffer_out) { if((size_in & 1) != 0) { return PARSEB16_ERROR; // wrong number of bytes } u8* in = (u8*)buffer_in; u8* out = buffer_out; while(size_in > 0) { u8 h = __DEBASE16__[*in++]; u8 l = __DEBASE16__[*in++]; if(((h | l) & 0x80) != 0) { return PARSEB16_ERROR; } *out++ = (h << 4) | l; size_in -= 2; } return (out - buffer_out); } u8 base16_decode_nibble(char nibble) { return __DEBASE16__[(ssize_t)nibble]; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/base32.c0000644000000000000000000000013114505005532020552 xustar000000000000000030 mtime=1695812442.486982818 29 atime=1695812445.79603021 30 ctime=1695812494.466727273 yadifa-2.6.5-11201/lib/dnscore/src/base32.c0000664000374500037450000002636714505005532020533 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup base Base conversion functions * @ingroup dnscore * @brief Base 32 codec * * Base 32 codec functions * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include "dnscore/base32.h" /* * */ #define BASE32_PADDING '=' static const char __BASE32__[256] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', }; /** * Encodes bytes into base32 * The output size must be at least size_in * 8/5 * * @param buffer_in bytes to convert * @param size_in number of bytes * @param buffer_out output buffer of a size >= size_in * 8/5 * * @return output size */ u32 base32_encode(const u8* buffer_in, u32 size_in, char* buffer_out) { char* ptr = buffer_out; while(size_in >= 5) { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; u8 b3 = *buffer_in++; u8 b4 = *buffer_in++; *ptr++ = __BASE32__[ b0 >> 3 ]; *ptr++ = __BASE32__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32__[ b1 >> 1 ]; *ptr++ = __BASE32__[(u8)((b1 << 4) | (b2 >> 4))]; *ptr++ = __BASE32__[(u8)((b2 << 1) | (b3 >> 7))]; *ptr++ = __BASE32__[ b3 >> 2 ]; *ptr++ = __BASE32__[(u8)((b3 << 3) | (b4 >> 5))]; *ptr++ = __BASE32__[ b4 ]; size_in -= 5; } switch(size_in) { case 4: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; u8 b3 = *buffer_in++; *ptr++ = __BASE32__[ b0 >> 3 ]; *ptr++ = __BASE32__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32__[ b1 >> 1 ]; *ptr++ = __BASE32__[(u8)((b1 << 4) | (b2 >> 4))]; *ptr++ = __BASE32__[(u8)((b2 << 1) | (b3 >> 7))]; *ptr++ = __BASE32__[ b3 >> 2 ]; *ptr++ = __BASE32__[(u8)(b3 << 3)]; *ptr++ = BASE32_PADDING; break; } case 3: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; *ptr++ = __BASE32__[ b0 >> 3 ]; *ptr++ = __BASE32__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32__[ b1 >> 1 ]; *ptr++ = __BASE32__[(u8)((b1 << 4) | (b2 >> 4))]; *ptr++ = __BASE32__[(u8)(b2 << 1)]; *ptr++ = BASE32_PADDING; *ptr++ = BASE32_PADDING; *ptr++ = BASE32_PADDING; break; } case 2: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; *ptr++ = __BASE32__[ b0 >> 3 ]; *ptr++ = __BASE32__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32__[ b1 >> 1 ]; *ptr++ = __BASE32__[(u8)(b1 << 4)]; *ptr++ = BASE32_PADDING; *ptr++ = BASE32_PADDING; *ptr++ = BASE32_PADDING; *ptr++ = BASE32_PADDING; break; } case 1: { u8 b0 = *buffer_in++; *ptr++ = __BASE32__[ b0 >> 3 ]; *ptr++ = __BASE32__[(u8)(b0 << 2) ]; *ptr++ = BASE32_PADDING; *ptr++ = BASE32_PADDING; *ptr++ = BASE32_PADDING; *ptr++ = BASE32_PADDING; *ptr++ = BASE32_PADDING; *ptr++ = BASE32_PADDING; break; } } return (u32)(ptr - buffer_out); } #define __DEBASE32__STOP__ 0x80 static const u8 __DEBASE32__[256] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0 - 7 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8 - 15 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 - 23 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24 - 31 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 - 39 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 40 - 47 ...+.../ */ 0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 01234567 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, /* 89...=.. */ 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* .ABCDEFG */ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /* HIJKLMNO */ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* PQRSTUVW */ 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ..... */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* .abcdefg */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* hijklmno */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* pqrstuvw */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* xyz..... */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /** * Decodes base32 into bytes * The output size must be at least size_in * 5/8 * * @param buffer_in base32 text * @param size_in number of chars * @param buffer_out output buffer of a size >= size_in * 5/8 * * @return output size */ ya_result base32_decode(const char* buffer_in, u32 size_in, u8* buffer_out) { if((size_in & 7) != 0) { return PARSEB32_ERROR; // wrong number of bytes } u8* in = (u8*)buffer_in; u8* out = buffer_out; while(size_in > 8) { u8 a = __DEBASE32__[*in++]; u8 b = __DEBASE32__[*in++]; u8 c = __DEBASE32__[*in++]; u8 d = __DEBASE32__[*in++]; u8 e = __DEBASE32__[*in++]; u8 f = __DEBASE32__[*in++]; u8 g = __DEBASE32__[*in++]; u8 h = __DEBASE32__[*in++]; if(((a | b | c | d | e | f | g | h)&0x40) != 0x00) { /* PARSE ERROR */ return PARSEB32_ERROR; } *out++ = (a << 3) | (b >> 2); *out++ = (b << 6) | (c << 1) | (d >> 4); *out++ = (d << 4) | (e >> 1); *out++ = (e << 7) | (f << 2) | (g >> 3); *out++ = (g << 5) | h; size_in -= 8; } if(size_in != 0) /* It's either 0 or 4 */ { u8 a = __DEBASE32__[*in++]; u8 b = __DEBASE32__[*in++]; if(((a | b)&0xc0) != 0x00) { /* PARSE ERROR */ return PARSEB32_ERROR; } *out++ = (a << 3) | (b >> 2); u8 c = __DEBASE32__[*in++]; u8 d = __DEBASE32__[*in++]; if((c != __DEBASE32__STOP__) && (d != __DEBASE32__STOP__)) { if(((c | d)&0x40) != 0) { return PARSEB32_ERROR; } *out++ = (b << 6) | (c << 1) | (d >> 4); u8 e = __DEBASE32__[*in++]; if(e != __DEBASE32__STOP__) { if((e & 0x40) != 0) { return PARSEB32_ERROR; } *out++ = (d << 4) | (e >> 1); u8 f = __DEBASE32__[*in++]; u8 g = __DEBASE32__[*in++]; if((f != __DEBASE32__STOP__) && (g != __DEBASE32__STOP__)) { if(((f | g)&0x40) != 0) { return PARSEB32_ERROR; } *out++ = (e << 7) | (f << 2) | (g >> 3); u8 h = __DEBASE32__[*in++]; if(h != __DEBASE32__STOP__) { if((h & 0x40) != 0) { return PARSEB32_ERROR; } *out++ = (g << 5) | h; } } } } } return out - buffer_out; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/base32hex.c0000644000000000000000000000013214505005532021260 xustar000000000000000030 mtime=1695812442.506983105 30 atime=1695812445.797030225 30 ctime=1695812494.468727301 yadifa-2.6.5-11201/lib/dnscore/src/base32hex.c0000664000374500037450000004203014505005532021221 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup base Base conversion functions * @ingroup dnscore * @brief Base 32 hex codec * * Base 32-hex codec functions * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include "dnscore/base32hex.h" /* * */ #define BASE32_HEX_PADDING '=' static const char __BASE32_HEX__[256] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', }; static const char __BASE32_HEX_LC__[256] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', }; /** * Encodes bytes into base32hex * The output size must be at least size_in * 8/5 * * @param buffer_in bytes to convert * @param size_in number of bytes * @param buffer_out output buffer of a size >= size_in * 8/5 * * @return output size */ u32 base32hex_encode(const u8* buffer_in, u32 size_in, char* buffer_out) { char* ptr = buffer_out; while(size_in >= 5) { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; u8 b3 = *buffer_in++; u8 b4 = *buffer_in++; *ptr++ = __BASE32_HEX__[ b0 >> 3 ]; *ptr++ = __BASE32_HEX__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32_HEX__[ b1 >> 1 ]; *ptr++ = __BASE32_HEX__[(u8)((b1 << 4) | (b2 >> 4))]; *ptr++ = __BASE32_HEX__[(u8)((b2 << 1) | (b3 >> 7))]; *ptr++ = __BASE32_HEX__[ b3 >> 2 ]; *ptr++ = __BASE32_HEX__[(u8)((b3 << 3) | (b4 >> 5))]; *ptr++ = __BASE32_HEX__[ b4 ]; size_in -= 5; } switch(size_in) { case 4: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; u8 b3 = *buffer_in++; *ptr++ = __BASE32_HEX__[ b0 >> 3 ]; *ptr++ = __BASE32_HEX__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32_HEX__[ b1 >> 1 ]; *ptr++ = __BASE32_HEX__[(u8)((b1 << 4) | (b2 >> 4))]; *ptr++ = __BASE32_HEX__[(u8)((b2 << 1) | (b3 >> 7))]; *ptr++ = __BASE32_HEX__[ b3 >> 2 ]; *ptr++ = __BASE32_HEX__[(u8)(b3 << 3)]; *ptr++ = BASE32_HEX_PADDING; break; } case 3: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; *ptr++ = __BASE32_HEX__[ b0 >> 3 ]; *ptr++ = __BASE32_HEX__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32_HEX__[ b1 >> 1 ]; *ptr++ = __BASE32_HEX__[(u8)((b1 << 4) | (b2 >> 4))]; *ptr++ = __BASE32_HEX__[(u8)(b2 << 1)]; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; break; } case 2: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; *ptr++ = __BASE32_HEX__[ b0 >> 3 ]; *ptr++ = __BASE32_HEX__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32_HEX__[ b1 >> 1 ]; *ptr++ = __BASE32_HEX__[(u8)(b1 << 4)]; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; break; } case 1: { u8 b0 = *buffer_in++; *ptr++ = __BASE32_HEX__[ b0 >> 3 ]; *ptr++ = __BASE32_HEX__[(u8)(b0 << 2) ]; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; break; } } return (u32)(ptr - buffer_out); } u32 base32hex_lc_encode(const u8* buffer_in, u32 size_in, char* buffer_out) { char* ptr = buffer_out; while(size_in >= 5) { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; u8 b3 = *buffer_in++; u8 b4 = *buffer_in++; *ptr++ = __BASE32_HEX_LC__[ b0 >> 3 ]; *ptr++ = __BASE32_HEX_LC__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32_HEX_LC__[ b1 >> 1 ]; *ptr++ = __BASE32_HEX_LC__[(u8)((b1 << 4) | (b2 >> 4))]; *ptr++ = __BASE32_HEX_LC__[(u8)((b2 << 1) | (b3 >> 7))]; *ptr++ = __BASE32_HEX_LC__[ b3 >> 2 ]; *ptr++ = __BASE32_HEX_LC__[(u8)((b3 << 3) | (b4 >> 5))]; *ptr++ = __BASE32_HEX_LC__[ b4 ]; size_in -= 5; } switch(size_in) { case 4: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; u8 b3 = *buffer_in++; *ptr++ = __BASE32_HEX_LC__[ b0 >> 3 ]; *ptr++ = __BASE32_HEX_LC__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32_HEX_LC__[ b1 >> 1 ]; *ptr++ = __BASE32_HEX_LC__[(u8)((b1 << 4) | (b2 >> 4))]; *ptr++ = __BASE32_HEX_LC__[(u8)((b2 << 1) | (b3 >> 7))]; *ptr++ = __BASE32_HEX_LC__[ b3 >> 2 ]; *ptr++ = __BASE32_HEX_LC__[(u8)(b3 << 3)]; *ptr++ = BASE32_HEX_PADDING; break; } case 3: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; *ptr++ = __BASE32_HEX_LC__[ b0 >> 3 ]; *ptr++ = __BASE32_HEX_LC__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32_HEX_LC__[ b1 >> 1 ]; *ptr++ = __BASE32_HEX_LC__[(u8)((b1 << 4) | (b2 >> 4))]; *ptr++ = __BASE32_HEX_LC__[(u8)(b2 << 1)]; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; break; } case 2: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; *ptr++ = __BASE32_HEX_LC__[ b0 >> 3 ]; *ptr++ = __BASE32_HEX_LC__[(u8)((b0 << 2) | (b1 >> 6))]; *ptr++ = __BASE32_HEX_LC__[ b1 >> 1 ]; *ptr++ = __BASE32_HEX_LC__[(u8)(b1 << 4)]; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; break; } case 1: { u8 b0 = *buffer_in++; *ptr++ = __BASE32_HEX_LC__[ b0 >> 3 ]; *ptr++ = __BASE32_HEX_LC__[(u8)(b0 << 2) ]; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; *ptr++ = BASE32_HEX_PADDING; break; } } return (u32)(ptr - buffer_out); } #define __DEBASE32_HEX__STOP__ 0x80 static const u8 __DEBASE32_HEX__[256] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0 - 7 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8 - 15 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 - 23 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24 - 31 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 - 39 */ 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, /* 40 - 47 ...+.../ */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ 0x08, 0x09, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, /* 89...=.. */ 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* .ABCDEFG */ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* HIJKLMNO */ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, /* PQRSTUVW */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ..... */ 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* .abcdefg */ /* Added to support NSD */ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* hijklmno */ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, /* pqrstuvw */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* xyz..... */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /** * Decodes base32hex into bytes * The output size must be at least size_in * 5/8 * * @param buffer_in base32hex text * @param size_in number of chars * @param buffer_out output buffer of a size >= size_in * 5/8 * * @return output size */ ya_result base32hex_decode(const char* buffer_in, u32 size_in, u8* buffer_out) { if((size_in & 7) != 0) { return PARSEB32H_ERROR; // wrong number of bytes } u8* in = (u8*)buffer_in; u8* out = buffer_out; while(size_in > 8) { u8 a = __DEBASE32_HEX__[*in++]; u8 b = __DEBASE32_HEX__[*in++]; u8 c = __DEBASE32_HEX__[*in++]; u8 d = __DEBASE32_HEX__[*in++]; u8 e = __DEBASE32_HEX__[*in++]; u8 f = __DEBASE32_HEX__[*in++]; u8 g = __DEBASE32_HEX__[*in++]; u8 h = __DEBASE32_HEX__[*in++]; if(((a | b | c | d | e | f | g | h)&0x40) != 0x00) { /* PARSE ERROR */ return PARSEB32H_ERROR; } *out++ = (a << 3) | (b >> 2); *out++ = (b << 6) | (c << 1) | (d >> 4); *out++ = (d << 4) | (e >> 1); *out++ = (e << 7) | (f << 2) | (g >> 3); *out++ = (g << 5) | h; size_in -= 8; } if(size_in != 0) /* It's either 0 or 4 */ { u8 a = __DEBASE32_HEX__[*in++]; u8 b = __DEBASE32_HEX__[*in++]; if(((a | b)&0xc0) != 0x00) { /* PARSE ERROR */ return PARSEB32H_ERROR; } *out++ = (a << 3) | (b >> 2); u8 c = __DEBASE32_HEX__[*in++]; u8 d = __DEBASE32_HEX__[*in++]; if((c != __DEBASE32_HEX__STOP__) && (d != __DEBASE32_HEX__STOP__)) { if(((c | d)&0x40) != 0) { return PARSEB32H_ERROR; } *out++ = (b << 6) | (c << 1) | (d >> 4); u8 e = __DEBASE32_HEX__[*in++]; if(e != __DEBASE32_HEX__STOP__) { if((e & 0x40) != 0) { return PARSEB32H_ERROR; } *out++ = (d << 4) | (e >> 1); u8 f = __DEBASE32_HEX__[*in++]; u8 g = __DEBASE32_HEX__[*in++]; if((f != __DEBASE32_HEX__STOP__) && (g != __DEBASE32_HEX__STOP__)) { if(((f | g)&0x40) != 0) { return PARSEB32H_ERROR; } *out++ = (e << 7) | (f << 2) | (g >> 3); u8 h = __DEBASE32_HEX__[*in++]; if(h != __DEBASE32_HEX__STOP__) { if((h & 0x40) != 0) { return PARSEB32H_ERROR; } *out++ = (g << 5) | h; } } } } } return out - buffer_out; } /** * encodes the buffer into base32hex to the output stream * * @param os output stream * @param buffer_in buffer to encode * @param size_in size of the buffer * * @return bytes written */ ya_result output_stream_write_base32hex(output_stream* os, const u8* buffer_in, u32 size_in) { ya_result total = ((size_in + (BASE32HEX_DECODED_CHUNK - 1)) / BASE32HEX_DECODED_CHUNK) * BASE32HEX_ENCODED_CHUNK; char tmp[8]; while(size_in >= BASE32HEX_DECODED_CHUNK) { /* this cannot fail */ base32hex_encode(buffer_in, BASE32HEX_DECODED_CHUNK, tmp); output_stream_write(os, (u8*)tmp, BASE32HEX_ENCODED_CHUNK); buffer_in += BASE32HEX_DECODED_CHUNK; size_in -= BASE32HEX_DECODED_CHUNK; } ya_result return_code; /* doing the general case in the if block results into faster code */ if(ISOK(return_code = output_stream_write(os, (u8*)tmp, base32hex_encode(buffer_in, size_in, tmp)))) { return total; } return return_code; } /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/base64.c0000644000000000000000000000013114505005532020557 xustar000000000000000030 mtime=1695812442.429982002 30 atime=1695812445.793030168 29 ctime=1695812494.47072733 yadifa-2.6.5-11201/lib/dnscore/src/base64.c0000664000374500037450000002370714505005532020533 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup base Base conversion functions * @ingroup dnscore * @brief Base 64 codec * * Base 64 codec functions * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/base64.h" /* * */ #define BASE64_PADDING '=' static const char __BASE64__[256] ={ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; /** * Encodes bytes into base64 * The output size must be at least size_in * 8/5 * * @param buffer_in bytes to convert * @param size_in number of bytes * @param buffer_out output buffer of a size >= size_in * 4/3 * * @return output size */ u32 base64_encode(const u8* buffer_in, u32 size_in, char* buffer_out) { char* ptr = buffer_out; while(size_in >= 3) { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; *ptr++ = __BASE64__[ b0 >> 2 ]; *ptr++ = __BASE64__[(u8)((b0 << 4) | (b1 >> 4))]; *ptr++ = __BASE64__[(u8)((b1 << 2) | (b2 >> 6))]; *ptr++ = __BASE64__[ b2 ]; size_in -= 3; } switch(size_in) { case 2: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in; *ptr++ = __BASE64__[ b0 >> 2 ]; *ptr++ = __BASE64__[(u8)((b0 << 4) | (b1 >> 4))]; *ptr++ = __BASE64__[(u8)(b1 << 2) ]; *ptr++ = BASE64_PADDING; break; } case 1: { u8 b0 = *buffer_in; *ptr++ = __BASE64__[ b0 >> 2 ]; *ptr++ = __BASE64__[ (u8)(b0 << 4) ]; *ptr++ = BASE64_PADDING; *ptr++ = BASE64_PADDING; break; } } return (u32)(ptr - buffer_out); } u32 base64_print(const u8* buffer_in, u32 size_in, output_stream *os) { uint32_t count = BASE64_ENCODED_SIZE(size_in); char buffer[4]; while(size_in >= 3) { u8 b0 = *buffer_in++; u8 b1 = *buffer_in++; u8 b2 = *buffer_in++; buffer[0] = __BASE64__[ b0 >> 2 ]; buffer[1] = __BASE64__[(u8)((b0 << 4) | (b1 >> 4))]; buffer[2] = __BASE64__[(u8)((b1 << 2) | (b2 >> 6))]; buffer[3] = __BASE64__[ b2 ]; output_stream_write(os, buffer, sizeof(buffer)); size_in -= 3; } switch(size_in) { case 2: { u8 b0 = *buffer_in++; u8 b1 = *buffer_in; buffer[0] = __BASE64__[ b0 >> 2 ]; buffer[1] = __BASE64__[(u8)((b0 << 4) | (b1 >> 4))]; buffer[2] = __BASE64__[(u8)(b1 << 2) ]; buffer[3] = BASE64_PADDING; output_stream_write(os, buffer, sizeof(buffer)); break; } case 1: { u8 b0 = *buffer_in; buffer[0] = __BASE64__[ b0 >> 2 ]; buffer[1] = __BASE64__[ (u8)(b0 << 4) ]; buffer[2] = BASE64_PADDING; buffer[3] = BASE64_PADDING; output_stream_write(os, buffer, sizeof(buffer)); break; } } return count; } #define __DEBASE64__STOP__ 0x80 static const u8 __DEBASE64__[256] ={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0 - 7 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8 - 15 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 - 23 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24 - 31 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 - 39 */ 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, /* 40 - 47 ...+.../ */ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, /* 01234567 */ 0x3c, 0x3d, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, /* 89...=.. */ 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* .ABCDEFG */ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /* HIJKLMNO */ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* PQRSTUVW */ 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ..... */ 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, /* .abcdefg */ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, /* hijklmno */ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, /* pqrstuvw */ 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, /* xyz..... */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; bool base64_character_set_contains(char c) { return __DEBASE64__[(u8)c] != (u8)0xff; } /** * Decodes base64 into bytes * The output size must be at least size_in * 3/4 * * @param buffer_in base64 text * @param size_in number of chars * @param buffer_out output buffer of a size >= size_in * 3/4 * * @return output size */ ya_result base64_decode(const char* buffer_in, u32 size_in, u8* buffer_out) { if((size_in & 3) != 0) { return PARSEB64_ERROR; // wrong number of bytes } u8* in = (u8*)buffer_in; u8* out = buffer_out; while(size_in > 4) { u8 a = __DEBASE64__[*in++]; u8 b = __DEBASE64__[*in++]; u8 c = __DEBASE64__[*in++]; u8 d = __DEBASE64__[*in++]; if(((a | b | c | d)&0x80) != 0x00) { /* PARSE ERROR */ return PARSEB64_ERROR; } *out++ = (a << 2) | (b >> 4); *out++ = (b << 4) | (c >> 2); *out++ = (c << 6) | d; size_in -= 4; } if(size_in != 0) /* It's either 0 or 4 */ { u8 a = __DEBASE64__[*in++]; u8 b = __DEBASE64__[*in++]; if(((a | b)&0xc0) != 0x00) { /* PARSE ERROR */ return PARSEB64_ERROR; } *out++ = (a << 2) | (b >> 4); u8 c = __DEBASE64__[*in++]; if(c != __DEBASE64__STOP__) { if((c & 0xc0) != 0) { return PARSEB64_ERROR; } *out++ = (b << 4) | (c >> 2); u8 d = __DEBASE64__[*in++]; if(d != __DEBASE64__STOP__) { if((d & 0xc0) != 0) { return PARSEB64_ERROR; } *out++ = (c << 6) | d; } } } return out - buffer_out; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/basic-priority-queue.c0000644000000000000000000000013114505005532023555 xustar000000000000000030 mtime=1695812442.487982833 29 atime=1695812445.79603021 30 ctime=1695812494.472727359 yadifa-2.6.5-11201/lib/dnscore/src/basic-priority-queue.c0000664000374500037450000001145614505005532023527 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A node-based single linked list where insertions are always sorted * * A node-based single linked list where insertions are always sorted by priority. * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include "dnscore/basic-priority-queue.h" #define LISTDATA_TAG 0x415441445453494c /*------------------------------------------------------------------------------ * FUNCTIONS */ /** * Initialises a list. * * @param list */ void bpqueue_init(bpqueue_s *list) { list->first = NULL; list->last = NULL; list->size = 0; } /** * Adds an item at the head of the list. * * @param list * @param data */ void bpqueue_enqueue(bpqueue_s *list, void *data, u32 priority) { bpqueue_node_s *node; MALLOC_OBJECT_OR_DIE(node, bpqueue_node_s, BPQNODE_TAG); node->data = data; node->priority = priority; if(list->size > 0) { if(list->last->priority <= priority) { // append node->next = NULL; list->last->next = node; list->last = node; } else if(list->first->priority > priority) { node->next = list->first; list->first = node; } else { // seek and insert // there are at least two items in the list // the item WILL be added before the last one bpqueue_node_s *prev = list->first; while(prev->next->priority <= priority) { prev = prev->next; } node->next = prev->next; prev->next = node; } list->size++; } else { node->next = NULL; list->first = node; list->last = node; list->size = 1; } } /** * Remove the first item from the list. * Deletes the node but not the data. * The data is returned. * * @param list * @return the data or NULL if the list is empty */ void* bpqueue_dequeue(bpqueue_s *list) { if(list->size > 0) { bpqueue_node_s *node = list->first; void *data = node->data; list->first = node->next; list->size--; if(list->size == 0) { list->last = NULL; } free(node); return data; } else { return NULL; } } /** * Remove all items from the list. * Deletes the nodes but not the data. * * @param list */ void bpqueue_clear(bpqueue_s *list) { bpqueue_node_s *node = list->first; while(node->next != NULL) { bpqueue_node_s *tmp = node; node = node->next; free(tmp); } list->first = NULL; list->last = NULL; list->size = 0; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/buffer_input_stream.c0000644000000000000000000000013214505005532023537 xustar000000000000000030 mtime=1695812442.480982732 30 atime=1695812445.795030196 30 ctime=1695812494.474727387 yadifa-2.6.5-11201/lib/dnscore/src/buffer_input_stream.c0000664000374500037450000002245514505005532023511 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/buffer_input_stream.h" #define BUFFER_INPUT_STREAM_TAG 0x53495246465542 /* BUFFERIS */ typedef struct buffer_input_stream_data buffer_input_stream_data; struct buffer_input_stream_data { input_stream filtered; u32 buffer_maxsize; // physical size of the buffer u32 buffer_size; // amount of the buffer that's filled u32 buffer_offset; // position in the buffer u8 buffer[1]; }; static ya_result buffer_input_stream_read(input_stream *stream, void* buffer_, u32 len) { buffer_input_stream_data* data = (buffer_input_stream_data*)stream->data; u8* buffer = (u8*)buffer_; u8* src = data->buffer; ya_result ret; u32 remaining = data->buffer_size - data->buffer_offset; if(len <= remaining) { MEMCOPY(buffer, &src[data->buffer_offset], len); data->buffer_offset += len; /* There are still some bytes available */ return len; } /* len >= remaining : copy what remains in the buffer */ MEMCOPY(buffer, &src[data->buffer_offset], remaining); len -= remaining; buffer += remaining; /* NOTE: at this point the internal buffer is empty */ if(len >= data->buffer_maxsize) { /* It would be pointless to buffer a read bigger than the buffer */ data->buffer_offset = data->buffer_size; /* mark the buffer as "empty" */ if(ISOK(ret = input_stream_read(&data->filtered, buffer, len))) { return remaining + ret; /* the chunk we've read from the buffer + the chunk we've read from the stream */ } else // 'remaining' bytes may have been copied already, if so, return that before the error { return (remaining > 0) ? (s32)remaining : ret; } } #if DEBUG memset(data->buffer, 0xbe, data->buffer_maxsize); #endif // What remains to read is smaller than the buffer max size: // read a full buffer if((ret = input_stream_read(&data->filtered, data->buffer, data->buffer_maxsize)) <= 0) { data->buffer_size = 0; data->buffer_offset = 0; // 'remaining' bytes may have been copied already, if so, return that before the error return (remaining > 0) ? (s32)remaining : ERROR /* eof */; } if(len > (u32)ret) // ret > 0 { len = (u32)ret; } MEMCOPY(buffer, data->buffer, len); /* starts at offset 0 */ data->buffer_size = (u32)ret; data->buffer_offset = len; return remaining + len; } static void buffer_input_stream_close(input_stream* stream) { buffer_input_stream_data* data = (buffer_input_stream_data*)stream->data; input_stream_close(&data->filtered); free(data); input_stream_set_void(stream); } static ya_result buffer_input_stream_skip(input_stream* stream, u32 len) { ya_result ret; buffer_input_stream_data* data = (buffer_input_stream_data*)stream->data; u32 remaining = data->buffer_size - data->buffer_offset; if(len <= remaining) { data->buffer_offset += len; return len; } len -= remaining; data->buffer_offset = data->buffer_size; if(FAIL(ret = input_stream_skip(&data->filtered, len))) { // 'remaining' bytes may have been skipped already, if so, return that before the error return (remaining > 0)?(s32)remaining:ret; } return remaining + ret; } static const input_stream_vtbl buffer_input_stream_vtbl = { buffer_input_stream_read, buffer_input_stream_skip, buffer_input_stream_close, "buffer_input_stream" }; void buffer_input_stream_init(input_stream* stream, input_stream* filtered, int buffer_size) { buffer_input_stream_data* data; if(buffer_size == 0) { buffer_size = BUFFER_INPUT_STREAM_DEFAULT_BUFFER_SIZE; } yassert(filtered->vtbl != NULL); MALLOC_OR_DIE(buffer_input_stream_data*, data, sizeof(buffer_input_stream_data) + buffer_size - 1, BUFFER_INPUT_STREAM_TAG); data->filtered.data = filtered->data; data->filtered.vtbl = filtered->vtbl; filtered->data = NULL; filtered->vtbl = NULL; data->buffer_maxsize = (u32)buffer_size; data->buffer_size = 0; data->buffer_offset = 0; stream->data = data; stream->vtbl = &buffer_input_stream_vtbl; } ya_result buffer_input_stream_read_line(input_stream* stream, char* buffer, u32 len) { assert(stream->vtbl == &buffer_input_stream_vtbl); buffer_input_stream_data* data = (buffer_input_stream_data*)stream->data; assert(data->buffer_offset <= data->buffer_size); char *src = (char*)data->buffer; if(len == 0) { return BUFFER_WOULD_OVERFLOW; } len--; u32 total = 0; /* * look for '\n' in the remaining bytes */ char *b = &src[data->buffer_offset]; s32 n = data->buffer_size - data->buffer_offset; if(n == 0) { if((n = input_stream_read(&data->filtered, (u8*)src, data->buffer_maxsize)) <= 0) { data->buffer_offset = 0; data->buffer_size = 0; return n /* eof */; } data->buffer_offset = 0; data->buffer_size = (u32)n; b = src; } for(;;) { n = MIN((s32)len, n); #if 0 /* fix */ #else // char *eol = (char*)memchr(b, '\n', (size_t)n); if(eol != NULL) { ++eol; u32 len_to_the_end = eol - b; data->buffer_offset = eol - src; memcpy(buffer, b, len_to_the_end); buffer[len_to_the_end] = '\0'; return total + len_to_the_end; } memcpy(buffer, b, (size_t)n); buffer += n; #endif // total += n; len -= (s32)n; if(len == 0) { data->buffer_offset += len; *buffer = '\0'; return total; } /* What remains to read is smaller than the buffer max size */ data->buffer_offset = 0; if((n = input_stream_read(&data->filtered, (u8*)src, data->buffer_maxsize)) <= 0) { data->buffer_size = 0; *buffer = '\0'; return (total > 0) ? (s32)total : ERROR /* eof */; } data->buffer_size = (u32)n; b = src; } } input_stream* buffer_input_stream_get_filtered(input_stream *bos) { buffer_input_stream_data* data = (buffer_input_stream_data*)bos->data; return &data->filtered; } /** * Rewinds the input stream back of a given number of bytes * * @param bos * @param bytes_back * * @return bytes_back : the operation was successful * > 0 : the maximum number of bytes available for rewind at the time of the call */ ya_result buffer_input_stream_rewind(input_stream *bos, u32 bytes_back) { buffer_input_stream_data* data = (buffer_input_stream_data*)bos->data; if(bytes_back < data->buffer_offset) { data->buffer_offset -= bytes_back; return bytes_back; } else { return data->buffer_offset; } } /** * Returns true iff the input stream is a buffer input stream * * @param bos * @return */ bool is_buffer_input_stream(input_stream *bos) { return bos->vtbl == &buffer_input_stream_vtbl; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/buffer_output_stream.c0000644000000000000000000000013214505005532023740 xustar000000000000000030 mtime=1695812442.392981472 30 atime=1695812445.792030153 30 ctime=1695812494.476727416 yadifa-2.6.5-11201/lib/dnscore/src/buffer_output_stream.c0000664000374500037450000002007314505005532023704 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/buffer_output_stream.h" #define BUFFER_OUTPUT_STREAM_TAG 0x534F5246465542 /* BUFFROS */ typedef struct buffer_output_stream_data buffer_output_stream_data; struct buffer_output_stream_data { output_stream filtered; u32 buffer_maxsize; u32 buffer_offset; u8 buffer[1]; }; static inline ya_result buffer_output_stream_data_write_buffer(buffer_output_stream_data* data) { ya_result ret; u8 *base = data->buffer; u8 *buffer = base; u32 len = data->buffer_offset; for(;;) { ret = output_stream_write_fully(&data->filtered, buffer, len); if(ISOK(ret)) { if((u32)ret == len) { return data->buffer_offset; } len -= ret; buffer += ret; } else { s32 d = buffer - base; if(d > 0) { memmove(base, buffer, len); data->buffer_offset = len; return d; } else { return ret; } } } } static ya_result buffer_output_stream_write(output_stream* stream, const u8* buffer, u32 len) { buffer_output_stream_data* data = (buffer_output_stream_data*)stream->data; u8* src = data->buffer; ya_result ret; if(data->buffer_offset == 0) // empty buffer { if(len < data->buffer_maxsize) // few bytes { MEMCOPY(src, buffer, len); // accumulate data->buffer_offset = len; return len; } else // write { ret = output_stream_write(&data->filtered, buffer, len); return ret; } } else // buffer not empty { u32 remaining = data->buffer_maxsize - data->buffer_offset; if(len < data->buffer_maxsize) // will not immediately require two writes { if(len < remaining) { MEMCOPY(&src[data->buffer_offset], buffer, len); data->buffer_offset += len; return len; } else // len >= remaining { // fill the remaining of the buffer MEMCOPY(&src[data->buffer_offset], buffer, remaining); data->buffer_offset += remaining; // write the content if(ISOK(ret = buffer_output_stream_data_write_buffer(data))) { len -= remaining; buffer += remaining; // still have len to write if(len < data->buffer_maxsize) { MEMCOPY(src, buffer, len); data->buffer_offset = len; return remaining + len; } else { data->buffer_offset = 0; if(ISOK(ret = output_stream_write(&data->filtered, buffer, len))) { return remaining + ret; } else { return (remaining > 0) ? (s32)remaining : ret; } } } else { return (remaining > 0)? (s32)remaining : ret; } } } else // the write will not go through the buffer: write the buffer then write the data { if(ISOK(ret = buffer_output_stream_data_write_buffer(data))) { data->buffer_offset = 0; ret = output_stream_write(&data->filtered, buffer, len); } return ret; } } } static ya_result buffer_output_stream_flush(output_stream* stream) { buffer_output_stream_data* data = (buffer_output_stream_data*)stream->data; if(data->buffer_offset > 0) { ya_result ret; if(ISOK(ret = buffer_output_stream_data_write_buffer(data))) { data->buffer_offset = 0; return output_stream_flush(&data->filtered); } else { return ret; } } else { return output_stream_flush(&data->filtered); } } static void buffer_output_stream_close(output_stream* stream) { buffer_output_stream_flush(stream); buffer_output_stream_data* data = (buffer_output_stream_data*)stream->data; output_stream_close(&data->filtered); free(data); output_stream_set_void(stream); } static const output_stream_vtbl buffer_output_stream_vtbl ={ buffer_output_stream_write, buffer_output_stream_flush, buffer_output_stream_close, "buffer_output_stream", }; ya_result buffer_output_stream_init(output_stream* stream, output_stream* filtered, int buffer_size) { buffer_output_stream_data* data; if(filtered->vtbl == NULL) { return OBJECT_NOT_INITIALIZED; } if(buffer_size <= 0) { buffer_size = 512; } MALLOC_OR_DIE(buffer_output_stream_data*, data, sizeof(buffer_output_stream_data) + buffer_size - 1, BUFFER_OUTPUT_STREAM_TAG); data->filtered.data = filtered->data; data->filtered.vtbl = filtered->vtbl; data->buffer_maxsize = buffer_size; data->buffer_offset = 0; output_stream_set_void(filtered); stream->data = data; stream->vtbl = &buffer_output_stream_vtbl; return SUCCESS; } output_stream* buffer_output_stream_get_filtered(output_stream* bos) { buffer_output_stream_data* data = (buffer_output_stream_data*)bos->data; yassert(bos->vtbl == &buffer_output_stream_vtbl); return &data->filtered; } bool is_buffer_output_stream(output_stream* os) { return (os != NULL) && (os->vtbl == &buffer_output_stream_vtbl); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/buffered-file.c0000644000000000000000000000013214505005532022173 xustar000000000000000030 mtime=1695812442.365981085 30 atime=1695812445.791030139 30 ctime=1695812494.478727445 yadifa-2.6.5-11201/lib/dnscore/src/buffered-file.c0000664000374500037450000011416014505005532022140 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #define __BUFFERED_FILE_C__ 1 #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #include "dnscore/ptr_set.h" #include "dnscore/mutex.h" #include "dnscore/list-dl.h" #include "dnscore/fdtools.h" #include "dnscore/logger.h" #include "dnscore/file.h" #include "dnscore/u64_set.h" #include "dnscore/timems.h" #define BUFFERED_STATISTICS_ON_STDOUT 0 #define IGNORE_COST 0 #if BUFFERED_STATISTICS_ON_STDOUT #include "dnscore/format.h" #endif #define MODULE_MSG_HANDLE g_system_logger #define BUFFERED_FILE_TAG 0x454c4946524642 // BFRFILE_TAG #define BUFFERED_FILE_PAGE_TAG 0x50454c4946524642 // BFRFILEP_TAG #define BUFFERED_FILE_CACHE_TAG 0x43454c4946524642 // BFRFILEC_TAG #define PAGE_USE_OLD_ENOUGH_VALUE_US 500000LL // 0.5s struct buffered_file_t_; typedef struct buffered_file_t_* buffered_file_t; struct buffered_file_page { struct list_dl_node_s *next; struct list_dl_node_s *prev; buffered_file_t file; u8 *buffer; s64 position; // position of the page in the file (multiple of page granularity) s64 timestamp; // last use (so it does fnot exit the MRU too fast except to be given to the same id) s64 cost; // the time in us that was required to build that page (IOs) s32 size; s32 written_from; // if written_from <= written_to then the page needs to be written s32 written_to_plus_one; s32 read_to; // number of bytes in that page (usually = size unless it's the last one of the file) int index; // for sorting bool in_mru; }; typedef struct buffered_file_page buffered_file_page; typedef struct buffered_file_page* buffered_file_page_t; struct buffered_file_page_set { group_mutex_t mtx; u64_set offset_to_page; }; typedef struct buffered_file_page_set buffered_file_page_set; struct buffered_file_cache_t_ { group_mutex_t mtx; ptr_set id_to_page_set; void *page_pool; size_t page_pool_size; s64 granularity_mask; list_dl_s mru; list_dl_s avail; const char * name; s32 rc; u8 log2_page_size; bool source_is_mmap; #if BUFFERED_STATISTICS_ON_STDOUT u32 cache_acquired; u32 cache_released; u32 cache_reclaimed; u32 cache_denied; u32 cache_denied_nolock; u32 cache_denied_cost; u32 cache_denied_writefail; #endif }; typedef struct buffered_file_cache_t_* buffered_file_cache_t; struct buffered_file_t_ { const struct file_vtbl *vtbl; file_t buffered_file; // the file covered by the cache buffered_file_cache_t page_cache; // the cache used for this file buffered_file_page_set page_set; // the set of pages covering the file (offset -> page) s64 position_current; // the position where the file pointer really is s64 position_requested; // the position where the file pointer is supposed to be s64 size; // the size of the file }; #include // just to match the function signatures static void buffered_file_cache_page_init(buffered_file_page_t page, buffered_file_t f, u8 *buffer, s32 size, int index) { assert((buffer != NULL) && (size > 0)); page->file = f; page->buffer = buffer; page->position = 0; page->timestamp = 0; page->cost = 0; page->written_from = size; page->written_to_plus_one = 0; page->read_to = 0; page->size = size; page->index = index; page->in_mru = FALSE; } static buffered_file_page_t buffered_file_cache_page_new_instance(u8 *buffer, s32 size, int index) { buffered_file_page_t page; ZALLOC_OBJECT_OR_DIE(page, struct buffered_file_page, BUFFERED_FILE_PAGE_TAG); buffered_file_cache_page_init(page, NULL, buffer, size, index); return page; } static void buffered_file_cache_page_update(buffered_file_page_t page, buffered_file_t f, s64 position) { page->file = f; page->position = position; page->timestamp = 0; page->cost = 0; page->written_from = page->size; page->written_to_plus_one = 0; page->read_to = 0; } buffered_file_cache_t buffered_file_cache_new_instance(const char* name, u32 count, u8 log2_granularity, bool use_mmap) { if((log2_granularity < 4) || (log2_granularity > 20)) // 16 bytes to 1 MB { return NULL; } size_t page_size = 1LLU << log2_granularity; size_t total_size = page_size * count; u8 *pages; if(use_mmap) { pages = (u8*)mmap(NULL, total_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if(pages == (u8*)MAP_FAILED) { return NULL; } } else { MALLOC_OBJECT_ARRAY(pages, u8, total_size, BUFFERED_FILE_CACHE_TAG); //pages = (u8*)malloc(total_size); if(pages == NULL) { return NULL; } } buffered_file_cache_t fc; ZALLOC_OBJECT_OR_DIE(fc, struct buffered_file_cache_t_, BUFFERED_FILE_CACHE_TAG); #if BUFFERED_STATISTICS_ON_STDOUT memset(fc, 0, sizeof(*fc)); #endif group_mutex_init(&fc->mtx); fc->page_pool = pages; fc->page_pool_size = total_size; fc->granularity_mask = page_size - 1; list_dl_init(&fc->mru); list_dl_init(&fc->avail); fc->name = strdup(name); fc->source_is_mmap = use_mmap; fc->log2_page_size = log2_granularity; fc->rc = 1; for(u32 i = 0; i < count; ++i) { list_dl_append_node(&fc->avail, (list_dl_node_s*)buffered_file_cache_page_new_instance(&pages[page_size * i], page_size, i)); } #if DEBUG log_info("buffered_file_cache_new_instance('%s', %u, %hhu, %i) = %p", STRNULL(name), count, log2_granularity, use_mmap, fc); #endif return fc; } static void buffered_file_cache_acquire(buffered_file_cache_t fc) { group_mutex_lock(&fc->mtx, GROUP_MUTEX_WRITE); ++fc->rc; #if DEBUG log_info("buffered_file_cache_acquire(%p '%s') = %i", fc, STRNULL(fc->name), fc->rc); #endif group_mutex_unlock(&fc->mtx, GROUP_MUTEX_WRITE); } static void buffered_file_cache_release(buffered_file_cache_t fc) { group_mutex_lock(&fc->mtx, GROUP_MUTEX_WRITE); s32 n = --fc->rc; group_mutex_unlock(&fc->mtx, GROUP_MUTEX_WRITE); #if DEBUG log_info("buffered_file_cache_release(%p '%s') = %i", fc, STRNULL(fc->name), n); #endif #if BUFFERED_STATISTICS_ON_STDOUT formatln("cache: acquired=%u released=%u reclaimed=%u denied=%u denied-nolock=%u denied-cost=%u denied-writefail=%u", fc->cache_acquired, fc->cache_released, fc->cache_reclaimed, fc->cache_denied, fc->cache_denied_nolock, fc->cache_denied_cost, fc->cache_denied_writefail); flushout(); #endif if(n == 0) { // the mru should be empty // the avail should be full if(fc->source_is_mmap) { munmap(fc->page_pool, fc->page_pool_size); } else { free(fc->page_pool); } } } void buffered_file_cache_delete(buffered_file_cache_t fc) { #if DEBUG group_mutex_lock(&fc->mtx, GROUP_MUTEX_READ); if(fc->rc > 1) { log_warn("buffered_file_cache_delete(%p '%s') rc=%i", fc, STRNULL(fc->name), fc->rc); } group_mutex_unlock(&fc->mtx, GROUP_MUTEX_READ); #endif buffered_file_cache_release(fc); } /** * Looks for a victim page among the ones available. * If there are none, tries to take the last page of the MRU from the file using it (flushing it if needed). * This last step can fail if the page is too young based on it's IO cost, or if the page set is locked. * * @param fc * * @return a page or NULL if none were available */ static buffered_file_page_t buffered_file_cache_reclaim_page_nolock(buffered_file_cache_t fc) { // if the least recently used has been used more than (e.g.) 0.5 seconds ago, try to reclaim it // if it cannot (locked) give up // it it can, flush it, take it from its current user and return it buffered_file_page_t page = (buffered_file_page_t)list_dl_last_node(&fc->mru); if(page == NULL) { return NULL; } if(group_mutex_trylock(&page->file->page_set.mtx, GROUP_MUTEX_WRITE)) { s64 now = timeus(); #if !IGNORE_COST if(now - page->timestamp > page->cost) #else if(TRUE) #endif { s32 page_content = page->written_to_plus_one - page->written_from; if(page_content > 0) { // flush page /* s64 stored_position = page->file->position_current; */ s64 write_position = page->position + page->written_from; write_position = page->file->buffered_file->vtbl->seek(page->file->buffered_file, write_position, SEEK_SET); if(ISOK(write_position)) { page->file->position_current = write_position; s32 ret = page->file->buffered_file->vtbl->write(page->file->buffered_file, &page->buffer[page->written_from], page_content); if(ISOK(ret) && (ret == page_content)) { page->file->position_current += ret; // page flushed u64_set_delete(&page->file->page_set.offset_to_page, page->position); if(page->in_mru) { list_dl_remove_node(&fc->mru, (list_dl_node_s*)page); page->in_mru = FALSE; } #if BUFFERED_STATISTICS_ON_STDOUT ++fc->cache_reclaimed; #endif /* s64 restored_position = page->file->buffered_file->vtbl->seek(page->file->buffered_file, stored_position, SEEK_SET); assert(restored_position == stored_position); */ group_mutex_unlock(&page->file->page_set.mtx, GROUP_MUTEX_WRITE); } else // could not properly write it { #if BUFFERED_STATISTICS_ON_STDOUT ++fc->cache_denied_writefail; #endif /* s64 restored_position = page->file->buffered_file->vtbl->seek(page->file->buffered_file, stored_position, SEEK_SET); assert(restored_position == stored_position); */ group_mutex_unlock(&page->file->page_set.mtx, GROUP_MUTEX_WRITE); page = NULL; } } else { group_mutex_unlock(&page->file->page_set.mtx, GROUP_MUTEX_WRITE); page = NULL; } } else { // page does not need to be flushed u64_set_delete(&page->file->page_set.offset_to_page, page->position); group_mutex_unlock(&page->file->page_set.mtx, GROUP_MUTEX_WRITE); } } else { #if BUFFERED_STATISTICS_ON_STDOUT ++fc->cache_denied_cost; #endif group_mutex_unlock(&page->file->page_set.mtx, GROUP_MUTEX_WRITE); page = NULL; } } #if BUFFERED_STATISTICS_ON_STDOUT else { ++fc->cache_denied_nolock; } #endif return page; } /** * * Returns one page set for a file at a given position * * @param fc * @param file * @param position * @return */ static buffered_file_page_t buffered_file_cache_acquire_page(buffered_file_cache_t fc, buffered_file_t file, s64 position) { buffered_file_page_t page; group_mutex_lock(&fc->mtx, GROUP_MUTEX_WRITE); if(list_dl_size(&fc->avail) == 0) { // find a victim if((page = buffered_file_cache_reclaim_page_nolock(fc)) != NULL) { buffered_file_cache_page_update(page, file, position); } } else { // take the first available one page = (buffered_file_page_t)list_dl_remove_first_node(&fc->avail); buffered_file_cache_page_update(page, file, position); } #if BUFFERED_STATISTICS_ON_STDOUT if(page != NULL) { ++fc->cache_acquired; } else { ++fc->cache_denied; } #endif group_mutex_unlock(&fc->mtx, GROUP_MUTEX_WRITE); return page; } void buffered_file_cache_release_page(buffered_file_cache_t fc, buffered_file_page_t page) { //u64_set_delete(page->file->page_set.offset_to_page, page->position); group_mutex_lock(&fc->mtx, GROUP_MUTEX_WRITE); #if BUFFERED_STATISTICS_ON_STDOUT ++fc->cache_released; #endif if(page->in_mru) { list_dl_remove_node(&fc->mru, (list_dl_node_s*)page); page->in_mru = FALSE; } page->file = NULL; list_dl_insert_node(&fc->avail, (list_dl_node_s*)page); group_mutex_unlock(&fc->mtx, GROUP_MUTEX_WRITE); } void buffered_file_cache_set_page_as_most_recently_used(buffered_file_cache_t fc, buffered_file_page_t page) { group_mutex_lock(&fc->mtx, GROUP_MUTEX_WRITE); if(page->in_mru) { list_dl_remove_node(&fc->mru, (list_dl_node_s*)page); } list_dl_insert_node(&fc->mru, (list_dl_node_s*)page); page->in_mru = TRUE; group_mutex_unlock(&fc->mtx, GROUP_MUTEX_WRITE); } struct io_range { s64 from; s64 to; buffered_file_page_t page; }; typedef struct io_range io_range; static ssize_t buffered_file_read(file_t f, void *buffer_, ssize_t size) { buffered_file_t bf = (buffered_file_t)f; if(bf->buffered_file == NULL) { return INVALID_STATE_ERROR; } // see if wanted position (which is where we will be reading from) page is in the cache // if not, move to position, acquire the page and update its content with the file // if page acquisition is not possible, do a direct read // from the page, copy the bytes to the buffer u8 *buffer = (u8*)buffer_; u8* buffer_org = buffer; buffered_file_page_t page = NULL; s64 page_position = bf->position_requested & ~bf->page_cache->granularity_mask; s64 in_page_from = bf->position_requested & bf->page_cache->granularity_mask; // we know the page_position and the position in the page group_mutex_lock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); for(;;) // until there are no more bytes to read { // see if the page is cached u64_node *node = u64_set_find(&bf->page_set.offset_to_page, page_position); if(node == NULL) { // the page is not cached group_mutex_unlock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); // acquire a page to use for caching page = buffered_file_cache_acquire_page(bf->page_cache, bf, page_position); if(page == NULL) { // case where the cache is over used so taking a page would be counter-productive by making the cache a glorified intermediary buffer if(bf->position_current != bf->position_requested) { // move into the file at the requested position ssize_t ret = bf->buffered_file->vtbl->seek(bf->buffered_file, bf->position_requested, SEEK_SET); if(FAIL(ret)) { ssize_t total = buffer - buffer_org; if(total > 0) { ret = total; } return ret; } bf->position_current = ret; } // read until the next cached page s64 to_read = size; s64 next_page_position = page_position; for(;;) { next_page_position += bf->page_cache->granularity_mask + 1; if(next_page_position >= bf->position_current + size) { break; } if(u64_set_find(&bf->page_set.offset_to_page, next_page_position) != NULL) { // a page exists at that position to_read = next_page_position - bf->position_current; break; } } ssize_t ret = bf->buffered_file->vtbl->read(bf->buffered_file, buffer, to_read); if(ISOK(ret)) { bf->position_current += ret; bf->position_requested = bf->position_current; buffer += ret; size -= ret; if((size == 0) && (ret == to_read)) { ssize_t total = buffer - buffer_org; return total; } page_position = next_page_position; in_page_from = 0; group_mutex_lock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); continue; } else { // handle the error so read bytes are not ignored ssize_t total = buffer - buffer_org; if(total > 0) { ret = total; } return ret; } } s64 cost_computation_begin = timeus(); s64 end_avail = bf->size - page_position; if(end_avail > 0) { if(bf->position_current != page_position) { // move into the file at the requested position ssize_t ret = bf->buffered_file->vtbl->seek(bf->buffered_file, page_position, SEEK_SET); if(FAIL(ret)) { buffered_file_cache_release_page(bf->page_cache, page); ssize_t total = buffer - buffer_org; if(total > 0) { ret = total; } return ret; } bf->position_current = ret; } // fill the page size_t expected_size = MIN(end_avail, page->size); ssize_t ret = bf->buffered_file->vtbl->read(bf->buffered_file, page->buffer, expected_size); if(FAIL(ret)) { buffered_file_cache_release_page(bf->page_cache, page); ssize_t total = buffer - buffer_org; if(total > 0) { ret = total; } return ret; } bf->position_current += ret; page->read_to = ret; } else { page->read_to = 0; } s64 cost_computation_end = timeus(); // update the cost page->cost = (cost_computation_end - cost_computation_begin) * 2; group_mutex_lock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); page->timestamp = MAX_S64; u64_node *page_node = u64_set_insert(&bf->page_set.offset_to_page, page->position); page_node->value = page; } else { page = (buffered_file_page_t)node->value; } // copy from the page ssize_t available_in_page = page->read_to - in_page_from; ssize_t n = MIN(available_in_page, size); memcpy(buffer, &page->buffer[in_page_from], n); bf->position_requested += n; page->timestamp = timeus(); size -= n; // move the page at the top of the MRU buffered_file_cache_set_page_as_most_recently_used(bf->page_cache, page); buffer += n; // if size == 0 the job is done // if page->read_to != page->size this is the end of the file if((size == 0) || (page->read_to != page->size)) { group_mutex_unlock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); break; } // at this point, bf->position_requested & bf->page_cache->granularity_mask should be 0 assert((bf->position_requested & bf->page_cache->granularity_mask) == 0); page_position += page->size; in_page_from = 0; page = NULL; } ssize_t total = buffer - buffer_org; return total; } static ssize_t buffered_file_write(file_t f, const void *buffer_, ssize_t size) { buffered_file_t bf = (buffered_file_t)f; if(bf->buffered_file == NULL) { return INVALID_STATE_ERROR; } // see if wanted position (which is where we will be reading from) page is in the cache // if not, move to position, acquire the page and update its content with the file (if the position is outside the file, just fill with zeroes) // if page acquisition is not possible, do a direct write // from the buffer, copy the bytes to the page and update the written range const u8 *buffer = (const u8*)buffer_; const u8* buffer_org = buffer; buffered_file_page_t page = NULL; s64 page_position = bf->position_requested & ~bf->page_cache->granularity_mask; s64 in_page_from = bf->position_requested & bf->page_cache->granularity_mask; // we know the page_position and the position in the page group_mutex_lock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); for(;;) // until there are no more bytes to read { // see if the page is cached u64_node *node = u64_set_find(&bf->page_set.offset_to_page, page_position); if(node == NULL) { // the page is not cached group_mutex_unlock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); // acquire a page to use for caching page = buffered_file_cache_acquire_page(bf->page_cache, bf, page_position); if(page == NULL) { // case where the cache is over used so taking a page would be counter-productive by making the cache a glorified intermediary buffer if(bf->position_current != bf->position_requested) { // move into the file at the requested position ssize_t ret = bf->buffered_file->vtbl->seek(bf->buffered_file, bf->position_requested, SEEK_SET); if(FAIL(ret)) { buffered_file_cache_release_page(bf->page_cache, page); if(bf->position_requested > bf->size) { bf->size = bf->position_requested; } ssize_t total = buffer - buffer_org; if(total > 0) { ret = total; } return ret; } bf->position_current = ret; } // write until the next cached page s64 to_write = size; s64 next_page_position = page_position; for(;;) { next_page_position += bf->page_cache->granularity_mask + 1; if(next_page_position >= bf->position_current + size) { break; } if(u64_set_find(&bf->page_set.offset_to_page, next_page_position) != NULL) { // a page exists at that position to_write = next_page_position - bf->position_current; break; } } ssize_t ret = bf->buffered_file->vtbl->write(bf->buffered_file, buffer, to_write); if(ISOK(ret)) { bf->position_current += ret; bf->position_requested = bf->position_current; buffer += ret; size -= ret; if(bf->position_requested > bf->size) { bf->size = bf->position_requested; } if((size == 0) && (ret == to_write)) { ssize_t total = buffer - buffer_org; return total; } page_position = next_page_position; in_page_from = 0; group_mutex_lock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); continue; } else { // handle the error so read bytes are not ignored if(bf->position_current > bf->size) { bf->size = bf->position_current; } ssize_t total = buffer - buffer_org; if(total > 0) { ret = total; } return ret; } } s64 cost_computation_begin = timeus(); s64 end_avail = bf->size - page_position; if(end_avail > 0) { if(bf->position_current != page_position) { // move into the file at the requested position ssize_t ret = bf->buffered_file->vtbl->seek(bf->buffered_file, page_position, SEEK_SET); if(FAIL(ret)) { if(bf->position_current > bf->size) { bf->size = bf->position_current; } buffered_file_cache_release_page(bf->page_cache, page); ssize_t total = buffer - buffer_org; if(total > 0) { ret = total; } return ret; } bf->position_current = ret; } // fill the page size_t expected_size = MIN(end_avail, page->size); ssize_t ret = bf->buffered_file->vtbl->read(bf->buffered_file, page->buffer, expected_size); if(FAIL(ret)) { if(bf->position_current > bf->size) { bf->size = bf->position_current; } buffered_file_cache_release_page(bf->page_cache, page); ssize_t total = buffer - buffer_org; if(total > 0) { ret = total; } return ret; } page->read_to = ret; } else { page->read_to = 0; } s64 cost_computation_end = timeus(); // update the cost page->cost = (cost_computation_end - cost_computation_begin) * 2; group_mutex_lock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); page->timestamp = MAX_S64; u64_node *page_node = u64_set_insert(&bf->page_set.offset_to_page, page->position); page_node->value = page; } else { page = (buffered_file_page_t)node->value; } // copy from the page ssize_t available_in_page = page->size - in_page_from; // it's size and not read_to ssize_t n = MIN(available_in_page, size); memcpy(&page->buffer[in_page_from], buffer, n); if(page->written_from > in_page_from) { page->written_from = in_page_from; } if(page->written_to_plus_one < in_page_from + n) { page->written_to_plus_one = in_page_from + n; } if(page->read_to < in_page_from + n) { page->read_to = in_page_from + n; } bf->position_requested += n; page->timestamp = timeus(); size -= n; // move the page at the top of the MRU buffered_file_cache_set_page_as_most_recently_used(bf->page_cache, page); buffer += n; // if size == 0 the job is done // if page->read_to != page->size this is the end of the file if((size == 0) || (page->read_to != page->size)) { if(bf->position_requested > bf->size) { bf->size = bf->position_requested; } group_mutex_unlock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); break; } // at this point, bf->position_requested & bf->page_cache->granularity_mask should be 0 assert((bf->position_requested & bf->page_cache->granularity_mask) == 0); page_position += page->size; in_page_from = 0; page = NULL; } ssize_t total = buffer - buffer_org; return total; } static ssize_t buffered_file_seek(file_t f, ssize_t position, int whence) { buffered_file_t bf = (buffered_file_t)f; if(bf->buffered_file == NULL) { return INVALID_STATE_ERROR; } switch(whence) { case SEEK_SET: { bf->position_requested = position; return position; } case SEEK_CUR: { if(bf->position_requested + position >= 0) { bf->position_requested += position; return bf->position_requested; } else { bf->position_requested = 0; return 0; } } case SEEK_END: { if(bf->size + position >= 0) { bf->position_requested = bf->size + position; return bf->position_requested; } else { bf->position_requested = 0; return 0; } } default: { return INVALID_ARGUMENT_ERROR; } } } static ssize_t buffered_file_tell(file_t f) { buffered_file_t bf = (buffered_file_t)f; if(bf->buffered_file == NULL) { return INVALID_STATE_ERROR; } return bf->position_requested; } static ya_result buffered_file_flush(file_t f) { buffered_file_t bf = (buffered_file_t)f; if(bf->buffered_file == NULL) { return INVALID_STATE_ERROR; } ssize_t ret = 0; bool moved = FALSE; group_mutex_lock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); u64_set_iterator iter; u64_set_iterator_init(&bf->page_set.offset_to_page, &iter); while(u64_set_iterator_hasnext(&iter)) { u64_node *node = u64_set_iterator_next_node(&iter); buffered_file_page* page = (buffered_file_page*)node->value; if(page->written_from <= page->written_to_plus_one) { // move at the position // write the bytes ssize_t target = page->position + page->written_from; ret = bf->buffered_file->vtbl->seek(bf->buffered_file, target, SEEK_SET); if(ret != target) { if(ret >= 0) // the returned value does not match the expected position { ret = INVALID_STATE_ERROR; } break; } size_t size = (size_t)page->written_to_plus_one - page->written_from; ret = bf->buffered_file->vtbl->write(bf->buffered_file, &page->buffer[page->written_from], size); if(ret != (ssize_t)size) { if(ret >= 0) // the number of bytes do not match the expected written amount { ret = INVALID_STATE_ERROR; } break; } page->written_from = size; page->written_to_plus_one = 0; moved = TRUE; } } group_mutex_unlock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); if(moved) { bf->position_current = bf->buffered_file->vtbl->seek(bf->buffered_file, bf->position_requested, SEEK_SET); } return ret; } static int buffered_file_close(file_t f) { buffered_file_t bf = (buffered_file_t)f; if(bf->buffered_file == NULL) { return INVALID_STATE_ERROR; } buffered_file_flush(f); group_mutex_lock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); u64_set_iterator iter; u64_set_iterator_init(&bf->page_set.offset_to_page, &iter); while(u64_set_iterator_hasnext(&iter)) { u64_node *node = u64_set_iterator_next_node(&iter); buffered_file_page* page = (buffered_file_page*)node->value; buffered_file_cache_release_page(bf->page_cache, page); } u64_set_destroy(&bf->page_set.offset_to_page); group_mutex_unlock(&bf->page_set.mtx, GROUP_MUTEX_WRITE); bf->buffered_file->vtbl->close(bf->buffered_file); buffered_file_cache_release(bf->page_cache); bf->page_cache = NULL; bf->vtbl = NULL; ZFREE_OBJECT(bf); return SUCCESS; } static ssize_t buffered_file_size(file_t f) { buffered_file_t bf = (buffered_file_t)f; if(bf->buffered_file == NULL) { return INVALID_STATE_ERROR; } return bf->size; } static int buffered_file_resize(file_t f, ssize_t size) { buffered_file_t bf = (buffered_file_t)f; if(bf->buffered_file == NULL) { return INVALID_STATE_ERROR; } if(size < 0) { return INVALID_ARGUMENT_ERROR; } int ret = file_resize(bf->buffered_file, size); if(ret >= 0) { bf->size = size; } return ret; } static const struct file_vtbl buffered_file_vtbl = { buffered_file_read, buffered_file_write, buffered_file_seek, buffered_file_tell, buffered_file_flush, buffered_file_close, buffered_file_size, buffered_file_resize }; ya_result buffered_file_init(file_t *fp, file_t file_to_buffer_, buffered_file_cache_t fc) { if(fp == NULL || file_to_buffer_ == NULL || fc == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } file_t file_to_buffer = file_to_buffer_; buffered_file_t bf; ZALLOC_OBJECT_OR_DIE(bf,struct buffered_file_t_, BUFFERED_FILE_TAG); bf->vtbl = &buffered_file_vtbl; bf->buffered_file = file_to_buffer; buffered_file_cache_acquire(fc); bf->page_cache = fc; group_mutex_init(&bf->page_set.mtx); bf->page_set.offset_to_page = NULL; bf->position_current = file_to_buffer->vtbl->tell(file_to_buffer); bf->position_requested = bf->position_current; bf->size = file_to_buffer->vtbl->size(file_to_buffer); *fp = (file_t)bf; return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/bytearray_input_stream.c0000644000000000000000000000013214505005532024270 xustar000000000000000030 mtime=1695812442.472982618 30 atime=1695812445.795030196 30 ctime=1695812494.480727473 yadifa-2.6.5-11201/lib/dnscore/src/bytearray_input_stream.c0000664000374500037450000001746614505005532024250 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/bytearray_input_stream.h" #include "dnscore/zalloc.h" #define BYTE_ARRAY_INPUT_STREAM_TAG 0x53494142 // BAIS #define BYTE_ARRAY_INPUT_STREAM_DATA_TAG 0x4154414453494142 // BAISDATA #define BYTE_ARRAY_INPUT_STREAM_BUFF_TAG 0x4646554253494142 // BAISBUFF typedef struct bytearray_input_stream_data bytearray_input_stream_data; /* flags */ struct bytearray_input_stream_data { const u8* buffer; u32 offset; u32 size; bool own_buffer; }; static ya_result bytearray_input_stream_read(input_stream* stream, void *buffer, u32 len) { if(len == 0) { return 0; } bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; u32 remaining = data->size - data->offset; if(len > remaining) { if(remaining == 0) { return 0; /* EOF */ } len = remaining; } const u8* src = &data->buffer[data->offset]; MEMCOPY(buffer, src, len); data->offset += len; return len; } static ya_result bytearray_input_stream_skip(input_stream* stream, u32 len) { if(len == 0) { return 0; } bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; u32 remaining = data->size - data->offset; if(len > remaining) { if(remaining == 0) { return 0; /* EOF */ } len = remaining; } data->offset += len; return len; } static void bytearray_input_stream_close(input_stream* stream) { bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; if(data->own_buffer) { free((void*)data->buffer); } ZFREE_OBJECT(data); input_stream_set_void(stream); } static const input_stream_vtbl bytearray_input_stream_vtbl = { bytearray_input_stream_read, bytearray_input_stream_skip, bytearray_input_stream_close, "bytearray_input_stream", }; void bytearray_input_stream_init_const(input_stream* out_stream, const void* array, u32 size) { bytearray_input_stream_data* data; ZALLOC_OBJECT_OR_DIE( data, bytearray_input_stream_data, BYTE_ARRAY_INPUT_STREAM_DATA_TAG); data->buffer = array; data->offset = 0; data->size = size; data->own_buffer = FALSE; out_stream->data = data; out_stream->vtbl = &bytearray_input_stream_vtbl; } void bytearray_input_stream_init(input_stream* out_stream, void* array, u32 size, bool owned) { bytearray_input_stream_data* data; ZALLOC_OBJECT_OR_DIE( data, bytearray_input_stream_data, BYTE_ARRAY_INPUT_STREAM_DATA_TAG); data->buffer = array; data->offset = 0; data->size = size; data->own_buffer = owned; out_stream->data = data; out_stream->vtbl = &bytearray_input_stream_vtbl; } void bytearray_input_stream_reset(input_stream* stream) { bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; data->offset = 0; } void bytearray_input_stream_update(input_stream* stream, void* array, u32 size, bool owned) { bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; if(data->own_buffer && (data->buffer != array)) { free((u8*)data->buffer); } data->buffer = array; data->size = size; data->own_buffer = owned; } u32 bytearray_input_stream_offset(const input_stream* stream) { bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; return data->offset; } u32 bytearray_input_stream_set_offset(input_stream* stream, u32 offset) { bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; if(data->size <= offset) { offset = data->size - 1; } data->offset = offset; return offset; } u32 bytearray_input_stream_size(const input_stream* stream) { bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; return data->size; } u32 bytearray_input_stream_remaining(const input_stream* stream) { bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; u32 remaining = data->size - data->offset; return remaining; } const u8* bytearray_input_stream_buffer(const input_stream* stream) { bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; return data->buffer; } u8* bytearray_input_stream_detach(input_stream* stream) { bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; data->own_buffer = FALSE; return (u8*)data->buffer; } bool bytearray_input_stream_is_instance_of(const input_stream* stream) { return (stream != NULL) && (stream->vtbl == &bytearray_input_stream_vtbl); } /** * Z-allocate a byte array input stream matching the one passed as a parameter. * Offset is matched. * Buffer is owned. */ input_stream *bytearray_input_stream_clone(const input_stream* stream) { if(bytearray_input_stream_is_instance_of(stream)) { bytearray_input_stream_data* data = (bytearray_input_stream_data*)stream->data; input_stream *is; ZALLOC_OBJECT_OR_DIE(is, input_stream, BYTE_ARRAY_INPUT_STREAM_TAG); bytearray_input_stream_data* is_data; ZALLOC_OBJECT_OR_DIE( is_data, bytearray_input_stream_data, BYTE_ARRAY_INPUT_STREAM_DATA_TAG); //is_data->buffer <= data->array; MALLOC_OBJECT_ARRAY_OR_DIE(is_data->buffer, u8, data->size, BYTE_ARRAY_INPUT_STREAM_BUFF_TAG) memcpy((char*)is_data->buffer, data->buffer, data->size); is_data->offset = data->offset; is_data->size = data->size; is_data->own_buffer = TRUE; is->data = is_data; is->vtbl = &bytearray_input_stream_vtbl; return is; } else { return NULL; } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/bytearray_output_stream.c0000644000000000000000000000013214505005532024471 xustar000000000000000030 mtime=1695812442.405981658 30 atime=1695812445.792030153 30 ctime=1695812494.482727502 yadifa-2.6.5-11201/lib/dnscore/src/bytearray_output_stream.c0000664000374500037450000002311114505005532024431 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/bytearray_output_stream.h" #include "dnscore/zalloc.h" #define BYTE_ARRAY_OUTPUT_STREAM_TAG 0x534f4142 /* BAOS */ #define BYTE_ARRAY_OUTPUT_STREAM_DATA_TAG 0x41544144534f4142 /* BAOSDATA */ #define BYTE_ARRAY_OUTPUT_STREAM_BUFF_TAG 0x46465542534f4142 /* BAOSBUFF */ #define BYTEARRAY_STARTSIZE 1024 #define BYTEARRAY_OUTPUT_STREAM_GROWTH_THRESHOLD 0x100000 #define BAOSZDUP_TAG 0x5055445a534f4142 #define BAOSDUP_TAG 0x505544534f4142 typedef struct bytearray_output_stream_data bytearray_output_stream_data; /** * @NOTE: if this changes, take care that bytearray_output_stream_context in the header file has at least the SAME SIZE */ struct bytearray_output_stream_data { u8* buffer; u32 buffer_size; u32 buffer_offset; u8 flags; }; static ya_result bytearray_output_stream_write(output_stream* stream, const u8* buffer, u32 len) { if(len == 0) { return 0; } bytearray_output_stream_data* data = (bytearray_output_stream_data*)stream->data; u32 remaining = data->buffer_size - data->buffer_offset; if(len > remaining) { /* Either we can resize, either we have to trunk */ if((data->flags & BYTEARRAY_DYNAMIC) != 0) { u8* newbuffer; u32 newsize = data->buffer_size; do { if(newsize < BYTEARRAY_OUTPUT_STREAM_GROWTH_THRESHOLD) { newsize = newsize * 2; } else { newsize += BYTEARRAY_OUTPUT_STREAM_GROWTH_THRESHOLD; } } while(newsize < data->buffer_size + len); MALLOC_OR_DIE(u8*, newbuffer, newsize, BYTE_ARRAY_OUTPUT_STREAM_BUFF_TAG); MEMCOPY(newbuffer, data->buffer, data->buffer_offset); if((data->flags & BYTEARRAY_OWNED) != 0) { free(data->buffer); } data->buffer = newbuffer; data->buffer_size = newsize; data->flags |= BYTEARRAY_OWNED; } else { len = remaining; } } MEMCOPY(&data->buffer[data->buffer_offset], buffer, len); data->buffer_offset += len; return len; } static ya_result bytearray_output_stream_flush(output_stream* stream) { (void)stream; return SUCCESS; } static void bytearray_output_stream_close(output_stream* stream) { bytearray_output_stream_data* data = (bytearray_output_stream_data*)stream->data; if((data->flags & BYTEARRAY_OWNED) != 0) { #if DEBUG memset(data->buffer, 0xe5, data->buffer_size); #endif free(data->buffer); } if((data->flags & BYTEARRAY_ZALLOC_CONTEXT) != 0) { ZFREE(data,bytearray_output_stream_data); } output_stream_set_void(stream); } static const output_stream_vtbl bytearray_output_stream_vtbl = { bytearray_output_stream_write, bytearray_output_stream_flush, bytearray_output_stream_close, "bytearray_output_stream", }; void bytearray_output_stream_init_ex_static(output_stream* out_stream, u8* array,u32 size, u8 flags, bytearray_output_stream_context *ctx) { bytearray_output_stream_data *data = (bytearray_output_stream_data*)ctx; if(array == NULL) { flags |= BYTEARRAY_OWNED; if(size == 0) { flags |= BYTEARRAY_DYNAMIC; size = BYTEARRAY_STARTSIZE; } MALLOC_OR_DIE(u8*, array, size, BYTE_ARRAY_OUTPUT_STREAM_BUFF_TAG); } data->buffer = array; data->buffer_size = size; data->buffer_offset = 0; data->flags = flags; out_stream->data = data; out_stream->vtbl = &bytearray_output_stream_vtbl; } void bytearray_output_stream_init_ex(output_stream* out_stream, u8* array, u32 size, u8 flags) { bytearray_output_stream_data* data; ZALLOC_OBJECT_OR_DIE( data, bytearray_output_stream_data, BYTE_ARRAY_OUTPUT_STREAM_DATA_TAG); flags |= BYTEARRAY_ZALLOC_CONTEXT; bytearray_output_stream_init_ex_static(out_stream, array, size, flags, (bytearray_output_stream_context*)data); } void bytearray_output_stream_init(output_stream* out_stream, u8* array, u32 size) { bytearray_output_stream_init_ex(out_stream, array, size, 0); } void bytearray_output_stream_reset(output_stream* stream) { bytearray_output_stream_data* data = (bytearray_output_stream_data*)stream->data; data->buffer_offset = 0; } ya_result bytearray_output_stream_ensure(output_stream* stream, u32 size) { bytearray_output_stream_data* data = (bytearray_output_stream_data*)stream->data; if(data->buffer_size < size) { /* Either we can resize, either we have to trunk */ size = (size + 7) & ~7; if((data->flags & BYTEARRAY_DYNAMIC) != 0) { u8* newbuffer; MALLOC_OR_DIE(u8*, newbuffer, size, BYTE_ARRAY_OUTPUT_STREAM_BUFF_TAG); MEMCOPY(newbuffer, data->buffer, data->buffer_offset); if((data->flags & BYTEARRAY_OWNED) != 0) { free(data->buffer); } data->buffer = newbuffer; data->buffer_size = size; data->flags |= BYTEARRAY_OWNED; } else { return ERROR; // not dynamic } } return SUCCESS; } u32 bytearray_output_stream_size(output_stream* stream) { bytearray_output_stream_data* data = (bytearray_output_stream_data*)stream->data; return data->buffer_offset; } u8* bytearray_output_stream_buffer(output_stream* stream) { bytearray_output_stream_data* data = (bytearray_output_stream_data*)stream->data; return data->buffer; } u8* bytearray_output_stream_detach(output_stream* stream) { bytearray_output_stream_data* data = (bytearray_output_stream_data*)stream->data; data->flags &= ~BYTEARRAY_OWNED; return data->buffer; } void bytearray_output_stream_set(output_stream* stream, u8 *buffer, u32 buffer_size, bool owned) { bytearray_output_stream_data* data = (bytearray_output_stream_data*)stream->data; if((data->buffer != buffer) && ((data->flags & BYTEARRAY_OWNED) != 0)) { free(data->buffer); } data->buffer = buffer; data->buffer_offset = buffer_size; data->buffer_size = buffer_size; data->flags = (data->flags & BYTEARRAY_ZALLOC_CONTEXT) | ((owned)?BYTEARRAY_OWNED:0); } /** * @param out_stream * @param by * @return the actual rewind_count */ u32 bytearray_output_stream_rewind(output_stream* out_stream, u32 rewind_count) { bytearray_output_stream_data* data = (bytearray_output_stream_data*)out_stream->data; if(rewind_count < data->buffer_offset) { data->buffer_offset -= rewind_count; } else { rewind_count = data->buffer_offset; data->buffer_offset = 0; } return rewind_count; } u8* bytearray_output_stream_zdup(output_stream* out_stream) { bytearray_output_stream_data* data = (bytearray_output_stream_data*)out_stream->data; u8 *ret; u32 n = MAX(data->buffer_offset, 1); // because allocating 0 bytes can be an hassle ZALLOC_OBJECT_ARRAY_OR_DIE(ret, u8, n, BAOSZDUP_TAG); memcpy(ret, data->buffer, n); return ret; } u8* bytearray_output_stream_dup(output_stream* out_stream) { bytearray_output_stream_data* data = (bytearray_output_stream_data*)out_stream->data; u8 *ret; u32 n = MAX(data->buffer_offset, 1); // because allocating 0 bytes can be an hassle MALLOC_OR_DIE(u8*, ret, n, BAOSDUP_TAG); memcpy(ret, data->buffer, n); return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/bytezarray_output_stream.c0000644000000000000000000000013214505005532024663 xustar000000000000000030 mtime=1695812442.430982016 30 atime=1695812445.793030168 30 ctime=1695812494.484727531 yadifa-2.6.5-11201/lib/dnscore/src/bytezarray_output_stream.c0000664000374500037450000001715314505005532024634 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/bytezarray_output_stream.h" #include "dnscore/zalloc.h" #define BYTE_ARRAY_OUTPUT_STREAM_TAG 0x534f4142 /* BAOS */ #define BYTE_ARRAY_OUTPUT_STREAM_DATA_TAG 0x41544144534f4142 /* BAOSDATA */ #define BYTE_ARRAY_OUTPUT_STREAM_BUFF_TAG 0x46465542534f4142 /* BAOSBUFF */ #define BYTEARRAY_STARTSIZE 1024 typedef struct bytezarray_output_stream_data bytezarray_output_stream_data; /** * @NOTE: if this changes, take care that bytezarray_output_stream_context in the header file has at least the SAME SIZE */ struct bytezarray_output_stream_data { u8* buffer; u32 buffer_size; u32 buffer_offset; u8 flags; }; static ya_result bytezarray_output_stream_write(output_stream* stream, const u8* buffer, u32 len) { if(len == 0) { return 0; } bytezarray_output_stream_data* data = (bytezarray_output_stream_data*)stream->data; u32 remaining = data->buffer_size - data->buffer_offset; if(len > remaining) { /* Either we can resize, either we have to trunk */ if((data->flags & BYTEARRAY_DYNAMIC) != 0) { u8* newbuffer; u32 newsize = data->buffer_size; do { newsize = newsize * 2; } while(newsize < data->buffer_size + len); ZALLOC_OBJECT_ARRAY_OR_DIE(newbuffer, u8, newsize, BYTE_ARRAY_OUTPUT_STREAM_TAG); MEMCOPY(newbuffer, data->buffer, data->buffer_offset); if((data->flags & BYTEARRAY_OWNED) != 0) { ZFREE_ARRAY(data->buffer, data->buffer_size); } data->buffer = newbuffer; data->buffer_size = newsize; data->flags |= BYTEARRAY_OWNED; } else { len = remaining; } } MEMCOPY(&data->buffer[data->buffer_offset], buffer, len); data->buffer_offset += len; return len; } static ya_result bytezarray_output_stream_flush(output_stream* stream) { (void)stream; return SUCCESS; } static void bytezarray_output_stream_close(output_stream* stream) { bytezarray_output_stream_data* data = (bytezarray_output_stream_data*)stream->data; if((data->flags & BYTEARRAY_OWNED) != 0) { #if DEBUG memset(data->buffer, 0xe5, data->buffer_size); #endif ZFREE_ARRAY(data->buffer, data->buffer_size); } if((data->flags & BYTEARRAY_ZALLOC_CONTEXT) != 0) { ZFREE(data, bytezarray_output_stream_data); } output_stream_set_void(stream); } static const output_stream_vtbl bytezarray_output_stream_vtbl = { bytezarray_output_stream_write, bytezarray_output_stream_flush, bytezarray_output_stream_close, "bytezarray_output_stream", }; void bytezarray_output_stream_init_ex_static(output_stream* out_stream, u8* array,u32 size, u8 flags, bytezarray_output_stream_context *ctx) { bytezarray_output_stream_data *data = (bytezarray_output_stream_data*)ctx; if(array == NULL) { flags |= BYTEARRAY_OWNED; if(size == 0) { flags |= BYTEARRAY_DYNAMIC; size = BYTEARRAY_STARTSIZE; } ZALLOC_OBJECT_ARRAY_OR_DIE(array, u8, size, BYTE_ARRAY_OUTPUT_STREAM_BUFF_TAG); } data->buffer = array; data->buffer_size = size; data->buffer_offset = 0; data->flags = flags; out_stream->data = data; out_stream->vtbl = &bytezarray_output_stream_vtbl; } void bytezarray_output_stream_init_ex(output_stream* out_stream, u8* array, u32 size, u8 flags) { bytezarray_output_stream_data* data; ZALLOC_OBJECT_OR_DIE( data, bytezarray_output_stream_data, BYTE_ARRAY_OUTPUT_STREAM_DATA_TAG); flags |= BYTEARRAY_ZALLOC_CONTEXT; bytezarray_output_stream_init_ex_static(out_stream, array, size, flags, (bytezarray_output_stream_context*)data); } void bytezarray_output_stream_init(output_stream* out_stream, u8* array, u32 size) { bytezarray_output_stream_init_ex(out_stream, array, size, 0); } void bytezarray_output_stream_reset(output_stream* stream) { bytezarray_output_stream_data* data = (bytezarray_output_stream_data*)stream->data; data->buffer_offset = 0; } u32 bytezarray_output_stream_size(output_stream* stream) { bytezarray_output_stream_data* data = (bytezarray_output_stream_data*)stream->data; return data->buffer_offset; } u32 bytezarray_output_stream_buffer_size(output_stream* stream) { bytezarray_output_stream_data* data = (bytezarray_output_stream_data*)stream->data; return data->buffer_size; } u32 bytezarray_output_stream_buffer_offset(output_stream* stream) { bytezarray_output_stream_data* data = (bytezarray_output_stream_data*)stream->data; return data->buffer_offset; } u8* bytezarray_output_stream_buffer(output_stream* stream) { bytezarray_output_stream_data* data = (bytezarray_output_stream_data*)stream->data; return data->buffer; } u8* bytezarray_output_stream_detach(output_stream* stream) { bytezarray_output_stream_data* data = (bytezarray_output_stream_data*)stream->data; data->flags &= ~BYTEARRAY_OWNED; return data->buffer; } void bytezarray_output_stream_set(output_stream* stream, u8 *buffer, u32 buffer_size, bool owned) { bytezarray_output_stream_data* data = (bytezarray_output_stream_data*)stream->data; if((data->buffer != buffer) && ((data->flags & BYTEARRAY_OWNED) != 0)) { ZFREE_ARRAY(data->buffer, data->buffer_size); } data->buffer = buffer; data->buffer_offset = buffer_size; data->buffer_size = buffer_size; data->flags = (data->flags & BYTEARRAY_ZALLOC_CONTEXT) | ((owned)?BYTEARRAY_OWNED:0); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/checked_output_stream.c0000644000000000000000000000013114505005532024054 xustar000000000000000029 mtime=1695812442.44798226 30 atime=1695812445.794030182 30 ctime=1695812494.486727559 yadifa-2.6.5-11201/lib/dnscore/src/checked_output_stream.c0000664000374500037450000001234614505005532024025 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include "dnscore/checked_output_stream.h" static void checked_data_update_from_error(checked_output_stream_data_t* data, ya_result ret) { switch(ret) { case MAKE_ERRNO_ERROR(ENOSPC): data->state |= CHECKED_OUTPUT_STREAM_NOSPC; break; case MAKE_ERRNO_ERROR(EPERM): data->state |= CHECKED_OUTPUT_STREAM_PERM; break; case MAKE_ERRNO_ERROR(EIO): data->state |= CHECKED_OUTPUT_STREAM_IO; break; case MAKE_ERRNO_ERROR(EFBIG): data->state |= CHECKED_OUTPUT_STREAM_FBIG; break; case MAKE_ERRNO_ERROR(EDQUOT): data->state |= CHECKED_OUTPUT_STREAM_DQUOT; break; case MAKE_ERRNO_ERROR(EBADF): data->state |= CHECKED_OUTPUT_STREAM_BADF; break; } } static ya_result checked_write(output_stream* stream, const u8* buffer, u32 len) { checked_output_stream_data_t* data = (checked_output_stream_data_t*)stream->data; ya_result ret = output_stream_write(data->filtered, buffer, len); if(FAIL(ret)) { checked_data_update_from_error(data, ret); } return ret; } static ya_result checked_flush(output_stream* stream) { checked_output_stream_data_t* data = (checked_output_stream_data_t*)stream->data; ya_result ret = output_stream_flush(data->filtered); if(FAIL(ret)) { checked_data_update_from_error(data, ret); } return ret; } static void checked_close(output_stream* stream) { // checked_output_stream_data_t* data = (checked_output_stream_data_t*)stream->data; output_stream_set_void(stream); } static const output_stream_vtbl checked_output_stream_vtbl ={ checked_write, checked_flush, checked_close, "checked_output_stream", }; static int checked_output_stream_errnos[CHECKED_OUTPUT_STREAM_STATES_COUNT] = { MAKE_ERRNO_ERROR(ENOSPC), MAKE_ERRNO_ERROR(EPERM), MAKE_ERRNO_ERROR(EIO), MAKE_ERRNO_ERROR(EFBIG), MAKE_ERRNO_ERROR(EDQUOT), MAKE_ERRNO_ERROR(EBADF) }; ya_result checked_output_stream_error(output_stream* os) { assert(checked_output_stream_instance(os)); output_stream_flush(os); // else a buffering will make all this checking pointless checked_output_stream_data_t* data = (checked_output_stream_data_t*)os->data; u32 state = data->state; if(state == 0) { return SUCCESS; } else { s32 index = 0; while((state & 1) == 0) { ++index; state >>= 1; } if(index < CHECKED_OUTPUT_STREAM_STATES_COUNT) { return checked_output_stream_errnos[index]; } else { return INVALID_STATE_ERROR; } } } void checked_output_stream_init(output_stream* stream, output_stream* filtered, checked_output_stream_data_t* checked_data) { yassert(filtered != stream); checked_output_stream_data_t* data = checked_data; data->filtered = filtered; data->state = 0; stream->data = data; stream->vtbl = &checked_output_stream_vtbl; } bool checked_output_stream_instance(output_stream *stream) { return (stream != NULL) && (stream->vtbl == &checked_output_stream_vtbl); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/chroot.c0000644000000000000000000000013114505005532020771 xustar000000000000000030 mtime=1695812442.492982904 29 atime=1695812445.79603021 30 ctime=1695812494.489727602 yadifa-2.6.5-11201/lib/dnscore/src/chroot.c0000664000374500037450000002131114505005532020732 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup chroot * @ingroup dnscore * @brief Chroot functions * * @{ */ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/thread.h" #include "dnscore/chroot.h" #include "dnscore/logger.h" #include "dnscore/ptr_set.h" #include "dnscore/mutex.h" #define MODULE_MSG_HANDLE g_system_logger static const char CHROOT_DEFAULT[] = "/"; static const char *chroot_path = CHROOT_DEFAULT; static bool chroot_jailed = FALSE; #define CHRTMPTH_TAG 0x4854504d54524843 struct chroot_managed_path_s { char **managed_location; char *prefixed_path; bool chrooted; }; typedef struct chroot_managed_path_s chroot_managed_path_s; static ptr_set chroot_managed_path_set = PTR_SET_PTR_EMPTY; static mutex_t choot_managed_path_set_mtx = MUTEX_INITIALIZER; /** * chroot relative: /my-sub-dirs or my-sub-dirs * not chroot relative: /my-chroot/my-sub-dirs * * @param managed_location is a pointer to the pointer of the path which MUST be mallocated (e.g.: strdup). * @param path * @param chroot_relative */ ya_result chroot_manage_path(char **managed_location, const char *path, bool chroot_relative) { const char *cp = chroot_get_path();; const char *prefixed_path = path; int cl = ((int)strlen(cp)) - 1; if(cl < 0) { return ERROR; } if(cp[cl] != '/') { return ERROR; } if(!chroot_relative) { int pl = (int)strlen(path); if(pl < cl) { return ERROR; } if(memcmp(path, cp, (size_t )cl) != 0) { return ERROR; // prefix is wrong } prefixed_path = &path[cl]; } else { if(path[0] != '/') { return ERROR; } } mutex_lock(&choot_managed_path_set_mtx); ptr_node *node = ptr_set_insert(&chroot_managed_path_set, managed_location); if(node->value == NULL) { chroot_managed_path_s *cmp; MALLOC_OBJECT_OR_DIE(cmp, chroot_managed_path_s, CHRTMPTH_TAG); cmp->managed_location = managed_location; cmp->prefixed_path = strdup(prefixed_path); cmp->chrooted = FALSE; node->value = cmp; mutex_unlock(&choot_managed_path_set_mtx); return SUCCESS; } else { // location already managed mutex_unlock(&choot_managed_path_set_mtx); return ERROR; } } ya_result chroot_unmanage_path(char **managed_location) { mutex_lock(&choot_managed_path_set_mtx); ptr_node *node = ptr_set_find(&chroot_managed_path_set, managed_location); if(node != NULL) { chroot_managed_path_s *cmp = (chroot_managed_path_s*)node->value; ptr_set_delete(&chroot_managed_path_set, managed_location); free(*cmp->managed_location); *cmp->managed_location = NULL; free(cmp->prefixed_path); free(cmp); mutex_unlock(&choot_managed_path_set_mtx); return SUCCESS; } else { mutex_unlock(&choot_managed_path_set_mtx); return ERROR; } } static void chroot_unmanage_all_cb(ptr_node *node) { chroot_managed_path_s *cmp = (chroot_managed_path_s*)node->value; free(*cmp->managed_location); *cmp->managed_location = NULL; free(cmp->prefixed_path); free(cmp); } void chroot_unmanage_all() { mutex_lock(&choot_managed_path_set_mtx); ptr_set_callback_and_destroy(&chroot_managed_path_set, chroot_unmanage_all_cb); mutex_unlock(&choot_managed_path_set_mtx); } const char * chroot_get_path() { return chroot_path; } ya_result chroot_set_path(const char *path) { if(chroot_jailed) { return CHROOT_ALREADY_JAILED; } if(path != NULL) { if(strcmp(path, chroot_path) == 0) { return SUCCESS; } struct stat fileinfo; if(stat(path, &fileinfo) < 0) { return ERRNO_ERROR; } /* Is it a directory ? */ if(!S_ISDIR(fileinfo.st_mode)) { return CHROOT_NOT_A_DIRECTORY; } if(chroot_path != CHROOT_DEFAULT) { free((char*)chroot_path); } chroot_path = strdup(path); } else { if(chroot_path != CHROOT_DEFAULT) { free((char*)chroot_path); chroot_path = CHROOT_DEFAULT; } } #if DEBUG osformatln(termout, "chroot_set_path: set to '%s'", chroot_path); #endif return SUCCESS; } /** * dummy thread used to pre-load libgcc_s.so.1 (if the architecture needs this) * * @param config */ static void * chroot_jail_dummy_thread(void *parm) { thread_exit(parm); // unreachable // return parm; return NULL; // just so some old compiler shuts-up } ya_result chroot_jail() { if(chroot_jailed) { return CHROOT_ALREADY_JAILED; } thread_t t; /** * This thread is a workaround against libraries not being linked yet * from outside the chroot environment. * * Launching it will trigger the linkage. */ if(thread_create(&t, chroot_jail_dummy_thread, NULL) == 0) { thread_join(t, NULL); } else { log_err("chroot-jail: unable to start dummy thread"); } if(chroot(chroot_path) < 0) { return ERRNO_ERROR; } chroot_jailed = TRUE; if(chdir("/") < 0) { log_warn("chroot-jail: failed to change directory to '/'"); } mutex_lock(&choot_managed_path_set_mtx); ptr_set_iterator iter; ptr_set_iterator_init(&chroot_managed_path_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); chroot_managed_path_s *cmp = (chroot_managed_path_s*)node->value; if(!cmp->chrooted) { char *new_path = strdup(cmp->prefixed_path); char *old_path = *cmp->managed_location; int new_path_len = (int)strlen(new_path); bool dirsep = TRUE; int j = 1; for(int i = 1; i <= new_path_len; i++) { char c = new_path[i]; if(c == '/') { if(!dirsep) { new_path[j++] = c; } dirsep = TRUE; } else { new_path[j++] = new_path[i]; dirsep = FALSE; } } #if DEBUG log_debug("chroot-jail: @%p: '%s' -> '%s'", *cmp->managed_location, old_path, new_path); #endif *cmp->managed_location = new_path; free(old_path); cmp->chrooted = TRUE; } } mutex_unlock(&choot_managed_path_set_mtx); return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/circular-file.c0000644000000000000000000000013214505005532022215 xustar000000000000000030 mtime=1695812442.462982475 30 atime=1695812445.795030196 30 ctime=1695812494.491727631 yadifa-2.6.5-11201/lib/dnscore/src/circular-file.c0000664000374500037450000010467614505005532022175 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ //#include "dnscore/circular-file.h" #include #include #include #include #include #include #define CIRCULAR_FILE_C 1 #include "dnscore/fdtools.h" #include "dnscore/file-pool.h" #include "dnscore/zalloc.h" #if DEBUG #include "dnscore/format.h" #endif #include "dnscore/logger.h" #define MODULE_MSG_HANDLE g_system_logger #define CIRCFILE_TAG 0x454c494643524943 #if DEBUG #ifndef CIRCULAR_FILE_DEBUG // should be 0 #define CIRCULAR_FILE_DEBUG 0 #endif #else // not DEBUG #if CIRCULAR_FILE_DEBUG #pragma message("***********************************************************") #pragma message("***********************************************************") #pragma message("CIRCULAR_FILE_DEBUG 1") #pragma message("***********************************************************") #pragma message("***********************************************************") #endif #endif /* * u32 magic * u32 reserved space size * u64 maximum size for the storage * u8 reserved[reserved space size] * u8 storage[] * */ struct circular_file_s { file_pool_file_t f; u64 maximum_size; // the current maximum size of the file u64 pending_size; // the pending maximum size of the file, to be put into maximum_size as soon as the file isn't wrapped (anymore) u64 begin; // the beginning in the file, relative to the header u64 size; // the size of the file, the number of bytes from begin (wrapped or not) u64 position; // the relative position to read/write, relative to begin u64 modulo; // the physical size of the file - headers u32 reserved_size; // the size of a reserved header (for the calling code) bool header_changed; // this flag tells the header has changed and should be written with the next flush or close }; typedef struct circular_file_s circular_file_s; struct circular_file_header_s { u8 magic[4]; // magic number u32 reserved_size; // fixed size reserved at the beginning of the file (just after this header) u64 maximum_size; // maximum allowed size of the file u64 begin; // beginning of the file u64 size; // end of the file }; #include "dnscore/circular-file.h" /* static inline u64 circular_file_end(circular_file_t cf) { return (cf->begin + cf->size) % cf->modulo; } static inline u64 circular_file_end_checked(circular_file_t cf) { if(cf->modulo > 0) { return circular_file_end(cf); } else { return 0; } } */ static inline bool circular_file_wrapped(circular_file_t cf) { return (cf->begin + cf->size) > cf->modulo; } ya_result circular_file_create(circular_file_t *cfp, file_pool_t fp, const u8 magic[4], const char* path, s64 size_max, u32 reserved_header_size) { // static_assert(sizeof(struct circular_file_header_s) == 32); if(size_max < 0) { size_max = MAX_S64; } #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_create(%p, %p, %08x, '%s', %lli, %u)", cfp, fp, *(u32*)magic, path, size_max, reserved_header_size); #endif if(sizeof(struct circular_file_header_s) + reserved_header_size > (u64)size_max) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_create(%p, %p, %08x, '%s', %lli, %u) failed: %r", cfp, fp, *(u32*)magic, path, size_max, reserved_header_size, INVALID_ARGUMENT_ERROR); #endif return INVALID_ARGUMENT_ERROR; } //O_LARGEFILE //O_NOATIME file_pool_file_t f = file_pool_open_ex(fp, path, O_CREAT|O_EXCL, 0644); if(f == NULL) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_create(%p, %p, %08x, '%s', %lli, %u) failed: %r", cfp, fp, *(u32*)magic, path, size_max, reserved_header_size, ERRNO_ERROR); #endif return ERRNO_ERROR; } struct circular_file_header_s hdr; memcpy(hdr.magic, magic, 4); hdr.reserved_size = reserved_header_size; hdr.maximum_size = size_max - sizeof(hdr) - reserved_header_size; hdr.begin = 0; hdr.size = 0; ya_result ret = file_pool_writefully(f, &hdr, sizeof(hdr)); if(FAIL(ret)) { file_pool_close(f); #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_create(%p, %p, %08x, '%s', %lli, %u) failed: %r", cfp, fp, *(u32*)magic, path, ret); #endif return ret; } circular_file_t cf; ZALLOC_OBJECT_OR_DIE(cf, circular_file_s, CIRCFILE_TAG); cf->f = f; cf->maximum_size = hdr.maximum_size; cf->pending_size = cf->maximum_size; cf->begin = hdr.begin; cf->size = hdr.size; cf->position = 0; cf->modulo = hdr.size; // file size - (header + reserved) cf->reserved_size = hdr.reserved_size; cf->header_changed = FALSE; *cfp = cf; circular_file_seek(cf, 0); return SUCCESS; } ya_result circular_file_open(circular_file_t *cfp, file_pool_t fp, const u8 magic[4], const char *path) { // static_assert(sizeof(struct circular_file_header_s) == 32); #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_open(%p, %p, %08x, '%s')", cfp, fp, *(u32*)magic, path); #endif file_pool_file_t f = file_pool_open(fp, path); if(f == NULL) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_open(%p, %p, %08x, '%s') failed: %r", cfp, fp, *(u32*)magic, path, ERRNO_ERROR); #endif return ERRNO_ERROR; } struct circular_file_header_s hdr; ya_result ret = file_pool_readfully(f, &hdr, sizeof(hdr)); if(FAIL(ret)) { file_pool_close(f); #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_create(%p, %p, %08x, '%s') failed: %r", cfp, fp, *(u32*)magic, path, ret); #endif return ret; } if(memcmp(magic, hdr.magic, 4) != 0) { file_pool_close(f); #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_create(%p, %p, %08x, '%s') failed: %r", cfp, fp, *(u32*)magic, path, DATA_FORMAT_ERROR); #endif return DATA_FORMAT_ERROR; // wrong magic } if(sizeof(struct circular_file_header_s) + hdr.reserved_size > hdr.maximum_size) { file_pool_close(f); #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_create(%p, %p, %08x, '%s') failed: %r", cfp, fp, *(u32*)magic, path, DATA_FORMAT_ERROR); #endif return DATA_FORMAT_ERROR; // the header makes no sense } size_t file_size = 0; if(FAIL(ret = file_pool_get_size(f, &file_size))) { file_pool_close(f); #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_create(%p, %p, %08x, '%s') failed: %r", cfp, fp, *(u32*)magic, path, ret); #endif return ret; } ssize_t modulo = (ssize_t)(file_size - (sizeof(struct circular_file_header_s) + hdr.reserved_size)); if((modulo < 0) || (modulo > (ssize_t )hdr.maximum_size)) { file_pool_close(f); #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_create(%p, %p, %08x, '%s') failed: %r", cfp, fp, *(u32*)magic, path, DATA_FORMAT_ERROR); #endif return DATA_FORMAT_ERROR; } circular_file_t cf; ZALLOC_OBJECT_OR_DIE(cf, circular_file_s, CIRCFILE_TAG); cf->f = f; cf->maximum_size = hdr.maximum_size; cf->pending_size = cf->maximum_size; cf->begin = hdr.begin; cf->size = hdr.size; cf->position = 0; cf->modulo = (u64)modulo; // file size - (header + reserved) cf->reserved_size = hdr.reserved_size; cf->header_changed = FALSE; *cfp = cf; circular_file_seek(cf, 0); return SUCCESS; } /** * Close the circular file reference. * The file will be effectively closed when */ ya_result circular_file_close(circular_file_t cf) { if(cf->f != NULL) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_close(%p)", cf); #endif circular_file_flush(cf); file_pool_close(cf->f); memset(cf, 0x00, sizeof(*cf)); ZFREE_OBJECT(cf); return SUCCESS; } else { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_close(%p) failed: already closed", cf); #endif return ERROR; } } const char* circular_file_name(circular_file_t cf) { if((cf != NULL) && (cf->f != NULL)) { const char *name = file_pool_filename(cf->f); #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_name(%p) = '%s'", cf, name); #endif return name; } else { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_name(%p) failed: invalid state, returning 'NULL'", cf); #endif return "NULL"; } } ya_result circular_file_unlink(circular_file_t cf) { ya_result ret = file_pool_unlink(cf->f); #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_unlink(%p) (%r)", cf, ret); #endif return ret; } u64 circular_file_tell(circular_file_t cf) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_tell(%p) = %llu", cf, cf->position); #endif return cf->position; } /** * Moves to the specified position in the file * * @param relative_offset * @return */ ssize_t circular_file_seek(circular_file_t cf, ssize_t relative_offset) { ssize_t ret; #if CIRCULAR_FILE_DEBUG ssize_t saved_position = relative_offset; log_debug5("circular_file_seek(%p, %lli)", cf, saved_position); #endif relative_offset = MIN(relative_offset, (s64)cf->size); ssize_t wrapped_position = cf->begin + relative_offset; if(cf->modulo > 0) { if(circular_file_wrapped(cf)) { wrapped_position %= cf->modulo; } } ret = file_pool_seek(cf->f, (size_t)wrapped_position + cf->reserved_size + sizeof(struct circular_file_header_s), SEEK_SET); if(ISOK(ret)) { cf->position = (u64)relative_offset; } else { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_seek(%p, %lli) failed: %r", cf, saved_position, ret); #endif relative_offset = ret; } return relative_offset; } /** * Moves relatively from the current position in the file * * @param relative_offset * @return */ ssize_t circular_file_seek_relative(circular_file_t cf, ssize_t relative_offset) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_seek_relative(%p, %lli)", cf, relative_offset); #endif ssize_t position = circular_file_tell(cf) + relative_offset; position = circular_file_seek(cf, position); return position; } /** * Reads bytes in the file. */ ya_result circular_file_read(circular_file_t cf, void* buffer_, u32 n) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_read(%p, %p, %i)", cf, buffer_, n); #endif u8* buffer = (u8*)buffer_; ya_result ret; if(n == 0) { return 0; } u64 avail = cf->size - cf->position; // both position and size are relative to begin if(avail < n) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_read(%p, %p, %i) failed: %r", cf, buffer_, n, CIRCULAR_FILE_SHORT); #endif if(avail > 0) { return CIRCULAR_FILE_SHORT; } else { return CIRCULAR_FILE_END; } } if(!circular_file_wrapped(cf)) { // the file does not wraps : everything will be read in one operation u64 abs_position = cf->begin + cf->position; assert(abs_position <= cf->maximum_size); if(ISOK(ret = file_pool_seek(cf->f, abs_position + cf->reserved_size + sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_readfully(cf->f, buffer, n))) { cf->position += n; assert(cf->position <= cf->maximum_size); ret = n; } } } else { // the file wraps: we may have to read in two operations u64 abs_position = (cf->begin + cf->position) % cf->modulo; assert(abs_position <= cf->maximum_size); //u64 abs_end = circular_file_end(cf); // abs_end is the position of the end of the data relatively to position 0 if((cf->position > 0) && (abs_position <= cf->begin)) { // if the absolute position is before the end, we will have to read from position to end // then if more has to be read, from 0 to whatever remains to be read u64 end_avail = MIN(cf->begin - abs_position, n); if(end_avail < n) { // it will be a short read return CIRCULAR_FILE_SHORT; } if(ISOK(ret = file_pool_seek(cf->f, abs_position + cf->reserved_size + sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_readfully(cf->f, buffer, end_avail))) { cf->position += n; assert(cf->position <= cf->maximum_size); ret = n; } } } else { // if the absolute position is after or equal to the end, we will have to read from position to modulo // then from 0 to end u64 end_avail = MIN(cf->modulo - abs_position, n); if(ISOK(ret = file_pool_seek(cf->f, abs_position + cf->reserved_size + sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_readfully(cf->f, buffer, end_avail))) { u64 m = n - end_avail; if(m > 0) { if(ISOK(ret = file_pool_seek(cf->f, cf->reserved_size + sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_readfully(cf->f, &buffer[end_avail], m))) { cf->position += n; assert(cf->position <= cf->maximum_size); ret = n; } } } else { cf->position += n; assert(cf->position <= cf->maximum_size); ret = n; } } } } } #if CIRCULAR_FILE_DEBUG if(FAIL(ret)) { log_debug5("circular_file_read(%p, %p, %i) failed: %r", cf, buffer_, n, ret); } #endif return ret; } /** * Writes bytes in the file. * If there is no room anymore, a short count is returned. */ ya_result circular_file_write(circular_file_t cf, const void* buffer_, u32 n) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_write(%p, %p, %i)", cf, buffer_, n); #endif u8* buffer = (u8*)buffer_; ya_result ret; if(n == 0) { return 0; } if(!circular_file_wrapped(cf)) { // the file does not wraps u64 abs_position = cf->begin + cf->position; assert(abs_position <= cf->maximum_size); u64 end_avail = cf->maximum_size - abs_position; u64 begin_avail = cf->begin; u64 avail = end_avail + begin_avail; if(avail < n) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_write(%p, %p, %i) failed: %r", cf, buffer_, n, CIRCULAR_FILE_FULL); #endif return CIRCULAR_FILE_FULL; } end_avail = MIN(end_avail, n); if(ISOK(ret = file_pool_seek(cf->f, abs_position + cf->reserved_size + sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_writefully(cf->f, buffer, end_avail))) { if(abs_position + end_avail > cf->modulo) { cf->modulo = abs_position + end_avail; } u64 m = n - end_avail; if(m > 0) { if(ISOK(ret = file_pool_seek(cf->f, cf->reserved_size + sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_writefully(cf->f, &buffer[end_avail], m))) { cf->position += n; if(cf->position > cf->size) { cf->size = cf->position; cf->header_changed = TRUE; } ret = n; } } } else { cf->position += n; assert(cf->position <= cf->maximum_size); if(cf->position > cf->size) { cf->size = cf->position; cf->header_changed = TRUE; } ret = n; } } } } else { // the file wraps: we may have to write the buffer in two operations // the file cannot grow at this moment (as it is wrapped) // so what is available is // real position in file = (begin + position) % modulo // if real position < begin: available = begin - real position // else: available = modulo - real position + begin u64 abs_position = (cf->begin + cf->position) % cf->modulo; // abs_end is the position of the end of the data relatively to position 0 if((cf->position > 0) && (abs_position <= cf->begin)) { // if the absolute position is before the end, we will have to read from position to end // then if more has to be read, from 0 to whatever remains to be read u64 end_avail = cf->begin - abs_position; if(end_avail < n) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_write(%p, %p, %i) failed: %r", cf, buffer_, n, CIRCULAR_FILE_FULL); #endif return CIRCULAR_FILE_FULL; } end_avail = MIN(end_avail, n); if(ISOK(ret = file_pool_seek(cf->f, abs_position + cf->reserved_size + sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_writefully(cf->f, buffer, end_avail))) { if(abs_position + end_avail > cf->modulo) { cf->modulo = abs_position + end_avail; } cf->position += n; if(cf->position > cf->size) { cf->size = cf->position; cf->header_changed = TRUE; } ret = n; } } } else { // if the absolute position is after or equal to the end, we will have to write from position to begin // then from 0 to end u64 total_avail = cf->modulo - abs_position + cf->begin; if(total_avail < n) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_write(%p, %p, %i) failed: %r", cf, buffer_, n, CIRCULAR_FILE_FULL); #endif return CIRCULAR_FILE_FULL; } u64 end_avail = MIN(cf->modulo - abs_position, n); if(ISOK(ret = file_pool_seek(cf->f, abs_position + cf->reserved_size + sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_writefully(cf->f, buffer, end_avail))) { if(abs_position + end_avail > cf->modulo) { cf->modulo = abs_position + end_avail; } u64 m = n - end_avail; if(m > 0) { if(ISOK(ret = file_pool_seek(cf->f, cf->reserved_size + sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_writefully(cf->f, &buffer[end_avail], m))) { cf->position += n; if(cf->position > cf->size) { cf->size = cf->position; cf->header_changed = TRUE; } ret = n; } } } else { cf->position += n; if(cf->position > cf->size) { cf->size = cf->position; cf->header_changed = TRUE; } ret = n; } } } } } #if CIRCULAR_FILE_DEBUG if(FAIL(ret)) { log_debug5("circular_file_write(%p, %p, %i) failed: %r", cf, buffer_, n, ret); } #endif return ret; } /** * To know how much space is available on the file before having to overwrite * */ u64 circular_file_get_used_space(circular_file_t cf) { if(cf->begin <= cf->size) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_get_used_space(%p) = %llu", cf, (cf->maximum_size - cf->size) + cf->begin); #endif return (cf->maximum_size - cf->size) + cf->begin; } else { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_get_used_space(%p) = %llu", cf, cf->begin - cf->size); #endif return cf->begin - cf->size; } } u64 circular_file_get_maximum_size(circular_file_t cf) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_get_maximum_size(%p) = %llu", cf, cf->maximum_size); #endif return cf->maximum_size; } u64 circular_file_get_pending_size(circular_file_t cf) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_get_maximum_size(%p) = %llu", cf, cf->pending_size); #endif return cf->pending_size; } u64 circular_file_get_size(circular_file_t cf) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_get_size(%p) = %llu", cf, cf->size); #endif return cf->size; } void circular_file_set_size(circular_file_t cf, u64 size) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_set_size(%p, %llu)", cf, size); #endif cf->size = size; if(cf->position > size) { cf->position = size; } } s64 circular_file_get_read_available(circular_file_t cf) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_get_read_available(%p) = %llu", cf, cf->size - cf->position); #endif return cf->size - cf->position; } s64 circular_file_get_write_available(circular_file_t cf) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_write(%p, %p, %i)", cf, buffer_, n); #endif if(!circular_file_wrapped(cf)) { // the file does not wraps s64 abs_position = cf->begin + cf->position; assert(abs_position <= (s64)cf->maximum_size); s64 end_avail = cf->maximum_size - abs_position; s64 begin_avail = cf->begin; s64 avail = end_avail + begin_avail; return avail; } else { s64 abs_position = (cf->begin + cf->position) % cf->modulo; // abs_end is the position of the end of the data relatively to position 0 if((cf->position > 0) && (abs_position <= (s64)cf->begin)) { // if the absolute position is before the end, we will have to read from position to end // then if more has to be read, from 0 to whatever remains to be read s64 end_avail = cf->begin - abs_position; return end_avail; } else { // if the absolute position is after or equal to the end, we will have to write from position to begin // then from 0 to end s64 total_avail = cf->modulo - abs_position + cf->begin; return total_avail; } } } /** * Changes the maximum size to an higher value. The new space may not be made available * instantly if the write offset is physically before the logical start of the file. * The new size must bi bigger than sizeof(struct circular_file_header_s) */ ya_result circular_file_grow(circular_file_t cf, s64 new_maximum_size) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_grow(%p, %lli)", cf, new_maximum_size); #endif if(new_maximum_size <= (s64)sizeof(struct circular_file_header_s)) { return INVALID_ARGUMENT_ERROR; } if(cf->maximum_size < (u64)new_maximum_size) { cf->pending_size = (u64)new_maximum_size; if(!circular_file_wrapped(cf)) { cf->maximum_size = (u64)new_maximum_size; cf->header_changed = TRUE; } return SUCCESS; } else { return CIRCULAR_FILE_LIMIT_EXCEEDED; } } ya_result circular_file_get_reserved_header_size(circular_file_t cf, s32 *reserved_size) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_get_reserved_header_size(%p, %p) = ", cf, reserved_size, cf->reserved_size); #endif *reserved_size = cf->reserved_size; return SUCCESS; } ya_result circular_file_read_reserved_header(circular_file_t cf, void *buffer, u32 buffer_size) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_read_reserved_header(%p, %p, %i) = ", cf, buffer, buffer_size); #endif if(cf->reserved_size <= buffer_size) { ssize_t position; ya_result ret; if(ISOK(ret = file_pool_tell(cf->f, (size_t*)&position))) { if(ISOK(ret = file_pool_seek(cf->f, sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_read(cf->f, buffer, cf->reserved_size))) { ret = file_pool_seek(cf->f, position, SEEK_SET); } } } #if CIRCULAR_FILE_DEBUG if(FAIL(ret)) { log_debug5("circular_file_read_reserved_header(%p, %p, %i) failed: %r", cf, buffer, buffer_size, ret); } #endif return ret; } else { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_read_reserved_header(%p, %p, %i) failed: %r", cf, buffer, buffer_size, BUFFER_WOULD_OVERFLOW); #endif return BUFFER_WOULD_OVERFLOW; } } ya_result circular_file_write_reserved_header(circular_file_t cf, void *buffer, u32 buffer_size) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_write_reserved_header(%p, %p, %i)", cf, buffer, buffer_size); #endif if(cf->reserved_size <= buffer_size) { ssize_t position; ya_result ret; if(ISOK(ret = file_pool_tell(cf->f, (size_t*)&position))) { if(ISOK(ret = file_pool_seek(cf->f, sizeof(struct circular_file_header_s), SEEK_SET))) { if(ISOK(ret = file_pool_write(cf->f, buffer, cf->reserved_size))) { ret = file_pool_seek(cf->f, position, SEEK_SET); } } } #if CIRCULAR_FILE_DEBUG if(FAIL(ret)) { log_debug5("circular_file_write_reserved_header(%p, %p, %i) failed: %r", cf, buffer, buffer_size, ret); } #endif return ret; } else { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_write_reserved_header(%p, %p, %i) failed: %r", cf, buffer, buffer_size, BUFFER_WOULD_OVERFLOW); #endif return BUFFER_WOULD_OVERFLOW; } } ya_result circular_file_flush(circular_file_t cf) { ya_result ret = SUCCESS; log_debug5("circular_file_flush(%p)", cf); if(cf->header_changed) { ssize_t position; if(ISOK(ret = file_pool_tell(cf->f, (size_t*)&position))) { struct circular_file_header_s hdr = { {0,0,0,0}, 0, cf->maximum_size, cf->begin, cf->size, }; if(ISOK(ret = file_pool_seek(cf->f, offsetof(struct circular_file_header_s, maximum_size), SEEK_SET))) { ret = file_pool_write(cf->f, &hdr.maximum_size, sizeof(struct circular_file_header_s) - offsetof(struct circular_file_header_s, maximum_size)); file_pool_seek(cf->f, position, SEEK_SET); // can only fail if the 3rd parameter is wrong } } cf->header_changed = FALSE; } if(ISOK(ret)) { ret = file_pool_flush(cf->f); } #if CIRCULAR_FILE_DEBUG if(FAIL(ret)) { log_debug5("circular_file_flush(%p) failed: %r", cf, ret); } #endif return ret; } /** * Releases space at the logical beginning of the file * Should be called by the callback when space is needed */ ya_result circular_file_shift(circular_file_t cf, s64 bytes) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_shift(%p, %lli)", cf, bytes); #endif if(bytes > (s64)cf->size) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_shift(%p, %lli) failed: %r", cf, bytes, INVALID_ARGUMENT_ERROR); #endif return INVALID_ARGUMENT_ERROR; } cf->begin += bytes; cf->size -= bytes; cf->position -= bytes; // could result in a negative position, but may be used by a relative seek forward assert(cf->size <= cf->maximum_size); if(cf->begin >= cf->modulo) { cf->begin %= cf->modulo; } if(cf->maximum_size < cf->pending_size) { if(!circular_file_wrapped(cf)) { cf->maximum_size = cf->pending_size; } } cf->header_changed = TRUE; return SUCCESS; } static ya_result circular_file_input_stream_read(input_stream* is, void *buffer, u32 len) { ya_result ret; #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_input_stream_read(%p, %p, %u)", is, buffer, len); #endif ret = circular_file_read((circular_file_t)is->data, buffer, len); return ret; } static ya_result circular_file_input_stream_skip(input_stream* is, u32 len) { ya_result ret; u32 remain = len; u8 tmp[512]; #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_input_stream_skip(%p, %u)", is, len); #endif while(remain > 0) { if(FAIL(ret = circular_file_read((circular_file_t)is->data, tmp, MIN(sizeof(tmp), remain)))) { len -= remain; if(len > 0) { ret = len; } return ret; } remain -= ret; } return len; } static void circular_file_input_stream_close(input_stream* is) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_input_stream_close(%p)", is); #endif circular_file_close((circular_file_t)is->data); } static void circular_file_input_stream_noclose(input_stream* is) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_input_stream_noclose(%p)", is); #endif (void)is; } static const input_stream_vtbl circular_file_input_stream_vtbl = { circular_file_input_stream_read, circular_file_input_stream_skip, circular_file_input_stream_close, "circular_file_input_stream", }; static const input_stream_vtbl circular_file_input_stream_noclose_vtbl = { circular_file_input_stream_read, circular_file_input_stream_skip, circular_file_input_stream_noclose, "circular_file_input_stream_noclose", }; void circular_file_input_stream_init(input_stream *is, circular_file_t cf) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_input_stream_init(%p, %p)", is, cf); #endif is->data = cf; is->vtbl = &circular_file_input_stream_vtbl; } void circular_file_input_stream_noclose_init(input_stream *is, circular_file_t cf) { #if CIRCULAR_FILE_DEBUG log_debug5("circular_file_input_stream_noclose_init(%p, %p)", is, cf); #endif is->data = cf; is->vtbl = &circular_file_input_stream_noclose_vtbl; } void circular_file_dump(circular_file_t cf) { #if DEBUG formatln("%p: [%6llu += %6llu] @ %6llu [%6llu of %6llu to %6llu] %i", cf->f, cf->begin, cf->size, cf->position, cf->modulo, cf->maximum_size, cf->pending_size, cf->header_changed); yassert(cf->size <= cf->maximum_size); yassert(cf->position <= cf->size); #endif (void)cf; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/clone_input_output_stream.c0000644000000000000000000000013114505005532025005 xustar000000000000000030 mtime=1695812442.396981529 30 atime=1695812445.792030153 29 ctime=1695812494.49372766 yadifa-2.6.5-11201/lib/dnscore/src/clone_input_output_stream.c0000664000374500037450000001204714505005532024754 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/clone_input_output_stream.h" #include "dnscore/zalloc.h" #define CLONE_INPUT_OUTPUT_STREAM_TAG 0x534f49454e4f4c43 /* CLONEIOS */ typedef struct clone_input_output_stream_data clone_input_output_stream_data; struct clone_input_output_stream_data { input_stream cloned; output_stream copy; }; static ya_result clone_input_output_stream_read(input_stream* stream, void* buffer, u32 len) { clone_input_output_stream_data* data = (clone_input_output_stream_data*)stream->data; ya_result return_value; if(ISOK(return_value = input_stream_read(&data->cloned, buffer, len))) { output_stream_write(&data->copy, buffer, (u32)return_value); } return return_value; } static void clone_input_output_stream_close(input_stream* stream) { clone_input_output_stream_data* data = (clone_input_output_stream_data*)stream->data; input_stream_close(&data->cloned); output_stream_close(&data->copy); ZFREE(data, clone_input_output_stream_data); input_stream_set_void(stream); } static u8 skip[4] = {'S', 'K', 'I', 'P'}; static ya_result clone_input_output_stream_skip(input_stream* stream, u32 len) { clone_input_output_stream_data* data = (clone_input_output_stream_data*)stream->data; ya_result return_code; if(ISOK(return_code = input_stream_skip(&data->cloned, len))) { int n = return_code; while(n > 4) { output_stream_write(&data->copy, skip, 4); n -= 4; } output_stream_write(&data->copy, skip, (u32)n); } return return_code; } static const input_stream_vtbl clone_input_output_stream_vtbl ={ clone_input_output_stream_read, clone_input_output_stream_skip, clone_input_output_stream_close, "clone_input_output_stream" }; ya_result clone_input_output_stream_init(input_stream *cis, input_stream *in_cloned, output_stream *out_stream) { clone_input_output_stream_data* data; if((in_cloned->vtbl == NULL) || (out_stream == NULL)) { return OBJECT_NOT_INITIALIZED; } ZALLOC_OBJECT_OR_DIE( data, clone_input_output_stream_data, CLONE_INPUT_OUTPUT_STREAM_TAG); data->cloned.data = in_cloned->data; data->cloned.vtbl = in_cloned->vtbl; data->copy.data = out_stream->data; data->copy.vtbl = out_stream->vtbl; in_cloned->data = NULL; in_cloned->vtbl = NULL; out_stream->data = NULL; out_stream->vtbl = NULL; cis->data = data; cis->vtbl = &clone_input_output_stream_vtbl; return SUCCESS; } input_stream * clone_input_output_stream_get_cloned(input_stream *cis) { clone_input_output_stream_data *data = (clone_input_output_stream_data*)cis->data; return &data->cloned; } output_stream * clone_input_output_stream_get_copy(input_stream *cis) { clone_input_output_stream_data *data = (clone_input_output_stream_data*)cis->data; return &data->copy; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/cmdline.c0000644000000000000000000000013214505005532021107 xustar000000000000000030 mtime=1695812442.371981171 30 atime=1695812445.791030139 30 ctime=1695812494.495727688 yadifa-2.6.5-11201/lib/dnscore/src/cmdline.c0000664000374500037450000003675114505005532021065 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include #include "dnscore/dnscore-config.h" #include "dnscore/bytearray_input_stream.h" #include "dnscore/bytearray_output_stream.h" #include "dnscore/ptr_set.h" #include "dnscore/format.h" #include "dnscore/cmdline.h" #define CMDLOSAP_TAG 0x5041534f4c444d43 static ptr_set g_cmdline_sections = PTR_SET_ASCIIZ_EMPTY; static bool cmdline_init_error_codes_done = FALSE; /* #if 0 v = value; t = translate; ya_result cmdline_tsigkey_translate(output_stream *os, const char *text, const char *section_name) { } CMDLINE(0, "main"); v, 'd', "daemon", "on" , "daemon" /// (on/off) CMDLINE(0, "zone"); v, 0, "nodaemon", "off" , "daemon" /// (on/off) CMDLINE(0, "main"); v, 't', "thread-count, NULL , "thread-count" {0, "key"} {t, "key", 'y', cmdline_tsigkey_translate} daemon || d === on /off; i thread-count || t , "10" #endif */ ya_result cmdline_process_argument(const cmdline_desc_s *desc, const char *section_name, const char *arg) { ya_result return_code; if((desc->flags & CMDLINE_FLAG_ARGUMENTS) && (arg == NULL)) { return CMDLINE_OPT_EXPECTS_ARGUMENT; } ptr_node *node; node = ptr_set_insert(&g_cmdline_sections, (char*)section_name); output_stream *os; if(node->value == NULL) { MALLOC_OBJECT_OR_DIE(os, output_stream, CMDLOSAP_TAG); bytearray_output_stream_init(os, NULL, 0); osformatln(os, "<%s>", section_name); node->value = os; } os = (output_stream *)node->value; switch(desc->flags) { case CMDLINE_FLAG_SECTION: return_code = CMDLINE_PROCESSING_SECTION_AS_ARGUMENT; break; case CMDLINE_FLAG_ALIAS: osformatln(os, "%s \"%s\"", desc->target.alias, desc->value); return_code = 0; break; case CMDLINE_FLAG_TRANSLATOR: return_code = desc->target.translator(desc, os, section_name, desc->value); if(return_code >= 0) { return_code = 0; } break; case CMDLINE_FLAG_ALIAS | CMDLINE_FLAG_ARGUMENTS: osformatln(os, "%s \"%s\"", desc->target.alias, arg); return_code = 1; break; case CMDLINE_FLAG_TRANSLATOR | CMDLINE_FLAG_ARGUMENTS: return_code = desc->target.translator(desc, os, section_name, arg); break; default: // ignore return_code = 0; break; } return return_code; } ya_result cmdline_get_opt_long(const cmdline_desc_s *table, const char *name, const char *arg) { ya_result return_code = CMDLINE_LONG_OPT_UNDEFINED; int i; bool internal_arg = FALSE; char clean_name[128]; for(i = 0; name[i] != '\0'; i++) { if(name[i] != '=') { clean_name[i] = name[i]; } else { arg = &name[i + 1]; internal_arg = TRUE; break; } } clean_name[i] = '\0'; const char *section_name = ""; for(const cmdline_desc_s *desc = table; cmdline_desc_not_end(desc); desc++) { if(desc->flags == CMDLINE_FLAG_SECTION) { section_name = desc->name; continue; } if((desc->name != NULL) && (strcmp(clean_name, desc->name) == 0)) { if(ISOK(return_code = cmdline_process_argument(desc, section_name, arg))) { if(internal_arg) { return_code = 0; } } if((desc->flags & CMDLINE_FLAG_OBFUSCATE) != 0) { if(arg != NULL) { for(char *p = (char*)arg; *p != '\0'; ++p) { *p = '\t'; } } } break; } } return return_code; } /** * Returns 1 if the argument has been eaten, 0 if not. */ ya_result cmdline_get_opt_short(const cmdline_desc_s *table, const char *name, const char *arg) { ya_result return_code = CMDLINE_SHORT_OPT_UNDEFINED; const char *section_name = ""; while(*name != '\0') { for(const cmdline_desc_s *desc = table; cmdline_desc_not_end(desc); desc++) { if(desc->flags == CMDLINE_FLAG_SECTION) { section_name = desc->name; continue; } if(*name == desc->letter) { if(desc->flags & CMDLINE_FLAG_ARGUMENTS) { if(name[1] != '\0') { arg = &name[1]; } return_code = cmdline_process_argument(desc, section_name, arg); if(arg != NULL) { if((desc->flags & CMDLINE_FLAG_OBFUSCATE) != 0) { for(char *p = (char*)arg; *p != '\0'; ++p) { *p = '\t'; } } } /* if(ISOK(return_code)) { return_code = desc->flags & CMDLINE_FLAG_ARGUMENTS; } */ return return_code; } else { return_code = cmdline_process_argument(desc, section_name, arg); if(arg != NULL) { if((desc->flags & CMDLINE_FLAG_OBFUSCATE) != 0) { for(char *p = (char*)arg; *p != '\0'; ++p) { *p = '\t'; } } } break; } } } name++; } return return_code; } ya_result cmdline_parse(const cmdline_desc_s *table, int argc, char **argv, cmdline_filter_callback *filter, void *filter_arg, input_stream *is, int *argc_errorp) { if((table == NULL) || (argv == NULL) || (is == NULL)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } if(argc_errorp != NULL) { *argc_errorp = -1; } // ensures the IS is unusable if something goes wrong here input_stream_set_void(is); // check if the first line after "CMDLINE_BEGIN" sets the filter if((table->flags & CMDLINE_FLAG_FILTER_SET) != 0) { // override the filter filter = table->target.filter; filter_arg = CMDLINE_CALLBACK_ARG_GET(table); } for(int i = 1; i < argc; i++) { char *arg = argv[i]; int arg_len = strlen(arg); ya_result return_code; if((arg[0] == '-') && (arg_len > 1)) { // fetch next val const char *val = NULL; if(i < argc - 1) { val = argv[i + 1]; /* if(val[0] == '-') { val = NULL; } */ } // check opt(long/short) or add if(arg[1] != '-') { // short argument if(FAIL(return_code = cmdline_get_opt_short(table, &arg[1], val))) { if(argc_errorp != NULL) { *argc_errorp = i; } return return_code; } i += return_code; continue; } else { // long argument if(arg_len > 2) { if(FAIL(return_code = cmdline_get_opt_long(table, &arg[2], val))) { if(argc_errorp != NULL) { *argc_errorp = i; } return return_code; } i += return_code; continue; } else // == 2 { // case of "--" // fall outside of the if } } } if(filter != NULL) { return_code = filter(table, arg, filter_arg); switch(return_code) { case CMDLINE_ARG_STOP_PROCESSING_FLAG_OPTIONS: { for(++i;i < argc;i++) { char *arg_i = argv[i]; if(FAIL(return_code = filter(table, arg_i, filter_arg))) { break; } } break; } default: break; } if(FAIL(return_code)) { if(argc_errorp != NULL) { *argc_errorp = i; } return return_code; } } } // for /// output_stream complete_config_os; bytearray_output_stream_init(&complete_config_os, NULL, 0); ptr_set_iterator iter; ptr_set_iterator_init(&g_cmdline_sections, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); output_stream *os = (output_stream *)node->value; const char *section_name = (const char *)node->key; osformatln(os, "", section_name); u32 buffer_size = bytearray_output_stream_size(os); const u8 *buffer = bytearray_output_stream_buffer(os); output_stream_write(&complete_config_os, buffer, buffer_size); output_stream_close(os); // VS false positive: 'os' cannot be NULL or the node would not exist free(node->value); node->value = NULL; } ptr_set_destroy(&g_cmdline_sections); u32 buffer_size = bytearray_output_stream_size(&complete_config_os); u8 *buffer = bytearray_output_stream_detach(&complete_config_os); output_stream_close(&complete_config_os); bytearray_input_stream_init(is, buffer, buffer_size, TRUE); return buffer_size; } void cmdline_init_error_codes() { if(cmdline_init_error_codes_done) { return; } cmdline_init_error_codes_done = TRUE; error_register(CMDLINE_PROCESSING_SECTION_AS_ARGUMENT, "CMDLINE_PROCESSING_SECTION_AS_ARGUMENT"); error_register(CMDLINE_PROCESSING_INVALID_DESCRIPTOR, "CMDLINE_PROCESSING_INVALID_DESCRIPTOR"); error_register(CMDLINE_LONG_OPT_UNDEFINED, "CMDLINE_LONG_OPT_UNDEFINED"); error_register(CMDLINE_SHORT_OPT_UNDEFINED, "CMDLINE_SHORT_OPT_UNDEFINED"); error_register(CMDLINE_OPT_EXPECTS_ARGUMENT, "CMDLINE_OPT_EXPECTS_ARGUMENT"); } ya_result cmdline_print_help(const cmdline_desc_s *table, int arg_column_prefix, int arg_width, const char *column_separator, int text_width, output_stream *os) { const cmdline_desc_s *p = NULL; const cmdline_desc_s *t = table; while(cmdline_desc_not_end(t)) { if((t->flags & CMDLINE_FLAG_HELP_LINE) && (p != NULL)) { osprint_char_times(os, ' ', arg_column_prefix); int width = 0; if(p->letter != '\0') { width += output_stream_write_u8(os, '-'); width += output_stream_write_u8(os, (u8)p->letter); if(p->name != NULL) { width += output_stream_write(os, ", ", 2); } } if(p->name != NULL) { width += output_stream_write(os, "--", 2); width += osprint(os, p->name); if((t->name != NULL) && (t->name[0] != '\0')) { width += output_stream_write_u8(os, ' '); width += osprint(os, t->name); } } osprint_char_times(os, ' ', arg_width - width); osprint(os, column_separator); int help_len = (int)strlen(t->value); if(help_len < text_width) { osprint(os, t->value); } else { #if DEBUG #pragma message("TODO: (COSMETIC) cut the t->value text word by word and wrap to the next line when needed") #endif osprint(os, t->value); } output_stream_write_u8(os, '\n'); } else if(t->flags & CMDLINE_FLAG_HELP_MESSAGE) { if(t->flags & CMDLINE_FLAG_INDENTED) { osprint_char_times(os, ' ', arg_column_prefix); } int width = osprint(os, t->name); osprint_char_times(os, ' ', arg_width - width); if(t->letter != 0) { output_stream_write_u8(os, t->letter); } if(t->flags & CMDLINE_FLAG_SEPARATOR) { osprint(os, column_separator); } osprint(os, t->value); output_stream_write_u8(os, '\n'); } else if(t->flags & CMDLINE_FLAG_HELP_CALLBACK) { t->target.printer(t, os); output_stream_write_u8(os, '\n'); } else if(t->flags == CMDLINE_FLAG_INDENTED) { arg_column_prefix = MAX(arg_column_prefix + t->target.integer_value, 0); } p = t; ++t; } return SUCCESS; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/concat_input_stream.c0000644000000000000000000000013214505005532023535 xustar000000000000000030 mtime=1695812442.423981916 30 atime=1695812445.793030168 30 ctime=1695812494.497727717 yadifa-2.6.5-11201/lib/dnscore/src/concat_input_stream.c0000664000374500037450000001476314505005532023512 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/concat_input_stream.h" #include "dnscore/zalloc.h" #define CONCAT_INPUT_STREAM_TAG 0x53495441434e4f43 /* CONCATIS */ #define CONCAT_INPUT_STREAM_NODE_TAG 0x5349444e54434e43 /* CNCTNDIS */ typedef struct concat_input_stream_data_node concat_input_stream_data_node; struct concat_input_stream_data_node { struct concat_input_stream_data_node *next; input_stream filtered; }; typedef struct concat_input_stream_data concat_input_stream_data; struct concat_input_stream_data { concat_input_stream_data_node* current; concat_input_stream_data_node** lastlink; }; static ya_result concat_read(input_stream* stream, void* buffer_, u32 len) { concat_input_stream_data *data = (concat_input_stream_data*)stream->data; u8 *buffer = (u8*)buffer_; ya_result total = 0; ya_result return_value = SUCCESS; while(len > 0) { if(data->current == NULL) { return_value = SUCCESS; break; } if(FAIL(return_value = input_stream_read(&data->current->filtered, &buffer[total], len))) { break; } if(return_value == 0) /* EOF */ { concat_input_stream_data_node *next = data->current->next; input_stream_close(&data->current->filtered); ZFREE(data->current, concat_input_stream_data_node); data->current = next; if(data->current == NULL) { data->lastlink = &data->current; } continue; } total += return_value; len -= return_value; } if((total == 0) && FAIL(return_value)) { total = return_value; } return total; } static void concat_close(input_stream* stream) { concat_input_stream_data* data = (concat_input_stream_data*)stream->data; while(data->current != NULL) { input_stream_close(&data->current->filtered); concat_input_stream_data_node *next = data->current->next; ZFREE(data->current, concat_input_stream_data_node); data->current = next; } ZFREE(data, concat_input_stream_data); input_stream_set_void(stream); } static ya_result concat_skip(input_stream* stream, u32 len) { concat_input_stream_data *data = (concat_input_stream_data*)stream->data; ya_result total = 0; ya_result return_value = SUCCESS; while(len > 0) { if(data->current == NULL) { return_value = -1; break; } if(FAIL(return_value = input_stream_skip(&data->current->filtered, len))) { if(return_value == -1) { concat_input_stream_data_node *next = data->current->next; input_stream_close(&data->current->filtered); ZFREE(data->current, concat_input_stream_data_node); data->current = next; if(data->current == NULL) { data->lastlink = &data->current; } continue; } break; } total += return_value; len -= return_value; } if((total == 0) && FAIL(return_value)) { total = return_value; } return total; } static const input_stream_vtbl concat_input_stream_vtbl = { concat_read, concat_skip, concat_close, "concat_input_stream" }; /** * * @param cis */ void concat_input_stream_init(input_stream *cis) { concat_input_stream_data* data; ZALLOC_OBJECT_OR_DIE(data, concat_input_stream_data, CONCAT_INPUT_STREAM_TAG); data->current = NULL; data->lastlink = &data->current; cis->data = data; cis->vtbl = &concat_input_stream_vtbl; } /** * * @param cis * @param added_stream */ void concat_input_stream_add(input_stream *cis, input_stream *added_stream) { concat_input_stream_data* data = (concat_input_stream_data*)cis->data; concat_input_stream_data_node *node; ZALLOC_OBJECT_OR_DIE( node, concat_input_stream_data_node, CONCAT_INPUT_STREAM_NODE_TAG); node->filtered.data = added_stream->data; node->filtered.vtbl = added_stream->vtbl; node->next = NULL; added_stream->data = NULL; added_stream->vtbl = NULL; *data->lastlink = node; data->lastlink = &node->next; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/config-cmdline.c0000644000000000000000000000013014505005532022350 xustar000000000000000028 mtime=1695812442.3739812 30 atime=1695812445.791030139 30 ctime=1695812494.499727745 yadifa-2.6.5-11201/lib/dnscore/src/config-cmdline.c0000664000374500037450000000654714505005532022330 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #define CONFIG_CMDLINE_C #include "dnscore/dnscore-config.h" #include "dnscore/config_settings.h" const char CMDLINE_CONTAINER[] = "\001cmdline"; /// command line container // only for the general settings: // version // help typedef struct cmdline_general_settings_s cmdline_general_settings_s; struct cmdline_general_settings_s { u8 version; bool help; }; #define CONFIG_TYPE cmdline_general_settings_s CONFIG_BEGIN(cmdline_settings_desc) CONFIG_U8_INC(version) CONFIG_BOOL(help, "0") CONFIG_END(cmdline_settings_desc) #undef CONFIG_TYPE // declare and init global variable static cmdline_general_settings_s cmdline_general_settings = {0, FALSE}; ya_result config_register_cmdline(u8 priority) { ya_result return_code; // init and register general command line settings container if(FAIL(return_code = config_register_struct(CMDLINE_CONTAINER, cmdline_settings_desc, &cmdline_general_settings, priority))) { return return_code; } return SUCCESS; } /** * Returns if the CMDLINE_VERSION_HELP(main_cmdline) command line help hook detected a --help * Needs to have config_register_cmdline(priority++) called in the configuration registration code. */ bool cmdline_help_get() { return cmdline_general_settings.help; } /** * Returns if the CMDLINE_VERSION_HELP(main_cmdline) command line help hook detected a --version * Needs to have config_register_cmdline(priority++) called in the configuration registration code. */ u8 cmdline_version_get() { return cmdline_general_settings.version; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/config_file_reader.c0000644000000000000000000000013114505005532023261 xustar000000000000000029 mtime=1695812442.40398163 30 atime=1695812445.792030153 30 ctime=1695812494.501727774 yadifa-2.6.5-11201/lib/dnscore/src/config_file_reader.c0000664000374500037450000005521614505005532023235 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #define DO_PRINT 0 #include "dnscore/fdtools.h" #include "dnscore/dnscore-config.h" #include "dnscore/config_file_reader.h" #include "dnscore/parser.h" #include "dnscore/logger.h" #include "dnscore/file_input_stream.h" #include "dnscore/typebitmap.h" #include "dnscore/config_settings.h" #include "dnscore/fdtools.h" #define CONFIG_FILE_READER_INCLUDE_DEPTH_MAX 4 #define CFREADER_TAG 0x5245444145524641 extern logger_handle *g_zone_logger; #define MODULE_MSG_HANDLE g_zone_logger typedef struct config_file_reader config_file_reader; struct config_file_reader { parser_s parser; config_section_descriptor_s *section_descriptor; config_error_s *error_context; struct file_mtime_set_s *file_mtime_set; const char *container_name; size_t container_name_length; size_t key_length; size_t current_container_name_length; //u8 container_type; u8 includes_count; bool in_container; bool expected_container; /// char text_buffer[512]; char key[256]; char current_container_name[256]; input_stream includes[CONFIG_FILE_READER_INCLUDE_DEPTH_MAX]; char* file_name[CONFIG_FILE_READER_INCLUDE_DEPTH_MAX]; }; /** * Prepends the path of the base file to the file path * file_path should be in a buffer of at least PATH_MAX chars * * @param file_path of size PATH_MAX * @param base_file_path * @return */ static ya_result config_file_reader_prepend_path_from_file(char *file_path, const char *base_file_path) { size_t n = 0; const char *file_name_last_slash = strrchr(base_file_path, '/'); if(file_name_last_slash == NULL) { size_t m = strlen(file_path); return m; } else { ++file_name_last_slash; } n = file_name_last_slash - base_file_path; if(n >= PATH_MAX) { return CONFIG_FILE_PATH_TOO_BIG; } size_t m = strlen(file_path); if(n + m + 1 >= PATH_MAX) { return CONFIG_FILE_PATH_TOO_BIG; } memmove(&file_path[n], file_path, m + 1); memcpy(file_path, base_file_path, n); return n + m; } /** * * Parses a configuration * * @param cfr * @return */ static ya_result config_file_reader_read(config_file_reader *cfr, config_error_s *cfgerr) /// config_reader { parser_s *p = &cfr->parser; ya_result return_code; int token_count = 0; for(;;) { // get the next token if(ISOK(return_code = parser_next_token(p))) { if((token_count & 255) == 0) // force early stop for cases with huge configurations/includes { if(dnscore_shuttingdown()) { return_code = PARSER_EOF; } } ++token_count; if(!(return_code & PARSER_WORD)) { if(return_code & PARSER_COMMENT) { #if DO_PRINT print("[COMMENT]"); #endif continue; } if(return_code & PARSER_EOL) { #if DO_PRINT println("[EOL]"); #endif continue; } if(return_code & PARSER_EOF) { #if DO_PRINT println("[EOF]"); #endif // EOF: close the stream and pop the next one if available // else just finish parsing --cfr->includes_count; free(cfr->file_name[cfr->includes_count]); input_stream *completed_stream = parser_pop_stream(p); input_stream_close(completed_stream); if(parser_stream_count(p) > 0) { continue; } else { break; } } continue; } p->needle_mark = p->text; // keywords u32 text_len = parser_text_length(p); const char *text = parser_text(p); #if DO_PRINT formatln("[%i]'%s'", text_len, text); #endif if(text_len > 0) { /// test of container if(text[0] == '<') { if(text[text_len - 1] != '>') { return_code = CONFIG_PARSE_SECTION_TAG_NOT_CLOSED; return return_code; } /// if there are enough characters if(text_len > 3) { // if it's beginning of a container if(text[1] != '/') { // if already in a container if(cfr->in_container) { // this is bad return_code = CONFIG_PARSE_UNEXPECTED_SECTION_OPEN; return return_code; } // if tag is the correct one if((cfr->container_name_length == text_len - 2) && (memcmp(&text[1], cfr->container_name, cfr->container_name_length) == 0)) { #if DO_PRINT print("(EXPECTED)"); output_stream_write(termout, (const u8*)cfr->container_name, cfr->container_name_length); #endif // the container is the one we expected // use the callback telling the container is starting cfr->section_descriptor->vtbl->start(cfr->section_descriptor); cfr->expected_container = TRUE; } if(text_len - 2 > sizeof(cfr->current_container_name)) { return_code = CONFIG_PARSE_SECTION_TAG_NOT_CLOSED; // because it's too big return return_code; } memcpy(cfr->current_container_name, &text[1], text_len - 2); // copy between < > cfr->current_container_name_length = text_len - 2; #if DO_PRINT print("(CONTAINER)"); output_stream_write(termout, (const u8*)cfr->current_container_name, cfr->current_container_name_length); #endif // mark the container as OPEN cfr->in_container = TRUE; continue; } else // if it's end of a container { // if not in container if(!cfr->in_container) { // this is bad return_code = CONFIG_PARSE_UNEXPECTED_SECTION_CLOSE; return return_code; } // if((cfr->current_container_name_length == text_len - 3) && (memcmp(&text[2], cfr->current_container_name, cfr->current_container_name_length) == 0)) { if(cfr->expected_container) { // we are closing the container // if the current source level is below the set autodefault if(config_get_autodefault_after_source() <= config_get_source()) { // save the current source u8 level = config_get_source(); // set the source level to default config_set_source(config_get_default_source()); // apply the default values if(FAIL(return_code = config_set_section_default(cfr->section_descriptor, cfr->error_context))) { return return_code; } // restore the source level config_set_source(level); } // use the callback telling the section/container is closed if(FAIL(return_code = cfr->section_descriptor->vtbl->stop(cfr->section_descriptor))) { return return_code; } } #if DO_PRINT print("(container)"); if(cfr->expected_container) { print("(expected)"); } #endif cfr->in_container = FALSE; cfr->expected_container = FALSE; continue; } else { // this is bad return_code = CONFIG_PARSE_CLOSED_WRONG_SECTION; return return_code; } } } else { // this is bad return_code = CONFIG_PARSE_SECTION_TAG_TOO_SMALL; return return_code; } } else // the first char is not '<' : it's not a container tag { // if we are not in a container if(!cfr->in_container) { // keyword match : include file ? if(parse_word_match(text, text_len, "include", 7)) { char file_name[PATH_MAX]; if(FAIL(return_code = parser_copy_next_word(p, file_name, sizeof(file_name)))) { if(return_code != PARSER_BUFFER_TOO_SMALL) { return_code = CONFIG_PARSE_INCLUDE_EXPECTED_FILE_PATH; } else { return_code = CONFIG_FILE_PATH_TOO_BIG; } return return_code; } // return_code is the length of the path if(file_name[0] != '/') { // relative path if(FAIL(return_code = config_file_reader_prepend_path_from_file(file_name, cfr->file_name[cfr->includes_count - 1]))) { return return_code; } } if(return_code > 0) { ya_result err; if(ISOK(err = file_input_stream_open(&cfr->includes[cfr->includes_count], file_name))) { // add the file and its mtime to the context if(cfr->file_mtime_set != NULL) { file_mtime_set_add_file(cfr->file_mtime_set, file_name); } parser_push_stream(&cfr->parser, &cfr->includes[cfr->includes_count]); cfr->file_name[cfr->includes_count] = strdup(file_name); ++cfr->includes_count; token_count = 0; } else { if((err == MAKE_ERRNO_ERROR(ENOENT)) || (err == MAKE_ERRNO_ERROR(EACCES))) { err = CANNOT_OPEN_FILE; } return err; } } else { return_code = CONFIG_PARSE_INCLUDE_EXPECTED_FILE_PATH; return return_code; } } else // incorrect keyword { return_code = CONFIG_PARSE_UNKNOWN_KEYWORD; return return_code; } } else if(cfr->expected_container) // in container { // we are in a container : the current token is the key if(text_len - 1 > sizeof(cfr->key)) { return_code = CONFIG_KEY_PARSE_ERROR; return return_code; } memcpy(cfr->key, text, text_len); cfr->key_length = text_len; cfr->key[text_len] = '\0'; // concat the remainder of the line for the value if(FAIL(return_code = parser_concat_next_tokens(p))) { return_code = CONFIG_PARSE_EXPECTED_VALUE; return return_code; } // get the concatenated text text = parser_text(p); #if DO_PRINT text_len = parser_text_length(p); #else parser_text_length(p); #endif // cut the text as asciiz (state can be restored) parser_text_asciiz(p); #if DO_PRINT print("[KEY]"); output_stream_write(termout, (const u8*)cfr->key, cfr->key_length); print("[VALUE]"); output_stream_write(termout, (const u8*)text, text_len); println("[EOL]"); #endif // using the descriptor table : set the value in the target struct return_code = config_value_set(cfr->section_descriptor, cfr->key, text, cfgerr); // restore the character cut of parser_text_unasciiz(p); if(FAIL(return_code)) { return return_code; } } } } else { // empty line } #if DO_PRINT flushout(); #endif } else { formatln("[ERROR %r]", return_code); flushout(); break; } } // for(;;) return return_code; } /** * * Parses an input stream for a section/container defined by its config sectiondescriptor. * * @param stream_name a name to identify the stream in case of error * @param ins the input stream to parse * @param csd the descriptor of the section to parse * @param cfgerr if not NULL, the error reporting structure to fill in case of error * * @return an error code */ ya_result config_file_reader_parse_stream(const char* stream_name, input_stream *ins, config_section_descriptor_s *csd, config_error_s *cfgerr) { config_file_reader *cfr; /// remove ya_result return_code; file_mtime_set_t *file_mtime_set = file_mtime_set_get_for_file(stream_name); // allocates and initialises a config file reader structure MALLOC_OBJECT_OR_DIE(cfr, config_file_reader, CFREADER_TAG); ZEROMEMORY(cfr, sizeof(config_file_reader)); config_error_reset(cfgerr); cfr->error_context = cfgerr; cfr->file_mtime_set = file_mtime_set; // initalises a parser const char *string_delimiters = "\"\"''"; const char *multiline_delimiters = "()"; const char *comment_markers = "#"; const char *blank_makers = "\040\t\r"; const char *escape_characters = ""; if(ISOK(return_code = parser_init(&cfr->parser, string_delimiters, // by 2 multiline_delimiters, // by 2 comment_markers, // by 1 blank_makers, // by 1 escape_characters))) // by 1 { // the parser is initalised : push the stream to parse to it parser_push_stream(&cfr->parser, ins); if(stream_name == NULL) { // if the stream is anonymous, give it a name. stream_name = "?"; } cfr->file_name[cfr->includes_count] = strdup(stream_name); ++cfr->includes_count; cfr->container_name = csd->vtbl->name; cfr->container_name_length = strlen(cfr->container_name); // the csd describes the section we want to parse cfr->section_descriptor = csd; // the config file reader structure is now ready : parse the stream // parsing will setup fields described by the config section descriptor if(FAIL(return_code = config_file_reader_read(cfr, cfgerr))) { // failure: if the error reporting is set then use it if((cfgerr != NULL) && (cfr->includes_count > 0) && !cfgerr->has_content) { const char *file_name = cfr->file_name[cfr->includes_count - 1]; if(file_name == NULL) { file_name = "?"; } strcpy_ex(cfgerr->file, file_name, sizeof(cfgerr->file)); size_t len = MIN(strlen(cfr->parser.line_buffer), sizeof(cfgerr->line) - 1); memcpy(cfgerr->line, cfr->parser.line_buffer, len); if(cfgerr->line[len - 1] == '\n') { cfgerr->line[len - 1] = '\0'; } cfgerr->line_number = parser_get_line_number(&cfr->parser); cfgerr->has_content = TRUE; } } // ends parsing, this also closes the input stream pushed to the parser parser_finalize(&cfr->parser); } #if DEBUG memset(cfr, 0xfe, sizeof(config_file_reader)); #endif free(cfr); return return_code; } /** * * Parses a file for a section/container defined by its config sectiondescriptor. * * @param fullpath the file path * @param csd the descriptor of the section to parse * @param cfgerr if not NULL, the error reporting structure to fill in case of error * * @return an error code */ ya_result config_file_reader_open(const char* fullpath, config_section_descriptor_s *csd, config_error_s *cfgerr) { input_stream ins; ya_result return_value; if(FAIL(return_value = file_input_stream_open(&ins, fullpath))) { return return_value; } // add the file and its mtime to the context #if (DNSDB_USE_POSIX_ADVISE != 0) && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && !defined(__gnu__hurd__) int fd = fd_input_stream_get_filedescriptor(&ins); posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); #endif return_value = config_file_reader_parse_stream(fullpath, &ins, csd, cfgerr); return return_value; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/config_key.c0000644000000000000000000000013214505005532021611 xustar000000000000000030 mtime=1695812442.397981544 30 atime=1695812445.792030153 30 ctime=1695812494.503727803 yadifa-2.6.5-11201/lib/dnscore/src/config_key.c0000664000374500037450000001722514505005532021562 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include #include "dnscore/dnscore-config.h" #include "dnscore/tsig.h" #include "dnscore/base64.h" #include "dnscore/config_settings.h" #define CFGSKEY_TAG 0x59454b53474643 #define CSKEYTMP_TAG 0x504d5459454b5343 struct config_section_key_s { char name[256]; char algorithm[32]; char secret[BASE64_ENCODED_SIZE(64) + 1]; }; typedef struct config_section_key_s config_section_key_s; #define CONFIG_TYPE config_section_key_s CONFIG_BEGIN(config_section_key_desc) CONFIG_STRING_COPY(name, NULL) CONFIG_STRING_COPY(algorithm, NULL) CONFIG_STRING_COPY(secret, NULL) CONFIG_END(config_section_key_desc) #undef CONFIG_TYPE static ya_result config_section_key_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } static ya_result config_section_key_start(struct config_section_descriptor_s *csd) { // NOP //config_section_key_s *csk = (config_section_key_s*)csd->base; config_section_key_s *csk; MALLOC_OBJECT_OR_DIE(csk, config_section_key_s, CFGSKEY_TAG); csd->base = csk; csk->name[0] = '\0'; csk->algorithm[0] = '\0'; csk->secret[0] = '\0'; #if CONFIG_SETTINGS_DEBUG formatln("config: section: key: start"); #endif return SUCCESS; } static void config_section_key_delete(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { free(csd->base); } csd->base = NULL; } } static ya_result config_section_key_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key: stop"); #endif // NOP config_section_key_s *csk = (config_section_key_s*)csd->base; if( csk->name[0] == '\0' || csk->algorithm[0] == '\0' || csk->secret[0] == '\0' ) { if(csk->name[0] == '\0' && csk->algorithm[0] == '\0' && csk->secret[0] == '\0' ) { config_section_key_delete(csd); return SUCCESS; // empty key, ignored } else { config_section_key_delete(csd); return CONFIG_KEY_INCOMPLETE_KEY; } } // check if algorithm is supported ya_result ret; u32 hmac_digest; if(ISOK(ret = tsig_get_hmac_algorithm_from_friendly_name(csk->algorithm))) { hmac_digest = (u32)ret; } else { config_section_key_delete(csd); return CONFIG_KEY_UNSUPPORTED_ALGORITHM; } // decode the secret u32 secret_len; u32 len = strlen(csk->secret); u8 fqdn[MAX_DOMAIN_LENGTH]; u8 secret_buffer[512]; if(ISOK(ret = base64_decode(csk->secret, len, secret_buffer))) { secret_len = ret; if(ISOK(ret = cstr_to_dnsname_with_check(fqdn, csk->name))) { ret = tsig_register(fqdn, secret_buffer, secret_len, hmac_digest); } } config_section_key_delete(csd); #if CONFIG_SETTINGS_DEBUG formatln("tsig_register(%s,%s,%s) = %r", csk->name, csk->algorithm, csk->secret, ret); #endif return ret; } static ya_result config_section_key_postprocess(struct config_section_descriptor_s *csd) { (void)csd; return SUCCESS; } static ya_result config_section_key_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { config_section_key_delete(csd); free(csd); } return SUCCESS; } static ya_result config_section_key_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_key_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)key; u32* indexp; if(*context == NULL) { MALLOC_OBJECT_OR_DIE(indexp, u32, CSKEYTMP_TAG); *indexp = 0; *context = indexp; } else { indexp = (u32*)*context; } if(*indexp < tsig_get_count()) { /* CONFIG_STRING_COPY(name, NULL) CONFIG_STRING_COPY(algorithm, NULL) CONFIG_STRING_COPY(secret, NULL) */ tsig_item* tsig = tsig_get_at_index(*indexp); if(tsig != NULL) // shouldn't be { osformatln(os, "name %{dnsname}", tsig->name); osformatln(os, "algorithm %s", tsig_get_friendly_name_from_hmac_algorithm(tsig->mac_algorithm)); output_stream_write(os, "secret ", 10); base64_print(tsig->mac, tsig->mac_size, os); output_stream_write_u8(os, '\n'); } ++(*indexp); } else { free(indexp); *context = NULL; } return CONFIG_UNKNOWN_SETTING; } static const config_section_descriptor_vtbl_s config_section_key_descriptor_vtbl = { "key", config_section_key_desc, // no table config_section_key_set_wild, config_section_key_print_wild, config_section_key_init, config_section_key_start, config_section_key_stop, config_section_key_postprocess, config_section_key_finalize }; ya_result config_register_key(const char *null_or_key_name, s32 priority) { //null_or_key_name = "key"; (void)null_or_key_name; config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_key_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // no, there is no leak of desc, it is either put in the collection, either freed } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/config_logger.c0000644000000000000000000000013214505005532022300 xustar000000000000000030 mtime=1695812442.456982388 30 atime=1695812445.794030182 30 ctime=1695812494.505727831 yadifa-2.6.5-11201/lib/dnscore/src/config_logger.c0000664000374500037450000004206214505005532022246 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/logger.h" #include "dnscore/file_output_stream.h" #include "dnscore/logger_channel_stream.h" #include "dnscore/logger_channel_syslog.h" #include "dnscore/logger_channel_file.h" #include "dnscore/logger_channel_pipe.h" #include "dnscore/parsing.h" #include "dnscore/chroot.h" #include "dnscore/fdtools.h" #include "dnscore/config_settings.h" /** * Syslog levels */ #define SYSLOG_LEVEL_TOKEN_DELIMITER ",;:+" /** * Syslog channels */ #define SYSLOG_CHANNEL_TOKEN_DELIMITER "\t ,;:+" enum channel_type { CT_STDOUT, CT_STDERR, CT_SYSLOG, CT_FILE }; typedef enum channel_type channel_type; /* * CHANNELS is a dynamic section so there is no config_table */ #define FILE_CHANNEL_DEFAULT_ACCESS_RIGHTS 0644 static const value_name_table syslog_channel_arguments_options[] = { #ifdef LOG_CONS {LOG_CONS, "cons"}, #endif #ifdef LOG_NDELAY {LOG_NDELAY, "ndelay"}, #endif #ifdef LOG_NOWAIT {LOG_NOWAIT, "nowait"}, #endif #ifdef LOG_ODELAY {LOG_ODELAY, "odelay"}, #endif #ifdef LOG_PERROR {LOG_PERROR, "perror"}, #endif #ifdef LOG_PID {LOG_PID, "pid"}, #endif {0, NULL} }; static const value_name_table syslog_channel_arguments_facility[] = { #ifdef LOG_AUTH {LOG_AUTH, "auth"}, #endif #ifdef LOG_AUTHPRIV {LOG_AUTHPRIV, "authpriv"}, #endif #ifdef LOG_CRON {LOG_CRON, "cron"}, #endif #ifdef LOG_DAEMON {LOG_DAEMON, "daemon"}, #endif #ifdef LOG_FTP {LOG_FTP, "ftp"}, #endif /* This is forbidden for anybody but the kernel. #ifdef LOG_KERN {LOG_KERN, "kern"}, #endif */ #ifdef LOG_LOCAL0 {LOG_LOCAL0, "local0"}, #endif #ifdef LOG_LOCAL1 {LOG_LOCAL1, "local1"}, #endif #ifdef LOG_LOCAL2 {LOG_LOCAL2, "local2"}, #endif #ifdef LOG_LOCAL3 {LOG_LOCAL3, "local3"}, #endif #ifdef LOG_LOCAL4 {LOG_LOCAL4, "local4"}, #endif #ifdef LOG_LOCAL5 {LOG_LOCAL5, "local5"}, #endif #ifdef LOG_LOCAL6 {LOG_LOCAL6, "local6"}, #endif #ifdef LOG_LOCAL7 {LOG_LOCAL7, "local7"}, #endif #ifdef LOG_LPR {LOG_LPR, "lpr"}, #endif #ifdef LOG_MAIL {LOG_MAIL, "mail"}, #endif #ifdef LOG_NEWS {LOG_NEWS, "news"}, #endif #ifdef LOG_SYSLOG {LOG_SYSLOG, "syslog"}, #endif #ifdef LOG_USER {LOG_USER, "user"}, #endif #ifdef LOG_UUCP {LOG_UUCP, "uucp"}, #endif {0, NULL} }; static const value_name_table logger_debuglevels[] = { {1 << MSG_EMERG, "emerg"}, {1 << MSG_ALERT, "alert"}, {1 << MSG_CRIT, "crit"}, {1 << MSG_ERR, "err"}, {1 << MSG_WARNING, "warning"}, {1 << MSG_NOTICE, "notice"}, {1 << MSG_INFO, "info"}, {1 << MSG_DEBUG, "debug"}, {1 << MSG_DEBUG1, "debug1"}, {1 << MSG_DEBUG2, "debug2"}, {1 << MSG_DEBUG3, "debug3"}, {1 << MSG_DEBUG4, "debug4"}, {1 << MSG_DEBUG5, "debug5"}, {1 << MSG_DEBUG6, "debug6"}, {1 << MSG_DEBUG7, "debug7"}, {(1 << (MSG_ALL + 1)) - 1, "all"}, {(1 << (MSG_ALL + 1)) - 1, "*"}, {(1 << MSG_EMERG)|(1 << MSG_ALERT)|(1 << MSG_CRIT)|(1 << MSG_ERR)|(1 << MSG_WARNING)|(1 << MSG_NOTICE)|(1 << MSG_INFO), "prod"}, {0, NULL} }; static const char DEFAULT_PATH[] = ""; static const char *log_path = DEFAULT_PATH; static bool logger_section_found = FALSE; void config_set_log_base_path(const char *path) { if(path != NULL) { if(strcmp(path, log_path) == 0) { return; } log_path = strdup(path); } else { if(log_path != DEFAULT_PATH) { free((char*)log_path); } log_path = DEFAULT_PATH; } } static ya_result config_section_handles_init(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_handles_start(struct config_section_descriptor_s *csd) { // NOP (void)csd; logger_section_found = TRUE; //logger_channel_close_all(); return SUCCESS; } static ya_result config_section_handles_stop(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_handles_postprocess(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_handles_finalize(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_handles_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { if(logger_channel_get_usage_count(key) >= 0) { return CONFIG_LOGGER_HANDLE_ALREADY_DEFINED; // already defined } char value_target[PATH_MAX]; parse_copy_word(value_target, sizeof(value_target), value); if(strcasecmp("stdout", value_target) == 0) { output_stream stdout_os; fd_output_stream_attach(&stdout_os, dup_ex(1)); logger_channel *stdout_channel = logger_channel_alloc(); logger_channel_stream_open(&stdout_os, FALSE, stdout_channel); logger_channel_register(key, stdout_channel); } else if(strcasecmp("stderr", value_target) == 0) { output_stream stderr_os; fd_output_stream_attach(&stderr_os, dup_ex(2)); logger_channel *stderr_channel = logger_channel_alloc(); logger_channel_stream_open(&stderr_os, FALSE, stderr_channel); logger_channel_register(key, stderr_channel); } else if(strcasecmp("syslog", value_target) == 0) { char* token; /* * Tokenize */ u32 options = 0; u32 facility = 0; /* WARNING: NEVER EVER USE A CONST STRING AS ARGUMENT OR strtok WILL SIGSEGV */ char *tmp_value = strdup(value); // value, not value_target for(token = strtok(tmp_value, SYSLOG_CHANNEL_TOKEN_DELIMITER); token != NULL; token = strtok(NULL, SYSLOG_CHANNEL_TOKEN_DELIMITER)) { u32 token_value; if(ISOK(value_name_table_get_value_from_casename(syslog_channel_arguments_options, token, &token_value))) { options |= token_value; } else if(ISOK(value_name_table_get_value_from_casename(syslog_channel_arguments_facility, token, &token_value))) { facility = token_value; // Facility is NOT a bit mask } else { /* Note: empty statement is taken care of here */ osformatln(termerr, "wrong syslog argument '%s' : ", csd->vtbl->name); free(tmp_value); return PARSE_INVALID_ARGUMENT; } } free(tmp_value); logger_channel *syslog_channel = logger_channel_alloc(); logger_channel_syslog_open(key, options, facility, syslog_channel); logger_channel_register(key, syslog_channel); } else { #if __unix__ const char *chroot_base = chroot_get_path(); uid_t uid = logger_get_uid(); gid_t gid = logger_get_gid(); ya_result return_code; unsigned int access_rights; char fullpath[PATH_MAX]; // find the end of the word // cut it const char *path_limit = parse_next_blank(value); size_t path_len = path_limit - value; size_t pathbase_len; if(value[0] != '|') { if(value[0] != '/') { pathbase_len = snformat(fullpath, sizeof(fullpath), "%s%s", chroot_base, log_path); } else { pathbase_len = snformat(fullpath, sizeof(fullpath), "%s", chroot_base); } if(pathbase_len + path_len + 1 >= sizeof(fullpath)) { return CONFIG_FILE_PATH_TOO_BIG; } memcpy(&fullpath[pathbase_len], value, path_len); path_len += pathbase_len; fullpath[path_len] = '\0'; // parse the next word, it is supposed to be an octal number #if 1 errno = 0; access_rights = strtol(path_limit, NULL, 8); if(errno != 0) { access_rights = FILE_CHANNEL_DEFAULT_ACCESS_RIGHTS; } #else if(sscanf(path_limit, "%o", &access_rights) != 1) { access_rights = FILE_CHANNEL_DEFAULT_ACCESS_RIGHTS; } #endif bool sync = FALSE; // if the path starts with a slash, it's absolute, else it's relative // to the log directory logger_channel* file_channel = logger_channel_alloc(); if(FAIL(return_code = logger_channel_file_open(fullpath, uid, gid, access_rights, sync, file_channel))) { osformatln(termerr, "config: unable to open file channel '%s' (%d:%d %o) : %r", fullpath, uid, gid, access_rights, return_code); flusherr(); return return_code; } logger_channel_register(key, file_channel); } else { ++value; logger_channel* file_channel = logger_channel_alloc(); if(FAIL(return_code = logger_channel_pipe_open(value, FALSE, file_channel))) { osformatln(termerr, "config: unable to open pipe channel '%s' : %r", fullpath, return_code); flusherr(); return return_code; } logger_channel_register(key, file_channel); } #else osformatln(termerr, "config: pipes not supported"); return ERROR; #endif } return SUCCESS; } static ya_result config_section_handles_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)key; (void)context; return FEATURE_NOT_IMPLEMENTED_ERROR; } static ya_result config_section_loggers_init(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_loggers_start(struct config_section_descriptor_s *csd) { // NOP (void)csd; logger_section_found = TRUE; // clear all loggers return SUCCESS; } static ya_result config_section_loggers_stop(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_loggers_postprocess(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_loggers_finalize(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_loggers_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; u32 debuglevel = 0; ya_result return_code; // next word(base,delimiter) // bool end_of_level = FALSE; do { char level[16]; value = parse_skip_spaces(value); if(*value == '\0') { break; } if(FAIL(return_code = parse_next_token(level, sizeof(level), value, SYSLOG_LEVEL_TOKEN_DELIMITER))) { return return_code; } // if the token has spaces between two chars, then we need to cut char *end_of_first_word = (char*)parse_next_blank(level); // level is not const if(*end_of_first_word != '\0') { char *start_of_next_word = (char*)parse_skip_spaces(end_of_first_word); // end_of_first_word is not const if(start_of_next_word != end_of_first_word) { // last loop iteration end_of_level = TRUE; } *end_of_first_word = '\0'; // adjust next word search start value += end_of_first_word - level + 1; } else { value += (size_t)return_code + 1; // note: false positive from cppcheck } // u32 debuglevel_value; if(FAIL(value_name_table_get_value_from_casename(logger_debuglevels, level, &debuglevel_value))) { return CONFIG_LOGGER_INVALID_DEBUGLEVEL; } debuglevel |= debuglevel_value; } while(!end_of_level); for(;;) { char channel_name[64]; value = parse_skip_spaces(value); if(*value == '\0') { break; } if(FAIL(return_code = parse_next_token(channel_name, sizeof(channel_name), value, SYSLOG_CHANNEL_TOKEN_DELIMITER))) { return return_code; } if(*channel_name == '\0') { continue; } logger_handle_add_channel(key, (int)debuglevel, channel_name); value += return_code; if(*value == '\0') { break; } value++; } return SUCCESS; } static ya_result config_section_loggers_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)key; (void)context; return FEATURE_NOT_IMPLEMENTED_ERROR; } static const config_section_descriptor_vtbl_s config_section_handles_descriptor_vtbl = { "channels", // no table NULL, config_section_handles_set_wild, config_section_handles_print_wild, config_section_handles_init, config_section_handles_start, config_section_handles_stop, config_section_handles_postprocess, config_section_handles_finalize }; static const config_section_descriptor_s config_section_handles_descriptor = { NULL, &config_section_handles_descriptor_vtbl }; static const config_section_descriptor_vtbl_s config_section_loggers_descriptor_vtbl = { "loggers", NULL, // no table config_section_loggers_set_wild, config_section_loggers_print_wild, config_section_loggers_init, config_section_loggers_start, config_section_loggers_stop, config_section_loggers_postprocess, config_section_loggers_finalize }; static const config_section_descriptor_s config_section_loggers_descriptor = { NULL, &config_section_loggers_descriptor_vtbl }; /// register the logging configuration /// note that for this to work, logger_handle_create("handle-name",logger_handle_for_handle_name_ptr_ptr) /// must be called before the config_read is done ya_result config_register_logger(const char *null_or_channels_name, const char *null_or_loggers_name, s32 priority) { //null_or_channels_name = "channels"; //null_or_loggers_name = "loggers"; (void)null_or_channels_name; (void)null_or_loggers_name; if(priority < 0) { priority = 0; } ya_result return_code; if(ISOK(return_code = config_register_const(&config_section_handles_descriptor, priority + 0))) { return_code = config_register_const(&config_section_loggers_descriptor, priority + 1); } return return_code; } bool config_logger_isconfigured() { return logger_section_found; } void config_logger_clearconfigured() { logger_section_found = FALSE; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/config_settings.c0000644000000000000000000000013114505005532022660 xustar000000000000000030 mtime=1695812442.467982546 30 atime=1695812445.795030196 29 ctime=1695812494.50772786 yadifa-2.6.5-11201/lib/dnscore/src/config_settings.c0000664000374500037450000023445014505005532022633 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * @{ */ #include "dnscore/dnscore-config.h" #include #include #include #if __unix__ #include #include #endif #include #include "dnscore/config_settings.h" #include "dnscore/cmdline.h" #include "dnscore/acl-config.h" #include "dnscore/logger.h" #include "dnscore/base64.h" #include "dnscore/u32_set.h" #include "dnscore/parsing.h" #include "dnscore/tsig.h" #include "dnscore/file_input_stream.h" #include "dnscore/bytearray_input_stream.h" #include "dnscore/config_settings.h" #include "dnscore/config_file_reader.h" #include "dnscore/chroot.h" #include "dnscore/ptr_set.h" #include "dnscore/host_address.h" #define MODULE_MSG_HANDLE g_system_logger #define UIDNAME_TAG 0x454d414e444955 #define GIDNAME_TAG 0x454d414e444947 /** * This collection links configuration parsing functions to printing functions. * Used for extensions (ie: ACL) */ static ptr_set config_section_struct_type_handler_set = PTR_SET_PTR_EMPTY; static ptr_set on_section_read_callback_set = PTR_SET_ASCIIZ_EMPTY; /** * These two union are used to store functions ptrs as void* in the collections * The pointer sizes are supposed to be equal (else dnscore will fail at init) * * In the event the code has to be compiled on an architecture where void* and void (*f)() are * of different size, it will still be time to make a structure that has function pointers for key and value. */ union config_set_field_function_as_voidp { config_set_field_function *setter; void *ptr; }; typedef union config_set_field_function_as_voidp config_set_field_function_as_voidp; union config_section_struct_type_handler_as_voidp { config_section_struct_type_handler *handler; void *ptr; }; typedef union config_section_struct_type_handler_as_voidp config_section_struct_type_handler_as_voidp; static const char *config_error_prefix = "config: "; static const value_name_table true_false_enum[]= { {1, "yes"}, {1, "1"}, {1, "enable"}, {1, "enabled"}, {1, "on"}, {1, "true"}, {0, "no"}, {0, "0"}, {0, "disable"}, {0, "disabled"}, {0, "off"}, {0, "false"}, {0, NULL} }; static u32_set section_descriptor_set = U32_SET_EMPTY; static u8 config_current_source = CONFIG_SOURCE_NONE; static u8 config_autodefault_after_source = CONFIG_SOURCE_FILE; static u8 config_default_source = CONFIG_SOURCE_DEFAULT; static bool config_init_error_codes_done = FALSE; union code_data_ptr { config_callback_function *function; void *data; intptr value; }; typedef union code_data_ptr code_data_ptr; ya_result config_add_on_section_read_callback(const char *section_name, config_callback_function *on_section_read) { ptr_node *node = ptr_set_insert(&on_section_read_callback_set, (char*)section_name); if(node->value != NULL) { return CONFIG_SECTION_CALLBACK_ALREADY_SET; // already exists } node->key = strdup(section_name); code_data_ptr ptr = {.function = on_section_read}; node->value = ptr.data; return SUCCESS; } ya_result config_remove_on_section_read_callback(const char *section_name, config_callback_function *on_section_read) { if(section_name == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } ptr_node *node = ptr_set_find(&on_section_read_callback_set, section_name); if(node != NULL) { code_data_ptr ptr = {.function = on_section_read}; if(node->value != ptr.data) { return CONFIG_SECTION_CALLBACK_NOT_FOUND; // not the right one } free(node->key); ptr_set_delete(&on_section_read_callback_set, section_name); return SUCCESS; } else { return CONFIG_SECTION_CALLBACK_NOT_SET; } } static ya_result config_fire_on_section_read_callback(const char *section_name, int index) { ya_result return_code = SUCCESS; ptr_node *node = ptr_set_find(&on_section_read_callback_set, section_name); if(node != NULL) { code_data_ptr ptr = {.data = node->value}; config_callback_function *on_section_read = ptr.function; if(on_section_read != NULL) { return_code = on_section_read(section_name, index); } else { return_code = CONFIG_SECTION_ERROR; } } return return_code; } /** @brief Yes or No option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_bool(const char *value, bool *dest, const anytype notused) { (void)notused; ya_result return_code; u32 integer_value; bool yes_or_no; if(ISOK(return_code = value_name_table_get_value_from_casename(true_false_enum, value, &integer_value))) { yes_or_no = (integer_value != 0); *dest = yes_or_no; } return return_code; } /** @brief flag option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_flag8(const char *value, u8 *dest, const anytype mask8) { ya_result return_code; bool b; if(ISOK(return_code = config_set_bool(value, &b, mask8))) { if(b) { *dest |= mask8._u8; } else { *dest &= ~mask8._u8; } } return return_code; } /** @brief flag option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_flag16(const char *value, u16 *dest, const anytype mask16) { ya_result return_code; bool b; if(ISOK(return_code = config_set_bool(value, &b, mask16))) { if(b) { *dest |= mask16._u16; } else { *dest &= ~mask16._u16; } } return return_code; } /** @brief flag option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_flag32(const char *value, u32 *dest, const anytype mask32) { ya_result return_code; bool b; if(ISOK(return_code = config_set_bool(value, &b, mask32))) { if(b) { *dest |= mask32._u32; } else { *dest &= ~mask32._u32; } } return return_code; } /** @brief flag option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_flag64(const char *value, u64 *dest, const anytype mask64) { ya_result return_code; bool b; if(ISOK(return_code = config_set_bool(value, &b, mask64))) { if(b) { *dest |= mask64._u64; } else { *dest &= ~mask64._u64; } } return return_code; } /** @brief Integer option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_u64(const char *value,u64 *dest, const anytype notused) { (void)notused; errno = 0; char *first_invalid = NULL; s64 tmp = strtoll(value, &first_invalid, 10); int err = errno; if(err == 0) { *dest = (u64)tmp; return SUCCESS; } else { return MAKE_ERRNO_ERROR(err); } } /** @brief Integer option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_u32(const char *value,u32 *dest, const anytype notused) { (void)notused; errno = 0; char *first_invalid = NULL; s64 tmp = strtoll(value, &first_invalid, 10); int err = errno; if(err == 0) { if((tmp >= 0) && (tmp <= MAX_U32)) { *dest = (u32)tmp; return SUCCESS; } else { return MAKE_ERRNO_ERROR(EOVERFLOW); } } else { return MAKE_ERRNO_ERROR(err); } } /** @brief Integer option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_s32(const char *value, s32 *dest, const anytype notused) { (void)notused; errno = 0; char *first_invalid = NULL; s64 tmp = strtoll(value, &first_invalid, 10); int err = errno; if(err == 0) { if((tmp >= MIN_S32) && (tmp <= MAX_S32)) { *dest = (s32)tmp; return SUCCESS; } else { return MAKE_ERRNO_ERROR(EOVERFLOW); } } else { return MAKE_ERRNO_ERROR(err); } } /** @brief Integer option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_u32_range(const char *value,u32 *dest, const anytype range) { errno = 0; char *first_invalid = NULL; s64 tmp = strtoll(value, &first_invalid, 10); int err = errno; if(err == 0) { if(tmp >= range._2u32[0] && tmp <= range._2u32[1]) { *dest = (u32)tmp; return SUCCESS; } else { return CONFIG_VALUE_OUT_OF_RANGE; } } else { return MAKE_ERRNO_ERROR(err); } } /** @brief Integer option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_u32_clamp(const char *value,u32 *dest, const anytype range) { errno = 0; char *first_invalid = NULL; s64 tmp = strtoll(value, &first_invalid, 10); int err = errno; if(err == 0) { if(tmp < range._2u32[0]) { tmp = range._2u32[0]; } else if(tmp > range._2u32[1]) { tmp = range._2u32[1]; } *dest = (u32)tmp; return SUCCESS; } else { return MAKE_ERRNO_ERROR(err); } } /** @brief Integer option value parser * * @param[in] value in asciiz * @param[out] dest to the value * * @retval OK * @retval NOK */ ya_result config_set_u16(const char *value,u16 *dest, const anytype notused) { (void)notused; errno = 0; char *first_invalid = NULL; s64 tmp = strtoll(value, &first_invalid, 10); int err = errno; if(err == 0) { if((tmp >= 0) && (tmp <= MAX_U16)) { *dest = (u16)tmp; return SUCCESS; } else { return MAKE_ERRNO_ERROR(EOVERFLOW); } } else { return MAKE_ERRNO_ERROR(err); } } ya_result config_set_u8(const char *value,u8 *dest, const anytype notused) { (void)notused; errno = 0; char *first_invalid = NULL; s64 tmp = strtoll(value, &first_invalid, 10); int err = errno; if(err == 0) { if((tmp >= 0) && (tmp <= MAX_U8)) { *dest = (u8)tmp; return SUCCESS; } else { return MAKE_ERRNO_ERROR(EOVERFLOW); } } else { return MAKE_ERRNO_ERROR(err); } } ya_result config_inc_u8(const char *value_notused,u8 *dest, const anytype notused) { (void)value_notused; (void)notused; (*dest)++; return OK; } ya_result config_set_dnskey_algorithm(const char *value, u8 *dest, const anytype notused) { (void)notused; ya_result ret; u32 val; if(FAIL(ret = parse_u32_check_range(value, &val, 1, 255, BASE_10))) { ret = dns_encryption_algorithm_from_case_name(value, dest); } else { *dest = (u8)val; } return ret; } /** @brief String parser * * @param[in] value * @param[in] config_command * @param[out] config * * @retval OK * @retval NOK */ ya_result config_set_string(const char *value, char **dest, const anytype notused) { (void)notused; if(*dest != NULL) { if(strcmp(*dest, value) != 0) { free(*dest); *dest = strdup(value); } } else { *dest = strdup(value); } return OK; } /** @brief String parser * * @param[in] value * @param[in] config_command * @param[out] config * * @retval OK * @retval NOK */ ya_result config_set_string_copy(const char *value, char *dest, const anytype maxlen) { size_t len = strlen(value); if(len > maxlen._u32 - 1) { return CONFIG_TEXT_LENGTH_TOO_BIG; } memcpy(dest, value, len); dest[len] = '\0'; return len + 1; } /** @brief String parser * * @param[in] value * @param[in] config_command * @param[out] config * * @retval OK * @retval NOK */ ya_result config_append_string_array_item(const char *value, ptr_vector *dest, const anytype maxsize) { if(ptr_vector_size(dest) >= maxsize._s32) { return CONFIG_ARRAY_SIZE_TOO_BIG; } if(value != NULL) { ptr_vector_append(dest, strdup(value)); } return ptr_vector_size(dest); } /** @brief Password parser * * @param[in] value * @param[in] config_command * @param[out] config * * @retval OK * @retval NOK */ ya_result config_set_password(const char *value, char **dest, const anytype notused) { (void)notused; if(*dest != NULL) { if(strcmp(*dest, value) != 0) { size_t n = strlen(*dest); for(size_t i = 0; i < n; i++) { *dest[i] = rand(); } free(*dest); *dest = strdup(value); } } else { *dest = strdup(value); } return SUCCESS; } /** @brief String parser * * @param[in] value * @param[in] config_command * @param[out] config * * @retval OK * @retval NOK */ ya_result config_set_fqdn(const char *value, u8 **dest, const anytype notused) { (void)notused; ya_result return_value; u8 tmp[MAX_DOMAIN_LENGTH]; return_value = cstr_to_dnsname(tmp, value); if(ISOK(return_value)) { if(*dest != NULL) { if(!dnsname_equals(*dest, tmp)) { free(*dest); *dest = dnsname_dup(tmp); } } else { *dest = dnsname_dup(tmp); } } return return_value; } /** @brief Path parser * * Ensures that the stored value ends with '/' * * @param[in] value * @param[in] config_command * @param[out] config * * @retval OK * @retval NOK */ ya_result config_set_path(const char *value, char **dest, const anytype notused) { (void)notused; size_t len = strlen(value); if(*dest != NULL) { size_t dest_len = strlen(*dest); if(value[len - 1] != '/') { if(dest_len == len + 1) // implies last char of *dest is '/' { if(memcmp(*dest, value, len) == 0) { return SUCCESS; } } } else { if(strcmp(*dest, value) == 0) { return SUCCESS; } } free(*dest); *dest = NULL; } if(value[len - 1] != '/') { char *tmp = (char*)malloc(len + 2); if(tmp != NULL) { memcpy(tmp, value, len); tmp[len] = '/'; tmp[len + 1] = '\0'; *dest = tmp; } else { return MAKE_ERRNO_ERROR(ENOMEM); } } else { if((*dest = strdup(value)) == NULL) { return MAKE_ERRNO_ERROR(ENOMEM); } } return SUCCESS; } ya_result config_set_logpath(const char *value, char **dest, const anytype notused) { ya_result return_code; if(ISOK(return_code = config_set_path(value, dest, notused))) { config_set_log_base_path(*dest); } return return_code; } ya_result config_set_chroot(const char *value, char **dest, const anytype notused) { (void)notused; ya_result return_code; #if __unix__ if(ISOK(return_code = config_set_path(value, dest, notused))) { return_code = chroot_set_path(*dest); //chdir(*dest); } return return_code; #else return FEATURE_NOT_IMPLEMENTED_ERROR; #endif } ya_result config_set_file(const char *value, char **dest, const anytype notused) { (void)notused; struct stat fileinfo; if(stat(value, &fileinfo) < 0) { int err = ERRNO_ERROR; if(err == MAKE_ERRNO_ERROR(ENOENT)) { return CONFIG_FILE_NOT_FOUND; } else { return ERRNO_ERROR; } } /* Is it a regular file */ if(!S_ISREG(fileinfo.st_mode)) { return CONFIG_NOT_A_REGULAR_FILE; } if(*dest != NULL) { if(strcmp(*dest, value) != 0) { free(*dest); *dest = strdup(value); } } else { *dest = strdup(value); } return SUCCESS; } /** @brief UID parser * * @param[in] value * @param[in] config_command * @param[out] config * * @retval OK * @retval CONFIG_BAD_UID */ ya_result config_set_uid_t(const char *value, uid_t *dest, const anytype notused) { (void)notused; #if __unix__ if((*value == '\0') || (strcmp(value, "-") == 0)) { *dest = getuid(); } else { struct passwd pwd; struct passwd *result; char *buffer; long buffer_size = sysconf(_SC_GETPW_R_SIZE_MAX); /* * This fix has been made for FreeBSD that returns -1 for the above call */ if(buffer_size < 0) { buffer_size = 1024; } MALLOC_OR_DIE(char*, buffer, buffer_size, UIDNAME_TAG); getpwnam_r(value,&pwd,buffer,buffer_size,&result); *dest = pwd.pw_uid; free(buffer); if(result == NULL) { u32 val; if(FAIL(parse_u32_check_range(value, &val, 0, MAX_U32, BASE_10))) { return CONFIG_BAD_UID; } *dest = val; } } #endif return SUCCESS; } /** @brief GID parser * * @param[in] value * @param[in] config_command * @param[out] config * * @retval OK * @retval CONFIG_BAD_GID */ ya_result config_set_gid_t(const char *value, gid_t *dest, const anytype notused) { #if __unix__ (void)notused; if((*value == '\0') || (strcmp(value, "-") == 0)) { *dest = getgid(); } else { struct group grp; struct group *result; char *buffer; long buffer_size = sysconf(_SC_GETGR_R_SIZE_MAX); /* * This fix has been made for FreeBSD that returns -1 for the above call */ if(buffer_size < 0) { buffer_size = 1024; } MALLOC_OR_DIE(char*, buffer, buffer_size, GIDNAME_TAG); getgrnam_r(value, &grp, buffer, buffer_size, &result); *dest = grp.gr_gid; free(buffer); if(result == NULL) { u32 val; if(FAIL(parse_u32_check_range(value, &val, 0, MAX_U32, BASE_10))) { return CONFIG_BAD_GID; } *dest = val; } } #endif return SUCCESS; } ya_result config_set_dnsclass(const char *value, u16 *dest, const anytype notused) { (void)notused; u16 qclass; if(FAIL(dns_class_from_case_name(value, &qclass))) { return NOK; } *dest = ntohs(qclass); return OK; } ya_result config_set_dnstype(const char *value, u16 *dest, const anytype notused) { (void)notused; u16 qtype; if(FAIL(dns_type_from_case_name(value, &qtype))) { return NOK; } *dest = ntohs(qtype); return OK; } ya_result config_set_enum_value(const char *value, u32 *dest, const anytype enum_value_name_table) { ya_result return_code; u32 integer_value; value_name_table *table = (value_name_table*)enum_value_name_table._voidp; if(ISOK(return_code = value_name_table_get_value_from_casename(table, value, &integer_value))) { *dest = integer_value; } return return_code; } ya_result config_set_enum8_value(const char *value, u8 *dest, const anytype enum_value_name_table) { ya_result return_code; u32 integer_value; value_name_table *table = (value_name_table*)enum_value_name_table._voidp; if(ISOK(return_code = value_name_table_get_value_from_casename(table, value, &integer_value))) { *dest = integer_value; } return return_code; } /* * IP port n, */ ya_result config_set_host_list(const char *value, host_address **dest, const anytype settings) { if(value == NULL) /* nothing to do */ { return UNEXPECTED_NULL_ARGUMENT_ERROR; } ya_result return_code; const char *from = value; u16 ip_port = 0; #if DNSCORE_HAS_TSIG_SUPPORT tsig_item *tsig = NULL; #endif u8 ip_size; u8 host_type = HOST_ADDRESS_NONE; bool eol = (*from == '\0'); u8 flags = settings._8u8[0]; u8 ip_buffer[MAX_DOMAIN_LENGTH]; if(! (flags & CONFIG_HOST_LIST_FLAGS_APPEND)) { /* delete the content of the list */ if(*dest != NULL) { host_address_delete_list(*dest); *dest = NULL; } } else { /* find the last node of the list so the new ones will be append */ u32 counter = 0; while(*dest != NULL) { counter++; dest = &(*dest)->next; } if(counter > settings._8u8[1]) { return CONFIG_TOO_MANY_HOSTS; } } while(!eol) { /* skip the white spaces */ from = (char*)parse_skip_spaces(from); const char *to = from; /* get the end of statement */ to = (char*)parse_skip_until_chars(to, ",;", 2); if(to == from) { /* No new statement */ break; } eol = (*to == '\0'); /* now skip from until space */ const char *port_or_key = from; port_or_key = (char*)parse_next_space(port_or_key); const char *next_word = port_or_key; next_word = parse_skip_spaces(next_word); bool ip_only = (next_word >= to); port_or_key = MIN(port_or_key, to); host_type = HOST_ADDRESS_NONE; if(FAIL(return_code = parse_ip_address(from, port_or_key - from, ip_buffer, sizeof(ip_buffer)))) { if(! (flags & CONFIG_HOST_LIST_FLAGS_FQDN)) { return CONFIG_FQDN_NOT_ALLOWED; } if(FAIL(return_code = cstr_to_dnsname_with_check_len(ip_buffer, from, port_or_key - from))) { return return_code; } host_type = HOST_ADDRESS_DNAME; } ip_size = (u8)return_code; if(ip_size == 4) { if(! (flags & CONFIG_HOST_LIST_FLAGS_IPV4)) { return CONFIG_IPV4_NOT_ALLOWED; } host_type = HOST_ADDRESS_IPV4; } if(ip_size == 16) { if(! (flags & CONFIG_HOST_LIST_FLAGS_IPV6)) { return CONFIG_IPV6_NOT_ALLOWED; } host_type = HOST_ADDRESS_IPV6; } ip_port = 0; #if DNSCORE_HAS_TSIG_SUPPORT tsig = NULL; #endif if(!ip_only) { /* parse & skip 'port */ bool got_one = FALSE; u8 key_dnsname[MAX_DOMAIN_LENGTH + 1]; #if DNSCORE_HAS_TSIG_SUPPORT char key_name[MAX_DOMAIN_TEXT_LENGTH + 1]; #endif static const char *port_word="port"; static const char *key_word="key"; /// get PORT if(ISOK(return_code = parse_skip_word_specific(port_or_key, to-port_or_key, &port_word, 1, NULL))) { if(!(flags & CONFIG_HOST_LIST_FLAGS_PORT)) { return CONFIG_PORT_NOT_ALLOWED; } next_word = parse_skip_spaces(&port_or_key[return_code]); u32 port_value; if(FAIL(return_code = parse_u32_check_range(next_word, &port_value, 1, MAX_U16, BASE_10))) { /* parse error, expected something */ log_err("%sport parse error around '%s'", config_error_prefix, next_word); return CONFIG_EXPECTED_VALID_PORT_VALUE; } next_word = parse_next_space(next_word); next_word = MIN(next_word, to); port_or_key = next_word; ip_port = (u16)port_value; got_one = TRUE; } /// get KEY if(ISOK(return_code = parse_skip_word_specific(port_or_key, to-port_or_key, &key_word, 1, NULL))) { #if DNSCORE_HAS_TSIG_SUPPORT if(!(flags & CONFIG_HOST_LIST_FLAGS_TSIG)) { return CONFIG_TSIG_NOT_ALLOWED; } const char *key_name_start = parse_skip_spaces(&port_or_key[return_code]); key_name_start = (char*)parse_skip_spaces(key_name_start); next_word = key_name_start; next_word = (char*)parse_next_space(next_word); next_word = MIN(next_word, to); //port_or_key = next_word; size_t key_name_len = next_word - key_name_start; if(key_name_len < MAX_DOMAIN_TEXT_LENGTH) { memcpy(key_name, key_name_start, key_name_len); key_name[key_name_len] = '\0'; //*next_word++ = '\0'; port_or_key = next_word; if(ISOK(return_code = cstr_to_dnsname_with_check(key_dnsname, key_name))) { tsig = tsig_get(key_dnsname); if(tsig == NULL) { log_err("%skey '%s' has not been defined",config_error_prefix ,key_name); return CONFIG_KEY_UNKNOWN; } got_one = TRUE; } else { log_err("%skey name parse error around '%s': %r",config_error_prefix , key_name, return_code); return CONFIG_KEY_PARSE_ERROR; } } else { log_err("%skey name is too big",config_error_prefix ); return CONFIG_KEY_PARSE_ERROR; } #else #endif } if(!got_one) { log_err("%sgarbage around '%s'",config_error_prefix , port_or_key); /* parse error, expected something */ return CONFIG_KEY_PARSE_ERROR; } } /* * Now we can add a host structure node */ host_address *address; //MALLOC_OBJECT_OR_DIE(address, host_address, HOSTADDR_TAG); //address->next = NULL; address = host_address_alloc(); // sets version=0, next = NULL, tsig = NULL #if DNSCORE_HAS_TSIG_SUPPORT address->tsig = tsig; #endif switch(host_type) { case HOST_ADDRESS_IPV4: { host_address_set_ipv4(address, ip_buffer, htons(ip_port)); break; } case HOST_ADDRESS_IPV6: { host_address_set_ipv6(address, ip_buffer, htons(ip_port)); break; } case HOST_ADDRESS_DNAME: { host_address_set_dname(address, ip_buffer, htons(ip_port)); break; } case HOST_ADDRESS_NONE: { host_address_delete(address); return PARSEIP_ERROR; } } *dest = address; dest = &address->next; from = to + 1; } return SUCCESS; } /* * obfuscated format: something used by the server to store information * that it needs as is. (ie: dynamic provisioning related fields) * * 01 83 [flags] [serial] [checksum] */ ya_result config_set_bytes(const char *value, void *dest, const anytype sizeoftarget) { (void)dest; (void)sizeoftarget; ya_result return_value; return_value = base64_decode(value, /*sizeoftarget._u32*/strlen(value), (u8*)dest); return return_value; } /** * [hmac:]name:key */ ya_result config_set_tsig_item(const char *value, tsig_item **dest, const anytype unused) { (void)unused; ya_result ret; char *token2; char *token3; const char *value_limit = &value[strlen(value)]; token2 = strchr(value, ':'); if(token2 == NULL) { return PARSE_INVALID_ARGUMENT; // expects at least one ':' } token3 = strchr(token2 + 1, ':'); size_t hmac_name_size; size_t key_name_size; char hmac_name[32]; u8 key_name[MAX_DOMAIN_LENGTH]; u8 key_bytes[1024]; if(token3 == NULL) { // hmac-md5 OR hmac-sha256 :name:key memcpy(hmac_name, "hmac-md5", 9); } else { // hmac:name:key hmac_name_size = token2 - value; if(hmac_name_size < sizeof(hmac_name) - 1) { memcpy(hmac_name, value, hmac_name_size); hmac_name[hmac_name_size] = '\0'; } else { return BUFFER_WOULD_OVERFLOW; } value = token2 + 1; token2 = token3; } key_name_size = token2 - value; ret = charp_to_locase_dnsname(key_name, value, key_name_size); if(ISOK(ret)) { ++token2; size_t key_size = value_limit - token2; if(BASE64_DECODED_SIZE(key_size) <= sizeof(key_bytes)) { ret = base64_decode(token2, key_size, key_bytes); if(ISOK(ret)) { key_size = (size_t)ret; if(ISOK(ret = tsig_get_hmac_algorithm_from_friendly_name(hmac_name))) { u32 hmac_algorithm = (u32)ret; ret = tsig_register(key_name, key_bytes, key_size, hmac_algorithm); if(ISOK(ret)) { tsig_item *tsig_key = tsig_get(key_name); if(dest != NULL) { *dest = tsig_key; } } return ret; } else { return UNKNOWN_NAME; } } else { return ret; } } else { return BUFFER_WOULD_OVERFLOW; } } else { return ret; } } ya_result config_set_obsolete(const char *value, void *dest, const anytype notused) { (void)dest; (void)notused; if(logger_is_running()) { log_warn("parameter '%s' is not used", value); } else { osformatln(termerr, "parameter '%s' is not used", value); } return SUCCESS; } void config_init_error_codes() { if(config_init_error_codes_done) { return; } config_init_error_codes_done = TRUE; error_register(CONFIG_SECTION_ALREADY_REGISTERED, "CONFIG_SECTION_ALREADY_REGISTERED"); error_register(CONFIG_ALIAS_CHAIN_TOO_BIG, "CONFIG_ALIAS_CHAIN_TOO_BIG"); error_register(CONFIG_PARSE_SECTION_TAG_NOT_CLOSED,"CONFIG_PARSE_SECTION_TAG_NOT_CLOSED"); error_register(CONFIG_PARSE_UNEXPECTED_SECTION_OPEN,"CONFIG_PARSE_UNEXPECTED_SECTION_OPEN"); error_register(CONFIG_PARSE_UNEXPECTED_SECTION_CLOSE,"CONFIG_PARSE_UNEXPECTED_SECTION_CLOSE"); error_register(CONFIG_PARSE_CLOSED_WRONG_SECTION,"CONFIG_PARSE_CLOSED_WRONG_SECTION"); error_register(CONFIG_PARSE_SECTION_TAG_TOO_SMALL,"CONFIG_PARSE_SECTION_TAG_TOO_SMALL"); error_register(CONFIG_PARSE_INCLUDE_EXPECTED_FILE_PATH,"CONFIG_PARSE_INCLUDE_EXPECTED_FILE_PATH"); error_register(CONFIG_PARSE_UNKNOWN_KEYWORD,"CONFIG_PARSE_UNKNOWN_KEYWORD"); error_register(CONFIG_PARSE_EXPECTED_VALUE,"CONFIG_PARSE_EXPECTED_VALUE"); error_register(CONFIG_UNKNOWN_SETTING, "CONFIG_UNKNOWN_SETTING"); error_register(CONFIG_VALUE_OUT_OF_RANGE, "CONFIG_VALUE_OUT_OF_RANGE"); error_register(CONFIG_FILE_PATH_TOO_BIG, "CONFIG_FILE_PATH_TOO_BIG"); error_register(CONFIG_BAD_UID, "CONFIG_BAD_UID"); error_register(CONFIG_BAD_GID, "CONFIG_BAD_GID"); error_register(CONFIG_TEXT_LENGTH_TOO_BIG, "CONFIG_TEXT_LENGTH_TOO_BIG"); error_register(CONFIG_ARRAY_SIZE_TOO_BIG, "CONFIG_ARRAY_SIZE_TOO_BIG"); error_register(CONFIG_LOGGER_HANDLE_ALREADY_DEFINED, "CONFIG_LOGGER_HANDLE_ALREADY_DEFINED"); error_register(CONFIG_LOGGER_INVALID_DEBUGLEVEL, "CONFIG_LOGGER_INVALID_DEBUGLEVEL"); error_register(CONFIG_KEY_INCOMPLETE_KEY, "CONFIG_KEY_INCOMPLETE_KEY"); error_register(CONFIG_KEY_UNSUPPORTED_ALGORITHM, "CONFIG_KEY_UNSUPPORTED_ALGORITHM"); } u8 config_get_source() { return config_current_source; } void config_set_source(u8 l) { config_current_source = l; } /** * If the source level has been parsed, automatically fill the default values * for fields that are not set yet. * * @param l after what level do we automatically set the default values in the container ? */ void config_set_autodefault_after_source(u8 l) { config_autodefault_after_source = l; } /** * If the source level has been parsed, automatically fill the default values * for fields that are not set yet. * * @return after what level do we automatically set the default values in the container */ u8 config_get_autodefault_after_source() { return config_autodefault_after_source; } u8 config_get_default_source() { return config_default_source; } void config_set_default_source(u8 l) { config_default_source = l; } ya_result config_init() { config_init_error_codes(); return SUCCESS; } /** * * Will store the pointer to the descriptor into a global collection. * Returns an error if the node exists already and is not identical. * Which should lead to free the redundant descriptor by the caller. * * @param section_descriptor * @param priority * @return */ ya_result config_register(config_section_descriptor_s *section_descriptor, s32 priority) { if(priority < 0) { priority = 0x1000; } u32_node *node = u32_set_find(§ion_descriptor_set, (u32)priority); if(node == NULL) { node = u32_set_insert(§ion_descriptor_set, (u32)priority); node->value = /*(void*)*/section_descriptor; return SUCCESS; } else { if(node->value == section_descriptor) { return SUCCESS; } else { return CONFIG_SECTION_ALREADY_REGISTERED; } } } ya_result config_register_const(const config_section_descriptor_s *section_descriptor, s32 priority) { ya_result ret; ret = config_register((config_section_descriptor_s*)section_descriptor, priority); return ret; } ya_result config_unregister(config_section_descriptor_s *section_descriptor) { u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); if(node->value == section_descriptor) { u32_set_delete(§ion_descriptor_set, node->key); return SUCCESS; } } return ERROR; } config_section_descriptor_s* config_unregister_by_name(const char *name) { u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); if(node->value != NULL) { config_section_descriptor_s* desc = (config_section_descriptor_s*)node->value; if(desc->vtbl != NULL) { if(strcmp(desc->vtbl->name, name) == 0) { u32_set_delete(§ion_descriptor_set, node->key); return desc; } } } } return NULL; } ya_result config_set_section_default(config_section_descriptor_s *section_descriptor, config_error_s *cfgerr) { s32 err = SUCCESS; if((section_descriptor->vtbl->table != NULL) && (section_descriptor->base != NULL)) { section_descriptor->vtbl->init(section_descriptor); for(const config_table_descriptor_item_s *item = section_descriptor->vtbl->table; item->name != NULL; item++) { if((item->default_value_string != NULL) && (item->setter != NULL)) { if(FAIL(err = config_value_set(section_descriptor, item->name, item->default_value_string, cfgerr))) { if((cfgerr != NULL) && !cfgerr->has_content) { cfgerr->variable_name = item->name; cfgerr->line_number = 0; cfgerr->has_content = TRUE; strcpy_ex(cfgerr->file, "default values", sizeof(cfgerr->file)); strcpy_ex(cfgerr->line, item->name, sizeof(cfgerr->line)); snformat(cfgerr->line, sizeof(cfgerr->line), "%s \"%s\"", item->name, item->default_value_string); } break; } } } } return err; } ya_result config_read_section(const char *the_configuration_file_path, config_error_s *cfgerr, const char *section_name) { ya_result err = SUCCESS; char configuration_file_path[PATH_MAX]; // if the passed value is a pointer into a configuration structure, // there is a risk that the value is freed and replaced by a different one // => bad // so a copy is done first strcpy_ex(configuration_file_path, the_configuration_file_path, sizeof(configuration_file_path)); u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); config_section_descriptor_s *section_descriptor = (config_section_descriptor_s*)node->value; if((section_name != NULL) && (strcmp(section_descriptor->vtbl->name, section_name) != 0)) { // skip continue; } #if CONFIG_SETTINGS_DEBUG formatln("config file: section '%s' start", section_descriptor->vtbl->name); #endif section_descriptor->vtbl->init(section_descriptor); input_stream ins; if(ISOK(err = file_input_stream_open(&ins, configuration_file_path))) { // parse stream will parse ALL sections if(ISOK(err = config_file_reader_parse_stream(configuration_file_path, &ins, section_descriptor, cfgerr))) { // whatever #if CONFIG_SETTINGS_DEBUG formatln("config file: section '%s' done", section_descriptor->vtbl->name); #endif if((config_autodefault_after_source != 0) && (config_autodefault_after_source == config_current_source)) { #if CONFIG_SETTINGS_DEBUG formatln("config file: section '%s' applying default", section_descriptor->vtbl->name); #endif // apply default config_current_source = config_default_source; err = config_set_section_default(section_descriptor, cfgerr); config_current_source = config_autodefault_after_source; if(FAIL(err)) { break; } } if((err = config_fire_on_section_read_callback(section_descriptor->vtbl->name, -1)) != 0) { break; } } else { break; } } else { #if DEBUG formatln("config file: cannot open: '%s': %r", configuration_file_path, err); #endif break; } if(section_descriptor->vtbl->postprocess != NULL) { if(FAIL(err = section_descriptor->vtbl->postprocess(section_descriptor))) { if(cfgerr != NULL && !cfgerr->has_content) { cfgerr->line_number = 0; cfgerr->has_content = TRUE; cfgerr->line[0] = '\0'; snformat(cfgerr->file, sizeof(cfgerr->file), "section %s", section_descriptor->vtbl->name); } break; } } } return err; } ya_result config_read(const char *configuration_file_path, config_error_s *cfgerr) { ya_result return_code = config_read_section(configuration_file_path, cfgerr, NULL); return return_code; } /** * * @param buffer source buffer * @param buffer_len source buffer size * @param buffer_name name of the buffer for error reporting ie: "command-line" * @param cfgerr error handling structure * * @return an error code */ ya_result config_read_from_buffer(const char *buffer, u32 buffer_len, const char *buffer_name, config_error_s *cfgerr) { ya_result err = SUCCESS; u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); config_section_descriptor_s *section_descriptor = (config_section_descriptor_s*)node->value; #if CONFIG_SETTINGS_DEBUG formatln("config buffer: section '%s' start", section_descriptor->vtbl->name); #endif section_descriptor->vtbl->init(section_descriptor); input_stream ins; bytearray_input_stream_init_const(&ins, (const u8*)buffer, buffer_len); err = config_file_reader_parse_stream(buffer_name, &ins, section_descriptor, cfgerr); /// @note config_file_reader_parse_stream closes the stream // DO NOT: input_stream_close(&ins); if(ISOK(err)) { // whatever #if CONFIG_SETTINGS_DEBUG formatln("config buffer: section '%s' done", section_descriptor->vtbl->name); #endif } else { break; } } return err; } static ya_result config_source_get_from_buffer(struct config_source_s *source, input_stream *out_stream, config_error_s *cfgerr) { (void)cfgerr; bytearray_input_stream_init_const(out_stream, (const u8*)source->source.buffer.text, source->source.buffer.size); return SUCCESS; } void config_source_set_buffer(struct config_source_s *source, const char *name, u8 level, const char *buffer, u32 buffer_len) { source->get_source = config_source_get_from_buffer; source->name = name; source->__class__ = "buffer_source"; source->source.buffer.text = buffer; source->source.buffer.size = buffer_len; source->level = level; } static ya_result config_source_get_from_file(struct config_source_s *source, input_stream *out_stream, config_error_s *cfgerr) { ya_result return_code; if(source->source.file_name.name != NULL) { return_code = file_input_stream_open(out_stream, source->source.file_name.name); if(FAIL(return_code)) { if(cfgerr != NULL) { strcpy_ex(cfgerr->file, source->source.file_name.name, sizeof(cfgerr->file)); strcpy_ex(cfgerr->line, "unable to open file", sizeof(cfgerr->line)); cfgerr->line_number = 0; } } } else { return CONFIG_INTERNAL_ERROR; } return return_code; } void config_source_set_file(struct config_source_s *source, const char *name, u8 level) { source->get_source = config_source_get_from_file; source->name = name; source->__class__ = "file_source"; source->source.file_name.name = name; source->level = level; } ya_result config_source_set_commandline(struct config_source_s *source, const cmdline_desc_s *cmdline, int argc, char **argv) { input_stream config_is; ya_result ret; source->get_source = config_source_get_from_buffer; source->name = "command line"; source->__class__ = "command line source"; source->source.file_name.name = "command line"; source->level = CONFIG_SOURCE_CMDLINE; int argc_error; if(FAIL(ret = cmdline_parse(cmdline, argc, argv, NULL, NULL, &config_is, &argc_error))) { if(argc_error > 0) { formatln("command line: %r at '%s'", ret, argv[argc_error]); } else { formatln("command line: %r", ret); } flushout(); return ret; } source->source.buffer.size = bytearray_input_stream_size(&config_is); source->source.buffer.text = (char*)bytearray_input_stream_detach(&config_is); input_stream_close(&config_is); return SUCCESS; } ya_result config_read_from_sources(struct config_source_s *sources, u32 sources_count, config_error_s *cfgerr) { ya_result err = SUCCESS; config_error_reset(cfgerr); // test that the sources are setup properly u8 last_source = MAX_U8; for(u32 i = 0; i < sources_count; i++) { if(sources[i].get_source == NULL) { return CONFIG_INTERNAL_ERROR; // NULL callback } if(sources[i].level > last_source) { return CONFIG_INTERNAL_ERROR; // sources are not sorted } last_source = sources[i].level; } if(last_source <= 1) { return CONFIG_INTERNAL_ERROR; // do not put "default" nor "none" in a source level } u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); config_section_descriptor_s *section_descriptor = (config_section_descriptor_s*)node->value; #if CONFIG_SETTINGS_DEBUG formatln("config buffer: section '%s' start", section_descriptor->vtbl->name); #endif section_descriptor->vtbl->init(section_descriptor); // command line input_stream ins; for(u32 source_index = 0; source_index < sources_count; source_index++) { struct config_source_s *source = &sources[source_index]; #if CONFIG_SETTINGS_DEBUG formatln("config buffer: section '%s' getting source '%s'", section_descriptor->vtbl->name, source->name); #endif config_set_source(source->level); // retrieve the stream if(FAIL(err = sources[source_index].get_source(source, &ins, cfgerr))) { break; } #if CONFIG_SETTINGS_DEBUG formatln("config buffer: section '%s' parsing stream", section_descriptor->vtbl->name); #endif if(FAIL(err = config_file_reader_parse_stream(source->name, &ins, section_descriptor, cfgerr))) { break; } #if CONFIG_SETTINGS_DEBUG formatln("config buffer: section '%s' parsing stream done", section_descriptor->vtbl->name); #endif // note: ins must be closed } // default if(ISOK(err)) { config_set_source(CONFIG_SOURCE_DEFAULT); if(FAIL(err = config_set_section_default(section_descriptor, cfgerr))) { if((cfgerr != NULL) && !cfgerr->has_content) { cfgerr->variable_name = ""; cfgerr->line_number = 0; cfgerr->has_content = TRUE; cfgerr->line[0] = '\0'; snformat(cfgerr->file, sizeof(cfgerr->file), "setting-up section %s default", section_descriptor->vtbl->name); } break; } if(section_descriptor->vtbl->postprocess != NULL) { if(FAIL(err = section_descriptor->vtbl->postprocess(section_descriptor))) { if((cfgerr != NULL) && !cfgerr->has_content) { cfgerr->variable_name = ""; cfgerr->line_number = 0; cfgerr->has_content = TRUE; cfgerr->line[0] = '\0'; snformat(cfgerr->file, sizeof(cfgerr->file), "section %s", section_descriptor->vtbl->name); } break; } } // callback if((err = config_fire_on_section_read_callback(section_descriptor->vtbl->name, -1)) != 0) { if(FAIL(err)) { if((cfgerr != NULL) && !cfgerr->has_content) { cfgerr->variable_name = ""; cfgerr->line_number = 0; cfgerr->has_content = FALSE; cfgerr->line[0] = '\0'; cfgerr->file[0] = '\0'; } } break; } } else { if(err != MAKE_ERRNO_ERROR(ENOENT)) { break; } } } config_set_source(CONFIG_SOURCE_NONE); return err; } ya_result config_set_default(config_error_s *cfgerr) { ya_result err = SUCCESS; u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); config_section_descriptor_s *section_descriptor = (config_section_descriptor_s*)node->value; #if CONFIG_SETTINGS_DEBUG formatln("config default: section '%s' start", section_descriptor->vtbl->name); #endif err = config_set_section_default(section_descriptor, cfgerr); #if CONFIG_SETTINGS_DEBUG formatln("config default: section '%s' done", section_descriptor->vtbl->name); #endif if(ISOK(err)) { // whatever log_debug("config default: section '%s'", section_descriptor->vtbl->name); } else { break; } } return err; } ya_result config_value_set_to_default(const char *section_name, const char *name, config_error_s *cfgerr) { config_section_descriptor_s *section_descriptor = NULL; ya_result err = CONFIG_SECTION_ERROR; u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); config_section_descriptor_s *section_desc = (config_section_descriptor_s*)node->value; if(strcmp(section_desc->vtbl->name, section_name) == 0) { section_descriptor = section_desc; break; } } if(section_descriptor != NULL) { if(section_descriptor->vtbl->table != NULL) { section_descriptor->vtbl->init(section_descriptor); if(ISOK(err = config_item_index_get(section_descriptor->vtbl->table, name))) { const config_table_descriptor_item_s *item = §ion_descriptor->vtbl->table[err]; if(item->default_value_string != NULL) { if(FAIL(err = config_value_set(section_descriptor, item->name, item->default_value_string, cfgerr))) { if((cfgerr != NULL) && !cfgerr->has_content) { cfgerr->variable_name = ""; cfgerr->line_number = 0; cfgerr->has_content = TRUE; strcpy_ex(cfgerr->line, item->name, sizeof(cfgerr->line)); strcpy_ex(cfgerr->file, STRNULL(item->default_value_string), sizeof(cfgerr->file)); } } } } } } return err; } ya_result config_value_get_source(const char *section_name, const char *name) { config_section_descriptor_s *section_descriptor = NULL; ya_result ret = CONFIG_SECTION_ERROR; u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); config_section_descriptor_s *section_desc = (config_section_descriptor_s*)node->value; if(strcmp(section_desc->vtbl->name, section_name) == 0) { section_descriptor = section_desc; break; } } if(section_descriptor != NULL) { if(section_descriptor->vtbl->table != NULL) { section_descriptor->vtbl->init(section_descriptor); if(ISOK(ret = config_item_index_get(section_descriptor->vtbl->table, name))) { const config_table_descriptor_item_s *item = §ion_descriptor->vtbl->table[ret]; ret = item->source; } } } return ret; } static inline void config_item_name_canonize(const char *name, char *filtered_name) { size_t name_len = strlen(name); for(size_t i = 0; i < name_len; i++) { char c = name[i]; if((c == '-') || (c == '.')) { c = '_'; } filtered_name[i] = c; } filtered_name[name_len] = '\0'; } bool config_section_struct_register_type_handler(config_set_field_function *setter, config_section_struct_type_handler *handler) { // workaround config_set_field_function_as_voidp key; key.setter = setter; ptr_node *node = ptr_set_insert(&config_section_struct_type_handler_set, key.ptr); if(node->value == NULL) { config_section_struct_type_handler_as_voidp value; value.handler = handler; node->value = value.ptr; return TRUE; } else { return FALSE; } } void config_section_struct_print(const config_section_descriptor_s *section_descriptor, const void* configbase, output_stream *os) { const char *value; const config_table_descriptor_item_s *table = section_descriptor->vtbl->table; char tmp[1024]; if(configbase == NULL) { return; } while(table->name != NULL) { bool already = FALSE; char filtered_name[128]; config_item_name_canonize(table->name, filtered_name); /* table->setter is NULL for aliases */ if(table->setter != NULL) { intptr base = (intptr)configbase; intptr offs = (intptr)table->field_offset; void *ptr = (void*)(base + offs); if(table->setter == (config_set_field_function*)config_set_bool) { bool b = *(bool*)ptr; value=(b)?"yes":"no"; } else if(table->setter == (config_set_field_function*)config_set_flag8) { u8 *f = (u8*)ptr; bool b = *f & table->function_specific._u8; value=(b)?"yes":"no"; } else if(table->setter == (config_set_field_function*)config_set_flag16) { u16 *f = (u16*)ptr; bool b = *f & table->function_specific._u16; value=(b)?"yes":"no"; } else if(table->setter == (config_set_field_function*)config_set_flag32) { u32 *f = (u32*)ptr; bool b = *f & table->function_specific._u32; value=(b)?"yes":"no"; } else if(table->setter == (config_set_field_function*)config_set_flag64) { u64 *f = (u64*)ptr; bool b = *f & table->function_specific._u64; value=(b)?"yes":"no"; } else if(table->setter == (config_set_field_function*)config_set_u64) { u64 *v = (u64*)ptr; snformat(tmp, sizeof(tmp),"%lld", *v); value = tmp; } else if( (table->setter == (config_set_field_function*)config_set_u32) || (table->setter == (config_set_field_function*)config_set_u32_range) || (table->setter == (config_set_field_function*)config_set_u32_clamp)) { u32 *v = (u32*)ptr; snformat(tmp, sizeof(tmp),"%d", *v); value = tmp; } else if(table->setter == (config_set_field_function*)config_set_s32) { s32 *v = (s32*)ptr; snformat(tmp, sizeof(tmp),"%i", *v); value = tmp; } else if(table->setter == (config_set_field_function*)config_set_u16) { u16 *v = (u16*)ptr; snformat(tmp, sizeof(tmp),"%d", *v); value = tmp; } else if((table->setter == (config_set_field_function*)config_set_u8) || (table->setter == (config_set_field_function*)config_inc_u8)) { u8 *v = (u8*)ptr; snformat(tmp, sizeof(tmp),"%d", *v); value = tmp; } else if(table->setter == (config_set_field_function*)config_set_uid_t) { uid_t *v = (uid_t*)ptr; snformat(tmp, sizeof(tmp),"%d", *v); value = tmp; } else if(table->setter == (config_set_field_function*)config_set_gid_t) { gid_t *v = (gid_t*)ptr; snformat(tmp, sizeof(tmp),"%d", *v); value = tmp; } else if((table->setter == (config_set_field_function*)config_set_string) || (table->setter == (config_set_field_function*)config_set_path) || (table->setter == (config_set_field_function*)config_set_logpath) || (table->setter == (config_set_field_function*)config_set_file)) { value = *((char**)ptr); if((value == NULL) || (strlen(value) == 0)) { value = "\"\""; } } else if(table->setter == (config_set_field_function*)config_set_password) { value = "????????"; } #if __unix__ else if(table->setter == (config_set_field_function*)config_set_chroot) { value = chroot_get_path(); } #endif else if(table->setter == (config_set_field_function*)config_set_dnstype) { u16 *v = (u16*)ptr; value = dns_type_get_name(*v); } else if(table->setter == (config_set_field_function*)config_set_dnsclass) { u16 *v = (u16*)ptr; value = dns_class_get_name(*v); } else if(table->setter == (config_set_field_function*)config_set_string_copy) { value = (char*)ptr; if((value == NULL) || (strlen(value) == 0)) { value = "\"\""; } } else if(table->setter == (config_set_field_function*)config_set_fqdn) { snformat(tmp, sizeof(tmp), "%{dnsname}", *((u8**)ptr)); value = tmp; } else if(table->setter == (config_set_field_function*)acl_config_set_item) { address_match_set* ams = (address_match_set*)ptr; if(ams != NULL) { osformat(os, "%24s", filtered_name); acl_address_match_set_to_stream(os, ams); osprintln(os,""); } else { osformatln(os, "# '%s' is empty", filtered_name); } already = TRUE; value = NULL; } else if(table->setter == (config_set_field_function*)config_set_host_list) { host_address *v = *(host_address**)ptr; if(v != NULL) { osformat(os, "%24s", filtered_name); char sep = ' '; do { socketaddress sa; host_address2sockaddr(v, &sa); osformat(os, "%c%{sockaddrip}", sep, &sa); if(v->port != NU16(DNS_DEFAULT_PORT)) { osformat(os, " port %hd", ntohs(v->port)); } #if DNSCORE_HAS_TSIG_SUPPORT if(v->tsig != NULL) { osformat(os, " key %{dnsname}", v->tsig->name); } #endif sep = ','; v = v->next; } while(v != NULL); osprintln(os,""); } else { osformatln(os, "# '%s' is empty", filtered_name); } already = TRUE; value = NULL; } else if(table->setter == (config_set_field_function*)config_set_enum_value) { u32 *v = (u32*)ptr; value_name_table* tbl = table->function_specific._voidp; value = "?"; while(tbl->data != NULL) { if(tbl->id == *v) { value = tbl->data; break; } tbl++; } } else if(table->setter == (config_set_field_function*)config_set_enum8_value) { u8 *v = (u8*)ptr; value_name_table* tbl = table->function_specific._voidp; value = "?"; while(tbl->data != NULL) { if(tbl->id == *v) { value = tbl->data; break; } tbl++; } } else if(table->setter == (config_set_field_function*)config_set_bytes) { u8 *v = (u8*)ptr; if(v != NULL) { u32 v_size = table->function_specific._u32; assert(v_size < (sizeof(tmp) * 3 + 3) / 4); u32 e_size = base64_encode(v, v_size, tmp); tmp[e_size] = '\0'; value = tmp; } else { value = NULL; } } /* else if(table->setter == (config_set_field_function*)acl_config_set_access_control_item) { } */ else { config_set_field_function_as_voidp key; key.setter = table->setter; ptr_node *node = ptr_set_find(&config_section_struct_type_handler_set, key.ptr); if(node != NULL) { config_section_struct_type_handler_as_voidp alias_value; alias_value.ptr = node->value; config_section_struct_type_handler *type_handler = alias_value.handler; already = type_handler(os, table->name, ptr); value = NULL; } else { osformatln(os, "# '%s' parameter cannot be dumped", filtered_name); value = NULL; already = TRUE; } } if(!already) { if(value != NULL) { osformatln(os, "%s %s", filtered_name, value); } #if DEBUG else { osformatln(os, "# '%s' is not set", filtered_name); } #endif } } table++; } } void config_section_struct_free(const config_section_descriptor_s *section_descriptor, const void* configbase) { const config_table_descriptor_item_s *table = section_descriptor->vtbl->table; if(configbase == NULL) { return; } while(table->name != NULL) { char filtered_name[128]; config_item_name_canonize(table->name, filtered_name); /* table->setter is NULL for aliases */ if(table->setter != NULL) { intptr base = (intptr)configbase; intptr offs = (intptr)table->field_offset; void *ptr = (void*)(base + offs); if(table->setter == (config_set_field_function*)config_set_bool) { } else if(table->setter == (config_set_field_function*)config_set_flag8) { } else if(table->setter == (config_set_field_function*)config_set_flag16) { } else if(table->setter == (config_set_field_function*)config_set_flag32) { } else if(table->setter == (config_set_field_function*)config_set_flag64) { } else if(table->setter == (config_set_field_function*)config_set_u64) { } else if( (table->setter == (config_set_field_function*)config_set_u32) || (table->setter == (config_set_field_function*)config_set_u32_range) || (table->setter == (config_set_field_function*)config_set_u32_clamp)) { } else if(table->setter == (config_set_field_function*)config_set_s32) { } else if(table->setter == (config_set_field_function*)config_set_u16) { } else if((table->setter == (config_set_field_function*)config_set_u8) || (table->setter == (config_set_field_function*)config_inc_u8)) { } else if(table->setter == (config_set_field_function*)config_set_uid_t) { } else if(table->setter == (config_set_field_function*)config_set_gid_t) { } else if((table->setter == (config_set_field_function*)config_set_string) || (table->setter == (config_set_field_function*)config_set_path) || (table->setter == (config_set_field_function*)config_set_logpath) || (table->setter == (config_set_field_function*)config_set_file)) { char *text = *((char**)ptr); if((text != NULL)) { free(text); *((char**)ptr) = NULL; } } else if(table->setter == (config_set_field_function*)config_set_password) { } #if __unix__ else if(table->setter == (config_set_field_function*)config_set_chroot) { chroot_set_path(NULL); } #endif else if(table->setter == (config_set_field_function*)config_set_dnstype) { } else if(table->setter == (config_set_field_function*)config_set_dnsclass) { } else if(table->setter == (config_set_field_function*)config_set_string_copy) { } else if(table->setter == (config_set_field_function*)config_set_fqdn) { u8 *fqdn = *((u8**)ptr); if(fqdn != NULL) { free(fqdn); *((u8**)ptr) = NULL; } } else if(table->setter == (config_set_field_function*)config_set_host_list) { host_address *v = *(host_address**)ptr; if(v != NULL) { host_address_delete_list(v); *(host_address**)ptr = NULL; } } else if(table->setter == (config_set_field_function*)config_set_enum_value) { } else if(table->setter == (config_set_field_function*)config_set_enum8_value) { } else if(table->setter == (config_set_field_function*)config_set_bytes) { } else { config_set_field_function_as_voidp key; key.setter = table->setter; ptr_node *node = ptr_set_find(&config_section_struct_type_handler_set, key.ptr); if(node != NULL) { //config_section_struct_type_handler_as_voidp alias_value; //alias_value.ptr = node->value; //config_section_struct_type_handler *type_handler = alias_value.handler; //value = NULL; } else { } } } table++; } } void config_section_print(const config_section_descriptor_s *section_descriptor, output_stream *os) { config_section_struct_print(section_descriptor, section_descriptor->base, os); } void config_print(output_stream *os) { u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); config_section_descriptor_s *section_descriptor = (config_section_descriptor_s*)node->value; if((section_descriptor->vtbl->table != NULL) && (section_descriptor->base != NULL)) { osformatln(os, "<%s>", section_descriptor->vtbl->name); config_section_print(section_descriptor, os); osformatln(os, "\n", section_descriptor->vtbl->name); } else // there is not fixed structure associated to the configuration { // note: never stop iterating before the updated context value is NULL void *context = NULL; do { osformatln(os, "<%s>", section_descriptor->vtbl->name); section_descriptor->vtbl->print_wild(section_descriptor, os, NULL, &context); osformatln(os, "\n", section_descriptor->vtbl->name); } while(context != NULL); } } } ya_result config_item_index_get(const config_table_descriptor_item_s *table, const char *name) { if(table != NULL) { // replaces all '-' and '.' by '_' char filtered_name[128]; config_item_name_canonize(name, filtered_name); int count = 0; while(table[count].name != NULL) { if(strchr(table[count].name, '.') == NULL) { if(strcasecmp(table[count].name, filtered_name) == 0) { return count; } } else { char table_filtered_name[128]; config_item_name_canonize(table[count].name, table_filtered_name); if(strcasecmp(table_filtered_name, filtered_name) == 0) { return count; } } count++; } } return CONFIG_UNKNOWN_SETTING; /* not found */ } config_section_descriptor_s * config_section_get_descriptor(const char *name) { u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); config_section_descriptor_s *section_descriptor = (config_section_descriptor_s*)node->value; if(strcmp(section_descriptor->vtbl->name, name) == 0) { return section_descriptor; } } return NULL; } ya_result config_value_set(config_section_descriptor_s *section_descriptor, const char *key, const char *value, config_error_s *cfgerr) { (void)cfgerr; ya_result err; s8 maxalias = 16; // seek the entry, going through aliases if needs to be for(;;) { if(FAIL(err = config_item_index_get(section_descriptor->vtbl->table, key))) { if(section_descriptor->vtbl->set_wild != NULL) { err = section_descriptor->vtbl->set_wild(section_descriptor, key, value); } return err; } if(section_descriptor->vtbl->table[err].setter != NULL) { break; } if(--maxalias <= 0) { return CONFIG_ALIAS_CHAIN_TOO_BIG; // alias chain too big } // point to the aliased key = section_descriptor->vtbl->table[err].default_value_string; } config_table_descriptor_item_s *item = §ion_descriptor->vtbl->table[err]; // only set it if the field has not been set by a source beyond the current one if(item->source <= config_current_source) { u8 *base = (u8*)section_descriptor->base; log_debug1("config: '%s' setting '%s' to '%s'", STRNULL(section_descriptor->vtbl->name), STRNULL(key), STRNULL(value)); if(ISOK(err = item->setter(value, &base[item->field_offset], item->function_specific))) { item->source = config_current_source; } } else { log_debug1("config: '%s' has already been set by source %u (current is %u)", item->name, item->source, config_current_source); } return err; } ya_result config_source_set_by_target(config_section_descriptor_s *section_descriptor, void *target_ptr) { config_table_descriptor_item_s *item = section_descriptor->vtbl->table; u8 *base = (u8*)section_descriptor->base; while(item->name != NULL) { if((void*)&base[item->field_offset] == target_ptr) { item->source = config_default_source; return SUCCESS; } } return ERROR; } ya_result config_postprocess() { ya_result return_code = SUCCESS; u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); config_section_descriptor_s *section_descriptor = (config_section_descriptor_s*)node->value; if(section_descriptor->vtbl->postprocess != NULL) { if(FAIL(return_code = section_descriptor->vtbl->postprocess(section_descriptor))) { return return_code; } } } return SUCCESS; } ya_result config_finalize() { ya_result return_code = SUCCESS; u32_set_iterator iter; u32_set_iterator_init(§ion_descriptor_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); config_section_descriptor_s *section_descriptor = (config_section_descriptor_s*)node->value; if(section_descriptor->vtbl->finalise != NULL) { if(FAIL(return_code = section_descriptor->vtbl->finalise(section_descriptor))) { return return_code; } } } u32_set_destroy(§ion_descriptor_set); ptr_set_iterator iter2; ptr_set_iterator_init(&on_section_read_callback_set, &iter2); while(ptr_set_iterator_hasnext(&iter2)) { ptr_node *node = ptr_set_iterator_next_node(&iter2); free(node->key); } ptr_set_destroy(&on_section_read_callback_set); return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/config_struct.c0000644000000000000000000000013114505005532022344 xustar000000000000000029 mtime=1695812442.41098173 30 atime=1695812445.793030168 30 ctime=1695812494.509727889 yadifa-2.6.5-11201/lib/dnscore/src/config_struct.c0000664000374500037450000001252214505005532022311 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include #include "dnscore/dnscore-config.h" #include "dnscore/config_settings.h" static ya_result config_section_struct_init(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_struct_start(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_struct_stop(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_struct_postprocess(struct config_section_descriptor_s *csd) { // NOP (void)csd; return SUCCESS; } static ya_result config_section_struct_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->vtbl != NULL) { free((char*)csd->vtbl->name); free((config_section_descriptor_vtbl_s*)csd->vtbl); } free(csd); } return SUCCESS; } static ya_result config_section_struct_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_struct_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)key; (void)context; return CONFIG_UNKNOWN_SETTING; } static const config_section_descriptor_vtbl_s config_section_struct_descriptor = { NULL, NULL, config_section_struct_set_wild, config_section_struct_print_wild, config_section_struct_init, config_section_struct_start, config_section_struct_stop, config_section_struct_postprocess, config_section_struct_finalize }; /// register a simple (static) struct ya_result config_register_struct(const char *name, config_table_descriptor_item_s *table, void *data_struct, s32 priority) { config_section_descriptor_vtbl_s *vtbl; MALLOC_OBJECT_OR_DIE(vtbl, config_section_descriptor_vtbl_s, CFGSVTBL_TAG); memcpy(vtbl, &config_section_struct_descriptor, sizeof(config_section_descriptor_vtbl_s)); vtbl->name = strdup(name); vtbl->table = table; const config_table_descriptor_item_s *t = table; while(t->name != NULL) { size_t expected = t->expected_size; size_t field = t->field_size; if(expected != field) { osformatln(termerr, "config descriptor: '%s' field '%s': expected size: %i, field size: %i", name, t->name, expected, field); flusherr(); } ++t; } config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = data_struct; desc->vtbl = vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free((char*)vtbl->name); free(vtbl); free(desc); } return return_code; } void* config_unregister_struct(const char *name, const config_table_descriptor_item_s *table) { void *data_struct = NULL; config_section_descriptor_s *desc = config_unregister_by_name(name); if(desc != NULL) { config_section_descriptor_vtbl_s *vtbl = (config_section_descriptor_vtbl_s*)desc->vtbl; assert(vtbl != NULL); assert(vtbl->table == table); (void)table; free((char*)vtbl->name); free(vtbl); data_struct = desc->base; free(desc); } return data_struct; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/counter_output_stream.c0000644000000000000000000000013214505005532024146 xustar000000000000000030 mtime=1695812442.440982159 30 atime=1695812445.794030182 30 ctime=1695812494.512727932 yadifa-2.6.5-11201/lib/dnscore/src/counter_output_stream.c0000664000374500037450000000714314505005532024115 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/counter_output_stream.h" static ya_result counter_write(output_stream* stream, const u8* buffer, u32 len) { counter_output_stream_data* data = (counter_output_stream_data*)stream->data; data->write_count += len; if(ISOK(data->result)) { data->result = output_stream_write(data->filtered, buffer, len); if(ISOK(data->result)) { data->written_count += data->result; } } return data->result; } static ya_result counter_flush(output_stream* stream) { counter_output_stream_data* data = (counter_output_stream_data*)stream->data; if(ISOK(data->result)) { data->result = output_stream_flush(data->filtered); } return data->result; } static void counter_close(output_stream* stream) { // counter_output_stream_data* data = (counter_output_stream_data*)stream->data; output_stream_set_void(stream); } static const output_stream_vtbl counter_output_stream_vtbl ={ counter_write, counter_flush, counter_close, "counter_output_stream", }; void counter_output_stream_init(output_stream* filtered, output_stream* stream, counter_output_stream_data* counter_data) { yassert(filtered != stream); counter_output_stream_data* data = counter_data; data->filtered = filtered; data->write_count = 0; data->written_count = 0; data->result = SUCCESS; stream->data = data; stream->vtbl = &counter_output_stream_vtbl; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/debug.c0000644000000000000000000000012714505005532020566 xustar000000000000000028 mtime=1695812442.3809813 30 atime=1695812445.791030139 29 ctime=1695812494.51472796 yadifa-2.6.5-11201/lib/dnscore/src/debug.c0000664000374500037450000001143614505005532020531 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup debug Debug functions * @ingroup dnscore * @brief Debug functions. * * Definitions of debug functions/hooks, mainly memory related. * * @{ */ #include "dnscore/dnscore-config.h" #include "dnscore/debug_config.h" #include #include #include #if defined(__linux__) #include #endif #include #include #include "dnscore/thread.h" #include "dnscore/timems.h" #if defined(__GLIBC__) || defined(__APPLE__) #include #include #include #endif #include "dnscore/sys_types.h" #include "dnscore/format.h" #include "dnscore/debug.h" #include "dnscore/mutex.h" #include "dnscore/logger.h" #include "dnscore/ptr_set_debug.h" #include "dnscore/u64_set_debug.h" #include "dnscore/list-sl-debug.h" #if defined(__GLIBC__) || defined(__APPLE__) #define DNSCORE_DEBUG_STACKTRACE 1 #else /* __FreeBSD__ or unknown */ #define DNSCORE_DEBUG_STACKTRACE 0 #endif #if defined(__linux__) #define DNSCORE_DEBUG_MMAP 1 #endif #ifdef __cplusplus extern "C" output_stream __termout__; extern "C" output_stream __termerr__; #else extern output_stream __termout__; extern output_stream __termerr__; #endif extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger /****************************************************************************/ void debug_dump(void* data_pointer_, size_t size_, size_t line_size, bool hex, bool text) { debug_dump_ex(data_pointer_, size_, line_size, hex, text, FALSE); } /****************************************************************************/ void debug_dump_ex(void* data_pointer_, size_t size_, size_t line_size, bool hex, bool text, bool address) { if(__termout__.vtbl == NULL) { return; } osprint_dump(termout, data_pointer_, size_, line_size, ((address)?OSPRINT_DUMP_ADDRESS:0) | ((hex)?OSPRINT_DUMP_HEX:0) | ((text)?OSPRINT_DUMP_TEXT:0)); } char* debug_strdup(const char* str) { size_t l = strlen(str) + 1; char* out; MALLOC_OR_DIE(char*, out, l, ZDB_STRDUP_TAG); /* ZALLOC IMPOSSIBLE, MUST KEEP MALLOC_OR_DIE */ MEMCOPY(out, str, l); return out; } #if (DNSCORE_HAS_MALLOC_DEBUG_SUPPORT || DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT || DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT || DNSCORE_HAS_MMAP_DEBUG_SUPPORT) #if DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT void debug_memory_stat(int mask); #endif void debug_stat(int mask) { (void)mask; if(__termout__.vtbl == NULL) { return; } debug_memory_stat(mask); zalloc_print_stats(termout); } #endif /** * Dumps the 4K-aligned page containing the pointer on stdout. */ void debug_dump_page(void* ptr) { if(__termout__.vtbl != NULL) { formatln("Page for %p:\n", ptr); if(ptr != NULL) { intptr p = (intptr)ptr; p = p & (~4095); debug_dump_ex((void*)p, 4096, 32, TRUE, TRUE, TRUE); } } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/debug_bench.c0000644000000000000000000000013214505005532021721 xustar000000000000000030 mtime=1695812442.448982274 30 atime=1695812445.794030182 30 ctime=1695812494.516727989 yadifa-2.6.5-11201/lib/dnscore/src/debug_bench.c0000664000374500037450000001570014505005532021666 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup debug Debug functions * @ingroup dnscore * @brief Debug functions. * * Definitions of debug functions/hooks, mainly memory related. * * @{ */ #include "dnscore/dnscore-config.h" #include "dnscore/debug_config.h" #include #include #include #include "dnscore/timems.h" #include "dnscore/sys_types.h" #include "dnscore/format.h" #include "dnscore/logger.h" #include "dnscore/debug.h" #undef malloc #undef free #undef realloc #undef calloc #undef debug_mtest #undef debug_stat #undef debug_mallocated #define MODULE_MSG_HANDLE g_system_logger #if DEBUG static pthread_mutex_t debug_bench_mtx = PTHREAD_MUTEX_INITIALIZER; static debug_bench_s *debug_bench_first = NULL; static bool debug_bench_init_done = FALSE; void debug_bench_malloc_init(); void debug_bench_init() { if(debug_bench_init_done) { return; } debug_bench_malloc_init(); pthread_mutexattr_t mta; int err; err = pthread_mutexattr_init(&mta); if(err == 0) { err = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE); if(err == 0) { err = pthread_mutex_init(&debug_bench_mtx, &mta); if(err == 0) { debug_bench_init_done = TRUE; } else { formatln("debug_bench_init: pthread_mutex_init: %r", MAKE_ERRNO_ERROR(err)); } } else { formatln("debug_bench_init: pthread_mutexattr_settype: %r", MAKE_ERRNO_ERROR(err)); } pthread_mutexattr_destroy(&mta); } else { formatln("debug_bench_init: pthread_mutexattr_init: %r", MAKE_ERRNO_ERROR(err)); } } void debug_bench_register(debug_bench_s *bench, const char *name) { if((bench == NULL) || (name == NULL)) { return; } pthread_mutex_lock(&debug_bench_mtx); debug_bench_s *b = debug_bench_first; while((b != bench) && (b != NULL)) { b = b->next; } if(b == NULL) { bench->next = debug_bench_first; bench->name = strdup(name); bench->time_min = MAX_U64; bench->time_max = 0; bench->time_total = 0; bench->time_count = 0; debug_bench_first = bench; } else { log_debug("debug_bench_register(%p,%s): duplicate", bench, name); } pthread_mutex_unlock(&debug_bench_mtx); } void debug_bench_commit(debug_bench_s *bench, u64 delta) { pthread_mutex_lock(&debug_bench_mtx); bench->time_min = MIN(bench->time_min, delta); bench->time_max = MAX(bench->time_max, delta); bench->time_total += delta; bench->time_count++; pthread_mutex_unlock(&debug_bench_mtx); } void debug_bench_logdump_all() { pthread_mutex_lock(&debug_bench_mtx); debug_bench_s *p = debug_bench_first; while(p != NULL) { double min = p->time_min; min /= ONE_SECOND_US_F; double max = p->time_max; max /= ONE_SECOND_US_F; double total = p->time_total; total /= ONE_SECOND_US_F; u32 count = p->time_count; double total_mean = (count != 0)?total/count:0; double total_rate = (total != 0)?count/total:0; if(logger_is_running()) { log_info("bench: %16s: [%9.6fs:%9.6fs] total=%9.6fs mean=%9.6fs rate=%12.3f/s calls=%9u", p->name, min, max, total, total_mean, total_rate, count); } else { formatln("bench: %16s: [%9.6fs:%9.6fs] total=%9.6fs mean=%9.6fs rate=%12.3f/s calls=%9u", p->name, min, max, total, total_mean, total_rate, count); } p = p->next; } pthread_mutex_unlock(&debug_bench_mtx); } void debug_bench_print_all(output_stream *os) { pthread_mutex_lock(&debug_bench_mtx); debug_bench_s *p = debug_bench_first; while(p != NULL) { double min = p->time_min; min /= ONE_SECOND_US_F; double max = p->time_max; max /= ONE_SECOND_US_F; double total = p->time_total; total /= ONE_SECOND_US_F; u32 count = p->time_count; double total_mean = (count != 0)?total/count:0; double total_rate = (total != 0)?count/total:0; osformatln(os, "bench: %16s: [%9.6fs:%9.6fs] total=%9.6fs mean=%9.6fs rate=%12.3f/s calls=%9u", p->name, min, max, total, total_mean, total_rate, count); p = p->next; } pthread_mutex_unlock(&debug_bench_mtx); } void debug_bench_unregister_all() { pthread_mutex_lock(&debug_bench_mtx); debug_bench_s *p = debug_bench_first; while(p != NULL) { debug_bench_s *tmp = p; p = p->next; #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT debug_free((void*)tmp->name,__FILE__,__LINE__); #else free((void*)tmp->name); #endif } debug_bench_first = NULL; pthread_mutex_unlock(&debug_bench_mtx); } #else void debug_bench_init() { } void debug_bench_register(debug_bench_s *bench, const char *name) { (void)bench; (void)name; } void debug_bench_commit(debug_bench_s *bench, u64 delta) { (void)bench; (void)delta; } void debug_bench_logdump_all() { } void debug_bench_unregister_all() { } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/debug_bfd.c0000644000000000000000000000013214505005532021375 xustar000000000000000030 mtime=1695812442.478982704 30 atime=1695812445.795030196 30 ctime=1695812494.518728018 yadifa-2.6.5-11201/lib/dnscore/src/debug_bfd.c0000664000374500037450000003125014505005532021340 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup debug Debug functions * @ingroup dnscore * @brief Debug functions. * * Definitions of debug functions/hooks, mainly memory related. * * @{ */ #include "dnscore/dnscore-config-features.h" #include "dnscore/dnscore-config.h" #include "dnscore/debug_config.h" #include #include #include #if defined(__linux__) #include #endif #include #include #include "dnscore/thread.h" #include "dnscore/timems.h" #if defined(__GLIBC__) || defined(__APPLE__) #include #include #include #if DNSCORE_HAS_BFD_DEBUG_SUPPORT #include #endif #endif #include "dnscore/sys_types.h" #include "dnscore/format.h" #include "dnscore/debug.h" #include "dnscore/mutex.h" #include "dnscore/logger.h" #include "dnscore/ptr_set_debug.h" #include "dnscore/u64_set_debug.h" #include "dnscore/list-sl-debug.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #if DNSCORE_HAS_BFD_DEBUG_SUPPORT ////////////////////////////////////////////////////////////////////////////// // // Line numbers in stacktraces // ////////////////////////////////////////////////////////////////////////////// /// @note edf: from http://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/The_call_stack struct bfd_node { bfd* _bfd; asymbol **_symbols; asection *_text; u32 _symbols_count; bool _has_symbols; }; typedef struct bfd_node bfd_node; static pthread_mutex_t bfd_mtx = PTHREAD_MUTEX_INITIALIZER; static bool bfd_initialised = FALSE; static ptr_set_debug bfd_collection = PTR_SET_DEBUG_ASCIIZ_EMPTY; static char *proc_self_exe = NULL; static char * debug_get_self_exe() { char path[PATH_MAX]; ssize_t n = readlink("/proc/self/exe", path, sizeof(path)); if(n > 0) { path[n] = '\0'; char *ret = strdup(path); return ret; } return NULL; } struct bfd_data { bfd_node *bfdn; bfd_vma pc; bfd_boolean found; const char *filename; const char *function; unsigned int line; }; static void debug_bfd_flags_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters) { u64 flags = (u64)value; output_stream_write(os, "{ ", 2); if(flags & HAS_RELOC) { output_stream_write(os, "RELOC ", 6); } if(flags & EXEC_P) { output_stream_write(os, "EXEC ", 5); } if(flags & HAS_LINENO) { output_stream_write(os, "LINENO ", 7); } if(flags & HAS_DEBUG) { output_stream_write(os, "DEBUG ", 6); } if(flags & HAS_SYMS) { output_stream_write(os, "SYMS ", 5); } if(flags & HAS_LOCALS) { output_stream_write(os, "LOCALS ", 6); } if(flags & DYNAMIC) { output_stream_write(os, "DYNAMIC ", 8); } output_stream_write(os, "}", 1); } static const char debug_bfd_symbol_flags_format_letter[24] = { 'l','g','D','f', '?','k','K','w', 's','o','!','C', 'W','I','F','d', 'O','R','T','e', 'E','S','u','U' }; static void debug_bfd_symbol_flags_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters) { char *p; char tmp[24]; (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u32 flags = (u32)(intptr)value; if(flags != 0) { p = tmp; for(int i = 0; i < 24; i++) { if((flags & (1 << i)) != 0) { *p++ = debug_bfd_symbol_flags_format_letter[i]; } } output_stream_write(os, tmp, p - tmp); } else { tmp[0] = '-'; output_stream_write(os, tmp, 1); } } static void debug_bfd_symbol_flag_help() { log_debug( "- : no flags\n" "l : local The symbol has local scope; <> in <>. The value is the offset into the section of the data.\n" "g : global The symbol has global scope; initialized data in <>. The value is the offset into the section of the data.\n" "D : debugging The symbol is a debugging record. The value has an arbitrary meaning, unless BSF_DEBUGGING_RELOC is also set.\n" "f : function The symbol denotes a function entry point. Used in ELF, perhaps others someday.\n" /*#if 0 // not common "? : unknown\n" "k : keep Used by the linker.\n" "L : keep g Used by the linker. (global ?)\n" "w : weak A weak global symbol, overridable without warnings by a regular global symbol of the same name.\n" #endif*/ "s : section Points to a section.\n" /*#if 0 // not common "o : oldcommon The symbol used to be a common symbol, but now it is allocated.\n" "! : notatend In some files the type of a symbol sometimes alters its location in an output file - ie in coff a <> symbol which is also <> symbol appears where it was declared and not at the end of a section. This bit is set by the target BFD part to convey this information.\n" "C : construct Signal that the symbol is the label of constructor section.\n" "W : warning Signal that the symbol is a warning symbol. The name is a warning. The name of the next symbol is the one to warn about; if a reference is made to a symbol with the same name as the next symbol, a warning is issued by the linker.\n" "I : indirect Signal that the symbol is indirect. This symbol is an indirect pointer to the symbol with the same name as the next symbol.\n" "F : file Marks symbols that contain a file name. This is used for ELF STT_FILE symbols.\n" #endif*/ "d : dynamic Symbol is from dynamic linking information.\n" "O : object The symbol denotes a data object. Used in ELF, and perhaps others someday.\n" /*#if 0 // not common "R : dbg reloc This symbol is a debugging symbol. The value is the offset into the section of the data. BSF_DEBUGGING should be set as well.\n" "T : threadloc This symbol is thread local.\n" "e : relc This symbol represents a complex relocation expression, with the expression tree serialized in the symbol name.\n" "E : srelc This symbol represents a signed complex relocation expression, with the expression tree serialized in the symbol name.\n" "S : synthetic This symbol was created by bfd_get_synthetic_symtab.\n" "u : gnuidrctf This symbol is an indirect code object. Unrelated to BSF_INDIRECT. The dynamic linker will compute the value of this symbol by calling the function that it points to. BSF_FUNCTION must also be also set.\n" "U : gnunique This symbol is a globally unique data object. The dynamic linker will make sure that in the entire process there is just one symbol with this name and type in use. BSF_OBJECT must also be set.\n" #endif*/ ); } bool debug_bfd_resolve_address(void *address, const char *binary_file_path, const char **out_file, const char **out_function, u32 *out_line) { if(binary_file_path == NULL) { if(proc_self_exe == NULL) { proc_self_exe = debug_get_self_exe(); if(proc_self_exe == NULL) { return FALSE; } } binary_file_path = proc_self_exe; } pthread_mutex_lock(&bfd_mtx); if(!bfd_initialised) { bfd_init(); bfd_initialised = TRUE; debug_bfd_symbol_flag_help(); } ptr_node_debug *node = ptr_set_debug_insert(&bfd_collection, (char*)binary_file_path); bfd_node *bfdn = (bfd_node*)node->value; if(bfdn == NULL) { bfd* b = bfd_openr(binary_file_path, 0); if(b != NULL) { if(bfd_check_format(b, bfd_archive)) { bfd_close(b); return FALSE; } char **matching = NULL; if(!bfd_check_format_matches(b, bfd_object, &matching)) { free(matching); bfd_close(b); return FALSE; } bfdn = (bfd_node*)malloc(sizeof(bfd_node)); ZEROMEMORY(bfdn, sizeof(bfd_node)); bfdn->_bfd = b; u32 flags = bfd_get_file_flags(b); format_writer bfd_flags_writer = {debug_bfd_flags_format, (void*)(intptr)flags}; log_debug("bfd: %s: %w", binary_file_path, &bfd_flags_writer); format_writer bfd_symbol_flags_writer = {debug_bfd_symbol_flags_format, 0}; if( (bfdn->_has_symbols = (flags & HAS_SYMS)) ) { u32 tab_n = bfd_get_symtab_upper_bound(b); u32 dyntab_n = bfd_get_dynamic_symtab_upper_bound(b); bool dynamic = (flags & DYNAMIC); u32 n = (dynamic)?dyntab_n:tab_n; bfdn->_symbols = (asymbol**)malloc(n); if(!dynamic) { bfdn->_symbols_count = bfd_canonicalize_symtab(b, bfdn->_symbols); } else { bfdn->_symbols_count = bfd_canonicalize_dynamic_symtab(b, bfdn->_symbols); } bfdn->_text = bfd_get_section_by_name(b, ".text"); asymbol** sympa = bfdn->_symbols; for(u32 i = 0; i < bfdn->_symbols_count; i++) { asymbol *sym = sympa[i]; bfd_symbol_flags_writer.value = (void*)(intptr)sym->flags; log_debug1("bfd: %s %w %p", sym->name, &bfd_symbol_flags_writer, sym->value); } } node->key = strdup(binary_file_path); node->value = bfdn; } else { ptr_set_debug_delete(&bfd_collection, binary_file_path); } } pthread_mutex_unlock(&bfd_mtx); bool ret = FALSE; if(bfdn != NULL) { intptr offset = (intptr)address; if(offset >= bfdn->_text->vma) { offset -= bfdn->_text->vma; pthread_mutex_lock(&bfd_mtx); ret = bfd_find_nearest_line(bfdn->_bfd, bfdn->_text, bfdn->_symbols, offset, out_file, out_function, out_line); #if DEBUG if(!ret) { log_debug("bfd: line not found ..."); } #endif pthread_mutex_unlock(&bfd_mtx); } else { *out_line = 0; } } return ret; } static void debug_bfd_clear_delete(ptr_node_debug *node) { bfd_node *bfd = (bfd_node*)node->value; if(bfd != NULL) { free(bfd->_symbols); bfd_close(bfd->_bfd); free(bfd); } free(node->key); } void debug_bfd_clear() { pthread_mutex_lock(&bfd_mtx); ptr_set_debug_callback_and_destroy(&bfd_collection, debug_bfd_clear_delete); pthread_mutex_unlock(&bfd_mtx); } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/debug_malloc.c0000644000000000000000000000013214505005532022111 xustar000000000000000030 mtime=1695812442.372981185 30 atime=1695812445.791030139 30 ctime=1695812494.520728046 yadifa-2.6.5-11201/lib/dnscore/src/debug_malloc.c0000664000374500037450000012304314505005532022056 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup debug Debug functions * @ingroup dnscore * @brief Debug functions. * * Definitions of debug functions/hooks, mainly memory related. * * @{ */ #include "dnscore/dnscore-config.h" #include "dnscore/debug_config.h" #include #include #include #if defined(__linux__) #include #endif #include #include #include "dnscore/thread.h" #include "dnscore/timems.h" #if defined(__GLIBC__) || defined(__APPLE__) || defined(__FreeBSD__) #include #include #include #include #endif #include "dnscore/sys_types.h" #include "dnscore/format.h" #include "dnscore/debug.h" #include "dnscore/mutex.h" #include "dnscore/logger.h" #include "dnscore/ptr_set_debug.h" #include "dnscore/u64_set_debug.h" #include "dnscore/list-sl-debug.h" #undef malloc #undef free #undef realloc #undef calloc #undef debug_mtest #undef debug_stat #undef debug_mallocated #if defined(__GLIBC__) || defined(__APPLE__) #define DNSCORE_DEBUG_STACKTRACE 1 #else /* __FreeBSD__ or unknown */ #define DNSCORE_DEBUG_STACKTRACE 0 #endif #if defined(__GLIBC__) void *__libc_malloc(size_t); void *__libc_realloc (void *__ptr, size_t __size); void __libc_free(void*); void *__libc_memalign(size_t,size_t); #endif #if defined(__linux__) #define DNSCORE_DEBUG_MMAP 1 #endif extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #if DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT static pthread_mutex_t malloc_hook_mtx = PTHREAD_MUTEX_INITIALIZER; static ptr_set_debug malloc_hook_tracked_set = PTR_SET_DEBUG_PTR_EMPTY; static ptr_set_debug malloc_hook_caller_set = PTR_SET_DEBUG_PTR_EMPTY; volatile size_t malloc_hook_total = 0; volatile size_t malloc_hook_malloc = 0; volatile size_t malloc_hook_free = 0; volatile size_t malloc_hook_realloc = 0; volatile size_t malloc_hook_memalign = 0; struct malloc_hook_header_t { u64 begin; u32 magic; u32 size; stacktrace caller_stacktrace; #if __SIZEOF_POINTER__ == 4 u32 padding; #endif u64 end; }; typedef struct malloc_hook_header_t malloc_hook_header_t; void debug_malloc_hook_tracked_dump(); void debug_malloc_hook_caller_dump(); #endif /** * These are to ensure I get trashed memory at alloc and on a free. * => * No "lucky" inits. * No "lucky" destroyed uses. * */ #define DB_MALLOC_MAGIC 0xd1a2e81c #define DB_MFREED_MAGIC 0xe81cd1a2 #define MALLOC_PADDING 8 #define MALLOC_REALSIZE(mr_size_) ((mr_size_+(MALLOC_PADDING-1))&(-MALLOC_PADDING)) struct debug_memory_by_tag_info_s { s64 allocated_bytes_peak; s64 allocated_count_total; s64 freed_count_total; s64 allocated_count_peak; s64 allocated_bytes_total; s64 freed_bytes_total; s64 size; }; typedef struct debug_memory_by_tag_info_s debug_memory_by_tag_info_t; struct debug_memory_by_tag_context_s { u64_set_debug info_set; pthread_mutex_t mtx; s64 allocated_bytes_peak; s64 allocated_count_total; s64 freed_count_total; s64 allocated_count_peak; s64 allocated_bytes_total; s64 freed_bytes_total; const char *name; }; typedef struct debug_memory_by_tag_context_s debug_memory_by_tag_context_t; #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_HAS_BLOCK_TAG static debug_memory_by_tag_context_t malloc_debug_memory_by_tag_ctx; #endif #if DNSCORE_DEBUG_CHAIN_ALLOCATED_BLOCKS static debug_memory_by_tag_context_t *debug_memory_by_tag_contexts[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; static pthread_mutex_t debug_memory_by_tag_contexts_mtx = PTHREAD_MUTEX_INITIALIZER; #endif struct db_header { u32 magic; u32 size; #if DNSCORE_DEBUG_HAS_BLOCK_TAG #define HEADER_TAG_SIZE 8 u64 tag; #else #define HEADER_TAG_SIZE 0 #endif #if DNSCORE_DEBUG_SERIALNUMBERIZE_BLOCKS u64 serial; #endif #if DNSCORE_DEBUG_CHAIN_ALLOCATED_BLOCKS #define HEADER_SIZE_CHAIN (8+(2*__SIZEOF_POINTER__)) struct db_header* next; struct db_header* previous; #else #define HEADER_SIZE_CHAIN 0 #endif #if DNSCORE_DEBUG_STACKTRACE intptr* _trace; #endif }; typedef struct db_header db_header; #define HEADER_SIZE sizeof(db_header) #if DNSCORE_DEBUG_CHAIN_ALLOCATED_BLOCKS static db_header db_mem_first = { DB_MALLOC_MAGIC, 0, #if DNSCORE_DEBUG_HAS_BLOCK_TAG 0xffffffffffffffffLL, #endif #if DNSCORE_DEBUG_SERIALNUMBERIZE_BLOCKS 0, #endif #if DNSCORE_DEBUG_CHAIN_ALLOCATED_BLOCKS &db_mem_first, &db_mem_first, #endif #if DNSCORE_DEBUG_STACKTRACE NULL, #endif }; #define REAL_SIZE(rs_size_) MALLOC_REALSIZE((rs_size_)+HEADER_SIZE) #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_ENHANCED_STATISTICS /* [ 0] 1.. 8 * [ 1] 9.. 16 * [ 2] 17.. 24 * ... * [ 15] 121..128 * [ 31] 248..256 * [ 32] 257..2^31 */ static u64 db_alloc_count_by_size[(DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE / 8) + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static u64 db_alloc_peak_by_size[(DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE / 8) + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static u64 db_total_allocated = 0; static u64 db_total_freed = 0; static u64 db_current_allocated = 0; static u64 db_current_blocks = 0; static u64 db_peak_allocated = 0; #endif #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_SERIALNUMBERIZE_BLOCKS static u64 db_next_block_serial = 0; #endif #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT || DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT static bool db_showallocs = DNSCORE_DEBUG_SHOW_ALLOCS; static pthread_mutex_t alloc_mutex = PTHREAD_MUTEX_INITIALIZER; #endif void debug_bench_malloc_init() { #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT { pthread_mutexattr_t mta; pthread_mutexattr_init(&mta); pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&alloc_mutex, &mta); } #if DNSCORE_DEBUG_HAS_BLOCK_TAG debug_memory_by_tag_init(&malloc_debug_memory_by_tag_ctx, "malloc"); #endif #endif } #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT || DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT void debug_malloc_mutex_lock() { pthread_mutex_lock(&alloc_mutex); } void debug_malloc_mutex_unlock() { pthread_mutex_unlock(&alloc_mutex); } #endif static void debug_memory_by_tag_context_register(debug_memory_by_tag_context_t* ctx) { pthread_mutex_lock(&debug_memory_by_tag_contexts_mtx); for(int i = 0; i < (int)(sizeof(debug_memory_by_tag_contexts) / sizeof(debug_memory_by_tag_context_t*)); ++i) { if(debug_memory_by_tag_contexts[i] == NULL) { debug_memory_by_tag_contexts[i] = ctx; break; } if(debug_memory_by_tag_contexts[i] == ctx) { break; } } pthread_mutex_unlock(&debug_memory_by_tag_contexts_mtx); } static void debug_memory_by_tag_context_unregister(debug_memory_by_tag_context_t* ctx) { pthread_mutex_lock(&debug_memory_by_tag_contexts_mtx); for(int i = 0; i < (int)(sizeof(debug_memory_by_tag_contexts) / sizeof(debug_memory_by_tag_context_t*)); ++i) { if(debug_memory_by_tag_contexts[i] == ctx) { for(;i < (int)(sizeof(debug_memory_by_tag_contexts) / sizeof(debug_memory_by_tag_context_t*)) - 1; ++i) { debug_memory_by_tag_contexts[i] = debug_memory_by_tag_contexts[i + 1]; } debug_memory_by_tag_contexts[sizeof(debug_memory_by_tag_contexts) / sizeof(debug_memory_by_tag_context_t*) - 1] = NULL; break; } } pthread_mutex_unlock(&debug_memory_by_tag_contexts_mtx); } debug_memory_by_tag_context_t* debug_memory_by_tag_new_instance(const char* name) { debug_memory_by_tag_context_t *ctx = (debug_memory_by_tag_context_t*)debug_malloc_unmonitored(sizeof(debug_memory_by_tag_context_t)); if(ctx != NULL) { debug_memory_by_tag_init(ctx, name); } return ctx; } void debug_memory_by_tag_delete(debug_memory_by_tag_context_t *ctx) { if(ctx != NULL) { debug_memory_by_tag_finalize(ctx); debug_free_unmonitored(ctx); } } void debug_memory_by_tag_init(debug_memory_by_tag_context_t *ctx, const char* name) { ZEROMEMORY(ctx, sizeof(debug_memory_by_tag_context_t)); u64_set_debug_init(&ctx->info_set); pthread_mutex_init(&ctx->mtx, NULL); ctx->name = name; debug_memory_by_tag_context_register(ctx); } static void debug_memory_by_tag_finalize_cb(u64_node_debug *node) { debug_free_unmonitored(node->value); node->value = NULL; } void debug_memory_by_tag_finalize(debug_memory_by_tag_context_t *ctx) { debug_memory_by_tag_context_unregister(ctx); pthread_mutex_lock(&ctx->mtx); u64_set_debug_callback_and_destroy(&ctx->info_set, debug_memory_by_tag_finalize_cb); pthread_mutex_unlock(&ctx->mtx); pthread_mutex_destroy(&ctx->mtx); } #define ZDB_RECORD_TAG 0x4443455242445a /** "ZDBRECD" */ void break_here() { } void debug_memory_by_tag_alloc_notify(debug_memory_by_tag_context_t *ctx, u64 tag, s64 size) { if(tag == ZDB_RECORD_TAG) { break_here(); } pthread_mutex_lock(&ctx->mtx); debug_memory_by_tag_info_t *info; u64_node_debug *node = u64_set_debug_insert(&ctx->info_set, tag); if(node->value != NULL) { info = (debug_memory_by_tag_info_t *)node->value; } else { info = (debug_memory_by_tag_info_t*)debug_malloc_unmonitored(sizeof(debug_memory_by_tag_info_t)); ZEROMEMORY(info, sizeof(debug_memory_by_tag_info_t)); info->size = size; node->value = info; } ++info->allocated_count_total; info->allocated_bytes_total += (s64)size; info->allocated_count_peak = MAX(info->allocated_count_peak, info->allocated_count_total - info->freed_count_total); info->allocated_bytes_peak = MAX(info->allocated_bytes_peak, info->allocated_bytes_total - info->freed_bytes_total); ++ctx->allocated_count_total; ctx->allocated_bytes_total += (s64)size; ctx->allocated_count_peak = MAX(ctx->allocated_count_peak, ctx->allocated_count_total - ctx->freed_count_total); ctx->allocated_bytes_peak = MAX(ctx->allocated_bytes_peak, ctx->allocated_bytes_total - ctx->freed_bytes_total); pthread_mutex_unlock(&ctx->mtx); } void debug_memory_by_tag_free_notify(debug_memory_by_tag_context_t *ctx, u64 tag, s64 size) { pthread_mutex_lock(&ctx->mtx); debug_memory_by_tag_info_t *info; u64_node_debug *node = u64_set_debug_insert(&ctx->info_set, tag); if(node->value != NULL) { info = (debug_memory_by_tag_info_t *)node->value; } else { info = (debug_memory_by_tag_info_t*)debug_malloc_unmonitored(sizeof(debug_memory_by_tag_info_t)); ZEROMEMORY(info, sizeof(debug_memory_by_tag_info_t)); node->value = info; } ++info->freed_count_total; info->freed_bytes_total += size; ++ctx->freed_count_total; ctx->freed_bytes_total += size; pthread_mutex_unlock(&ctx->mtx); } void debug_memory_by_tag_print(debug_memory_by_tag_context_t *ctx, output_stream *os) { pthread_mutex_lock(&ctx->mtx); s64 now = timeus(); osformatln(os,"debug_memory: %s set: %llT %lli", ctx->name, now, now); u64_set_debug_iterator iter; u64_set_debug_iterator_init(&ctx->info_set, &iter); osprintln(os," ________ | ALLOCATED_ | FREED_____ | CURRENT___ | PEAK______ | alloc c | freed c | current c| peak c | mean"); while(u64_set_debug_iterator_hasnext(&iter)) { u64_node_debug *node = u64_set_debug_iterator_next_node(&iter); debug_memory_by_tag_info_t *info = (debug_memory_by_tag_info_t*)node->value; char tag_name[sizeof(node->key)]; u64 *tag_namep = (u64*)&tag_name[0]; // pointing to tag_name *tag_namep = node->key; // setting-up 64 bits of tag_name in one operation for(int i = 0; i < (int)sizeof(node->key); ++i) { if(tag_name[i] == '\0') // scan-build false positive: tag_name has been fully initialised 3 lines above. { tag_name[i] = 32; // space character } } output_stream_write(os, "TAG ", 4); output_stream_write(os, tag_name, sizeof(tag_name)); osformatln(os, " | %10lli | %10lli | %10lli | %10lli | %8lli | %8lli | %8lli | %8lli | %8lli", info->allocated_bytes_total, info->freed_bytes_total, info->allocated_bytes_total - info->freed_bytes_total, info->allocated_bytes_peak, info->allocated_count_total, info->freed_count_total, info->allocated_count_total - info->freed_count_total, info->allocated_count_peak, info->allocated_bytes_total / MAX(info->allocated_count_total, 1)); } // TAG XXXXXXXX osformatln(os, " TOTAL | %10lli | %10lli | %10lli | %10lli | %8lli | %8lli | %8lli | %8lli | %8lli", ctx->allocated_bytes_total, ctx->freed_bytes_total, ctx->allocated_bytes_total - ctx->freed_bytes_total, ctx->allocated_bytes_peak, ctx->allocated_count_total, ctx->freed_count_total, ctx->allocated_count_total - ctx->freed_count_total, ctx->allocated_count_peak, ctx->allocated_bytes_total / MAX(ctx->allocated_count_total, 1)); osprintln(os," ________ | ALLOCATED_ | FREED_____ | CURRENT___ | PEAK______ | alloc c | freed c | current c| peak c | mean"); pthread_mutex_unlock(&ctx->mtx); } #endif // DNSCORE_DEBUG_HAS_BLOCK_TAG /** * These functions allow to add information to an allocation (e.g. file, line, tag) */ #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT void* debug_malloc( size_t size_, const char* file, int line #if DNSCORE_DEBUG_HAS_BLOCK_TAG , u64 tag #endif ) { size_t size = MALLOC_REALSIZE(size_); #if DNSCORE_DEBUG_HAS_BLOCK_TAG assert((tag != 0) && (tag != ~0ULL)); #endif pthread_mutex_lock(&alloc_mutex); u64 current_allocated = db_current_allocated; #if DNSCORE_DEBUG_HAS_BLOCK_TAG debug_memory_by_tag_alloc_notify(&malloc_debug_memory_by_tag_ctx, tag, size); #endif pthread_mutex_unlock(&alloc_mutex); if(current_allocated + size > DNSCORE_DEBUG_ALLOC_MAX) { if(__termout__.vtbl != NULL) { format("DB_MAX_ALLOC reached !!! (%u)", DNSCORE_DEBUG_ALLOC_MAX); } abort(); } db_header* ptr = (db_header*)debug_malloc_unmonitored(size + HEADER_SIZE); /* Header */ if(ptr == NULL) { perror("debug_malloc"); fflush(NULL); abort(); } pthread_mutex_lock(&alloc_mutex); #if DNSCORE_DEBUG_STACKTRACE ptr->_trace = debug_stacktrace_get(); #endif ptr->magic = DB_MALLOC_MAGIC; ptr->size = size; #if DNSCORE_DEBUG_HAS_BLOCK_TAG ptr->tag = tag; #endif #if DNSCORE_DEBUG_SERIALNUMBERIZE_BLOCKS ptr->serial = ++db_next_block_serial; if(ptr->serial == 0x01cb || ptr->serial == 0x01d0) { time(NULL); } #endif #if DNSCORE_DEBUG_CHAIN_ALLOCATED_BLOCKS ptr->next = &db_mem_first; ptr->previous = db_mem_first.previous; db_mem_first.previous->next = ptr; db_mem_first.previous = ptr; #endif db_total_allocated += size; db_current_allocated += size; db_peak_allocated = MAX(db_current_allocated, db_peak_allocated); db_current_blocks++; #if DNSCORE_DEBUG_ENHANCED_STATISTICS if(size_ < DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE) { db_alloc_count_by_size[(size_ - 1) >> 3]++; db_alloc_peak_by_size[(size_ - 1) >> 3]++; } else { db_alloc_count_by_size[DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE >> 3]++; db_alloc_peak_by_size[DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE >> 3]++; } #endif pthread_mutex_unlock(&alloc_mutex); if(db_showallocs) { if(__termout__.vtbl != NULL) { format("[%08x] malloc(%3x", thread_self(), (u32)size); #if DNSCORE_DEBUG_HAS_BLOCK_TAG print(" | "); debug_dump((u8*) & ptr->tag, 8, 8, FALSE, TRUE); #endif #if DNSCORE_DEBUG_SERIALNUMBERIZE_BLOCKS format(" | #%08llx", ptr->serial); #endif formatln(")=%p (%s:%i)", ptr + 1, file, line); } } ptr++; /* ensure the memory is not initialized "by chance" */ #if DNSCORE_DEBUG_MALLOC_TRASHMEMORY memset(ptr, 0xac, size_); /* AC : AlloCated */ memset(((u8*)ptr) + size_, 0xca, size - size_); /* CA : AlloCated for padding */ #endif return ptr; } void* debug_calloc( size_t size_, const char* file, int line #if DNSCORE_DEBUG_HAS_BLOCK_TAG , u64 tag #endif ) { void* p = debug_malloc(size_, file, line #if DNSCORE_DEBUG_HAS_BLOCK_TAG , tag #endif ); if(p != NULL) { ZEROMEMORY(p, size_); } return p; } void debug_free(void* ptr_, const char* file, int line) { if(ptr_ == NULL) { return; } db_header* ptr = (db_header*)ptr_; ptr--; if(ptr->magic != DB_MALLOC_MAGIC) { fflush(NULL); if(__termout__.vtbl != NULL) { if(ptr->magic == DB_MFREED_MAGIC) { formatln("DOUBLE FREE @ %p (%s:%i)", ptr, file, line); } else { formatln("MEMORY CORRUPTED @%p (%s:%i)", ptr, file, line); } } stacktrace trace = debug_stacktrace_get(); debug_stacktrace_print(termout, trace); debug_dump(ptr, 64, 32, TRUE, TRUE); flushout(); abort(); } size_t size = ptr->size; if(db_showallocs) { if(__termout__.vtbl != NULL) { format("[%08x] free(%p [%3x]", thread_self(), ptr + 1, (u32)size); #if DNSCORE_DEBUG_HAS_BLOCK_TAG print(" | "); debug_dump((u8*) & ptr->tag, 8, 8, FALSE, TRUE); #endif #if DNSCORE_DEBUG_SERIALNUMBERIZE_BLOCKS format(" | #%08llx", ptr->serial); #endif formatln(") (%s:%i)", file, line); } } pthread_mutex_lock(&alloc_mutex); #if DNSCORE_DEBUG_HAS_BLOCK_TAG debug_memory_by_tag_free_notify(&malloc_debug_memory_by_tag_ctx, ptr->tag, size); #endif #if DNSCORE_DEBUG_CHAIN_ALLOCATED_BLOCKS ptr->previous->next = ptr->next; ptr->next->previous = ptr->previous; ptr->next = (void*)~0; ptr->previous = (void*)~0; #endif db_total_freed += size; db_current_allocated -= size; db_current_blocks--; #if DNSCORE_DEBUG_ENHANCED_STATISTICS if(size < DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE) { db_alloc_count_by_size[(size - 1) >> 3]--; } else { db_alloc_count_by_size[DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE >> 3]--; } #endif pthread_mutex_unlock(&alloc_mutex); ptr->magic = DB_MFREED_MAGIC; /* This is destroyed AFTER free */ memset(ptr + 1, 0xfe, size); /* FE : FrEed */ debug_free_unmonitored(ptr); } void * debug_realloc(void* ptr, size_t size, const char* file, int line) { #if DNSCORE_DEBUG_HAS_BLOCK_TAG u64 tag = 0x4c554e4152; #endif db_header* hdr; if(ptr != NULL) { hdr = (db_header*)ptr; hdr--; #if DNSCORE_DEBUG_HAS_BLOCK_TAG tag = hdr->tag; #endif } void* newptr = debug_malloc(size, file, line #if DNSCORE_DEBUG_HAS_BLOCK_TAG , tag #endif ); if(ptr != NULL) { if(hdr->size < size) { size = hdr->size; } MEMCOPY(newptr, ptr, size); debug_free(ptr, file, line); } return newptr; } #endif void debug_mtest(void* ptr_) { if(ptr_ == NULL) { return; } db_header* ptr = (db_header*)ptr_; ptr--; if(ptr->magic != DB_MALLOC_MAGIC) { if(__termout__.vtbl != NULL) { if(ptr->magic == DB_MFREED_MAGIC) { formatln("DOUBLE FREE @ %p", ptr); } else { formatln("MEMORY CORRUPTED @%p", ptr); } } stacktrace trace = debug_stacktrace_get(); debug_stacktrace_print(termout, trace); debug_dump(ptr, 64, 32, TRUE, TRUE); abort(); } } u32 debug_get_block_count() { #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_ENHANCED_STATISTICS return db_current_blocks; #else return 0; #endif } bool debug_mallocated(void* ptr) { if(ptr == NULL) { /* NULL is ok */ return TRUE; } db_header* hdr = (db_header*)ptr; hdr--; if(hdr->magic == DB_MALLOC_MAGIC) { return TRUE; } else if(hdr->magic == DB_MFREED_MAGIC) { if(__termout__.vtbl != NULL) { if(hdr->magic == DB_MFREED_MAGIC) { formatln("DOUBLE FREE @ %p", ptr); debug_dump_page(ptr); } } return FALSE; } else { if(__termout__.vtbl != NULL) { formatln("MEMORY CORRUPTED @%p", ptr); debug_dump_page(ptr); } assert(FALSE); return FALSE; } } #if DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT #define DEBUG_MALLOC_HOOK_DUMP 0 /** * Returns true iff the ptr is a tracked memory bloc */ static bool debug_malloc_istracked(void* ptr) { bool ret; pthread_mutex_lock(&malloc_hook_mtx); ptr_node_debug *node = ptr_set_debug_find(&malloc_hook_tracked_set, ptr); ret = (node != NULL); pthread_mutex_unlock(&malloc_hook_mtx); return ret; } /** * Adds the ptr to tracked memory bloc set */ static void debug_malloc_track_alloc_nolock(void* ptr) { //formatln("track alloc %p", ptr); ptr_node_debug *node = ptr_set_debug_insert(&malloc_hook_tracked_set, ptr); intptr flags = (intptr)node->value; if(flags != 0) { // track bug pthread_mutex_unlock(&malloc_hook_mtx); abort(); } flags |= 1; node->value = (void*)flags; } /** * Removes the ptr to tracked memory bloc set */ static void debug_malloc_track_free_nolock(void* ptr) { //formatln("track free %p", ptr); ptr_node_debug *node = ptr_set_debug_find(&malloc_hook_tracked_set, ptr); if(node == NULL) { // free of non-existing pthread_mutex_unlock(&malloc_hook_mtx); abort(); } intptr flags = (intptr)node->value; if((flags & 1) != 1) { // double free pthread_mutex_unlock(&malloc_hook_mtx); abort(); } flags &= ~1; node->value = (void*)flags; } /** * Lists all the tracked memory blocs to stdout */ void debug_malloc_hook_tracked_dump() { pthread_mutex_lock(&malloc_hook_mtx); ptr_set_debug_iterator iter; ptr_set_debug_iterator_init(&malloc_hook_tracked_set, &iter); while(ptr_set_debug_iterator_hasnext(&iter)) { const ptr_node_debug *node = ptr_set_debug_iterator_next_node(&iter); if(((intptr)node->value) == 1) { const malloc_hook_header_t *hdr = (const malloc_hook_header_t*)node->key; --hdr; formatln("%p : size=%llu caller=%p", node->key, hdr->size, hdr->caller_stacktrace); } } pthread_mutex_unlock(&malloc_hook_mtx); } struct malloc_hook_caller_t { ssize_t count; ssize_t size; ssize_t peak; }; typedef struct malloc_hook_caller_t malloc_hook_caller_t; /** * Adds size bytes to the caller_address (to track memory usage) */ static void debug_malloc_caller_add(const void* caller_stacktrace, ssize_t size) { ptr_node_debug *node = ptr_set_debug_insert(&malloc_hook_caller_set, (void*)caller_stacktrace); malloc_hook_caller_t *caller = (malloc_hook_caller_t*)node->value; if(caller == NULL) { caller = (malloc_hook_caller_t*)debug_malloc_unmonitored(sizeof(malloc_hook_caller_t)); memset(caller, 0, sizeof(malloc_hook_caller_t)); node->value = caller; } if(size > 0) { ++caller->count; } else if(size < 0) { --caller->count; } caller->size += size; if(caller->size > caller->peak) { caller->peak = caller->size; } } void debug_malloc_hook_caller_dump() { formatln("debug_malloc_hook_caller_dump(): begin"); ssize_t count_total = 0; ssize_t size_total = 0; pthread_mutex_lock(&malloc_hook_mtx); ptr_set_debug_iterator iter; ptr_set_debug_iterator_init(&malloc_hook_caller_set, &iter); while(ptr_set_debug_iterator_hasnext(&iter)) { const ptr_node_debug *node = ptr_set_debug_iterator_next_node(&iter); stacktrace st = (stacktrace)node->key; const malloc_hook_caller_t *caller = (malloc_hook_caller_t*)node->value; ssize_t count = caller->count; if(count == 0) { continue; } ssize_t mean = 0; ssize_t size = caller->size; if(count != 0) { mean = size / count; } debug_stacktrace_print(termout, st); formatln("**************** count=%lli size=%lli peak=%lli (mean bloc size=%lli)", caller->count, caller->size, caller->peak, mean); count_total += caller->count; size_total += caller->size; } pthread_mutex_unlock(&malloc_hook_mtx); formatln("COUNT TOTAL : %lli", count_total); formatln("SIZE TOTAL : %lli", size_total); formatln("debug_malloc_hook_caller_dump(): end"); } /** * Allocates memory with a few added information. */ static void *debug_malloc_hook(size_t size, const stacktrace caller_stacktrace) { void *ret = debug_malloc_unmonitored(size + sizeof(malloc_hook_header_t)); if(ret != NULL) { malloc_hook_header_t *hdr = (malloc_hook_header_t*)ret; hdr->begin = 0x4242424242424242; hdr->magic = 0xd1a27344; hdr->size = size; hdr->caller_stacktrace = caller_stacktrace; hdr->end = 0x4545454545454545; ++hdr; pthread_mutex_lock(&malloc_hook_mtx); malloc_hook_total += size; malloc_hook_malloc++; debug_malloc_caller_add(caller_stacktrace, size); debug_malloc_track_alloc_nolock(hdr); pthread_mutex_unlock(&malloc_hook_mtx); #if DEBUG_MALLOC_HOOK_DUMP formatln("malloc(%llu) = %p", size, hdr); #endif return hdr; } else { return ret; } } /** * Reallocates memory with a few added information. */ static void *debug_realloc_hook(void *ptr, size_t size, const stacktrace caller_stacktrace) { if(ptr != NULL) { if(!debug_malloc_istracked(ptr)) { #if DEBUG_MALLOC_HOOK_DUMP formatln("realloc(%p, %llu) untracked", ptr, size); #endif return debug_realloc_unmonitored(ptr, size); } malloc_hook_header_t *hdr = (malloc_hook_header_t*)ptr; --hdr; if(hdr->magic != 0xd1a27344) { abort(); } malloc_hook_header_t *old_hdr = hdr; hdr->begin = 0x6262626262626262; // trashes the memory in case the ptr moves hdr->magic = 0xbad15bad; hdr->end = 0x6565656565656565; const void* old_caller = hdr->caller_stacktrace; ssize_t old_size = hdr->size; void *ret = debug_realloc_unmonitored(hdr, size + sizeof(malloc_hook_header_t)); if(ret != NULL) { hdr = (malloc_hook_header_t*)ret; hdr->begin = 0x4242424242424242; hdr->magic = 0xd1a27344; hdr->size = size; hdr->caller_stacktrace = caller_stacktrace; hdr->end = 0x4545454545454545; ++hdr; pthread_mutex_lock(&malloc_hook_mtx); debug_malloc_caller_add(old_caller, -old_size); debug_malloc_track_free_nolock(ptr); malloc_hook_total += size - old_size; malloc_hook_realloc++; debug_malloc_caller_add(caller_stacktrace, size); debug_malloc_track_alloc_nolock(hdr); pthread_mutex_unlock(&malloc_hook_mtx); #if DEBUG_MALLOC_HOOK_DUMP formatln("realloc(%p, %llu) = %p", ptr, size, hdr); #endif return hdr; } else { old_hdr->begin = 0x4242424242424242; hdr->magic = 0xd1a27344; old_hdr->end = 0x4545454545454545; return ret; } } else { ptr = debug_malloc_hook(size, caller_stacktrace); return ptr; } } /** * Frees memory with a few added information. */ static void debug_free_hook(void *ptr) { if(ptr != NULL) { if(!debug_malloc_istracked(ptr)) { #if DEBUG_MALLOC_HOOK_DUMP formatln("free(%p) untracked", ptr); #endif debug_free_unmonitored(ptr); return; } malloc_hook_header_t *hdr = (malloc_hook_header_t*)ptr; --hdr; if(hdr->magic != 0xd1a27344) { abort(); } hdr->begin = 0x6262626262626262; hdr->end = 0x6565656565656565; ssize_t size = hdr->size; pthread_mutex_lock(&malloc_hook_mtx); malloc_hook_total -= size; malloc_hook_free++; debug_malloc_caller_add(hdr->caller_stacktrace, -size); debug_malloc_track_free_nolock(ptr); pthread_mutex_unlock(&malloc_hook_mtx); debug_free_unmonitored(hdr); #if DEBUG_MALLOC_HOOK_DUMP formatln("free(%p)", ptr); #endif } } /** * Allocates memory-aligned memory with a few added information. */ static void *debug_memalign_hook(size_t alignment, size_t size, const stacktrace caller_stacktrace) { void *ret = debug_memalign_unmonitored(alignment, size + sizeof(malloc_hook_header_t)); if(ret != NULL) { malloc_hook_header_t *hdr = (malloc_hook_header_t*)ret; hdr->begin = 0x4242424242424242; hdr->magic = 0xd1a27344; hdr->size = size; hdr->caller_stacktrace = caller_stacktrace; hdr->end = 0x4545454545454545; ++hdr; pthread_mutex_lock(&malloc_hook_mtx); malloc_hook_total += size; malloc_hook_memalign++; debug_malloc_caller_add(caller_stacktrace, size); debug_malloc_track_alloc_nolock(hdr); pthread_mutex_unlock(&malloc_hook_mtx); #if DEBUG_MALLOC_HOOK_DUMP formatln("memalign(%llu, %llu) = %p", alignment, size, hdr); #endif return hdr; } else { return ret; } } void debug_malloc_hooks_init() { } void debug_malloc_hooks_finalize() { } static thread_local int g_malloc_busy = 0; void malloc_busy_acquire() { ++g_malloc_busy; } void malloc_busy_release() { --g_malloc_busy; } void *malloc(size_t size) { void *ret; if(g_malloc_busy == 0) { ++g_malloc_busy; stacktrace st = debug_stacktrace_get_ex(2); ret = debug_malloc_hook(size, st); --g_malloc_busy; } else { ret = debug_malloc_unmonitored(size); } return ret; } void *realloc (void *ptr, size_t size) { void *ret; if(!g_malloc_busy) { stacktrace st = debug_stacktrace_get_ex(2); ret = debug_realloc_hook(ptr, size, st); } else { ret = debug_realloc_unmonitored(ptr, size); } return ret; } void free(void* ptr) { debug_free_hook(ptr); } void *memalign(size_t aligned,size_t size) { void *ret; if(!g_malloc_busy) { stacktrace st = debug_stacktrace_get_ex(2); ret = debug_memalign_hook(aligned, size, st); } else { ret = debug_memalign_unmonitored(aligned, size); } return ret; } void *debug_malloc_unmonitored(size_t size) { return __libc_malloc(size); } void *debug_realloc_unmonitored(void* ptr, size_t size) { return __libc_realloc(ptr, size); } void debug_free_unmonitored(void* ptr) { __libc_free(ptr); } void *debug_memalign_unmonitored(size_t alignment, size_t size) { return __libc_memalign(alignment, size); } #else void debug_malloc_hooks_init() { } void debug_malloc_hooks_finalize() { } void *debug_malloc_unmonitored(size_t size) { void *ptr = malloc(size); if(ptr == NULL) { abort(); } return ptr; } void debug_free_unmonitored(void* ptr) { free(ptr); } void debug_malloc_hook_tracked_dump() { } #endif /** * Prints various statistics on stdout */ void debug_memory_stat(int mask) { if(__termout__.vtbl == NULL) { return; } #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_ENHANCED_STATISTICS pthread_mutex_lock(&alloc_mutex); formatln("%16llx | DB: MEM: Total Allocated=%llu", timeus(), db_total_allocated); formatln("%16llx | DB: MEM: Total Freed=%llu", timeus(), db_total_freed); formatln("%16llx | DB: MEM: Peak Usage=%llu", timeus(), db_peak_allocated); formatln("%16llx | DB: MEM: Allocated=%llu", timeus(), db_current_allocated); formatln("%16llx | DB: MEM: Blocks=%llu", timeus(), db_current_blocks); formatln("%16llx | DB: MEM: Monitoring Overhead=%llu (%i)", timeus(), (u64)(db_current_blocks * HEADER_SIZE), (int)HEADER_SIZE); #if DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT formatln("%16llx | C ALLOC: total: %llu malloc=%llu free=%llu realloc=%llu memalign=%llu", timeus(), malloc_hook_total, malloc_hook_malloc, malloc_hook_free, malloc_hook_realloc, malloc_hook_memalign); #endif #else if(mask == 0) { return; } #endif #if DNSCORE_HAS_MMAP_DEBUG_SUPPORT if(mask & DEBUG_STAT_MMAP) { debug_mmap_stat(); } #endif #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT && DNSCORE_DEBUG_ENHANCED_STATISTICS if(mask & DEBUG_STAT_SIZES) { formatln("%16llx | DB: MEM: Block sizes: ([size/8]={current / peak}", timeus()); format("%16llx | ", timeus()); int i; for(i = 0; i < (DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE >> 3); i++) { format("[%4i]={%8llu / %8llu} ;", (i + 1) << 3, db_alloc_count_by_size[i], db_alloc_peak_by_size[i]); if((i & 3) == 3) { format("\n%16llx | ", timeus()); } } println(""); formatln("%16llx | [++++]={%8llu / %8llu}", timeus(), db_alloc_count_by_size[DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE >> 3], db_alloc_peak_by_size[DNSCORE_DEBUG_ENHANCED_STATISTICS_MAX_MONITORED_SIZE >> 3]); } #endif #if DNSCORE_DEBUG_HAS_BLOCK_TAG if(mask & DEBUG_STAT_TAGS) { output_stream *os = termout; s64 allocated_bytes_peak = 0; s64 allocated_count_total = 0; s64 freed_count_total = 0; s64 allocated_count_peak = 0; s64 allocated_bytes_total = 0; s64 freed_bytes_total = 0; for(int i = 0; i < (int)(sizeof(debug_memory_by_tag_contexts) / sizeof(debug_memory_by_tag_context_t*)); ++i) { debug_memory_by_tag_context_t *ctx = debug_memory_by_tag_contexts[i]; if(ctx == NULL) { break; } debug_memory_by_tag_print(ctx, os); allocated_bytes_peak += ctx->allocated_bytes_peak; allocated_count_total += ctx->allocated_count_total; freed_count_total += ctx->freed_count_total; allocated_count_peak += ctx->allocated_count_peak; allocated_bytes_total += ctx->allocated_bytes_total; freed_bytes_total += ctx->freed_bytes_total; } osformatln(os, " GRAND TOTAL | %10lli | %10lli | %10lli | %10lli | %8lli | %8lli | %8lli | %8lli", allocated_bytes_total, freed_bytes_total, allocated_bytes_total - freed_bytes_total, allocated_bytes_peak, allocated_count_total, freed_count_total, allocated_count_total - freed_count_total, allocated_count_peak); osprintln(os," ________ | ALLOCATED_ | FREED_____ | CURRENT___ | PEAK______ | alloc c | freed c | current c| peak c |"); } #endif #if DNSCORE_DEBUG_CHAIN_ALLOCATED_BLOCKS if(mask & DEBUG_STAT_WALK) { db_header *ptr; u64 mintag = MAX_U64; u64 nexttag; // find the minimum for(ptr = db_mem_first.next; ptr != &db_mem_first; ptr = ptr->next) { u64 tag = ptr->tag; if(tag < mintag) { mintag = tag; } } formatln("%16llx | ", timeus()); // 0123456789ABCDEF 012345678 012345678 012345678 012345678 012345678 formatln("%16llx | [-----TAG------] : COUNT : MIN : MAX : MEAN : TOTAL", timeus()); for(; mintag != MAX_U64; mintag = nexttag) { nexttag = MAX_U64; u32 count = 0; u32 minsize = MAX_U32; u32 maxsize = 0; u64 totalsize = 0; for(ptr = db_mem_first.next; ptr != &db_mem_first; ptr = ptr->next) { u64 tag = ptr->tag; if((tag > mintag) && (tag < nexttag)) { nexttag = tag; continue; } if(tag != mintag) { continue; } count++; totalsize += ptr->size; if(ptr->size < minsize) { minsize = ptr->size; } if(ptr->size > maxsize) { maxsize = ptr->size; } } char tag_text[9]; SET_U64_AT(tag_text[0], mintag); tag_text[8] = '\0'; if(count > 0) { formatln("%16llx | %16s : %10u : %10u : %10u : %10u : %12llu", timeus(), tag_text, count, minsize, maxsize, totalsize / count, totalsize); } else { formatln("%16llx | %16s : %10u : %10u : %10u : ---------- : %12llu", timeus(), tag_text, count, minsize, maxsize, totalsize); } } formatln("%16llx | ", timeus()); } flushout(); if(mask & DEBUG_STAT_DUMP) { db_header* ptr = db_mem_first.next; int index = 0; while(ptr != &db_mem_first) { formatln("block #%04x %16p [%08x]\nBLOCK ", index, (void*)& ptr[1], ptr->size); #if DNSCORE_DEBUG_HAS_BLOCK_TAG debug_dump((u8*) & ptr->tag, 8, 8, FALSE, TRUE); formatln(" | "); #endif #if DNSCORE_DEBUG_STACKTRACE int n = 0; intptr *st = ptr->_trace; if(st != NULL) { while(st[n] != 0) { ++n; } char **trace_strings = (char**)st[n + 1]; for(int i = 0; i < n; i++) { formatln("%p %s", (void*)st[i], (trace_strings != NULL) ? trace_strings[i] : "???"); } } #endif #if DNSCORE_DEBUG_SERIALNUMBERIZE_BLOCKS formatln("#%08llx | ", ptr->serial); #endif osprint_dump(termout, & ptr[1], MIN(ptr->size, 128), 32, OSPRINT_DUMP_ALL); formatln("\n"); ptr = ptr->next; index++; } flushout(); flusherr(); //malloc_stats(); //malloc_info(0, stdout); } #endif #if DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT debug_malloc_hook_caller_dump(); #endif #if DEBUG debug_bench_print_all(termout); #endif #if defined(__GLIBC__) || defined(__APPLE__) || defined(__FreeBSD__) shared_heap_print_map(0, NULL, NULL); #endif #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT || DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT pthread_mutex_unlock(&alloc_mutex); #endif } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/debug_mmap.c0000644000000000000000000000013214505005532021574 xustar000000000000000030 mtime=1695812442.476982675 30 atime=1695812445.795030196 30 ctime=1695812494.522728075 yadifa-2.6.5-11201/lib/dnscore/src/debug_mmap.c0000664000374500037450000001271314505005532021542 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup debug Debug functions * @ingroup dnscore * @brief Debug functions. * * Definitions of debug functions/hooks, mainly memory related. * * @{ */ #include "dnscore/dnscore-config.h" #include "dnscore/debug_config.h" #include #include #include #include #include #include "dnscore/sys_types.h" #include "dnscore/format.h" #include "dnscore/debug.h" #include "dnscore/mutex.h" #include "dnscore/logger.h" #include "dnscore/ptr_set_debug.h" #undef malloc #undef free #undef realloc #undef calloc #undef debug_mtest #undef debug_stat #undef debug_mallocated extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger struct debug_mmap_s { void *addr; size_t len; int prot; int flags; int fildes; off_t off; s64 ts; stacktrace trace; void *mapped; }; typedef struct debug_mmap_s debug_mmap_t; #undef mmap #undef munmap #if DNSCORE_HAS_MMAP_DEBUG_SUPPORT static ptr_set_debug debug_mmap_set = PTR_SET_DEBUG_EMPTY; static pthread_mutex_t debug_mmap_mtx = PTHREAD_MUTEX_INITIALIZER; void* debug_mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) { // DO NOT: formatln("debug_mmap(%p, %llx, %i, %i, %i, %lli)", addr, len, prot, flags, fildes, off); void *ret = mmap(addr, len, prot, flags, fildes, off); if(ret != MAP_FAILED) { debug_mmap_t *debug_mmap = (debug_mmap_t*)debug_malloc_unmonitored(sizeof(debug_mmap_t)); debug_mmap->addr = addr; debug_mmap->len = len; debug_mmap->prot = prot; debug_mmap->flags = flags; debug_mmap->fildes = fildes; debug_mmap->off = off; debug_mmap->trace = debug_stacktrace_get(); debug_mmap->ts = timeus(); debug_mmap->mapped = ret; pthread_mutex_lock(&debug_mmap_mtx); ptr_node_debug *node = ptr_set_debug_insert(&debug_mmap_set, ret); node->value = debug_mmap; pthread_mutex_unlock(&debug_mmap_mtx); } return ret; } int debug_munmap(void *addr, size_t len) { pthread_mutex_lock(&debug_mmap_mtx); ptr_node_debug *node = ptr_set_debug_find(&debug_mmap_set, addr); if(node != NULL) { debug_mmap_t *debug_mmap = (debug_mmap_t *)node->value; debug_free_unmonitored(debug_mmap); ptr_set_debug_delete(&debug_mmap_set, addr); } pthread_mutex_unlock(&debug_mmap_mtx); int ret = munmap(addr, len); return ret; } void debug_mmap_stat() { u32 count = 0; u64 total = 0; formatln("MMAP statistics:"); pthread_mutex_lock(&debug_mmap_mtx); ptr_set_debug_iterator iter; ptr_set_debug_iterator_init(&debug_mmap_set, &iter); while(ptr_set_debug_iterator_hasnext(&iter)) { const ptr_node_debug *node = ptr_set_debug_iterator_next_node(&iter); const debug_mmap_t *debug_mmap = (const debug_mmap_t *)node->value; formatln("MMAP %p %016llx %04x %04x %5i %08x (%lli)", debug_mmap->mapped, debug_mmap->len, debug_mmap->prot, debug_mmap->flags, debug_mmap->fildes, debug_mmap->off, debug_mmap->ts); debug_stacktrace_print(termout, debug_mmap->trace); output_stream_write_u8(termout, (u8)'\n'); ++count; total += debug_mmap->len; } pthread_mutex_unlock(&debug_mmap_mtx); formatln("MMAP count: %u total: %llx (%llu)", count, total, total); } #else void* debug_mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) { void *ret = mmap(addr, len, prot, flags, fildes, off); return ret; } int debug_munmap(void *addr, size_t len) { int ret = munmap(addr, len); return ret; } void debug_mmap_stat() { } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/debug_stacktrace.c0000644000000000000000000000013214505005532022766 xustar000000000000000030 mtime=1695812442.471982604 30 atime=1695812445.795030196 30 ctime=1695812494.524728103 yadifa-2.6.5-11201/lib/dnscore/src/debug_stacktrace.c0000664000374500037450000003464514505005532022744 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup stacktrace Stack trace debug functions * @ingroup dnscore * @brief Debug functions. * * Definitions of stacktrace functions * * @{ */ #include "dnscore/dnscore-config.h" #include "dnscore/debug_config.h" #include #include #include #if defined(__GLIBC__) || defined(__FreeBSD__) || defined(__APPLE__) #define HAS_BACKTRACE 1 #else #define HAS_BACKTRACE 0 #endif #if HAS_BACKTRACE #include #if HAS_BFD_DEBUG_SUPPORT #include #ifndef DMGL_PARAMS #define DMGL_PARAMS (1 << 0) /* Include function args */ #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ #endif #endif #endif #include #include #include "dnscore/sys_types.h" #include "dnscore/u64_set_debug.h" #undef malloc #undef free #undef realloc #undef calloc #undef debug_mtest #undef debug_stat #undef debug_mallocated ////////////////////////////////////////////////////////////////////////////// // // STACKTRACE // ////////////////////////////////////////////////////////////////////////////// bool debug_bfd_resolve_address(void *address, const char *binary_file_path, const char **out_file, const char **out_function, u32 *out_line); void debug_bfd_clear(); #if HAS_BACKTRACE typedef u64_set_debug stacktrace_set; static stacktrace_set stacktraces_list_set = U64_SET_EMPTY; static pthread_mutex_t stacktraces_mutex = PTHREAD_MUTEX_INITIALIZER; #endif void malloc_busy_acquire(); void malloc_busy_release(); #if HAS_BACKTRACE static ya_result debug_stacktraces_list_set_search(void* data, void* parm) { stacktrace trace_a = (stacktrace)data; stacktrace trace_b = (stacktrace)parm; if(data == NULL || parm == NULL) { return COLLECTION_ITEM_STOP; } for(;;) { if(*trace_a != *trace_b) { break; } if((*trace_a|*trace_b) == 0) { return COLLECTION_ITEM_PROCESS_THEN_STOP; } trace_a++; trace_b++; } return COLLECTION_ITEM_STOP; } #endif stacktrace debug_stacktrace_get_ex(int index) { #if HAS_BACKTRACE void* buffer_[1024]; #if DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT malloc_busy_acquire(); #endif int n = backtrace(buffer_, sizeof(buffer_) / sizeof(void*)); void** buffer = &buffer_[index]; n -= index; // minus this function if(n < 0) { #if DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT malloc_busy_release(); #endif return NULL; } // backtrace to key stacktrace sp = (stacktrace)buffer; u64 key = 0; for(int i = 0; i < n; i++) { key += sp[i] << ( n & ((__SIZEOF_POINTER__ * 8) - 1) ); } pthread_mutex_lock(&stacktraces_mutex); stacktrace trace; u64_node_debug *node = u64_set_debug_insert(&stacktraces_list_set, key); if(node->value == NULL) { list_sl_debug_s *sll; sll = (list_sl_debug_s*)debug_malloc_unmonitored(sizeof(list_sl_debug_s)); list_sl_debug_init(sll); node->value = sll; trace = (stacktrace)debug_malloc_unmonitored((n + 2) * sizeof(intptr)); memcpy(trace, buffer, n * sizeof(void*)); trace[n] = 0; list_sl_debug_insert(sll, trace); trace[n+1] = (intptr)backtrace_symbols(buffer, n); } else { list_sl_debug_s *sll; sll = (list_sl_debug_s *)node->value; trace = (stacktrace)list_sl_debug_search(sll, debug_stacktraces_list_set_search, buffer); if(trace == NULL) { trace = (stacktrace)debug_malloc_unmonitored((n + 2) * sizeof(intptr)); memcpy(trace, buffer, n * sizeof(void*)); trace[n] = 0; list_sl_debug_insert(sll, trace); trace[n+1] = (intptr)backtrace_symbols(buffer, n); } } pthread_mutex_unlock(&stacktraces_mutex); #if DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT malloc_busy_release(); #endif return trace; #else (void)index; return NULL; #endif } stacktrace debug_stacktrace_get() { stacktrace st = debug_stacktrace_get_ex(1); return st; } /** * clears all stacktraces from memory * should only be called at shutdown */ #if HAS_BACKTRACE static void debug_stacktrace_clear_delete(u64_node_debug *node) { list_sl_debug_s *sll = (list_sl_debug_s *)node->value; if(sll != NULL) { stacktrace trace; while((trace = (stacktrace)list_sl_debug_pop(sll)) != NULL) { int n = 0; while(trace[n] != 0) { ++n; } char **trace_strings = (char**)trace[n + 1]; debug_free_unmonitored(trace_strings); debug_free_unmonitored(trace); } debug_free_unmonitored(sll); node->value = NULL; } } #endif void debug_stacktrace_clear() { #if HAS_BACKTRACE pthread_mutex_lock(&stacktraces_mutex); u64_set_debug_callback_and_destroy(&stacktraces_list_set, debug_stacktrace_clear_delete); pthread_mutex_unlock(&stacktraces_mutex); #if !DNSCORE_HAS_MALLOC_DEBUG_SUPPORT #if HAS_BFD_DEBUG_SUPPORT debug_bfd_clear(); #endif #endif #endif } void debug_stacktrace_log(logger_handle* handle, u32 level, stacktrace trace) { #if HAS_BACKTRACE int n = 0; if(trace != NULL) { while(trace[n] != 0) { ++n; } char **trace_strings = (char**)trace[n + 1]; for(int i = 0; i < n; i++) { void *address = (void*)trace[i]; const char *text = (trace_strings != NULL) ? trace_strings[i] : "???"; #if HAS_BFD_DEBUG_SUPPORT char *parenthesis = strchr(text, '('); if(parenthesis != NULL) { u32 n = parenthesis - text; assert(n < PATH_MAX); char binary[PATH_MAX]; memcpy(binary, text, n); binary[n] = '\0'; const char *file = NULL; const char *function = NULL; u32 line; debug_bfd_resolve_address(address, binary, &file, &function, &line); if((file != NULL) && (*file != '\0')) { logger_handle_msg(handle, level, "%p: %s (%s:%i)", address, function, file, line); } else { logger_handle_msg(handle, level, "%p: %s", address, text); } } else { #endif logger_handle_msg(handle, level, "%p %s", address, text); #if HAS_BFD_DEBUG_SUPPORT } #endif } } #else (void)trace; logger_handle_msg(handle, level, "backtrace not supported"); #endif } void debug_stacktrace_log_with_prefix(logger_handle* handle, u32 level, stacktrace trace, const char *prefix) { #if HAS_BACKTRACE int n = 0; if(trace != NULL) { while(trace[n] != 0) { ++n; } char **trace_strings = (char**)trace[n + 1]; for(int i = 0; i < n; i++) { void *address = (void*)trace[i]; const char *text = (trace_strings != NULL) ? trace_strings[i] : "???"; #if HAS_BFD_DEBUG_SUPPORT char *parenthesis = strchr(text, '('); if(parenthesis != NULL) { u32 n = parenthesis - text; assert(n < PATH_MAX); char binary[PATH_MAX]; memcpy(binary, text, n); binary[n] = '\0'; const char *file = NULL; const char *function = NULL; u32 line; debug_bfd_resolve_address(address, binary, &file, &function, &line); if((file != NULL) && (*file != '\0')) { logger_handle_msg(handle, level, "%s%p: %s (%s:%i)", prefix, address, function, file, line); } else { logger_handle_msg(handle, level, "%s%p: %s", prefix, address, text); } } else { #endif logger_handle_msg(handle, level, "%s%p %s", prefix, address, text); #if HAS_BFD_DEBUG_SUPPORT } #endif } } #else (void)trace; (void)prefix; logger_handle_msg(handle, level, "backtrace not supported"); #endif } void debug_stacktrace_try_log(logger_handle* handle, u32 level, stacktrace trace) { #if HAS_BACKTRACE int n = 0; if(trace != NULL) { while(trace[n] != 0) { ++n; } char **trace_strings = (char**)trace[n + 1]; for(int i = 0; i < n; i++) { void *address = (void*)trace[i]; const char *text = (trace_strings != NULL) ? trace_strings[i] : "???"; #if HAS_BFD_DEBUG_SUPPORT char *parenthesis = strchr(text, '('); if(parenthesis != NULL) { u32 n = parenthesis - text; assert(n < PATH_MAX); char binary[PATH_MAX]; memcpy(binary, text, n); binary[n] = '\0'; const char *file = NULL; const char *function = NULL; u32 line; debug_bfd_resolve_address(address, binary, &file, &function, &line); if((file != NULL) && (*file != '\0')) { logger_handle_msg(handle, level, "%p: %s (%s:%i)", address, function, file, line); } else { logger_handle_msg(handle, level, "%p: %s", address, text); } } else { #endif logger_handle_try_msg(handle, level, "%p %s", address, text); #if HAS_BFD_DEBUG_SUPPORT } #endif } } #else (void)trace; logger_handle_try_msg(handle, level, "backtrace not supported"); #endif } void debug_stacktrace_print(output_stream *os, stacktrace trace) { if(trace == NULL) { output_stream_write(os, "NULL-TRACE", 10); return; } #if HAS_BACKTRACE int n = 0; while(trace[n] != 0) { ++n; } char **trace_strings = (char**)trace[n + 1]; for(int i = 0; i < n; i++) { osformatln(os, "%p %s", (void*)trace[i], (trace_strings != NULL) ? trace_strings[i] : "???"); } #else osformatln(os, "backtrace not supported"); #endif } #if defined(__GLIBC__) bool debug_log_stacktrace(logger_handle *handle, u32 level, const char *prefix) { void* addresses[1024]; #if HAS_BFD_DEBUG_SUPPORT char binary[PATH_MAX]; #endif #if defined(__GLIBC__) int n = backtrace(addresses, sizeof(addresses) / sizeof(void*)); if(n > 0) { char **symbols = backtrace_symbols(addresses, n); if(symbols != NULL) { for(int i = 1; i < n; i++) { char *parenthesis = strchr(symbols[i], '('); if(parenthesis != NULL) { #if HAS_BFD_DEBUG_SUPPORT u32 n = parenthesis - symbols[i]; memcpy(binary, symbols[i], n); binary[n] = '\0'; const char *func = "?"; const char *file = "?"; u32 line = ~0; debug_bfd_resolve_address(addresses[i], binary, &file, &func, &line); if((file != NULL) && (*file != '\0')) { logger_handle_msg(handle, level, "%s: %p: %s (%s:%i)", prefix, addresses[i], func, file, line); } else { logger_handle_msg(handle, level, "%s: %p: %s", prefix, addresses[i], symbols[i]); } #else logger_handle_msg(handle, level, "%s: %p: %s", prefix, addresses[i], symbols[i]); #endif } } free(symbols); } else { for(int i = 1; i < n; i++) { logger_handle_msg(handle, level, "%s: %p: ?", prefix, addresses[i]); } } } else #endif // linux only { logger_handle_msg(handle, level, "%s: ?: ?", prefix); } return TRUE; } #else bool debug_log_stacktrace(logger_handle *handle, u32 level, const char *prefix) { (void)handle; (void)level; (void)prefix; return TRUE; } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/digest_rawdata.c0000644000000000000000000000013214505005532022456 xustar000000000000000030 mtime=1695812442.377981257 30 atime=1695812445.791030139 30 ctime=1695812494.526728132 yadifa-2.6.5-11201/lib/dnscore/src/digest_rawdata.c0000664000374500037450000000725714505005532022433 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include #include "dnscore/dnscore-config.h" #include "dnscore/digest.h" #include "dnscore/bytearray_output_stream.h" static s32 digest_rawdata_update(digest_s* ctx, const void* buffer, u32 size) { return output_stream_write(&ctx->ctx.rawdata.baos, buffer, size) - 1; } static s32 digest_rawdata_final(digest_s* ctx) { (void)ctx; return SUCCESS; } static ya_result digest_rawdata_final_copy_bytes(digest_s* ctx, void *output, u32 output_size) { u32 size = bytearray_output_stream_size(&ctx->ctx.rawdata.baos); if(size <= output_size) { memcpy(output, bytearray_output_stream_buffer(&ctx->ctx.rawdata.baos), size); return SUCCESS; } else { return BUFFER_WOULD_OVERFLOW; } } static s32 digest_rawdata_get_size(digest_s* ctx) { s32 ret = (s32)bytearray_output_stream_size(&ctx->ctx.rawdata.baos); return ret; } static s32 digest_rawdata_get_digest(struct digest_s* ctx, void** p) { *p = bytearray_output_stream_buffer(&ctx->ctx.rawdata.baos); return SUCCESS; } static void digest_rawdata_finalise(struct digest_s* ctx) { #if DEBUG memset(bytearray_output_stream_buffer(&ctx->ctx.rawdata.baos), 0xee, bytearray_output_stream_size(&ctx->ctx.rawdata.baos)); #endif output_stream_close(&ctx->ctx.rawdata.baos); } static const struct digest_vtbl rawdata_vtbl = { digest_rawdata_update, digest_rawdata_final, digest_rawdata_final_copy_bytes, digest_rawdata_get_size, digest_rawdata_get_digest, digest_rawdata_finalise, "RAWDATA" }; void digest_rawdata_init(digest_s *ctx) { ctx->vtbl = &rawdata_vtbl; //bytearray_output_stream_init(&ctx->ctx.rawdata, NULL, 0); bytearray_output_stream_init_ex_static(&ctx->ctx.rawdata.baos, ctx->ctx.rawdata.data, sizeof(ctx->ctx.rawdata.data), BYTEARRAY_DYNAMIC, &ctx->ctx.rawdata.baos_ctx); } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/digest_sha1.c0000644000000000000000000000013214505005532021667 xustar000000000000000030 mtime=1695812442.450982303 30 atime=1695812445.794030182 30 ctime=1695812494.528728161 yadifa-2.6.5-11201/lib/dnscore/src/digest_sha1.c0000664000374500037450000000574114505005532021640 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include "dnscore/digest.h" #ifndef OPENSSL_NO_SHA1 static s32 digest_sha1_update(digest_s* ctx, const void* buffer, u32 size) { return SHA1_Update(&ctx->ctx.sha1, buffer, size) - 1; } static s32 digest_sha1_final(digest_s* ctx) { return SHA1_Final(ctx->digest, &ctx->ctx.sha1) - 1; } static s32 digest_sha1_final_copy_bytes(digest_s* ctx, void* buffer, u32 size) { if(size >= SHA_DIGEST_LENGTH) { return SHA1_Final(buffer, &ctx->ctx.sha1) - 1; } return BUFFER_WOULD_OVERFLOW; } static s32 digest_sha1_get_size(digest_s* ctx) { (void)ctx; return SHA_DIGEST_LENGTH; } static s32 digest_sha1_get_digest(digest_s* ctx, void **ptr) { *ptr = &ctx->digest[0]; return SHA_DIGEST_LENGTH; } static void digest_sha1_finalise(struct digest_s* ctx) { (void)ctx; } static const struct digest_vtbl sha1_vtbl = { digest_sha1_update, digest_sha1_final, digest_sha1_final_copy_bytes, digest_sha1_get_size, digest_sha1_get_digest, digest_sha1_finalise, "SHA1" }; void digest_sha1_init(digest_s *ctx) { ctx->vtbl = &sha1_vtbl; SHA1_Init(&ctx->ctx.sha1); } #endif yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/digest_sha256.c0000644000000000000000000000013014505005532022041 xustar000000000000000029 mtime=1695812442.49898299 29 atime=1695812445.79603021 30 ctime=1695812494.530728189 yadifa-2.6.5-11201/lib/dnscore/src/digest_sha256.c0000664000374500037450000000607114505005532022011 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include #include "dnscore/dnscore-config.h" #include "dnscore/digest.h" #ifndef OPENSSL_NO_SHA256 static s32 digest_sha256_update(digest_s* ctx, const void* buffer, u32 size) { return SHA256_Update(&ctx->ctx.sha256, buffer, size) - 1; } static s32 digest_sha256_final(digest_s* ctx) { return SHA256_Final(ctx->digest, &ctx->ctx.sha256) - 1; } static s32 digest_sha256_final_copy_bytes(digest_s* ctx, void* buffer, u32 size) { if(size >= SHA256_DIGEST_LENGTH) { return SHA256_Final(buffer, &ctx->ctx.sha256) - 1; } return BUFFER_WOULD_OVERFLOW; } static s32 digest_sha256_get_size(digest_s* ctx) { (void)ctx; return SHA256_DIGEST_LENGTH; } static s32 digest_sha256_get_digest(digest_s* ctx, void **ptr) { *ptr = &ctx->digest[0]; return SHA256_DIGEST_LENGTH; } static void digest_sha256_finalise(struct digest_s* ctx) { (void)ctx; } static const struct digest_vtbl sha256_vtbl = { digest_sha256_update, digest_sha256_final, digest_sha256_final_copy_bytes, digest_sha256_get_size, digest_sha256_get_digest, digest_sha256_finalise, "SHA256" }; void digest_sha256_init(digest_s *ctx) { ctx->vtbl = &sha256_vtbl; SHA256_Init(&ctx->ctx.sha256); } #endif yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/digest_sha384.c0000644000000000000000000000013214505005532022045 xustar000000000000000030 mtime=1695812442.367981114 30 atime=1695812445.791030139 30 ctime=1695812494.532728218 yadifa-2.6.5-11201/lib/dnscore/src/digest_sha384.c0000664000374500037450000000603414505005532022012 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include "dnscore/digest.h" #ifndef OPENSSL_NO_SHA512 static s32 digest_sha384_update(digest_s* ctx, const void* buffer, u32 size) { return SHA384_Update(&ctx->ctx.sha384, buffer, size) - 1; } static s32 digest_sha384_final(digest_s* ctx) { return SHA384_Final(ctx->digest, &ctx->ctx.sha384) - 1; } static s32 digest_sha384_final_copy_bytes(digest_s* ctx, void* buffer, u32 size) { if(size >= SHA384_DIGEST_LENGTH) { return SHA384_Final(buffer, &ctx->ctx.sha384) - 1; } return BUFFER_WOULD_OVERFLOW; } static s32 digest_sha384_get_size(digest_s* ctx) { (void)ctx; return SHA384_DIGEST_LENGTH; } static s32 digest_sha384_get_digest(digest_s* ctx, void **ptr) { *ptr = &ctx->digest[0]; return SHA384_DIGEST_LENGTH; } static void digest_sha384_finalise(struct digest_s* ctx) { (void)ctx; } static const struct digest_vtbl sha384_vtbl = { digest_sha384_update, digest_sha384_final, digest_sha384_final_copy_bytes, digest_sha384_get_size, digest_sha384_get_digest, digest_sha384_finalise, "SHA384" }; void digest_sha384_init(digest_s *ctx) { ctx->vtbl = &sha384_vtbl; SHA384_Init(&ctx->ctx.sha384); } #endif yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/digest_sha512.c0000644000000000000000000000013114505005532022035 xustar000000000000000030 mtime=1695812442.495982947 29 atime=1695812445.79603021 30 ctime=1695812494.534728247 yadifa-2.6.5-11201/lib/dnscore/src/digest_sha512.c0000664000374500037450000000603514505005532022004 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include "dnscore/digest.h" #ifndef OPENSSL_NO_SHA512 static s32 digest_sha512_update(digest_s* ctx, const void* buffer, u32 size) { return SHA512_Update(&ctx->ctx.sha512, buffer, size) - 1; } static s32 digest_sha512_final(digest_s* ctx) { return SHA512_Final(ctx->digest, &ctx->ctx.sha512) - 1; } static s32 digest_sha512_final_copy_bytes(digest_s* ctx, void* buffer, u32 size) { if(size >= SHA512_DIGEST_LENGTH) { return SHA512_Final(buffer, &ctx->ctx.sha512) - 1; } return BUFFER_WOULD_OVERFLOW; } static s32 digest_sha512_get_size(digest_s* ctx) { (void)ctx; return SHA512_DIGEST_LENGTH; } static s32 digest_sha512_get_digest(digest_s* ctx, void **ptr) { *ptr = &ctx->digest[0]; return SHA512_DIGEST_LENGTH; } static void digest_sha512_finalise(struct digest_s* ctx) { (void)ctx; } static const struct digest_vtbl sha512_vtbl = { digest_sha512_update, digest_sha512_final, digest_sha512_final_copy_bytes, digest_sha512_get_size, digest_sha512_get_digest, digest_sha512_finalise, "SHA512" }; void digest_sha512_init(digest_s *ctx) { ctx->vtbl = &sha512_vtbl; SHA512_Init(&ctx->ctx.sha512); } #endif yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dns-udp.c0000644000000000000000000000013214505005532021046 xustar000000000000000030 mtime=1695812442.459982432 30 atime=1695812445.794030182 30 ctime=1695812494.536728275 yadifa-2.6.5-11201/lib/dnscore/src/dns-udp.c0000664000374500037450000031571314505005532021022 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include #include #include #include #include "dnscore/fdtools.h" #include "dnscore/dns_resource_record.h" #include "dnscore/thread_pool.h" #include "dnscore/random.h" #include "dnscore/message.h" #include "dnscore/tcp_io_stream.h" #include "dnscore/u64_set.h" #include "dnscore/ptr_set.h" #include "dnscore/pool.h" #include "dnscore/thread_pool.h" #include "dnscore/service.h" #include "dnscore/async.h" #include "dnscore/dns-udp.h" #include "dnscore/limiter.h" #include "dnscore/list-dl.h" #include "dnscore/list-sl.h" #include "dnscore/mutex.h" #include "dnscore/dnsname.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define SCKTARRY_TAG 0x59525241544b4353 #define DNSUDPHS_TAG 0x5348504455534e44 #define DNS_UDP_TC_FALLBACK_TO_TCP_SUPPORT 1 #define DNS_UDP_SIMPLE_QUERY 0 #define DNS_UDP_SIMPLE_MESSAGE_FLAG_NONE 0 #define DNS_UDP_SIMPLE_MESSAGE_FLAG_DNSSEC 1 #define DNS_SIMPLE_MESSAGE_RETRIES_DEFAULT 2 // 3 tries total #define DNSURECV_TAG 0x5643455255534e44 #define DNSSMAND_TAG 0x444e414d53534e44 #define DNSSMESG_TAG 0x4753454d53534e44 #define DNSURMU_TAG 0x554d5255534e44 #define DNSURAU_TAG 0x55415255534e44 #define DNSURCTX_TAG 0x5854435255534e44 //#define DNS_UDP_HOST_RATE_WAIT 10000 // 10ms wait between two packets #define DNS_UDP_HOST_RATE_WAIT 1000000 // 1s wait between two packets #define DNS_UDP_HOST_BANDWIDTH_MAX 4096 // bytes per second #define DNS_UDP_HOST_RATE_MAX 5 // packet per second static const u8 V4_WRAPPED_IN_V6[12] = {0,0,0,0,0,0,0,0,0,0,255,255}; static struct service_s dns_udp_send_handler = UNINITIALIZED_SERVICE; static struct service_s dns_udp_receive_read_handler = UNINITIALIZED_SERVICE; static struct service_s dns_udp_receive_process_handler = UNINITIALIZED_SERVICE; static struct service_s dns_udp_timeout_handler = UNINITIALIZED_SERVICE; static async_queue_s dns_udp_send_handler_queue; static bool dns_udp_handler_initialized = FALSE; //static smp_int domain_test_count = SMP_INT_INITIALIZER; static int dns_udp_send_service(struct service_worker_s *worker); static int dns_udp_receive_read_service(struct service_worker_s *worker); static int dns_udp_receive_process_service(struct service_worker_s *worker); struct dns_udp_receive_ctx; static size_t dns_udp_receive_ctx_available(struct dns_udp_receive_ctx *ctx); static int dns_udp_timeout_service(struct service_worker_s *worker); static int *dns_udp_socket = NULL; struct dns_udp_receive_ctx; static struct dns_udp_receive_ctx **dns_udp_receive_context = NULL; static list_dl_s *volatile dns_udp_high_priority = NULL; static u32 dns_udp_socket_count = 0; static pool_s dns_simple_message_pool; static pool_s message_data_pool; static pool_s dns_simple_message_async_node_pool; static mutex_t sendto_statistics_mtx = MUTEX_INITIALIZER; static mutex_t recvfrom_statistics_mtx = MUTEX_INITIALIZER; static volatile u32 sendto_epoch = 0; static volatile u32 sendto_total = 0; static volatile u32 sendto_packets = 0; static volatile u32 sendto_packets_aggregated = 0; static volatile u32 recvfrom_epoch = 0; static volatile u32 recvfrom_total = 0; static volatile u32 recvfrom_packets = 0; #if DNS_UDP_TC_FALLBACK_TO_TCP_SUPPORT // local define static struct thread_pool_s *tcp_query_thread_pool = NULL; #endif static struct thread_pool_s *dns_udp_callback_tp = NULL; static int dns_udp_send_simple_message_node_compare(const void *key_a, const void *key_b); static ptr_set message_collection = { NULL, dns_udp_send_simple_message_node_compare }; static mutex_t message_collection_mtx = MUTEX_INITIALIZER; static volatile s64 message_collection_keys = 0; static volatile s64 message_collection_size = 0; static const dns_udp_settings_s default_dns_udp_settings = { DNS_UDP_TIMEOUT_US, DNS_UDP_SEND_RATE, DNS_UDP_SEND_BANDWIDTH, DNS_UDP_RECV_BANDWIDTH, DNS_UDP_SEND_QUEUE, DNS_UDP_PORT_COUNT, DNS_UDP_RETRY_COUNT, DNS_UDP_PER_DNS_RATE, DNS_UDP_PER_DNS_BANDWIDTH, DNS_UDP_PER_DNS_FREQ_MIN, DNS_UDP_READ_BUFFER_COUNT, DNS_UDP_CALLBACK_QUEUE_SIZE, DNS_UDP_CALLBACK_THREAD_COUNT, DNS_UDP_TCP_THREAD_POOL_SIZE, DNS_UDP_TCP_FALLBACK_ON_TIMEOUT }; static const dns_udp_settings_s *dns_udp_settings = &default_dns_udp_settings; /****************************************************************************** * * @note edf 20170905 -- this block handles the various new limits * *****************************************************************************/ // the bits that will be squashed so the delay collection does not explodes with keys #define LIMIT_DELAYED_SET_GRANULARITY_WINDOW 16383 // 16ms struct dns_udp_host_state_s { host_address* host; // a nameserver limiter_t send_rate; limiter_t send_bandwidth; }; typedef struct dns_udp_host_state_s dns_udp_host_state_s; static int dns_udp_host_state_node_compare(const void *key_a, const void *key_b) { const host_address* a = (const host_address*)key_a; const host_address* b = (const host_address*)key_b; int d = host_address_compare(a, b); return d; } /** * @note edf 20170905 -- this is for limiting the global send bandwidth * */ static limiter_t dns_udp_send_bandwidth; static mutex_t limiter_send_wait_mtx = MUTEX_INITIALIZER; static mutex_t limiter_recv_wait_mtx = MUTEX_INITIALIZER; /** * @note edf 20170905 -- this is for limiting the global packets sent per second * */ static limiter_t dns_udp_send_rate; /** * @note edf 20170905 -- this is for limiting the global recv bandwidth * Of course there is no pps limiter for input as it is closely * correlated to the 'send' one. */ static limiter_t dns_udp_recv_bandwidth; static struct ptr_set host_state_set = PTR_SET_EMPTY_WITH_COMPARATOR(dns_udp_host_state_node_compare); static mutex_t host_state_set_mtx = MUTEX_INITIALIZER; static dns_udp_host_state_s* dns_udp_host_state_get_nolock(const host_address* host) { ptr_node* node = ptr_set_insert(&host_state_set, (host_address*)host); dns_udp_host_state_s* state; if(node->value == NULL) { ZALLOC_OBJECT_OR_DIE(state, dns_udp_host_state_s, DNSUDPHS_TAG); state->host = host_address_copy(host); node->key = state->host; limiter_init(&state->send_bandwidth, dns_udp_settings->per_dns_bandwidth); limiter_init(&state->send_rate, dns_udp_settings->per_dns_rate); limiter_set_wait_time(&state->send_rate, dns_udp_settings->per_dns_freq_min); node->value = state; } state = (dns_udp_host_state_s*)node->value; return state; } u64 dns_udp_host_state_packet_try(host_address* host, u32 size) { mutex_lock(&host_state_set_mtx); dns_udp_host_state_s* state = dns_udp_host_state_get_nolock(host); limiter_count_t available_now; u64 rate_wait_time; u64 bandwidth_wait_time = 0; u64 now; log_debug4("sender: %{hostaddr} waiting for the send rate to be low enough", host); now = limiter_quota(&state->send_rate, 1, &available_now, &rate_wait_time); if(available_now == 1) { log_debug4("sender: %{hostaddr} waiting for the send bandwidth to be low enough", host); limiter_quota(&state->send_bandwidth, size, &available_now, &bandwidth_wait_time); if(size == available_now) { limiter_add(&state->send_rate, 1, &available_now, &rate_wait_time); limiter_add(&state->send_bandwidth, size, &available_now, &bandwidth_wait_time); log_debug4("sender: %{hostaddr} allocating send rate and bandwidth", host); // can be sent now mutex_unlock(&host_state_set_mtx); return 0; } } log_debug4("sender: %{hostaddr} query will be delayed", host); // has to be delayed u64 delay_epoch_us = (now + MAX(rate_wait_time, bandwidth_wait_time) + (LIMIT_DELAYED_SET_GRANULARITY_WINDOW - 1)) & ~LIMIT_DELAYED_SET_GRANULARITY_WINDOW; mutex_unlock(&host_state_set_mtx); return delay_epoch_us; } static u64_set delayed_message_set = U64_SET_EMPTY; static mutex_t delayed_message_set_mtx = MUTEX_INITIALIZER; static s64 delayed_message_count = 0; static void delayed_message_insert(u64 epoch_us, async_message_s* async) { mutex_lock(&delayed_message_set_mtx); u64_node* node = u64_set_insert(&delayed_message_set, epoch_us); list_sl_s* list; if(node->value == NULL) { list = list_sl_new_instance(); node->value = list; } list = (list_sl_s*)node->value; list_sl_add(list, async); ++delayed_message_count; mutex_unlock(&delayed_message_set_mtx); } static async_message_s* delayed_message_next_at(u64 epoch_us) { async_message_s* ret = NULL; mutex_lock(&delayed_message_set_mtx); for(;;) { u64_node* node = u64_set_get_first(&delayed_message_set); if(node == NULL) { break; } if(node->key > epoch_us) { break; } list_sl_s* list = (list_sl_s*)node->value; ret = (async_message_s*)list_sl_remove_first(list); if(ret != NULL) { --delayed_message_count; break; } // remove the whole node list_sl_delete_instance(list); u64_set_delete(&delayed_message_set, node->key); } mutex_unlock(&delayed_message_set_mtx); return ret; } static async_message_s* delayed_message_next() { async_message_s* async = delayed_message_next_at(timeus()); return async; } /*****************************************************************************/ static void * dns_simple_message_async_node_pool_alloc(void *_ignored_) { dns_simple_message_async_node_s *sma; (void)_ignored_; ZALLOC_OBJECT_OR_DIE(sma, dns_simple_message_async_node_s, DNSSMAND_TAG); ZEROMEMORY(sma, sizeof(dns_simple_message_async_node_s)); return sma; } static void dns_simple_message_async_node_pool_free(void *sma_, void *_ignored_) { (void)_ignored_; dns_simple_message_async_node_s* sma = (dns_simple_message_async_node_s*)sma_; memset(sma, 0xd0, sizeof(dns_simple_message_async_node_s)); //free(sma); // POOL ZFREE_OBJECT(sma); } static void * dns_simple_message_pool_alloc(void *_ignored_) { dns_simple_message_s *msg; (void)_ignored_; ZALLOC_OBJECT_OR_DIE(msg, dns_simple_message_s, DNSSMESG_TAG); ZEROMEMORY(msg, sizeof(dns_simple_message_s)); msg->sender_socket = -1; return msg; } static void dns_simple_message_pool_free(void *msg_, void *_ignored_) { (void)_ignored_; dns_simple_message_s* msg = (dns_simple_message_s*)msg_; memset(msg, 0xd1, sizeof(dns_simple_message_s)); #if DEBUG //msg->rc.value = 0; #endif //free(p); // POOL ZFREE_OBJECT(msg); } static void * message_data_pool_alloc(void *_ignored_) { message_data *mesg; (void)_ignored_; mesg = message_new_instance(); return mesg; } #if UNUSED static void message_data_pool_reset(void *p, void *_ignored_) { (void)_ignored_; message_reset_buffer_size((message_data*)p); message_send_udp_reset((message_data*)p); } #endif static void message_data_pool_free(void *p, void *_ignored_) { (void)_ignored_; message_free((message_data*)p); } static void dns_udp_handler_message_collection_free_node_callback(ptr_node *node) { dns_simple_message_s *simple_message = (dns_simple_message_s*)node->key; dns_udp_simple_message_release(simple_message); } void dns_udp_handler_configure(const dns_udp_settings_s *settings) { if(settings == NULL) { settings = &default_dns_udp_settings; } dns_udp_settings = settings; } /** * Overwrites (creates) the limits for a given host. * Meant for the caching nameserver(s) for the DNSQ project. * * @param name_server * @param rate * @param bandwidth * @param freq_min */ void dns_udp_handler_host_limit_set(const host_address* name_server, u32 rate, u32 bandwidth, u32 freq_min) { mutex_lock(&host_state_set_mtx); dns_udp_host_state_s* state = dns_udp_host_state_get_nolock(name_server); limiter_init(&state->send_bandwidth, bandwidth); limiter_init(&state->send_rate, rate); limiter_set_wait_time(&state->send_rate, freq_min); mutex_unlock(&host_state_set_mtx); } int dns_udp_handler_start() { int err = SERVICE_NOT_INITIALISED; if(dns_udp_handler_initialized) { if(ISOK(err = service_start(&dns_udp_send_handler))) { if(ISOK(err = service_start(&dns_udp_receive_read_handler))) { if(ISOK(err = service_start(&dns_udp_receive_process_handler))) { if(ISOK(err = service_start(&dns_udp_timeout_handler))) { return err; } service_stop(&dns_udp_receive_process_handler); service_wait(&dns_udp_receive_process_handler); } service_stop(&dns_udp_receive_read_handler); service_wait(&dns_udp_receive_read_handler); } service_stop(&dns_udp_send_handler); service_wait(&dns_udp_send_handler); } } return err; } int dns_udp_handler_stop() { int err = SUCCESS; int err0 = SUCCESS; int err1 = SUCCESS; int err2 = SUCCESS; int err2b = SUCCESS; int err3 = SUCCESS; int err4 = SUCCESS; if(!dns_udp_handler_initialized) { return SERVICE_NOT_INITIALISED; } if(!service_stopped(&dns_udp_send_handler)) { if(FAIL(err1 = service_stop(&dns_udp_send_handler))) { log_err("failed to stop dns_udp_send_handler: %r", err1); err = err1; } } if(!service_stopped(&dns_udp_receive_process_handler)) { if(FAIL(err2 = service_stop(&dns_udp_receive_process_handler))) { log_err("failed to stop dns_udp_receive_process_handler: %r", err2); err = err2; } } if(!service_stopped(&dns_udp_receive_read_handler)) { if(FAIL(err2b = service_stop(&dns_udp_receive_read_handler))) { log_err("failed to stop dns_udp_receive_read_handler: %r", err2); err = err2b; } } if(!service_stopped(&dns_udp_timeout_handler)) { if(FAIL(err3 = service_stop(&dns_udp_timeout_handler))) { log_err("failed to stop dns_udp_timeout_handler: %r", err3); err = err3; } } #if DNS_UDP_TC_FALLBACK_TO_TCP_SUPPORT if(tcp_query_thread_pool != NULL) { if(FAIL(err0 = thread_pool_destroy(tcp_query_thread_pool))) { log_err("failed to stop tcp_query_thread_pool: %r", err0); err = err0; } tcp_query_thread_pool = NULL; } #endif log_debug("closing %i sockets", dns_udp_socket_count); for(u32 i = 0; i < dns_udp_socket_count; i++) { if(dns_udp_socket[i] != ~0) { log_debug1("dns_udp_handler_stop: closing socket %i", dns_udp_socket[i]); close_ex(dns_udp_socket[i]); dns_udp_socket[i] = ~0; } } log_debug("closed %i sockets", dns_udp_socket_count); // cleans-up whatever is waiting ... if(dns_udp_high_priority != NULL) { for(u32 i = 0; i < dns_udp_socket_count; ++i) { list_dl_s *list = &dns_udp_high_priority[i]; async_message_s *async; while((async = (async_message_s*)list_dl_remove_first(list)) != NULL) { dns_simple_message_s *simple_message = (dns_simple_message_s*)async->args; simple_message->sent_time_us = MAX_S64; simple_message->worker_index = i; simple_message->source_port = 0; // pre-increase the RC because of this new reference (into the DB) // dns_udp_simple_message_retain(simple_message); async->error_code = DNS_UDP_CANCEL; //dns_udp_simple_message_answer_call_handlers(simple_message); log_debug("send: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) is cancelled", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); simple_message->received_time_us = MAX_U64; dns_simple_message_async_node_s *node = simple_message->async_node.next; while(node != NULL) { // the handler MUST release one reference (so we acquire one right before) dns_udp_simple_message_retain(simple_message); node->async->error_code = DNS_UDP_CANCEL; node->async->handler(node->async); // stop time, no need to thread node = node->next; } // there is no need to retain, the reference from the collection has not been decreased yet simple_message->async_node.async->error_code = DNS_UDP_CANCEL; simple_message->async_node.async->handler(simple_message->async_node.async); simple_message = NULL; //async->handler(async); //async_wait_progress(aw, 1); } } } if(ISOK(err1)) { service_wait(&dns_udp_send_handler); } if(ISOK(err2)) { service_wait(&dns_udp_receive_process_handler); } if(ISOK(err2b)) { service_wait(&dns_udp_receive_read_handler); } if(ISOK(err3)) { service_wait(&dns_udp_timeout_handler); } if(ISOK(err4)) { dns_udp_socket_count = 0; } dns_udp_cancel_all_queries(); return err; } static int dns_udp_send_simple_message_node_compare(const void *key_a, const void *key_b) { dns_simple_message_s *a = (dns_simple_message_s*)key_a; dns_simple_message_s *b = (dns_simple_message_s*)key_b; // test queried type int ka = a->qclass; ka <<= 16; ka |= a->qtype; int kb = b->qclass; kb <<= 16; kb |= b->qtype; if((ka -= kb) != 0) { return ka; } // test name server address if((ka = host_address_compare(a->name_server, b->name_server)) != 0) { return ka; } // test queried domain return dnsname_compare(a->fqdn, b->fqdn); } static message_data * dns_udp_allocate_message_data(struct service_worker_s *worker) { for(;;) { message_data *mesg = (message_data*)pool_alloc(&message_data_pool); if(mesg != NULL) { return mesg; } if(!service_should_run(worker)) { return NULL; } sleep(1); } } /** * Calls the handlers of the aggregated queries on a message. * * First calls the handlers for the list of aggregated. * Then calls the handler for original one. * * @param simple_message */ static void *dns_udp_simple_message_answer_call_handlers_thread(void* arg) { dns_simple_message_s *simple_message = (dns_simple_message_s*)arg; s64 start = timeus(); dns_simple_message_async_node_s *node = simple_message->async_node.next; while(node != NULL) { // the handler MUST release one reference so we increase it here dns_udp_simple_message_retain(simple_message); if((node->async != NULL) && (node->async->handler != NULL)) { node->async->handler(node->async); } else { if(node->async != NULL) { log_err("receive: async=%p handler=%p", node->async, node->async->handler); } else { log_err("receive: async=%p handler=?", node->async); } } node = node->next; } #if DEBUG if(smp_int_get(&simple_message->rc) > 1) { log_warn("receive: message RC is not 1 (%i)", smp_int_get(&simple_message->rc)); } #endif assert(smp_int_get(&simple_message->rc) > 0); // there is no need to retain, the reference from the collection has not been decreased yet simple_message->async_node.async->handler(simple_message->async_node.async); s64 end = timeus(); double dps = end - start; dps /= ONE_SECOND_US_F; log_debug("receive: handler processing took %6.3fs", dps); dns_udp_simple_message_release(simple_message); return NULL; } static void dns_udp_simple_message_answer_call_handlers(dns_simple_message_s *simple_message) { dns_udp_simple_message_retain(simple_message); thread_pool_enqueue_call(dns_udp_callback_tp, dns_udp_simple_message_answer_call_handlers_thread, simple_message, NULL, "dns-cb"); } #if DNS_UDP_TC_FALLBACK_TO_TCP_SUPPORT #define DNSUTQTP_TAG 0x5054515455534e44 struct dns_udp_tcp_query_thread_params { dns_simple_message_s *simple_message; struct service_worker_s *worker; }; typedef struct dns_udp_tcp_query_thread_params dns_udp_tcp_query_thread_params; int dns_udp_tcp_query_count = 0; int dns_udp_tcp_query_failures = 0; static void* dns_udp_tcp_query_thread(void *args) { dns_udp_tcp_query_thread_params *parms = (dns_udp_tcp_query_thread_params*)args; dns_simple_message_s *simple_message = (dns_simple_message_s *)parms->simple_message; struct service_worker_s *worker = (struct service_worker_s *)parms->worker; ZFREE(parms, dns_udp_tcp_query_thread_params); ya_result ret; random_ctx rndctx = thread_pool_get_random_ctx(); yassert(simple_message->answer == NULL); message_data *mesg = dns_udp_allocate_message_data(worker); dns_udp_tcp_query_count++; if(mesg != NULL) { simple_message->dns_id = (u16)random_next(rndctx); simple_message->tcp_used = TRUE; message_make_query_ex(mesg, simple_message->dns_id, simple_message->fqdn, simple_message->qtype, simple_message->qclass, simple_message->flags); if(simple_message->recurse) { message_set_rd_flag(mesg); } // send message socketaddress sa; //socklen_t sa_len = sizeof(sa.sa6); if(ISOK(ret = host_address2sockaddr(simple_message->name_server, &sa))) { //s32 retries = (s32)dns_udp_settings->retry_count; s32 retries = simple_message->retries_left; do { // send the packet simple_message->sent_time_us = timeus(); log_notice("send: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) using TCP", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); ret = message_query_tcp_with_timeout(mesg, simple_message->name_server, dns_udp_settings->timeout / 1000000); simple_message->received_time_us = timeus(); s64 dt = MAX(simple_message->received_time_us - simple_message->sent_time_us, 0); double dts = dt; dts/=ONE_SECOND_US_F; if(ISOK(ret) || ((ret & RCODE_ERROR_BASE) == RCODE_ERROR_BASE)) { log_notice("receive: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) [%6.3fs] using TCP", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, dts); simple_message->status &= ~DNS_SIMPLE_MESSAGE_STATUS_COLLECTED; simple_message->status |= DNS_SIMPLE_MESSAGE_STATUS_RECEIVED; simple_message->answer = mesg; simple_message->tcp_replied = TRUE; mesg = NULL; dns_udp_simple_message_answer_call_handlers(simple_message); // dns_udp_simple_message_answer_call_handlers does a retain //dns_udp_simple_message_release(simple_message); simple_message = NULL; ret = SUCCESS; break; } else { if(--retries >= 0) { log_warn("send: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) [%6.3fs] using TCP failed: %r, retrying", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, dts, ret); } else { log_err("send: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) [%6.3fs] using TCP failed: %r, no retries left", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, dts, ret); } } } while(retries >= 0); } } else { log_err("send: tcp was unable to allocate a message"); ret = MAKE_ERRNO_ERROR(ENOMEM); } if(FAIL(ret)) { dns_udp_tcp_query_failures++; log_err("send: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) using TCP failed: %r", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, ret); if(ret == MAKE_ERRNO_ERROR(EAGAIN)) { ret = DNS_UDP_TIMEOUT; } simple_message->received_time_us = MAX_U64; dns_simple_message_async_node_s *node = simple_message->async_node.next; while(node != NULL) { // the handler MUST release one reference dns_udp_simple_message_retain(simple_message); node->async->error_code = ret; node->async->handler(node->async); node = node->next; } // there is no need to retain, the reference from the collection has not been decreased yet simple_message->async_node.async->error_code = ret; simple_message->async_node.async->handler(simple_message->async_node.async); // simple_message = NULL; } if(mesg != NULL) { message_debug_trash_buffer(mesg); pool_release(&message_data_pool, mesg); } // simple_message->async_node.async->handler(simple_message->async_node.async); return NULL; } static void dns_udp_tcp_query(dns_simple_message_s *simple_message, struct service_worker_s *worker) { dns_udp_tcp_query_thread_params *parms; ZALLOC_OBJECT_OR_DIE( parms, dns_udp_tcp_query_thread_params, DNSUTQTP_TAG); parms->simple_message = simple_message; parms->worker = worker; thread_pool_enqueue_call(tcp_query_thread_pool, dns_udp_tcp_query_thread, parms, NULL, "dns-udp-tcp"); } #endif void dns_udp_send_simple_message(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass, u16 flags, async_done_callback *cb, void* cbargs) { log_debug("query: %{hostaddr} %{dnsname} %{dnstype} %{dnsclass} %s", name_server, fqdn, &qtype, &qclass, (flags!=0)?"":"+dnssec"); async_message_s *domain_message = async_message_alloc(); dns_simple_message_s *simple_message = (dns_simple_message_s*)pool_alloc(&dns_simple_message_pool); #if DEBUG memset(simple_message, 0xac, sizeof(dns_simple_message_s)); #endif simple_message->name_server = host_address_copy(name_server); // MALLOCATED MEMORY RETURNED simple_message->answer = NULL; simple_message->async_node.async = domain_message; simple_message->async_node.next = NULL; simple_message->queued_time_us = timeus(); simple_message->sent_time_us = MAX_S64; simple_message->received_time_us = 0; simple_message->qtype = qtype; simple_message->qclass = qclass; simple_message->retries_left = dns_udp_settings->retry_count; simple_message->flags = flags; simple_message->dns_id = 0; simple_message->status = DNS_SIMPLE_MESSAGE_STATUS_QUEUED; simple_message->recurse = FALSE; simple_message->tcp = FALSE; simple_message->tcp_used = FALSE; simple_message->tcp_replied = FALSE; group_mutex_init(&simple_message->mtx); #if DNS_SIMPLE_MESSAGE_HAS_WAIT_COND cond_init(&simple_message->mtx_cond); #endif simple_message->owner = 0; smp_int_init_set(&simple_message->rc, 1); // sets it to 1 dnsname_canonize(fqdn, simple_message->fqdn); log_debug5("new message@%p: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr}", simple_message, simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server); domain_message->id = DNS_UDP_SIMPLE_QUERY; domain_message->args = simple_message; domain_message->handler = cb; domain_message->handler_args = cbargs; async_message_call(&dns_udp_send_handler_queue, domain_message); } void dns_udp_send_recursive_message(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass, u16 flags, async_done_callback *cb, void* cbargs) { log_debug("query: %{hostaddr} %{dnsname} %{dnstype} %{dnsclass} %s (recursive)", name_server, fqdn, &qtype, &qclass, (flags!=0)?"":"+dnssec"); async_message_s *domain_message = async_message_alloc(); dns_simple_message_s *simple_message = (dns_simple_message_s*)pool_alloc(&dns_simple_message_pool); #if DEBUG memset(simple_message, 0xac, sizeof(dns_simple_message_s)); #endif simple_message->name_server = host_address_copy(name_server); // MALLOCATED MEMORY RETURNED simple_message->answer = NULL; simple_message->async_node.async = domain_message; simple_message->async_node.next = NULL; simple_message->queued_time_us = timeus(); simple_message->sent_time_us = MAX_S64; simple_message->received_time_us = 0; simple_message->qtype = qtype; simple_message->qclass = qclass; simple_message->retries_left = dns_udp_settings->retry_count; simple_message->flags = flags; simple_message->dns_id = 0; simple_message->status = DNS_SIMPLE_MESSAGE_STATUS_QUEUED; simple_message->recurse = TRUE; simple_message->tcp = FALSE; simple_message->tcp_used = FALSE; simple_message->tcp_replied = FALSE; group_mutex_init(&simple_message->mtx); #if DNS_SIMPLE_MESSAGE_HAS_WAIT_COND cond_init(&simple_message->mtx_cond); #endif simple_message->owner = 0; smp_int_init_set(&simple_message->rc, 1); // sets it to 1 dnsname_canonize(fqdn, simple_message->fqdn); log_debug5("new message@%p: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr}", simple_message, simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server); domain_message->id = DNS_UDP_SIMPLE_QUERY; domain_message->args = simple_message; domain_message->handler = cb; domain_message->handler_args = cbargs; async_message_call(&dns_udp_send_handler_queue, domain_message); } struct dns_udp_send_simple_message_sync_s { #if __FreeBSD__ struct async_wait_s* wait; #else struct async_wait_s wait; #endif dns_simple_message_s *simple_message; }; static void dns_udp_send_simple_message_sync_handler(struct async_message_s *msg) { dns_simple_message_s *simple_message = (dns_simple_message_s*)msg->args; struct dns_udp_send_simple_message_sync_s *args = (struct dns_udp_send_simple_message_sync_s*)msg->handler_args; args->simple_message = simple_message; #if __FreeBSD__ args->wait->error_code = msg->error_code; async_wait_progress(args->wait, 1); #else args->wait.error_code = msg->error_code; async_wait_progress(&args->wait, 1); #endif } ya_result dns_udp_send_recursive_message_sync(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass, u16 flags, dns_simple_message_s **to_release) { struct dns_udp_send_simple_message_sync_s args; #if __FreeBSD__ args.wait = async_wait_new_instance(1); #else async_wait_init(&args.wait, 1); #endif args.simple_message = NULL; dns_udp_send_recursive_message(name_server, fqdn, qtype, qclass, flags, dns_udp_send_simple_message_sync_handler, &args); #if __FreeBSD__ async_wait(args.wait); s32 ret = args.wait->error_code; #else async_wait(&args.wait); s32 ret = args.wait.error_code; #endif if(to_release != NULL) { *to_release = args.simple_message; } #if __FreeBSD__ async_wait_finalize(args.wait); #else async_wait_finalize(&args.wait); #endif return ret; } ya_result dns_udp_send_simple_message_sync(const host_address* name_server, const u8 *fqdn, u16 qtype, u16 qclass, u16 flags, dns_simple_message_s **to_release) { struct dns_udp_send_simple_message_sync_s args; #if __FreeBSD__ args.wait = async_wait_new_instance(1); #else async_wait_init(&args.wait, 1); #endif args.simple_message = NULL; dns_udp_send_simple_message(name_server, fqdn, qtype, qclass, flags, dns_udp_send_simple_message_sync_handler, &args); #if __FreeBSD__ async_wait(args.wait); s32 ret = args.wait->error_code; #else async_wait(&args.wait); s32 ret = args.wait.error_code; #endif if(to_release != NULL) { *to_release = args.simple_message; } #if __FreeBSD__ async_wait_finalize(args.wait); #else async_wait_finalize(&args.wait); #endif return ret; } bool dns_udp_simple_message_trylock(dns_simple_message_s *message) { log_debug7("dns_udp_simple_message_lock(%p) try locking (#%i)", message, smp_int_get(&message->rc)); if(group_mutex_trylock(&message->mtx, GROUP_MUTEX_WRITE)) { if(message->owner == 0) { message->owner = thread_self(); } log_debug7("dns_udp_simple_message_lock(%p) --- locked", message); //mutex_unlock(&message->mtx); return TRUE; } else { log_debug7("dns_udp_simple_message_lock(%p) NOT locked", message); return FALSE; } } void dns_udp_simple_message_lock(dns_simple_message_s *message) { log_debug7("dns_udp_simple_message_lock(%p) locking", message); group_mutex_lock(&message->mtx, GROUP_MUTEX_WRITE); #if DNS_SIMPLE_MESSAGE_HAS_WAIT_COND while( message->owner != 0 ) { cond_wait(&message->mtx_cond, &message->mtx); } #endif message->owner = thread_self(); log_debug7("dns_udp_simple_message_lock(%p) locked", message); } void dns_udp_simple_message_unlock(dns_simple_message_s *message) { log_debug7("dns_udp_simple_message_lock(%p) unlocking", message); //mutex_lock(&message->mtx); message->owner = 0; #if DNS_SIMPLE_MESSAGE_HAS_WAIT_COND cond_notify(&message->mtx_cond); #endif group_mutex_unlock(&message->mtx, GROUP_MUTEX_WRITE); log_debug7("dns_udp_simple_message_lock(%p) unlocked", message); } void dns_udp_simple_message_retain(dns_simple_message_s *simple_message) { log_debug7("dns_udp_simple_message_retain(%p)", simple_message); int n = smp_int_inc_get(&simple_message->rc); if(n == 1) { log_warn("dns_udp_simple_message_retain(%p) : retained from 0", simple_message); } } void dns_udp_simple_message_release(dns_simple_message_s *simple_message) { #if DEBUG u16 qtype = simple_message->qtype; u16 qclass = simple_message->qclass; u32 fqdn_len; u8 fqdn[MAX_DOMAIN_LENGTH]; if((fqdn_len = dnsname_len(simple_message->fqdn)) <= sizeof(fqdn)) { memcpy(fqdn, simple_message->fqdn, fqdn_len); } else { log_err("dns_udp_simple_message_release(%p) looks broken", simple_message); memcpy(fqdn, "\006BROKEN", 8); logger_flush(); abort(); } #endif int n = smp_int_dec_get(&simple_message->rc); if(n <= 0) { log_debug7("dns_udp_simple_message_release(%p) destroying", simple_message); if(n < 0) { log_err("dns_udp_simple_message_release(%p) : NEGATIVE RC: type=%{dnstype} class=%{dnsclass} status=%x", simple_message, &simple_message->qtype, &simple_message->qclass, simple_message->status); logger_flush(); abort(); } log_debug7("dns_udp_simple_message_release(%p) : %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x)", simple_message, simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); // clear the answer if(simple_message->answer != NULL) { message_debug_trash_buffer(simple_message->answer); pool_release(&message_data_pool, simple_message->answer); simple_message->answer = NULL; } // clear the name server (hostaddr) host_address_delete(simple_message->name_server); simple_message->name_server = NULL; // release the sync if(simple_message->async_node.async != NULL) { async_message_release(simple_message->async_node.async); //--message_collection_size; this one is with keys simple_message->async_node.async = NULL; } dns_simple_message_async_node_s *node = simple_message->async_node.next; while(node != NULL) { if(node->async != NULL) { async_message_release(node->async); --message_collection_size; node->async = NULL; } dns_simple_message_async_node_s *prev = node; node = node->next; #if DEBUG memset(prev, 0xd7, sizeof(dns_simple_message_async_node_s)); #endif pool_release(&dns_simple_message_async_node_pool, prev); } simple_message->async_node.next = NULL; // release the mutexes #if DNS_SIMPLE_MESSAGE_HAS_WAIT_COND cond_finalize(&simple_message->mtx_cond); #endif group_mutex_destroy(&simple_message->mtx); smp_int_destroy(&simple_message->rc); u8 status = simple_message->status | DNS_SIMPLE_MESSAGE_STATUS_INVALID; memset(simple_message, 0xd5, sizeof(dns_simple_message_s)); #if DEBUG smp_int_set(&simple_message->rc, -12345678); #endif simple_message->status = status; log_debug7("dns_udp_simple_message_release(%p) destroyed (%x)", simple_message, simple_message->status); pool_release(&dns_simple_message_pool, simple_message); } else { // nothing to do yet. // note that since the message is not locked, the content CANNOT be printed #if !DEBUG log_debug7("dns_udp_simple_message_release(%p) (%x)", simple_message, n); #else log_debug7("dns_udp_simple_message_release(%p) (%x) : %{dnsname} %{dnstype} %{dnsclass}", simple_message, n, fqdn, &qtype, &qclass); #endif } } static void dns_udp_aggregate_simple_messages(dns_simple_message_s *head, dns_simple_message_s *tail) { dns_simple_message_async_node_s *node = (dns_simple_message_async_node_s*)pool_alloc(&dns_simple_message_async_node_pool); dns_udp_simple_message_lock(head); dns_udp_simple_message_lock(tail); log_debug6("dns_udp_aggregate_simple_messages(%p, %p) head %p->%p", head, tail, &head->async_node, head->async_node.next); // prepare the container to match the simple message's // append the current list to the new node (should be only one item) node->next = tail->async_node.next; // node->async = tail->async_node.async; tail->async_node.next = NULL; tail->async_node.async = NULL; node->async->args = head; // change the linked message to the first one log_debug6("dns_udp_aggregate_simple_messages(%p, %p) edit %p->%p", head, tail, node, node->next); // update the first_message for the whole list (every time ?) dns_simple_message_async_node_s *sm_last_node = node; while(sm_last_node->next != NULL) { sm_last_node = sm_last_node->next; log_debug6("dns_udp_aggregate_simple_messages(%p, %p) edit %p->%p. Updating message as %p (was %p)", head, tail, sm_last_node, sm_last_node->next, sm_last_node->async->args, head); sm_last_node->async->args = head; // change the linked message to the first one } // last node of the list, append the original list to the current list sm_last_node->next = head->async_node.next; head->async_node.next = node; // the list is ready #if DEBUG while(node != NULL) { log_debug6("dns_udp_aggregate_simple_messages(%p, %p) node %p=>%p", head, tail, node, node->next); node = node->next; } #endif head->status |= DNS_SIMPLE_MESSAGE_STATUS_AGGREGATED; // added sendto_packets_aggregated++; log_debug5("added message@%p to message@%p: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} %s (%x)", tail, head, head->fqdn, &head->qtype, &head->qclass, head->name_server, (head->recurse)?"rd":"", head->status); // adding a query grants a new retry head->retries_left = dns_udp_settings->retry_count + 1; dns_udp_simple_message_unlock(tail); // unlock B dns_udp_simple_message_unlock(head); } static int dns_udp_receive_service_hook(dns_simple_message_s *simple_message, message_data *mesg); static bool dns_udp_send_simple_message_process_hook_default(dns_simple_message_s *simple_message, message_data *mesg) { (void)simple_message; (void)mesg; return FALSE; } static dns_udp_query_hook *dns_udp_send_simple_message_process_hook = dns_udp_send_simple_message_process_hook_default; /** * Called by the send worker(s) to do a query * * The return value is ignored by its only caller. */ static int dns_udp_send_simple_message_process(async_message_s *domain_message, random_ctx rndctx, u16 source_port, int source_socket, u32 worker_index) { dns_simple_message_s *simple_message = (dns_simple_message_s*)domain_message->args; // check if in pending collection #if DEBUG if(domain_message->start_time < 0) { logger_flush(); abort(); } #endif // pre-increase the RC because of this new reference (into the DB) dns_udp_simple_message_retain(simple_message); /// @note: at this point, in a normal usage, the RC of simple_message should be 2 // lock the collection log_debug7("sending: locking message collection"); mutex_lock(&message_collection_mtx); // lock A log_debug7("sending: message collection locked"); // lock the simple message dns_udp_simple_message_lock(simple_message); // lock B ptr_node *node = ptr_set_find(&message_collection, simple_message); if((node == NULL) || (node->value == NULL)) { u32 simple_message_size = DNS_HEADER_LENGTH + dnsname_len(simple_message->fqdn) + 4 + 11; u64 delay_epoch_us = dns_udp_host_state_packet_try(simple_message->name_server, simple_message_size); if(delay_epoch_us > 0) { dns_udp_simple_message_unlock(simple_message); // unlock B mutex_unlock(&message_collection_mtx); // unlock A dns_udp_simple_message_release(simple_message); // delay log_debug4("delaying: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) to %llT (from %llT)", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, delay_epoch_us, timeus()); delayed_message_insert(delay_epoch_us, domain_message); return SUCCESS; } if(node == NULL) { node = ptr_set_insert(&message_collection, simple_message); } ++message_collection_keys; // newly inserted // put in pending collection // RC already increased node->value = domain_message; simple_message->status |= DNS_SIMPLE_MESSAGE_STATUS_COLLECTED; simple_message->status &= ~DNS_SIMPLE_MESSAGE_STATUS_QUEUED; dns_udp_simple_message_unlock(simple_message); mutex_unlock(&message_collection_mtx); // unlock A log_debug7("sending: message collection unlocked"); int return_code; // we have allocated the right to send the query mutex_lock(&limiter_send_wait_mtx); // this one is a loose test // there cannot be a reasonable blocking lock with the sender // so for now I focus on having it's content added properly (senders are locking each-other for a few microseconds) // and I only ensure the memory wall is applied using the send mutex // // the next two waits are perfectly normal // // note: maybe I should use a group mutex as they are better equipped for potential long waits log_debug4("sender: waiting for the receiving bandwidth to be low enough"); limiter_wait(&dns_udp_recv_bandwidth, 0); log_debug4("sender: waiting for the send rate to be low enough"); limiter_wait(&dns_udp_send_rate, 1); log_debug4("sender: waiting for the send bandwidth to be low enough"); limiter_wait(&dns_udp_send_bandwidth, simple_message_size); mutex_unlock(&limiter_send_wait_mtx); // don't give a sent time until it's actually sent (high loads could trigger a timeout before the packet is sent) simple_message->sent_time_us = MAX_S64; // if the message is retried, use the same address:port as before if(simple_message->sender_socket < 0) { log_debug("sending: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x)", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); simple_message->sender_socket = source_socket; simple_message->worker_index = worker_index; simple_message->source_port = source_port; } else { log_debug("sending: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) again", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); source_socket = simple_message->sender_socket; //worker_index = simple_message->worker_index; //source_port = simple_message->source_port; } dns_udp_simple_message_lock(simple_message); log_debug5("set message@%p: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} %s (%x)", domain_message, simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, (simple_message->recurse)?"rd":"", simple_message->status); // generate message message_data_with_buffer mesg_buff; message_data *mesg = message_data_with_buffer_init(&mesg_buff); // message_send_udp_reset(mesg); if(simple_message->dns_id == 0) { simple_message->dns_id = (u16)random_next(rndctx); } message_make_query_ex(mesg, simple_message->dns_id, simple_message->fqdn, simple_message->qtype, simple_message->qclass, simple_message->flags); if(simple_message->recurse) { message_set_rd_flag(mesg); } // send message // // answer = send back to sender // return_code = message_set_sender_from_host_address(mesg, simple_message->name_server); dns_udp_simple_message_unlock(simple_message); if(ISOK(return_code)) { if(!dns_udp_send_simple_message_process_hook(simple_message, mesg)) { for(;;) { // send the packet //if((return_code = sendto(s, mesg->buffer, mesg->send_length, 0, &sa.sa, sa_len)) == mesg->send_length) if((return_code = message_send_udp(mesg, source_socket)) == (s32)message_get_size(mesg)) { dns_udp_simple_message_lock(simple_message); simple_message->status |= DNS_SIMPLE_MESSAGE_STATUS_SENT; log_notice("sent: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) (@%p)", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, simple_message); simple_message->sent_time_us = timeus(); dns_udp_simple_message_unlock(simple_message); // unlock B // one RC can be released from this reference dns_udp_simple_message_release(simple_message); /// @note at this point the RC is set to 1, but /// it potentially could be 0 (and thus simple_message could already be destroyed) // message should NOT be used after this point // u64 now = time(NULL); mutex_lock(&sendto_statistics_mtx); if(sendto_epoch == now) { sendto_total += return_code; sendto_packets++; mutex_unlock(&sendto_statistics_mtx); } else { u32 st = sendto_total; u32 sq = sendto_packets; u32 sqa = sendto_packets_aggregated; sendto_epoch = now; sendto_total = return_code; sendto_packets = 0; sendto_packets_aggregated = 0; mutex_unlock(&sendto_statistics_mtx); log_debug("sent: total=%db/s (packets=%d/aggregated=%d/s)", st, sq, sqa); } // return return_code; } // an error occurred if((return_code != MAKE_ERRNO_ERROR(EAGAIN)) && (return_code != MAKE_ERRNO_ERROR(EWOULDBLOCK))) { // return_code = MAKE_ERRNO_ERROR(err); break; } // try again } } else // the hook did something { if((simple_message->status & DNS_SIMPLE_MESSAGE_STATUS_TIMEDOUT) == 0) { dns_udp_receive_service_hook(simple_message, mesg); } dns_udp_simple_message_release(simple_message); return SUCCESS; } } // error occurred while sending the message dns_udp_simple_message_lock(simple_message); simple_message->status |= DNS_SIMPLE_MESSAGE_STATUS_FAILURE; log_err("sending: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x): %r", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, return_code); dns_udp_simple_message_unlock(simple_message); mutex_lock(&message_collection_mtx); // ensure that the node still exists ptr_node *simple_message_node = ptr_set_find(&message_collection, simple_message); if(simple_message_node != NULL) { ptr_set_delete(&message_collection, simple_message); --message_collection_keys; // one RC can be released for the collection dns_udp_simple_message_lock(simple_message); simple_message->status &= ~DNS_SIMPLE_MESSAGE_STATUS_COLLECTED; dns_udp_simple_message_unlock(simple_message); dns_udp_simple_message_release(simple_message); } else { // even if this is possible, this should NEVER happen log_debug6("message @%p had been removed from the collection already", simple_message); } mutex_unlock(&message_collection_mtx); log_debug7("sending: message collection unlocked"); /// @note RC = 1 // the handler NEEDS to do the final release domain_message->error_code = return_code; domain_message->handler(domain_message); return return_code; } else // probable aggregation { simple_message->sent_time_us = timeus(); simple_message->status |= DNS_SIMPLE_MESSAGE_STATUS_COLLECTED; simple_message->status &= ~DNS_SIMPLE_MESSAGE_STATUS_QUEUED; dns_udp_simple_message_unlock(simple_message); log_debug("sending: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) aggregated", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); // append the async callback to the dns_simple_message structure // the first message for this query, it will reference the new message dns_simple_message_s *old_message = (dns_simple_message_s *)node->key; // aggregate /append simple_message to first_message dns_udp_aggregate_simple_messages(old_message, simple_message); ++message_collection_size; mutex_unlock(&message_collection_mtx); // one RC can be released from the collection dns_udp_simple_message_release(simple_message); // one RC can be released from this reference dns_udp_simple_message_release(simple_message); // should be destroyed at this point return SUCCESS; } } static int dns_udp_send_service(struct service_worker_s *worker) { struct sockaddr_in6 sin6; random_ctx rndctx; const u32 worker_index = worker->worker_index; log_debug("send: service started (%u/%u)", worker_index + 1, worker->service->worker_count); const int my_socket = dns_udp_socket[worker_index]; struct dns_udp_receive_ctx *ctx = dns_udp_receive_context[worker->worker_index]; rndctx = thread_pool_get_random_ctx(); ZEROMEMORY(&sin6, sizeof(sin6)); socklen_t sin6len = sizeof(sin6); getsockname(my_socket, (struct sockaddr*)&sin6, &sin6len); const u16 source_port = sin6.sin6_port; bool threadpool_pacing = FALSE; while(service_should_run(worker) /*|| !async_queue_empty(&dns_udp_send_handler_queue)*/) { // timeout high priority list. async_message_s *domain_message; // callback threadpool pacing if(dns_udp_settings->callback_queue_size > 0) { s64 r = thread_pool_queue_size(dns_udp_callback_tp); r *= 100; r /= dns_udp_settings->callback_queue_size; if(r > 95) // 95% full => pause { usleep(100000); if(!threadpool_pacing) { log_debug("dns-udp: threadpool queue is almost full: pacing"); threadpool_pacing = TRUE; } continue; } } if(threadpool_pacing) { log_debug("dns-udp: threadpool queue has reached acceptable levels: resuming"); threadpool_pacing = FALSE; } // size_t read_avail = dns_udp_receive_ctx_available(ctx); if(read_avail < 4) { log_debug("send: pausing as the buffer of receiver #%i is almost full: %lli slots available", worker_index, read_avail); usleep(20000); continue; } // I'm using the worker lock to synchronise with its counterpart, // so I don't have to create yet another mutex mutex_lock(&worker->lock); domain_message = list_dl_dequeue(&dns_udp_high_priority[worker_index]); mutex_unlock(&worker->lock); if(domain_message == NULL) { domain_message = delayed_message_next(); if(domain_message == NULL) { domain_message = async_message_next(&dns_udp_send_handler_queue); // this call waits if nothing is available if(domain_message == NULL) { continue; } else { dns_simple_message_s *simple_message = (dns_simple_message_s*)domain_message->args; log_debug3("send: next: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x)", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); } } else { dns_simple_message_s *simple_message = (dns_simple_message_s*)domain_message->args; log_debug3("send: delayed: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x)", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); } } else { dns_simple_message_s *simple_message = (dns_simple_message_s*)domain_message->args; log_debug3("send: timedout: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x)", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); if(dns_udp_settings->tcp_fallback_on_timeout) { simple_message->tcp |= simple_message->retries_left == 0; } } log_debug6("send: processing message (%u still in queue)", async_queue_size(&dns_udp_send_handler_queue)); switch(domain_message->id) { case DNS_UDP_SIMPLE_QUERY: { log_debug6("DNS_UDP_SIMPLE_QUERY"); dns_simple_message_s *simple_message = (dns_simple_message_s*)domain_message->args; if(!simple_message->tcp) { log_debug3("send: next: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) (udp)", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); dns_udp_send_simple_message_process(domain_message, rndctx, source_port, my_socket, worker_index); } else { log_debug3("send: next: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) (tdp)", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status); dns_udp_tcp_query(simple_message, worker); } break; } default: { log_err("DNS_UDP_? %u", domain_message->id); domain_message->error_code = SERVICE_ID_ERROR; domain_message->handler(domain_message); break; } } } service_set_stopping(worker); log_debug("send: service stopped (%u/%u)", worker_index + 1, worker->service->worker_count); return 0; } typedef u8 message_4k[4096]; struct aligned_socketaddress { socketaddress sa; socklen_t sa_len; size_t msg_len; time_t epoch; // char padding[1024 - sizeof(socketaddress) - sizeof(size_t) * 2 - sizeof(time_t)]; }; typedef struct aligned_socketaddress aligned_socketaddress; struct dns_udp_receive_ctx { mutex_t mtx; cond_t cond; u8* messages_unaligned; u8* addreses_unaligned; message_4k *messages; // = malloc(message_buffer_count * sizeof(message_4k)); aligned_socketaddress *addresses; // = malloc(message_buffer_count * sizeof(socketaddress)); size_t count; // total number of slots #if __unix__ size_t read_index __attribute__((aligned(64))); // where incoming messages can be read size_t proc_index __attribute__((aligned(64))); // where processor can get its next one //size_t read_avail __attribute__((aligned(64))); // how many incoming slots are available #else size_t read_index; // where incoming messages can be read size_t proc_index; // where processor can get its next one //size_t read_avail; // how many incoming slots are available #endif }; typedef struct dns_udp_receive_ctx dns_udp_receive_ctx; static dns_udp_receive_ctx* dns_udp_receive_ctx_init(size_t count) { dns_udp_receive_ctx *ctx; ZALLOC_OBJECT_OR_DIE(ctx, dns_udp_receive_ctx, DNSURECV_TAG); //group_mutex_init(&ctx->mtx); mutex_init(&ctx->mtx); cond_init(&ctx->cond); MALLOC_OR_DIE(u8*, ctx->messages_unaligned, count * sizeof(message_4k) + 4095, DNSURMU_TAG); MALLOC_OR_DIE(u8*, ctx->addreses_unaligned, count * sizeof(aligned_socketaddress) + 63, DNSURAU_TAG); ctx->messages = (message_4k*)(((intptr)ctx->messages_unaligned + 4095) & ~4095); ctx->addresses = (aligned_socketaddress*)(((intptr)ctx->addreses_unaligned + 63) & ~63); ctx->count = count; ctx->read_index = 0; // avail = count - (r - p) ctx->proc_index = 0; // while p!=r: process, ++p for(size_t i = 0; i < count; ++i) { ctx->addresses->sa_len = sizeof(socketaddress); ctx->addresses->msg_len = 0; } //ctx->read_avail = count; return ctx; } static void dns_udp_receive_ctx_destroy(dns_udp_receive_ctx *ctx) { free(ctx->messages_unaligned); free(ctx->addreses_unaligned); //group_mutex_destroy(&ctx->mtx); cond_finalize(&ctx->cond); mutex_destroy(&ctx->mtx); ZFREE_OBJECT(ctx); } static size_t dns_udp_receive_ctx_available(dns_udp_receive_ctx *ctx) { mutex_lock(&ctx->mtx); size_t avail = ctx->count - (ctx->read_index - ctx->proc_index); mutex_unlock(&ctx->mtx); return avail; } static ssize_t dns_udp_receive_ctx_wait_to_read(dns_udp_receive_ctx *ctx) { mutex_lock(&ctx->mtx); for(;;) { size_t avail = ctx->count - (ctx->read_index - ctx->proc_index); if(avail != 0) { break; } if(cond_timedwait(&ctx->cond, &ctx->mtx, 1000000ULL) != 0) { mutex_unlock(&ctx->mtx); return -1; } } mutex_unlock(&ctx->mtx); return ctx->read_index % ctx->count; } static void dns_udp_receive_ctx_notify_read(dns_udp_receive_ctx *ctx) { mutex_lock(&ctx->mtx); ++ctx->read_index; cond_notify(&ctx->cond); mutex_unlock(&ctx->mtx); } static ssize_t dns_udp_receive_ctx_wait_to_process(dns_udp_receive_ctx *ctx) { mutex_lock(&ctx->mtx); for(;;) { if(ctx->proc_index < ctx->read_index) { break; } if(cond_timedwait(&ctx->cond, &ctx->mtx, 1000000ULL) != 0) { mutex_unlock(&ctx->mtx); return -1; } } mutex_unlock(&ctx->mtx); return ctx->proc_index % ctx->count; } static void dns_udp_receive_ctx_notify_process(dns_udp_receive_ctx *ctx) { mutex_lock(&ctx->mtx); ++ctx->proc_index; cond_notify(&ctx->cond); mutex_unlock(&ctx->mtx); } static int dns_udp_receive_read_service(struct service_worker_s *worker) { log_debug("receive: service read started (%u/%u)", worker->worker_index + 1, worker->service->worker_count); int my_socket = dns_udp_socket[worker->worker_index]; dns_udp_receive_ctx *ctx = dns_udp_receive_context[worker->worker_index]; // u16 port; struct sockaddr_in6 sin6; ZEROMEMORY(&sin6, sizeof(sin6)); socklen_t sin6len = sizeof(sin6); getsockname(my_socket, (struct sockaddr*)&sin6, &sin6len); log_debug("receive: listening on %{sockaddr}", &sin6); tcp_set_recvtimeout(my_socket, dns_udp_settings->timeout / ONE_SECOND_US, dns_udp_settings->timeout % ONE_SECOND_US); s64 last_loop = timeus(); while(service_should_run(worker)) { int n; ssize_t index = dns_udp_receive_ctx_wait_to_read(ctx); if(index < 0) { #if DEBUG log_debug7("receive: wait to read"); #endif continue; } ctx->addresses[index].sa_len = sizeof(socketaddress); s64 now = timeus(); s64 elapsed = now - last_loop; log_debug6("receive: recvfrom(%i, %p, %lli, %i, %p, %p=%i) in %lli (elapsed: %llu)", my_socket, &ctx->messages[index], sizeof(ctx->messages[index]), 0, &ctx->addresses[index].sa.sa, &ctx->addresses[index].sa_len, ctx->addresses[index].sa_len, index, elapsed); n = recvfrom(my_socket, &ctx->messages[index], sizeof(ctx->messages[index]), 0, &ctx->addresses[index].sa.sa, &ctx->addresses[index].sa_len); last_loop = timeus(); if(n >= 0) { if(n > 0) { log_debug6("receive: recvfrom(%i, ... , %{sockaddr}) = %i", my_socket, &ctx->addresses[index].sa.sa, n); ctx->addresses[index].epoch = time(NULL); ctx->addresses[index].msg_len = n; dns_udp_receive_ctx_notify_read(ctx); } else { log_debug6("receive: recvfrom(%i, ... , %{sockaddr}) = 0 = empty packet (ignoring)", my_socket, &ctx->addresses[index].sa.sa); } } else { int err = errno; if(err == EINTR) { #if DEBUG log_debug7("receive: recvfrom EINTR"); #endif continue; } if(err == EAGAIN) { #if DEBUG log_debug7("receive: recvfrom EAGAIN"); #endif continue; } log_err("receive: recvfrom error: %r", MAKE_ERRNO_ERROR(err)); } } service_set_stopping(worker); log_debug("receive: service read stopped (%u/%u)", worker->worker_index + 1, worker->service->worker_count); return SUCCESS; } static int dns_udp_receive_process_service(struct service_worker_s *worker) { log_debug("receive: service process started (%u/%u)", worker->worker_index + 1, worker->service->worker_count); int my_socket = dns_udp_socket[worker->worker_index]; dns_udp_receive_ctx *ctx = dns_udp_receive_context[worker->worker_index]; struct sockaddr_in6 sin6; ZEROMEMORY(&sin6, sizeof(sin6)); socklen_t sin6len = sizeof(sin6); getsockname(my_socket, (struct sockaddr*)&sin6, &sin6len); message_data *mesg; for(;;) { mesg = (message_data*)pool_alloc(&message_data_pool); if(mesg != NULL) { break; } if(!service_should_run(worker)) { service_set_stopping(worker); log_debug("receive: service process stopped (%u/%u) (early)", worker->worker_index + 1, worker->service->worker_count); return 0; } sleep(1); } host_address sender_host_address; while(service_should_run(worker)) { log_debug("receive: waiting %i / next", my_socket); ssize_t index = dns_udp_receive_ctx_wait_to_process(ctx); if(index < 0) { log_debug("receive: timed-out %i / next", my_socket); continue; } log_debug("receive: processing %i / %lli", my_socket, index); size_t n = ctx->addresses[index].msg_len; time_t now = ctx->addresses[index].epoch; mutex_lock(&limiter_recv_wait_mtx); // force add the received bytes to the limit (this feels insufficient) limiter_add_anyway(&dns_udp_recv_bandwidth, n, NULL, NULL); mutex_unlock(&limiter_recv_wait_mtx); mutex_lock(&recvfrom_statistics_mtx); if(recvfrom_epoch == now) { recvfrom_total += n; recvfrom_packets++; mutex_unlock(&recvfrom_statistics_mtx); } else { recvfrom_epoch = now; u32 rt = recvfrom_total; recvfrom_total = n; u32 rq = recvfrom_packets; recvfrom_packets = 0; mutex_unlock(&recvfrom_statistics_mtx); log_debug("receive: recvfrom: %d b/s %d p/s", rt, rq); } log_debug2("receive: statistics updated %i", my_socket); message_reset_buffer_size(mesg); message_copy_into_buffer(mesg, ctx->messages[index], n); // scan-build false-positive: mesg is not NULL, thus buffer cannot be NULL message_copy_sender_from_sa(mesg, &ctx->addresses[index].sa.sa, ctx->addresses[index].sa_len); ya_result return_code; if(ISOK(return_code = message_process_lenient(mesg))) { // look in the timeout collection host_address_set_with_sockaddr(&sender_host_address, message_get_sender(mesg)); if(sender_host_address.version == 6) { if(memcmp(sender_host_address.ip.v6.bytes, V4_WRAPPED_IN_V6, sizeof(V4_WRAPPED_IN_V6)) == 0) { // unwrap u32 ipv4 = sender_host_address.ip.v6.dwords[3]; sender_host_address.ip.v4.value = ipv4; sender_host_address.version = 4; } } dns_simple_message_s message; message.name_server = &sender_host_address; message.sent_time_us = MAX_S64; message.received_time_us = 0; message.retries_left = 0; int len = dnsname_copy(message.fqdn, message_get_canonised_fqdn(mesg)); if(ISOK(len)) { message.qtype = message_get_u16_at(mesg, 12 + len); message.qclass = message_get_u16_at(mesg, 12 + len + 2); // remove it from the collection log_debug7("receive: locking message collection", my_socket); mutex_lock(&message_collection_mtx); log_debug7("receive: seeking matching message", my_socket); ptr_node *node = ptr_set_find(&message_collection, &message); if(node != NULL) { // proceed bool truncated = message_istruncated(mesg); dns_simple_message_s *simple_message = (dns_simple_message_s*)node->key; dns_udp_simple_message_lock(simple_message); log_debug2("receive: deleting message", my_socket); ptr_set_delete(&message_collection, simple_message); --message_collection_keys; // the message is not in the timeout collection anymore // it should contain an answer, or an error, ... or a message with the TC bit on if(!truncated) { simple_message->status &= ~DNS_SIMPLE_MESSAGE_STATUS_COLLECTED; simple_message->status |= DNS_SIMPLE_MESSAGE_STATUS_RECEIVED; } dns_udp_simple_message_unlock(simple_message); mutex_unlock(&message_collection_mtx); log_debug7("receive: message collection unlocked", my_socket); // RC is supposed to be 1 #if DEBUG if(smp_int_get(&simple_message->rc) != 1) { log_warn("receive: message RC is not 1 (%i)", smp_int_get(&simple_message->rc)); } #endif simple_message->received_time_us = timeus(); s64 dt = MAX(simple_message->received_time_us - simple_message->sent_time_us, 0); double dts = dt; dts /= ONE_SECOND_US_F; #if DNS_UDP_TC_FALLBACK_TO_TCP_SUPPORT if(!truncated) { #endif simple_message->answer = mesg; log_notice("receive: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) [%6.3fs]", message.fqdn, &message.qtype, &message.qclass, message.name_server, simple_message->status, dts); dns_udp_simple_message_answer_call_handlers(simple_message); // simple_message = NULL; // not necessarry, but informative // allocate the next buffer, handle the hard_limit of the pool: // when the pool has reached peak capacity, allocation returns NULL mesg = dns_udp_allocate_message_data(worker); #if DNS_UDP_TC_FALLBACK_TO_TCP_SUPPORT } else { // the message has been truncated // it should be queried again using TCP log_notice("receive: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) [%6.3fs]: truncated", message.fqdn, &message.qtype, &message.qclass, message.name_server, simple_message->status, dts); dns_udp_tcp_query(simple_message, worker); } #endif } else { mutex_unlock(&message_collection_mtx); log_debug7("receive: message collection unlocked", my_socket); // unknown log_warn("receive: unexpected message %{dnsname} %{dnstype} %{dnsclass} from %{sockaddr}", message.fqdn, &message.qtype, &message.qclass, message_get_sender_sa(mesg)); } } else { log_err("receive: an error occurred while copying the name '%{dnsname}': %r", message_get_canonised_fqdn(mesg), len); } } else { if(service_should_run(worker)) { #if DEBUG log_memdump(g_system_logger, MSG_DEBUG3, message_get_buffer_const(mesg), message_get_size(mesg), 32); #endif log_err("receive: cannot handle answer: %r", return_code); } } dns_udp_receive_ctx_notify_process(ctx); } if(mesg != NULL) { message_debug_trash_buffer(mesg); pool_release(&message_data_pool, mesg); } service_set_stopping(worker); log_debug("receive: service process stopped (%u/%u)", worker->worker_index + 1, worker->service->worker_count); return 0; } static void dns_udp_timeout_service_cull(ptr_vector *todeletep) { int messages_count = 0; int failed_tries = 0; log_debug7("timeout: locking message collection"); if(mutex_trylock(&message_collection_mtx)) { log_debug7("timeout: message collection locked"); ptr_set_iterator iter; ptr_set_iterator_init(&message_collection, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); dns_simple_message_s *simple_message = (dns_simple_message_s *)node->key; messages_count++; if(dns_udp_simple_message_trylock(simple_message)) { s64 now = timeus(); if(simple_message->sent_time_us != MAX_S64) { #if DEBUG if(now < simple_message->sent_time_us) { log_debug("message was sent %llT in the future! (sent at %llT, now is %llT, really %llT)", simple_message->sent_time_us - now, simple_message->sent_time_us, now, timeus()); } #endif if((simple_message->status & DNS_SIMPLE_MESSAGE_STATUS_SENT) != 0) { if((simple_message->status & DNS_SIMPLE_MESSAGE_STATUS_RECEIVED) == 0) { if(now - simple_message->sent_time_us > dns_udp_settings->timeout) // older than 3s ? => remove { // timed out // retain because the reference is now in two collection dns_udp_simple_message_retain(simple_message); simple_message->status |= DNS_SIMPLE_MESSAGE_STATUS_TIMEDOUT; ptr_vector_append(todeletep, simple_message); } } } } // else this message has not been sent yet dns_udp_simple_message_unlock(simple_message); } else { failed_tries++; } } if(failed_tries > 0) { log_warn("timeout: failed to lock %i messages (on a total of %i)", failed_tries, messages_count); } for(int i = 0; i <= ptr_vector_last_index(todeletep); i++) { dns_simple_message_s *simple_message = (dns_simple_message_s *)ptr_vector_get(todeletep, i); ptr_set_delete(&message_collection, simple_message); // release because it has been removed from one collection --message_collection_keys; dns_udp_simple_message_release(simple_message); simple_message->status &= ~DNS_SIMPLE_MESSAGE_STATUS_COLLECTED; } mutex_unlock(&message_collection_mtx); log_debug7("timeout: message collection unlocked"); } else { log_debug7("timeout: failed to lock message collection"); } } static int dns_udp_timeout_service(struct service_worker_s *worker) { log_debug("dns_udp_timeout_service started"); ptr_vector todelete = PTR_VECTOR_EMPTY; while(service_should_run(worker)) { sleep(1); if(!service_should_run(worker)) { break; } ptr_vector_clear(&todelete); dns_udp_timeout_service_cull(&todelete); s64 now = timeus(); for(int i = 0; i <= ptr_vector_last_index(&todelete); i++) { dns_simple_message_s *simple_message = (dns_simple_message_s *)ptr_vector_get(&todelete, i); log_debug("timeout: [r=%i] %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) (sent at %llT, now is %llT)", simple_message->retries_left, simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, simple_message->sent_time_us, now); if(simple_message->retries_left > 0) { simple_message->retries_left--; async_message_s* async = simple_message->async_node.async; log_debug5("timeout: re-queueing message with id=%i", async->id); /** * @note Here was the issue. The messages are queued so it can take a long time until they are retried. */ async->id = DNS_UDP_SIMPLE_QUERY; async->start_time = timeus(); struct service_worker_s *owning_worker = service_get_worker(&dns_udp_send_handler, simple_message->worker_index); assert(owning_worker != NULL); mutex_lock(&owning_worker->lock); list_dl_enqueue(&dns_udp_high_priority[simple_message->worker_index], async); mutex_unlock(&owning_worker->lock); } else { simple_message->received_time_us = MAX_U64; yassert(now >= simple_message->sent_time_us); double dts = now - simple_message->sent_time_us; dts /= ONE_SECOND_US_F; log_notice("receive: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) timed-out [%6.3fs]", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, dts); dns_simple_message_async_node_s *node = simple_message->async_node.next; while(node != NULL) { // the handler MUST release one reference dns_udp_simple_message_retain(simple_message); node->async->error_code = DNS_UDP_TIMEOUT; node->async->handler(node->async); node = node->next; } // there is no need to retain, the reference from the collection has not been decreased yet simple_message->async_node.async->error_code = DNS_UDP_TIMEOUT; simple_message->async_node.async->handler(simple_message->async_node.async); } } } service_set_stopping(worker); ptr_vector_destroy(&todelete); log_debug("dns_udp_timeout_service stopped"); return 0; } void dns_udp_cancel_all_queries() { int messages_count = 0; int failed_tries = 0; ptr_vector todelete = PTR_VECTOR_EMPTY; s64 now = timeus(); mutex_lock(&message_collection_mtx); ptr_set_iterator iter; ptr_set_iterator_init(&message_collection, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); dns_simple_message_s *simple_message = (dns_simple_message_s *)node->key; messages_count++; if(dns_udp_simple_message_trylock(simple_message)) { now = timeus(); if(simple_message->sent_time_us != MAX_S64) { #if DEBUG if(now < simple_message->sent_time_us) { log_debug("message was sent %llT in the future! (sent at %llT, now is %llT, really %llT)", simple_message->sent_time_us - now, simple_message->sent_time_us, now, timeus()); } #endif if(now - simple_message->sent_time_us > dns_udp_settings->timeout) // older than 3s ? => remove { // timed out // retain because the reference is now in two collection dns_udp_simple_message_retain(simple_message); simple_message->status |= DNS_SIMPLE_MESSAGE_STATUS_TIMEDOUT|DNS_SIMPLE_MESSAGE_STATUS_INVALID; ptr_vector_append(&todelete, simple_message); } } #if DEBUG else { if(now - simple_message->sent_time_us > dns_udp_settings->timeout) { log_warn("timeout: message would have wrongly been timed-out"); } } #endif dns_udp_simple_message_unlock(simple_message); } else { failed_tries++; } } if(failed_tries > 0) { log_warn("timeout: failed to lock %i messages (on a total of %i)", failed_tries, messages_count); } for(int i = 0; i <= ptr_vector_last_index(&todelete); i++) { dns_simple_message_s *simple_message = (dns_simple_message_s *)ptr_vector_get(&todelete, i); ptr_set_delete(&message_collection, simple_message); --message_collection_keys; // release because it has been removed from one collection dns_udp_simple_message_release(simple_message); simple_message->status &= ~DNS_SIMPLE_MESSAGE_STATUS_COLLECTED; } mutex_unlock(&message_collection_mtx); for(int i = 0; i <= ptr_vector_last_index(&todelete); i++) { dns_simple_message_s *simple_message = (dns_simple_message_s *)ptr_vector_get(&todelete, i); log_debug("cancel: [r=%i] %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) (sent at %llT, now is %llT)", simple_message->retries_left, simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, simple_message->sent_time_us, now); simple_message->received_time_us = MAX_U64; yassert(now >= simple_message->sent_time_us); double dts = now - simple_message->sent_time_us; dts /= ONE_SECOND_US_F; log_notice("cancel: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) cancelled [%6.3fs]", simple_message->fqdn, &simple_message->qtype, &simple_message->qclass, simple_message->name_server, simple_message->status, dts); dns_simple_message_async_node_s *node = simple_message->async_node.next; while(node != NULL) { // the handler MUST release one reference dns_udp_simple_message_retain(simple_message); node->async->error_code = DNS_UDP_CANCEL; node->async->handler(node->async); node = node->next; } // there is no need to retain, the reference from the collection has not been decreased yet simple_message->async_node.async->error_code = DNS_UDP_CANCEL; simple_message->async_node.async->handler(simple_message->async_node.async); } } u32 dns_udp_send_queue_size() { u32 ret = async_queue_size(&dns_udp_send_handler_queue); return ret; } u32 dns_udp_pending_queries_count() { return message_collection_keys; } u32 dns_udp_pending_feedback_count() { return message_collection_keys + message_collection_size; } /** * Sets a hook for queries. * * The hook is called by the service on each messages and is expected to answer * TRUE if it wrote an answer on it * FALSE if it did not * * Every use of the dns_udp service is affected by this. * Only one hook is possible at a given time. * * @param hook a function or NULL to reset to no HOOK. */ void dns_udp_set_query_hook(dns_udp_query_hook *hook) { if(hook != NULL) { dns_udp_send_simple_message_process_hook = hook; } else { dns_udp_send_simple_message_process_hook = dns_udp_send_simple_message_process_hook_default; } } static int dns_udp_receive_service_hook(dns_simple_message_s *simple_message, message_data *mesg) { (void)simple_message; host_address sender_host_address; int n = message_get_size(mesg); if(n > 0) { log_debug6("receive: recvfrom(hook, ... , %{sockaddr}) = %i (hook)", message_get_sender(mesg), n); } else { log_debug6("receive: empty packet (hook)"); } u64 now = time(NULL); mutex_lock(&recvfrom_statistics_mtx); if(recvfrom_epoch == now) { recvfrom_total += n; recvfrom_packets++; mutex_unlock(&recvfrom_statistics_mtx); } else { recvfrom_epoch = now; u32 rt = recvfrom_total; recvfrom_total = n; u32 rq = recvfrom_packets; recvfrom_packets = 0; mutex_unlock(&recvfrom_statistics_mtx); log_debug("receive: recvfrom: %d b/s %d p/s (hook)", rt, rq); } ya_result return_code; if(ISOK(return_code = message_process_lenient(mesg))) { // look in the timeout collection host_address_set_with_sockaddr(&sender_host_address, message_get_sender(mesg)); if(sender_host_address.version == 6) { if(memcmp(sender_host_address.ip.v6.bytes, V4_WRAPPED_IN_V6, sizeof(V4_WRAPPED_IN_V6)) == 0) { // unwrap u32 ipv4 = sender_host_address.ip.v6.dwords[3]; sender_host_address.ip.v4.value = ipv4; sender_host_address.version = 4; } } dns_simple_message_s message; message.name_server = &sender_host_address; message.sent_time_us = MAX_S64; message.received_time_us = 0; message.retries_left = 0; int len = dnsname_copy(message.fqdn, message_get_canonised_fqdn(mesg)); if(ISOK(len)) { message.qtype = message_get_u16_at(mesg, 12 + len); message.qclass = message_get_u16_at(mesg, 12 + len + 2); // remove it from the collection mutex_lock(&message_collection_mtx); ptr_node *simple_message_node = ptr_set_find(&message_collection, &message); if(simple_message_node != NULL) { // proceed bool truncated = message_istruncated(mesg); dns_simple_message_s *simple_message_cached = (dns_simple_message_s*)simple_message_node->key; dns_udp_simple_message_lock(simple_message_cached); ptr_set_delete(&message_collection, simple_message_cached); --message_collection_keys; // the message is not in the timeout collection anymore // it should contain an answer, or an error, ... or a message with the TC bit on if(!truncated) { simple_message_cached->status &= ~DNS_SIMPLE_MESSAGE_STATUS_COLLECTED; simple_message_cached->status |= DNS_SIMPLE_MESSAGE_STATUS_RECEIVED; } dns_udp_simple_message_unlock(simple_message_cached); mutex_unlock(&message_collection_mtx); // RC is supposed to be 1 #if DEBUG if(smp_int_get(&simple_message_cached->rc) != 1) { log_warn("receive: message RC is not 1 (%i) (hook)", smp_int_get(&simple_message_cached->rc)); } #endif simple_message_cached->received_time_us = timeus(); s64 dt = MAX(simple_message_cached->received_time_us - simple_message_cached->sent_time_us, 0); double dts = dt; dts /= ONE_SECOND_US_F; #if DNS_UDP_TC_FALLBACK_TO_TCP_SUPPORT if(!truncated) { #endif simple_message_cached->answer = mesg; log_notice("receive: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) [%6.3fs] (hook)", message.fqdn, &message.qtype, &message.qclass, message.name_server, simple_message_cached->status, dts); dns_udp_simple_message_retain(simple_message_cached); dns_udp_simple_message_answer_call_handlers(simple_message_cached); simple_message_cached->answer = NULL; //dns_udp_simple_message_release(simple_message_cached); // allocate the next buffer, handle the hard_limit of the pool: // when the pool has reached peak capacity, allocation returns NULL #if DNS_UDP_TC_FALLBACK_TO_TCP_SUPPORT } else { // the message has been truncated // it should be queried again using TCP log_notice("receive: %{dnsname} %{dnstype} %{dnsclass} to %{hostaddr} (%x) [%6.3fs]: truncated (hook)", message.fqdn, &message.qtype, &message.qclass, message.name_server, simple_message_cached->status, dts); // TCP ??? } #endif } else { mutex_unlock(&message_collection_mtx); // unknown log_warn("receive: unexpected message %{dnsname} %{dnstype} %{dnsclass}", message.fqdn, &message.qtype, &message.qclass); } } else { log_err("receive: an error occurred while copying the name '%{dnsname}': %r", message_get_canonised_fqdn(mesg), len); } } else { // nop } return return_code; } /** * * Mark a simple message as being timed-out * Meant for use in hooks. * Use with care. * * @param simple_message */ void dns_udp_mark_as_timedout(dns_simple_message_s *simple_message) { simple_message->sent_time_us = timeus() - 10000000; // 10 seconds ago simple_message->received_time_us = MAX_S64; simple_message->status |= DNS_SIMPLE_MESSAGE_STATUS_TIMEDOUT; } int dns_udp_handler_init() { int err = SUCCESS; if(!dns_udp_handler_initialized) { if(dns_udp_settings->port_count == 0) { return INVALID_ARGUMENT_ERROR; // invalid value } error_register(DNS_UDP_TIMEOUT, "query timed out"); error_register(DNS_UDP_INTERNAL, "internal error"); message_edns0_setmaxsize(4096); limiter_init(&dns_udp_send_bandwidth, dns_udp_settings->send_bandwidth); // bytes-per-second limiter_init(&dns_udp_send_rate, dns_udp_settings->send_rate); // bytes-per-second limiter_init(&dns_udp_recv_bandwidth, dns_udp_settings->recv_bandwidth); // bytes-per-second //dns_udp_settings->port_count != 0 u32 worker_count = dns_udp_settings->port_count; MALLOC_OR_DIE(dns_udp_receive_ctx**, dns_udp_receive_context, sizeof (dns_udp_receive_ctx*) * worker_count, DNSURCTX_TAG); for(u32 i = 0; i < worker_count; i++) // dns_udp_socket_count is guaranteed > 0 { dns_udp_receive_context[i] = dns_udp_receive_ctx_init(dns_udp_settings->udp_read_buffer_count); } // open "worker_count" udp sockets (V6) dns_udp_socket_count = worker_count; MALLOC_OR_DIE(int*, dns_udp_socket, sizeof (int) * dns_udp_socket_count, SCKTARRY_TAG); // DON'T POOL for(u32 i = 0; i < dns_udp_socket_count; i++) // dns_udp_socket_count is guaranteed > 0 { int s; if((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { for(u32 j = 0; j < i; j++) { if(dns_udp_socket[j] != ~0) { log_debug1("dns_udp_handler_init: closing socket %i", dns_udp_socket[j]); close_ex(dns_udp_socket[j]); dns_udp_socket[j] = ~0; } } return ERRNO_ERROR; } // dns_udp_socket[i] = s; struct sockaddr_in6 sin6; ZEROMEMORY(&sin6, sizeof (sin6)); sin6.sin6_family = AF_INET6; socklen_t sin6len = sizeof (sin6); if(bind(s, (struct sockaddr*) &sin6, sin6len) < 0) { err = ERRNO_ERROR; log_err("bind: %r", err); for(u32 j = 0; j < i; j++) { if(dns_udp_socket[j] != ~0) { log_debug1("dns_udp_handler_init: closing socket %i", dns_udp_socket[j]); close_ex(dns_udp_socket[j]); dns_udp_socket[j] = ~0; } } free(dns_udp_socket); dns_udp_socket = NULL; dns_udp_socket_count = 0; return err; } struct sockaddr_storage assigned_address; socklen_t assigned_address_len = sizeof (assigned_address); if(getsockname(s, (struct sockaddr*) &assigned_address, &assigned_address_len) == 0) { log_info("dns udp: socket[%i]=%i is bound to %{sockaddr}", i, s, &assigned_address); } else { log_warn("dns udp: socket[%i]=%i bound address cannot be found: %r", i, s, ERRNO_ERROR); } } // scan-build false positive: dns_udp_socket_count > 0 assert(dns_udp_socket_count > 0); MALLOC_OR_DIE(list_dl_s*, dns_udp_high_priority, sizeof (list_dl_s) * dns_udp_socket_count, LISTDL_TAG); // DON'T POOL, count ALWAYS > 0 for(u32 i = 0; i < dns_udp_socket_count; i++) { list_dl_init(&dns_udp_high_priority[i]); } // each couple of socket will be the responsibility of a writer if(ISOK(err = service_init_ex(&dns_udp_send_handler, dns_udp_send_service, "qs", worker_count))) { async_queue_init(&dns_udp_send_handler_queue, dns_udp_settings->queue_size, 1, 100000, "dns-udp-send"); if(ISOK(err = service_init_ex(&dns_udp_receive_read_handler, dns_udp_receive_read_service, "qrrs", worker_count))) { if(ISOK(err = service_init_ex(&dns_udp_receive_process_handler, dns_udp_receive_process_service, "qrps", worker_count))) { if(ISOK(err = service_init(&dns_udp_timeout_handler, dns_udp_timeout_service, "qts"))) { #if DNS_UDP_TC_FALLBACK_TO_TCP_SUPPORT if((tcp_query_thread_pool = thread_pool_init_ex(dns_udp_settings->tcp_thread_pool_size, 0x4000, "dnstcpqr")) != NULL) { #endif pool_init(&dns_simple_message_async_node_pool, dns_simple_message_async_node_pool_alloc, dns_simple_message_async_node_pool_free, NULL, "dns simple message answer"); pool_init(&dns_simple_message_pool, dns_simple_message_pool_alloc, dns_simple_message_pool_free, NULL, "dns simple message"); pool_init(&message_data_pool, message_data_pool_alloc, message_data_pool_free, NULL, "message data"); #ifndef VALGRIND_FRIENDLY pool_set_size(&dns_simple_message_async_node_pool, 0x10000); pool_set_size(&dns_simple_message_pool, 0x10000); pool_set_size(&message_data_pool, 0x2000); message_data_pool.hard_limit = TRUE; #else // for valgrind pool_set_size(&dns_simple_message_async_node_pool, 0); pool_set_size(&dns_simple_message_pool, 0); pool_set_size(&message_data_pool, 0); #endif dns_udp_callback_tp = thread_pool_init_ex(dns_udp_settings->callback_thread_count, dns_udp_settings->callback_queue_size, "udp-cb"); if(dns_udp_callback_tp != NULL) { dns_udp_handler_initialized = TRUE; return SUCCESS; } pool_finalize(&message_data_pool); pool_finalize(&dns_simple_message_pool); pool_finalize(&dns_simple_message_async_node_pool); #if DNS_UDP_TC_FALLBACK_TO_TCP_SUPPORT thread_pool_destroy(tcp_query_thread_pool); tcp_query_thread_pool = NULL; } service_finalize(&dns_udp_timeout_handler); err = THREAD_CREATION_ERROR; #endif } service_finalize(&dns_udp_receive_process_handler); } service_finalize(&dns_udp_receive_read_handler); } service_finalize(&dns_udp_send_handler); } for(u32 i = 0; i < dns_udp_socket_count; i++) { if(dns_udp_socket[i] != ~0) { log_debug1("dns_udp_handler_init: closing socket %i", dns_udp_socket[i]); close_ex(dns_udp_socket[i]); dns_udp_socket[i] = ~0; } //list_dl_s *list = &dns_udp_high_priority[i]; } free(dns_udp_high_priority); dns_udp_high_priority = NULL; free(dns_udp_socket); // One array, don't pool dns_udp_socket = NULL; dns_udp_socket_count = 0; } return err; } int dns_udp_handler_finalize() { if(!dns_udp_handler_initialized) { return SUCCESS; } dns_udp_handler_stop(); if(dns_udp_callback_tp != NULL) { thread_pool_destroy(dns_udp_callback_tp); dns_udp_callback_tp = NULL; } service_finalize(&dns_udp_send_handler); service_finalize(&dns_udp_receive_read_handler); service_finalize(&dns_udp_receive_process_handler); service_finalize(&dns_udp_timeout_handler); if(dns_udp_socket != NULL) { for(u32 i = 0; i < dns_udp_socket_count; i++) { if(dns_udp_socket[i] != ~0) { log_debug1("dns_udp_handler_finalize: closing socket %i", dns_udp_socket[i]); if(shutdown(dns_udp_socket[i], SHUT_RDWR) < 0) { log_debug1("dns_udp_handler_finalize: unable to shutdown socket %i: %r", dns_udp_socket[i], ERRNO_ERROR); } close_ex(dns_udp_socket[i]); dns_udp_socket[i] = ~0; } } free(dns_udp_socket); // One array, don't pool dns_udp_socket = NULL; } if(dns_udp_receive_context != NULL) { for(u32 i = 0; i < dns_udp_socket_count; i++) // dns_udp_socket_count is guaranteed > 0 { dns_udp_receive_ctx_destroy(dns_udp_receive_context[i]); } free(dns_udp_receive_context); dns_udp_receive_context = NULL; } if(dns_udp_high_priority != NULL) { free(dns_udp_high_priority); dns_udp_high_priority = NULL; } dns_udp_socket_count = 0; async_queue_finalize(&dns_udp_send_handler_queue); ptr_set_callback_and_destroy(&message_collection, dns_udp_handler_message_collection_free_node_callback); message_collection_keys = 0; message_collection_size = 0; pool_finalize(&dns_simple_message_async_node_pool); pool_finalize(&dns_simple_message_pool); pool_finalize(&message_data_pool); limiter_finalize(&dns_udp_send_bandwidth); dns_udp_handler_initialized = FALSE; return SUCCESS; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dns_resource_record.c0000644000000000000000000000013214505005532023525 xustar000000000000000030 mtime=1695812442.419981859 30 atime=1695812445.793030168 30 ctime=1695812494.538728304 yadifa-2.6.5-11201/lib/dnscore/src/dns_resource_record.c0000664000374500037450000002772114505005532023500 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore * @ingroup dnscore * @brief Wire resource record reader * * Wire resource record reader * * @{ */ #include "dnscore/dnscore-config.h" #include "dnscore/dnscore-config.h" #include #include #include #define RRRDATA_TAG 0x0041544144525252 void dns_resource_record_init(dns_resource_record *rr) { #if DEBUG memset(rr, 0xf1, sizeof(dns_resource_record)); #endif rr->rdata = NULL; rr->rdata_size = 0; rr->rdata_buffer_size = 0; } void dns_resource_record_clear(dns_resource_record *rr) { if(rr->rdata != NULL) { #if DEBUG memset(rr->rdata, 0xfe, rr->rdata_size); #endif yassert(rr->rdata_buffer_size > 0); free(rr->rdata); rr->rdata = NULL; rr->rdata_size = 0; rr->rdata_buffer_size = 0; } } ya_result dns_resource_record_set_fqdn(dns_resource_record *rr, const u8* fqdn) { u32 len = dnsname_len(fqdn); if(len <= sizeof(rr->name)) { memcpy(rr->name, fqdn, len); rr->name_len = len; return len; } else { return DOMAIN_TOO_LONG; } } ya_result dns_resource_record_set_record(dns_resource_record *rr, const u8* fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size, const u8 *rdata) { ya_result ret; if(ISOK(ret = dns_resource_record_set_fqdn(rr, fqdn))) { rr->tctr.qtype = rtype; rr->tctr.qclass = rclass; rr->tctr.rdlen = htons(rdata_size); rr->tctr.ttl = htonl(ttl); rr->rdata_size = rdata_size; if(rr->rdata_size > 0) { if(rr->rdata_buffer_size < rdata_size) { u8 *tmp; // do the computations into 32 bits words u32 rdata_size_32 = rr->rdata_size; u32 buffer_size_32 = MIN(((rdata_size_32 + 15) & ~15), 0xffff); #if DEBUG if(rr->rdata != NULL) { memset(rr->rdata, 0xfe, rr->rdata_buffer_size); } #endif rr->rdata_buffer_size = buffer_size_32; MALLOC_OR_DIE(u8*, tmp, rr->rdata_buffer_size, RRRDATA_TAG); free(rr->rdata); rr->rdata = tmp; } memcpy(rr->rdata, rdata, rdata_size); // rdata_size != 0 => rdata != 0 && rr->rdata != NULL ; also: VS false positive (nonsense) } } return ret; } ya_result dns_resource_record_init_record(dns_resource_record *rr, const u8* fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size, const u8 *rdata) { yassert((rdata != NULL) && (rdata_size > 0)); ya_result ret; dns_resource_record_init(rr); ret = dns_resource_record_set_record(rr, fqdn, rtype, rclass, ttl, rdata_size, rdata); return ret; } ya_result dns_resource_init_from_record(dns_resource_record *rr, const dns_resource_record *src) { yassert((src != NULL) && (src->rdata != NULL) && (src->rdata_size > 0)); ya_result ret; ret = dns_resource_record_init_record(rr, src->name, src->tctr.qtype, src->tctr.qclass, ntohl(src->tctr.ttl), src->rdata_size, src->rdata); return ret; } ya_result dns_resource_set_from_record(dns_resource_record *rr, const dns_resource_record *src) { ya_result ret; ret = dns_resource_record_set_record(rr, src->name, src->tctr.qtype, src->tctr.qclass, ntohl(src->tctr.ttl), src->rdata_size, src->rdata); return ret; } /** * * This utility function reads an uncompressed record from a stream. * Compression has to be handled by the underlying input_stream * If an error code is returned, then most likely the stream is broken. * * @param is * @param rr * * @return an error code or the number of bytes read */ ya_result dns_resource_record_read(dns_resource_record *rr, input_stream *is) { ya_result ret; if(FAIL(ret = input_stream_read_dnsname(is, &rr->name[0]))) { return ret; } if(ret == 0) { return 0; } rr->name_len = ret; if(FAIL(ret = input_stream_read_fully(is, &rr->tctr, 10))) /* cannot use sizeof(tctr) */ { return ret; } rr->rdata_size = htons(rr->tctr.rdlen); if(rr->rdata_buffer_size < rr->rdata_size) { u8 *tmp; // do the computations into 32 bits words u32 rdata_size = rr->rdata_size; u32 buffer_size = MIN((rdata_size + 255) & 0xff00, 0xffff); #if DEBUG memset(rr->rdata, 0xfe, rr->rdata_buffer_size); #endif rr->rdata_buffer_size = buffer_size; MALLOC_OR_DIE(u8*, tmp, rr->rdata_buffer_size, RRRDATA_TAG); free(rr->rdata); rr->rdata = tmp; } if(FAIL(ret = input_stream_read_fully(is, rr->rdata, rr->rdata_size))) { return ret; } #if DEBUG memset(&rr->rdata[rr->rdata_size], 0xee, rr->rdata_buffer_size - rr->rdata_size); #endif return rr->name_len + 10 + rr->rdata_size; /* total bytes read */ } /** * * This utility function writes an uncompressed record to a stream. * Compression has to be handled by the underlying output_stream * If an error code is returned, then most likely the stream is broken. * * @param os * @param rr * * @return an error code or the number of bytes written */ ya_result dns_resource_record_write(const dns_resource_record *rr, output_stream *os) { ya_result return_value; if(FAIL(return_value = output_stream_write(os, rr->name, rr->name_len))) { return return_value; } if(FAIL(return_value = output_stream_write(os, (u8*)&rr->tctr, 10))) { return return_value; } if(FAIL(return_value = output_stream_write(os, rr->rdata, rr->rdata_size))) { return return_value; } return rr->name_len + 10 + rr->rdata_size; /* total bytes read */ } bool dns_resource_record_equals(const dns_resource_record *a, const dns_resource_record *b) { if((a->rdata_size == b->rdata_size) && (a->name_len == b->name_len)) { if(memcmp(&a->tctr, &b->tctr, sizeof(a->tctr)) == 0) { if(dnsname_equals(a->name, b->name)) { if(memcmp(a->rdata, b->rdata, a->rdata_size) == 0) { return TRUE; } } } } return FALSE; } bool dns_resource_record_match(const dns_resource_record *a, const dns_resource_record *b) { if((a->rdata_size == b->rdata_size) && (a->name_len == b->name_len)) { if((a->tctr.qtype == b->tctr.qtype) && (a->tctr.qclass == b->tctr.qclass) && (a->tctr.rdlen == b->tctr.rdlen)) { if(dnsname_equals(a->name, b->name)) { if(memcmp(a->rdata, b->rdata, a->rdata_size) == 0) { return TRUE; } } } } return FALSE; } int dns_resource_record_compare(const dns_resource_record *a, const dns_resource_record *b) { int d; d = dnsname_compare(a->name, b->name); if(d == 0) { d = a->tctr.qclass; d -= b->tctr.qclass; if(d == 0) { d = a->tctr.qtype; d -= b->tctr.qtype; if(d == 0) { d = a->tctr.ttl; d -= b->tctr.ttl; if(d == 0) { d = a->rdata_size; d -= b->rdata_size; if(d == 0) { d = memcmp(a->rdata, b->rdata, a->rdata_size); } } } } } return d; } int ptr_set_dns_resource_record_node_compare(const void *node_a, const void *node_b) { if(node_a != NULL) { if(node_b != NULL) { return dns_resource_record_compare((const dns_resource_record*)node_a, (const dns_resource_record*)node_b); } else { return -1; } } else { return (node_b == NULL)?0:1; } } static const u8* dns_resource_record_view_get_fqdn(void *data, const void *rr_) { (void)data; const dns_resource_record* rr = (const dns_resource_record*)rr_; return rr->name; } static u16 dns_resource_record_view_get_type(void *data, const void *rr_) { (void)data; const dns_resource_record* rr = (const dns_resource_record*)rr_; return rr->tctr.qtype; } static u16 dns_resource_record_view_get_class(void *data, const void *rr_) { (void)data; const dns_resource_record* rr = (const dns_resource_record*)rr_; return rr->tctr.qclass; } static s32 dns_resource_record_view_get_ttl(void *data, const void *rr_) { (void)data; const dns_resource_record* rr = (const dns_resource_record*)rr_; return ntohl(rr->tctr.ttl); } static u16 dns_resource_record_view_get_rdata_size(void *data, const void *rr_) { (void)data; const dns_resource_record* rr = (const dns_resource_record*)rr_; return rr->rdata_size; } static const u8* dns_resource_record_view_get_rdata(void *data, const void *rr_) { (void)data; const dns_resource_record* rr = (const dns_resource_record*)rr_; return rr->rdata; } static void *dns_resource_record_view_new_instance(void *data, const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size, const u8 *rdata) { (void)data; dns_resource_record* rr; ZALLOC_OBJECT_OR_DIE(rr, dns_resource_record, DNSRREC_TAG); dns_resource_record_init_record(rr, fqdn, rtype, rclass, ttl, rdata_size, rdata); return rr; } static resource_record_view_vtbl dns_resource_record_view_vtbl = { dns_resource_record_view_get_fqdn, dns_resource_record_view_get_type, dns_resource_record_view_get_class, dns_resource_record_view_get_ttl, dns_resource_record_view_get_rdata_size, dns_resource_record_view_get_rdata, dns_resource_record_view_new_instance }; void dns_resource_record_resource_record_view_init(struct resource_record_view *rrv) { rrv->data = NULL; rrv->vtbl = &dns_resource_record_view_vtbl; } void dns_resource_record_resource_record_view_finalise(struct resource_record_view *rrv) { rrv->vtbl = NULL; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dnscore.c0000644000000000000000000000013214505005532021131 xustar000000000000000030 mtime=1695812442.387981401 30 atime=1695812445.792030153 30 ctime=1695812494.540728333 yadifa-2.6.5-11201/lib/dnscore/src/dnscore.c0000664000374500037450000007505614505005532021110 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore System core functions * @brief System core functions * * @{ */ #define __DNSCORE_C__ #include "dnscore/dnscore-config.h" #if HAS_PTHREAD_SETNAME_NP #if DEBUG #define _GNU_SOURCE 1 #endif #endif #include #include #include #include #include "dnscore/zalloc.h" #include "dnscore/message.h" #include "dnscore/file_output_stream.h" #include "dnscore/buffer_output_stream.h" #include "dnscore/mt_output_stream.h" #include "dnscore/format.h" #include "dnscore/dnsformat.h" #include "dnscore/logger.h" #include "dnscore/random.h" #include "dnscore/process.h" #include "dnscore/sys_error.h" #include "dnscore/thread.h" #include "dnscore/thread_pool.h" #include "dnscore/tsig.h" #include "dnscore/mutex.h" #include "dnscore/alarm.h" #include "dnscore/tcp_io_stream.h" #include "dnscore/config_settings.h" #include "dnscore/async.h" #include "dnscore/hash.h" #include "dnscore/socket-server.h" #include "dnscore/shared-heap.h" #if DNSCORE_HAS_TCP_MANAGER #include "dnscore/tcp_manager.h" #endif #include #if DNSCORE_HAS_TSIG_SUPPORT #include #include #include #include #endif #define TERM_BUFFER_SIZE 4096 #define DNSCORE_TIDY_UP_MEMORY 1 #define MODULE_MSG_HANDLE g_system_logger /*****************************************************************************/ #if DNSCORE_HAS_TSIG_SUPPORT #if !DNSCORE_HAS_ACL_SUPPORT #error "TSIG support is irrelevant without ACL support" #endif #endif #ifndef __DATE__ #define __DATE__ "date?" #endif #ifndef __TIME__ #define __TIME__ "time?" #endif #if HAS_BUILD_TIMESTAMP #if DEBUG const char *dnscore_lib = "dnscore " __DATE__ " " __TIME__ " debug"; #else const char *dnscore_lib = "dnscore " __DATE__ " " __TIME__ " release"; #endif #else #if DEBUG const char *dnscore_lib = "dnscore debug"; #else const char *dnscore_lib = "dnscore release"; #endif #endif void rfc_init(); void rfc_finalize(); void format_class_finalize(); #if __unix__ void chroot_unmanage_all(); #endif void signal_handler_finalize(); void dnskey_init(); void dnskey_finalize(); void xfr_input_stream_finalize(); /*********************************************************************** * These macros are silly or inefficient on purpose. Don't "fix" them. * ***********************************************************************/ static const char* ARCH_RECOMPILE_WARNING = "Please recompile with the correct settings."; static const char* ARCH_CHECK_SIZE_WARNING = "PANIC: %s does not match the size requirements (%i instead of %i).\n"; static const char* ARCH_CHECK_SIGN_WARNING = "PANIC: %s does not match the sign requirements.\n"; #define ARCH_CHECK_SIZE(a,b) if(a!=b) { printf(ARCH_CHECK_SIZE_WARNING,#a,a,b);puts(ARCH_RECOMPILE_WARNING);DIE(ERROR); } #define ARCH_CHECK_SIGNED(a) {a val=~0;if(val>0) { printf(ARCH_CHECK_SIGN_WARNING,#a);puts(ARCH_RECOMPILE_WARNING);DIE(ERROR); }} #define ARCH_CHECK_UNSIGNED(a) {a val=~0;if(val<0) { printf(ARCH_CHECK_SIGN_WARNING,#a);puts(ARCH_RECOMPILE_WARNING);DIE(ERROR); }} /***********************************************************************/ logger_handle *g_system_logger = LOGGER_HANDLE_SINK; static smp_int g_shutdown = SMP_INT_INITIALIZER; /** * Tests the architecture: * * Ensures that types sizes are exactly what they are expected to be. * Ensures that signed types are signed and unsigned types are unsigned. * Ensures that endianness is as expected. * Ensures that structure alignment is as expected. * * Will kill the program if an inconsistency is detected. */ typedef void (*function_pointer_t)(const u8 *fqdn); static void dnscore_arch_checkup() { /// @note 20170413 edf -- older compilers (gcc 4.6 and such) used to complain a lot about this /// # pragma message("Don't worry about the possible warnings below") ARCH_CHECK_SIZE(__SIZEOF_POINTER__, sizeof(void*)); ARCH_CHECK_SIZE(sizeof(u8), 1); ARCH_CHECK_SIZE(sizeof(s8), 1); ARCH_CHECK_SIZE(sizeof(u16), 2); ARCH_CHECK_SIZE(sizeof(s16), 2); ARCH_CHECK_SIZE(sizeof(u32), 4); ARCH_CHECK_SIZE(sizeof(s32), 4); ARCH_CHECK_SIZE(sizeof(u64), 8); ARCH_CHECK_SIZE(sizeof(s64), 8); ARCH_CHECK_SIZE(sizeof(intptr), sizeof(void*)); ARCH_CHECK_SIZE(sizeof(function_pointer_t), sizeof(void*)); // to safely ignore the function pointer/data pointer conversion ARCH_CHECK_SIGNED(s8); ARCH_CHECK_SIGNED(s16); ARCH_CHECK_SIGNED(s32); ARCH_CHECK_SIGNED(s64); ARCH_CHECK_UNSIGNED(u8); ARCH_CHECK_UNSIGNED(u16); ARCH_CHECK_UNSIGNED(u32); ARCH_CHECK_UNSIGNED(u64); ARCH_CHECK_UNSIGNED(intptr); #if !MESSAGE_PAYLOAD_IS_POINTER message_data* msg = NULL; intptr msg_diffs = (intptr)(msg->_buffer - msg->_buffer_tcp_len); // cppcheck : false positive: of course it's a null pointer if(msg_diffs != 2) { printf("Structure aligment is wrong. Expected 2 but got %i. (see message_data)\n", (int)msg_diffs); DIE(ERROR); } #endif # pragma message("You can resume worrying about warnings ...") #if WORDS_BIGENDIAN == 1 static const u8 endian[4] = {1, 2, 3, 4}; /* BIG */ static const char* endian_name = "BIG"; #else static const u8 endian[4] = {4, 3, 2, 1}; /* LITTLE */ static const char* endian_name = "LITTLE"; #endif u32 endian_match = GET_U32_AT(endian[0]); if(endian_match != 0x01020304) { fprintf(stderr, "Endianness is wrong. Compiled for %s\n", endian_name); puts(ARCH_RECOMPILE_WARNING); fflush(NULL); DIE(ERROR); } } struct dnscore_ipc_prefix_t { char zero; char pid[8]; char uid[8]; char gid[8]; char timestamp[16]; char rnd[7]; }; #if __unix__ static struct dnscore_ipc_prefix_t dnscore_ipc_prefix; static void dnscore_init_ipc_prefix() { int pid = getpid(); int uid = getpid(); int gid = getgid(); u64 timestamp = timeus(); snformat(dnscore_ipc_prefix.pid, sizeof(dnscore_ipc_prefix) - 1, "%08x%08x%08x%016x", pid, uid, gid, timestamp); dnscore_ipc_prefix.zero = '\0'; random_ctx rnd = thread_pool_get_random_ctx(); for(size_t i = 0; i < sizeof(dnscore_ipc_prefix.rnd); ++i) { char c = random_next(rnd)&0x7f7f7f7f; c %= 62; if(c < 10) { c += '0' - 0; } else if(c < 36) { c += 'A' - 10; } else // if(c < 62) { c += 'a' - 36; } dnscore_ipc_prefix.rnd[i] = c; } } static size_t dnscore_ipc_prefix_copy(char *out_buffer, size_t out_buffer_size) { if(out_buffer != NULL) { if(out_buffer_size >= sizeof(struct dnscore_ipc_prefix_t)) { memcpy(out_buffer, &dnscore_ipc_prefix, sizeof(struct dnscore_ipc_prefix_t)); } else { return 0; } } return sizeof(struct dnscore_ipc_prefix_t); } size_t dnscore_ipc_make_name(const char *suffix, char *out_buffer, size_t out_buffer_size) { size_t offset = dnscore_ipc_prefix_copy(out_buffer, out_buffer_size); if(offset > 0) { size_t suffix_len = strlen(suffix) + 1; if(out_buffer != NULL) { if(offset + suffix_len <= out_buffer_size) { memcpy(&out_buffer[offset], suffix, suffix_len); } else { return 0; } } return offset + suffix_len; } return 0; } #endif /*****************************************************************************/ dnscore_fingerprint dnscore_getfingerprint() { dnscore_fingerprint ret = dnscore_getmyfingerprint(); return ret; } u32 dnscore_fingerprint_mask() { return DNSCORE_TSIG; } /*****************************************************************************/ static dnscore_meminfo_t dnscore_meminfo = {0, 0, 0, 0, 0, 0}; const dnscore_meminfo_t* dnscore_meminfo_get(dnscore_meminfo_t *mi) { if(mi == NULL) { mi = &dnscore_meminfo; if(mi->page_size != 0) { return mi; } } s64 page_size = sysconf(_SC_PAGE_SIZE); s64 page_count = sysconf(_SC_PHYS_PAGES); s64 total_memory = page_size * page_count; struct rlimit limits; getrlimit(RLIMIT_RSS, &limits); s64 program_memory_limit = MIN(total_memory, (s64)limits.rlim_cur); mi->page_size = page_size; mi->page_count = page_count; mi->rss_current = limits.rlim_cur; mi->rss_max = limits.rlim_max; mi->program_memory_limit = program_memory_limit; return mi; } /*****************************************************************************/ output_stream __termout__ = {NULL, NULL}; output_stream __termerr__ = {NULL, NULL}; static void stdstream_init(bool bufferise) { output_stream tmp; output_stream tmp2; if(bufferise) { fd_output_stream_attach(&tmp, 1); buffer_output_stream_init(&tmp2, &tmp, TERM_BUFFER_SIZE); mt_output_stream_init(&__termout__, &tmp2); } else { fd_output_stream_attach(&__termout__, 1); } if(bufferise) { fd_output_stream_attach(&tmp, 2); buffer_output_stream_init(&tmp2, &tmp, TERM_BUFFER_SIZE); mt_output_stream_init(&__termerr__, &tmp2); } else { fd_output_stream_attach(&__termerr__, 2); } } static void stdstream_flush_both_terms() { output_stream_flush(&__termout__); output_stream_flush(&__termerr__); } /** * Detaches the fd at the bottom of the mt(buffer(file(fd))) stream ... if it can. * * @param os * @return 1 if an seemingly valid fd has been found and detached. 0 otherwise. */ ya_result stdstream_detach_fd(output_stream *os) { output_stream *wos = NULL; ya_result ret = 0; output_stream_flush(os); if(is_mt_output_stream(wos)) { output_stream filtered; wos = &filtered; mt_output_stream_detach_filtered(os, &filtered); if(is_buffer_output_stream(&filtered)) { wos = buffer_output_stream_get_filtered(wos); if(is_fd_output_stream(wos)) { fd_output_stream_detach(wos); ret = 1; } } else if(is_fd_output_stream(&filtered)) { fd_output_stream_detach(&filtered); ret = 1; } else { // no clues } } else { if(is_buffer_output_stream(os)) { wos = buffer_output_stream_get_filtered(wos); if(is_fd_output_stream(wos)) { fd_output_stream_detach(wos); ret = 1; } } else if(is_fd_output_stream(os)) { fd_output_stream_detach(os); ret = 1; } else { // no clues } } return ret; } ya_result stdstream_detach_fd_and_close_filtered(output_stream *os) { output_stream *wos = NULL; ya_result ret = 0; output_stream_flush(os); if(is_mt_output_stream(wos)) { output_stream filtered; wos = &filtered; mt_output_stream_detach_filtered(os, &filtered); if(is_buffer_output_stream(&filtered)) { wos = buffer_output_stream_get_filtered(wos); if(is_fd_output_stream(wos)) { fd_output_stream_detach(wos); ret = 1; } } else if(is_fd_output_stream(&filtered)) { fd_output_stream_detach(&filtered); ret = 1; } else { // no clues } // closes the whole output_stream stack but not the file descriptor at the bottom output_stream_close(&filtered); ret |= 2; } else { if(is_buffer_output_stream(os)) { wos = buffer_output_stream_get_filtered(wos); if(is_fd_output_stream(wos)) { fd_output_stream_detach(wos); ret = 1; } } else if(is_fd_output_stream(os)) { fd_output_stream_detach(os); ret = 1; } else { // no clues } } return ret; } void stdstream_detach_fds_and_close() { stdstream_detach_fd_and_close_filtered(&__termout__); stdstream_detach_fd_and_close_filtered(&__termerr__); } void stdstream_detach_fds() { stdstream_detach_fd(&__termout__); stdstream_detach_fd(&__termerr__); } bool stdstream_is_tty(output_stream *os) { if(is_mt_output_stream(os)) { os = mt_output_stream_get_filtered(os); } if(is_buffer_output_stream(os)) { os = buffer_output_stream_get_filtered(os); } bool ret = is_fd_output_stream(os); return ret; } //static smp_int dnscore_time_thread_must_run = SMP_INT_INITIALIZER; static async_wait_s* timer_thread_sync = NULL; static thread_t dnscore_timer_thread_id = 0; static volatile int dnscore_timer_creator_pid = 0; static int dnscore_timer_period = 5; static volatile u32 dnscore_timer_tick = 0; static mutex_t dnscore_timer_mtx = MUTEX_INITIALIZER; static noreturn void* dnscore_timer_thread(void * unused0) { (void)unused0; thread_pool_setup_random_ctx(); mutex_lock(&dnscore_timer_mtx); dnscore_timer_tick = time(NULL); mutex_unlock(&dnscore_timer_mtx); thread_set_name("timer", 0, 0); #if DNSCORE_HAS_LOG_THREAD_TAG static char dnscore_timer_thread_tag[9] = "timer"; logger_handle_set_thread_tag(dnscore_timer_thread_tag); #endif log_debug5("dnscore_timer_thread started"); // if the counter reaches 0 then we have to stop u64 loop_period = dnscore_timer_period; loop_period *= ONE_SECOND_US; u64 loop_next_timeout_epoch = timeus(); // every timeout (1s) loops as the async_ call returned FALSE. while(!async_wait_timeout_absolute(timer_thread_sync, loop_next_timeout_epoch)) { /* log & term output flush handling */ stdstream_flush_both_terms(); logger_flush(); mutex_lock(&dnscore_timer_mtx); dnscore_timer_tick = time(NULL); u32 local_dnscore_timer_tick = dnscore_timer_tick; mutex_unlock(&dnscore_timer_mtx); if(!dnscore_shuttingdown()) { alarm_run_tick(local_dnscore_timer_tick); } else { loop_period = 1000000LL; } loop_next_timeout_epoch += loop_period; } log_debug5("dnscore_timer_thread stopping"); thread_pool_destroy_random_ctx(); log_debug5("dnscore_timer_thread stopped"); #if DNSCORE_HAS_LOG_THREAD_TAG logger_handle_clear_thread_tag(); #endif thread_exit(NULL); /* not from the pool, so it's the way */ // unreachable // return NULL; #ifndef _STDNORETURN_H return NULL; // just so the compiler shuts-up #endif } void dnscore_reset_timer() { assert(getpid_ex() == getpid()); int mypid = getpid_ex(); mutex_lock(&dnscore_timer_mtx); if(mypid != dnscore_timer_creator_pid) { dnscore_timer_tick = 0; dnscore_timer_creator_pid = mypid; mutex_unlock(&dnscore_timer_mtx); if(timer_thread_sync != NULL) { log_err("timer_thread_sync isn't NULL"); abort(); } timer_thread_sync = async_wait_new_instance(1); log_debug("starting timer"); if(thread_create(&dnscore_timer_thread_id, dnscore_timer_thread, NULL) != 0) { mutex_lock(&dnscore_timer_mtx); dnscore_timer_thread_id = 0; dnscore_timer_creator_pid = 0; mutex_unlock(&dnscore_timer_mtx); log_err("failed to create timer thread: %r", ERRNO_ERROR); exit(EXIT_CODE_THREADCREATE_ERROR); } } else { mutex_unlock(&dnscore_timer_mtx); } } u32 dnscore_timer_get_tick() { mutex_lock(&dnscore_timer_mtx); u32 ret = dnscore_timer_tick; mutex_unlock(&dnscore_timer_mtx); return ret; } static volatile u32 dnscore_features = 0; static volatile bool dnscore_arch_checked = FALSE; static volatile bool dnscore_tty_init = FALSE; static volatile bool dnscore_tty_set = FALSE; static volatile bool dnscore_random_set = FALSE; static volatile bool dnscore_atexit_registered = FALSE; void dnscore_init_ex(u32 features, int argc, char **argv) { if(!dnscore_arch_checked) { dnscore_arch_checkup(); dnscore_arch_checked = TRUE; const u32 wild_label_hash = hash_dnslabel((const u8*)"\001*"); if(wild_label_hash != WILD_LABEL_HASH) { puts(ARCH_RECOMPILE_WARNING); DIE(ERROR); } } dnscore_meminfo_get(NULL); g_pid = getpid(); #if DEBUG debug_bench_init(); debug_malloc_hooks_init(); #endif /* Init the hash tables */ hash_init(); if(!dnscore_tty_init) { output_stream_set_sink(&__termout__); output_stream_set_sink(&__termerr__); dnscore_tty_init = TRUE; } #if DNSCORE_HAS_ZALLOC_SUPPORT if((features & DNSCORE_ZALLOC) && !(dnscore_features & DNSCORE_ZALLOC)) { zalloc_init(); dnscore_features |= DNSCORE_ZALLOC; } #endif if(((features & DNSCORE_TTY_BUFFERED) && !(dnscore_features & DNSCORE_TTY_BUFFERED)) || !dnscore_tty_set) { if(dnscore_tty_set) { stdstream_detach_fds_and_close(); dnscore_tty_set = FALSE; } if(features & DNSCORE_TTY_BUFFERED) { features |= DNSCORE_TIMER_THREAD; } stdstream_init(features & DNSCORE_TTY_BUFFERED); dnscore_features |= DNSCORE_TTY_BUFFERED; dnscore_tty_set = TRUE; } #if MUTEX_CONTENTION_MONITOR //mutex_contention_monitor_start(); #endif if(!dnscore_random_set) { thread_pool_setup_random_ctx(); random_ctx rnd = thread_pool_get_random_ctx(); // random NEEDS to work. for(int impossible_collisions_countdown = 16; impossible_collisions_countdown >= 0; --impossible_collisions_countdown) { u32 r0 = random_next(rnd); u32 r1 = random_next(rnd); u32 r2 = random_next(rnd); u32 r3 = random_next(rnd); if( ((r0 == 0) && (r1 == 0) && (r2 == 0) && (r3 == 0)) || ((r0 == r1) && (r1 == r2) && (r2 == r3)) ) { // this IS possible, but has one chance in the order of 2^128 to happen if(impossible_collisions_countdown == 0) { printf("panic: random generation fails. (%08x,%08x,%08x,%08x)\n", r0, r1, r2, r3); exit(EXIT_FAILURE); } } else { break; } } dnscore_random_set = TRUE; #if __unix__ dnscore_init_ipc_prefix(); #endif } netformat_class_init(); if((features & DNSCORE_DNS) && !(dnscore_features & DNSCORE_DNS)) { rfc_init(); dnsformat_class_init(); dnscore_features |= DNSCORE_DNS; } #if 0 #if DEBUG osformatln(&__termerr__, "dnscore debug features list begin"); #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT osformatln(&__termerr__, "dnscore: DNSCORE_HAS_MALLOC_DEBUG_SUPPORT"); #endif #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT osformatln(&__termerr__, "dnscore: DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT"); #endif #if DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT osformatln(&__termerr__, "dnscore: DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT"); #endif #if DNSCORE_HAS_MMAP_DEBUG_SUPPORT osformatln(&__termerr__, "dnscore: DNSCORE_HAS_MMAP_DEBUG_SUPPORT"); #endif osformatln(&__termerr__, "dnscore debug features list end"); output_stream_flush(&__termerr__); #endif #endif if((features & DNSCORE_LOGGER) && !(dnscore_features & DNSCORE_LOGGER)) { features |= DNSCORE_TIMER_THREAD; logger_init(); dnscore_features |= DNSCORE_LOGGER; } if((features & DNSCORE_SHARED_HEAP) && !(dnscore_features & DNSCORE_SHARED_HEAP)) { shared_heap_init(); /* int ret = shared_heap_create(20); if(ret < 0) { osformatln(&__termerr__, "[%i] failed to allocate shared memory: %r", getpid(), ret); exit(1); } if(ret != 0) { osformatln(&__termerr__, "[%i] expected shared memory id to be 0, instead it is %i", getpid(), ret); exit(2); } */ dnscore_features |= DNSCORE_SHARED_HEAP; } #if DNSCORE_HAS_LOG_THREAD_TAG static char dnscore_main_thread_tag[9] = "main"; logger_handle_set_thread_tag(dnscore_main_thread_tag); #endif dnscore_register_errors(); if((features & DNSCORE_CRYPTO) && !(dnscore_features & DNSCORE_CRYPTO)) { #if DNSCORE_HAS_TSIG_SUPPORT ENGINE_load_openssl(); ENGINE_load_builtin_engines(); SSL_library_init(); SSL_load_error_strings(); tsig_register_algorithms(); #endif dnskey_init(); dnscore_features |= DNSCORE_CRYPTO; } /* if(features & DNSCORE_SHARED_HEAP) { shared_heap_init(); } */ if(!dnscore_atexit_registered) { atexit(dnscore_finalize); dnscore_atexit_registered = TRUE; } if((features & DNSCORE_ALARM) && !(dnscore_features & DNSCORE_ALARM)) { features |= DNSCORE_TIMER_THREAD; alarm_init(); dnscore_features |= DNSCORE_ALARM; } int timer_period = (features >> (32 - 6)) & 0x3f; if(timer_period == 0) { timer_period = 5; } dnscore_timer_period = timer_period; if((features & DNSCORE_TIMER_THREAD) && !(dnscore_features & DNSCORE_TIMER_THREAD)) { dnscore_reset_timer(); dnscore_features |= DNSCORE_TIMER_THREAD; } tcp_init_with_env(); if((features & DNSCORE_SOCKET_SERVER) && !(dnscore_features & DNSCORE_SOCKET_SERVER)) { if(FAIL(socket_server_init(argc, argv))) // yes, even before the core { puts("no server socket available ..."); fflush(NULL); exit(EXIT_FAILURE); } dnscore_features |= DNSCORE_SOCKET_SERVER; } #if DNSCORE_HAS_TCP_MANAGER if(features & DNSCORE_TCP_MANAGER) { dnscore_features |= DNSCORE_TCP_MANAGER; tcp_manager_init(); } #endif } void dnscore_init() { dnscore_init_ex(DNSCORE_MOST, 0, NULL); } u32 dnscore_get_active_features() { return dnscore_features; } void dnscore_stop_timer() { /* * Timer thread stop */ //yassert(getpid_ex() == getpid()); int mypid = getpid_ex(); if(mypid == dnscore_timer_creator_pid) { dnscore_timer_creator_pid = 0; if(dnscore_timer_thread_id != 0) { log_debug("stopping timer"); async_wait_progress(timer_thread_sync, 1); // pthread_kill(dnscore_timer_thread_id, SIGUSR1); thread_join(dnscore_timer_thread_id, NULL); dnscore_timer_thread_id = 0; async_wait_destroy(timer_thread_sync); timer_thread_sync = NULL; } } else { #if DEBUG if(dnscore_timer_creator_pid != 0) { log_debug("timer owned by %d, not touching it (I'm %d)", dnscore_timer_creator_pid, mypid); } else { log_debug("timer stopped already (I'm %d)", mypid); } #endif } logger_flush(); } void dnscore_wait_timer_stopped() { thread_t id = dnscore_timer_thread_id; if(id != 0) { thread_join(id, NULL); } } void dnscore_shutdown() { smp_int_set(&g_shutdown, 1); } bool dnscore_shuttingdown() { return smp_int_get(&g_shutdown) != 0; } static volatile bool dnscore_finalizing = FALSE; void log_assert__(bool b, const char *txt, const char *file, int line) { if(!b) { #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED if(logger_is_running() && (g_system_logger != NULL) && (g_system_logger != LOGGER_HANDLE_SINK)) { //logger_handle_exit_level(MAX_U32); log_crit("assert: at %s:%d: %s", file, line, txt); /* this is in yassert */ logger_flush(); } #endif osformatln(&__termerr__,"assert: [pid=%i, thread=%p] at %s:%d: %s", getpid(), thread_self(), file, line, txt); stdstream_flush_both_terms(); abort(); } } void dnscore_finalize(void) { /* * No need to "finalize" format, dnsformat and rfc */ if(dnscore_finalizing) { /* OOPS : ALREADY BUSY SHUTTING DOWN */ /* DO NOT USE LOGGER HERE ! */ return; } dnscore_finalizing = TRUE; dnscore_shutdown(); #if 0 // DEBUG debug_bench_logdump_all(); #endif #if DEBUG log_debug("exit: destroying the thread pool"); #endif logger_flush(); #if DEBUG log_debug("exit: bye (pid=%hd)", getpid()); logger_flush(); #endif #if DNSCORE_HAS_TCP_MANAGER #if DEBUG log_debug("exit: destroying the TCP manager"); logger_flush(); #endif tcp_manager_finalise(); #endif dnscore_stop_timer(); // timer uses logger dnscore_wait_timer_stopped(); if(dnscore_features & DNSCORE_ALARM) { alarm_finalize(); } config_finalize(); async_message_pool_finalize(); stdstream_flush_both_terms(); signal_handler_finalize(); xfr_input_stream_finalize(); logger_finalize(); /** @note does a logger_stop */ config_set_log_base_path(NULL); #if DEBUG || defined(DNSCORE_TIDY_UP_MEMORY) /* * It may not be required right now, but in case the stdstream are filtered/buffered * this will flush them. */ thread_pool_destroy_random_ctx(); stdstream_flush_both_terms(); #if DNSCORE_HAS_TSIG_SUPPORT tsig_finalize(); #if SSL_API_LT_110 CONF_modules_free(); #endif ENGINE_cleanup(); #if SSL_API_LT_110 CONF_modules_unload(1); #endif ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); //sk_free(SSL_COMP_get_compression_methods()); #endif #if __unix__ chroot_unmanage_all(); #endif error_unregister_all(); rfc_finalize(); format_class_finalize(); stdstream_flush_both_terms(); dnskey_finalize(); #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT||DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT||DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT||DNSCORE_HAS_MMAP_DEBUG_SUPPORT debug_stat(DEBUG_STAT_SIZES|DEBUG_STAT_TAGS|DEBUG_STAT_DUMP|DEBUG_STAT_WALK|DEBUG_STAT_MMAP); zalloc_print_stats(&__termout__); stdstream_flush_both_terms(); #endif #endif // DNSCORE_TIDY_UP_MEMORY if(__termerr__.vtbl != NULL) { output_stream_close(&__termerr__); } if(__termout__.vtbl != NULL) { output_stream_close(&__termout__); } debug_bench_unregister_all(); debug_stacktrace_clear(); debug_malloc_hooks_finalize(); #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_stop(); #endif #if DEBUG FILE* dnscore_finalize_file = fopen("/tmp/dnscore_finalize_file.txt", "a+"); if(dnscore_finalize_file != NULL) { fprintf(dnscore_finalize_file, "dnscore_finalize() of pid %i properly terminated\n", getpid()); fclose(dnscore_finalize_file); } #endif } static void dnscore_signature_check_one(const char* name, int should, int is) { if(is != should) { printf("critical: dnscore: '%s' should be of size %i but is of size %i\n", name, is, should); fflush(stdout); abort(); } } void dnscore_signature_check(int so_mutex_t, int so_group_mutex_t) { dnscore_signature_check_one("mutex_t", sizeof(mutex_t), so_mutex_t); dnscore_signature_check_one("group_mutex_t", sizeof(group_mutex_t), so_group_mutex_t); } /** * Helper function, used for tracking generic error codes. */ bool dnscore_monitored_isok(ya_result ret) { if(ret == -1 /* ERROR */) { log_warn("error-code-monitor: a function returned the generic ERROR code"); debug_log_stacktrace(g_system_logger, MSG_WARNING, "error-code-monitor: "); } return ((((u32)(ret)) & ((u32)ERRNO_ERROR_BASE)) == 0); } /** * Helper function, used for tracking generic error codes. */ bool dnscore_monitored_fail(ya_result ret) { if(ret == -1 /* ERROR */) { log_warn("error-code-monitor: a function returned the generic ERROR code"); debug_log_stacktrace(g_system_logger, MSG_WARNING, "error-code-monitor: "); } return ((((u32)(ret)) & ((u32)ERRNO_ERROR_BASE)) != 0); } void dnscore_hookme() { puts("BREAKPOINT HOLDER"); } #ifdef LIBRESSL_VERSION_NUMBER void ENGINE_load_openssl(void) {} void ENGINE_cleanup(void) {} int SSL_library_init(void) {return 1;} void SSL_load_error_strings(void) {} void ERR_free_strings(void) {} void EVP_cleanup(void) {} void CRYPTO_cleanup_all_ex_data(void) {} #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dnsformat.c0000644000000000000000000000013214505005532021471 xustar000000000000000030 mtime=1695812442.436982102 30 atime=1695812445.794030182 30 ctime=1695812494.543728376 yadifa-2.6.5-11201/lib/dnscore/src/dnsformat.c0000664000374500037450000011321114505005532021432 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup format C-string formatting * @ingroup dnscore * @brief * * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include /* Required for BSD */ #include #include #include #include "dnscore/rfc.h" #include "dnscore/ctrl-rfc.h" #include "dnscore/format.h" #include "dnscore/base32hex.h" #include "dnscore/dnsformat.h" #include "dnscore/host_address.h" #include "dnscore/dns_resource_record.h" #define NULL_STRING_SUBSTITUTE (u8*)"(NULL)" #define NULL_STRING_SUBSTITUTE_LEN 6 /*(sizeof(NULL_STRING_SUBSTITUTE)-1)*/ #define INVALID_LABEL_LENGTH "INVALID_LABEL_LENGTH" #define INVALID_LABEL_LENGTH_LEN (sizeof(INVALID_LABEL_LENGTH) - 1) #define PORT_SEPARATOR '#' #define PORT_SEPARATOR_V4 PORT_SEPARATOR #define PORT_SEPARATOR_V6 PORT_SEPARATOR #define TMP00002_TAG 0x3230303030504d54 /** digest32h * * @note The digest format is 1 byte of length, n bytes of digest data. */ static void digest32h_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)reserved_for_method_parameters; u8 *digest = (u8 *)val; if(digest != NULL) { output_stream_write_base32hex(stream, &digest[1], *digest); } else { format_asciiz("NULL", stream, padding, pad_char, left_justified); } } static const format_handler_descriptor digest32h_format_handler_descriptor ={ "digest32h", 9, digest32h_format_handler_method }; /* dnsname */ void dnsname_format_handler_method(const void *val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; const u8 dot = (u8)'.'; u8 *label = (u8*)val; if(label != NULL) { u8 label_len; FORMAT_BREAK_ON_INVALID(label, 1); label_len = *label; if(label_len > 0) { do { if(label_len > 63) { output_stream_write(stream, INVALID_LABEL_LENGTH, INVALID_LABEL_LENGTH_LEN); break; } FORMAT_BREAK_ON_INVALID(&label[1], label_len); output_stream_write(stream, ++label, label_len); output_stream_write(stream, &dot, 1); label += label_len; FORMAT_BREAK_ON_INVALID(label, 1); label_len = *label; } while(label_len > 0); } else { output_stream_write(stream, &dot, 1); } } else { output_stream_write(stream, NULL_STRING_SUBSTITUTE, NULL_STRING_SUBSTITUTE_LEN); } } static const format_handler_descriptor dnsname_format_handler_descriptor ={ "dnsname", 7, dnsname_format_handler_method }; /* */ static void dnsnamevector_format_handler_method(const void *val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u8 dot = '.'; dnsname_vector* namevector = (dnsname_vector *)val; if(namevector != NULL) { FORMAT_BREAK_ON_INVALID(namevector, sizeof(dnsname_vector)); s32 top = namevector->size; if(top >= 0) { s32 idx; for(idx = 0; idx <= top; idx++) { const u8 *label = namevector->labels[idx]; FORMAT_BREAK_ON_INVALID(label, 1); u8 label_len = *label++; FORMAT_BREAK_ON_INVALID(label, label_len); output_stream_write(stream, label, label_len); output_stream_write(stream, &dot, 1); } } else { output_stream_write(stream, &dot, 1); } } else { output_stream_write(stream, NULL_STRING_SUBSTITUTE, NULL_STRING_SUBSTITUTE_LEN); } } static const format_handler_descriptor dnsnamevector_format_handler_descriptor = { "dnsnamevector", 13, dnsnamevector_format_handler_method }; /* dnsnamestack */ static void dnsnamestack_format_handler_method(const void *val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u8 dot = '.'; dnsname_stack *namestack = (dnsname_stack *)val; if(namestack != NULL) { s32 top = namestack->size; if(top >= 0) { do { const u8 *label = namestack->labels[top]; u8 label_len = *label++; output_stream_write(stream, label, label_len); output_stream_write(stream, &dot, 1); } while(--top >= 0); } else { output_stream_write(stream, &dot, 1); } } else { output_stream_write(stream, NULL_STRING_SUBSTITUTE, NULL_STRING_SUBSTITUTE_LEN); } } static const format_handler_descriptor dnsnamestack_format_handler_descriptor = { "dnsnamestack", 12, dnsnamestack_format_handler_method }; /* dnslabel */ static void dnslabel_format_handler_method(const void *val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u8 *label = (u8 *)val; if(label != NULL) { u8 label_len = *label++; output_stream_write(stream, label, label_len); } else { output_stream_write(stream, NULL_STRING_SUBSTITUTE, NULL_STRING_SUBSTITUTE_LEN); } } static const format_handler_descriptor dnslabel_format_handler_descriptor = { "dnslabel", 8, dnslabel_format_handler_method }; /* class */ static void dnsclass_format_handler_method(const void *val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u16 *classp = (u16 *)val; if(classp != NULL) { const char *txt = NULL; s32 len = 0; switch(GET_U16_AT(*classp)) { case CLASS_IN: len = 2; txt = CLASS_IN_NAME; break; case CLASS_CH: len = 2; txt = CLASS_CH_NAME; break; case CLASS_HS: len = 2; txt = CLASS_HS_NAME; break; case CLASS_CTRL: len = 4; txt = CLASS_CTRL_NAME; break; #if HAS_WHOIS case CLASS_WHOIS: len = 5; txt = CLASS_WHOIS_NAME; break; #endif // HAS_WHOIS case CLASS_NONE: len = 4; txt = CLASS_NONE_NAME; break; case CLASS_ANY: len = 3; txt = CLASS_ANY_NAME; break; default: output_stream_write(stream, (u8 *)"CLASS", 5); /* rfc 3597 */ format_dec_u64((u64) ntohs(*classp), stream, 0, ' ', TRUE); return; } output_stream_write(stream, (u8 *)txt, len); } else { output_stream_write(stream, NULL_STRING_SUBSTITUTE, NULL_STRING_SUBSTITUTE_LEN); } } static const format_handler_descriptor dnsclass_format_handler_descriptor ={ "dnsclass", 8, dnsclass_format_handler_method }; /* type */ static void dnstype_format_handler_method(const void *val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u16 *typep = (u16 *)val; if(typep != NULL) { const char *txt = NULL; s32 len = 0; switch(GET_U16_AT(*typep)) { case TYPE_A: len = 1; txt = TYPE_A_NAME; break; case TYPE_NS: len = 2; txt = TYPE_NS_NAME; break; case TYPE_MD: len = 2; txt = TYPE_MD_NAME; break; case TYPE_MF: len = 2; txt = TYPE_MF_NAME; break; case TYPE_CNAME: len = 5; txt = TYPE_CNAME_NAME; break; case TYPE_SOA: len = 3; txt = TYPE_SOA_NAME; break; case TYPE_MB: len = 2; txt = TYPE_MB_NAME; break; case TYPE_MG: len = 2; txt = TYPE_MG_NAME; break; case TYPE_MR: len = 2; txt = TYPE_MR_NAME; break; case TYPE_NULL: len = 4; txt = TYPE_NULL_NAME; break; case TYPE_WKS: len = 3; txt = TYPE_WKS_NAME; break; case TYPE_PTR: len = 3; txt = TYPE_PTR_NAME; break; case TYPE_HINFO: len = 5; txt = TYPE_HINFO_NAME; break; case TYPE_MINFO: len = 5; txt = TYPE_MINFO_NAME; break; case TYPE_MX: len = 2; txt = TYPE_MX_NAME; break; case TYPE_TXT: len = 3; txt = TYPE_TXT_NAME; break; case TYPE_RP: len = 2; txt = TYPE_RP_NAME; break; case TYPE_AFSDB: len = 5; txt = TYPE_AFSDB_NAME; break; case TYPE_X25: len = 3; txt = TYPE_X25_NAME; break; case TYPE_ISDN: len = 4; txt = TYPE_ISDN_NAME; break; case TYPE_RT: len = 2; txt = TYPE_RT_NAME; break; case TYPE_NSAP: len = 4; txt = TYPE_NSAP_NAME; break; case TYPE_NSAP_PTR: len = 8; txt = TYPE_NSAP_PTR_NAME; break; case TYPE_SIG: len = 3; txt = TYPE_SIG_NAME; break; case TYPE_KEY: len = 3; txt = TYPE_KEY_NAME; break; case TYPE_PX: len = 2; txt = TYPE_PX_NAME; break; case TYPE_GPOS: len = 4; txt = TYPE_GPOS_NAME; break; case TYPE_AAAA: len = 4; txt = TYPE_AAAA_NAME; break; case TYPE_LOC: len = 3; txt = TYPE_LOC_NAME; break; case TYPE_NXT: len = 3; txt = TYPE_NXT_NAME; break; case TYPE_EID: len = 3; txt = TYPE_EID_NAME; break; case TYPE_NIMLOC: len = 6; txt = TYPE_NIMLOC_NAME; break; case TYPE_SRV: len = 3; txt = TYPE_SRV_NAME; break; case TYPE_ATMA: len = 4; txt = TYPE_ATMA_NAME; break; case TYPE_NAPTR: len = 5; txt = TYPE_NAPTR_NAME; break; case TYPE_KX: len = 2; txt = TYPE_KX_NAME; break; case TYPE_CERT: len = 4; txt = TYPE_CERT_NAME; break; case TYPE_A6: len = 2; txt = TYPE_A6_NAME; break; case TYPE_DNAME: len = 5; txt = TYPE_DNAME_NAME; break; case TYPE_SINK: len = 4; txt = TYPE_SINK_NAME; break; case TYPE_OPT: len = 3; txt = TYPE_OPT_NAME; break; case TYPE_APL: len = 3; txt = TYPE_APL_NAME; break; case TYPE_DS: len = 2; txt = TYPE_DS_NAME; break; case TYPE_SSHFP: len = 5; txt = TYPE_SSHFP_NAME; break; case TYPE_IPSECKEY: len = 8; txt = TYPE_IPSECKEY_NAME; break; case TYPE_RRSIG: len = 5; txt = TYPE_RRSIG_NAME; break; case TYPE_NSEC: len = 4; txt = TYPE_NSEC_NAME; break; case TYPE_DNSKEY: len = 6; txt = TYPE_DNSKEY_NAME; break; case TYPE_DHCID: len = 5; txt = TYPE_DHCID_NAME; break; case TYPE_NSEC3: len = 5; txt = TYPE_NSEC3_NAME; break; case TYPE_NSEC3PARAM: len = 10; txt = TYPE_NSEC3PARAM_NAME; break; case TYPE_TLSA: len = 4; txt = TYPE_TLSA_NAME; break; case TYPE_HIP: len = 3; txt = TYPE_HIP_NAME; break; case TYPE_NINFO: len = 5; txt = TYPE_NINFO_NAME; break; case TYPE_RKEY: len = 4; txt = TYPE_RKEY_NAME; break; case TYPE_TALINK: len = 6; txt = TYPE_TALINK_NAME; break; case TYPE_CDS: len = 3; txt = TYPE_CDS_NAME; break; case TYPE_CDNSKEY: len = 7; txt = TYPE_CDNSKEY_NAME; break; case TYPE_OPENPGPKEY: len = 10; txt = TYPE_OPENPGPKEY_NAME; break; case TYPE_SPF: len = 3; txt = TYPE_SPF_NAME; break; case TYPE_UINFO: len = 5; txt = TYPE_UINFO_NAME; break; case TYPE_UID: len = 3; txt = TYPE_UID_NAME; break; case TYPE_GID: len = 3; txt = TYPE_GID_NAME; break; case TYPE_UNSPEC: len = 6; txt = TYPE_UNSPEC_NAME; break; case TYPE_NID: len = 3; txt = TYPE_NID_NAME; break; case TYPE_L32: len = 3; txt = TYPE_L32_NAME; break; case TYPE_L64: len = 3; txt = TYPE_L64_NAME; break; case TYPE_LP: len = 2; txt = TYPE_LP_NAME; break; case TYPE_EUI48: len = 5; txt = TYPE_EUI48_NAME; break; case TYPE_EUI64: len = 5; txt = TYPE_EUI64_NAME; break; case TYPE_TKEY: len = 4; txt = TYPE_TKEY_NAME; break; case TYPE_TSIG: len = 4; txt = TYPE_TSIG_NAME; break; case TYPE_IXFR: len = 4; txt = TYPE_IXFR_NAME; break; case TYPE_AXFR: len = 4; txt = TYPE_AXFR_NAME; break; case TYPE_MAILB: len = 5; txt = TYPE_MAILB_NAME; break; case TYPE_MAILA: len = 5; txt = TYPE_MAILA_NAME; break; case TYPE_ANY: len = 3; txt = TYPE_ANY_NAME; break; case TYPE_URI: len = 3; txt = TYPE_URI_NAME; break; case TYPE_CAA: len = 3; txt = TYPE_CAA_NAME; break; case TYPE_AVC: len = 3; txt = TYPE_AVC_NAME; break; case TYPE_TA: len = 2; txt = TYPE_TA_NAME; break; case TYPE_DLV: len = 3; txt = TYPE_DLV_NAME; break; #if HAS_CTRL case TYPE_CTRL_SRVCFGRELOAD: len = 9; txt = TYPE_CTRL_SRVCFGRELOAD_NAME; break; case TYPE_CTRL_SRVLOGREOPEN: len = 9; txt = TYPE_CTRL_SRVLOGREOPEN_NAME; break; case TYPE_CTRL_SRVLOGLEVEL: len = 8; txt = TYPE_CTRL_SRVLOGLEVEL_NAME; break; case TYPE_CTRL_SRVSHUTDOWN: len = 8; txt = TYPE_CTRL_SHUTDOWN_NAME; break; case TYPE_CTRL_SRVQUERYLOG: len = 8; txt = TYPE_CTRL_SRVQUERYLOG_NAME; break; case TYPE_CTRL_ZONECFGRELOAD: len = 13; txt = TYPE_CTRL_ZONECFGRELOAD_NAME; break; case TYPE_CTRL_ZONECFGRELOADALL: len = 16; txt = TYPE_CTRL_ZONECFGRELOADALL_NAME; break; case TYPE_CTRL_ZONEFREEZE: len = 6; txt = TYPE_CTRL_ZONEFREEZE_NAME; break; case TYPE_CTRL_ZONEUNFREEZE: len = 8; txt = TYPE_CTRL_ZONEUNFREEZE_NAME; break; case TYPE_CTRL_ZONERELOAD: len = 6; txt = TYPE_CTRL_ZONERELOAD_NAME; break; case TYPE_CTRL_ZONEFREEZEALL: len = 9; txt = TYPE_CTRL_ZONEFREEZEALL_NAME; break; case TYPE_CTRL_ZONEUNFREEZEALL: len = 11; txt = TYPE_CTRL_ZONEUNFREEZEALL_NAME; break; case TYPE_CTRL_ZONESYNC: len = 4; txt = TYPE_CTRL_ZONESYNC_NAME; break; case TYPE_CTRL_ZONENOTIFY: len = 6; txt = TYPE_CTRL_ZONENOTIFY_NAME; break; #endif // 1 HAS_CTRL default: output_stream_write(stream, (u8 *)"TYPE", 4); /* rfc 3597 */ format_dec_u64((u64) ntohs(*typep), stream, 0, ' ', TRUE); return; } output_stream_write(stream, (u8 *)txt, len); } else { output_stream_write(stream, NULL_STRING_SUBSTITUTE, NULL_STRING_SUBSTITUTE_LEN); } } static const format_handler_descriptor dnstype_format_handler_descriptor ={ "dnstype", 7, dnstype_format_handler_method }; static void sockaddr_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *restrict reserved_for_method_parameters) { (void)reserved_for_method_parameters; char buffer[INET6_ADDRSTRLEN + 1 + 5 + 1]; char *src = buffer; struct sockaddr *sa = (struct sockaddr*)val; switch(sa->sa_family) { case AF_INET: { struct sockaddr_in *ipv4 = (struct sockaddr_in*)sa; if(inet_ntop(ipv4->sin_family, &ipv4->sin_addr, buffer, sizeof(buffer)) != NULL) { int n = strlen(buffer); buffer[n++] = PORT_SEPARATOR_V4; snprintf(&buffer[n],6, "%i", ntohs(ipv4->sin_port)); } else { src = strerror(errno); } break; } case AF_INET6: { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6*)sa; if(inet_ntop(ipv6->sin6_family, &ipv6->sin6_addr, buffer, sizeof(buffer)) != NULL) { int n = strlen(buffer); buffer[n++] = PORT_SEPARATOR_V6; snprintf(&buffer[n],6, "%i", ntohs(ipv6->sin6_port)); } else { src = strerror(errno); } break; } default: { snprintf(buffer, sizeof(buffer), "AF_#%i:?", sa->sa_family); break; } } format_asciiz(src, stream, padding, pad_char, left_justified); } static const format_handler_descriptor sockaddr_format_handler_descriptor ={ "sockaddr", 8, sockaddr_format_handler_method }; static void hostaddr_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *restrict reserved_for_method_parameters) { (void)reserved_for_method_parameters; char buffer[MAX_DOMAIN_LENGTH + 1 + 5 + 1]; char *src = buffer; if(val != NULL) { host_address *ha = (struct host_address*)val; switch(ha->version) { case HOST_ADDRESS_IPV4: { if(inet_ntop(AF_INET, ha->ip.v4.bytes, buffer, sizeof(buffer)) != NULL) { int n = strlen(buffer); buffer[n++] = PORT_SEPARATOR_V4; snprintf(&buffer[n],6, "%i", ntohs(ha->port)); } else { src = strerror(errno); } break; } case HOST_ADDRESS_IPV6: { if(inet_ntop(AF_INET6, ha->ip.v6.bytes, buffer, sizeof(buffer)) != NULL) { int n = strlen(buffer); buffer[n++] = PORT_SEPARATOR_V6; snprintf(&buffer[n],6, "%i", ntohs(ha->port)); } else { src = strerror(errno); } break; } case HOST_ADDRESS_DNAME: { buffer[0] = '\0'; dnsname_to_cstr(buffer, ha->ip.dname.dname); break; } default: { src = "INVALID"; break; } } } else { src = "NULL"; } format_asciiz(src, stream, padding, pad_char, left_justified); } static const format_handler_descriptor hostaddr_format_handler_descriptor ={ "hostaddr", 8, hostaddr_format_handler_method }; static void hostaddrip_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *restrict reserved_for_method_parameters) { (void)reserved_for_method_parameters; char buffer[MAX_DOMAIN_LENGTH + 1 + 5 + 1]; char *src = buffer; if(val != NULL) { host_address *ha = (struct host_address*)val; switch(ha->version) { case HOST_ADDRESS_IPV4: { if(inet_ntop(AF_INET, ha->ip.v4.bytes, buffer, sizeof(buffer)) != NULL) { } else { src = strerror(errno); } break; } case HOST_ADDRESS_IPV6: { if(inet_ntop(AF_INET6, ha->ip.v6.bytes, buffer, sizeof(buffer)) != NULL) { } else { src = strerror(errno); } break; } case HOST_ADDRESS_DNAME: { buffer[0] = '\0'; dnsname_to_cstr(buffer, ha->ip.dname.dname); break; } default: { src = "INVALID"; break; } } } else { src = "NULL"; } format_asciiz(src, stream, padding, pad_char, left_justified); } static const format_handler_descriptor hostaddrip_format_handler_descriptor ={ "hostaddrip", 10, hostaddrip_format_handler_method }; static void hostaddrlist_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *restrict reserved_for_method_parameters) { (void)reserved_for_method_parameters; char *src; char *p; char *limit; int len; bool allocated = FALSE; char buffer_tmp[1024]; src = buffer_tmp; p = buffer_tmp; len = sizeof(buffer_tmp); limit = &buffer_tmp[len]; if(val != NULL) { host_address *ha = (struct host_address*)val; for(;;) { switch(ha->version) { case HOST_ADDRESS_IPV4: { if(inet_ntop(AF_INET, ha->ip.v4.bytes, p, limit - p) != NULL) { p += strlen(p); if(ha->port != 0) { p += snprintf(p, 12, " port %i", ntohs(ha->port)); } } else { strcpy_ex(src, strerror(errno), limit - src); } break; } case HOST_ADDRESS_IPV6: { if(inet_ntop(AF_INET6, ha->ip.v6.bytes, p, limit - p) != NULL) { p += strlen(p); if(ha->port != 0) { p += snprintf(p, 12, " port %i", ntohs(ha->port)); } } else { strcpy_ex(src, strerror(errno), limit - src); } break; } case HOST_ADDRESS_DNAME: { *p = '\0'; p += dnsname_to_cstr(p, ha->ip.dname.dname); break; } default: { memcpy(p, "INVALID", 8); p += 8; break; } } ha = ha->next; if(ha == NULL) { break; } *p++ = ','; if(limit - p < MAX_DOMAIN_LENGTH + 12 + 1) { char *tmp; len <<= 1; MALLOC_OR_DIE(char*, tmp, len, TMP00002_TAG); memcpy(tmp, src, p - src); if(allocated) { free(src); } allocated = TRUE; p = &tmp[p - src]; // VS false positive: uninitialised yes, but only its address matters src = tmp; limit = &tmp[len]; } } } else { memcpy(src, "NULL", 5); } format_asciiz(src, stream, padding, pad_char, left_justified); if(allocated) { free(src); } } static const format_handler_descriptor hostaddrlist_format_handler_descriptor ={ "hostaddrlist", 12, hostaddrlist_format_handler_method }; static void sockaddrip_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)reserved_for_method_parameters; char buffer[INET6_ADDRSTRLEN + 1 + 5 + 1]; char *src = buffer; struct sockaddr *sa = (struct sockaddr*)val; switch(sa->sa_family) { case AF_INET: { struct sockaddr_in *ipv4 = (struct sockaddr_in*)sa; if(inet_ntop(ipv4->sin_family, &ipv4->sin_addr, buffer, sizeof(buffer)) != NULL) { } else { src = strerror(errno); } break; } case AF_INET6: { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6*)sa; if(inet_ntop(ipv6->sin6_family, &ipv6->sin6_addr, buffer, sizeof(buffer)) != NULL) { } else { src = strerror(errno); } break; } default: { snprintf(buffer, sizeof(buffer), "AF_#%i:?", sa->sa_family); break; } } format_asciiz(src, stream, padding, pad_char, left_justified); } static const format_handler_descriptor sockaddrip_format_handler_descriptor ={ "sockaddrip", /* only the IP */ 10, sockaddrip_format_handler_method }; static void rdatadesc_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; rdata_desc *desc = (rdata_desc *)val; if(desc->len > 0) { osprint_rdata(stream, desc->type, desc->rdata, desc->len); } } static const format_handler_descriptor rdatadesc_format_handler_descriptor ={ "rdatadesc", 9, rdatadesc_format_handler_method }; static void typerdatadesc_format_handler_method(const void * restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { rdata_desc *desc = (rdata_desc*)val; dnstype_format_handler_method(&desc->type, stream, padding, pad_char, left_justified, reserved_for_method_parameters); output_stream_write_u8(stream, (u8)pad_char); osprint_rdata(stream, desc->type, desc->rdata, desc->len); } static const format_handler_descriptor typerdatadesc_format_handler_descriptor = { "typerdatadesc", 13, typerdatadesc_format_handler_method }; static void recordwire_format_handler_method(const void * restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { u8 *domain = (u8 *)val; u32 domain_len = dnsname_len(domain); u16 *typeptr = (u16 *)&domain[domain_len]; u16 *classptr = (u16 *)&domain[domain_len + 2]; //u32 ttl = ntohl(GET_U32_AT(domain[domain_len + 4])); u16 rdata_len = ntohs(GET_U16_AT(domain[domain_len + 8])); u8 *rdata = &domain[domain_len + 10]; dnsname_format_handler_method(domain, stream, padding, pad_char, left_justified, reserved_for_method_parameters); output_stream_write_u8(stream, (u8)pad_char); dnsclass_format_handler_method(classptr, stream, padding, pad_char, left_justified, reserved_for_method_parameters); output_stream_write_u8(stream, (u8)pad_char); dnstype_format_handler_method(typeptr, stream, padding, pad_char, left_justified, reserved_for_method_parameters); output_stream_write_u8(stream, (u8)pad_char); osprint_rdata(stream, *typeptr, rdata, rdata_len); } static const format_handler_descriptor recordwire_format_handler_descriptor = { "recordwire", 10, recordwire_format_handler_method }; static void dnsrr_format_handler_method(const void * restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { dns_resource_record *rr = (dns_resource_record*)val; if(rr == NULL) { output_stream_write(stream,(const u8*)"*** NULL RESOURCE RECORD ***", 28); return; } dnsname_format_handler_method(rr->name, stream, padding, pad_char, left_justified, reserved_for_method_parameters); output_stream_write_u8(stream, (u8)pad_char); dnstype_format_handler_method(&rr->tctr.qtype, stream, padding, pad_char, left_justified, reserved_for_method_parameters); output_stream_write_u8(stream, (u8)pad_char); if(rr->rdata != NULL) { osprint_rdata(stream, rr->tctr.qtype, rr->rdata, rr->rdata_size); } else { output_stream_write(stream, (const u8*)"*** NULL RDATA ***", 18); } } static const format_handler_descriptor dnsrr_format_handler_descriptor = { "dnsrr", 5, dnsrr_format_handler_method }; static void dnszrr_format_handler_method(const void * restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { dns_resource_record *rr = (dns_resource_record*)val; if(rr == NULL) { output_stream_write(stream,(const u8*)"*** NULL RESOURCE RECORD ***", 28); return; } dnsname_format_handler_method(rr->name, stream, padding, pad_char, left_justified, reserved_for_method_parameters); output_stream_write_u8(stream, (u8)pad_char); format_dec_u64((u64)ntohl(rr->tctr.ttl), stream, 0, ' ', FALSE); output_stream_write_u8(stream, (u8)pad_char); dnstype_format_handler_method(&rr->tctr.qtype, stream, padding, pad_char, left_justified, reserved_for_method_parameters); output_stream_write_u8(stream, (u8)pad_char); if(rr->rdata != NULL) { osprint_rdata(stream, rr->tctr.qtype, rr->rdata, rr->rdata_size); } else { output_stream_write(stream, (const u8*)"*** NULL RDATA ***", 18); } } static const format_handler_descriptor dnszrr_format_handler_descriptor = { "dnszrr", 6, dnszrr_format_handler_method }; static bool netformat_class_init_done = FALSE; static bool dnsformat_class_init_done = FALSE; void netformat_class_init() { if(netformat_class_init_done) { return; } netformat_class_init_done = TRUE; format_class_init(); format_registerclass(&sockaddr_format_handler_descriptor); format_registerclass(&sockaddrip_format_handler_descriptor); format_registerclass(&hostaddr_format_handler_descriptor); format_registerclass(&hostaddrip_format_handler_descriptor); format_registerclass(&hostaddrlist_format_handler_descriptor); } void dnsformat_class_init() { if(dnsformat_class_init_done) { return; } dnsformat_class_init_done = TRUE; format_class_init(); format_registerclass(&dnsname_format_handler_descriptor); format_registerclass(&dnslabel_format_handler_descriptor); format_registerclass(&dnsclass_format_handler_descriptor); format_registerclass(&dnstype_format_handler_descriptor); format_registerclass(&dnsnamestack_format_handler_descriptor); format_registerclass(&dnsnamevector_format_handler_descriptor); format_registerclass(&digest32h_format_handler_descriptor); format_registerclass(&rdatadesc_format_handler_descriptor); format_registerclass(&typerdatadesc_format_handler_descriptor); format_registerclass(&recordwire_format_handler_descriptor); format_registerclass(&dnsrr_format_handler_descriptor); format_registerclass(&dnszrr_format_handler_descriptor); } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dnskey.c0000644000000000000000000000013214505005532020771 xustar000000000000000030 mtime=1695812442.421981887 30 atime=1695812445.793030168 30 ctime=1695812494.545728404 yadifa-2.6.5-11201/lib/dnscore/src/dnskey.c0000664000374500037450000021127014505005532020736 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @addtogroup dnskey DNSKEY functions * @brief * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #define DNSCORE_DNSKEY_C 1 #include #include #include #include #include "dnscore/openssl.h" #include "dnscore/dnsname.h" #include "dnscore/dnskey.h" #include "dnscore/dnskey_rsa.h" #include "dnscore/dnskey_dsa.h" #if DNSCORE_HAS_ECDSA_SUPPORT #include "dnscore/dnskey_ecdsa.h" #endif #if DNSCORE_HAS_EDDSA_SUPPORT #include "dnscore/dnskey_eddsa.h" #endif #ifdef DNSKEY_ALGORITHM_DUMMY #include "dnscore/dnskey_dummy.h" #endif #include "dnscore/digest.h" #include "dnscore/base64.h" #include "dnscore/string_set.h" #include "dnscore/file_input_stream.h" #include "dnscore/file_output_stream.h" #include "dnscore/buffer_output_stream.h" #include "dnscore/checked_output_stream.h" #include "dnscore/parser.h" #include "dnscore/zalloc.h" #include "dnscore/logger.h" #include "dnscore/fdtools.h" #include "dnscore/mutex.h" #include "dnscore/timeformat.h" extern logger_handle* g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define ZDB_DNSKEY_TAG 0x59454b534e44 #define ZDB_DNSKEY_NAME_TAG 0x454d414e59454b #define ORIGNDUP_TAG 0x5055444e4749524f #define DNSKRAWB_TAG 0x425741524b534e44 // dumps key acquisition/release #define DUMP_ACQUIRE_RELEASE_STACK_TRACE 0 static string_set dnssec_key_load_private_keywords_set = STRING_SET_EMPTY; #define DNSKEY_FIELD_ALGORITHM 1 #define DNSKEY_FIELD_FORMAT 2 #define DNSKEY_FIELD_CREATED 3 #define DNSKEY_FIELD_PUBLISH 4 #define DNSKEY_FIELD_ACTIVATE 5 #define DNSKEY_FIELD_INACTIVE 7 #define DNSKEY_FIELD_DELETE 8 #define DNSKEY_FIELD_ENGINE 9 static value_name_table dnssec_key_load_private_keywords_common_names[] = { {DNSKEY_FIELD_ALGORITHM, "Algorithm"}, {DNSKEY_FIELD_FORMAT, "Private-key-format"}, {DNSKEY_FIELD_CREATED, "Created"}, {DNSKEY_FIELD_PUBLISH, "Publish"}, {DNSKEY_FIELD_ACTIVATE, "Activate"}, {DNSKEY_FIELD_INACTIVE, "Inactive"}, {DNSKEY_FIELD_DELETE, "Delete"}, {DNSKEY_FIELD_ENGINE, "Engine"}, {0, NULL} }; static group_mutex_t dnskey_rc_mtx = GROUP_MUTEX_INITIALIZER; static const char *rsamd5_names[] = {DNSKEY_ALGORITHM_RSAMD5_NAME,"1", NULL}; static const char *dsasha1_names[] = {DNSKEY_ALGORITHM_DSASHA1_NAME,"3", NULL}; static const char *rsasha1_names[] = {DNSKEY_ALGORITHM_RSASHA1_NAME,"5", NULL}; static const char *dsasha1nsec3_names[] = {DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME,"6", NULL}; static const char *rsasha1nsec3_names[] = {DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME,"7", NULL}; static const char *rsasha256_names[] = {DNSKEY_ALGORITHM_RSASHA256_NSEC3_NAME,"8", NULL}; static const char *rsasha512_names[] = {DNSKEY_ALGORITHM_RSASHA512_NSEC3_NAME,"10", NULL}; #if DNSCORE_HAS_ECDSA_SUPPORT static const char *ecdsap256sha256_names[] = {DNSKEY_ALGORITHM_ECDSAP256SHA256_NAME,"13", NULL}; static const char *ecdsap384sha384_names[] = {DNSKEY_ALGORITHM_ECDSAP384SHA384_NAME,"14", NULL}; #endif #if DNSCORE_HAS_EDDSA_SUPPORT static const char *ed25619_names[] = { DNSKEY_ALGORITHM_ED25519_NAME, "15", NULL}; static const char *ed448_names[] = { DNSKEY_ALGORITHM_ED448_NAME, "16", NULL}; #endif #ifdef DNSKEY_ALGORITHM_DUMMY static const char *dnskey_dummy_names[] = {DNSKEY_ALGORITHM_DUMMY_NAME,"254", NULL}; #endif //static const char *empty_names[] = {NULL}; static const struct dnskey_features dnskey_supported_algorithms[] = { //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 0 { rsamd5_names, 512,4096, 2048, 1024, 1, DNSKEY_ALGORITHM_RSAMD5, DNSKEY_FEATURE_ZONE_NSEC }, //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 2 { dsasha1_names, 512,1024, 1024, 1024, 64, DNSKEY_ALGORITHM_DSASHA1, DNSKEY_FEATURE_ZONE_NSEC }, //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 4 { rsasha1_names, 512,4096, 2048, 1024, 1, DNSKEY_ALGORITHM_RSASHA1, DNSKEY_FEATURE_ZONE_NSEC }, { dsasha1nsec3_names, 512,1024, 1024, 1024, 64, DNSKEY_ALGORITHM_DSASHA1_NSEC3, DNSKEY_FEATURE_ZONE_NSEC3 }, { rsasha1nsec3_names, 512,4096, 2048, 1024, 1, DNSKEY_ALGORITHM_RSASHA1_NSEC3, DNSKEY_FEATURE_ZONE_NSEC3 }, { rsasha256_names, 512,4096, 2048, 1024, 1, DNSKEY_ALGORITHM_RSASHA256_NSEC3, DNSKEY_FEATURE_ZONE_MODERN }, //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 9 { rsasha512_names, 1024,4096, 2048, 1024, 1, DNSKEY_ALGORITHM_RSASHA512_NSEC3, DNSKEY_FEATURE_ZONE_MODERN }, //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 11 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 12 #if DNSCORE_HAS_ECDSA_SUPPORT { ecdsap256sha256_names, 256,256, 256, 256, 1, DNSKEY_ALGORITHM_ECDSAP256SHA256, DNSKEY_FEATURE_ZONE_MODERN }, { ecdsap384sha384_names, 384,384, 384, 384, 1, DNSKEY_ALGORITHM_ECDSAP384SHA384, DNSKEY_FEATURE_ZONE_MODERN }, #else //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 13 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 14 #endif #if DNSCORE_HAS_EDDSA_SUPPORT { ed25619_names, 0,0, 0, 0, 1, DNSKEY_ALGORITHM_ED25519, DNSKEY_FEATURE_ZONE_MODERN }, { ed448_names, 0,0, 0, 0, 1, DNSKEY_ALGORITHM_ED448, DNSKEY_FEATURE_ZONE_MODERN }, #else //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 15 //{NULL, 0, 0, 0, 0, 0, 0, 0}, // 16 #endif #ifdef DNSKEY_ALGORITHM_DUMMY { dnskey_dummy_names, 16,16, 16, 16, 16, DNSKEY_ALGORITHM_DUMMY, DNSKEY_FEATURE_ZONE_MODERN }, #endif /* { // terminator empty_names, 0,0, 0, 0, 0, 0 }*/ }; static const char * dnskey_get_algorithm_name_from_value(int alg) { switch(alg) { case DNSKEY_ALGORITHM_RSAMD5: return "RSAMD5"; case DNSKEY_ALGORITHM_DIFFIE_HELLMAN: return "DH"; case DNSKEY_ALGORITHM_DSASHA1: return "DSASHA1"; case DNSKEY_ALGORITHM_RSASHA1: return "RSASHA1"; case DNSKEY_ALGORITHM_DSASHA1_NSEC3: return "NSEC3DSA"; case DNSKEY_ALGORITHM_RSASHA1_NSEC3: return "NSEC3RSASHA1"; case DNSKEY_ALGORITHM_RSASHA256_NSEC3: return "RSASHA256"; case DNSKEY_ALGORITHM_RSASHA512_NSEC3: return "RSASHA512"; case DNSKEY_ALGORITHM_GOST: return "ECCGOST"; case DNSKEY_ALGORITHM_ECDSAP256SHA256: return "ECDSAP256SHA256"; case DNSKEY_ALGORITHM_ECDSAP384SHA384: return "ECDSAP384SHA384"; case DNSKEY_ALGORITHM_ED25519: return "ED25519"; case DNSKEY_ALGORITHM_ED448: return "ED448"; #ifdef DNSKEY_ALGORITHM_DUMMY case DNSKEY_ALGORITHM_DUMMY: return "DUMMY"; #endif default: return "?"; } } static ya_result dnskey_field_parser_dummy_parse_field(struct dnskey_field_parser *parser, struct parser_s *p) { (void)parser; (void)p; return FEATURE_NOT_IMPLEMENTED_ERROR; } static ya_result dnskey_field_parser_dummy_set_key(struct dnskey_field_parser *parser, dnssec_key *key) { (void)parser; (void)key; return FEATURE_NOT_IMPLEMENTED_ERROR; } static void dnskey_field_parser_dummy_finalize_method(struct dnskey_field_parser *parser) { (void)parser; } struct dnskey_field_parser_vtbl dnskey_field_dummy_parser = { dnskey_field_parser_dummy_parse_field, dnskey_field_parser_dummy_set_key, dnskey_field_parser_dummy_finalize_method, "DUMMY" }; ya_result dnskey_field_access_parse(const struct dnskey_field_access *sd, void *base, parser_s *p) { ya_result ret = INVALID_STATE_ERROR; u32 label_len = parser_text_length(p); const char *label = parser_text(p); bool parsed_it = FALSE; u8 tmp_out[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; for(; sd->type != STRUCTDESCRIPTOR_NONE; sd++) { switch(sd->type) { case STRUCTDESCRIPTOR_BN: { if(memcmp(label, sd->name, label_len) == 0) { BIGNUM **bnp = (BIGNUM**)(((u8*)base) + sd->relative); ret = parser_next_word(p); if((*bnp != NULL) || FAIL(ret)) { return ret; } u32 word_len = parser_text_length(p); const char *word = parser_text(p); ya_result n = base64_decode(word, word_len, tmp_out); if(FAIL(n)) { log_err("dnskey: unable to decode field %s", sd->name); return n; } *bnp = BN_bin2bn(tmp_out, n, NULL); if(*bnp == NULL) { log_err("dnskey: unable to get big number from field %s", sd->name); return DNSSEC_ERROR_BNISNULL; } parsed_it = TRUE; goto dnskey_field_access_parse_loop_exit; } break; } case STRUCTDESCRIPTOR_RAW: { if(memcmp(label, sd->name, label_len) == 0) { dnskey_raw_field_t *raw = (dnskey_raw_field_t*)(((u8*)base) + sd->relative); ret = parser_next_word(p); if((raw->buffer != NULL) || FAIL(ret)) { return ret; } u32 word_len = parser_text_length(p); const char *word = parser_text(p); ya_result n = base64_decode(word, word_len, tmp_out); if(FAIL(n)) { log_err("dnskey: unable to decode field %s", sd->name); return n; } ZALLOC_OBJECT_ARRAY_OR_DIE(raw->buffer, u8, n, DNSKRAWB_TAG); memcpy(raw->buffer, tmp_out, n); raw->size = n; parsed_it = TRUE; goto dnskey_field_access_parse_loop_exit; } break; } } } /* for each possible field */ dnskey_field_access_parse_loop_exit: if(!parsed_it) { return SUCCESS; // unknown keyword (ignore) } return ret; } ya_result dnskey_field_access_print(const struct dnskey_field_access *sd, const void *base, output_stream *os) { ya_result ret = SUCCESS; for(; sd->type != STRUCTDESCRIPTOR_NONE; sd++) { switch(sd->type) { case STRUCTDESCRIPTOR_BN: { const u8 *bn_ptr_ptr = (((const u8*)base) + sd->relative); const BIGNUM **bn = (const BIGNUM**)bn_ptr_ptr; if(bn != NULL) { osformat(os, "%s: ", sd->name); dnskey_write_bignum_as_base64_to_stream(*bn, os); osprintln(os, ""); } break; } case STRUCTDESCRIPTOR_RAW: { const u8 *bn_ptr_ptr = (((const u8*)base) + sd->relative); const dnskey_raw_field_t *raw = (const dnskey_raw_field_t *)bn_ptr_ptr; osformat(os, "%s: ", sd->name); char buffer[1024]; u32 encoded_size = BASE64_ENCODED_SIZE(raw->size); if(encoded_size > sizeof(buffer)) { return BUFFER_WOULD_OVERFLOW; } u32 n = base64_encode(raw->buffer, raw->size, buffer); output_stream_write(os, buffer, n); osprintln(os, ""); break; } case STRUCTDESCRIPTOR_U16: { const u8 *bn_ptr_ptr = (((const u8*)base) + sd->relative); const u16 *valuep = (const u16 *)bn_ptr_ptr; osformat(os, "%s: %hu", sd->name, *valuep); break; } } } return ret; } /* unsigned long ac; * assumed to be 32 bits or larger * int i; * loop index * for ( ac = 0, i = 0; i < keysize; ++i ) ac += (i & 1) ? key[i] : key[i] << 8; ac += (ac >> 16) & 0xFFFF; return ac & 0xFFFF; => s=0; s+=key[0] s+=key[1]<<8 s+=key[2] s+=key[3]<<8 Basically it's a sum of little-endian unsigned 16 bits words And the reference implementation does not match the definition. "ignoring any carry bits" Yes ? So this is wrong : ac += (i & 1) ? key[i] : key[i] << 8; The least significant byte will have the add carry bit carried to the most signiticant byte. */ /** * Generates a key tag from the DNSKEY RDATA wire * * @param dnskey_rdata * @param dnskey_rdata_size * @return */ u16 dnskey_get_tag_from_rdata(const u8* dnskey_rdata, u32 dnskey_rdata_size) { u32 sum = 0; u32 sumh = 0; while(dnskey_rdata_size > 1) { sumh += *dnskey_rdata++; sum += *dnskey_rdata++; dnskey_rdata_size -= 2; } if(dnskey_rdata_size != 0) { sumh += *dnskey_rdata++; } sum += sumh << 8; sum += sum >> 16; return (u16)sum; } /** * Initialises the context for a key algorithm. * * @param ctx * @param algorithm * @return */ ya_result dnskey_digest_init(digest_s *ctx, u8 algorithm) { switch(algorithm) { case DNSKEY_ALGORITHM_DSASHA1: case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_DSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: digest_sha1_init(ctx); break; case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_ECDSAP256SHA256: digest_sha256_init(ctx); break; case DNSKEY_ALGORITHM_ECDSAP384SHA384: digest_sha384_init(ctx); break; case DNSKEY_ALGORITHM_RSASHA512_NSEC3: digest_sha512_init(ctx); break; #if DNSCORE_HAS_EDDSA_SUPPORT case DNSKEY_ALGORITHM_ED25519: case DNSKEY_ALGORITHM_ED448: digest_rawdata_init(ctx); break; #endif #ifdef DNSKEY_ALGORITHM_DUMMY case DNSKEY_ALGORITHM_DUMMY: break; #endif default: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } return SUCCESS; } /** * Generate the RDATA of a DS records using the RDATA from a DSNKEY record * * @param digest_type the type of DS * @param dnskey_fqdn the domain of the record * @param dnskey_rdata the rdata of the DNSKEY * @param dnskey_rdata_size the size of the rdata of the DNSKEY * @param out_rdata the output buffer that has to be the right size (known given digest_type) * @return */ ya_result dnskey_generate_ds_rdata(u8 digest_type, const u8 *dnskey_fqdn, const u8 *dnskey_rdata,u16 dnskey_rdata_size, u8 *out_rdata) { digest_s ctx; s32 digest_size; switch(digest_type) { case DS_DIGEST_SHA1: digest_sha1_init(&ctx); break; case DS_DIGEST_SHA256: digest_sha256_init(&ctx); break; default: return DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM; } digest_size = digest_get_size(&ctx); u16 tag = dnskey_get_tag_from_rdata(dnskey_rdata, dnskey_rdata_size); u8 algorithm = dnskey_rdata[3]; digest_update(&ctx, dnskey_fqdn, dnsname_len(dnskey_fqdn)); digest_update(&ctx, dnskey_rdata, dnskey_rdata_size); out_rdata[0] = tag >> 8; out_rdata[1] = tag; out_rdata[2] = algorithm; out_rdata[3] = digest_type; digest_final_copy_bytes(&ctx, &out_rdata[4], digest_size); // generates DS record : safe use return 4 + digest_size; } /** * Sanitises an text origin and returns a zallocated copy of it * * @param origin * @return a sanitized zallocated copy of origin */ static char* dnskey_origin_zdup_sanitize(const char* origin) { char* ret; if(origin == NULL) { ZALLOC_OBJECT_ARRAY_OR_DIE(ret, char, 2, ORIGNDUP_TAG); ret[0] = '.'; ret[1] = '\0'; return ret; } int origin_len = strlen(origin); if(origin_len == 0) { ZALLOC_OBJECT_ARRAY_OR_DIE(ret, char, 2, ORIGNDUP_TAG); ret[0] = '.'; ret[1] = '\0'; return ret; } if(origin[origin_len - 1] == '.') { origin_len++; ZALLOC_OBJECT_ARRAY_OR_DIE(ret, char, origin_len, ORIGNDUP_TAG); //MEMCOPY(ret, origin, origin_len); for(int i = 0; i < origin_len; i++) { ret[i] = tolower(origin[i]); } } else { ZALLOC_OBJECT_ARRAY_OR_DIE(ret, char, (origin_len + 2), ORIGNDUP_TAG); //MEMCOPY(ret, origin, origin_len); for(int i = 0; i < origin_len; i++) { ret[i] = tolower(origin[i]); } ret[origin_len++] = '.'; // VS false positive (nonsense) ret[origin_len] = '\0'; } return ret; } /** * Initialises an empty instance of a DNSKEY * No cryptographic content is put in the key. * Needs further setup. * * @param algorithm the algorithm of the key. * @param flags the flags of the key * @param origin the origin of the key * * @return a pointer to an empty instance (no real key attached) of a key. */ dnssec_key* dnskey_newemptyinstance(u8 algorithm, u16 flags, const char *origin) { yassert(origin != NULL); char *origin_copy = dnskey_origin_zdup_sanitize(origin); u8 *owner_name = dnsname_zdup_from_name(origin_copy); if(owner_name == NULL) { log_err("dnskey_newemptyinstance(%hhu, %hx, %s = '%s'): origin parameter is not a domain name", algorithm, flags, origin, origin_copy); ZFREE_ARRAY(origin_copy, strlen(origin_copy) + 1); return NULL; } dnssec_key* key; ZALLOC_OBJECT_OR_DIE( key, dnssec_key, ZDB_DNSKEY_TAG); ZEROMEMORY(key, sizeof(dnssec_key)); key->origin = origin_copy; /* origin is allocated with ZALLOC using ZALLOC_STRING_OR_DIE * In this mode, the byte before the pointer is the size of the string. */ key->owner_name = owner_name; key->rc = 1; key->epoch_created = 0; key->epoch_publish = 0; key->epoch_activate = 0; /* key->epoch_inactive = 0; key->epoch_delete = 0; */ key->flags = flags; key->algorithm = algorithm; /*key->status = 0;*/ /*key->key.X=....*/ /*key->tag=00000*/ /*key->is_private=TRUE;*/ log_debug("dnskey_newemptyinstance: %{dnsname} +%03d+-----/%d status=%x rc=%i (%p)", dnskey_get_domain(key), key->algorithm, ntohs(key->flags), key->status, key->rc, key); return key; } /** * Increases the reference count on a dnssec_key * * @param key */ #if DUMP_ACQUIRE_RELEASE_STACK_TRACE static void dnskey_acquire_debug() { stacktrace st = debug_stacktrace_get(); debug_stacktrace_log_with_prefix(MODULE_MSG_HANDLE, MSG_DEBUG, st, "dnskey_acquire: "); } static void dnskey_release_debug() { stacktrace st = debug_stacktrace_get(); debug_stacktrace_log_with_prefix(MODULE_MSG_HANDLE, MSG_DEBUG, st, "dnskey_release: "); } #endif void dnskey_acquire(dnssec_key *key) { yassert(key->rc > 0); log_debug("dnskey_acquire: %{dnsname} +%03d+%05d/%d status=%x rc=%i (%p)", dnskey_get_domain(key), key->algorithm, key->tag, ntohs(key->flags), key->status, key->rc + 1, key); group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); ++key->rc; #if DUMP_ACQUIRE_RELEASE_STACK_TRACE dnskey_acquire_debug(); #endif group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } /** * Releases the reference count on a dnssec_key. * If the reference count reaches zero, destroys the key. * * @param a * @param b */ void dnskey_release(dnssec_key *key) { yassert(key != NULL && key->rc > 0); log_debug("dnskey_release: %{dnsname} +%03d+%05d/%d status=%x rc=%i (%p)", dnskey_get_domain(key), key->algorithm, key->tag, ntohs(key->flags), key->status, key->rc - 1, key); #if DUMP_ACQUIRE_RELEASE_STACK_TRACE dnskey_release_debug(); #endif group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); if(--key->rc == 0) { group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); #if DEBUG if(key->next != NULL) { // log_err("dnskey_release(%p): a key should be detached from its list before destruction", key); logger_flush(); abort(); } #endif if(key->vtbl != NULL) { key->vtbl->dnssec_key_free(key); } ZFREE_ARRAY(key->origin, strlen(key->origin) + 1); // +1 because the 0 has to be taken in account too (duh!) dnsname_zfree(key->owner_name); #if DEBUG memset(key, 0xfe, sizeof(dnssec_key)); #endif ZFREE(key, dnssec_key); } else { group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } } /** * Generate a (public) key using the RDATA * * RC ok * * @param rdata * @param rdata_size * @param origin * @param out_key points to a pointer for the instantiated key * * @return an error code (success or error) */ ya_result dnskey_new_from_rdata(const u8 *rdata, u16 rdata_size, const u8 *fqdn, dnssec_key **out_key) { if(out_key == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } ya_result return_value; u8 algorithm = rdata[3]; char origin[MAX_DOMAIN_LENGTH]; dnsname_to_cstr(origin, fqdn); *out_key = NULL; switch(algorithm) { case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: return_value = dnskey_rsa_loadpublic(rdata, rdata_size, origin, out_key); // RC break; case DNSKEY_ALGORITHM_DSASHA1: case DNSKEY_ALGORITHM_DSASHA1_NSEC3: return_value = dnskey_dsa_loadpublic(rdata, rdata_size, origin, out_key); // RC break; #if DNSCORE_HAS_ECDSA_SUPPORT case DNSKEY_ALGORITHM_ECDSAP256SHA256: case DNSKEY_ALGORITHM_ECDSAP384SHA384: return_value = dnskey_ecdsa_loadpublic(rdata, rdata_size, origin, out_key); // RC break; #endif #if DNSCORE_HAS_EDDSA_SUPPORT case DNSKEY_ALGORITHM_ED25519: case DNSKEY_ALGORITHM_ED448: return_value = dnskey_eddsa_loadpublic(rdata, rdata_size, origin, out_key); // RC break; #endif #ifdef DNSKEY_ALGORITHM_DUMMY case DNSKEY_ALGORITHM_DUMMY: return_value = dnskey_dummy_loadpublic(rdata, rdata_size, origin, out_key); break; #endif default: return_value = DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; break; } return return_value; } /** * Writes a BIGNUM integer to a stream */ ya_result dnskey_write_bignum_as_base64_to_stream(const BIGNUM *num, output_stream *os) { u8 *buffer; char *buffer2; u8 buffer_[4096]; char buffer2_[4096]; if(num == NULL) { return DNSSEC_ERROR_BNISNULL; } u32 n = BN_num_bytes(num); u32 m = BASE64_ENCODED_SIZE(n); if(n <= sizeof(buffer_)) { buffer = buffer_; } else { MALLOC_OBJECT_ARRAY_OR_DIE(buffer, u8, n, TMPBUFFR_TAG); //buffer = (u8*)malloc(n); } if(m <= sizeof(buffer2_)) { buffer2 = buffer2_; } else { MALLOC_OBJECT_ARRAY_OR_DIE(buffer2, char, m, TMPBUFFR_TAG); //buffer2 = (char*)malloc(m); } BN_bn2bin(num, buffer); u32 o = base64_encode(buffer,n,buffer2); yassert(o <= m); output_stream_write(os, buffer2, o); if(buffer != buffer_) free(buffer); if(buffer2 != buffer2_) free(buffer2); return SUCCESS; } /** * Returns the most relevant publication time. * * publish > activate > created > now * * @param key * @return */ time_t dnskey_get_publish_epoch(const dnssec_key *key) { u32 ret; group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ); if(key->epoch_publish != 0) { ret = key->epoch_publish; } else if(key->epoch_activate != 0) { ret = key->epoch_activate; } else if(key->epoch_created != 0) { ret = key->epoch_created; } else { ret = 0; // of course, the last if/else could be replaced by ret = key->epoch_created } group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ); return ret; } void dnskey_set_created_epoch(dnssec_key *key, time_t t) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); key->epoch_created = t; key->status |= DNSKEY_KEY_HAS_SMART_FIELD_CREATED; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } void dnskey_set_publish_epoch(dnssec_key *key, time_t t) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); key->epoch_publish = t; key->status |= DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } /** * Returns the most relevant activation time. * * activate > publish > created > now * * @param key * @return */ time_t dnskey_get_activate_epoch(const dnssec_key *key) { u32 ret; group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); if(key->epoch_activate != 0) { ret = key->epoch_activate; } else if(key->epoch_publish != 0) { ret = key->epoch_publish; } else if(key->epoch_created != 0) { ret = key->epoch_created; } else { ret = 0; } group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); return ret; } void dnskey_set_activate_epoch(dnssec_key *key, time_t t) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); key->epoch_activate = t; key->status |= DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } /** * Returns the most relevant inactivation time. * * inactive > delete > never * * @param key * @return */ time_t dnskey_get_inactive_epoch(const dnssec_key *key) { u32 ret; group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); if(key->epoch_inactive != 0) { ret = key->epoch_inactive; } else if(key->epoch_activate != 0) { // if activation was a lie, inactivation is one too anyway if((key->epoch_created != 0) && (key->epoch_delete > key->epoch_created)) { s64 leniency = (key->epoch_delete - key->epoch_created) / 4; if(leniency > 86400) { leniency = 86400; } s64 inactive_epoch = key->epoch_delete - leniency; if(inactive_epoch > MAX_S32) inactive_epoch = MAX_S32; ret = (s32)inactive_epoch; } else { ret = MAX_S32; } } else { ret = MAX_S32; // don't use MAX_U32 here } group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); return ret; } void dnskey_set_inactive_epoch(dnssec_key *key, time_t t) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); key->epoch_inactive = t; key->status |= DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } /** * Returns the most relevant delete time. * * delete > inactive > never * * @param key * @return */ time_t dnskey_get_delete_epoch(const dnssec_key *key) { u32 ret; group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ); if(key->epoch_delete != 0) { ret = key->epoch_delete; } else if(key->epoch_publish == 0) { // if publication was a lie, delete is one too anyway if((key->epoch_created != 0) && (key->epoch_inactive > key->epoch_activate)) { s64 leniency = (key->epoch_inactive - key->epoch_activate) / 4; if(leniency > 86400) { leniency = 86400; } s64 delete_epoch = key->epoch_inactive + leniency; if(delete_epoch > MAX_S32) delete_epoch = MAX_S32; ret = (s32)delete_epoch; } else { ret = MAX_S32; } } else { ret = MAX_S32; // don't use MAX_U32 here } group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ); return ret; } void dnskey_set_delete_epoch(dnssec_key *key, time_t t) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); key->epoch_delete= t; key->status |= DNSKEY_KEY_HAS_SMART_FIELD_DELETE; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } /** * * Compares two keys for equality on a cryptographic point of view * Uses the tag, flags, algorithm, origin and key content. * * @param a * @param b * * @return TRUE iff the keys are the same. */ bool dnskey_equals(const dnssec_key* a, const dnssec_key* b) { if(a == b) { return TRUE; } if(dnssec_key_tag_field_set(a) && dnssec_key_tag_field_set(b)) { if(a->tag != b->tag) { return FALSE; } } if((a->flags == b->flags) && (a->algorithm == b->algorithm)) { /* Compare the origin */ if(strcmp(a->origin, b->origin) == 0) { /* Compare the content of the key */ return a->vtbl->dnssec_key_equals(a, b); } } return FALSE; } /** * * Compares two keys for equality on a cryptographic point of view * Uses the tag, flags, algorithm, origin and public key content. * * @param a * @param b * * @return TRUE iff the keys are the same. */ bool dnskey_public_equals(const dnssec_key *a, const dnssec_key *b) { if(a == b) { return TRUE; } if(dnssec_key_tag_field_set(a) && dnssec_key_tag_field_set(b)) { if(a->tag != b->tag) { return FALSE; } } if((a->flags == b->flags) && (a->algorithm == b->algorithm)) { /* Compare the origin */ if(strcmp(a->origin, b->origin) == 0) { /* Compare the content of the key */ u8 rdata_a[4096]; u8 rdata_b[4096]; u32 rdata_a_size = a->vtbl->dnssec_key_writerdata(a, rdata_a, sizeof(rdata_a)); u32 rdata_b_size = b->vtbl->dnssec_key_writerdata(b, rdata_b, sizeof(rdata_b)); if(rdata_a_size == rdata_b_size) { bool ret = (memcmp(rdata_a, rdata_b, rdata_a_size) == 0); return ret; } } } return FALSE; } /** * Returns TRUE if the tag and algorithm of the rdata are matching the ones of the key. * * @param key * @param rdata * @param rdata_size * @return */ bool dnskey_matches_rdata(const dnssec_key *key, const u8 *rdata, u16 rdata_size) { if(dnskey_get_algorithm(key) == rdata[3]) { u16 key_tag = dnskey_get_tag_const(key); u16 rdata_tag = dnskey_get_tag_from_rdata(rdata, rdata_size); return key_tag == rdata_tag; } return FALSE; } u16 dnskey_get_tag(dnssec_key *key) { if((dnskey_state_get(key) & DNSKEY_KEY_TAG_SET) == 0) { u8 rdata[2048]; u32 rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, sizeof(rdata)); yassert(rdata_size <= 2048); u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size); group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); key->tag = tag; key->status |= DNSKEY_KEY_TAG_SET; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } return key->tag; } u16 dnskey_get_tag_const(const dnssec_key *key) { u16 tag; if(key->status & DNSKEY_KEY_TAG_SET) { tag = key->tag; } else { u8 rdata[2048]; u32 rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, sizeof(rdata)); yassert(rdata_size <= 2048); tag = dnskey_get_tag_from_rdata(rdata, rdata_size); } return tag; } u8 dnskey_get_algorithm(const dnssec_key *key) { return key->algorithm; } const u8 * dnskey_get_domain(const dnssec_key *key) { if(key != NULL) { return key->owner_name; } else { return (const u8*)"\004NULL"; } } bool dnskey_is_private(const dnssec_key *key) { return (key->status & DNSKEY_KEY_IS_PRIVATE) != 0; } /** * Adds/Remove a key from a key chain. * The 'next' field of the key is used. * A key can only be in one chain at a time. * This is meant to be used in the keystore. * * RC ok * * @param keyp */ void dnskey_add_to_chain(dnssec_key *key, dnssec_key **prevp) { yassert(key->next == NULL); u16 key_tag = dnskey_get_tag(key); while(*prevp != NULL) { if(dnskey_get_tag(*prevp) > key_tag) { key->next = *prevp; *prevp = key; dnskey_acquire(key); return; } prevp = &((*prevp)->next); } // append *prevp = key; dnskey_acquire(key); key->next = NULL; } /** * Adds/Remove a key from a key chain. * The 'next' field of the key is used. * A key can only be in one chain at a time. * This is meant to be used in the keystore. * * RC ok * * @param keyp */ void dnskey_remove_from_chain(dnssec_key *key, dnssec_key **prevp) { u16 key_tag = dnskey_get_tag(key); while(*prevp != NULL) { u16 tag; if((tag = dnskey_get_tag(*prevp)) >= key_tag) { if(tag == key_tag) { dnssec_key *key_to_release = *prevp; *prevp = (*prevp)->next; // now (and only now) the next field can (and must) be cleared key_to_release->next = NULL; dnskey_release(key_to_release); } break; } prevp = &((*prevp)->next); } } ya_result dnskey_new_public_key_from_stream(input_stream *is, dnssec_key** keyp) { parser_s parser; ya_result ret; u16 rclass; u16 rtype; u16 flags; u16 rdata_size; char origin[MAX_DOMAIN_LENGTH + 1]; u8 fqdn[MAX_DOMAIN_LENGTH]; u8 rdata[1024 + 4]; parser_init(&parser, "\"\"''", "()", ";#", "\040\t\r", "\\"); parser.close_last_stream = FALSE; parser_push_stream(&parser, is); for(;;) { if(ISOK(ret = parser_next_token(&parser))) { if(!(ret & PARSER_WORD)) { if(ret & (PARSER_COMMENT|PARSER_EOL)) { continue; } if(ret & PARSER_EOF) { input_stream *completed_stream = parser_pop_stream(&parser); if(completed_stream != is) { input_stream_close(completed_stream); } ret = UNEXPECTED_EOF; break; } continue; } } const char *text = parser_text(&parser); u32 text_len = parser_text_length(&parser); memcpy(origin, text, text_len); origin[text_len] = '\0'; if(FAIL(ret = cstr_to_dnsname_with_check_len(fqdn, text, text_len))) { break; } if(FAIL(ret = parser_copy_next_class(&parser, &rclass))) { break; } if(rclass != CLASS_IN) { // not IN ret = DNSSEC_ERROR_EXPECTED_CLASS_IN; break; } if(FAIL(ret = parser_copy_next_type(&parser, &rtype))) { break; } if(rtype != TYPE_DNSKEY) { // not DNSKEY ret = DNSSEC_ERROR_EXPECTED_TYPE_DNSKEY; break; } if(FAIL(ret = parser_copy_next_u16(&parser, &flags))) { break; } flags = htons(flags); // need to fix the endianness SET_U16_AT_P(rdata, flags); // protocol (8 bits integer) if(FAIL(ret = parser_copy_next_u8(&parser, &rdata[2]))) { break; } // algorithm (8 bits integer) if(FAIL(ret = parser_copy_next_u8(&parser, &rdata[3]))) { break; } // key (base64) if(FAIL(ret = parser_concat_next_tokens_nospace(&parser))) { break; } if(BASE64_DECODED_SIZE(ret) > (int)sizeof(rdata) - 4) { // overflow ret = DNSSEC_ERROR_UNEXPECTEDKEYSIZE; break; } if(FAIL(ret = base64_decode(parser_text(&parser), parser_text_length(&parser), &rdata[4]))) { break; } if(ret > 1024) { ret = DNSSEC_ERROR_KEYISTOOBIG; break; } rdata_size = 4 + ret; ret = dnskey_new_from_rdata(rdata, rdata_size, fqdn, keyp); // RC break; } parser_finalize(&parser); return ret; } /** * Loads a public key from a file. * * ie: Keu.+007+12345.key * * RC ok * * @param filename * @param keyp * @return */ ya_result dnskey_new_public_key_from_file(const char *filename, dnssec_key** keyp) { input_stream is; ya_result ret; if(keyp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } *keyp = NULL; if(ISOK(ret = file_input_stream_open(&is, filename))) { ret = dnskey_new_public_key_from_stream(&is, keyp); input_stream_close(&is); } return ret; } ya_result dnskey_add_private_key_from_stream(input_stream *is, dnssec_key *key, const char* path, u8 algorithm) { dnskey_field_parser dnskey_parser = {NULL, &dnskey_field_dummy_parser}; parser_s parser; s64 timestamp; u32 smart_fields = 0; ya_result ret; u8 parsed_algorithm; if(path == NULL) { path = ""; } // in case of error, the timestamp is set to 0 fd_mtime(fd_input_stream_get_filedescriptor(is), ×tamp); if(ISOK(ret = parser_init(&parser, "", // by 2 "", // by 2 "#;", // by 1 " \t\r:", // by 1 "" // by 1 ))) { parser.close_last_stream = FALSE; parser_push_stream(&parser, is); for(;;) { // get the next token if(ISOK(ret = parser_next_token(&parser))) { if(!(ret & PARSER_WORD)) { if(ret & (PARSER_COMMENT|PARSER_EOL)) { continue; } } if(ret & PARSER_EOF) { break; } } // u32 label_len = parser_text_length(&parser); const char *label = parser_text(&parser); // makes the word asciiz (need to be undone) parser_text_asciiz(&parser); #if DEBUG log_debug("dnskey: parsing %s::%s", path, label); #endif string_node *node = string_set_find(&dnssec_key_load_private_keywords_set, label); // makes the word asciiz (need to be undone) parser_text_unasciiz(&parser); if(node != NULL) { // push to management // parse next word if(FAIL(ret = parser_next_word(&parser))) { break; } u32 word_len = parser_text_length(&parser); const char *word = parser_text(&parser); switch(node->value) { case DNSKEY_FIELD_ALGORITHM: { if(ISOK(ret = parser_get_u8(word, word_len, &parsed_algorithm))) { if(algorithm == 0) { algorithm = parsed_algorithm; } else if(parsed_algorithm != algorithm) { log_err("dnssec: error parsing %s: expected algorithm version %i, got %i", path, algorithm, parsed_algorithm); ret = DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } parser_expect_eol(&parser); } break; } case DNSKEY_FIELD_FORMAT: { ret = DNSSEC_ERROR_FILE_FORMAT_VERSION; if(word[0] == 'v') { if(word[1] == '1') { if(word[2] == '.') { // let's assume all 1.x are compatible ret = SUCCESS; break; } } } // makes the word asciiz (need to be undone) parser_text_asciiz(&parser); log_err("dnssec: error parsing %s: expected format v1.x, got %s", path, word); parser_text_unasciiz(&parser); break; } case DNSKEY_FIELD_CREATED: { if(ISOK(ret = parse_yyyymmddhhmmss_check_range_len(word, word_len, &key->epoch_created))) { smart_fields |= DNSKEY_KEY_HAS_SMART_FIELD_CREATED; } break; } case DNSKEY_FIELD_PUBLISH: { if(ISOK(ret = parse_yyyymmddhhmmss_check_range_len(word, word_len, &key->epoch_publish))) { smart_fields |= DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH; } break; } case DNSKEY_FIELD_ACTIVATE: { if(ISOK(ret = parse_yyyymmddhhmmss_check_range_len(word, word_len, &key->epoch_activate))) { smart_fields |= DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE; } break; } case DNSKEY_FIELD_INACTIVE: { if(ISOK(ret = parse_yyyymmddhhmmss_check_range_len(word, word_len, &key->epoch_inactive))) { smart_fields |= DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE; } break; } case DNSKEY_FIELD_DELETE: { if(ISOK(ret = parse_yyyymmddhhmmss_check_range_len(word, word_len, &key->epoch_delete))) { smart_fields |= DNSKEY_KEY_HAS_SMART_FIELD_DELETE; } break; } case DNSKEY_FIELD_ENGINE: { // a base64 encoded null-terminated engine name (ie: "pkcs11") break; } default: { log_err("dnssec: internal error: %s set as %i defined but not handled", node->key, node->value); ret = DNSSEC_ERROR_FIELD_NOT_HANDLED; } } if(FAIL(ret)) { if(ret != /**/ ERROR) { log_err("dnssec: error parsing %s: failed to parse value of field %s: %r", path, node->key, ret); } break; } while(FAIL(parser_expect_eol(&parser))) { log_warn("dnssec: expected end of line"); } } else { if(dnskey_parser.data == NULL) { switch(algorithm) { case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: { dnskey_rsa_parse_init(&dnskey_parser); break; } case DNSKEY_ALGORITHM_DSASHA1: case DNSKEY_ALGORITHM_DSASHA1_NSEC3: { dnskey_dsa_parse_init(&dnskey_parser); break; } #if DNSCORE_HAS_ECDSA_SUPPORT case DNSKEY_ALGORITHM_ECDSAP256SHA256: case DNSKEY_ALGORITHM_ECDSAP384SHA384: { dnskey_ecdsa_parse_init(&dnskey_parser); break; } #endif #if DNSCORE_HAS_EDDSA_SUPPORT case DNSKEY_ALGORITHM_ED25519: case DNSKEY_ALGORITHM_ED448: { dnskey_eddsa_parse_init(&dnskey_parser); break; } #endif #ifdef DNSKEY_ALGORITHM_DUMMY case DNSKEY_ALGORITHM_DUMMY: { dnskey_dummy_parse_init(&dnskey_parser); break; } #endif default: { ret = DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; goto dnskey_new_private_key_from_file_failure; /// *** GOTO *** /// // break; } } } ret = dnskey_parser.vtbl->parse_field(&dnskey_parser, &parser); if(FAIL(ret)) { log_err("dnssec: error parsing key %s: %r", path, ret); break; } while(FAIL(parser_expect_eol(&parser))) { log_warn("dnssec: expected end of line"); } } // if failed push to expected algorithm // else issue a warning // note the last modification time of the file, for management // close } // for(;;) if(ISOK(ret)) { if(FAIL(ret = dnskey_parser.vtbl->set_key(&dnskey_parser, key))) { log_err("dnssec: %s cannot be read as a private key", path); } key->status |= smart_fields; switch(smart_fields & (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE)) { case DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH: { key->epoch_activate = key->epoch_publish; break; } case DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE: { key->epoch_publish = key->epoch_activate; break; } } } dnskey_new_private_key_from_file_failure: dnskey_parser.vtbl->finalise(&dnskey_parser); parser_finalize(&parser); // also closes the stream if(ISOK(ret)) { if(!dnskey_is_private(key)) { log_err("dnssec: %s is not a valid private key", path); ret = DNSSEC_ERROR_KEYRING_KEY_IS_NOT_PRIVATE; } } if(ISOK(ret)) { key->timestamp = timestamp; } else { dnskey_release(key); key = NULL; } } return ret; } /** * Loads a private key from a file. * * ie: Keu.+007+12345.private * * The public key must be in the same folder as the private key. * * ie: Keu.+007+12345.key * * RC ok * * @param filename * @param keyp * @return */ ya_result dnskey_new_private_key_from_file(const char *filename, dnssec_key **keyp) { dnssec_key *key; ya_result ret; //u32 smart_fields = 0; int path_len; int algorithm = -1; int tag; //u8 parsed_algorithm; //bool ext_is_private; char extension[16]; char domain[256]; u8 origin[256]; char path[PATH_MAX]; if(keyp == NULL) { return INVALID_ARGUMENT_ERROR; } const char *name = strrchr(filename,'/'); if(name == NULL) { name = filename; } else { ++name; } if(sscanf(name, "K%255[^+]+%03d+%05d.%15s", domain, &algorithm, &tag, extension) != 4) { log_err("dnssec: don't know how to parse key file name: '%s'", filename); return PARSESTRING_ERROR; } if(FAIL(ret = cstr_to_dnsname_with_check(origin, domain))) { log_err("dnssec: could not parse domain name from file name: '%s': %r", filename, ret); return ret; } path_len = strlen(filename); if(memcmp(extension, "private", 7) == 0) { //ext_is_private = TRUE; path_len -= 7; } else if(memcmp(extension, "key", 3) == 0) { //ext_is_private = FALSE; path_len -= 3; } else { log_err("dnssec: expected .private or .key extension for the file: '%s'", filename); return INVALID_STATE_ERROR; } memcpy(path, filename, path_len); // first open the public key file, to get the flags memcpy(&path[path_len], "key", 4); if(FAIL(ret = dnskey_new_public_key_from_file(path, &key))) // RC { return ret; } // then open the private key file key->nid = 0; // else it will not be editable // scan-build false positive. key cannot be NULL. memcpy(&path[path_len], "private", 8); // open parser input_stream is; if(ISOK(ret = file_input_stream_open(&is, filename))) { ret = dnskey_add_private_key_from_stream(&is, key, path, algorithm); input_stream_close(&is); } *keyp = key; return ret; } /** * * Save the private part of a key to a stream * * @param key * @param filename * @return */ ya_result dnskey_store_private_key_to_stream(dnssec_key *key, output_stream *os) { yassert(os != NULL); yassert(key != NULL); checked_output_stream_data_t chkos_data; output_stream chkos; checked_output_stream_init(&chkos, os, &chkos_data); os = &chkos; const char *key_algorithm_name = dnskey_get_algorithm_name_from_value(key->algorithm); // basic fields osformatln(os, "Private-key-format: v1.3"); osformatln(os, "Algorithm: %i (%s)", key->algorithm, key_algorithm_name); // internal fields key->vtbl->dnssec_key_print_fields(key, os); // time fields : all are stored as an UTC YYYYMMDDhhmmss format_writer epoch = {packedepoch_format_handler_method, NULL}; if(key->epoch_created != 0) { epoch.value = (void*)(intptr)key->epoch_created; osformatln(os, "Created: %w", &epoch); } if(key->epoch_publish != 0) { epoch.value = (void*)(intptr)key->epoch_publish; osformatln(os, "Publish: %w", &epoch); } if(key->epoch_activate != 0) { epoch.value = (void*)(intptr)key->epoch_activate; osformatln(os, "Activate: %w", &epoch); } if(key->epoch_inactive != 0) { epoch.value = (void*)(intptr)key->epoch_inactive; osformatln(os, "Inactive: %w", &epoch); } if(key->epoch_delete != 0) { epoch.value = (void*)(intptr)key->epoch_delete; osformatln(os, "Delete: %w", &epoch); } return checked_output_stream_error(os); } /** * * Save the private part of a key to a file with the given name * * @param key * @param filename * @return */ ya_result dnskey_store_private_key_to_file(dnssec_key *key, const char *filename) { yassert(filename != NULL); yassert(key != NULL); output_stream os; ya_result ret; if(ISOK(ret = file_output_stream_create(&os, filename, 0644))) { buffer_output_stream_init(&os, &os, 4096); ret = dnskey_store_private_key_to_stream(key, &os); output_stream_close(&os); if(FAIL(ret)) { unlink(filename); } } return ret; } /** * * Save the public part of a key to a stream * * @param key * @param filename * @return */ ya_result dnskey_store_public_key_to_stream(dnssec_key *key, output_stream *os) { u8 rdata[2048]; if(key->vtbl->dnssec_key_rdatasize(key) < sizeof(rdata)) { checked_output_stream_data_t chkos_data; output_stream chkos; checked_output_stream_init(&chkos, os, &chkos_data); os = &chkos; int rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, sizeof(rdata)); rdata_desc dnskeyrdata = {TYPE_DNSKEY, rdata_size, rdata}; osformatln(os, "; This is a key, keyid %d, for domain %{dnsname}", dnskey_get_tag(key), key->owner_name); osformatln(os, "%{dnsname} IN %{typerdatadesc}", key->owner_name, &dnskeyrdata); return checked_output_stream_error(os); } else { return BUFFER_WOULD_OVERFLOW; } } /** * * Save the public part of a key to a file with the given name * * @param key * @param filename * @return */ ya_result dnskey_store_public_key_to_file(dnssec_key *key, const char *filename) { ya_result ret; if(key->vtbl->dnssec_key_rdatasize(key) < 2048) { output_stream os; if(ISOK(ret = file_output_stream_create(&os, filename, 0644))) { if(FAIL(ret = dnskey_store_public_key_to_stream(key, &os))) { unlink(filename); } output_stream_close(&os); } } else { ret = DNSSEC_ERROR_KEYISTOOBIG; // key too big (should never happen) } return ret; } /** * Save the private part of a key to a dir * * @param key * @param dirname * @return */ ya_result dnskey_store_private_key_to_dir(dnssec_key *key, const char *dirname) { ya_result ret; char filename[PATH_MAX]; if(ISOK(ret = snformat(filename, sizeof(filename), "%s/K%{dnsname}+%03d+%05d.private", dirname, key->owner_name, key->algorithm, dnskey_get_tag(key) ))) { ret = file_exists(filename); if(ret == 0) { ret = dnskey_store_private_key_to_file(key, filename); } else { // cannot create the file because it exists already or the path is not accessible ret = DNSSEC_ERROR_CANNOT_WRITE_NEW_FILE; } } return ret; } /** * * Saves the public part of the key in a dir * * @param key * @param dirname * @return */ ya_result dnskey_store_public_key_to_dir(dnssec_key *key, const char *dirname) { ya_result ret; char filename[PATH_MAX]; if(ISOK(ret = snformat(filename, sizeof(filename), "%s/K%{dnsname}+%03d+%05d.key", dirname, key->owner_name, key->algorithm, dnskey_get_tag(key) ))) { ret = file_exists(filename); if(ret == 0) { ret = dnskey_store_public_key_to_file(key, filename); } else { // cannot create the file because it exists already or the path is not accessible ret = DNSSEC_ERROR_CANNOT_WRITE_NEW_FILE; } } return ret; } /** * Save both parts of the key to the directory. * * @param key * @param dir * * @return an error code */ ya_result dnskey_store_keypair_to_dir(dnssec_key *key, const char *dir) { ya_result ret; if(ISOK(ret = dnskey_store_public_key_to_dir(key, dir))) { if(FAIL(ret = dnskey_store_private_key_to_dir(key, dir))) { // delete the public key file dnskey_delete_public_key_from_dir(key, dir); } } return ret; } ya_result dnskey_delete_public_key_from_dir(dnssec_key *key, const char *dirname) { ya_result ret; char filename[PATH_MAX]; if(ISOK(ret = snformat(filename, sizeof(filename), "%s/K%{dnsname}+%03d+%05d.key", dirname, key->owner_name, key->algorithm, dnskey_get_tag(key) ))) { unlink(filename); ret = ERRNO_ERROR; } return ret; } ya_result dnskey_delete_private_key_from_dir(dnssec_key *key, const char *dirname) { ya_result ret; char filename[PATH_MAX]; if(ISOK(ret = snformat(filename, sizeof(filename), "%s/K%{dnsname}+%03d+%05d.private", dirname, key->owner_name, key->algorithm, dnskey_get_tag(key) ))) { unlink(filename); ret = ERRNO_ERROR; } return ret; } ya_result dnskey_delete_keypair_from_dir(dnssec_key *key, const char *dirname) { ya_result ret1 = dnskey_delete_public_key_from_dir(key, dirname); ya_result ret2 = dnskey_delete_private_key_from_dir(key, dirname); if((ret1 != MAKE_ERRNO_ERROR(EACCES)) && (ret2 != MAKE_ERRNO_ERROR(EACCES))) { return SUCCESS; } else { return MAKE_ERRNO_ERROR(EACCES); } } bool dnskey_is_expired(const dnssec_key *key, time_t now) { return (key->epoch_delete != 0 && key->epoch_delete < now) || (key->epoch_inactive != 0 && key->epoch_inactive < now); } bool dnskey_is_expired_now(const dnssec_key *key) { time_t now = time(NULL); bool ret = dnskey_is_expired(key, now); return ret; } int dnskey_get_size(const dnssec_key *key) { int bits_size = key->vtbl->dnssec_key_size(key); return bits_size; } u16 dnskey_get_flags(const dnssec_key *key) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ); u16 flags = key->flags; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ); return flags; } void dnskey_state_enable(dnssec_key *key, u32 status) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); key->status |= status; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } void dnskey_state_disable(dnssec_key *key, u32 status) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); key->status &= ~status; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } u32 dnskey_state_get(const dnssec_key *key) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ); u32 state = key->status; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ); return state; } /** * Initialises internal info. */ void dnskey_init() { if(dnssec_key_load_private_keywords_set == STRING_SET_EMPTY) { for(int i = 0; dnssec_key_load_private_keywords_common_names[i].data != NULL; i++) { string_node *node = string_set_insert(&dnssec_key_load_private_keywords_set, dnssec_key_load_private_keywords_common_names[i].data); node->value = dnssec_key_load_private_keywords_common_names[i].id; } } } void dnskey_finalize() { string_set_destroy(&dnssec_key_load_private_keywords_set); } /** * Returns true if the key is supposed to have been added in the zone at the chosen time already. * * @param key * @param t * @return */ bool dnskey_is_published(const dnssec_key *key, time_t t) { // there is a publish time and it has occurred if(dnskey_has_explicit_publish(key) && (key->epoch_publish <= t)) { bool ret = !dnskey_is_unpublished(key, t); return ret; } // there is no publish time return !dnskey_is_unpublished(key, t); } /** * Returns true if the key is supposed to have been removed from the zone at the chosen time already. * * @param key * @param t * @return */ bool dnskey_is_unpublished(const dnssec_key *key, time_t t) { // true if and only if there is a removal time that occurred already return dnskey_has_explicit_delete(key) && (key->epoch_delete <= t); } /** * Returns true if the key is supposed to be used for signatures. * * @param key * @param t * @return */ bool dnskey_is_activated(const dnssec_key *key, time_t t) { // there is a active time and it has occurred if(dnskey_has_explicit_activate(key)) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ); time_t epoch_activate = key->epoch_activate; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ); if(epoch_activate <= t) // activation time passed { bool ret = !dnskey_is_deactivated(key, t); // not deactivated yet ? return ret; } return FALSE; // not active yet } else { // no activation defined : active at publication time but only until deactivation return dnskey_is_published(key, t) && !dnskey_is_deactivated(key, t); } } /** * Assumes we are in 'leniency' seconds in the future for activation (and in the present for deactivation) */ bool dnskey_is_activated_lenient(const dnssec_key *key, time_t t, u32 leniency) { // there is a active time and it has occurred if(dnskey_has_explicit_activate(key)) { group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ); time_t epoch_activate = key->epoch_activate; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ); if(epoch_activate <= t + leniency) // activation time passed { bool ret = !dnskey_is_deactivated(key, t); // not deactivated yet ? return ret; } return FALSE; // not active yet } else { // no activation defined : active at publication time but only until deactivation return dnskey_is_published(key, t) && !dnskey_is_deactivated(key, t); } } /** * Returns true if the key must not be used for signatures anymore. * * @param key * @param t * @return */ bool dnskey_is_deactivated(const dnssec_key *key, time_t t) { // there is a inactive time and it has occurred group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_READ); time_t epoch_inactive = key->epoch_inactive; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_READ); if(epoch_inactive > 0) { return (epoch_inactive <= t); } else { // the key has to be activated and not deleted return dnskey_is_unpublished(key, t); } } bool dnskey_has_explicit_publish(const dnssec_key *key) { return (dnskey_state_get(key) & DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH) != 0; } bool dnskey_has_explicit_delete(const dnssec_key *key) { return (dnskey_state_get(key) & DNSKEY_KEY_HAS_SMART_FIELD_DELETE) != 0; } bool dnskey_has_explicit_publish_or_delete(const dnssec_key *key) { return (dnskey_state_get(key) & (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE)) != 0; } bool dnskey_has_explicit_publish_and_delete(const dnssec_key *key) { return (dnskey_state_get(key) & (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE)) == (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE); } bool dnskey_has_explicit_activate(const dnssec_key *key) { return (dnskey_state_get(key) & DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE) != 0; } bool dnskey_has_explicit_deactivate(const dnssec_key *key) { return (dnskey_state_get(key) & DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE) != 0; } bool dnskey_has_activate_and_deactivate(const dnssec_key *key) { return (dnskey_state_get(key) & (DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE)) == (DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE); } bool dnskey_has_activate_or_deactivate(const dnssec_key *key) { return (dnskey_state_get(key) & (DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE)) != 0; } u8 dnskey_supported_algorithm_count() { return sizeof(dnskey_supported_algorithms)/sizeof(dnskey_supported_algorithms[0]); } const dnskey_features* dnskey_supported_algorithm_by_index(u8 index) { if(index < dnskey_supported_algorithm_count()) { const dnskey_features* ret = &dnskey_supported_algorithms[index]; return ret; } return NULL; } const dnskey_features* dnskey_supported_algorithm(u8 algorithm) { for(int i = 0; i < dnskey_supported_algorithm_count(); ++i) { const dnskey_features* ret = &dnskey_supported_algorithms[i]; if(ret->algorithm == algorithm) { return ret; } } return NULL; } ya_result dnskey_newinstance(u32 size, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key) { if(size > DNSSEC_MAXIMUM_KEY_SIZE) { return DNSSEC_ERROR_KEYISTOOBIG; } ya_result ret; switch(algorithm) { case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: ret = dnskey_rsa_newinstance(size, algorithm, flags, origin, out_key); break; case DNSKEY_ALGORITHM_DSASHA1: case DNSKEY_ALGORITHM_DSASHA1_NSEC3: ret = dnskey_dsa_newinstance(size, algorithm, flags, origin, out_key); break; #if DNSCORE_HAS_ECDSA_SUPPORT case DNSKEY_ALGORITHM_ECDSAP256SHA256: case DNSKEY_ALGORITHM_ECDSAP384SHA384: ret = dnskey_ecdsa_newinstance(size, algorithm, flags, origin, out_key); break; #endif #if DNSCORE_HAS_EDDSA_SUPPORT case DNSKEY_ALGORITHM_ED25519: case DNSKEY_ALGORITHM_ED448: ret = dnskey_eddsa_newinstance(size, algorithm, flags, origin, out_key); break; #endif #ifdef DNSKEY_ALGORITHM_DUMMY case DNSKEY_ALGORITHM_DUMMY: ret = dnskey_dummy_newinstance(size, algorithm, flags, origin, out_key); break; #endif default: ret = DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; break; } if(ISOK(ret)) { time_t now = time(NULL); group_mutex_lock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); (*out_key)->epoch_created = now; (*out_key)->status |= DNSKEY_KEY_HAS_SMART_FIELD_CREATED; group_mutex_unlock(&dnskey_rc_mtx, GROUP_MUTEX_WRITE); } return ret; } void dnskey_init_dns_resource_record(dnssec_key *key, s32 ttl, dns_resource_record *rr) { u8 rdata[8191]; u32 rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, sizeof(rdata)); dns_resource_record_init_record(rr, dnskey_get_domain(key), TYPE_DNSKEY, CLASS_IN, ttl, rdata_size, rdata); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dnskey-keyring.c0000644000000000000000000000013214505005532022437 xustar000000000000000030 mtime=1695812442.367981114 30 atime=1695812445.791030139 30 ctime=1695812494.547728433 yadifa-2.6.5-11201/lib/dnscore/src/dnskey-keyring.c0000664000374500037450000003307014505005532022404 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @addtogroup dnskey DNSKEY functions * @brief * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ /* #include #include */ #include "dnscore/dnscore-config.h" #include "dnscore/dnskey-keyring.h" #include "dnscore/logger.h" #include "dnscore/message.h" #include "dnscore/packet_reader.h" #define MODULE_MSG_HANDLE g_system_logger ya_result dnskey_keyring_init(dnskey_keyring *ks) { u32_set_init(&ks->tag_to_key); mutex_init(&ks->mtx); return SUCCESS; } static void dnskey_keyring_finalize_callback(u32_node *node) { dnssec_key* key; key = (dnssec_key*)node->value; dnskey_release(key); node->value = NULL; } void dnskey_keyring_finalize(dnskey_keyring *ks) { u32_set_callback_and_destroy(&ks->tag_to_key, dnskey_keyring_finalize_callback); mutex_destroy(&ks->mtx); } ya_result dnskey_keyring_add(dnskey_keyring *ks, dnssec_key* key) { u32 hash = key->algorithm; hash <<= 16; hash |= key->tag; mutex_lock(&ks->mtx); u32_node *node = u32_set_insert(&ks->tag_to_key, hash); if(node->value == NULL) { dnskey_acquire(key); node->value = key; mutex_unlock(&ks->mtx); return SUCCESS; } else { mutex_unlock(&ks->mtx); return DNSSEC_ERROR_KEYRING_ALGOTAG_COLLISION; } } ya_result dnskey_keyring_add_from_nameserver(dnskey_keyring *ks, const host_address *ha, const u8 *domain) { message_data *query = message_new_instance(); ya_result ret; log_debug("%{dnsname}: fetching public keys from %{hostaddr}", domain, ha); message_make_query(query, (u16)rand(), domain, TYPE_DNSKEY, CLASS_IN); if(ISOK(ret = message_query(query, ha))) { if(message_get_rcode(query) == RCODE_OK) { log_debug("%{dnsname}: %{hostaddr} answered", domain, ha); if(message_get_query_count(query) == 1) { u16 answers; if((answers = message_get_answer_count(query)) > 0) { // extract all keys packet_unpack_reader_data purd; packet_reader_init_from_message(&purd, query); packet_reader_skip_fqdn(&purd); // checked below packet_reader_skip(&purd, 4); // checked below if(!packet_reader_eof(&purd)) { int keys_added = 0; for(u16 i = 0; i < answers; ++i) { dnssec_key *key = NULL; u16 rtype; u16 rclass; s32 rttl; u16 rdata_size; u8 rdata[1024]; if(FAIL(packet_reader_read_fqdn(&purd, rdata, sizeof(rdata)))) { log_info("%{dnsname}: %{hostaddr} message FORMERR)", domain, ha); keys_added = MAKE_DNSMSG_ERROR(RCODE_FORMERR); break; } if(dnslabel_equals_ignorecase_left(domain, rdata)) { if(packet_reader_available(&purd) <= 10) { log_info("%{dnsname}: %{hostaddr} message FORMERR)", domain, ha); keys_added = MAKE_DNSMSG_ERROR(RCODE_FORMERR); break; } // unchecked because we did just that packet_reader_read_u16_unchecked(&purd, &rtype); // checked packet_reader_read_u16_unchecked(&purd, &rclass); // checked packet_reader_read_s32_unchecked(&purd, &rttl); // checked packet_reader_read_u16_unchecked(&purd, &rdata_size); // checked rdata_size = ntohs(rdata_size); if(rtype == TYPE_DNSKEY) { if(ISOK(ret = packet_reader_read_rdata(&purd, rtype, rdata_size, rdata, rdata_size))) { if(ISOK(ret = dnskey_new_from_rdata(rdata, rdata_size, domain, &key))) { if(ISOK(ret = dnskey_keyring_add(ks, key))) { log_info("%{dnsname}: %{hostaddr} added dnskey %{dnsname}: +%03d+%05d/%d added", domain, ha, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); ++keys_added; } else { log_warn("%{dnsname}: %{hostaddr} failed to add dnskey %{dnsname}: +%03d+%05d/%d: %r", domain, ha, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)), ret); } dnskey_release(key); } else { log_warn("%{dnsname}: %{hostaddr} cannot convert rdata to a dnskey: %r", domain, ha, ret); } } else { log_warn("%{dnsname}: %{hostaddr} cannot parse rdata: %r", domain, ha, ret); } } else { // not a DNSKEY: skip if(FAIL(packet_reader_skip(&purd, rdata_size))) { log_info("%{dnsname}: %{hostaddr} message FORMERR)", domain, ha); keys_added = MAKE_DNSMSG_ERROR(RCODE_FORMERR); break; } } } else { log_warn("%{dnsname}: %{hostaddr} wrong domain for key: %{dnsname}", domain, ha, rdata); } } // for all records in answer ret = keys_added; } else { ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } else { log_debug("%{dnsname}: %{hostaddr} has no keys", domain, ha); } } else { log_err("%{dnsname}: %{hostaddr} message is broken (QR != 1)", domain, ha); } } else { log_err("%{dnsname}: %{hostaddr} answered with rcode %s", domain, ha, dns_message_rcode_get_name(message_get_rcode(query))); } } else { log_err("%{dnsname}: %{hostaddr} query error: %r", domain, ha, ret); } message_free(query); return ret; } bool dnskey_keyring_remove(dnskey_keyring *ks, u8 algorithm, u16 tag, const u8 *domain) { u32 hash = algorithm; hash <<= 16; hash |= tag; mutex_lock(&ks->mtx); u32_node *node = u32_set_find(&ks->tag_to_key, hash); if(node != NULL) { dnssec_key *key = (dnssec_key*)node->value; if((key != NULL) && dnsname_equals(key->owner_name, domain)) { dnskey_release(key); u32_set_delete(&ks->tag_to_key, hash); mutex_unlock(&ks->mtx); return TRUE; } } mutex_unlock(&ks->mtx); return FALSE; } dnssec_key* dnskey_keyring_acquire(dnskey_keyring *ks, u8 algorithm, u16 tag, const u8 *domain) { u32 hash = algorithm; hash <<= 16; hash |= tag; mutex_lock(&ks->mtx); u32_node *node = u32_set_find(&ks->tag_to_key, hash); if(node != NULL) { dnssec_key *key = (dnssec_key*)node->value; if((key != NULL) && dnsname_equals(key->owner_name, domain)) { dnskey_acquire(key); mutex_unlock(&ks->mtx); return key; } } mutex_unlock(&ks->mtx); return NULL; } dnssec_key* dnskey_keyring_acquire_by_index(dnskey_keyring *ks, u8 algorithm, u16 tag, const u8 *domain) { u32 hash = algorithm; hash <<= 16; hash |= tag; mutex_lock(&ks->mtx); u32_node *node = u32_set_find(&ks->tag_to_key, hash); if(node != NULL) { dnssec_key *key = (dnssec_key*)node->value; if((key != NULL) && dnsname_equals(key->owner_name, domain)) { dnskey_acquire(key); mutex_unlock(&ks->mtx); return key; } } mutex_unlock(&ks->mtx); return NULL; } /** * * Returns TRUE iff the keyring contains a key matching the parameters * * @param ks * @param algorithm * @param tag * @param domain * @return */ bool dnskey_keyring_has_key(dnskey_keyring *ks, u8 algorithm, u16 tag, const u8 *domain) { u32 hash = algorithm; hash <<= 16; hash |= tag; mutex_lock(&ks->mtx); u32_node *node = u32_set_find(&ks->tag_to_key, hash); if(node != NULL) { dnssec_key *key = (dnssec_key*)node->value; if((key != NULL) && dnsname_equals(key->owner_name, domain)) { mutex_unlock(&ks->mtx); return TRUE; } } mutex_unlock(&ks->mtx); return FALSE; } static void dnskey_keyring_destroy_callback(u32_node *node) { /// @note mutex has been locked by the caller dnssec_key *key = (dnssec_key*)node->value; dnskey_release(key); } void dnskey_keyring_destroy(dnskey_keyring *ks) { mutex_lock(&ks->mtx); u32_set_callback_and_destroy(&ks->tag_to_key, dnskey_keyring_destroy_callback); mutex_unlock(&ks->mtx); mutex_destroy(&ks->mtx); } bool dnskey_keyring_isempty(dnskey_keyring *ks) { mutex_lock(&ks->mtx); bool ret = u32_set_isempty(&ks->tag_to_key); mutex_unlock(&ks->mtx); return ret; } dnssec_key * dnskey_keyring_acquire_key_at_index(dnskey_keyring *ks, int index) { u32_set_iterator iter; u32_set_iterator_init(&ks->tag_to_key, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); if(--index < 0) { dnssec_key *key = (dnssec_key*)node->value; dnskey_acquire(key); return key; } } return NULL; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dnskey_dsa.c0000644000000000000000000000013214505005532021620 xustar000000000000000030 mtime=1695812442.466982532 30 atime=1695812445.795030196 30 ctime=1695812494.549728461 yadifa-2.6.5-11201/lib/dnscore/src/dnskey_dsa.c0000664000374500037450000005571414505005532021576 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #include #include "dnscore/openssl.h" #include "dnscore/dnscore.h" #include "dnscore/sys_types.h" #include "dnscore/base64.h" #include "dnscore/logger.h" #include "dnscore/dnskey.h" #include "dnscore/dnskey_dsa.h" #include "dnscore/dnssec_errors.h" #include "dnscore/zalloc.h" #define MODULE_MSG_HANDLE g_system_logger #define KEYDSA_TAG 0x5f41534459454b #ifndef SSL_API #error "SSL_API not defined" #endif #if SSL_API_LT_110 /* * Backward-compatible interface for 0.9.x */ #define SSL_FIELD_GET(st_,f_) if(f_ != NULL) { *f_ = st_->f_; } #define SSL_FIELD_SET(st_,f_) if(f_ != NULL) { BN_free(st_->f_); st_->f_ = f_; } #define SSL_FIELD_SET_FAIL(st_,f_) (st_->f_ == NULL && f_ == NULL) static void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { SSL_FIELD_GET(d,p) SSL_FIELD_GET(d,q) SSL_FIELD_GET(d,g) } static int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) { if(SSL_FIELD_SET_FAIL(d,p) || SSL_FIELD_SET_FAIL(d,q) || SSL_FIELD_SET_FAIL(d,g)) { return 0; } SSL_FIELD_SET(d,p) SSL_FIELD_SET(d,q) SSL_FIELD_SET(d,g) return 1; } const BIGNUM *DSA_get0_p(const DSA *d) { return d->p; } void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) { SSL_FIELD_GET(d,pub_key) SSL_FIELD_GET(d,priv_key) } int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) { if(SSL_FIELD_SET_FAIL(d,pub_key)) { return 0; } SSL_FIELD_SET(d,pub_key) SSL_FIELD_SET(d,priv_key) return 1; } void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **r, const BIGNUM **s) { SSL_FIELD_GET(sig,r) SSL_FIELD_GET(sig,s) } int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) { if(SSL_FIELD_SET_FAIL(sig,r) || SSL_FIELD_SET_FAIL(sig,s)) { return 0; } SSL_FIELD_SET(sig,r) SSL_FIELD_SET(sig,s) return 1; } #elif SSL_API_LT_111 const BIGNUM *DSA_get0_p(const DSA *d) { const BIGNUM *p; const BIGNUM *q; const BIGNUM *g; DSA_get0_pqg(d, &p, &q, &g); return p; } #endif /* * Intermediary key */ struct dnskey_dsa { BIGNUM *p,*q,*g,*pub_key,*priv_key; }; struct dnskey_dsa_const { const BIGNUM *p,*q,*g,*pub_key,*priv_key; }; static void dnskey_dsa_init(struct dnskey_dsa *ydsa) { memset(ydsa, 0, sizeof(struct dnskey_dsa)); } static bool dnskey_dsa_to_dsa(struct dnskey_dsa *ydsa, DSA *dsa) { if(DSA_set0_pqg(dsa, ydsa->p, ydsa->q, ydsa->g) != 0) { ydsa->p = NULL; ydsa->q = NULL; ydsa->g = NULL; if(DSA_set0_key(dsa, ydsa->pub_key, ydsa->priv_key) != 0) { ydsa->pub_key = NULL; ydsa->priv_key = NULL; return TRUE; } } return FALSE; } static void dnskey_dsa_from_dsa(struct dnskey_dsa_const *ydsa, const DSA *dsa) { DSA_get0_pqg(dsa, &ydsa->p, &ydsa->q, &ydsa->g); DSA_get0_key(dsa, &ydsa->pub_key, &ydsa->priv_key); } static void dnskey_dsa_finalize(struct dnskey_dsa *ydsa) { if(ydsa->p != NULL) BN_free(ydsa->p); if(ydsa->q != NULL) BN_free(ydsa->q); if(ydsa->g != NULL) BN_free(ydsa->g); if(ydsa->pub_key != NULL) BN_free(ydsa->pub_key); if(ydsa->priv_key != NULL) BN_free(ydsa->priv_key); dnskey_dsa_init(ydsa); } static const struct dnskey_field_access DSA_field_access[] = { {"Prime(p)", offsetof(struct dnskey_dsa,p), STRUCTDESCRIPTOR_BN}, {"Subprime(q)", offsetof(struct dnskey_dsa,q), STRUCTDESCRIPTOR_BN}, {"Base(g)", offsetof(struct dnskey_dsa,g), STRUCTDESCRIPTOR_BN}, {"Private_value(x)", offsetof(struct dnskey_dsa,priv_key), STRUCTDESCRIPTOR_BN}, {"Public_value(y)", offsetof(struct dnskey_dsa,pub_key), STRUCTDESCRIPTOR_BN}, {"", 0, 0} }; static int dnskey_dsa_getnid(u8 algorithm) { switch(algorithm) { case DNSKEY_ALGORITHM_DSASHA1_NSEC3: case DNSKEY_ALGORITHM_DSASHA1: { return NID_sha1; } default: { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } } } static DSA* dnskey_dsa_genkey(u32 size) { yassert(size >= DNSSEC_MINIMUM_KEY_SIZE && size <= DNSSEC_MAXIMUM_KEY_SIZE); int err; DSA* dsa; #if SSL_API_LT_110 dsa = DSA_generate_parameters(size, NULL,0, NULL, NULL, NULL, NULL); #else dsa = DSA_new(); DSA_generate_parameters_ex(dsa, size, NULL, 0, NULL, NULL, NULL); #endif yassert(dsa != NULL); err = DSA_generate_key(dsa); /* no callback */ if(err == 0) { // error DSA_free(dsa); dsa = NULL; } return dsa; } static ya_result dnskey_dsa_signdigest(const dnssec_key *key, const u8 *digest, u32 digest_len, u8 *output_) { u8 *output = output_; DSA_SIG *sig = DSA_do_sign(digest, digest_len, key->key.dsa); if(sig != NULL) { const BIGNUM *sig_r; const BIGNUM *sig_s; const BIGNUM *p; p = DSA_get0_p(key->key.dsa); DSA_SIG_get0(sig, &sig_r, &sig_s); u32 p_size_bytes = BN_num_bytes(p); u32 t = (p_size_bytes - 64) >> 3; *output++ = t; const int bn_size = 20; int r_size = BN_num_bytes(sig_r); int r_pad = bn_size - r_size; memset(output, 0, r_pad); BN_bn2bin(sig_r, &output[r_pad]); output += bn_size; int s_size = BN_num_bytes(sig_s); int s_pad = bn_size - s_size; memset(output, 0, s_pad); BN_bn2bin(sig_s, &output[s_pad]); // output += bn_size; DSA_SIG_free(sig); //ya_result output_size = (rn << 1) + 1; ya_result output_size = 20 * 2 + 1; #if DEBUG if(!key->vtbl->dnssec_key_verify_digest(key, digest, digest_len, output_, output_size)) { log_err("CANNOT VERIFY OWN SIGNATURE!"); } #endif return output_size; } else { unsigned long ssl_err; while((ssl_err = ERR_get_error()) != 0) { char buffer[256]; ERR_error_string_n(ssl_err, buffer, sizeof(buffer)); log_err("dsa: sign: %{dnsname}/%05d: error %08x %s", key->owner_name, key->tag, ssl_err, buffer); } ERR_clear_error(); return DNSSEC_ERROR_DSASIGNATUREFAILED; } } static bool dnskey_dsa_verifydigest(const dnssec_key *key, const u8 *digest, u32 digest_len, const u8 *signature, u32 signature_len) { yassert(signature_len <= DNSSEC_MAXIMUM_KEY_SIZE_BYTES); #if DEBUG log_debug6("dsa_verifydigest(K%{dnsname}-%03d-%05d, @%p, @%p)", key->owner_name, key->algorithm, key->tag, digest, signature); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, digest, digest_len, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, signature, signature_len, 32); #endif if(signature_len != 41) { log_warn("DSA signature expected to be 41 bytes long"); } if((signature_len & 1) == 0) { log_err("DSA signature size expected to be an odd number"); return FALSE; } u8 t = *signature++; if(t != 8) { log_warn("DSA T!=8 (%i)", t); } signature_len--; signature_len >>= 1; DSA_SIG *sig = DSA_SIG_new(); BIGNUM *sig_r = BN_bin2bn(signature, signature_len, NULL); signature += signature_len; BIGNUM *sig_s = BN_bin2bn(signature, signature_len, NULL); DSA_SIG_set0(sig, sig_r, sig_s); int err = DSA_do_verify(digest, digest_len, sig, key->key.dsa); DSA_SIG_free(sig); if(err != 1) { unsigned long ssl_err; while((ssl_err = ERR_get_error()) != 0) { char buffer[256]; ERR_error_string_n(ssl_err, buffer, sizeof(buffer)); log_debug("dsa: verify: %{dnsname}/%05d: error %08x %s", key->owner_name, key->tag, ssl_err, buffer); } ERR_clear_error(); return FALSE; } return TRUE; } static DSA* dnskey_dsa_public_load(const u8* rdata, u16 rdata_size) { if(rdata == NULL) { return NULL; } const u8 *inptr = rdata; u32 t; t = *inptr; u32 pgy_len = 64 + (t << 3); if(rdata_size != 1 + 20 + 3 * pgy_len) { return NULL; } inptr++; BIGNUM* dsa_q; BIGNUM* dsa_p; BIGNUM* dsa_g; BIGNUM* dsa_pub_key; dsa_q = BN_bin2bn(inptr, 20, NULL); if(dsa_q == NULL) { log_err("dsa_public_load: NULL q"); return NULL; } inptr += 20; dsa_p = BN_bin2bn(inptr, pgy_len, NULL); if(dsa_p == NULL) { log_err("dsa_public_load: NULL p"); BN_free(dsa_q); return NULL; } inptr += pgy_len; dsa_g = BN_bin2bn(inptr, pgy_len, NULL); if(dsa_g == NULL) { log_err("dsa_public_load: NULL g"); BN_free(dsa_q); BN_free(dsa_p); return NULL; } inptr += pgy_len; dsa_pub_key = BN_bin2bn(inptr, pgy_len, NULL); if(dsa_pub_key == NULL) { log_err("dsa_public_load: NULL y"); BN_free(dsa_q); BN_free(dsa_p); BN_free(dsa_g); return NULL; } DSA* dsa; dsa = DSA_new(); yassert(dsa != NULL); DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g); DSA_set0_key(dsa, dsa_pub_key, NULL); return dsa; } static u32 dnskey_dsa_public_store(DSA* dsa, u8* output_buffer, u32 output_buffer_size) { unsigned char* outptr = output_buffer; const BIGNUM* q = NULL; const BIGNUM* p = NULL; const BIGNUM* g = NULL; const BIGNUM* y = NULL; DSA_get0_pqg(dsa, &p, &q, &g); DSA_get0_key(dsa, &y, NULL); u32 q_n = BN_num_bytes(q); if(q_n != 20) { return 0; } s32 p_n = BN_num_bytes(p); s32 g_n = BN_num_bytes(g); s32 y_n = BN_num_bytes(y); if((abs(p_n - g_n) > 2) || (abs(p_n - y_n) > 2)) /* sometimes, there is one byte difference in storage */ { log_err("dnskey_dsa_public_store: DSA key size discrepancy"); return 0; } s32 t = p_n; t -= 64; if(t < 0) { return 0; } if((t & 7) != 0) { return 0; } t >>= 3; if(t + q_n + p_n + g_n + y_n > output_buffer_size) { return 0; // BUFFER_WOULD_OVERFLOW; } *outptr++ = t; BN_bn2bin(q, outptr); outptr += q_n; BN_bn2bin(p, outptr); outptr += p_n; BN_bn2bin(g, outptr); outptr += g_n; BN_bn2bin(y, outptr); outptr += y_n; return outptr - output_buffer; } static u32 dnskey_dsa_dnskey_public_store(const dnssec_key* key, u8 *rdata, size_t rdata_size) { u32 len; SET_U16_AT(rdata[0], key->flags); rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = key->algorithm; len = dnskey_dsa_public_store(key->key.dsa, &rdata[4], rdata_size - 4) + 4; return len; } static u32 dnskey_dsa_size(const dnssec_key* key) { const BIGNUM* y; DSA_get0_key(key->key.dsa, &y, NULL); u32 y_n = BN_num_bytes(y); return y_n << 3; } static u32 dnskey_dsa_public_size(const DSA* dsa) { const BIGNUM* p; const BIGNUM* q; const BIGNUM* g; const BIGNUM* y; DSA_get0_pqg(dsa, &p, &q, &g); DSA_get0_key(dsa, &y, NULL); u32 p_n = BN_num_bytes(p); u32 q_n = BN_num_bytes(q); u32 g_n = BN_num_bytes(g); u32 y_n = BN_num_bytes(y); return 1 + p_n + q_n + g_n + y_n; } static u32 dnskey_dsa_dnskey_rdatasize(const dnssec_key* key) { return dnskey_dsa_public_size(key->key.dsa) + 4; } static void dnskey_dsa_free(dnssec_key* key) { DSA* dsa = key->key.dsa; DSA_free(dsa); key->key.dsa = NULL; } static bool dnskey_dsa_equals(const dnssec_key* key_a, const dnssec_key* key_b) { /* DSA, compare modulus and exponent, exponent first (it's the smallest) */ if(key_a == key_b) { return TRUE; } if(dnssec_key_tag_field_set(key_a) && dnssec_key_tag_field_set(key_b)) { if(key_a->tag != key_b->tag) { return FALSE; } } if((key_a->flags == key_b->flags) && (key_a->algorithm == key_b->algorithm)) { if(strcmp(key_a->origin, key_b->origin) == 0) { const DSA* a_dsa = key_a->key.dsa; const DSA* b_dsa = key_b->key.dsa; const BIGNUM* a_dsa_q; const BIGNUM* a_dsa_p; const BIGNUM* a_dsa_g; const BIGNUM* b_dsa_q; const BIGNUM* b_dsa_p; const BIGNUM* b_dsa_g; DSA_get0_pqg(a_dsa, &a_dsa_p, &a_dsa_q, &a_dsa_g); DSA_get0_pqg(b_dsa, &b_dsa_p, &b_dsa_q, &b_dsa_g); if(BN_cmp(a_dsa_q, b_dsa_q) == 0) { if(BN_cmp(a_dsa_p, b_dsa_p) == 0) { if(BN_cmp(a_dsa_g, b_dsa_g) == 0) { const BIGNUM* a_dsa_pub_key; const BIGNUM* a_dsa_priv_key; const BIGNUM* b_dsa_pub_key; const BIGNUM* b_dsa_priv_key; DSA_get0_key(a_dsa, &a_dsa_pub_key, &a_dsa_priv_key); DSA_get0_key(b_dsa, &b_dsa_pub_key, &b_dsa_priv_key); if(BN_cmp(a_dsa_pub_key, b_dsa_pub_key) == 0) { if(a_dsa_priv_key != NULL) { if(b_dsa_priv_key != NULL) { return BN_cmp(a_dsa_priv_key, b_dsa_priv_key) == 0; } } else { return b_dsa_priv_key == NULL; } } } } } } } return FALSE; } static ya_result dnskey_dsa_private_print_fields(dnssec_key *key, output_stream *os) { struct dnskey_dsa_const ydsa; dnskey_dsa_from_dsa(&ydsa, key->key.dsa); ya_result ret = dnskey_field_access_print(DSA_field_access, &ydsa, os); return ret; } static const dnssec_key_vtbl dsa_vtbl = { dnskey_dsa_signdigest, dnskey_dsa_verifydigest, dnskey_dsa_dnskey_rdatasize, dnskey_dsa_dnskey_public_store, dnskey_dsa_free, dnskey_dsa_equals, dnskey_dsa_private_print_fields, dnskey_dsa_size, "DSA" }; static ya_result dnskey_dsa_initinstance(DSA* dsa, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key) { int nid; u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; /* 4096 bits -> 1KB */ *out_key = NULL; if(FAIL(nid = dnskey_dsa_getnid(algorithm))) { return nid; } #if DEBUG memset(rdata, 0xff, sizeof(rdata)); #endif u32 rdata_size = dnskey_dsa_public_size(dsa); if(rdata_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES) { return DNSSEC_ERROR_KEYISTOOBIG; } SET_U16_AT(rdata[0], flags); // NATIVEFLAGS rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = algorithm; u32 stored_rdata_size = dnskey_dsa_public_store(dsa, &rdata[4], sizeof(rdata) - 4); if(stored_rdata_size != rdata_size) { return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */ } /* Note : + 4 because of the flags,protocol & algorithm bytes * are not taken in account */ u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size + 4); dnssec_key* key = dnskey_newemptyinstance(algorithm, flags, origin); // RC if(key == NULL) { return INVALID_ARGUMENT_ERROR; } key->key.dsa = dsa; key->vtbl = &dsa_vtbl; key->tag = tag; key->nid = nid; const BIGNUM *dsa_priv_key = NULL; DSA_get0_key(dsa, NULL, &dsa_priv_key); if(dsa_priv_key != NULL) { key->status |= DNSKEY_KEY_IS_PRIVATE; } *out_key = key; return SUCCESS; } static ya_result dnskey_dsa_parse_field(struct dnskey_field_parser *parser, parser_s *p) { struct dnskey_dsa *ydsa = (struct dnskey_dsa*)parser->data; ya_result ret = dnskey_field_access_parse(DSA_field_access, ydsa, p); return ret; } static ya_result dnskey_dsa_parse_set_key(struct dnskey_field_parser *parser, dnssec_key *key) { struct dnskey_dsa *ydsa = (struct dnskey_dsa*)parser->data; if(key == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } switch(key->algorithm) { case DNSKEY_ALGORITHM_DSASHA1_NSEC3: case DNSKEY_ALGORITHM_DSASHA1: break; default: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } if((ydsa->p == NULL) || (ydsa->q == NULL) || (ydsa->g == NULL) || (ydsa->pub_key == NULL)) { return DNSSEC_ERROR_INCOMPLETEKEY; } int nid; if(FAIL(nid = dnskey_dsa_getnid(key->algorithm))) { return nid; } bool has_private = ydsa->priv_key != NULL; if(key->key.dsa == NULL) { key->key.dsa = DSA_new(); key->vtbl = &dsa_vtbl; } if(dnskey_dsa_to_dsa(ydsa, key->key.dsa)) { // at this point, ydsa has been emptied DSA *dsa = key->key.dsa; u32 rdata_size = dnskey_dsa_public_size(dsa); u16 tag; u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; if(rdata_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES) { return DNSSEC_ERROR_KEYISTOOBIG; } SET_U16_AT(rdata[0], key->flags); rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = key->algorithm; if(dnskey_dsa_public_store(dsa, &rdata[4], sizeof(rdata) - 4) != rdata_size) { return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */ } /* Note : + 4 because of the flags,protocol & algorithm bytes * are not taken in account */ tag = dnskey_get_tag_from_rdata(rdata, rdata_size + 4); key->tag = tag; key->nid = nid; key->status |= DNSKEY_KEY_IS_VALID; if(has_private) { key->status |= DNSKEY_KEY_IS_PRIVATE; } return SUCCESS; } else { return DNSSEC_ERROR_INCOMPLETEKEY; } } static void dnskey_dsa_parse_finalize(struct dnskey_field_parser *parser) { struct dnskey_dsa *ydsa = (struct dnskey_dsa*)parser->data; if(ydsa != NULL) { dnskey_dsa_finalize(ydsa); ZFREE(ydsa, struct dnskey_dsa); } } static const struct dnskey_field_parser_vtbl dsa_field_parser_vtbl = { dnskey_dsa_parse_field, dnskey_dsa_parse_set_key, dnskey_dsa_parse_finalize, "DSA" }; void dnskey_dsa_parse_init(dnskey_field_parser *fp) { struct dnskey_dsa *ydsa; ZALLOC_OBJECT_OR_DIE(ydsa, struct dnskey_dsa, KEYDSA_TAG); ZEROMEMORY(ydsa, sizeof(struct dnskey_dsa)); fp->data = ydsa; fp->vtbl = &dsa_field_parser_vtbl; } ya_result dnskey_dsa_loadpublic(const u8 *rdata, u16 rdata_size, const char *origin, dnssec_key** out_key) { *out_key = NULL; if(rdata == NULL || rdata_size <= 6 || origin == NULL) { /* bad */ return UNEXPECTED_NULL_ARGUMENT_ERROR; } u16 flags = GET_U16_AT(rdata[0]); u8 algorithm = rdata[3]; if((algorithm != DNSKEY_ALGORITHM_DSASHA1_NSEC3) && (algorithm != DNSKEY_ALGORITHM_DSASHA1)) { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } rdata += 4; rdata_size -= 4; ya_result return_value = DNSSEC_ERROR_CANNOT_READ_KEY_FROM_RDATA; DSA *dsa = dnskey_dsa_public_load(rdata, rdata_size); if(dsa != NULL) { dnssec_key *key; if(ISOK(return_value = dnskey_dsa_initinstance(dsa, algorithm, flags, origin, &key))) { *out_key = key; return return_value; } DSA_free(dsa); } return return_value; } ya_result dnskey_dsa_newinstance(u32 size, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key) { *out_key = NULL; if(size > DNSSEC_MAXIMUM_KEY_SIZE) { return DNSSEC_ERROR_KEYISTOOBIG; } if((algorithm != DNSKEY_ALGORITHM_DSASHA1_NSEC3) && (algorithm != DNSKEY_ALGORITHM_DSASHA1)) { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } ya_result return_value = DNSSEC_ERROR_KEY_GENERATION_FAILED; DSA *dsa = dnskey_dsa_genkey(size); if(dsa != NULL) { dnssec_key *key; if(ISOK(return_value = dnskey_dsa_initinstance(dsa, algorithm, flags, origin, &key))) { *out_key = key; return return_value; } DSA_free(dsa); } return return_value; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dnskey_ecdsa.c0000644000000000000000000000013114505005532022127 xustar000000000000000030 mtime=1695812442.420981873 30 atime=1695812445.793030168 29 ctime=1695812494.55172849 yadifa-2.6.5-11201/lib/dnscore/src/dnskey_ecdsa.c0000664000374500037450000005150214505005532022075 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @brief * * NOT DONE * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include "dnscore/dnscore-config-features.h" #if DNSCORE_HAS_ECDSA_SUPPORT #include #include #include #include #include #include #include #include //#include #include #include #include #include "dnscore/openssl.h" #include "dnscore/dnscore-config.h" #include "dnscore/dnscore.h" #include "dnscore/sys_types.h" #include "dnscore/base64.h" #include "dnscore/logger.h" #include "dnscore/dnskey.h" #include "dnscore/dnskey_ecdsa.h" #include "dnscore/dnssec_errors.h" #include "dnscore/zalloc.h" #define MODULE_MSG_HANDLE g_system_logger #define KEYECDSA_TAG 0x415344434559454b #ifndef SSL_API #error "SSL_API not defined" #endif #define DNSKEY_ALGORITHM_ECDSAP256SHA256_NID NID_X9_62_prime256v1 #define DNSKEY_ALGORITHM_ECDSAP384SHA384_NID NID_secp384r1 #if SSL_API_LT_110 #define SSL_FIELD_GET(st_,f_) if(f_ != NULL) { *f_ = st_->f_; } #define SSL_FIELD_SET(st_,f_) if(f_ != NULL) { BN_free(st_->f_); st_->f_ = f_; } #define SSL_FIELD_SET_FAIL(st_,f_) (st_->f_ == NULL && f_ == NULL) void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **r, const BIGNUM **s) { SSL_FIELD_GET(sig,r) SSL_FIELD_GET(sig,s) } int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) { if(SSL_FIELD_SET_FAIL(sig,r) || SSL_FIELD_SET_FAIL(sig,s)) { return 0; } SSL_FIELD_SET(sig,r) SSL_FIELD_SET(sig,s) return 1; } #endif /* * Intermediary key */ struct dnskey_ecdsa { BIGNUM *private_key; }; struct dnskey_ecdsa_const { const BIGNUM *private_key; }; static void dnskey_ecdsa_init(struct dnskey_ecdsa *yecdsa) { memset(yecdsa, 0, sizeof(struct dnskey_ecdsa)); } static bool dnskey_ecdsa_to_ecdsa(struct dnskey_ecdsa *yecdsa, EC_KEY *ecdsa) { if(EC_KEY_set_private_key(ecdsa, yecdsa->private_key) != 0) { yecdsa->private_key = NULL; return TRUE; } return FALSE; } static void dnskey_ecdsa_from_ecdsa(struct dnskey_ecdsa_const *yecdsa, const EC_KEY *ecdsa) { yecdsa->private_key = EC_KEY_get0_private_key(ecdsa); } static void dnskey_ecdsa_finalize(struct dnskey_ecdsa *yecdsa) { if(yecdsa->private_key != NULL) BN_free(yecdsa->private_key); dnskey_ecdsa_init(yecdsa); } static const struct dnskey_field_access ECDSA_field_access[] = { {"PrivateKey", offsetof(struct dnskey_ecdsa,private_key), STRUCTDESCRIPTOR_BN}, {"", 0, 0} }; static int dnskey_ecdsa_getnid(u8 algorithm) { switch(algorithm) { case DNSKEY_ALGORITHM_ECDSAP256SHA256: { return DNSKEY_ALGORITHM_ECDSAP256SHA256_NID; } case DNSKEY_ALGORITHM_ECDSAP384SHA384: { return DNSKEY_ALGORITHM_ECDSAP384SHA384_NID; } default: { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } } } static int dnskey_ecdsa_nid_to_signature_bn_size(int nid) { switch(nid) { case DNSKEY_ALGORITHM_ECDSAP256SHA256_NID: { return 32; //64 } case DNSKEY_ALGORITHM_ECDSAP384SHA384_NID: { return 48; // 96 } default: { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } } } static EC_KEY* dnskey_ecdsa_genkey_by_nid(int nid) { //yassert(size == 256 || size == 384); int err; EC_KEY *ecdsa; EC_GROUP *group; if((group = EC_GROUP_new_by_curve_name(nid)) == NULL) { return NULL; } if((ecdsa = EC_KEY_new()) == NULL) { return NULL; } EC_KEY_set_group(ecdsa, group); err = EC_KEY_generate_key(ecdsa); /* no callback */ EC_GROUP_clear_free(group); if(err == 0) { // error EC_KEY_free(ecdsa); ecdsa = NULL; } return ecdsa; } static ya_result dnskey_ecdsa_signdigest(const dnssec_key *key, const u8 *digest, u32 digest_len, u8 *output_) { u8 *output; output = output_; ECDSA_SIG *sig = ECDSA_do_sign(digest, digest_len, key->key.ec); if(sig != NULL) { int bn_size = dnskey_ecdsa_nid_to_signature_bn_size(key->nid); ZEROMEMORY(output, bn_size * 2); const BIGNUM *sig_r; const BIGNUM *sig_s; ECDSA_SIG_get0(sig, &sig_r, &sig_s); int r_size = BN_num_bytes(sig_r); int r_pad = bn_size - r_size; memset(output, 0, r_pad); BN_bn2bin(sig_r, &output[r_pad]); output += bn_size; int s_size = BN_num_bytes(sig_s); int s_pad = bn_size - s_size; memset(output, 0, s_pad); BN_bn2bin(sig_s, &output[s_pad]); //output += bn_size; ECDSA_SIG_free(sig); ya_result output_size = bn_size * 2; // r_size + s_size; return output_size; } else { unsigned long ssl_err; while((ssl_err = ERR_get_error()) != 0) { char buffer[256]; ERR_error_string_n(ssl_err, buffer, sizeof(buffer)); log_err("digest signature returned an ssl error %08x %s", ssl_err, buffer); } ERR_clear_error(); return DNSSEC_ERROR_ECDSASIGNATUREFAILED; } } static bool dnskey_ecdsa_verifydigest(const dnssec_key *key, const u8 *digest, u32 digest_len, const u8 *signature, u32 signature_len) { yassert(signature_len <= DNSSEC_MAXIMUM_KEY_SIZE_BYTES); #if DEBUG log_debug6("ecdsa_verifydigest(K%{dnsname}-%03d-%05d, @%p, @%p)", key->owner_name, key->algorithm, key->tag, digest, signature); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, digest, digest_len, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, signature, signature_len, 32); #endif /* * For P-256, each integer MUST be encoded as 32 octets; * for P-384, each integer MUST be encoded as 48 octets. */ int bn_size = dnskey_ecdsa_nid_to_signature_bn_size(key->nid); if(FAIL(bn_size)) { log_err("EC_KEY getting size for NID returned: %r", bn_size); return FALSE; } if((int)signature_len != bn_size * 2) { log_err("EC_KEY signature size unexpected"); return FALSE; } ECDSA_SIG *sig = ECDSA_SIG_new(); BIGNUM *sig_r = BN_bin2bn(signature, bn_size, NULL); signature += bn_size; BIGNUM *sig_s = BN_bin2bn(signature, bn_size, NULL); ECDSA_SIG_set0(sig, sig_r, sig_s); int err = ECDSA_do_verify(digest, digest_len, sig, key->key.ec); if(err != 1) { unsigned long ssl_err; while((ssl_err = ERR_get_error()) != 0) { char buffer[256]; ERR_error_string_n(ssl_err, buffer, sizeof(buffer)); log_debug("digest verification returned an ssl error %08x %s", ssl_err, buffer); } ECDSA_SIG_free(sig); ERR_clear_error(); return FALSE; } ECDSA_SIG_free(sig); return TRUE; } static EC_KEY* dnskey_ecdsa_public_load(u8 algorithm, const u8* rdata, u16 rdata_size) { EC_KEY *ecdsa; if((ecdsa = EC_KEY_new_by_curve_name(dnskey_ecdsa_getnid(algorithm))) != NULL) { const EC_GROUP *group = EC_KEY_get0_group(ecdsa); EC_POINT *point = EC_POINT_new(group); u8 tmp[512]; tmp[0] = 4; memcpy(&tmp[1], rdata, rdata_size); if(EC_POINT_oct2point(group, point, tmp, rdata_size + 1, NULL) == 1) { EC_KEY_set_public_key(ecdsa, point); EC_POINT_free(point); return ecdsa; } EC_POINT_free(point); EC_KEY_free(ecdsa); } return NULL; } static u32 ecdsa_public_store(const EC_KEY* ecdsa, u8* output_buffer) { const EC_GROUP *group = EC_KEY_get0_group(ecdsa); const EC_POINT *point = EC_KEY_get0_public_key(ecdsa); BN_CTX *ctx = BN_CTX_new(); u8 tmp[512]; size_t size = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, tmp, sizeof(tmp), ctx); assert((size > 0) && (tmp[0] == 4)); memcpy(output_buffer, &tmp[1], size - 1); BN_CTX_free(ctx); return size - 1; } static u32 dnskey_ecdsa_dnskey_public_store(const dnssec_key* key, u8* rdata, size_t rdata_size) { (void)rdata_size; u32 len; SET_U16_AT(rdata[0], key->flags); rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = key->algorithm; len = ecdsa_public_store(key->key.ec, &rdata[4]) + 4; return len; } static u32 dnskey_ecdsa_size(const dnssec_key* key) { const EC_GROUP *group = EC_KEY_get0_group(key->key.ec); const EC_POINT *point = EC_KEY_get0_public_key(key->key.ec); BN_CTX *ctx = BN_CTX_new(); u8 tmp[512]; size_t size = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, tmp, sizeof(tmp), ctx); assert((size > 0) && (tmp[0] == 4)); BN_CTX_free(ctx); return (size - 1) << 2; } /** * Returns the size in byte of the public key. * * @param ecdsa * @return */ static u32 dnskey_ecdsa_public_size(const EC_KEY* ecdsa) { const EC_GROUP *group = EC_KEY_get0_group(ecdsa); const EC_POINT *point = EC_KEY_get0_public_key(ecdsa); BN_CTX *ctx = BN_CTX_new(); u8 tmp[512]; size_t size = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, tmp, sizeof(tmp), ctx); assert((size > 0) && (tmp[0] == 4)); BN_CTX_free(ctx); return size - 1; } static u32 dnskey_ecdsa_dnskey_rdatasize(const dnssec_key* key) { u32 size = dnskey_ecdsa_public_size(key->key.ec) + 4; return size; } static void dnskey_ecdsa_free(dnssec_key* key) { EC_KEY* ecdsa = key->key.ec; EC_KEY_free(ecdsa); key->key.ec = NULL; } static bool dnskey_ecdsa_equals(const dnssec_key *key_a, const dnssec_key *key_b) { /* RSA, compare modulus and exponent, exponent first (it's the smallest) */ if(key_a == key_b) { return TRUE; } if(dnssec_key_tag_field_set(key_a) && dnssec_key_tag_field_set(key_b)) { if(key_a->tag != key_b->tag) { return FALSE; } } if((key_a->flags == key_b->flags) && (key_a->algorithm == key_b->algorithm)) { if(strcmp(key_a->origin, key_b->origin) == 0) { const EC_GROUP *group_a = EC_KEY_get0_group(key_a->key.ec); const EC_GROUP *group_b = EC_KEY_get0_group(key_b->key.ec); BN_CTX *ctx = BN_CTX_new(); if(EC_GROUP_cmp(group_a, group_b, ctx) == 0) { const EC_POINT *point_a = EC_KEY_get0_public_key(key_a->key.ec); const EC_POINT *point_b = EC_KEY_get0_public_key(key_b->key.ec); bool ret = EC_POINT_cmp(group_a, point_a, point_b, ctx); BN_CTX_free(ctx); return ret; } BN_CTX_free(ctx); } } return FALSE; } static ya_result dnskey_ecdsa_print_fields(dnssec_key *key, output_stream *os) { struct dnskey_ecdsa_const yecdsa; dnskey_ecdsa_from_ecdsa(&yecdsa, key->key.ec); ya_result ret = dnskey_field_access_print(ECDSA_field_access, &yecdsa, os); return ret; } static const dnssec_key_vtbl ecdsa_vtbl = { dnskey_ecdsa_signdigest, dnskey_ecdsa_verifydigest, dnskey_ecdsa_dnskey_rdatasize, dnskey_ecdsa_dnskey_public_store, dnskey_ecdsa_free, dnskey_ecdsa_equals, dnskey_ecdsa_print_fields, dnskey_ecdsa_size, "ECDSA" }; static ya_result dnskey_ecdsa_initinstance(EC_KEY *ecdsa, u8 algorithm, u16 flags, const char *origin, dnssec_key **out_key) { int nid; u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; /* 4096 bits -> 1KB */ *out_key = NULL; if(FAIL(nid = dnskey_ecdsa_getnid(algorithm))) { return nid; } #if DEBUG memset(rdata, 0xff, sizeof(rdata)); #endif u32 public_key_size = dnskey_ecdsa_public_size(ecdsa); if(public_key_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES) { return DNSSEC_ERROR_KEYISTOOBIG; } SET_U16_AT(rdata[0], flags); // NATIVEFLAGS rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = algorithm; if(ecdsa_public_store(ecdsa, &rdata[4]) != public_key_size) { return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */ } /* Note : + 4 because of the flags,protocol & algorithm bytes * are not taken in account */ u16 tag = dnskey_get_tag_from_rdata(rdata, public_key_size + 4); dnssec_key* key = dnskey_newemptyinstance(algorithm, flags, origin); // RC if(key == NULL) { return INVALID_ARGUMENT_ERROR; } key->key.ec = ecdsa; key->vtbl = &ecdsa_vtbl; key->tag = tag; key->nid = nid; key->status |= (EC_KEY_get0_private_key(ecdsa) != NULL)?DNSKEY_KEY_IS_PRIVATE:0; *out_key = key; return SUCCESS; } static ya_result dnskey_ecdsa_parse_field(struct dnskey_field_parser *parser, parser_s *p) { struct dnskey_ecdsa *yecdsa = (struct dnskey_ecdsa*)parser->data; ya_result ret = dnskey_field_access_parse(ECDSA_field_access, yecdsa, p); return ret; } static ya_result dnskey_ecdsa_parse_set_key(struct dnskey_field_parser *parser, dnssec_key *key) { struct dnskey_ecdsa *yecdsa = (struct dnskey_ecdsa*)parser->data; if(key == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } switch(key->algorithm) { case DNSKEY_ALGORITHM_ECDSAP256SHA256: case DNSKEY_ALGORITHM_ECDSAP384SHA384: break; default: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } if(yecdsa->private_key == NULL) { return DNSSEC_ERROR_INCOMPLETEKEY; } int nid; if(FAIL(nid = dnskey_ecdsa_getnid(key->algorithm))) { return nid; } const EC_GROUP *group = NULL; if(key->key.ec == NULL) { EC_KEY *ecdsa = EC_KEY_new_by_curve_name(nid); if(ecdsa == NULL) { return DNSSEC_ERROR_INCOMPLETEKEY; } group = EC_KEY_get0_group(ecdsa); if(group == NULL) { return DNSSEC_ERROR_INCOMPLETEKEY; } key->key.ec = ecdsa; key->vtbl = &ecdsa_vtbl; } else { group = EC_KEY_get0_group(key->key.ec); if(group == NULL) { return DNSSEC_ERROR_INCOMPLETEKEY; } } EC_KEY *ecdsa = key->key.ec; const EC_POINT *point; if((point = EC_KEY_get0_public_key(ecdsa)) == NULL) { EC_POINT *gen_point = EC_POINT_new(group); if(EC_POINT_mul(group, gen_point, yecdsa->private_key, NULL, NULL, NULL) == 1) { EC_KEY_set_public_key(ecdsa, gen_point); point = gen_point; } EC_POINT_free(gen_point); } if(point != NULL) { if(dnskey_ecdsa_to_ecdsa(yecdsa, ecdsa) != 0) { // at this point, yecdsa has been emptied u32 rdata_size = dnskey_ecdsa_public_size(ecdsa); u16 tag; u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; if(rdata_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES) { return DNSSEC_ERROR_KEYISTOOBIG; } SET_U16_AT(rdata[0], key->flags); rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = key->algorithm; if(ecdsa_public_store(ecdsa, &rdata[4]) != rdata_size) { return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */ } /* Note : + 4 because of the flags,protocol & algorithm bytes * are not taken in account */ tag = dnskey_get_tag_from_rdata(rdata, rdata_size + 4); key->tag = tag; key->nid = nid; key->status |= DNSKEY_KEY_IS_VALID | DNSKEY_KEY_IS_PRIVATE; return SUCCESS; } } return DNSSEC_ERROR_INCOMPLETEKEY; } static void dnskey_ecdsa_parse_finalize(struct dnskey_field_parser *parser) { struct dnskey_ecdsa *ydsa = (struct dnskey_ecdsa*)parser->data; if(ydsa != NULL) { dnskey_ecdsa_finalize(ydsa); ZFREE(ydsa, struct dnskey_ecdsa); } } static const struct dnskey_field_parser_vtbl ecdsa_field_parser_vtbl = { dnskey_ecdsa_parse_field, dnskey_ecdsa_parse_set_key, dnskey_ecdsa_parse_finalize, "ECDSA" }; void dnskey_ecdsa_parse_init(dnskey_field_parser *fp) { struct dnskey_ecdsa *yecdsa; ZALLOC_OBJECT_OR_DIE(yecdsa, struct dnskey_ecdsa, KEYECDSA_TAG); ZEROMEMORY(yecdsa, sizeof(struct dnskey_ecdsa)); fp->data = yecdsa; fp->vtbl = &ecdsa_field_parser_vtbl; } ya_result dnskey_ecdsa_loadpublic(const u8 *rdata, u16 rdata_size, const char *origin, dnssec_key** out_key) { *out_key = NULL; if(rdata == NULL || rdata_size <= 6 || origin == NULL) { /* bad */ return UNEXPECTED_NULL_ARGUMENT_ERROR; } u16 flags = GET_U16_AT(rdata[0]); u8 algorithm = rdata[3]; if((algorithm != DNSKEY_ALGORITHM_ECDSAP256SHA256) && (algorithm != DNSKEY_ALGORITHM_ECDSAP384SHA384) && (algorithm != DNSKEY_ALGORITHM_ED25519) && (algorithm != DNSKEY_ALGORITHM_ED448)) { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } rdata += 4; rdata_size -= 4; ya_result return_value = DNSSEC_ERROR_CANNOT_READ_KEY_FROM_RDATA; EC_KEY *ecdsa = dnskey_ecdsa_public_load(algorithm, rdata, rdata_size); if(ecdsa != NULL) { dnssec_key *key; if(ISOK(return_value = dnskey_ecdsa_initinstance(ecdsa, algorithm, flags, origin, &key))) { *out_key = key; return return_value; } EC_KEY_free(ecdsa); } return return_value; } ya_result dnskey_ecdsa_newinstance(u32 size, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key) { *out_key = NULL; if(size > DNSSEC_MAXIMUM_KEY_SIZE) { return DNSSEC_ERROR_KEYISTOOBIG; } if((algorithm != DNSKEY_ALGORITHM_ECDSAP256SHA256) && (algorithm != DNSKEY_ALGORITHM_ECDSAP384SHA384) && (algorithm != DNSKEY_ALGORITHM_ED25519) && (algorithm != DNSKEY_ALGORITHM_ED448)) { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } ya_result return_value = DNSSEC_ERROR_KEY_GENERATION_FAILED; //EC_KEY *ecdsa = dnskey_ecdsa_genkey(size); EC_KEY *ecdsa = dnskey_ecdsa_genkey_by_nid(dnskey_ecdsa_getnid(algorithm)); if(ecdsa != NULL) { dnssec_key *key; if(ISOK(return_value = dnskey_ecdsa_initinstance(ecdsa, algorithm, flags, origin, &key))) { *out_key = key; return return_value; } EC_KEY_free(ecdsa); } return return_value; } #else void dnskey_ecdsa_not_supported() {} #endif // HAS_ECDSA_SUPPORT /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dnskey_eddsa.c0000644000000000000000000000013214505005532022131 xustar000000000000000030 mtime=1695812442.508983134 30 atime=1695812445.797030225 30 ctime=1695812494.553728519 yadifa-2.6.5-11201/lib/dnscore/src/dnskey_eddsa.c0000664000374500037450000004350014505005532022075 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @brief * * NOT DONE * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include "dnscore/dnscore-config-features.h" #if DNSCORE_HAS_EDDSA_SUPPORT #include #include #include #include #include #include #include #include #include #include "dnscore/openssl.h" #include "dnscore/dnscore-config.h" #include "dnscore/dnscore.h" #include "dnscore/sys_types.h" // EVP_PKEY_new_raw_public_key #include "dnscore/logger.h" #include "dnscore/dnskey.h" #if DNSCORE_HAS_EDDSA_SUPPORT #include "dnscore/dnskey_eddsa.h" #endif #include "dnscore/dnssec_errors.h" #include "dnscore/zalloc.h" #define MODULE_MSG_HANDLE g_system_logger #define KEYECDSA_TAG 0x415344434559454b #define EDDSABFR_TAG 0x5246424153444445 #ifndef SSL_API #error "SSL_API not defined" #endif #ifdef NID_ED25519 #define DNSKEY_ALGORITHM_ED25519_NID NID_ED25519 #elif defined(NID_Ed25519) #define DNSKEY_ALGORITHM_ED25519_NID NID_Ed25519 #else #error "ED25519 not defined" #endif #ifdef NID_ED448 #define DNSKEY_ALGORITHM_ED448_NID NID_ED448 #elif defined(NID_Ed448) #define DNSKEY_ALGORITHM_ED448_NID NID_Ed448 #else #error "ED448 not defined" #endif /* * Intermediary key */ struct dnskey_eddsa { dnskey_raw_field_t private_key; }; struct dnskey_eddsa_const { const dnskey_raw_field_t private_key; }; static void dnskey_eddsa_init(struct dnskey_eddsa *yeddsa) { memset(yeddsa, 0, sizeof(struct dnskey_eddsa)); } static void dnskey_eddsa_from_eddsa(struct dnskey_eddsa *yeddsa, const EVP_PKEY *eddsa) { u8 *buffer; size_t size; if(EVP_PKEY_get_raw_private_key(eddsa, NULL, &size) == 1) { ZALLOC_OBJECT_ARRAY_OR_DIE(buffer, u8, size, EDDSABFR_TAG); EVP_PKEY_get_raw_private_key(eddsa, buffer, &size); yeddsa->private_key.buffer = buffer; yeddsa->private_key.size = size; } } static void dnskey_eddsa_finalize(struct dnskey_eddsa *yeddsa) { if(yeddsa->private_key.buffer != NULL) { ZEROMEMORY(yeddsa->private_key.buffer, yeddsa->private_key.size); ZFREE_ARRAY(yeddsa->private_key.buffer, yeddsa->private_key.size); } dnskey_eddsa_init(yeddsa); } static const struct dnskey_field_access ECDSA_field_access[] = { {"PrivateKey", offsetof(struct dnskey_eddsa,private_key), STRUCTDESCRIPTOR_RAW}, {"", 0, STRUCTDESCRIPTOR_NONE} }; static int dnskey_eddsa_getnid(u8 algorithm) { switch(algorithm) { case DNSKEY_ALGORITHM_ED25519: { return DNSKEY_ALGORITHM_ED25519_NID; } case DNSKEY_ALGORITHM_ED448: { return DNSKEY_ALGORITHM_ED448_NID; } default: { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } } } #if 0 static int dnskey_eddsa_getnid_by_size(u32 size) { switch(size) { case 256: { return DNSKEY_ALGORITHM_ED25519_NID; } case 456: { return DNSKEY_ALGORITHM_ED448_NID; } default: { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } } } #endif static int dnskey_eddsa_nid_to_signature_bn_size(int nid) { switch(nid) { case DNSKEY_ALGORITHM_ED25519_NID: { return 32 * 2; } case DNSKEY_ALGORITHM_ED448_NID: { return 57 * 2; } default: { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } } } static ya_result dnskey_eddsa_signdigest(const dnssec_key *key, const u8 *digest, u32 digest_len, u8 *output) { ya_result ret; EVP_MD_CTX *ctx = EVP_MD_CTX_new(); if(ctx != NULL) { if(EVP_DigestSignInit(ctx, NULL, NULL, NULL, key->key.ed) == 1) { size_t output_size = DIGEST_BUFFER_SIZE; if(EVP_DigestSign(ctx, output, &output_size, digest, digest_len) == 1) { ret = (ya_result)output_size; } else { ret = ya_ssl_error(); } } else { ret = ya_ssl_error(); } EVP_MD_CTX_free(ctx); } else { ret = ya_ssl_error(); } return ret; } static bool dnskey_eddsa_verifydigest(const dnssec_key *key, const u8 *digest, u32 digest_len, const u8 *signature, u32 signature_len) { yassert(signature_len <= DNSSEC_MAXIMUM_KEY_SIZE_BYTES); #if DEBUG log_debug6("eddsa_verifydigest(K%{dnsname}-%03d-%05d, @%p, @%p)", key->owner_name, key->algorithm, key->tag, digest, signature); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, digest, digest_len, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, signature, signature_len, 32); #endif /* * For P-256, each integer MUST be encoded as 32 octets; * for P-384, each integer MUST be encoded as 48 octets. */ int bn_size = dnskey_eddsa_nid_to_signature_bn_size(key->nid); if(FAIL(bn_size)) { log_err("EDDSA: getting size for NID returned: %r", bn_size); return FALSE; } if((int)signature_len != bn_size) { log_err("EDDSA: signature size unexpected"); return FALSE; } bool ret = FALSE; EVP_MD_CTX *ctx = EVP_MD_CTX_new(); if(ctx != NULL) { if(EVP_DigestSignInit(ctx, NULL, NULL, NULL, key->key.ed) == 1) { if(EVP_DigestVerify(ctx, signature, signature_len, digest, digest_len) == 1) { ret = TRUE; } else { ya_ssl_error(); } } else { ya_ssl_error(); } EVP_MD_CTX_free(ctx); } else { ya_ssl_error(); } return ret; } static EVP_PKEY* dnskey_eddsa_public_load(u8 algorithm, const u8* rdata_key, u16 rdata_key_size) { EVP_PKEY *key = EVP_PKEY_new_raw_public_key(dnskey_eddsa_getnid(algorithm), NULL, rdata_key, rdata_key_size); return key; } static u32 eddsa_public_store(const EVP_PKEY* eddsa, u8* output_buffer, size_t output_buffer_size) { size_t size = output_buffer_size; if(EVP_PKEY_get_raw_public_key(eddsa, output_buffer, &size) == 1) { return size; } else { return ERROR; } } static u32 dnskey_eddsa_dnskey_public_store(const dnssec_key* key, u8* rdata, size_t rdata_size) { u32 len; SET_U16_AT(rdata[0], key->flags); rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = key->algorithm; len = eddsa_public_store(key->key.ed, &rdata[4], rdata_size) + 4; return len; } static u32 dnskey_eddsa_size(const dnssec_key* key) { size_t size = 0; EVP_PKEY_get_raw_private_key(key->key.ed, NULL, &size); return (u32)size * 8; } /** * Returns the size in byte of the public key. * * @param eddsa * @return */ static u32 dnskey_eddsa_public_size(const EVP_PKEY* eddsa) { size_t size = 0; EVP_PKEY_get_raw_public_key(eddsa, NULL, &size); return (u32)size; } static u32 dnskey_eddsa_dnskey_rdatasize(const dnssec_key* key) { u32 size = dnskey_eddsa_public_size(key->key.ed) + 4; return size; } static void dnskey_eddsa_free(dnssec_key* key) { EVP_PKEY* eddsa = key->key.ed; EVP_PKEY_free(eddsa); key->key.ed = NULL; } static bool dnskey_eddsa_equals(const dnssec_key *key_a, const dnssec_key *key_b) { if(key_a == key_b) { return TRUE; } if(dnssec_key_tag_field_set(key_a) && dnssec_key_tag_field_set(key_b)) { if(key_a->tag != key_b->tag) { return FALSE; } } if((key_a->flags == key_b->flags) && (key_a->algorithm == key_b->algorithm)) { if(strcmp(key_a->origin, key_b->origin) == 0) { #if SSL_API_GE_300 return EVP_PKEY_eq(key_a->key.ed, key_b->key.ed) == 1; #else return EVP_PKEY_cmp(key_a->key.ed, key_b->key.ed) == 1; #endif } } return FALSE; } static ya_result dnskey_eddsa_print_fields(dnssec_key *key, output_stream *os) { struct dnskey_eddsa yeddsa; dnskey_eddsa_from_eddsa(&yeddsa, key->key.ed); // @note 20220802 edf -- prints the private key on stdout for some test, disabled, obviously // PEM_write_PrivateKey(stdout, key->key.ed, NULL, NULL, 0, NULL, NULL); size_t buffer_size; u8 buffer[256]; buffer_size = sizeof(buffer); EVP_PKEY_get_raw_private_key(key->key.ed, buffer, &buffer_size); /* format("private[%llu]=", buffer_size); debug_dump_ex(buffer, buffer_size, 32, TRUE, FALSE, FALSE); */ buffer_size = sizeof(buffer); EVP_PKEY_get_raw_public_key(key->key.ed, buffer, &buffer_size); /* format("\npublic[%llu]=", buffer_size); debug_dump_ex(buffer, buffer_size, 32, TRUE, FALSE, FALSE); println(""); flushout(); */ ya_result ret = dnskey_field_access_print(ECDSA_field_access, &yeddsa, os); return ret; } static const dnssec_key_vtbl eddsa_vtbl = { dnskey_eddsa_signdigest, dnskey_eddsa_verifydigest, dnskey_eddsa_dnskey_rdatasize, dnskey_eddsa_dnskey_public_store, dnskey_eddsa_free, dnskey_eddsa_equals, dnskey_eddsa_print_fields, dnskey_eddsa_size, "ECDSA" }; static ya_result dnskey_eddsa_initinstance(EVP_PKEY *eddsa, u8 algorithm, u16 flags, const char *origin, dnssec_key **out_key) { int nid; // needed to compute the tag u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; /* 4096 bits -> 1KB */ *out_key = NULL; if(FAIL(nid = dnskey_eddsa_getnid(algorithm))) { return nid; } #if DEBUG memset(rdata, 0xff, sizeof(rdata)); #endif u32 public_key_size = dnskey_eddsa_public_size(eddsa); if(public_key_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES) { return DNSSEC_ERROR_KEYISTOOBIG; } SET_U16_AT(rdata[0], flags); // NATIVEFLAGS rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = algorithm; if(eddsa_public_store(eddsa, &rdata[4], sizeof(rdata) - 4) != public_key_size) { return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */ } /* Note : + 4 because of the flags,protocol & algorithm bytes * are not taken in account */ u16 tag = dnskey_get_tag_from_rdata(rdata, public_key_size + 4); dnssec_key* key = dnskey_newemptyinstance(algorithm, flags, origin); // RC key->key.ed = eddsa; key->vtbl = &eddsa_vtbl; key->tag = tag; key->nid = nid; key->status |= (i2d_PrivateKey(eddsa, NULL) > 0)?DNSKEY_KEY_IS_PRIVATE:0; *out_key = key; return SUCCESS; } static ya_result dnskey_eddsa_parse_field(struct dnskey_field_parser *parser, parser_s *p) { struct dnskey_eddsa *yeddsa = (struct dnskey_eddsa*)parser->data; ya_result ret = dnskey_field_access_parse(ECDSA_field_access, yeddsa, p); return ret; } static ya_result dnskey_eddsa_parse_set_key(struct dnskey_field_parser *parser, dnssec_key *key) { struct dnskey_eddsa *yeddsa = (struct dnskey_eddsa*)parser->data; if(key == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } switch(key->algorithm) { case DNSKEY_ALGORITHM_ED25519: case DNSKEY_ALGORITHM_ED448: break; default: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } if(yeddsa->private_key.buffer == NULL) { return DNSSEC_ERROR_INCOMPLETEKEY; } int nid; if(FAIL(nid = dnskey_eddsa_getnid(key->algorithm))) { return nid; } EVP_PKEY *eddsa = EVP_PKEY_new_raw_private_key(nid, NULL, yeddsa->private_key.buffer, yeddsa->private_key.size); if(eddsa != NULL) { // at this point, yeddsa has been emptied u32 rdata_size = dnskey_eddsa_public_size(eddsa); u16 tag; u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; if(rdata_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES) { EVP_PKEY_free(eddsa); return DNSSEC_ERROR_KEYISTOOBIG; } SET_U16_AT(rdata[0], key->flags); rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = key->algorithm; if(eddsa_public_store(eddsa, &rdata[4], sizeof(rdata) - 4) != rdata_size) { EVP_PKEY_free(eddsa); return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */ } /* Note : + 4 because of the flags,protocol & algorithm bytes * are not taken in account */ tag = dnskey_get_tag_from_rdata(rdata, rdata_size + 4); key->key.ed = eddsa; key->tag = tag; key->nid = nid; key->status |= DNSKEY_KEY_IS_VALID | DNSKEY_KEY_IS_PRIVATE; return SUCCESS; } return DNSSEC_ERROR_INCOMPLETEKEY; } static void dnskey_eddsa_parse_finalize(struct dnskey_field_parser *parser) { struct dnskey_eddsa *ydsa = (struct dnskey_eddsa*)parser->data; if(ydsa != NULL) { dnskey_eddsa_finalize(ydsa); ZFREE(ydsa, struct dnskey_eddsa); } } static const struct dnskey_field_parser_vtbl eddsa_field_parser_vtbl = { dnskey_eddsa_parse_field, dnskey_eddsa_parse_set_key, dnskey_eddsa_parse_finalize, "EDDSA" }; void dnskey_eddsa_parse_init(dnskey_field_parser *fp) { struct dnskey_eddsa *yeddsa; ZALLOC_OBJECT_OR_DIE(yeddsa, struct dnskey_eddsa, KEYECDSA_TAG); ZEROMEMORY(yeddsa, sizeof(struct dnskey_eddsa)); fp->data = yeddsa; fp->vtbl = &eddsa_field_parser_vtbl; } ya_result dnskey_eddsa_loadpublic(const u8 *rdata, u16 rdata_size, const char *origin, dnssec_key** out_key) { *out_key = NULL; if(rdata == NULL || rdata_size <= 6 || origin == NULL) { /* bad */ return UNEXPECTED_NULL_ARGUMENT_ERROR; } u16 flags = GET_U16_AT(rdata[0]); u8 algorithm = rdata[3]; if((algorithm != DNSKEY_ALGORITHM_ECDSAP256SHA256) && (algorithm != DNSKEY_ALGORITHM_ECDSAP384SHA384) && (algorithm != DNSKEY_ALGORITHM_ED25519) && (algorithm != DNSKEY_ALGORITHM_ED448)) { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } rdata += 4; rdata_size -= 4; ya_result return_value = DNSSEC_ERROR_CANNOT_READ_KEY_FROM_RDATA; EVP_PKEY *eddsa = dnskey_eddsa_public_load(algorithm, rdata, rdata_size); if(eddsa != NULL) { dnssec_key *key; if(ISOK(return_value = dnskey_eddsa_initinstance(eddsa, algorithm, flags, origin, &key))) { *out_key = key; return return_value; } EVP_PKEY_free(eddsa); } return return_value; } ya_result dnskey_eddsa_newinstance(u32 size, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key) { *out_key = NULL; if(size > DNSSEC_MAXIMUM_KEY_SIZE) { return DNSSEC_ERROR_KEYISTOOBIG; } if((algorithm != DNSKEY_ALGORITHM_ED25519) && (algorithm != DNSKEY_ALGORITHM_ED448)) { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } ya_result ret = ERROR; EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(dnskey_eddsa_getnid(algorithm), NULL); if(ctx != NULL) { if(EVP_PKEY_keygen_init(ctx) == 1) { EVP_PKEY *evp_key = NULL; if(EVP_PKEY_keygen(ctx, &evp_key) == 1) { dnssec_key *key = NULL; if(ISOK(ret = dnskey_eddsa_initinstance(evp_key, algorithm, flags, origin, &key))) { *out_key = key; } } } if(FAIL(ret)) { unsigned long ssl_err; while((ssl_err = ERR_get_error()) != 0) { char buffer[256]; ERR_error_string_n(ssl_err, buffer, sizeof(buffer)); osformatln(termerr, "digest signature returned an ssl error %08x %s", (unsigned int)ssl_err, buffer); } ERR_clear_error(); } EVP_PKEY_CTX_free(ctx); } return ret; } #else void dnskey_eddsa_not_supported() {} #endif // HAS_EDDSA_SUPPORT /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dnskey_rsa.c0000644000000000000000000000013214505005532021636 xustar000000000000000030 mtime=1695812442.479982718 30 atime=1695812445.795030196 30 ctime=1695812494.555728548 yadifa-2.6.5-11201/lib/dnscore/src/dnskey_rsa.c0000664000374500037450000005141414505005532021605 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #include #include #include "dnscore/openssl.h" #include "dnscore/sys_types.h" #include "dnscore/base64.h" #include "dnscore/logger.h" #include "dnscore/dnskey_rsa.h" #include "dnscore/dnssec_errors.h" #include "dnscore/parser.h" #include "dnscore/zalloc.h" #define MODULE_MSG_HANDLE g_system_logger #define KEYRSA_TAG 0x41535259454b #ifndef SSL_API #error "SSL_API not defined" #endif #if SSL_API_LT_110 #define SSL_FIELD_GET(st_,f_) if(f_ != NULL) { *f_ = st_->f_; } #define SSL_FIELD_SET(st_,f_) if(f_ != NULL) { BN_free(st_->f_); st_->f_ = f_; } #define SSL_FIELD_SET_FAIL(st_,f_) (st_->f_ == NULL && f_ == NULL) static void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { SSL_FIELD_GET(r,n) SSL_FIELD_GET(r,e) SSL_FIELD_GET(r,d) } static int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { if(SSL_FIELD_SET_FAIL(r,n) || SSL_FIELD_SET_FAIL(r,e)) { return 0; } SSL_FIELD_SET(r,n) SSL_FIELD_SET(r,e) SSL_FIELD_SET(r,d) return 1; } static void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) { SSL_FIELD_GET(r,p) SSL_FIELD_GET(r,q) } static int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) { if(SSL_FIELD_SET_FAIL(r,p) || SSL_FIELD_SET_FAIL(r,q)) { return 0; } SSL_FIELD_SET(r,p) SSL_FIELD_SET(r,q) return 1; } static void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp) { SSL_FIELD_GET(r,dmp1) SSL_FIELD_GET(r,dmq1) SSL_FIELD_GET(r,iqmp) } static int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) { if(SSL_FIELD_SET_FAIL(r,dmp1) || SSL_FIELD_SET_FAIL(r,dmq1) || SSL_FIELD_SET_FAIL(r,iqmp)) { return 0; } SSL_FIELD_SET(r,dmp1) SSL_FIELD_SET(r,dmq1) SSL_FIELD_SET(r,iqmp) return 1; } #endif struct dnskey_rsa { BIGNUM *n,*e,*d,*p,*q,*dmp1,*dmq1,*iqmp; }; struct dnskey_rsa_const { const BIGNUM *n,*e,*d,*p,*q,*dmp1,*dmq1,*iqmp; }; static void dnskey_rsa_init(struct dnskey_rsa *yrsa) { memset(yrsa, 0, sizeof(struct dnskey_rsa)); } static bool dnskey_rsa_to_rsa(struct dnskey_rsa *yrsa, RSA *rsa) { if(RSA_set0_key(rsa, yrsa->n, yrsa->e, yrsa->d) != 0) { yrsa->n = NULL; yrsa->e = NULL; yrsa->d = NULL; if(RSA_set0_factors(rsa, yrsa->p, yrsa->q) != 0) { yrsa->p = NULL; yrsa->q = NULL; if(RSA_set0_crt_params(rsa, yrsa->dmp1, yrsa->dmq1, yrsa->iqmp) != 0) { yrsa->dmp1 = NULL; yrsa->dmq1 = NULL; yrsa->iqmp = NULL; return TRUE; } } } return FALSE; } static void dnskey_rsa_from_rsa(struct dnskey_rsa_const *yrsa, const RSA *rsa) { RSA_get0_key(rsa, &yrsa->n, &yrsa->e, &yrsa->d); RSA_get0_factors(rsa, &yrsa->p, &yrsa->q); RSA_get0_crt_params(rsa, &yrsa->dmp1, &yrsa->dmq1, &yrsa->iqmp); } static void dnskey_rsa_finalize(struct dnskey_rsa *yrsa) { if(yrsa->n != NULL) BN_free(yrsa->n); if(yrsa->e != NULL) BN_free(yrsa->e); if(yrsa->d != NULL) BN_free(yrsa->d); if(yrsa->p != NULL) BN_free(yrsa->p); if(yrsa->q != NULL) BN_free(yrsa->q); if(yrsa->dmp1 != NULL) BN_free(yrsa->dmp1); if(yrsa->dmq1 != NULL) BN_free(yrsa->dmq1); if(yrsa->iqmp != NULL) BN_free(yrsa->iqmp); dnskey_rsa_init(yrsa); } static const struct dnskey_field_access RSA_field_access[] ={ {"Modulus", offsetof(struct dnskey_rsa,n), STRUCTDESCRIPTOR_BN}, {"PublicExponent", offsetof(struct dnskey_rsa,e), STRUCTDESCRIPTOR_BN}, {"PrivateExponent", offsetof(struct dnskey_rsa,d), STRUCTDESCRIPTOR_BN}, {"Prime1", offsetof(struct dnskey_rsa,p), STRUCTDESCRIPTOR_BN}, {"Prime2", offsetof(struct dnskey_rsa,q), STRUCTDESCRIPTOR_BN}, {"Exponent1", offsetof(struct dnskey_rsa,dmp1), STRUCTDESCRIPTOR_BN}, {"Exponent2", offsetof(struct dnskey_rsa,dmq1), STRUCTDESCRIPTOR_BN}, {"Coefficient", offsetof(struct dnskey_rsa,iqmp), STRUCTDESCRIPTOR_BN}, {"", 0, 0} }; static int dnskey_rsa_getnid(u8 algorithm) { switch(algorithm) { case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA1: { return NID_sha1; } case DNSKEY_ALGORITHM_RSASHA256_NSEC3: { return NID_sha256; } case DNSKEY_ALGORITHM_RSASHA512_NSEC3: { return NID_sha512; } default: { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } } } static RSA* dnskey_rsa_genkey(u32 size) { yassert(size >= DNSSEC_MINIMUM_KEY_SIZE && size <= DNSSEC_MAXIMUM_KEY_SIZE); int err; BN_CTX *ctx; BIGNUM *e; RSA* rsa; ctx = BN_CTX_new(); yassert(ctx != NULL); e = BN_new(); BN_set_word(e, 0x10001); // exponent, 65537 yassert(e != NULL); rsa = RSA_new(); yassert(rsa != NULL); err = RSA_generate_key_ex(rsa, size, e, NULL); /* no callback */ if(err == 0) { RSA_free(rsa); rsa = NULL; } BN_free(e); BN_CTX_free(ctx); return rsa; } static ya_result dnskey_rsa_signdigest(const dnssec_key *key, const u8 *digest, u32 digest_len, u8 *output) { u32 output_size = MAX_U32; int err = RSA_sign(key->nid, digest, digest_len, output, &output_size, key->key.rsa); #if DEBUG if(err == 0) { ERR_print_errors_fp(stderr); return DNSSEC_ERROR_RSASIGNATUREFAILED; } #endif return (err != 0) ? (s32)output_size : DNSSEC_ERROR_RSASIGNATUREFAILED; // condition is only "always true" if DEBUG is on } static bool dnskey_rsa_verifydigest(const dnssec_key *key, const u8 *digest, u32 digest_len, const u8 *signature, u32 signature_len) { yassert(signature_len <= DNSSEC_MAXIMUM_KEY_SIZE_BYTES); #if DEBUG log_debug6("rsa_verifydigest(K%{dnsname}-%03d-%05d, @%p, @%p)", key->owner_name, key->algorithm, key->tag, digest, signature); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, digest, digest_len, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, signature, signature_len, 32); #endif #if SSL_API_LT_100 int err = RSA_verify(key->nid, digest, digest_len, (unsigned char*)signature, signature_len, key->key.rsa); #else int err = RSA_verify(key->nid, digest, digest_len, signature, signature_len, key->key.rsa); #endif if(err != 1) { unsigned long ssl_err; while((ssl_err = ERR_get_error()) != 0) { #if DEBUG char buffer[256]; ERR_error_string_n(ssl_err, buffer, sizeof(buffer)); log_debug("digest verification returned an ssl error %08x %s", ssl_err, buffer); #endif } ERR_clear_error(); return FALSE; } return TRUE; } static RSA* dnskey_rsa_public_load(const u8* rdata, u16 rdata_size) { // rdata_size < 4 is harsher than needed but anyway such a small key would // and this avoid another test later be worthless if(rdata == NULL || rdata_size < 4) { return NULL; } const u8 *inptr = rdata; u32 n; n = *inptr++; rdata_size--; // rdata_size is at least 1, so it is OK if(n == 0) { n = *inptr++; n <<= 8; n |= *inptr++; rdata_size-=2; } if(rdata_size < n + 1) { return NULL; } BIGNUM* exponent; BIGNUM* modulus; exponent = BN_bin2bn(inptr, n, NULL); if(exponent == NULL) { log_err("rsa_public_load: NULL exponent"); return NULL; } inptr += n; n = rdata_size - n; modulus = BN_bin2bn(inptr, n, NULL); if(modulus == NULL) { log_err("rsa_public_load: NULL modulus"); BN_free(exponent); return NULL; } BN_CTX *ctx; RSA* rsa; ctx = BN_CTX_new(); yassert(ctx != NULL); rsa = RSA_new(); yassert(rsa != NULL); RSA_set0_key(rsa, modulus, exponent, NULL); BN_CTX_free(ctx); return rsa; } static u32 dnskey_rsa_public_store(RSA* rsa, u8* output_buffer, u32 output_buffer_size) { unsigned char* outptr = output_buffer; u32 n; u32 m; const BIGNUM* exponent; const BIGNUM* modulus; RSA_get0_key(rsa, &modulus, &exponent, NULL); n = BN_num_bytes(exponent); m = BN_num_bytes(modulus); if(n > 1 && n < 256) { if(1 + n + m > output_buffer_size) { return 0; } *outptr++ = n; } else { if(3 + n + m > output_buffer_size) { return 0; } *outptr++ = 0; *outptr++ = n >> 8; *outptr++ = n; } n = BN_bn2bin(exponent, outptr); outptr += n; n = BN_bn2bin(modulus, outptr); outptr += n; return outptr - output_buffer; } static u32 dnskey_rsa_dnskey_public_store(const dnssec_key *key, u8 *rdata, size_t rdata_size) { u32 len; SET_U16_AT(rdata[0], key->flags); rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = key->algorithm; len = dnskey_rsa_public_store(key->key.rsa, &rdata[4], rdata_size - 4) + 4; return len; } static u32 dnskey_rsa_size(const dnssec_key* key) { const BIGNUM* rsa_n; RSA_get0_key(key->key.rsa, &rsa_n, NULL, NULL); u32 m_size = BN_num_bytes(rsa_n); return m_size << 3; } static u32 dnskey_rsa_public_size(const RSA* rsa) { const BIGNUM* rsa_e; const BIGNUM* rsa_n; RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL); u32 e_size = BN_num_bytes(rsa_e); u32 m_size = BN_num_bytes(rsa_n); return m_size + e_size + ((e_size < 256) ? 1 : 3); } static u32 dnskey_rsa_dnskey_rdatasize(const dnssec_key* key) { u32 size = dnskey_rsa_public_size(key->key.rsa) + 4; return size; } static void dnskey_rsa_free(dnssec_key* key) { RSA* rsa = key->key.rsa; RSA_free(rsa); key->key.rsa = NULL; } static bool dnskey_rsa_equals(const dnssec_key* key_a, const dnssec_key* key_b) { /* RSA, compare modulus and exponent, exponent first (it's the smallest) */ if(key_a == key_b) { return TRUE; } if(dnssec_key_tag_field_set(key_a) && dnssec_key_tag_field_set(key_b)) { if(key_a->tag != key_b->tag) { return FALSE; } } if((key_a->flags == key_b->flags) && (key_a->algorithm == key_b->algorithm)) { if(strcmp(key_a->origin, key_b->origin) == 0) { RSA* a_rsa = key_a->key.rsa; RSA* b_rsa = key_b->key.rsa; const BIGNUM* a_rsa_e; const BIGNUM* a_rsa_n; const BIGNUM* b_rsa_e; const BIGNUM* b_rsa_n; RSA_get0_key(a_rsa, &a_rsa_n, &a_rsa_e, NULL); RSA_get0_key(b_rsa, &b_rsa_n, &b_rsa_e, NULL); if(BN_cmp(a_rsa_e, b_rsa_e) == 0) { if(BN_cmp(a_rsa_n, b_rsa_n) == 0) { return TRUE; } } } } return FALSE; } ya_result dnskey_rsa_private_print_fields(dnssec_key *key, output_stream *os) { struct dnskey_rsa_const yrsa; dnskey_rsa_from_rsa(&yrsa, key->key.rsa); ya_result ret = dnskey_field_access_print(RSA_field_access, &yrsa, os); return ret; } static const dnssec_key_vtbl rsa_vtbl = { dnskey_rsa_signdigest, dnskey_rsa_verifydigest, dnskey_rsa_dnskey_rdatasize, dnskey_rsa_dnskey_public_store, dnskey_rsa_free, dnskey_rsa_equals, dnskey_rsa_private_print_fields, dnskey_rsa_size, "RSA" }; static ya_result dnskey_rsa_initinstance(RSA* rsa, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key) { int nid; u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; /* 4096 bits -> 1KB */ *out_key = NULL; if(FAIL(nid = dnskey_rsa_getnid(algorithm))) { return nid; } #if DEBUG memset(rdata, 0xff, sizeof(rdata)); #endif u32 rdata_size = dnskey_rsa_public_size(rsa); if(rdata_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES) { return DNSSEC_ERROR_KEYISTOOBIG; } SET_U16_AT(rdata[0], flags); // NATIVEFLAGS rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = algorithm; if(dnskey_rsa_public_store(rsa, &rdata[4], sizeof(rdata) - 4) != rdata_size) { return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */ } /* Note : + 4 because of the flags,protocol & algorithm bytes * are not taken in account */ u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size + 4); dnssec_key* key = dnskey_newemptyinstance(algorithm, flags, origin); // RC if(key == NULL) { return INVALID_ARGUMENT_ERROR; } key->key.rsa = rsa; key->vtbl = &rsa_vtbl; key->tag = tag; key->nid = nid; const BIGNUM *rsa_p; const BIGNUM *rsa_q; RSA_get0_factors(rsa, &rsa_p, &rsa_q); if((rsa_q != NULL) && (rsa_p != NULL)) { key->status |= DNSKEY_KEY_IS_PRIVATE; } *out_key = key; return SUCCESS; } static ya_result dnskey_rsa_parse_field(struct dnskey_field_parser *parser, parser_s *p) { struct dnskey_rsa *yrsa = (struct dnskey_rsa*)parser->data; ya_result ret = dnskey_field_access_parse(RSA_field_access, yrsa, p); return ret; } static ya_result dnskey_rsa_parse_set_key(struct dnskey_field_parser *parser, dnssec_key *key) { if(key == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } //yassert(key->nid == 0); switch(key->algorithm) { case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: break; default: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } struct dnskey_rsa *yrsa = (struct dnskey_rsa*)parser->data; if((yrsa->n == NULL) || (yrsa->e == NULL) || (yrsa->d == NULL) || (yrsa->dmp1 == NULL) || (yrsa->dmq1 == NULL) || (yrsa->iqmp == NULL)) { return DNSSEC_ERROR_INCOMPLETEKEY; } if((yrsa->p == NULL) != (yrsa->q == NULL)) { // half a private key is wrong return DNSSEC_ERROR_INCOMPLETEKEY; } int nid; if(FAIL(nid = dnskey_rsa_getnid(key->algorithm))) { return nid; } if((key->nid != 0) && (key->nid != nid)) { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } bool has_private = (yrsa->p != NULL) && (yrsa->q != NULL); if(key->key.rsa == NULL) { key->key.rsa = RSA_new(); key->vtbl = &rsa_vtbl; } if(dnskey_rsa_to_rsa(yrsa, key->key.rsa)) { // at this point, yrsa has been emptied RSA *rsa = key->key.rsa; u32 rdata_size = dnskey_rsa_public_size(rsa); u16 tag; u8 rdata[DNSSEC_MAXIMUM_KEY_SIZE_BYTES]; if(rdata_size > DNSSEC_MAXIMUM_KEY_SIZE_BYTES) { return DNSSEC_ERROR_KEYISTOOBIG; } SET_U16_AT(rdata[0], key->flags); rdata[2] = DNSKEY_PROTOCOL_FIELD; rdata[3] = key->algorithm; if(dnskey_rsa_public_store(rsa, &rdata[4], sizeof(rdata) - 4) != rdata_size) { return DNSSEC_ERROR_UNEXPECTEDKEYSIZE; /* Computed size != real size */ } /* Note : + 4 because of the flags,protocol & algorithm bytes * are not taken in account */ tag = dnskey_get_tag_from_rdata(rdata, rdata_size + 4); key->tag = tag; key->nid = nid; key->status |= DNSKEY_KEY_IS_VALID; if(has_private) { key->status |= DNSKEY_KEY_IS_PRIVATE; } return SUCCESS; } else { return DNSSEC_ERROR_INCOMPLETEKEY; } } static void dnskey_rsa_parse_finalize(struct dnskey_field_parser *parser) { struct dnskey_rsa *yrsa = (struct dnskey_rsa*)parser->data; if(yrsa != NULL) { dnskey_rsa_finalize(yrsa); ZFREE(yrsa, struct dnskey_rsa); } } static const struct dnskey_field_parser_vtbl rsa_field_parser_vtbl = { dnskey_rsa_parse_field, dnskey_rsa_parse_set_key, dnskey_rsa_parse_finalize, "RSA" }; void dnskey_rsa_parse_init(dnskey_field_parser *fp) { struct dnskey_rsa *yrsa; ZALLOC_OBJECT_OR_DIE(yrsa, struct dnskey_rsa, KEYRSA_TAG); ZEROMEMORY(yrsa, sizeof(struct dnskey_rsa)); fp->data = yrsa; fp->vtbl = &rsa_field_parser_vtbl; } ya_result dnskey_rsa_loadpublic(const u8 *rdata, u16 rdata_size, const char *origin, dnssec_key **out_key) { *out_key = NULL; if(rdata == NULL || rdata_size <= 6 || origin == NULL) { /* bad */ return UNEXPECTED_NULL_ARGUMENT_ERROR; } u16 flags = GET_U16_AT(rdata[0]); u8 algorithm = rdata[3]; switch(algorithm) { case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: break; default: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } rdata += 4; rdata_size -= 4; ya_result return_value = DNSSEC_ERROR_CANNOT_READ_KEY_FROM_RDATA; RSA *rsa = dnskey_rsa_public_load(rdata, rdata_size); if(rsa != NULL) { dnssec_key *key; if(ISOK(return_value = dnskey_rsa_initinstance(rsa, algorithm, flags, origin, &key))) { *out_key = key; return return_value; } RSA_free(rsa); } return return_value; } ya_result dnskey_rsa_newinstance(u32 size, u8 algorithm, u16 flags, const char* origin, dnssec_key** out_key) { *out_key = NULL; if(size > DNSSEC_MAXIMUM_KEY_SIZE) { return DNSSEC_ERROR_KEYISTOOBIG; } switch(algorithm) { case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: break; default: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } ya_result return_value = DNSSEC_ERROR_KEY_GENERATION_FAILED; RSA *rsa = dnskey_rsa_genkey(size); if(rsa != NULL) { dnssec_key *key; if(ISOK(return_value = dnskey_rsa_initinstance(rsa, algorithm, flags, origin, &key))) { *out_key = key; return return_value; } RSA_free(rsa); } return return_value; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dnskey-signature.c0000644000000000000000000000013214505005532022770 xustar000000000000000030 mtime=1695812442.451982317 30 atime=1695812445.794030182 30 ctime=1695812494.557728576 yadifa-2.6.5-11201/lib/dnscore/src/dnskey-signature.c0000664000374500037450000004657014505005532022746 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup dnskey DNSSEC keys functions * @ingroup dnscorednssec * @addtogroup dnskey DNSKEY functions * @brief * * * @{ */ #include "dnscore/dnskey-signature.h" #include "dnscore/dnskey.h" #include "dnscore/logger.h" #define MODULE_MSG_HANDLE g_system_logger #define DEBUG_CRYPTO_INTERNALS 0 #if DEBUG_CRYPTO_INTERNALS #pragma message("WARNING: DEBUG_CRYPTO_INTERNALS is not set to 0") #endif #if DEBUG_CRYPTO_INTERNALS #define DNSKEY_SIGN_TIME_LENIENCY 0 #else #define DNSKEY_SIGN_TIME_LENIENCY 86400 #endif struct dnskey_signature_header { // this part MUST match the 18 bytes of wire image of an RRSIG u16 type_covered; u8 algorithm; u8 labels; s32 original_ttl; u32 expiration; u32 inception; // 16 bytes u16 tag; // 18 u8 fqdn_signature[]; }; union dnskey_signature_header_storage { u8 rdata[RRSIG_RDATA_HEADER_LEN + 256 + 2048]; struct dnskey_signature_header header; }; struct dnskey_signature_tctr { u16 rtype; u16 rclass; s32 ttl; u16 rdata_size; }; static int dnskey_signature_canonize_sort_record_view_rdata_compare(const void *a, const void *b, void *c) { const u8* ptr_a = (const u8*)a; const u8* ptr_b = (const u8*)b; resource_record_view *view = (resource_record_view*)c; u16 rr_a_size = view->vtbl->get_rdata_size(view->data, ptr_a); u16 rr_b_size = view->vtbl->get_rdata_size(view->data, ptr_b); int ret; int diff_len = rr_a_size; diff_len -= rr_b_size; const u8 *rr_a_rdata = view->vtbl->get_rdata(view->data, ptr_a); const u8 *rr_b_rdata = view->vtbl->get_rdata(view->data, ptr_b); if(diff_len != 0) { u16 len = MIN(rr_a_size, rr_b_size); ret = memcmp(rr_a_rdata, rr_b_rdata, len); if(ret == 0) { ret = diff_len; } } else { ret = memcmp(rr_a_rdata, rr_b_rdata, rr_a_size); } return ret; } void dnskey_signature_init(dnskey_signature *ds) { ZEROMEMORY(ds, sizeof(*ds)); } void dnskey_signature_set_validity(dnskey_signature *ds, time_t from, time_t to) { if(from != ds->inception) { ds->inception = (u32)from; ds->has_digest = 0; ds->inception_set = 1; } if(to != ds->expiration) { ds->expiration = (u32)to; ds->has_digest = 0; ds->expiration_set = 1; } } void dnskey_signature_set_view(dnskey_signature *ds, resource_record_view *view) { ds->rr_view = view; ds->is_canonised = 0; ds->has_digest = 0; } void dnskey_signature_set_rrset_reference(dnskey_signature *ds, ptr_vector *rrset) { ds->rrset_reference = rrset; ds->is_canonised = 0; ds->has_digest = 0; } void dnskey_signature_set_canonised(dnskey_signature *ds, bool canonised) { ds->is_canonised = canonised?1:0; } /** * out_rrsig_rr points to a mallocated dns_resource_record */ ya_result dnskey_signature_sign(dnskey_signature *ds, const dnssec_key *key, void **out_rrsig_rr) { u8 *signature; const void *rr0; const u8 *fqdn; size_t fqdn_len; const u8* owner_fqdn; size_t owner_fqdn_len; digest_s *ctx_ptr = &ds->digest_ctx; ya_result ret; struct dnskey_signature_tctr tctr; u8 fqdn_buffer[256]; union dnskey_signature_header_storage hdr; if(key == NULL) { return INVALID_ARGUMENT_ERROR; // no key } if(!dnskey_is_private(key)) { return DNSSEC_ERROR_KEYRING_KEY_IS_NOT_PRIVATE; // not private } if((ds->rrset_reference == NULL) || (ptr_vector_size(ds->rrset_reference) == 0)) { return INVALID_ARGUMENT_ERROR; // empty set } #if DEBUG || DEBUG_CRYPTO_INTERNALS memset(&hdr, 0xf5, sizeof(hdr)); #endif time_t inception = ds->inception; time_t expiration = ds->expiration/*dnskey_get_inactive_epoch(key)*/; u8 key_algorithm = dnskey_get_algorithm(key); if(key_algorithm != ds->key_algorithm) { ds->has_digest = 0; } ptr_vector *rrset = ds->rrset_reference; const resource_record_view_vtbl *view_vtbl = ds->rr_view->vtbl; void *data = ds->rr_view->data; if(!ds->has_digest) { if(FAIL(ret = dnskey_digest_init(ctx_ptr, key_algorithm))) { return ret; } rr0 = ptr_vector_get(rrset, 0); fqdn_len = dnsname_canonize(view_vtbl->get_fqdn(data, rr0), fqdn_buffer); fqdn = fqdn_buffer; //dnsname_len(fqdn); hdr.header.labels = 0; if((fqdn[0] == 1) && (fqdn[1] == (u8)'*')) { fqdn += *fqdn + 1; } while(fqdn[0] != 0) { ++hdr.header.labels; fqdn += *fqdn + 1; } fqdn = fqdn_buffer; owner_fqdn = dnskey_get_domain(key); owner_fqdn_len = dnsname_len(owner_fqdn); if(!ds->is_canonised) { ptr_vector_qsort_r(rrset, dnskey_signature_canonize_sort_record_view_rdata_compare, ds->rr_view); ds->is_canonised = 1; } hdr.header.type_covered = view_vtbl->get_type(data, rr0); hdr.header.algorithm = dnskey_get_algorithm(key); // hdr.header.labels has already been set hdr.header.original_ttl = htonl(view_vtbl->get_ttl(data, rr0)); hdr.header.expiration = ntohl(expiration); hdr.header.inception = ntohl(inception); hdr.header.tag = htons(dnskey_get_tag_const(key)); memcpy(&hdr.header.fqdn_signature[0], owner_fqdn, owner_fqdn_len); // VS false positive: more than enough room has been allocated on the stack signature = &hdr.header.fqdn_signature[owner_fqdn_len]; tctr.rtype = hdr.header.type_covered; tctr.rclass = view_vtbl->get_class(data, rr0); tctr.ttl = hdr.header.original_ttl; size_t hdr_size = signature - (u8*)&hdr; #if DEBUG_CRYPTO_INTERNALS log_debug("dnskey_signature_sign: digest for %{dnsname} %{dnstype} and key tag %i", owner_fqdn, &hdr.header.type_covered, dnskey_get_tag_const(key)); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, &hdr, hdr_size, 32); #endif digest_update(ctx_ptr, &hdr, hdr_size); for(int i = 0; i <= ptr_vector_last_index(rrset); ++i) { const void *rr = ptr_vector_get(rrset, i); digest_update(ctx_ptr, fqdn, fqdn_len); u16 rdata_size = view_vtbl->get_rdata_size(data, rr); tctr.rdata_size = htons(rdata_size); const void *rdata = view_vtbl->get_rdata(data, rr); #if DEBUG_CRYPTO_INTERNALS rdata_desc rdd = {tctr.rtype, rdata_size, rdata}; log_debug("dnskey_signature_sign: #%i: %{dnsname} %i %{dnsclass} %{typerdatadesc}", i, fqdn, ntohl(tctr.ttl), &tctr.rclass, &rdd); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, fqdn, fqdn_len, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, &tctr, 2 + 2 + 4 + 2, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, rdata, rdata_size, 32); #endif digest_update(ctx_ptr, &tctr, 2 + 2 + 4 + 2); digest_update(ctx_ptr, rdata, rdata_size); } s32 digest_size = digest_get_size(ctx_ptr); //digest_final_copy_bytes(ctx_ptr, ds->digest_buffer, sizeof(ds->digest_buffer)); digest_final(ctx_ptr); #if DEBUG_CRYPTO_INTERNALS log_debug("dnskey_signature_sign: digest value"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, digest_get_digest_ptr(ctx_ptr), digest_size, 32); #endif ds->digest_size = digest_size; ds->has_digest = 1; } else { // digest has already been computed, only need to ready the signature, // the rr0 and the fqdn #if DEBUG_CRYPTO_INTERNALS log_debug("dnskey_signature_sign: digest already computed"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, digest_get_digest_ptr(ctx_ptr), ds->digest_size, 32); #endif owner_fqdn = dnskey_get_domain(key); owner_fqdn_len = dnsname_len(owner_fqdn); signature = &hdr.header.fqdn_signature[owner_fqdn_len]; rr0 = ptr_vector_get(rrset, 0); fqdn = view_vtbl->get_fqdn(data, rr0); tctr.rtype = view_vtbl->get_type(data, rr0); tctr.rclass = view_vtbl->get_class(data, rr0); tctr.ttl = htonl(view_vtbl->get_ttl(data, rr0)); } void *digest_ptr; digest_get_digest(ctx_ptr, &digest_ptr); s32 signature_size = key->vtbl->dnssec_key_sign_digest(key, digest_ptr, ds->digest_size, signature); if(ISOK(signature_size)) { #if DEBUG_CRYPTO_INTERNALS log_debug("dnskey_signature_sign: signature value"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, signature, signature_size, 32); #endif u16 rrsig_rdata_size = RRSIG_RDATA_HEADER_LEN + owner_fqdn_len + signature_size; void *rrsig_rr = view_vtbl->new_instance(data, fqdn, TYPE_RRSIG, tctr.rclass, view_vtbl->get_ttl(data, rr0), rrsig_rdata_size, hdr.rdata); *out_rrsig_rr = rrsig_rr; return rrsig_rdata_size; } else { return signature_size; } } ya_result dnskey_signature_verify(dnskey_signature *ds, const dnssec_key *key, void *in_rrsig_rr) // not tested { const void *rr0; const u8 *fqdn; size_t fqdn_len; const u8* owner_fqdn; size_t owner_fqdn_len; digest_s *ctx_ptr = &ds->digest_ctx; ya_result ret; struct dnskey_signature_tctr tctr; u8 fqdn_buffer[256]; union dnskey_signature_header_storage hdr; if(key == NULL) { return INVALID_ARGUMENT_ERROR; // no key } if((ds->rrset_reference == NULL) || (ptr_vector_size(ds->rrset_reference) == 0)) { return INVALID_ARGUMENT_ERROR; // empty set } u8 key_algorithm = dnskey_get_algorithm(key); if(key_algorithm != ds->key_algorithm) { ds->has_digest = 0; } ptr_vector *rrset = ds->rrset_reference; const resource_record_view_vtbl *view_vtbl = ds->rr_view->vtbl; void *data = ds->rr_view->data; if(!ds->has_digest) { if(FAIL(ret = dnskey_digest_init(ctx_ptr, key_algorithm))) { return ret; } rr0 = ptr_vector_get(rrset, 0); fqdn_len = dnsname_canonize(view_vtbl->get_fqdn(data, rr0), fqdn_buffer); fqdn = fqdn_buffer; //dnsname_len(fqdn); hdr.header.labels = 0; if((fqdn[0] == 1) && (fqdn[1] == (u8)'*')) { fqdn += *fqdn + 1; } while(fqdn[0] != 0) { ++hdr.header.labels; fqdn += *fqdn + 1; } fqdn = fqdn_buffer; owner_fqdn = dnskey_get_domain(key); owner_fqdn_len = dnsname_len(owner_fqdn); if(!ds->is_canonised) { ptr_vector_qsort_r(rrset, dnskey_signature_canonize_sort_record_view_rdata_compare, ds->rr_view); ds->is_canonised = 1; } const u8 *rrsig_rdata = view_vtbl->get_rdata(data, in_rrsig_rr); /*u16 rrsig_rdata_size = */ view_vtbl->get_rdata_size(data, in_rrsig_rr); size_t hdr_size = &hdr.header.fqdn_signature[owner_fqdn_len] - (u8*)&hdr; memcpy(hdr.rdata, rrsig_rdata, hdr_size); /* hdr.header.type_covered = htons(rrsig_get_type_covered_from_rdata(rrsig_rdata, rrsig_rdata_size)); hdr.header.algorithm = rrsig_get_algorithm_from_rdata(rrsig_rdata, rrsig_rdata_size); // hdr.header.labels has already been set hdr.header.original_ttl = htonl(rrsig_get_original_ttl_from_rdata(rrsig_rdata, rrsig_rdata_size)); hdr.header.expiration = ntohl(rrsig_get_valid_until_from_rdata(rrsig_rdata, rrsig_rdata_size)); hdr.header.inception = ntohl(rrsig_get_valid_from_from_rdata(rrsig_rdata, rrsig_rdata_size)); hdr.header.tag = htons(rrsig_get_key_tag_from_rdata(rrsig_rdata, rrsig_rdata_size)); memcpy(&hdr.header.fqdn_signature[0], owner_fqdn, owner_fqdn_len); */ tctr.rtype = hdr.header.type_covered; tctr.rclass = view_vtbl->get_class(data, rr0); tctr.ttl = hdr.header.original_ttl; #if DEBUG_CRYPTO_INTERNALS log_debug("dnskey_signature_verify: digest for %{dnsname} %{dnstype} and key tag %i", owner_fqdn, &hdr.header.type_covered, dnskey_get_tag_const(key)); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, &hdr, hdr_size, 32); #endif digest_update(ctx_ptr, &hdr, hdr_size); for(int i = 0; i <= ptr_vector_last_index(rrset); ++i) { const void *rr = ptr_vector_get(rrset, i); digest_update(ctx_ptr, fqdn, fqdn_len); u16 rdata_size = view_vtbl->get_rdata_size(data, rr); tctr.rdata_size = htons(rdata_size); const void *rdata = view_vtbl->get_rdata(data, rr); #if DEBUG_CRYPTO_INTERNALS rdata_desc rdd = {tctr.rtype, rdata_size, rdata}; log_debug("dnskey_signature_verify: #%i: %{dnsname} %i %{dnsclass} %{typerdatadesc}", i, fqdn, ntohl(tctr.ttl), &tctr.rclass, &rdd); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, fqdn, fqdn_len, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, &tctr, 2 + 2 + 4 + 2, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, rdata, rdata_size, 32); #endif digest_update(ctx_ptr, &tctr, 2 + 2 + 4 + 2); digest_update(ctx_ptr, rdata, rdata_size); } s32 digest_size = digest_get_size(ctx_ptr); //digest_final_copy_bytes(ctx_ptr, ds->digest_buffer, sizeof(ds->digest_buffer)); digest_final(ctx_ptr); #if DEBUG_CRYPTO_INTERNALS log_debug("dnskey_signature_verify: digest value"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, digest_get_digest_ptr(ctx_ptr), digest_size, 32); #endif ds->digest_size = digest_size; ds->has_digest = 1; } else { // digest has already been computed, only need to ready the signature, // the rr0 and the fqdn #if DEBUG_CRYPTO_INTERNALS log_debug("dnskey_signature_verify: digest already computed"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, digest_get_digest_ptr(ctx_ptr), ds->digest_size, 32); #endif /// @TODO 20210218 edf -- add optional signature verification") // owner_fqdn = dnskey_get_domain(key); // never read // owner_fqdn_len = dnsname_len(owner_fqdn); // never read //signature = &hdr.header.fqdn_signature[owner_fqdn_len]; // rr0 = ptr_vector_get(rrset, 0); // never read // fqdn = view_vtbl->get_fqdn(data, rr0); // never read } const u8 *signature_rdata = view_vtbl->get_rdata(ds->rr_view->data, in_rrsig_rr); u16 signature_rdata_size = view_vtbl->get_rdata_size(ds->rr_view->data, in_rrsig_rr); u32 rrsig_signer_name_len = dnsname_len(rrsig_get_signer_name_from_rdata(signature_rdata, signature_rdata_size)); u32 rrsig_header_len = RRSIG_RDATA_HEADER_LEN + rrsig_signer_name_len; u16 signature_size = signature_rdata_size - rrsig_header_len; const u8 *signature = &signature_rdata[rrsig_header_len]; #if DEBUG_CRYPTO_INTERNALS log_debug("dnskey_signature_verify: signature value"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, signature, signature_size, 32); #endif void *digest_ptr; digest_get_digest(ctx_ptr, &digest_ptr); bool verified = key->vtbl->dnssec_key_verify_digest(key, digest_ptr, ds->digest_size, signature, signature_size); #if DEBUG_CRYPTO_INTERNALS log_debug("dnskey_signature_verify: %s", (verified)?"verified":"wrong"); #endif return (verified)?SUCCESS:ERROR; } void dnskey_signature_finalize(dnskey_signature *ds) { if(ds->has_digest) { digest_finalise(&ds->digest_ctx); } } ya_result dnskey_sign_rrset_with_maxinterval(const dnssec_key *key, ptr_vector *rrset, bool canonize, resource_record_view *view, s32 maxinterval, void **out_rrsig_rr) { if(dnskey_is_private(key)) { dnskey_signature ds; dnskey_signature_init(&ds); #if 1 s32 from_epoch = MAX(((s64)time(NULL)) - DNSKEY_SIGN_TIME_LENIENCY, 0); if(dnskey_has_explicit_activate(key)) { from_epoch = MAX(from_epoch, dnskey_get_activate_epoch(key)); } #else s32 from_epoch = MAX(time(NULL) - DNSKEY_SIGN_TIME_LENIENCY, 0); #endif s32 to_epoch = dnskey_get_inactive_epoch(key); // if the key will be inactive well after the maxinterval, use maxinterval to the life-time of the signature if(to_epoch - from_epoch > maxinterval + DNSKEY_SIGN_TIME_LENIENCY) // + 86400 : don't limit down for a small period of overhead { if(((s64)from_epoch + (s64)maxinterval) <= MAX_S32) // check for doomsday { to_epoch = from_epoch + maxinterval; } else { log_warn("dnskey_sign_rrset_with_maxinterval(%{dnsname}, ..., %i, %p)", dnskey_get_domain(key), maxinterval, out_rrsig_rr); to_epoch = MAX_S32; } } // else limit to the expiration time of the signature #if 0 from_epoch -= DNSKEY_SIGN_TIME_LENIENCY; // give some leniency for the validity start #endif dnskey_signature_set_validity(&ds, from_epoch, to_epoch); dnskey_signature_set_view(&ds, view); dnskey_signature_set_rrset_reference(&ds, rrset); dnskey_signature_set_canonised(&ds, !canonize); ya_result ret = dnskey_signature_sign(&ds, key, out_rrsig_rr); dnskey_signature_finalize(&ds); return ret; } else { return DNSSEC_ERROR_KEYRING_KEY_IS_NOT_PRIVATE; } } /* ya_result dnskey_signature_rrset_verify(dnskey_signature *ds, const dnssec_key *key, ptr_vector *rrset, resource_record_view *view) { } */ /** * @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/dnsname.c0000644000000000000000000000013214505005532021121 xustar000000000000000030 mtime=1695812442.379981286 30 atime=1695812445.791030139 30 ctime=1695812494.559728605 yadifa-2.6.5-11201/lib/dnscore/src/dnsname.c0000664000374500037450000021667114505005532021100 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore * @ingroup dnscore * @brief Functions used to manipulate dns formatted names and labels * * DNS names are stored in many ways: * _ C string : ASCII with a '\0' sentinel * _ DNS wire : label_length_byte + label_bytes) ending with a label_length_byte with a value of 0 * _ simple array of pointers to labels * _ simple stack of pointers to labels (so the same as above, but with the order reversed) * _ sized array of pointers to labels * _ sized stack of pointers to labels (so the same as above, but with the order reversed) * * @{ */ #define DNSNAME_C_ 1 #include "dnscore/dnscore-config.h" #include #include #include #include #include "dnscore/dnscore-config.h" #include "dnscore/sys_types.h" const u8 __LOCASE_TABLE__[256] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; #include "dnscore/dnsname.h" #include "dnscore/rfc.h" #include "dnscore/zalloc.h" #define DNSNAMED_TAG 0x44454d414e534e44 /***************************************************************************** * * BUFFER * *****************************************************************************/ /** @brief Converts a C string to a dns name. * * Converts a C string to a dns name. * * @param[in] str a pointer to the source c-string * @param[in] name a pointer to a buffer that will get the full dns name * * @return Returns the length of the string */ /* TWO uses */ /* * This table contains TRUE for both expected name terminators */ static bool cstr_to_dnsname_terminators[256] = { TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, /* '\0' */ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, /* '.' */ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, }; /** * 0: out of space * 1: in space * -1: terminator * * => * * test the map * signed -> terminator * zero -> out of space * */ #if !HAS_FULL_ASCII7 /* * The list of characters that are valid in a zone: * - _ 0..9 A..Z a..z * */ static s8 cstr_to_dnsname_map[256] = {// 0 1 2 3 4 5 6 7 8 9 A B C D E F -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 (HEX) */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1,-1, 0, /* 20 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 30 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 50 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; /* * The list of characters that are valid in a zone: - _ 0..9 A..Z a..z */ static s8 cstr_to_dnsname_map_nostar[256] = {// 0 1 2 3 4 5 6 7 8 9 A B C D E F -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 (HEX) */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,-1, 0, /* 20 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 30 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 50 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; #else static s8 cstr_to_dnsname_map[256] = { -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 (HEX) */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1, 1, /* 20 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static s8 cstr_to_dnsname_map_nostar[256] = { -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 (HEX) */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1, 1, /* 20 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; #endif // ASCII7 charset instead of strict DNS /** * This is a set for rname in the SOA TYPE * * 0: out of space * 1: in space * -1: terminator * * => * * test the map * signed -> terminator * zero -> out of space * */ #if !HAS_FULL_ASCII7 static const s8 cstr_to_dnsrname_map[256] = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 (HEX) */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,-1, 0, /* 20 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 30 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, 0, 1, /* 50 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; #else static const s8 cstr_to_dnsrname_map[256] = { -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 (HEX) */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1, 1, /* 20 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, /* 50 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; #endif /** * char DNS charset test * * @param c * @return TRUE iff c in in the DNS charset * */ bool dnsname_is_charspace(u8 c) { return cstr_to_dnsname_map[c] == 1; } s32 dnslabel_compare(const u8 *a, const u8 *b) { int len = MIN(*a, *b); int d = memcmp(a+1, b+1, len); if(d == 0) { d = *a; d -= *b; } return d; } /** * label DNS charset test * * @param label * @return TRUE iff each char in the label in in the DNS charset * */ bool dnslabel_verify_charspace(const u8 *label) { u8 n = *label; if(n > MAX_LABEL_LENGTH) { return FALSE; } const u8 *const limit = &label[n]; while(++label < limit) { u8 c = *label; if(cstr_to_dnsname_map[c] != 1) { return FALSE; } } return TRUE; } /** * dns name DNS charset test * * @param name_wire * @return TRUE if each char in the name is in the DNS charset * */ bool dnsname_verify_charspace(const u8 *name_wire) { u8 n; for(;;) { n = *name_wire; if(n == 0) { return TRUE; } if(n > MAX_LABEL_LENGTH) { return FALSE; } const u8 *const limit = &name_wire[n]; while(++name_wire <= limit) { u8 c = *name_wire; if(cstr_to_dnsname_map[c] != 1) { return FALSE; } } } } /** * label DNS charset test and set to lower case * * @param label * @return TRUE iff each char in the label in in the DNS charset * */ bool dnslabel_locase_verify_charspace(u8 *label) { u8 n = *label; if(n > MAX_LABEL_LENGTH) { return FALSE; } u8 * const limit = &label[n]; while(++label <= limit) { u8 c = *label; if(cstr_to_dnsname_map[c] != 1) { return FALSE; } *label = LOCASE(c); } return TRUE; } /** * dns name DNS charset test and set to lower case * * @param name_wire * @return TRUE iff each char in the name is in the DNS charset * */ bool dnsname_locase_verify_charspace(u8 *name_wire) { u8 n; for(;;) { n = *name_wire; if(n == 0) { return TRUE; } if(n > MAX_LABEL_LENGTH) { return FALSE; } u8 * const limit = &name_wire[n]; while(++name_wire <= limit) { u8 c = *name_wire; if(cstr_to_dnsname_map[c] != 1) { return FALSE; } *name_wire = LOCASE(c); } } } /** * dns name DNS charset test and set to lower case * * LOCASE is done using tolower(c) * * @param name_wire * @return TRUE iff each char in the name in in the DNS charset * */ bool dnsname_locase_verify_extended_charspace(u8 *name_wire) { u8 n; for(;;) { n = *name_wire; if(n == 0) { return TRUE; } if(n > MAX_LABEL_LENGTH) { return FALSE; } u8 * const limit = &name_wire[n]; while(++name_wire <= limit) { u8 c = *name_wire; if(cstr_to_dnsname_map[c] != 1) { return FALSE; } *name_wire = tolower(c); } } } /** * @brief Converts a C string to a dns name. * * Converts a C string to a dns name. * * @param[in] name_parm a pointer to a buffer that will get the full dns name * @param[in] str a pointer to the source c-string * * @return Returns the length of the string up to the last '\0' */ ya_result cstr_to_dnsname(u8* name_parm, const char* str) { u8 * const limit = &name_parm[MAX_DOMAIN_LENGTH]; u8 *s = name_parm; u8 *p = &name_parm[1]; u8 c; for(c = *str++;; c = *str++) { if(!cstr_to_dnsname_terminators[c] /*(c != '.') && (c != '\0')*/) { *p = c; } else { u8 l = p - s - 1; *s = l; s = p; if(l == 0) { break; } if(l > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } if(c == '\0') { if(p >= limit) { return DOMAIN_TOO_LONG; } *s++ = '\0'; break; } } if(++p > limit) { return DOMAIN_TOO_LONG; } } return s - name_parm; } ya_result cstr_to_locase_dnsname(u8* name_parm, const char* str) { u8 * const limit = &name_parm[MAX_DOMAIN_LENGTH]; u8 *s = name_parm; u8 *p = &name_parm[1]; u8 c; for(c = *str++;; c = *str++) { if(!cstr_to_dnsname_terminators[c] /*(c != '.') && (c != '\0')*/) { *p = LOCASE(c); } else { u8 l = p - s - 1; *s = l; s = p; if(l == 0) { break; } if(l > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } if(c == '\0') { if(p >= limit) { return DOMAIN_TOO_LONG; } *s++ = '\0'; break; } } if(++p > limit) { return DOMAIN_TOO_LONG; } } return s - name_parm; } ya_result charp_to_dnsname(u8* name_parm, const char* str, u32 str_len) { const char * const limit = &str[str_len]; u8 *s = name_parm; u8 *p = &name_parm[1]; u8 c; if(str_len >= MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } for(c = *str++; ; c = *str++) { if((str <= limit) && !cstr_to_dnsname_terminators[c] /*(c != '.') && (c != '\0')*/) { *p = c; } else { u8 l = p - s - 1; *s = l; s = p; if(l == 0) { break; } if(l > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } if(str >= limit) { *s++ = '\0'; break; } } ++p; } return s - name_parm; } ya_result charp_to_locase_dnsname(u8* name_parm, const char* str, u32 str_len) { const char * const limit = &str[str_len]; u8 *s = name_parm; u8 *p = &name_parm[1]; u8 c; if(str_len >= MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } for(c = *str++; ; c = *str++) { if((str <= limit) && !cstr_to_dnsname_terminators[c] /*(c != '.') && (c != '\0')*/) { *p = LOCASE(c); } else { u8 l = p - s - 1; *s = l; s = p; if(l == 0) { break; } if(l > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } if(str >= limit) { *s++ = '\0'; break; } } ++p; } return s - name_parm; } /** * Allows for '*' */ ya_result charp_to_locase_dnsname_with_check(u8* name_parm, const char* str, u32 str_len) { const char * const limit = &str[str_len]; u8 *s = name_parm; u8 *p = &name_parm[1]; u8 c; if(str_len >= MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } for(c = *str++; ; c = *str++) { if((str <= limit) && !cstr_to_dnsname_terminators[c] /*(c != '.') && (c != '\0')*/) { if(cstr_to_dnsname_map[c] == 0) { return INVALID_CHARSET; } *p = LOCASE(c); } else { u8 l = p - s - 1; *s = l; s = p; if(l == 0) { break; } if(l > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } if(str >= limit) { *s++ = '\0'; break; } } ++p; } return s - name_parm; } /** * @brief Converts a C string to a dns name and checks for validity * * Converts a C string to a dns name. * * @param[in] name_parm a pointer to a buffer that will get the full dns name * @param[in] str a pointer to the source c-string * * @return Returns the length of the string up to the last '\0' */ ya_result cstr_to_dnsname_with_check(u8* name_parm, const char* str) { u8 * const limit = &name_parm[MAX_DOMAIN_LENGTH]; u8 *s = name_parm; u8 *p = &name_parm[1]; u8 c; /* * I cannot check this in one go actually. * * It would work 99.9999999% of the time but if the string is "" and is at the end of a page it would overlap to a non-mapped * memory and crash. * */ if((str[0] == '.') && (str[1] == '\0')) { *name_parm = 0; return 1; } if(str[0] == '*') { if(str[1] == '\0') { name_parm[0] = 1; name_parm[1] = '*'; name_parm[2] = '\0'; return 3; } else if(str[1] == '.') { name_parm[0] = 1; name_parm[1] = '*'; str += 2; s += 2; p += 2; } else { return DOMAINNAME_INVALID; } } for(c = *str++;; c = *str++) { /* test if a switch/case is better (break mix issues for this switch in this particular loop) * * in theory this is test/jb/jz * a switch would be jmp [v] * */ if(cstr_to_dnsname_map_nostar[c] >= 0 /*(c != '.') && (c != '\0')*/) { if(cstr_to_dnsname_map_nostar[c] == 0) { return INVALID_CHARSET; } *p = c; } else { u8 l = p - s - 1; *s = l; s = p; if(l == 0) { if(c != '\0') { return DOMAINNAME_INVALID; } break; } if(l > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } if(c == '\0') { if(p >= limit) { return DOMAIN_TOO_LONG; } *s++ = '\0'; break; } } if(++p > limit) { return DOMAIN_TOO_LONG; } } return s - name_parm; } ya_result cstr_to_dnsname_with_check_len(u8* name_parm, const char* text, u32 text_len) { /* * . => 1 => 00 => 1 * * a => 1 => 01 'A' 00 => 3 * a.b => 3 => 01 'A' 01 'B' 00 => 5 * a.b. => 4 => 01 'A' 01 'B' 00 => 5 * */ u8 *label_start = name_parm; u8 *p = &name_parm[1]; u8 c; /* * I cannot check this in one go actually. * * It would work 99.9999999% of the time but if the string is "" and is at the end of a page it would overlap to a non-mapped * memory and crash. * */ if(text_len == 0) { return DOMAINNAME_INVALID; } if(text[0] == '.') { if(text_len == 1) { *name_parm = 0; return 1; } else { return DOMAINNAME_INVALID; } } if(text[0] != '*') { // ensure the length is acceptable u32 output_len = text_len + 1; if(text[text_len - 1] != '.') { output_len += 1; } if(output_len > MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } } else { if(text_len == 1) // '*' { name_parm[0] = 1; name_parm[1] = '*'; name_parm[2] = '\0'; return 3; } else if(text[1] == '.') // '*.????' note: at this point str_len is 2 or more { // ensure the length is acceptable u32 output_len = text_len + 1; if(text[text_len - 1] != '.') { output_len += 1; } if(output_len > MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } name_parm[0] = 1; name_parm[1] = '*'; if(text_len == 2) { name_parm[2] = '\0'; return 3; } text += 2; label_start += 2; p += 2; } else // '*????' { return DOMAINNAME_INVALID; } } const char * const text_limit = &text[text_len]; for(c = *text++; ; c = *text++) { /* test if a switch/case is better (break mix issues for this switch in this particular loop) * * in theory this is test/jb/jz * a switch would be jmp [v] * */ if(cstr_to_dnsname_map_nostar[c] >= 0) // (c != '.') && (c != '\0') { if(cstr_to_dnsname_map_nostar[c] == 0) { return INVALID_CHARSET; } *p++ = c; if(text == text_limit) { // close the label u8 label_length = p - label_start - 1; // size of the label if(label_length > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } *label_start = label_length; // close the fqdn *p++ = 0; return p - name_parm; } } else // reached '.' or end of cstr (which should not occur in this algorithm) { u8 label_length = p - label_start - 1; // size of the label /* if(label_length == 0) // .. case { if(c != '\0') { return DOMAINNAME_INVALID; } break; } */ if(label_length > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } *label_start = label_length; if(text == text_limit) { *p++ = '\0'; return p - name_parm; } label_start = p; p++; } } } ya_result cstr_to_locase_dnsname_with_check_len(u8* name_parm, const char* text, u32 text_len) { /* * . => 1 => 00 => 1 * * a => 1 => 01 'A' 00 => 3 * a.b => 3 => 01 'A' 01 'B' 00 => 5 * a.b. => 4 => 01 'A' 01 'B' 00 => 5 * */ u8 *label_start = name_parm; u8 *p = &name_parm[1]; u8 c; /* * I cannot check this in one go actually. * * It would work 99.9999999% of the time but if the string is "" and is at the end of a page it would overlap to a non-mapped * memory and crash. * */ if(text_len == 0) { return DOMAINNAME_INVALID; } if(text[0] == '.') { if(text_len == 1) { *name_parm = 0; return 1; } else { return DOMAINNAME_INVALID; } } if(text[0] != '*') { // ensure the length is acceptable u32 output_len = text_len + 1; if(text[text_len - 1] != '.') { output_len += 1; } if(output_len > MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } } else { if(text_len == 1) // '*' { name_parm[0] = 1; name_parm[1] = '*'; name_parm[2] = '\0'; return 3; } else if(text[1] == '.') // '*.????' note: at this point str_len is 2 or more { // ensure the length is acceptable u32 output_len = text_len + 1; if(text[text_len - 1] != '.') { output_len += 1; } if(output_len > MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } name_parm[0] = 1; name_parm[1] = '*'; if(text_len == 2) { name_parm[2] = '\0'; return 3; } text += 2; label_start += 2; p += 2; } else // '*????' { return DOMAINNAME_INVALID; } } const char * const text_limit = &text[text_len]; for(c = *text++; ; c = *text++) { /* test if a switch/case is better (break mix issues for this switch in this particular loop) * * in theory this is test/jb/jz * a switch would be jmp [v] * */ if(cstr_to_dnsname_map_nostar[c] >= 0) // (c != '.') && (c != '\0') { if(cstr_to_dnsname_map_nostar[c] == 0) { return INVALID_CHARSET; } *p++ = LOCASE(c); if(text == text_limit) { // close the label u8 label_length = p - label_start - 1; // size of the label if(label_length > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } *label_start = label_length; // close the fqdn *p++ = 0; return p - name_parm; } } else // reached '.' or end of cstr (which should not occur in this algorithm) { u8 label_length = p - label_start - 1; // size of the label /* if(label_length == 0) // .. case { if(c != '\0') { return DOMAINNAME_INVALID; } break; } */ if(label_length > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } *label_start = label_length; if(text == text_limit) { *p++ = '\0'; return p - name_parm; } label_start = p; p++; } } } ya_result cstr_to_dnsname_with_check_len_with_origin(u8* name_parm, const char* text, u32 text_len, const u8 *origin) { /* * . => 1 => 00 => 1 * * a => 1 => 01 'A' 00 => 3 * a.b => 3 => 01 'A' 01 'B' 00 => 5 * a.b. => 4 => 01 'A' 01 'B' 00 => 5 * */ u8 *label_start = name_parm; u8 *p = &name_parm[1]; u8 c; /* * I cannot check this in one go actually. * * It would work 99.9999999% of the time but if the string is "" and is at the end of a page it would overlap to a non-mapped * memory and crash. * */ if(text_len == 0) { return DOMAINNAME_INVALID; } if(text[0] == '.') { if(text_len == 1) { *name_parm = 0; return 1; } else { return DOMAINNAME_INVALID; } } if(text[0] != '*') { // ensure the length is acceptable u32 output_len = text_len + 1; if(text[text_len - 1] != '.') { output_len += 1; } if(output_len > MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } } else { if(text_len == 1) // '*' { name_parm[0] = 1; name_parm[1] = '*'; ya_result return_value = dnsname_copy(&name_parm[2], origin) + 2; return return_value; } else if(text[1] == '.') // '*.????' note: at this point str_len is 2 or more { // ensure the length is acceptable u32 output_len = text_len + 1; if(text[text_len - 1] != '.') { output_len += 1; } if(output_len > MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } name_parm[0] = 1; name_parm[1] = '*'; if(text_len == 2) { name_parm[2] = '\0'; return 3; } text += 2; label_start += 2; p += 2; } else // '*????' { return DOMAINNAME_INVALID; } } const char * const text_limit = &text[text_len]; for(c = *text++; ; c = *text++) { /* test if a switch/case is better (break mix issues for this switch in this particular loop) * * in theory this is test/jb/jz * a switch would be jmp [v] * */ if(cstr_to_dnsname_map_nostar[c] >= 0) // (c != '.') && (c != '\0') { if(cstr_to_dnsname_map_nostar[c] == 0) { return INVALID_CHARSET; } *p++ = c; if(text == text_limit) { // close the label u8 label_length = p - label_start - 1; // size of the label if(label_length > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } *label_start = label_length; // close the fqdn ya_result return_value = dnsname_copy(p, origin) + p - name_parm; return return_value; } } else // reached '.' or end of cstr (which should not occur in this algorithm) { u8 label_length = p - label_start - 1; // size of the label if(label_length > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } *label_start = label_length; if(text == text_limit) { *p++ = '\0'; return p - name_parm; } label_start = p; p++; } } } ya_result cstr_to_locase_dnsname_with_check_len_with_origin(u8* name_parm, const char* text, u32 text_len, const u8 *origin) { /* * . => 1 => 00 => 1 * * a => 1 => 01 'A' 00 => 3 * a.b => 3 => 01 'A' 01 'B' 00 => 5 * a.b. => 4 => 01 'A' 01 'B' 00 => 5 * */ u8 *label_start = name_parm; u8 *p = &name_parm[1]; u8 c; /* * I cannot check this in one go actually. * * It would work 99.9999999% of the time but if the string is "" and is at the end of a page it would overlap to a non-mapped * memory and crash. * */ if(text_len == 0) { return DOMAINNAME_INVALID; } if(text[0] == '.') { if(text_len == 1) { *name_parm = 0; return 1; } else { return DOMAINNAME_INVALID; } } if(text[0] != '*') { // ensure the length is acceptable u32 output_len = text_len + 1; if(text[text_len - 1] != '.') { output_len += 1; } if(output_len > MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } } else { if(text_len == 1) // '*' { name_parm[0] = 1; name_parm[1] = '*'; //ya_result return_value = dnsname_copy(&name_parm[2], origin) + 2; ya_result return_value = dnsname_canonize(origin, &name_parm[2]) + 2; return return_value; } else if(text[1] == '.') // '*.????' note: at this point str_len is 2 or more { // ensure the length is acceptable u32 output_len = text_len + 1; if(text[text_len - 1] != '.') { output_len += 1; } if(output_len > MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } name_parm[0] = 1; name_parm[1] = '*'; if(text_len == 2) { name_parm[2] = '\0'; return 3; } text += 2; label_start += 2; text_len -= 2; p += 2; } else // '*????' { return DOMAINNAME_INVALID; } } const char * const text_limit = &text[text_len]; for(c = *text++; ; c = *text++) { /* test if a switch/case is better (break mix issues for this switch in this particular loop) * * in theory this is test/jb/jz * a switch would be jmp [v] * */ if(cstr_to_dnsname_map_nostar[c] >= 0) // (c != '.') && (c != '\0') { if(cstr_to_dnsname_map_nostar[c] == 0) { return INVALID_CHARSET; } *p++ = LOCASE(c); if(text == text_limit) { // close the label u8 label_length = p - label_start - 1; // size of the label if(label_length > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } *label_start = label_length; // close the fqdn ya_result return_value = dnsname_copy(p, origin) + p - name_parm; return return_value; } } else // reached '.' or end of cstr (which should not occur in this algorithm) { u8 label_length = p - label_start - 1; // size of the label if(label_length > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } *label_start = label_length; if(text == text_limit) { if(label_length > 0) { *p++ = '\0'; } return p - name_parm; } label_start = p; p++; } } } /** * @brief Converts a C string to a dns rname and checks for validity * * Converts a C string to a dns rname. * * @param[in] name_parm a pointer to a buffer that will get the full dns name * @param[in] str a pointer to the source c-string * * @return the length of the string up to the last '\0' */ ya_result cstr_to_dnsrname_with_check(u8* name_parm, const char* str) { u8 * const limit = &name_parm[MAX_DOMAIN_LENGTH]; u8 *s = name_parm; u8 *p = &name_parm[1]; u8 c; bool escaped = FALSE; /* * I cannot check this in one go actually. * * It would work 99.9999999% of the time but if the string is "" and is at the end of a page it would overlap to a non-mapped * memory and crash. * */ for(c = *str++;; c = *str++) { /* test if a switch/case is better (break mix issues for this switch in this particular loop) * * in theory this is test/jb/jz * a switch would be jmp [v] * mmhh ... * */ if((cstr_to_dnsrname_map[c] >= 0) /*(c != '.') && (c != '\0')*/ || escaped) { if(!escaped) { if(cstr_to_dnsrname_map[c] == 0) { return INVALID_CHARSET; } /* escape character */ /* AFAIK there is only one escape : '\', so why use an indexed memory to test it ? if (cstr_to_dnsrname_map[c] == 2) */ if(c == '\\') { escaped = TRUE; /* reading the next char here is wrong is the record is corrupt and ends with my-wrong-rname\. */ continue; } } *p = c; escaped = FALSE; } else { u8 l = p - s - 1; *s = l; s = p; if(l == 0) { if(c != '\0') { return DOMAINNAME_INVALID; } break; } if(l > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } if(c == '\0') { if(p >= limit) { return DOMAIN_TOO_LONG; } *s++ = '\0'; break; } } if(++p > limit) { return DOMAIN_TOO_LONG; } } if(escaped) { return DOMAINNAME_INVALID; } return s - name_parm; } /* ONE use */ ya_result cstr_get_dnsname_len(const char* str) { ya_result total = 0; const char* start; if(*str == '.') { str++; } s32 label_len; do { char c; start = str; do { c = *str++; } while(c != '.' && c != '\0'); label_len = (str - start) - 1; if(label_len > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } total += label_len + 1; if(c == '\0') { if(label_len != 0) { total++; } break; } } while(label_len != 0); return total; } /** @brief Converts a dns name to a C string * * Converts a dns name to a C string * * @param[in] name a pointer to the source dns name * @param[in] str a pointer to a buffer that will get the c-string * * @return Returns the length of the string */ /* FOUR uses */ u32 dnsname_to_cstr(char* dest_cstr, const u8* name) { #if DEBUG yassert(name != NULL); #endif char* start = dest_cstr; u8 len; len = *name++; if(len != 0) { do { MEMCOPY(dest_cstr, name, len); dest_cstr += len; *dest_cstr++ = '.'; name += len; len = *name++; } while(len != 0); } else { *dest_cstr++ = '.'; } *dest_cstr = '\0'; return (u32)(dest_cstr - start); } /** @brief Tests if two DNS labels are equals * * Tests if two DNS labels are equals * * @param[in] name_a a pointer to a dnsname to compare * @param[in] name_b a pointer to a dnsname to compare * * @return Returns TRUE if names are equal, else FALSE. */ /* ELEVEN uses */ #if !DNSCORE_HAS_MEMALIGN_ISSUES bool dnslabel_equals(const u8* name_a, const u8* name_b) { u8 len = *name_a; if(len != *name_b) { return FALSE; } len++; /* Hopefully the compiler just does register renaming */ const u32* name_a_32 = (const u32*)name_a; const u32* name_b_32 = (const u32*)name_b; int idx; int len4 = len & ~3; for(idx = 0; idx < len4; idx += 4) { if(GET_U32_AT(name_a[idx]) != GET_U32_AT(name_b[idx])) { return FALSE; } } /* Hopefully the compiler just does register renaming */ name_a = (const u8*)name_a_32; name_b = (const u8*)name_b_32; switch(len & 3) { case 0: return TRUE; case 1: return name_a[idx] == name_b[idx]; case 2: return GET_U16_AT(name_a[idx]) == GET_U16_AT(name_b[idx]); case 3: return (GET_U16_AT(name_a[idx]) == GET_U16_AT(name_b[idx])) && (name_a[idx+2] == name_b[idx+2]); } // icc complains here but is wrong. // this line cannot EVER be reached assert(FALSE); /* NOT zassert */ return FALSE; } #else bool dnslabel_equals(const u8* name_a, const u8* name_b) { u8 len = *name_a; if(*name_b == len) { return memcmp(name_a + 1, name_b + 1, len) == 0; } return FALSE; } #endif /** @brief Tests if two DNS labels are (case-insensitive) equals * * Tests if two DNS labels are (case-insensitive) equals * * @param[in] name_a a pointer to a dnsname to compare * @param[in] name_b a pointer to a dnsname to compare * * @return Returns TRUE if names are equal, else FALSE. */ #if !DNSCORE_HAS_MEMALIGN_ISSUES bool dnslabel_equals_ignorecase_left1(const u8* name_a, const u8* name_b) { int len = (int)* name_a; if(len != (int)* name_b) { return FALSE; } len++; /* * Label size must match */ int idx; int len4 = len & ~3; for(idx = 0; idx < len4; idx += 4) { if(!LOCASEEQUALSBY4(&name_a[idx], &name_b[idx])) /* can be used because left is locase */ { return FALSE; } } /* Hopefully the compiler just does register renaming */ switch(len & 3) { case 0: return TRUE; case 1: return LOCASEEQUALS(name_a[idx], name_b[idx]); /* can be used because left is locase */ case 2: return LOCASEEQUALSBY2(&name_a[idx], &name_b[idx]); /* can be used because left is locase */ case 3: return LOCASEEQUALSBY3(&name_a[idx], &name_b[idx]); /* can be used because left is locase */ } assert(FALSE); /* NOT zassert */ return FALSE; } bool dnslabel_equals_ignorecase_left2(const u8* name_a, const u8* name_b) { int len = (int)* name_a; if(len != (int)* name_b) { return FALSE; } for(int i = 1; i < len; ++i) { //if(__LOCASE_TABLE__[name_a[i]] != __LOCASE_TABLE__[name_b[i]]) if(name_a[i] != __LOCASE_TABLE__[name_b[i]]) { return FALSE; } } return TRUE; } bool dnslabel_equals_ignorecase_left3(const u8* name_a, const u8* name_b) { int len = (int)* name_a; if(len != (int)* name_b) { return FALSE; } for(name_a++, name_b++; len > 4; len -= 4, name_a += 4, name_b += 4) { //if(__LOCASE_TABLE__[name_a[i]] != __LOCASE_TABLE__[name_b[i]]) u32 w = GET_U32_AT_P(name_a); u32 x = GET_U32_AT_P(name_b); if((w & 0xff) != __LOCASE_TABLE__[x & 0xff]) { return FALSE; } w >>= 8; x >>= 8; if((w & 0xff) != __LOCASE_TABLE__[x & 0xff]) { return FALSE; } w >>= 8; x >>= 8; if((w & 0xff) != __LOCASE_TABLE__[x & 0xff]) { return FALSE; } w >>= 8; x >>= 8; if((w) != __LOCASE_TABLE__[x]) { return FALSE; } } for(int i = 0; i < len; ++i) { //if(__LOCASE_TABLE__[name_a[i]] != __LOCASE_TABLE__[name_b[i]]) if(name_a[i] != __LOCASE_TABLE__[name_b[i]]) { return FALSE; } } return TRUE; } bool dnslabel_equals_ignorecase_left4(const u8* name_a, const u8* name_b) { int len = (int)* name_a; if(len != (int)* name_b) { return FALSE; } for(name_a++, name_b++; len > 4; len -= 4, name_a += 4, name_b += 4) { //if(__LOCASE_TABLE__[name_a[i]] != __LOCASE_TABLE__[name_b[i]]) u32 w = GET_U32_AT_P(name_a); u32 x = GET_U32_AT_P(name_b); u32 z = (u32)__LOCASE_TABLE__[x & 0xff] | ((u32)__LOCASE_TABLE__[(x >> 8) & 0xff] << 8) | ((u32)__LOCASE_TABLE__[(x >> 16) & 0xff] << 16) | ((u32)__LOCASE_TABLE__[(x >> 24) & 0xff] << 24); if(w != z) { return FALSE; } } for(int i = 0; i < len; ++i) { //if(__LOCASE_TABLE__[name_a[i]] != __LOCASE_TABLE__[name_b[i]]) if(name_a[i] != __LOCASE_TABLE__[name_b[i]]) { return FALSE; } } return TRUE; } bool dnslabel_equals_ignorecase_left5(const u8* name_a, const u8* name_b) { return strcasecmp((const char*)name_a, (const char*)name_b) == 0; } #else /** * This WILL work with label size too since a label size is 0->63 * which is well outside the [A-Za-z] space. */ bool dnslabel_equals_ignorecase_left(const u8* name_a, const u8* name_b) { return strcasecmp((const char*)name_a, (const char*)name_b) == 0; } #endif /** @brief Tests if two DNS names are equals * * Tests if two DNS labels are equals * * @param[in] name_a a pointer to a dnsname to compare * @param[in] name_b a pointer to a dnsname to compare * * @return Returns TRUE if names are equal, else FALSE. */ /* TWO uses */ bool dnsname_equals(const u8* name_a, const u8* name_b) { int la = dnsname_len(name_a); int lb = dnsname_len(name_b); if(la == lb) { return memcmp(name_a, name_b, la) == 0; } return FALSE; } /* * Comparison of a name by label */ int dnsname_compare(const u8* name_a, const u8* name_b) { for(;;) { s8 la = (s8)name_a[0]; s8 lb = (s8)name_b[0]; name_a++; name_b++; if(la == lb) { if( la > 0) { int c = memcmp(name_a, name_b, la); if( c != 0) { return c; } } else { return 0; } } else { int c = memcmp(name_a, name_b, MIN(la,lb)); if( c == 0) { c = la - lb; } return c; } name_a += la; name_b += lb; } } bool dnsname_is_subdomain(const u8* subdomain, const u8* domain) { #if !HAS_FULL_ASCII7 u32 len = dnsname_len(domain); u32 sub_len = dnsname_len(subdomain); if(sub_len >= len) { subdomain += sub_len - len; if(domain[0] == subdomain[0]) { int ret = memcmp(subdomain, domain, len); return ret == 0; } } #else dnsname_stack subdomain_stack; dnsname_stack domain_stack; s32 subdomain_top = dnsname_to_dnsname_stack(subdomain, &subdomain_stack); s32 domain_top = dnsname_to_dnsname_stack(domain, &domain_stack); if(subdomain_top >= domain_top) { for(int i = 0; i <= domain_top; ++i) { const u8 *sublabel = subdomain_stack.labels[i]; const u8 *label = domain_stack.labels[i]; if(!dnslabel_equals(sublabel, label)) { return FALSE; } } return TRUE; } #endif return FALSE; } /** @brief Tests if two DNS names are (ignore case) equals * * Tests if two DNS labels are (ignore case) equals * * @param[in] name_a a pointer to a LO-CASE dnsname to compare * @param[in] name_b a pointer to a dnsname to compare * * @return Returns TRUE if names are equal, else FALSE. */ /* TWO uses */ bool dnsname_equals_ignorecase1(const u8* name_a, const u8* name_b) { int len; do { len = (int)*name_a++; if(len != (int)*name_b++) { return FALSE; } if(len == 0) { return TRUE; } while(len > 4 && (LOCASEEQUALSBY4(name_a++,name_b++))) { len--; } while(len > 0 && (LOCASEEQUALS(*name_a++,*name_b++))) { len--; } } while(len == 0); return FALSE; } bool dnsname_equals_ignorecase2(const u8* name_a, const u8* name_b) { int len; for(int i = 0;; ++i) { len = (int)name_a[i]; if(len != (int)name_b[i]) { return FALSE; } if(len == 0) { return TRUE; } len += i; for(; i < len; ++i) { if(__LOCASE_TABLE__[name_a[i]] != __LOCASE_TABLE__[name_b[i]]) { return FALSE; } } } } bool dnsname_equals_ignorecase3(const u8* name_a, const u8* name_b) { int len_a = dnsname_len(name_a); int len_b = dnsname_len(name_b); return ((len_a == len_b) && (strncasecmp((const char*)name_a, (const char*)name_b, len_a) == 0)); } /** @brief Returns the full length of a dns name * * Returns the full length of a dns name * * @param[in] name a pointer to the dnsname * * @return The length of the dnsname, "." ( zero ) included */ /* SEVENTEEN uses (more or less) */ u32 dnsname_len(const u8 *name) { yassert(name != NULL); const u8 *start = name; u8 c; while((c = *name++) > 0) { name += c; } return name - start; } s32 dnsname_len_with_size(const u8 *name, size_t name_buffer_size) { yassert(name != NULL); const u8 *start = name; const u8 *limit = name + name_buffer_size; u8 c; while((c = *name++) > 0) { name += c; if(name >= limit) { return BUFFER_WOULD_OVERFLOW; } } return name - start; } s32 dnsname_len_checked_with_size(const u8 *name, size_t name_buffer_size) { yassert(name != NULL); const u8 *start = name; const u8 *limit = name + name_buffer_size; u8 c; while((c = *name++) > 0) { name += c; if(name >= limit) { return BUFFER_WOULD_OVERFLOW; } } s32 len = name - start; if(len > MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } return len; } ya_result dnsname_len_checked(const u8 *name) { yassert(name != NULL); ya_result total = 0; u8 c; while((c = *name++) > 0) { name += c; total += c; if(total > MAX_DOMAIN_LENGTH) { return DOMAIN_TOO_LONG; } } return total + 1; } s32 dnsname_len_with_limit(const u8 *name, const u8 *name_limit) { yassert(name != NULL); const u8 *start = name; u8 c; for(;;) { if(name >= name_limit) { return DOMAINNAME_INVALID; } c = *name; name += c; if(c == 0) { break; } ++name; } return name - start; } /* ONE use */ u32 dnsname_getdepth(const u8 *name) { yassert(name != NULL); u32 d = 0; u8 c; while((c = *name) > 0) { name += c + 1; d++; } return d; } u8* dnsname_dup(const u8* src) { u8 *dst; u32 len = dnsname_len(src); MALLOC_OR_DIE(u8*, dst, len, DNSNAMED_TAG); MEMCOPY(dst, src, len); return dst; } void dnsname_free(u8* ptr) { #if DEBUG u32 len = dnsname_len(ptr); memset(ptr, 0xfe, len); #endif free(ptr); } /* ONE use */ u32 dnsname_copy(u8* dst, const u8* src) { u32 len = dnsname_len(src); MEMCOPY(dst, src, len); return len; } ya_result dnsname_copy_checked(u8* dst, const u8* src) { ya_result len = dnsname_len_checked(src); if(ISOK(len)) { MEMCOPY(dst, src, len); } return len; } /** @brief Canonizes a dns name. * * Canonizes a dns name. (A.K.A : lo-cases it) * * @param[in] src a pointer to the dns name * @param[out] dst a pointer to a buffer that will hold the canonized dns name * * @return The length of the dns name */ /* TWELVE uses */ u32 dnsname_canonize(const u8* src, u8* dst) { const u8* org = src; u32 len; for(;;) { len = *src++; *dst++ = len; if(len == 0) { break; } while(len > 0) { *dst++ = LOCASE(*src++); /* Works with the dns character set */ len--; } } return (u32)(src - org); } /***************************************************************************** * * VECTOR * *****************************************************************************/ /* NO use (test) */ u32 dnslabel_vector_to_dnsname(const_dnslabel_vector_reference name, s32 top, u8* str_start) { u8* str = str_start; const_dnslabel_vector_reference limit = &name[top]; while(name <= limit) { const u8* label = *name++; u8 len = label[0] + 1; MEMCOPY(str, label, len); str += len; } *str++ = 0; return str - str_start; } /* NO use (test) */ u32 dnslabel_vector_to_cstr(const_dnslabel_vector_reference name, s32 top, char* str) { const_dnslabel_vector_reference limit = &name[top]; char* start = str; while(name < limit) { const u8* label = *name++; u8 len = *label++; MEMCOPY(str, label, len); str += len; *str++ = '.'; } *str++ = '\0'; return (u32)(str - start); } /* ONE use */ u32 dnslabel_vector_dnslabel_to_dnsname(const u8 *prefix, const dnsname_vector *namestack, s32 bottom, u8 *str) { u8* start = str; u32 len = *prefix; MEMCOPY(str, prefix, len + 1); str += len + 1; const_dnslabel_vector_reference name = &namestack->labels[bottom]; u32 top = (u32)namestack->size; while(bottom <= (s32)top) { const u8* label = *name++; u32 len = *label; MEMCOPY(str, label, len + 1); str += len + 1; bottom--; } *str++ = '\0'; return (u32)(str - start); } u32 dnslabel_vector_len(const_dnslabel_vector_reference name, s32 top) { u32 ret = 1; for(s32 i = 0; i <= top; i++) { ret += name[i][0]; } return ret; } /* ONE use */ u32 dnsname_vector_sub_to_dnsname(const dnsname_vector *name, s32 from, u8 *name_start) { u8* str = name_start; const_dnslabel_vector_reference limit = &name->labels[name->size]; const_dnslabel_vector_reference labelp = &name->labels[from]; while(labelp <= limit) { u32 len = *labelp[0] + 1; MEMCOPY(str, *labelp, len); str += len; labelp++; } *str++ = 0; return str - name_start; } /** @brief Divides a name into sections * * Divides a name into sections. * Writes a pointer to each label of the dnsname into an array * "." is never put in there. * * @param[in] name a pointer to the dnsname * @param[out] sections a pointer to the target array of pointers * * @return The index of the top-level label ("." is never put in there) */ /* TWO uses */ s32 dnsname_to_dnslabel_vector(const u8 *dns_name, dnslabel_vector_reference labels) { yassert(dns_name != NULL && labels != NULL); s32 idx = -1; int offset = 0; for(;;) { u32 len = dns_name[offset]; if(len == 0) { break; } labels[++idx] = &dns_name[offset]; offset += len + 1; } return idx; } /** @brief Divides a name into sections * * Divides a name into sections. * Writes a pointer to each label of the dnsname into an array * "." is never put in there. * * @param[in] name a pointer to the dnsname * @param[out] sections a pointer to the target array of pointers * * @return The index of the top-level label ("." is never put in there) */ /* TWENTY-ONE uses */ s32 dnsname_to_dnsname_vector(const u8* dns_name, dnsname_vector* name) { yassert(dns_name != NULL && name != NULL); s32 size = dnsname_to_dnslabel_vector(dns_name, name->labels); name->size = size; return size; } u32 dnsname_vector_copy(dnsname_vector* dst, const dnsname_vector* src) { dst->size = src->size; if(dst->size > 0) { memcpy((void*)&dst->labels[0], &src->labels[0], sizeof(u8*) * dst->size); } return dst->size; } u32 dnsname_vector_len(dnsname_vector *name_vector) { u32 len = 1; for(s32 size = 0; size <= name_vector->size; size++) { len += name_vector->labels[size][0] + 1; } return len; } /***************************************************************************** * * STACK * *****************************************************************************/ /** @brief Converts a stack of dns labels to a C string * * Converts a stack of dns labels to a C string * * @param[in] name a pointer to the dnslabel stack * @param[in] top the index of the top of the stack * @param[in] str a pointer to a buffer that will get the c-string * * @return Returns the length of the string */ /* ONE use */ u32 dnslabel_stack_to_cstr(const_dnslabel_stack_reference name, s32 top, char* str) { char* start = str; if(top >= 0) { do { const u8* label = name[top]; u8 len = *label++; MEMCOPY(str, label, len); str += len; *str++ = '.'; top--; } while(top >= 0); } else { *str++ = '.'; } *str++ = '\0'; return (u32)(str - start); } /* ONE use */ u32 dnslabel_stack_to_dnsname(const_dnslabel_stack_reference name, s32 top, u8* str_start) { u8* str = str_start; const_dnslabel_stack_reference base = name; name += top; while(name >= base) { const u8* label = *name--; u32 len = *label; MEMCOPY(str, label, len + 1); str += len + 1; } *str++ = '\0'; return (u32)(str - str_start); } s32 dnsname_to_dnslabel_stack(const u8* dns_name, dnslabel_stack_reference labels) { s32 label_pointers_top = -1; const u8 * label_pointers[MAX_LABEL_COUNT]; for(;;) { u8 len = *dns_name; if(len == 0) { break; } label_pointers[++label_pointers_top] = dns_name; dns_name += len + 1; } s32 size = label_pointers_top; const u8** labelp = labels; while(label_pointers_top >= 0) { *labelp++ = (u8*)label_pointers[label_pointers_top--]; } return size; } /* ONE use */ u32 dnsname_stack_to_dnsname(const dnsname_stack *name_stack, u8 *name_start) { u8* name = name_start; for(s32 size = name_stack->size; size >= 0; size--) { u32 len = name_stack->labels[size][0] + 1; MEMCOPY(name, name_stack->labels[size], len); name += len; } *name++ = '\0'; return name - name_start; } u32 dnsname_stack_len(const dnsname_stack* name_stack) { u32 len = 1; for(s32 size = 0; size <= name_stack->size; size++) { len += name_stack->labels[size][0] + 1; } return len; } /* TWO uses (debug) */ u32 dnsname_stack_to_cstr(const dnsname_stack* name, char* str) { return dnslabel_stack_to_cstr(name->labels, name->size, str); } /* ONE use */ bool dnsname_equals_dnsname_stack(const u8* str, const dnsname_stack* name) { s32 size = name->size; while(size >= 0) { const u8* label = name->labels[size]; u8 len = *label; if(len != *str) { return FALSE; } label++; str++; if(memcmp(str, label, len) != 0) { return FALSE; } str += len; size--; } return *str == 0; } bool dnsname_under_dnsname_stack(const u8* str, const dnsname_stack* name) { s32 size = name->size; while(size >= 0) { const u8* label = name->labels[size]; u8 len = *label; if(len != *str) { return (len != 0); } label++; str++; if(memcmp(str, label, len) != 0) { return FALSE; } str += len; size--; } return *str == 0; } /* FOUR uses */ s32 dnsname_stack_push_label(dnsname_stack* dns_name, const u8* dns_label) { yassert(dns_name != NULL && dns_label != NULL); dns_name->labels[++dns_name->size] = dns_label; return dns_name->size; } /* FOUR uses */ s32 dnsname_stack_pop_label(dnsname_stack* name) { yassert(name != NULL); #if DEBUG name->labels[name->size] = (u8*)~0; #endif return name->size--; } s32 dnsname_to_dnsname_stack(const u8* dns_name, dnsname_stack* name) { s32 label_pointers_top = -1; u8 * label_pointers[MAX_LABEL_COUNT]; for(;;) { u8 len = *dns_name; if(len == 0) { break; } label_pointers[++label_pointers_top] = (u8*)dns_name; dns_name += len + 1; } name->size = label_pointers_top; const u8** labelp = name->labels; while(label_pointers_top >= 0) { *labelp++ = label_pointers[label_pointers_top--]; } return name->size; } /** @brief Allocates and duplicates a name with ZALLOC. * * Allocates and duplicates a dns name with ZALLOC. * * @param[in] name a pointer to the dnsname * * @return A new instance of the dnsname. */ u8* dnsname_zdup(const u8* name) { yassert(name != NULL); u32 len = dnsname_len(name); u8* dup; ZALLOC_OBJECT_ARRAY_OR_DIE(dup, u8, len, ZDB_NAME_TAG); MEMCOPY(dup, name, len); // nothing wrong here return dup; } /** @brief Converts a name to a newly allocated dns name with ZALLOC. * * Converts a name to a newly allocated dns name with ZALLOC. * * @param domainname a pointer to the name * * @return a new instance of the name converted to a dnsname */ u8* dnsname_zdup_from_name(const char* domainname) { yassert(domainname != NULL); u32 len = cstr_get_dnsname_len(domainname); ya_result ret; u8* dup; ZALLOC_OBJECT_ARRAY_OR_DIE(dup, u8, len, ZDB_NAME_TAG); if(ISOK(ret = cstr_to_dnsname_with_check(dup, domainname))) { } else { ZFREE_ARRAY(dup, len); dup = NULL; } return dup; } void dnsname_zfree(u8 *name) { ZFREE_ARRAY(name, dnsname_len(name)); } /** @brief Allocates and duplicates a label with ZALLOC. * * Allocates and duplicates a label with ZALLOC. * * @param[in] name a pointer to the label * * @return A new instance of the label */ u8* dnslabel_zdup(const u8* name) { yassert(name != NULL); u32 len = name[0] + 1; u8* dup; ZALLOC_OBJECT_ARRAY_OR_DIE(dup, u8, len, ZDB_LABEL_TAG); MEMCOPY(dup, name, len); return dup; } void dnslabel_zfree(u8 *name) { u32 len = name[0] + 1; ZFREE_ARRAY(name, len); (void)len; // silences warning on some build settings } /** * * Expands a compressed FQDN from a wire. * * @param wire_base_ the address of the wire buffer * @param wire_size the size of the wire buffer * @param compressed_fqdn the address, in the wire buffer, of the FQDN to expand * @param output_fqdn the address of the buffer that will get a copy of the expanded FQDN * @param output_fqdn_size the size of the buffer that will get a a copy of the expanded FQDN * * @return a pointer to the next byte after the expanded FQDN (ie: points to a type) or NULL if an error occurred */ const u8* dnsname_expand_compressed(const void *wire_base_, size_t wire_size, const void *compressed_fqdn, u8 *output_fqdn, u32 output_fqdn_size) { const u8 *base = (const u8*)wire_base_; const u8 *p_limit = &base[wire_size]; yassert(output_fqdn_size >= MAX_DOMAIN_LENGTH); u8 *buffer = output_fqdn; u8 * const buffer_limit = &buffer[output_fqdn_size]; // pointer to the byte that must never be reached const u8 *p = (const u8*)compressed_fqdn; const u8 *ret_ptr; if((p < base) || (p >= p_limit)) { return NULL; /* EOF */ } for(;;) { u8 len = *p++; // get the next byte (length) if((len & 0xc0) == 0xc0) // test if it's a compressed code { ret_ptr = p + 1; /* reposition the pointer */ u32 new_offset = len & 0x3f; new_offset <<= 8; new_offset |= *p; p = &base[new_offset]; if(p < p_limit) // ensure we are not outside the message { break; } return NULL; } if((p + len >= p_limit) || (buffer + len + 1 >= buffer_limit)) { return NULL; } *buffer++ = len; if(len == 0) { return p; } u8 *label_limit = &buffer[len]; do { *buffer++ = tolower(*p++); } while(buffer < label_limit); } for(;;) { u8 len = *p; if((len & 0xc0) == 0xc0) /* EDF: better yet: cmp len, 192; jge */ { /* reposition the pointer */ u32 new_offset = len & 0x3f; new_offset <<= 8; new_offset |= p[1]; const u8* q = &base[new_offset]; if(q < p) { p = q; continue; } return NULL; } if((p + len >= p_limit) || (buffer + len + 1>= buffer_limit)) { return NULL; } *buffer++ = len; if(len == 0) { return ret_ptr; } ++p; u8 *label_limit = &buffer[len]; do { *buffer++ = tolower(*p++); } while(buffer < label_limit); } // never reached } /** * * Skip a compressed FQDN from a wire to position right after the FQDN. * * @param wire_base_ the address of the wire buffer * @param wire_size the size of the wire buffer * @param compressed_fqdn the address, in the wire buffer, of the FQDN to expand * * @return a pointer to the next byte after the FQDN (ie: points to a type) or NULL if an error occurred */ const u8* dnsname_skip_compressed(const void *wire_base_, size_t wire_size, const void *compressed_fqdn) { const u8 *base = (const u8*)wire_base_; const u8 *p_limit = &base[wire_size]; const u8 *p = (const u8*)compressed_fqdn; if((p < base) || (p >= p_limit)) { return NULL; /* EOF */ } for(;;) { u8 len = *p++; if((len & 0xc0) == 0xc0) { return p + 1; // yes, read the purpose of the function } if(len == 0) { return p; } p += len; if(p >= p_limit) { return NULL; } } // never reached } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/empty-input-stream.c0000644000000000000000000000013214505005532023260 xustar000000000000000030 mtime=1695812442.465982518 30 atime=1695812445.795030196 30 ctime=1695812494.561728633 yadifa-2.6.5-11201/lib/dnscore/src/empty-input-stream.c0000664000374500037450000000754714505005532023237 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include "dnscore/empty-input-stream.h" #define EIS_CLOSED 2 #define EIS_READONCE 1 #define EIS_CANREADMASK (EIS_CLOSED|EIS_READONCE) #define EIS_CANREAD 0 struct empty_input_stream_overload { union { void* _voidp; u32 flags; } data; const input_stream_vtbl *vtbl; }; typedef struct empty_input_stream_overload empty_input_stream_overload; static ya_result empty_input_stream_read(input_stream *stream_, void* buffer, u32 len) { yassert(stream_ != NULL); empty_input_stream_overload *eis = (empty_input_stream_overload*)stream_; // mutant stream (void)buffer; (void)len; if((eis->data.flags & EIS_CANREADMASK) == EIS_CANREAD) // closed read-once { if(len > 0) { eis->data.flags |= EIS_READONCE; // read-once } return 0; } else { return -1; } } static void empty_input_stream_close(input_stream *stream_) { yassert(stream_ != NULL); empty_input_stream_overload *eis = (empty_input_stream_overload*)stream_; // mutant stream eis->data.flags |= EIS_CLOSED; } static ya_result empty_input_stream_skip(input_stream *stream_, u32 len) { yassert(stream_ != NULL); empty_input_stream_overload *eis = (empty_input_stream_overload*)stream_; // mutant stream if((eis->data.flags & EIS_CANREADMASK) == EIS_CANREAD) // closed read-once { if(len > 0) { eis->data.flags |= EIS_READONCE; // read-once } return 0; } else { return -1; } } static const input_stream_vtbl empty_input_stream_vtbl ={ empty_input_stream_read, empty_input_stream_skip, empty_input_stream_close, "empty_input_stream" }; void empty_input_stream_init(input_stream *stream) { stream->data = NULL; stream->vtbl = &empty_input_stream_vtbl; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/error_state.c0000644000000000000000000000013214505005532022025 xustar000000000000000030 mtime=1695812442.470982589 30 atime=1695812445.795030196 30 ctime=1695812494.563728662 yadifa-2.6.5-11201/lib/dnscore/src/error_state.c0000664000374500037450000000723414505005532021775 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/error_state.h" #include "dnscore/logger.h" bool error_state_log(error_state_t *es, ya_result err) { bool log_message = FALSE; if(es->error != err) { s64 now = timeus(); es->error = err; es->count = 1; es->first_epoch = now; es->last_epoch = now; log_message = TRUE; } else { ++es->count; s64 now = timeus(); if(now - es->last_epoch >= ERROR_STATE_FAILURE_LOG_PERIOD) { log_message = TRUE; es->last_epoch = now; } } return log_message; } void error_state_clear(error_state_t *es, logger_handle *log_handle, int level, const char *notice_message) { if(es->error != 0) { s64 now = timeus(); if(now - es->last_epoch >= ERROR_STATE_FAILURE_LOG_PERIOD) { if((log_handle != NULL) && (notice_message != NULL)) { if(log_handle->active[level] != 0) { logger_handle_msg_nocull(log_handle, level, "%s recovered from a stream of %lli issues having occurred between %llT and %llT", notice_message, es->count, es->first_epoch, es->last_epoch); } } es->first_epoch = 0; es->last_epoch = 0; es->error = 0; es->count = 0; } } } bool error_state_log_locked(error_state_t *es, ya_result err) { mutex_lock(&es->mtx); bool ret = error_state_log(es, err); mutex_unlock(&es->mtx); return ret; } void error_state_clear_locked(error_state_t *es, logger_handle *log_handle, int level, const char *notice_message) { mutex_lock(&es->mtx); error_state_clear(es, log_handle, level, notice_message); mutex_unlock(&es->mtx); } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/fdtools.c0000644000000000000000000000013114505005532021145 xustar000000000000000030 mtime=1695812442.501983033 29 atime=1695812445.79603021 30 ctime=1695812494.565728691 yadifa-2.6.5-11201/lib/dnscore/src/fdtools.c0000664000374500037450000011646514505005532021125 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoretools Generic Tools * @ingroup dnscore * @brief * * @{ */ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #define FDTOOLS_C_ 1 #include "dnscore/fdtools.h" #include "dnscore/zalloc.h" #include "dnscore/ptr_set.h" #include "dnscore/timems.h" #include "dnscore/logger.h" #include "dnscore/mutex.h" #include "dnscore/error_state.h" /* GLOBAL VARIABLES */ extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #if DEBUG #define DEBUG_FD_OPEN_CLOSE_MONITOR 1 #else #define DEBUG_FD_OPEN_CLOSE_MONITOR 0 #endif #define FDTRACK_TAG 0x4b434152544446 #define MTIMESET_TAG 0x544553454d49544d #if DEBUG // avoids logging these operations in the logger. // this prevents a self-deadlock if the logger limit is reached (2^20 lines) bool logger_is_self(); #endif #if DEBUG static void admin_warn(const char *pathname) { uid_t uid = getuid(); uid_t euid = getuid(); gid_t gid = getgid(); gid_t egid = getegid(); bool is_admin = (uid==0)||(euid==0)||(gid==0)||(egid==0); if(is_admin) { printf("It is unlikely file or directory creation should be made as an admin '%s' (DEBUG)\n", pathname); fflush(NULL); } } #endif error_state_t nospace_error_state = ERROR_STATE_INITIALIZER; #if DEBUG_FD_OPEN_CLOSE_MONITOR // file descriptor track enabled #include "dnscore/u32_set.h" #include "dnscore/zalloc.h" #include "dnscore/error_state.h" static group_mutex_t fd_mtx = GROUP_MUTEX_INITIALIZER; static u32_set fd_to_name = U32_SET_EMPTY; struct fd_track { stacktrace opener; stacktrace closer; char name[256]; }; typedef struct fd_track fd_track; static void fd_set_name(int fd, const char *name) { fd_track *track; group_mutex_lock(&fd_mtx, GROUP_MUTEX_WRITE); log_debug6("file descriptor: %i is '%s'", fd, name); u32_node *node = u32_set_insert(&fd_to_name, fd); if(node->value == NULL) { ZALLOC_OBJECT_OR_DIE(track, fd_track, FDTRACK_TAG); node->value = track; track->opener = 0; track->closer = 0; track->name[0] = '\0'; } else { track = (fd_track*)node->value; if(track->name[0] != '\0') { log_err("file descriptor: %i was associated with '%s'", fd, track->name); } } strcpy_ex(track->name, name, sizeof(track->name)); track->opener = debug_stacktrace_get(); track->name[sizeof(track->name) - 1] = '\0'; group_mutex_unlock(&fd_mtx, GROUP_MUTEX_WRITE); } static void fd_clear_name(int fd) { group_mutex_lock(&fd_mtx, GROUP_MUTEX_WRITE); u32_node *node = u32_set_find(&fd_to_name, fd); if(node != NULL) { yassert(node->value != NULL); fd_track *track = (fd_track*)node->value; stacktrace st = debug_stacktrace_get(); if(track->name[0] != '\0') { log_debug6("file descriptor: %i is '%s' no more", fd, track->name); } else { log_debug6("file descriptor: %i is being closed by", fd); debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_DEBUG6, st); log_debug6("file descriptor: %i was closed already by", fd); debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_DEBUG6, track->closer); log_debug6("file descriptor: %i was last opened by", fd); debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_DEBUG6, track->opener); } track->closer = st; track->name[0] = '\0'; } else { stacktrace st = debug_stacktrace_get(); log_debug6("file descriptor: %i is untracked and is being closed by", fd); debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_DEBUG6, st); } group_mutex_unlock(&fd_mtx, GROUP_MUTEX_WRITE); } #endif /** * Writes fully the buffer to the fd * It will only return a short count for system errors. * ie: fs full, non-block would block, fd invalid/closed, ... */ ssize_t writefully(int fd, const void *buf, size_t count) { const u8* start = (const u8*)buf; const u8* current = start; ssize_t n; bool nospace = FALSE; while(count > 0) { if((n = write(fd, current, count)) <= 0) { if(n == 0) { break; } int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) /** @note It is nonsense to call writefully with a non-blocking fd */ { if(current - start > 0) { break; } if(nospace) { error_state_clear_locked(&nospace_error_state, NULL, 0, NULL); } return MAKE_ERRNO_ERROR(ETIMEDOUT); } if(err == ENOSPC) { // the disk is full : wait a bit, hope the admin catches it, try again later if(error_state_log_locked(&nospace_error_state, MAKE_ERRNO_ERROR(ENOSPC))) { log_err("filesystem full for file descriptor %i", fd); } nospace = TRUE; sleep((rand()&7) + 1); continue; } if(current - start > 0) { break; } if(nospace) { error_state_clear_locked(&nospace_error_state, NULL, 0, NULL); } return MAKE_ERRNO_ERROR(err); } current += n; count -= n; } if(nospace) { error_state_clear_locked(&nospace_error_state, NULL, 0, NULL); } return current - start; } /** * Reads fully the buffer from the fd * It will only return a short count for system errors. * ie: fs full, non-block would block, fd invalid/closed, ... */ ssize_t readfully(int fd, void *buf, size_t length) { u8* start = (u8*)buf; u8* current = start; ssize_t n; while(length > 0) { if((n = read(fd, current, length)) <= 0) { if(n == 0) // end of file { break; } int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) /** @note It is nonsense to call readfully with a non-blocking fd */ { break; } if(current - start > 0) { break; } return -1; } current += n; length -= n; } return current - start; } /** * Writes fully the buffer to the fd * It will only return a short count for system errors. * ie: fs full, non-block would block, fd invalid/closed, ... */ ssize_t writefully_limited(int fd, const void *buf, size_t count, double minimum_rate_us) { const u8* start = (const u8*)buf; const u8* current = start; ssize_t n; bool nospace = FALSE; u64 tstart = timeus(); // ASSUMED : timeout set on fd for read & write while(count > 0) { if((n = write(fd, current, count)) <= 0) { if(n == 0) { break; } int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) { /* * Measure the current elapsed time * Measure the current bytes * compare with the minimum rate * act on it */ /* t is in us */ u64 now = timeus(); u64 time_elapsed_u64 = now - tstart; if(time_elapsed_u64 >= ONE_SECOND_US) { double time_elapsed_us = time_elapsed_u64; double bytes_written = (current - (u8*)buf) * ONE_SECOND_US_F; double expected_bytes_written = minimum_rate_us * time_elapsed_us; if(bytes_written < expected_bytes_written) /* bytes/time < minimum_rate */ { if(nospace) { error_state_clear_locked(&nospace_error_state, NULL, 0, NULL); } #if DEBUG log_warn("writefully_limited: rate of %fBps < %fBps (%fµs)", bytes_written, expected_bytes_written, time_elapsed_us); #else log_debug("writefully_limited: rate of %fBps < %fBps (%fµs)", bytes_written, expected_bytes_written, time_elapsed_us); #endif return TCP_RATE_TOO_SLOW; } } continue; } if(err == ENOSPC) { // the disk is full : wait a bit, hope the admin catches it, try again later if(error_state_log_locked(&nospace_error_state, MAKE_ERRNO_ERROR(ENOSPC))) { log_err("filesystem full for file descriptor %i", fd); } nospace = TRUE; sleep((rand()&7) + 1); continue; } if(current - start > 0) { break; } if(nospace) { error_state_clear_locked(&nospace_error_state, NULL, 0, NULL); } return ERROR; } current += n; count -= n; } if(nospace) { error_state_clear_locked(&nospace_error_state, NULL, 0, NULL); } return current - start; } /** * Reads fully the buffer from the fd * It will only return a short count for system errors. * ie: fs full, non-block would block, fd invalid/closed, ... */ ssize_t readfully_limited(int fd, void *buf, size_t count, double minimum_rate_us) { u8* start = (u8*)buf; u8* current = start; ssize_t n; u64 tstart = timeus(); // ASSUME : timeout set on fd for read & write while(count > 0) { if((n = read(fd, current, count)) <= 0) { if(n == 0) { break; } int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) /** @note It is nonsense to call readfully with a non-blocking fd */ { /* * Measure the current elapsed time * Measure the current bytes * compare with the minimum rate * act on it */ u64 now = timeus(); /* t is in us */ u64 time_elapsed_u64 = now - tstart; double time_elapsed_us = time_elapsed_u64; if(time_elapsed_u64 >= ONE_SECOND_US) { double bytes_read = (current - (u8*)buf) * ONE_SECOND_US_F; double expected_bytes_read = minimum_rate_us * time_elapsed_us; if(bytes_read < expected_bytes_read) // bytes/time < minimum_rate { time_elapsed_us /= 1000000.0; #if DEBUG log_warn("readfully_limited: rate of %fBps < %fBps (%fµs) (DEBUG)", bytes_read, expected_bytes_read, time_elapsed_us); #else log_debug("readfully_limited: rate of %fBps < %fBps (%fµs)", bytes_read, expected_bytes_read, time_elapsed_us); #endif return TCP_RATE_TOO_SLOW; } } continue; } if(current - start > 0) { break; } return -1; /* EOF */ } current += n; count -= n; } return current - start; } /** * Reads fully the buffer from the fd * It will only return a short count for system errors. * ie: fs full, non-block would block, fd invalid/closed, ... */ ssize_t readfully_limited_ex(int fd, void *buf, size_t count, s64 timeout_us, double minimum_rate_us) { u8* start = (u8*)buf; u8* current = start; ssize_t n; if(timeout_us <= 0) { timeout_us = 1; } s64 tstart = timeus(); // ASSUME : timeout set on fd for read & write while(count > 0) { if((n = read(fd, current, count)) <= 0) { if(n == 0) { break; } int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) /** @note It is nonsense to call readfully with a non-blocking fd */ { /* * Measure the current elapsed time * Measure the current bytes * compare with the minimum rate * act on it */ s64 now = timeus(); /* t is in us */ s64 time_elapsed_u64 = now - tstart; double time_elapsed_us = time_elapsed_u64; if(time_elapsed_u64 >= timeout_us) { double bytes_read = (current - (u8*)buf); bytes_read *= ONE_SECOND_US_F; bytes_read /= time_elapsed_u64; double expected_bytes_read = minimum_rate_us * time_elapsed_us; if(bytes_read < expected_bytes_read) // bytes/time < minimum_rate { time_elapsed_us /= 1000000.0; #if DEBUG log_warn("readfully_limited: rate of %fBps < %fBps (%fµs) (DEBUG)", bytes_read, expected_bytes_read, time_elapsed_us); #else log_debug("readfully_limited: rate of %fBps < %fBps (%fµs)", bytes_read, expected_bytes_read, time_elapsed_us); #endif return TCP_RATE_TOO_SLOW; } } continue; } if(current - start > 0) { break; } return -1; /* EOF */ } current += n; count -= n; } return current - start; } /** * Reads an ASCII text line from fd, stops at EOF or '\n' */ ssize_t readtextline(int fd, char *start, size_t count) { char *current = start; const char * const limit = &start[count]; while(current < limit) { ssize_t n; if((n = read(fd, current, 1)) > 0) { u8 c = *current; current++; count --; if(c == '\n') { break; } } else { if(n == 0) { break; } int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) { continue; } if(current - start > 0) { break; } return -1; } } return current - start; } /** * Deletes a file (see man 2 unlink). * Handles EINTR and other retry errors. * Safe to use in the logger thread as it only logs (debug) if the current * thread is not the logger's * * @param fd * @return */ int unlink_ex(const char *folder, const char *filename) { char fullpath[PATH_MAX]; size_t l0 = strlen(folder); size_t l1 = strlen(filename); if(l0 + l1 < sizeof(fullpath)) { memcpy(fullpath, folder, l0); fullpath[l0] = '/'; memcpy(&fullpath[l0 + 1], filename, l1); fullpath[l0 + 1 + l1] = '\0'; return unlink(fullpath); } else { errno = ENOMEM; return -1; } } /** * Copies the absolute path of a file into a buffer. * * @param filename the file name * @param buffer the output buffer * @param buffer_size the size of the output buffer * @return the string length (without the terminator) */ ya_result file_get_absolute_path(const char *filename, char *buffer, size_t buffer_size) { ya_result ret; if(filename[0] == '/') { strcpy_ex(buffer, filename, buffer_size); ret = strlen(buffer); return ret; } else { if(getcwd(buffer, buffer_size) == NULL) { return ERRNO_ERROR; } size_t n = strlen(buffer); if(n < buffer_size) { ret = n + 1; buffer += n; buffer_size -= n; *buffer++ = '/'; --buffer_size; n = strlen(filename); if(n < buffer_size) { memcpy(buffer, filename, n); buffer[n] = '\0'; return ret + n; } } return ERROR; // not enough room } } #if DEBUG_BENCH_FD static debug_bench_s debug_open; static debug_bench_s debug_open_create; static debug_bench_s debug_close; static bool fdtools_debug_bench_register_done = FALSE; static inline void fdtools_debug_bench_register() { if(!fdtools_debug_bench_register_done) { fdtools_debug_bench_register_done = TRUE; debug_bench_register(&debug_open, "open"); debug_bench_register(&debug_open_create, "open_create"); debug_bench_register(&debug_close, "close"); } } #endif /** * Opens a file. (see man 2 open) * Handles EINTR and other retry errors. * Safe to use in the logger thread as it only logs (debug) if the current * thread is not the logger's * * @param fd * @return */ ya_result open_ex(const char *pathname, int flags) { int fd; #if DEBUG if(!logger_is_self() && logger_is_running()) { log_debug6("open_ex(%s,%o)", STRNULL(pathname), flags); errno = 0; } #endif yassert(pathname != NULL); #if DEBUG_BENCH_FD fdtools_debug_bench_register(); u64 bench = debug_bench_start(&debug_open); #endif #if DNSCORE_FDTOOLS_CLOEXEC bool cloexec = (flags & O_CLOEXEC) != 0; flags &= ~O_CLOEXEC; #endif while((fd = open(pathname, flags)) < 0) { int err = errno; if(err != EINTR) { break; } } #if DNSCORE_FDTOOLS_CLOEXEC if((fd >= 0) && cloexec) { ya_result ret; if(FAIL(ret = fd_setcloseonexec(fd))) { log_warn("open_ex(%s,%o): failed to set CLOEXEC: %r", STRNULL(pathname), flags|O_CLOEXEC, ret); } } #endif #if DEBUG_BENCH_FD debug_bench_stop(&debug_open, bench); #endif #if DEBUG if(!logger_is_self() && logger_is_running()) { log_debug6("open_ex(%s,%o): %r (%i)", STRNULL(pathname), flags, ERRNO_ERROR, fd); #if DEBUG_FD_OPEN_CLOSE_MONITOR if(fd > 0) { fd_set_name(fd, pathname); } #endif } #endif return fd; } /** * Opens a file, create if it does not exist. (see man 2 open with O_CREAT) * Handles EINTR and other retry errors. * Safe to use in the logger thread as it only logs (debug) if the current * thread is not the logger's * * @param fd * @return */ ya_result open_create_ex(const char *pathname, int flags, mode_t mode) { int fd; /// @note do NOT : flags |= O_CREAT; #if DEBUG if(!logger_is_self() && logger_is_running()) { log_debug6("open_create_ex(%s,%o,%o)", STRNULL(pathname), flags, mode); errno = 0; } #endif #if DEBUG admin_warn(pathname); #endif yassert(pathname != NULL); #if DEBUG_BENCH_FD fdtools_debug_bench_register(); u64 bench = debug_bench_start(&debug_open_create); #endif while((fd = open(pathname, flags, mode)) < 0) { int err = errno; if(err != EINTR) { // do NOT set this to an error code other than -1 //fd = MAKE_ERRNO_ERROR(err); break; } } #if DEBUG_BENCH_FD debug_bench_stop(&debug_open_create, bench); #endif #if DEBUG if(!logger_is_self() && logger_is_running()) { log_debug6("open_create_ex(%s,%o,%o): %r (%i)", STRNULL(pathname), flags, mode, ERRNO_ERROR, fd); #if DEBUG_FD_OPEN_CLOSE_MONITOR if(fd > 0) { fd_set_name(fd, pathname); } #endif } #endif return fd; } int mkstemp_ex(char * tmp_name_template) { #if __unix__ int fd = mkstemp(tmp_name_template); #if DEBUG if(!logger_is_self() && logger_is_running()) { #if DEBUG_FD_OPEN_CLOSE_MONITOR if(fd > 0) { fd_set_name(fd, tmp_name_template); } #endif } #endif return fd; #else return -1; #endif } /** * Opens a file, create if it does not exist. (see man 2 open with O_CREAT) * Handles EINTR and other retry errors. * This version of open_create_ex does NOT log anything, which is very important sometimes in the logger thread * * @param fd * @return */ ya_result open_create_ex_nolog(const char *pathname, int flags, mode_t mode) { int fd; #if DEBUG admin_warn(pathname); #endif while((fd = open(pathname, flags, mode)) < 0) { int err = errno; if(err != EINTR) { // do NOT set this to an error code other than -1 //fd = MAKE_ERRNO_ERROR(err); break; } } return fd; } /** * Closes a file descriptor (see man 2 close) * Handles EINTR and other retry errors. * At return the file will be closed or not closable. * * @param fd * @return */ ya_result #if !DNSCORE_HAS_CLOSE_EX_REF close_ex(int fd) #else close_ex_ref(int* fdp) #endif { ya_result return_value = SUCCESS; #if DNSCORE_HAS_CLOSE_EX_REF int fd = *fdp; if(fd == -2) { abort(); } *fdp = -2; #endif #if DEBUG if(!logger_is_self() && logger_is_running()) { #if DEBUG_FD_OPEN_CLOSE_MONITOR if(fd > 0) { fd_clear_name(fd); } #endif log_debug6("close_ex(%i)", fd); errno = 0; } #endif #if DEBUG_BENCH_FD fdtools_debug_bench_register(); u64 bench = debug_bench_start(&debug_close); #endif while(close(fd) < 0) { int err = errno; if(err != EINTR) { return_value = MAKE_ERRNO_ERROR(err); break; } } #if DEBUG_BENCH_FD debug_bench_stop(&debug_close, bench); #endif #if DEBUG if(!logger_is_self() && logger_is_running()) { log_debug6("close_ex(%i): %r", fd, return_value); if(FAIL(return_value)) { logger_flush(); } } #endif return return_value; } /** * Closes a file descriptor (see man 2 close) * Handles EINTR and other retry errors. * At return the file will be closed or not closable. * * @param fd * @return */ ya_result #if !DNSCORE_HAS_CLOSE_EX_REF close_ex_nolog(int fd) #else close_ex_nolog_ref(int* fdp) #endif { ya_result return_value = SUCCESS; #if DNSCORE_HAS_CLOSE_EX_REF int fd = *fdp; if(fd == -2) { abort(); } *fdp = -2; #endif while(close(fd) < 0) { int err = errno; if(err != EINTR) { return_value = MAKE_ERRNO_ERROR(err); break; } } return return_value; } int fsync_ex(int fd) { #if __unix__ while(fsync(fd) < 0) { int err = errno; if(err != EINTR) { return ERRNO_ERROR; } } #else FlushFileBuffers((HANDLE)_get_osfhandle(fd)); #endif return SUCCESS; } int fdatasync_ex(int fd) { #if __unix__ #if defined(__linux__) while(fdatasync(fd) < 0) #else while(fsync(fd) < 0) #endif { int err = errno; if(err != EINTR) { return ERRNO_ERROR; } } #else FlushFileBuffers((HANDLE)_get_osfhandle(fd)); #endif return SUCCESS; } int dup_ex(int fd) { int ret; while((ret = dup(fd)) < 0) { int err = errno; if(err != EINTR) { return ERRNO_ERROR; } } return ret; } int dup2_ex(int old_fd, int new_fd) { int ret; while((ret = dup2(old_fd, new_fd)) < 0) { int err = errno; if(err != EINTR) { return ERRNO_ERROR; } } return ret; } int truncate_ex(const char *path, off_t len) { int ret; while((ret = truncate(path, len)) < 0) { int err = errno; if(err != EINTR) { return ERRNO_ERROR; } } return ret; } int ftruncate_ex(int fd, off_t len) { int ret; while((ret = ftruncate(fd, len)) < 0) { int err = errno; if(err != EINTR) { return ERRNO_ERROR; } } return ret; } /** * Returns the type of socket. * * @param fd the file descriptor of the socket * @return SOCK_STREAM, SOCK_DGRAM, SOCK_RAW or an errno error code like MAKE_ERRON_ERROR(EBADF) or MAKE_ERRON_ERROR(ENOTSOCK) */ ya_result fd_getsockettype(int fd) { int stype; socklen_t stype_len = sizeof(stype); int ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, &stype, &stype_len); if(ret >= 0) { return stype; // SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, ... } else { return ERRNO_ERROR; // expecting EBADF or ENOTSOCK } } s64 filesize(const char *name) { struct stat s; if(stat(name, &s) >= 0) // MUST be stat { if(S_ISREG(s.st_mode)) { return s.st_size; } } return (s64)ERRNO_ERROR; } /** * Checks for existence of a file/dir/link * * @param name the file name * * @return 1 if the file exists, 0 if the file does not exists, an error otherwise */ ya_result file_exists(const char *name) { struct stat s; #if __unix__ if(lstat(name, &s) >= 0) // MUST be lstat { return 1; } #else if(stat(name, &s) >= 0) // MUST be lstat { return 1; } #endif int err = errno; if(err == ENOENT) { return 0; } return MAKE_ERRNO_ERROR(err); } /** * * Checks if a file exists and is a link * * @param name the file name * * @return 0 : not a link * 1 : a link * < 0 : error */ ya_result file_is_link(const char *name) { #if __unix__ struct stat s; if(lstat(name, &s) >= 0) // MUST be lstat { return S_ISLNK(s.st_mode)?SUCCESS:ERROR; } return ERRNO_ERROR; #else return 0; #endif } /** * * Checks if a file exists and is a directory * * @param name the file name * * @return 0 : not a link * 1 : a link * < 0 : error */ ya_result file_is_directory(const char *name) { #if __unix__ struct stat s; if(lstat(name, &s) >= 0) // MUST be lstat { return S_ISDIR(s.st_mode)?SUCCESS:ERROR; } return ERRNO_ERROR; #else return 0; #endif } /** * * Creates all directories on pathname. * * Could be optimised a bit : * * try the biggest path first, * going down until it works, * then create back up. * * @param pathname * @param mode * @param flags * * @return */ int mkdir_ex(const char *pathname, mode_t mode, u32 flags) { #if DEBUG log_debug("mkdir_ex(%s,%o,%x)", pathname, mode, flags); #endif #if DEBUG admin_warn(pathname); #endif const char *s; char *t; char dir_path[PATH_MAX]; s = pathname; t = dir_path; if(pathname[0] == '/') { t[0] = '/'; t++; s++; } for(;;) { const char *p = (const char*)strchr(s, '/'); bool last = (p == NULL); if(last) { if((flags & MKDIR_EX_PATH_TO_FILE) != 0) { return s - pathname; } p = s + strlen(s); } intptr n = (p - s); memcpy(t, s, n); t[n] = '\0'; struct stat file_stat; if(stat(dir_path, &file_stat) < 0) { int err = errno; if(err != ENOENT) { #if DEBUG log_debug("mkdir_ex(%s,%o): stat returned %r", pathname, mode, MAKE_ERRNO_ERROR(err)); #endif return MAKE_ERRNO_ERROR(err); } if(mkdir(dir_path, mode) < 0) { #if DEBUG log_debug("mkdir_ex(%s,%o): mkdir(%s, %o) returned %r", pathname, mode, dir_path, mode, MAKE_ERRNO_ERROR(err)); #endif return ERRNO_ERROR; } } if(last) { s = &s[n]; return s - pathname; } t[n++] = '/'; t = &t[n]; s = &s[n]; } } /** * Returns the modification time of the file in microseconds * This does not mean the precision of the time is that high. * This is only to simplify reading the time on a file. * * @param name the file name * @param timestamp a pointer to the timestamp * @return an error code */ ya_result file_mtime(const char *name, s64 *timestamp) { struct stat st; yassert(name != NULL); yassert(timestamp != NULL); if(stat(name, &st) >= 0) { #ifdef WIN32 s64 ts = ONE_SECOND_US * st.st_mtime; #elif !__APPLE__ s64 ts = (ONE_SECOND_US * st.st_mtim.tv_sec) + (st.st_mtim.tv_nsec / 1000LL); #else s64 ts = (ONE_SECOND_US * st.st_mtimespec.tv_sec) + (st.st_mtimespec.tv_nsec / 1000LL); #endif *timestamp = ts; return SUCCESS; } else { *timestamp = 0; return ERRNO_ERROR; } } /** * Returns the modification time of the file in microseconds * This does not mean the precision of the time is that high. * This is only to simplify reading the time on a file. * * @param name the file name * @param timestamp a pointer to the timestamp * @return an error code */ ya_result fd_mtime(int fd, s64 *timestamp) { struct stat st; yassert(timestamp != NULL); if(fstat(fd, &st) >= 0) { #ifdef WIN32 s64 ts = ONE_SECOND_US * st.st_mtime; #elif !__APPLE__ s64 ts = (ONE_SECOND_US * st.st_mtim.tv_sec) + (st.st_mtim.tv_nsec / 1000LL); #else s64 ts = (ONE_SECOND_US * st.st_mtimespec.tv_sec) + (st.st_mtimespec.tv_nsec / 1000LL); #endif *timestamp = ts; return SUCCESS; } else { *timestamp = 0; return ERRNO_ERROR; } } ya_result fd_setcloseonexec(int fd) { #if __unix__ int ret = fcntl(fd, F_SETFD, FD_CLOEXEC); if(FAIL(ret)) { ret = ERRNO_ERROR; } return ret; #else return SUCCESS; #endif } ya_result fd_setnonblocking(int fd) { #if __unix__ int ret; if(ISOK(ret = fcntl(fd, F_GETFL, 0))) { fcntl(fd, F_SETFL, ret | O_NONBLOCK); } else { ret = ERRNO_ERROR; } return ret; #else return SUCCESS; #endif } /** * Fixes an issue with the dirent not always set as expected. * * The type can be set to DT_UNKNOWN instead of file or directory. * In that case the function will call stats to get the type. */ u8 dirent_get_type_from_fullpath(const char *fullpath) { struct stat file_stat; u8 d_type; d_type = DT_UNKNOWN; while(stat(fullpath, &file_stat) < 0) { int e = errno; if(e != EINTR) { log_err("stat(%s): %r", fullpath, ERRNO_ERROR); break; } } if(S_ISREG(file_stat.st_mode)) { d_type = DT_REG; } else if(S_ISDIR(file_stat.st_mode)) { d_type = DT_DIR; } return d_type; } u8 dirent_get_file_type(const char *folder, const char *name) { u8 d_type; char fullpath[PATH_MAX]; d_type = DT_UNKNOWN; /* * If the FS OR the OS does not support d_type : */ if(ISOK(snprintf(fullpath, sizeof(fullpath), "%s/%s", folder, name))) { d_type = dirent_get_type_from_fullpath(fullpath); } return d_type; } // typedef ya_result readdir_callback(const char *basedir, const char* file, u8 filetype, void *args); static group_mutex_t readdir_mutex = GROUP_MUTEX_INITIALIZER; ya_result readdir_forall(const char *basedir, readdir_callback *func, void *args) { DIR *dir; ya_result ret; size_t basedir_len = strlen(basedir); char *name; char path[PATH_MAX]; memcpy(path, basedir, basedir_len); path[basedir_len] = '/'; name = &path[basedir_len + 1]; dir = opendir(basedir); if(dir == NULL) { return ERRNO_ERROR; } for(;;) { group_mutex_lock(&readdir_mutex, GROUP_MUTEX_WRITE); struct dirent *tmp = readdir(dir); if(tmp == NULL) { group_mutex_unlock(&readdir_mutex, GROUP_MUTEX_WRITE); ret = SUCCESS; break; } // ignore names "." and ".." #if __unix__ const char* tmp_name = tmp->d_name; #else const char* tmp_name = tmp->name; #endif if(tmp_name[0] == '.') { if( ((tmp_name[1] == '.') && (tmp_name[2] == '\0')) || (tmp_name[1] == '\0') ) { group_mutex_unlock(&readdir_mutex, GROUP_MUTEX_WRITE); continue; } } size_t name_len = strlen(tmp_name); if(name_len + basedir_len + 1 + 1 > sizeof(path)) { group_mutex_unlock(&readdir_mutex, GROUP_MUTEX_WRITE); log_err("readdir_forall: '%s/%s' is bigger than expected (%i): skipping", basedir, tmp_name, sizeof(path)); continue; } memcpy(name, tmp_name, name_len + 1); group_mutex_unlock(&readdir_mutex, GROUP_MUTEX_WRITE); u8 d_type = dirent_get_type_from_fullpath(path); if(FAIL(ret = func(basedir, name, d_type, args))) { return ret; } switch(ret) { case READDIR_CALLBACK_CONTINUE: { break; } case READDIR_CALLBACK_ENTER: { if(d_type == DT_DIR) { if(FAIL(ret = readdir_forall(path, func, args))) { return ret; } if(ret == READDIR_CALLBACK_EXIT) { return ret; } } break; } case READDIR_CALLBACK_EXIT: { return ret; } default: { // unhandled code break; } } } closedir(dir); return ret; } struct file_mtime_set_s { ptr_set files_mtime; char *name; bool is_new; }; typedef struct file_mtime_set_s file_mtime_set_t; static ptr_set file_mtime_sets = { NULL, ptr_set_asciizp_node_compare}; static mutex_t file_mtime_sets_mtx; file_mtime_set_t* file_mtime_set_get_for_file(const char *filename) { file_mtime_set_t *ret; mutex_lock(&file_mtime_sets_mtx); ptr_node *sets_node = ptr_set_insert(&file_mtime_sets, (char*)filename); if(sets_node->value != NULL) { ret = (file_mtime_set_t*)sets_node->value; } else { sets_node->key = strdup(filename); ZALLOC_OBJECT_OR_DIE(ret, file_mtime_set_t, MTIMESET_TAG); ret->files_mtime.root = NULL; ret->files_mtime.compare = ptr_set_asciizp_node_compare; ret->name = strdup(filename); ret->is_new = TRUE; sets_node->value = ret; file_mtime_set_add_file(ret, filename); } mutex_unlock(&file_mtime_sets_mtx); return ret; } void file_mtime_set_add_file(file_mtime_set_t *ctx, const char *filename) { s64 mtime; if(FAIL(file_mtime(filename, &mtime))) { mtime = MIN_S64; } ptr_node *node = ptr_set_insert(&ctx->files_mtime, (char*)filename); if(node->value == NULL) { node->key = strdup(filename); node->value_s64 = mtime; } } bool file_mtime_set_modified(file_mtime_set_t *ctx) { if(ctx->is_new) { ctx->is_new = FALSE; return TRUE; } ptr_set_iterator iter; ptr_set_iterator_init(&ctx->files_mtime, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); const char *filename = (const char*)node->key; s64 mtime; if(ISOK(file_mtime(filename, &mtime))) { if(node->value_s64 < mtime) { return TRUE; } } else { return TRUE; } } return FALSE; } void file_mtime_set_clear(file_mtime_set_t *ctx) { ptr_set_iterator iter; ptr_set_iterator_init(&ctx->files_mtime, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); free(node->key); } ptr_set_destroy(&ctx->files_mtime); file_mtime_set_add_file(ctx, ctx->name); } void file_mtime_set_delete(file_mtime_set_t *ctx) { mutex_lock(&file_mtime_sets_mtx); ptr_set_delete(&file_mtime_sets, ctx->name); mutex_unlock(&file_mtime_sets_mtx); free(ctx->name); file_mtime_set_clear(ctx); ZFREE_OBJECT(ctx); } ya_result access_check(const char* path, int mode) { int ret; ret = access(path, mode); if(ret < 0) { ret = ERRNO_ERROR; } return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/file_input_stream.c0000644000000000000000000000013214505005532023205 xustar000000000000000030 mtime=1695812442.368981128 30 atime=1695812445.791030139 30 ctime=1695812494.568728734 yadifa-2.6.5-11201/lib/dnscore/src/file_input_stream.c0000664000374500037450000001773514505005532023164 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #if _FILE_OFFSET_BITS != 64 #define _LARGEFILE64_SOURCE #endif #include "dnscore/dnscore-config.h" #include #include #include #include #include #include "dnscore/file_input_stream.h" #include "dnscore/fdtools.h" #include "dnscore/timems.h" typedef struct file_input_stream file_input_stream; struct file_input_stream { union { void* _voidp; int fd; } data; const input_stream_vtbl* vtbl; }; #if DEBUG_BENCH_FD static debug_bench_s debug_read; static bool file_input_stream_debug_bench_register_done = FALSE; static inline void file_input_stream_debug_bench_register() { if(!file_input_stream_debug_bench_register_done) { file_input_stream_debug_bench_register_done = TRUE; debug_bench_register(&debug_read, "read"); } } #endif /* * Maybe I should not do a "read-fully" here ... */ static ya_result file_input_stream_read(input_stream* stream_, void* buffer_, u32 len) { #if DEBUG_BENCH_FD file_input_stream_debug_bench_register(); u64 bench = debug_bench_start(&debug_read); #endif u8 *buffer = (u8*)buffer_; file_input_stream* stream = (file_input_stream*)stream_; u8* start = buffer; while(len > 0) { #if defined(SSIZE_MAX) && (SSIZE_MAX < 0xffffffffU) ssize_t ret = read(stream->data.fd, buffer, MIN(len, SSIZE_MAX)); #else ssize_t ret = read(stream->data.fd, buffer, len); #endif if(ret < 0) { int err = errno; if(err == EINTR) { continue; } #if DEBUG if(err == EBADF) { fprintf(stderr, "bad file descriptor %i", stream->data.fd); } #endif if(buffer - start > 0) { return buffer - start; } /* error */ return MAKE_ERRNO_ERROR(err); } if(ret == 0) /* EOF */ { break; } buffer += ret; len -= ret; } #if DEBUG_BENCH_FD debug_bench_stop(&debug_read, bench); #endif return buffer - start; } static void file_input_stream_close(input_stream* stream_) { file_input_stream* stream = (file_input_stream*)stream_; assert((stream->data.fd < 0)||(stream->data.fd >2)); if(stream->data.fd != -1) { close_ex(stream->data.fd); stream->data.fd = -1; } input_stream_set_void(stream_); } static void file_input_stream_noclose(input_stream* stream_) { file_input_stream* stream = (file_input_stream*)stream_; assert((stream->data.fd < 0)||(stream->data.fd >2)); stream->data.fd = -1; input_stream_set_void(stream_); } static ya_result file_input_stream_skip(input_stream* stream_, u32 len) { file_input_stream* stream = (file_input_stream*)stream_; if(lseek(stream->data.fd, len, SEEK_CUR) >= 0) { return len; } return ERRNO_ERROR; } static const input_stream_vtbl file_input_stream_vtbl = { file_input_stream_read, file_input_stream_skip, file_input_stream_close, "file_input_stream" }; static const input_stream_vtbl file_input_stream_noclose_vtbl = { file_input_stream_read, file_input_stream_skip, file_input_stream_noclose, "file_input_stream-noclose" }; ya_result fd_input_stream_attach(input_stream *stream_, int fd) { file_input_stream* stream = (file_input_stream*)stream_; if(fd < 0) { return ERRNO_ERROR; } stream->data.fd = fd; stream->vtbl = &file_input_stream_vtbl; return SUCCESS; } ya_result fd_input_stream_attach_noclose(input_stream *stream_, int fd) { file_input_stream* stream = (file_input_stream*)stream_; if(fd < 0) { return ERRNO_ERROR; } stream->data.fd = fd; stream->vtbl = &file_input_stream_noclose_vtbl; return SUCCESS; } void fd_input_stream_detach(input_stream *stream_) { file_input_stream* stream = (file_input_stream*)stream_; stream->data.fd = -1; } ya_result file_input_stream_open(input_stream *stream_, const char *filename) { int fd = open_ex(filename, O_RDONLY|O_CLOEXEC); #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && !defined(__gnu__hurd__) if(fd >= 0) { posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); } #endif return fd_input_stream_attach(stream_, fd); } ya_result file_input_stream_open_ex(input_stream *stream_, const char *filename, int flags) { int fd = open_ex(filename, O_RDONLY|O_CLOEXEC| flags); #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && !defined(__gnu__hurd__) if(fd >= 0) { posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); } #endif return fd_input_stream_attach(stream_, fd); } ya_result fd_input_stream_get_filedescriptor(input_stream* stream_) { file_input_stream* stream = (file_input_stream*)stream_; return stream->data.fd ; } ya_result fd_input_stream_seek(input_stream* stream_, u64 offset) { if(is_fd_input_stream(stream_)) { file_input_stream* stream = (file_input_stream*)stream_; int ret; #if _FILE_OFFSET_BITS == 64 ret = lseek(stream->data.fd, offset, SEEK_SET); #else ret = lseek64(stream->data.fd, offset, SEEK_SET); #endif if(ret >= 0) { return SUCCESS; } else { return ERRNO_ERROR; } } else { return INCORRECT_RDATA; } } bool is_fd_input_stream(input_stream* stream_) { file_input_stream* stream = (file_input_stream*)stream_; return (stream != NULL) && (stream->vtbl->read == file_input_stream_read); } void file_input_steam_advise_sequential(input_stream* stream_) { #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && !defined(__gnu_hurd__) file_input_stream* stream = (file_input_stream*)stream_; if(stream->data.fd >= 0) { posix_fadvise(stream->data.fd, 0, 0, POSIX_FADV_SEQUENTIAL); } #else (void)stream_; #endif } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/file_output_stream.c0000644000000000000000000000013214505005532023406 xustar000000000000000030 mtime=1695812442.395981515 30 atime=1695812445.792030153 30 ctime=1695812494.570728762 yadifa-2.6.5-11201/lib/dnscore/src/file_output_stream.c0000664000374500037450000002562514505005532023362 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include "dnscore/file_output_stream.h" #include "dnscore/fdtools.h" #include "dnscore/error_state.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger extern error_state_t nospace_error_state; /* * This structure is supposed to match the output_stream one * It helps using the void* data as an int without a INT_AT(x) kind of macro */ typedef struct file_output_stream file_output_stream; struct file_output_stream { union { void *voidp; int fd; } data; const output_stream_vtbl* vtbl; }; static ya_result file_output_stream_write(output_stream* stream_, const u8* buffer, u32 len) { const file_output_stream* stream = (file_output_stream*)stream_; const u8* start = buffer; while(len > 0) { ssize_t ret = write(stream->data.fd, buffer, len); if(ret <= 0) { int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) { #if __FreeBSD__ || __OpenBSD__ || __APPLE__ int oldflags = fcntl (stream->data.fd, F_GETFL, 0); if(oldflags < 0) { return MAKE_ERRNO_ERROR(err); } #endif continue; } /* error */ return MAKE_ERRNO_ERROR(err); } buffer += ret; len -= (u32)ret; } return (ya_result)(buffer - start); } static ya_result file_output_stream_writefully(output_stream* stream_, const u8* buffer, u32 len) { const file_output_stream* stream = (file_output_stream*)stream_; const u8* start = buffer; bool nospace = FALSE; while(len > 0) { ssize_t ret = write(stream->data.fd, buffer, len); if(ret <= 0) { int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) { #if __FreeBSD__ || __OpenBSD__ || __APPLE__ int oldflags = fcntl (stream->data.fd, F_GETFL, 0); if(oldflags < 0) { return MAKE_ERRNO_ERROR(err); } #endif continue; } if(err == ENOSPC) { // the disk is full : wait a bit, hope the admin catches it, try again later if(error_state_log_locked(&nospace_error_state, MAKE_ERRNO_ERROR(ENOSPC))) { log_err("filesystem full for stream"); } nospace = TRUE; sleep((rand()&7) + 1); continue; } /* error */ return MAKE_ERRNO_ERROR(err); } buffer += ret; len -= (u32)ret; } if(nospace) { error_state_clear_locked(&nospace_error_state, NULL, 0, NULL); } return (ya_result)(buffer - start); } static ya_result file_output_stream_flush(output_stream* stream_) { file_output_stream* stream = (file_output_stream*)stream_; if(fsync_ex(stream->data.fd) == 0) /* or fdatasync ... maybe it would be slightly better */ { return SUCCESS; } return ERRNO_ERROR; } static void file_output_stream_close(output_stream* stream_) { file_output_stream* stream = (file_output_stream*)stream_; /* don't, it's only for a test that I did this assert((stream->data.fd < 0)||(stream->data.fd >2)); */ if(stream->data.fd != -1) /* harmless close but still ... */ { close_ex(stream->data.fd); } output_stream_set_void(stream_); } static void file_output_stream_noclose(output_stream* stream_) { file_output_stream* stream = (file_output_stream*)stream_; stream->data.fd = -1; output_stream_set_void(stream_); } static const output_stream_vtbl file_output_stream_noclose_vtbl ={ file_output_stream_write, file_output_stream_flush, file_output_stream_noclose, "file_output_stream-noclose", }; static const output_stream_vtbl file_output_stream_vtbl ={ file_output_stream_write, file_output_stream_flush, file_output_stream_close, "file_output_stream", }; static const output_stream_vtbl file_full_output_stream_vtbl ={ file_output_stream_writefully, file_output_stream_flush, file_output_stream_close, "file_output_stream", }; ya_result file_output_stream_open(output_stream* stream, const char* filename) { ya_result ret; ret = file_output_stream_open_ex(stream, filename, O_RDWR|O_CLOEXEC, 0600); return ret; } ya_result file_output_stream_create(output_stream* stream, const char* filename, mode_t mode) { ya_result ret; ret = file_output_stream_open_ex(stream, filename, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, mode); return ret; } ya_result file_output_stream_create_excl(output_stream* stream, const char* filename, mode_t mode) { ya_result ret; ret = file_output_stream_open_ex(stream, filename, O_RDWR | O_CREAT | O_TRUNC | O_EXCL | O_CLOEXEC, mode); return ret; } ya_result file_output_stream_set_full_writes(output_stream* stream, bool full_writes) { if(is_fd_output_stream(stream)) { if(full_writes) { stream->vtbl = &file_full_output_stream_vtbl; } else { stream->vtbl = &file_output_stream_vtbl; } return SUCCESS; } else { return INVALID_STATE_ERROR; } } ya_result file_output_stream_open_ex(output_stream* stream_, const char* filename, int flags, mode_t mode) { yassert(sizeof(void*) >= sizeof(int)); int fd = open_create_ex(filename, flags, mode); if(fd < 0) { return ERRNO_ERROR; } #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && !defined(__gnu__hurd__) posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); #endif file_output_stream* stream = (file_output_stream*)stream_; stream->data.fd = fd; stream->vtbl = &file_output_stream_vtbl; return SUCCESS; } ya_result file_output_stream_open_ex_nolog(output_stream* stream_, const char* filename, int flags, mode_t mode) { yassert(sizeof(void*) >= sizeof(int)); int fd = open_create_ex_nolog(filename, flags, mode); if(fd < 0) { return ERRNO_ERROR; } #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && !defined(__gnu__hurd__) posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); #endif file_output_stream* stream = (file_output_stream*)stream_; stream->data.fd = fd; stream->vtbl = &file_output_stream_vtbl; return SUCCESS; } void file_output_stream_close_nolog(output_stream* stream_) { file_output_stream* stream = (file_output_stream*)stream_; /* don't, it's only for a test that I did this assert((stream->data.fd < 0)||(stream->data.fd >2)); */ if(stream->data.fd != -1) /* harmless close but still ... */ { close_ex(stream->data.fd); stream->data.fd = -1; } output_stream_set_void(stream_); } ya_result fd_output_stream_attach(output_stream* stream_, int fd) { yassert(sizeof(void*) >= sizeof(int)); file_output_stream* stream = (file_output_stream*)stream_; stream->data.fd = fd; stream->vtbl = &file_output_stream_vtbl; return SUCCESS; } ya_result fd_output_stream_attach_noclose(output_stream* stream_, int fd) { yassert(sizeof(void*) >= sizeof(int)); file_output_stream* stream = (file_output_stream*)stream_; stream->data.fd = fd; stream->vtbl = &file_output_stream_noclose_vtbl; return SUCCESS; } void fd_output_stream_detach(output_stream* stream_) { yassert(sizeof(void*) >= sizeof(int)); file_output_stream* stream = (file_output_stream*)stream_; stream->data.fd = -1; } ya_result fd_output_stream_get_filedescriptor(output_stream* stream) { file_output_stream *fos = (file_output_stream*)stream; return fos->data.fd; } bool is_fd_output_stream(output_stream* stream_) { file_output_stream* stream = (file_output_stream*)stream_; return (stream != NULL) && ((stream->vtbl == &file_output_stream_vtbl) || (stream->vtbl == &file_full_output_stream_vtbl)); } s64 fd_output_stream_get_size(output_stream* stream_) { file_output_stream* stream = (file_output_stream*)stream_; struct stat s; if(fstat(stream->data.fd, &s) >= 0) { if(S_ISREG(s.st_mode)) { return s.st_size; } } return (s64)ERRNO_ERROR; } void file_output_steam_advise_sequential(output_stream* stream_) { #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && !defined(__gnu__hurd__) file_output_stream* stream = (file_output_stream*)stream_; if(stream->data.fd >= 0) { posix_fadvise(stream->data.fd, 0, 0, POSIX_FADV_SEQUENTIAL); } #else (void)stream_; #endif } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/file-pool.c0000644000000000000000000000013214505005532021362 xustar000000000000000030 mtime=1695812442.468982561 30 atime=1695812445.795030196 30 ctime=1695812494.572728791 yadifa-2.6.5-11201/lib/dnscore/src/file-pool.c0000664000374500037450000011017514505005532021331 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #define __FILE_POOL_C__ 1 #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include "dnscore/ptr_set.h" #include "dnscore/mutex.h" #include "dnscore/list-dl.h" #include "dnscore/fdtools.h" #include "dnscore/logger.h" #define FP_USE_ABSTRACT_FILES 1 #if DNSCORE_HAS_FILEPOOL_CACHE #define FP_USE_CACHED_FILES 1 // minimal impact apparently #else #define FP_USE_CACHED_FILES 0 // minimal impact apparently #endif #if FP_USE_ABSTRACT_FILES #include "dnscore/filesystem-file.h" #include "dnscore/buffered-file.h" #endif extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define FILEPOOL_TAG 0x4c4f4f50454c4946 // FILEPOOL_TAG struct file_pool_t_ { group_mutex_t mtx; ptr_set name_to_file; list_dl_s mru; const char * name; int opened_file_count_max; #if FP_USE_CACHED_FILES buffered_file_cache_t file_cache; #endif }; typedef struct file_pool_t_* file_pool_t; struct file_common_t_ { list_dl_node_s mru_node; // the struct MUST start with a node file_pool_t file_pool; // the pool that manages this file char *name; // the name of this file size_t position; // the current position in the current fd #if FP_USE_ABSTRACT_FILES file_t file; #else int fd; // the fd that accesses this file #endif int rc; // the number of references to this file (opened) int ioc; // the number of io operations going on (immediately planned read/write/...) bool old; // an old file has been renamed and cannot be closed anymore until its RC reaches 0 }; typedef struct file_common_t_* file_common_t; struct file_pool_file_t_ { #if DEBUG u64 magic; #endif file_common_t common; // the common part of the file size_t position; // the position in the file int rdwr_flags; // has this "handle" the right to access the file in read and/or write ? }; typedef struct file_pool_file_t_* file_pool_file_t; #include file_pool_t file_pool_init_ex(const char * const pool_name, int opened_file_count_max, u32 cache_entries) // name is for logging { #if FP_USE_CACHED_FILES buffered_file_cache_t file_cache = buffered_file_cache_new_instance(pool_name, cache_entries, 12, TRUE); if(file_cache == NULL) { log_err("file-pool: failed to instantiate new pool %s using %i file descriptors and a cache of %u pages", pool_name, opened_file_count_max, cache_entries); return NULL; } #else (void)cache_entries; #endif file_pool_t fp; ZALLOC_OBJECT_OR_DIE(fp, struct file_pool_t_, FILEPOOL_TAG); group_mutex_init(&fp->mtx); ptr_set_init(&fp->name_to_file); fp->name_to_file.compare = ptr_set_asciizp_node_compare; list_dl_init(&fp->mru); fp->name = pool_name; fp->opened_file_count_max = MAX(opened_file_count_max, 1); #if FP_USE_CACHED_FILES fp->file_cache = file_cache; #endif log_debug("file-pool: new pool %s using %i file descriptors at %p", pool_name, opened_file_count_max, fp); return fp; } file_pool_t file_pool_init(const char * const pool_name, int opened_file_count_max) // name is for logging { file_pool_t fp = file_pool_init_ex(pool_name, opened_file_count_max, 4096); return fp; } static void file_pool_close_unused_in_excess(file_pool_t fp, int fd_max); static void file_common_destroy(file_common_t fc); static void file_common_mru_unlink(file_common_t fc); static void file_pool_finalize_name_to_file(ptr_node *node) { file_common_t fc = (file_common_t)node->value; file_common_mru_unlink(fc); file_common_destroy(fc); } void file_pool_finalize(file_pool_t fp) { if(fp == NULL) { return; } log_debug("file-pool: deleting pool %s using %i file descriptors at %p", fp->name, fp->opened_file_count_max, fp); ptr_set_iterator iter; group_mutex_double_lock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_pool_close_unused_in_excess(fp, 0); #if FP_USE_CACHED_FILES buffered_file_cache_delete(fp->file_cache); #endif group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); group_mutex_double_unlock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); bool log_flush_required = FALSE; ptr_set_iterator_init(&fp->name_to_file, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); if(node->value != NULL) { file_common_t fc = (file_common_t)node->value; if(fc->rc > 0) { log_err("file-pool: '%s' is still referenced %i times", fc->name, fc->rc); log_flush_required = TRUE; } } } if(log_flush_required) { logger_flush(); } ptr_set_callback_and_destroy(&fp->name_to_file, file_pool_finalize_name_to_file); group_mutex_destroy(&fp->mtx); ZFREE_OBJECT(fp); } #if FP_USE_ABSTRACT_FILES static file_common_t file_common_newinstance(file_pool_t fp, const char *name, file_t file) #else static file_common_t file_common_newinstance(file_pool_t fp, const char *name, int fd) #endif { file_common_t fc; ZALLOC_OBJECT_OR_DIE(fc, struct file_common_t_, FILEPOOL_TAG); fc->mru_node.next = NULL; fc->mru_node.prev = NULL; fc->mru_node.data = fc; fc->file_pool = fp; fc->name = strdup(name); fc->position = 0; #if FP_USE_ABSTRACT_FILES fc->file = file; #else fc->fd = fd; #endif fc->rc = 0; fc->ioc = 0; fc->old = FALSE; return fc; } static void file_common_destroy(file_common_t fc) { if(fc != NULL) { #if FP_USE_ABSTRACT_FILES //yassert(fc->file == NULL); if(fc->file != NULL) { if(fc->rc == 0) { file_close(fc->file); fc->file = NULL; } else { log_err("error: file_common_destroy called on a file with rc=%i: '%s'", fc->rc, STRNULL(fc->name)); logger_flush(); } } #else //yassert(fc->fd < 0); if(fc->fd >= 0) { if(fc->rc == 0) { close_ex(fc->fd); fc->fd = -1; } else { log_err("error: file_common_destroy called on a file with rc=%i: '%s'", fc->rc, STRNULL(fc->name)); logger_flush(); } } #endif fc->file_pool = NULL; free(fc->name); ZFREE(fc, struct file_common_t_); } } static void file_common_mru_to_link(file_common_t fc) { file_common_t first_one = (file_common_t)list_dl_peek_first(&fc->file_pool->mru); if(first_one != fc) { list_dl_insert_node(&fc->file_pool->mru, &fc->mru_node); } } static void file_common_mru_to_first(file_common_t fc) { file_common_t first_one = (file_common_t)list_dl_peek_first(&fc->file_pool->mru); if(first_one != fc) { if(fc->mru_node.next != NULL) { list_dl_remove_node(&fc->file_pool->mru, &fc->mru_node); } list_dl_insert_node(&fc->file_pool->mru, &fc->mru_node); } } static void file_common_mru_to_last(file_common_t fc) { file_common_t last_one = (file_common_t)list_dl_peek_last(&fc->file_pool->mru); if(last_one != fc) { if(fc->mru_node.next != NULL) { list_dl_remove_node(&fc->file_pool->mru, &fc->mru_node); } list_dl_append_node(&fc->file_pool->mru, &fc->mru_node); } } static void file_common_mru_unlink(file_common_t fc) { //file_common_t first_one = (file_common_t)list_dl_peek_first(&fc->file_pool->mru); //if(first_one != fc) { list_dl_remove_node(&fc->file_pool->mru, &fc->mru_node); } } static bool file_common_operating(file_common_t fc) { return (fc->ioc > 0) || (fc->old); // if there are operations running or the file is old (and thus is only waiting for RC reaching 0 to close) } /** * Close open FD above the given limit * * Locks must be (W,R) * * @param fp * @param fd_max */ static void file_pool_close_unused_in_excess(file_pool_t fp, int fd_max) { if(fd_max < 1) { fd_max = 1; } while(list_dl_size(&fp->mru) > (u32)fd_max) { file_common_t fc = (file_common_t)list_dl_peek_last(&fp->mru); if(!file_common_operating(fc)) { #if FP_USE_ABSTRACT_FILES if(fc->file != NULL) { group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); file_close(fc->file); fc->file = NULL; group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); } #else if(fc->fd >= 0) { group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); close_ex(fc->fd); group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); fc->fd = -1; } #endif file_common_mru_unlink(fc); if(fc->rc == 0) { // nobody is pointing to this anymore ptr_set_delete(&fp->name_to_file, fc->name); file_common_destroy(fc); } } else { group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); break; } } } ya_result file_pool_unlink_from_pool_and_filename(file_pool_t fp, const char *filename) { ya_result ret; group_mutex_double_lock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); if(unlink(filename) >= 0) { ret = SUCCESS; ptr_node *node; if((node = ptr_set_find(&fp->name_to_file, filename)) != NULL) { // the common node exists // get a new file referencing that node group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_common_t fc = (file_common_t)node->value; ptr_set_delete(&fp->name_to_file, fc->name); file_common_mru_unlink(fc); fc->old = TRUE; if(fc->rc == 0) { if(fc->file != NULL) { file_close(fc->file); fc->file = NULL; } file_common_destroy(fc); } group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); } } else { ret = ERRNO_ERROR; } group_mutex_double_unlock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); return ret; } static void file_common_acquire(file_common_t fc) { ++fc->rc; } static void file_common_release(file_common_t fc) { --fc->rc; if(fc->rc <= 0) { assert(fc->rc == 0); // an old file has been unlinked // it is not in the name_to_file set anymore // it is not in the mru anymore if(!fc->old) { file_common_mru_to_last(fc); } else { #if FP_USE_ABSTRACT_FILES if(fc->file != NULL) { file_pool_t fp = fc->file_pool; group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); file_close(fc->file); fc->file = NULL; group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); } #else if(fc->fd >= 0) { file_pool_t fp = fc->file_pool; group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); close_ex(fc->fd); group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); fc->fd = -1; } #endif file_common_mru_unlink(fc); file_common_destroy(fc); } } } static file_pool_file_t file_newinstance(file_common_t common, int rdwr_flags) { file_pool_file_t f; ZALLOC_OBJECT_OR_DIE(f, struct file_pool_file_t_, FILEPOOL_TAG); file_common_acquire(common); #if DEBUG f->magic = 0xf113B001; #endif f->common = common; f->position = 0; f->rdwr_flags = rdwr_flags; return f; } static void file_destroy(file_pool_file_t f) { if(f != NULL) { file_common_t fc = f->common; ZEROMEMORY(f, sizeof(struct file_pool_file_t_)); ZFREE(f, struct file_pool_file_t_); file_common_release(fc); } } /** * * * @param fp * @param filename * @param flags * @param mode * @return a handle or NULL (errno being set) */ file_pool_file_t file_pool_open_ex(file_pool_t fp, const char *filename, int flags, mode_t mode) { group_mutex_double_lock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_common_t fc; file_pool_file_t f; char absolute_filename[1024]; ya_result ret; if(ISOK(ret = file_get_absolute_path(filename, absolute_filename, sizeof(absolute_filename)))) { filename = absolute_filename; } ptr_node *node; if((node = ptr_set_find(&fp->name_to_file, filename)) != NULL) { // the common node exists // get a new file referencing that node group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); fc = (file_common_t)node->value; f = file_newinstance(fc, flags); file_common_mru_to_first(fc); group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); } else { // the first opening is required to eventually return an error code #if FP_USE_ABSTRACT_FILES file_t file; ret = filesystem_file_create_ex(&file, filename, O_RDWR|flags, mode); if(ISOK(ret)) { #if FP_USE_CACHED_FILES buffered_file_init(&file, file, fp->file_cache); // only fails if one of the parameters is NULL #endif group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); // close the exceeding fd(s) file_pool_close_unused_in_excess(fp, fp->opened_file_count_max - 1); // we know the node does not exist node = ptr_set_insert(&fp->name_to_file, (char*)filename); // cast as it will be fixed later fc = file_common_newinstance(fp, filename, file); #else int fd = open_create_ex(filename, O_RDWR|flags, mode); if(fd > 0) { group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); // close the exceeding fd(s) file_pool_close_unused_in_excess(fp, fp->opened_file_count_max - 1); // we know the node does not exist node = ptr_set_insert(&fp->name_to_file, (char*)filename); // cast as it will be fixed later fc = file_common_newinstance(fp, filename, fd); #endif node->value = fc; node->key = fc->name; f = file_newinstance(fc, flags); file_common_mru_to_link(fc); group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); } else { f = NULL; } } group_mutex_double_unlock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); return f; } file_pool_file_t file_dup(file_pool_file_t file) { group_mutex_double_lock(&file->common->file_pool->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); group_mutex_exchange_locks(&file->common->file_pool->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_pool_file_t file_dup = file_newinstance(file->common, file->rdwr_flags); file_common_mru_to_first(file->common); group_mutex_exchange_locks(&file->common->file_pool->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); group_mutex_double_unlock(&file->common->file_pool->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); return file_dup; } file_pool_file_t file_pool_open(file_pool_t fp, const char *filename) { file_pool_file_t f = file_pool_open_ex(fp, filename, O_RDONLY|O_CLOEXEC, 0); return f; } file_pool_file_t file_pool_create(file_pool_t fp, const char *filename, mode_t mode) { file_pool_file_t f = file_pool_open_ex(fp, filename, O_RDWR|O_CREAT|O_CLOEXEC, mode); return f; } file_pool_file_t file_pool_create_excl(file_pool_t fp, const char *filename, mode_t mode) { file_pool_file_t f = file_pool_open_ex(fp, filename, O_RDWR|O_CREAT|O_CLOEXEC|O_EXCL, mode); return f; } static void file_common_release_fd(file_pool_file_t f) { file_common_t fc = f->common; file_pool_t fp = fc->file_pool; group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); fc->position = f->position; --fc->ioc; group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); group_mutex_double_unlock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); } static void file_common_advance_position_release_fd(file_pool_file_t f, size_t offset) { file_common_t fc = f->common; file_pool_t fp = fc->file_pool; group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); f->position += offset; fc->position = f->position; --fc->ioc; group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); group_mutex_double_unlock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); } #if FP_USE_ABSTRACT_FILES static int file_common_acquire_fd(file_pool_file_t f, file_t *filep) { #if DEBUG yassert(f->magic == 0xf113B001); #endif // prevent changes, take dibs on making changes group_mutex_double_lock(&f->common->file_pool->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_common_t fc = f->common; file_pool_t fp = fc->file_pool; file_t file; ya_result ret = SUCCESS; if((file = fc->file) == NULL) { // need to get a file group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_pool_close_unused_in_excess(fp, fp->opened_file_count_max - 1); group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); ret = filesystem_file_open_ex(&file, fc->name, O_RDWR|O_CLOEXEC); if(FAIL(ret)) { group_mutex_double_unlock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); return ret; } #if FP_USE_CACHED_FILES buffered_file_init(&file, file, fp->file_cache); // only fails if one of the parameters is NULL #endif fc->file = file; fc->position = 0; } if(fc->position != f->position) { file_seek(file, f->position, SEEK_SET); } group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_common_mru_to_first(fc); ++fc->ioc; group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); // successful acquisition will be unlocked at release *filep = file; return ret; } ya_result file_pool_read(file_pool_file_t f, void *buffer, size_t bytes) { file_t file; int ret = file_common_acquire_fd(f, &file); if(FAIL(ret)) { return ret; } // read ssize_t n = file_read(file, buffer, bytes); if(n >= 0) { file_common_advance_position_release_fd(f, n); } else { file_common_release_fd(f); } return (ya_result)n; } ya_result file_pool_readfully(file_pool_file_t f, void *buffer, size_t bytes) { ya_result ret = file_pool_read(f, buffer, bytes); return ret; } ya_result file_pool_write(file_pool_file_t f, const void *buffer, size_t bytes) { file_t file; int ret = file_common_acquire_fd(f, &file); if(FAIL(ret)) { return ret; } // read ssize_t n = file_write(file, buffer, bytes); if(n >= 0) { file_common_advance_position_release_fd(f, n); } else { file_common_release_fd(f); } return (ya_result)n; } ya_result file_pool_writefully(file_pool_file_t f, const void *buffer, size_t bytes) { ya_result ret = file_pool_write(f, buffer, bytes); return ret; } ya_result file_pool_flush(file_pool_file_t f) { file_t file; int ret = file_common_acquire_fd(f, &file); if(FAIL(ret)) { return ret; } // flush ret = file_flush(file); file_common_release_fd(f); return ret; } ya_result file_pool_get_size(file_pool_file_t f, size_t *sizep) { if(sizep != NULL) { file_t file; int ret = file_common_acquire_fd(f, &file); if(FAIL(ret)) { *sizep = 0; return ret; } *sizep = (size_t)file_size(file); file_common_release_fd(f); return ret; } else { return UNEXPECTED_NULL_ARGUMENT_ERROR; } } ya_result file_pool_resize(file_pool_file_t f, size_t size) { file_t file; int ret = file_common_acquire_fd(f, &file); if(FAIL(ret)) { return ret; } // truncate ret = file_resize(file, size); file_common_release_fd(f); return ret; } #else static int file_common_acquire_fd(file_pool_file_t f) { #if DEBUG yassert(f->magic == 0xf113B001); #endif // prevent changes, take dibs on making changes group_mutex_double_lock(&f->common->file_pool->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_common_t fc = f->common; file_pool_t fp = fc->file_pool; int fd; if((fd = fc->fd) < 0) { // need to get an fd group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_pool_close_unused_in_excess(fp, fp->opened_file_count_max - 1); group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); if((fd = open_ex(fc->name, O_RDWR|O_CLOEXEC)) < 0) { fd = ERRNO_ERROR; group_mutex_double_unlock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); return fd; } fc->fd = fd; fc->position = 0; } if(fc->position != f->position) { lseek(fd, f->position, SEEK_SET); } group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_common_mru_to_first(fc); ++fc->ioc; group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); // successful acquisition will be unlocked at release return fd; } ya_result file_pool_read(file_pool_file_t f, void *buffer, size_t bytes) { int fd = file_common_acquire_fd(f); if(fd < 0) { return fd; } // read for(;;) { ssize_t n = read(fd, buffer, bytes); if(n >= 0) { file_common_advance_position_release_fd(f, n); return n; } else { int err = errno; if(err == EINTR) { continue; } file_common_release_fd(f); return err; } } } ya_result file_pool_readfully(file_pool_file_t f, void *buffer, size_t bytes) { int fd = file_common_acquire_fd(f); if(fd < 0) { return fd; } // read size_t total = 0; for(;;) { ssize_t n = read(fd, buffer, bytes); if(n >= 0) { bytes -= n; total += n; if((n == 0) || (bytes == 0)) { file_common_advance_position_release_fd(f, total); return total; } } else { int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) { continue; } file_common_advance_position_release_fd(f, total); return err; } } } ya_result file_pool_write(file_pool_file_t f, const void *buffer, size_t bytes) { int fd = file_common_acquire_fd(f); if(fd < 0) { return fd; } // write for(;;) { ssize_t n = write(fd, buffer, bytes); if(n >= 0) { file_common_advance_position_release_fd(f, n); return n; } else { int err = errno; if(err == EAGAIN) { continue; } file_common_release_fd(f); return err; } } } ya_result file_pool_writefully(file_pool_file_t f, const void *buffer, size_t bytes) { int fd = file_common_acquire_fd(f); if(fd < 0) { return fd; } // write size_t total = 0; for(;;) { ssize_t n = write(fd, buffer, bytes); if(n >= 0) { bytes -= n; total += n; if((n == 0) || (bytes == 0)) { file_common_advance_position_release_fd(f, total); return total; } } else { int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) { continue; } file_common_advance_position_release_fd(f, total); return err; } } } ya_result file_pool_flush(file_pool_file_t f) { int fd = file_common_acquire_fd(f); if(fd < 0) { return fd; } // flush ya_result ret = SUCCESS; if(fdatasync_ex(fd) < 0) { ret = ERRNO_ERROR; } file_common_release_fd(f); return ret; } ya_result file_pool_get_size(file_pool_file_t f, size_t *sizep) { if(sizep != NULL) { int fd = file_common_acquire_fd(f); if(fd < 0) { return fd; } // truncate ya_result ret = SUCCESS; struct stat st; if(fstat(fd, &st) >= 0) { *sizep = st.st_size; } else { ret = ERRNO_ERROR; } file_common_release_fd(f); return ret; } else { return ERROR; } } ya_result file_pool_resize(file_pool_file_t f, size_t size) { int fd = file_common_acquire_fd(f); if(fd < 0) { return fd; } // truncate ya_result ret = SUCCESS; if(ftruncate_ex(fd, size) < 0) { ret = ERRNO_ERROR; } file_common_release_fd(f); return ret; } #endif ssize_t file_pool_seek(file_pool_file_t f, ssize_t position, int from) { ssize_t ret; group_mutex_lock(&f->common->file_pool->mtx, GROUP_MUTEX_WRITE); switch(from) { case SEEK_SET: { f->position = position; ret = (ssize_t)f->position; break; } case SEEK_CUR: { ssize_t p = f->position + position; if(p >= 0) { f->position = p; } else { f->position = 0; } ret = (ssize_t)f->position; break; } case SEEK_END: { size_t size; if(ISOK(ret = file_pool_get_size(f, &size))) // can only fail if a NULL is given) { ssize_t p = size + position; if(p >= 0) { f->position = p; } else { f->position = 0; } ret = (ssize_t)f->position; } break; } default: { ret = INVALID_ARGUMENT_ERROR; break; } } group_mutex_unlock(&f->common->file_pool->mtx, GROUP_MUTEX_WRITE); return ret; } ya_result file_pool_tell(file_pool_file_t f, size_t *positionp) { if(positionp != NULL) { group_mutex_lock(&f->common->file_pool->mtx, GROUP_MUTEX_READ); *positionp = f->position; group_mutex_unlock(&f->common->file_pool->mtx, GROUP_MUTEX_READ); return SUCCESS; } else { return ERROR; } } // flushes, but only closes the file when fd are needed ya_result file_pool_close(file_pool_file_t f) { group_mutex_double_lock(&f->common->file_pool->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_common_t fc = f->common; file_pool_t fp = fc->file_pool; #if FP_USE_ABSTRACT_FILES if(fc->file != NULL) { file_flush(fc->file); } #else if(fc->fd >= 0) { fdatasync_ex(fc->fd); } #endif group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); file_destroy(f); group_mutex_exchange_locks(&fp->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); group_mutex_double_unlock(&fp->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); return SUCCESS; } ya_result file_pool_unlink(file_pool_file_t f) { ya_result ret; if(f != NULL) { ret = INVALID_ARGUMENT_ERROR; if(f->common != NULL) { if(f->common->file_pool != NULL) { ret = file_pool_unlink_from_pool_and_filename(f->common->file_pool, f->common->name); } } } else { ret = UNEXPECTED_NULL_ARGUMENT_ERROR; } return ret; } const char * file_pool_filename(const file_pool_file_t f) { if(f != NULL) { const file_common_t fc = f->common; return fc->name; } else { return "NULL"; } } static ya_result file_pool_file_output_stream_write(output_stream* os, const u8* buffer, u32 len) { file_pool_file_t f = (file_pool_file_t)os->data; ya_result ret = file_pool_write(f, buffer, len); return ret; } static ya_result file_pool_file_output_stream_writefully(output_stream* os, const u8* buffer, u32 len) { file_pool_file_t f = (file_pool_file_t)os->data; ya_result ret = file_pool_writefully(f, buffer, len); return ret; } static ya_result file_pool_file_output_stream_flush(output_stream* os) { file_pool_file_t f = (file_pool_file_t)os->data; ya_result ret = INVALID_STATE_ERROR; if(f != NULL) { ret = file_pool_flush(f); } return ret; } static void file_pool_file_output_stream_close(output_stream* os) { file_pool_file_t f = (file_pool_file_t)os->data; if(f != NULL) { file_pool_close(f); } } static const output_stream_vtbl file_pool_file_output_stream_vtbl = { file_pool_file_output_stream_write, file_pool_file_output_stream_flush, file_pool_file_output_stream_close, "file_pool_file_output_stream", }; static const output_stream_vtbl file_pool_file_full_output_stream_vtbl = { file_pool_file_output_stream_writefully, file_pool_file_output_stream_flush, file_pool_file_output_stream_close, "file_pool_file_output_stream", }; void file_pool_file_output_stream_init(output_stream *os, file_pool_file_t f) { os->data = f; os->vtbl = &file_pool_file_output_stream_vtbl; } void file_pool_file_output_stream_set_full_writes(output_stream *os, bool full_writes) { if(full_writes) { os->vtbl = &file_pool_file_full_output_stream_vtbl; } else { os->vtbl = &file_pool_file_output_stream_vtbl; } } void file_pool_file_output_stream_detach(output_stream *os) { assert((os->vtbl == &file_pool_file_output_stream_vtbl) || (os->vtbl == &file_pool_file_full_output_stream_vtbl)); os->data = NULL; } static ya_result file_pool_file_input_stream_read(input_stream* os, void* buffer, u32 len) { file_pool_file_t f = (file_pool_file_t)os->data; ya_result ret = file_pool_read(f, buffer, len); return ret; } static ya_result file_pool_file_input_stream_readfully(input_stream* os, void* buffer, u32 len) { file_pool_file_t f = (file_pool_file_t)os->data; ya_result ret = file_pool_readfully(f, buffer, len); return ret; } static ya_result file_pool_file_input_stream_skip(input_stream* os, u32 len) { file_pool_file_t f = (file_pool_file_t)os->data; ya_result ret = file_pool_seek(f, len, SEEK_CUR); return ret; } static void file_pool_file_input_stream_close(input_stream* os) { file_pool_file_t f = (file_pool_file_t)os->data; if(f != NULL) { file_pool_close(f); } } static const input_stream_vtbl file_pool_file_input_stream_vtbl = { file_pool_file_input_stream_read, file_pool_file_input_stream_skip, file_pool_file_input_stream_close, "file_pool_file_input_stream" }; static const input_stream_vtbl file_pool_file_full_input_stream_vtbl = { file_pool_file_input_stream_readfully, file_pool_file_input_stream_skip, file_pool_file_input_stream_close, "file_pool_file_input_stream" }; void file_pool_file_input_stream_init(input_stream *is, file_pool_file_t f) { is->data = f; is->vtbl = &file_pool_file_input_stream_vtbl; } void file_pool_file_input_stream_detach(input_stream *os) { assert((os->vtbl == &file_pool_file_input_stream_vtbl) || (os->vtbl == &file_pool_file_full_input_stream_vtbl)); os->data = NULL; } void file_pool_file_input_stream_set_full_reads(input_stream *is, bool full_writes) { if(full_writes) { is->vtbl = &file_pool_file_full_input_stream_vtbl; } else { is->vtbl = &file_pool_file_input_stream_vtbl; } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/filesystem-file.c0000644000000000000000000000013114505005532022574 xustar000000000000000030 mtime=1695812442.455982374 30 atime=1695812445.794030182 29 ctime=1695812494.57472882 yadifa-2.6.5-11201/lib/dnscore/src/filesystem-file.c0000664000374500037450000001455514505005532022551 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include "dnscore/filesystem-file.h" #include "dnscore/fdtools.h" #include "dnscore/zalloc.h" //extern logger_handle *g_system_logger; //#define MODULE_MSG_HANDLE g_system_logger #define FILESYSTEM_FILE_TAG 0x454c49465346 // FSFILE_TAG struct filesystem_file_t_ // matches the file_t_ signature, appends its own { const struct file_vtbl *vtbl; int fd; }; typedef struct filesystem_file_t_* filesystem_file_t; static ssize_t filesystem_file_read(file_t f, void *buffer, ssize_t size) { filesystem_file_t fsf = (filesystem_file_t)f; int fd = fsf->fd; if(fd < 0) { return INVALID_STATE_ERROR; } ssize_t ret = readfully(fd, buffer, size); return ret; } static ssize_t filesystem_file_write(file_t f, const void *buffer, ssize_t size) { filesystem_file_t fsf = (filesystem_file_t)f; int fd = fsf->fd; if(fd < 0) { return INVALID_STATE_ERROR; } ssize_t ret = writefully(fd, buffer, size); return ret; } static ssize_t filesystem_file_seek(file_t f, ssize_t position, int whence) { filesystem_file_t fsf = (filesystem_file_t)f; int fd = fsf->fd; if(fd < 0) { return INVALID_STATE_ERROR; } off_t ret = lseek(fd, position, whence); if(ret < 0) { ret = ERRNO_ERROR; } return ret; } static ssize_t filesystem_file_tell(file_t f) { filesystem_file_t fsf = (filesystem_file_t)f; int fd = fsf->fd; if(fd < 0) { return INVALID_STATE_ERROR; } off_t ret = lseek(fd, 0, SEEK_CUR); if(ret < 0) { ret = ERRNO_ERROR; } return ret; } static ya_result filesystem_file_flush(file_t f) { filesystem_file_t fsf = (filesystem_file_t)f; int fd = fsf->fd; if(fd < 0) { return INVALID_STATE_ERROR; } int ret = fdatasync_ex(fd); if(FAIL(ret)) { ret = ERRNO_ERROR; } return ret; } static int filesystem_file_close(file_t f) { filesystem_file_t fsf = (filesystem_file_t)f; int fd = fsf->fd; if(fd < 0) { return INVALID_STATE_ERROR; } close_ex(fd); fsf->fd = -2; fsf->vtbl = NULL; ZFREE_OBJECT(fsf); return SUCCESS; } static ssize_t filesystem_file_size(file_t f) { filesystem_file_t fsf = (filesystem_file_t)f; int fd = fsf->fd; if(fd < 0) { return INVALID_STATE_ERROR; } ssize_t ret; struct stat st; if(fstat(fd, &st) >= 0) { ret = st.st_size; } else { ret = ERRNO_ERROR; } return ret; } static int filesystem_file_resize(file_t f, ssize_t size) { filesystem_file_t fsf = (filesystem_file_t)f; int fd = fsf->fd; if(fd < 0) { return INVALID_STATE_ERROR; } ya_result ret = ftruncate(fd, size); if(FAIL(ret)) { ret = ERRNO_ERROR; } return ret; } static const struct file_vtbl filesystem_file_vtbl = { filesystem_file_read, filesystem_file_write, filesystem_file_seek, filesystem_file_tell, filesystem_file_flush, filesystem_file_close, filesystem_file_size, filesystem_file_resize }; /* file_t filesystem_file_open_ex(const char *filename, int flags, mode_t mode, ya_result *ret) */ ya_result filesystem_file_open_ex(file_t *fp, const char *filename, int flags) { ya_result ret; if(fp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } ret = open_ex(filename, flags); if(FAIL(ret)) { return ret; } filesystem_file_t fsf; ZALLOC_OBJECT_OR_DIE(fsf,struct filesystem_file_t_, FILESYSTEM_FILE_TAG); fsf->vtbl = &filesystem_file_vtbl; fsf->fd = ret; *fp = (file_t)fsf; return ret; } ya_result filesystem_file_create_ex(file_t *fp, const char *filename, int flags, mode_t mode) { ya_result ret; if(fp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } ret = open_create_ex(filename, flags, mode); if(ret < 0) { return ERRNO_ERROR; } filesystem_file_t fsf; ZALLOC_OBJECT_OR_DIE(fsf,struct filesystem_file_t_, FILESYSTEM_FILE_TAG); fsf->vtbl = &filesystem_file_vtbl; fsf->fd = ret; *fp = (file_t)fsf; return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/format.c0000644000000000000000000000013214505005532020764 xustar000000000000000030 mtime=1695812442.432982045 30 atime=1695812445.793030168 30 ctime=1695812494.576728848 yadifa-2.6.5-11201/lib/dnscore/src/format.c0000664000374500037450000025326114505005532020737 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup format C-string formatting * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #include "dnscore/timeformat.h" #include "dnscore/ctrl-rfc.h" #include "dnscore/hash.h" #include "dnscore/mutex.h" // Enables or disables the feature #define HAS_DLADDR_SUPPORT 0 #ifdef __linux__ #ifdef __GNUC__ // linux + gnu: Enabling enhanced function address translation #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif #ifndef __USE_GNU #define __USE_GNU 1 #endif #include #undef HAS_DLADDR_SUPPORT #define HAS_DLADDR_SUPPORT 0 // keep it disabled for the rest of the binary #endif #endif /* Added this for FreeBSD */ #ifdef __FreeBSD__ #include #include #include #elif defined __OpenBSD__ #include #endif /**/ #include #include #include "dnscore/format.h" #include "dnscore/bytearray_output_stream.h" #include "dnscore/counter_output_stream.h" #include "dnscore/ptr_vector.h" #include "dnscore/base64.h" #include "dnscore/base16.h" #include "dnscore/base32hex.h" #include "dnscore/sys_error.h" #define FMTHDESC_TAG 0x4353454448544d46 #define SENTINEL '%' #define NULL_STRING_SUBSTITUTE "(NULL)" #define NULL_STRING_SUBSTITUTE_LEN (sizeof(NULL_STRING_SUBSTITUTE)-1) #define CHR0 '\0' static const u8* STREOL = (const u8*)"\n"; //static const u8* STRCHR0 = (const u8*)"\0"; static const u8* STRMINUS = (const u8*)"-"; static const u8* STRESCAPE = (const u8*)"\\"; static const u8* STRQUOTE = (const u8*)"\""; static const u8 STRSEPARATOR[] = {' ', '|', ' '}; #if 0 static const char ESCAPE_CHARS[] = {'@', '$', '\\', ';', ' ', '\t'}; #endif #define TXT_ESCAPE_TYPE_NONE 0 #define TXT_ESCAPE_TYPE_CHAR 1 #define TXT_ESCAPE_TYPE_OCTL 2 static const u8 TXT_ESCAPE_TYPE[256] = { TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_CHAR,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x20 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x28 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x30 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x38 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x40 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x48 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x50 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_CHAR,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x58 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x60 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x68 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x70 TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE,TXT_ESCAPE_TYPE_NONE, // 0x78 TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL,TXT_ESCAPE_TYPE_OCTL, }; /* * Linear access to the format handlers. Accessed through a dichotomy. */ static ptr_vector format_handler_descriptor_table = {NULL, -1, -1}; static const format_handler_descriptor** format_handler_descriptor_hash_table = NULL; static int format_handler_descriptor_hash_table_size = 0; static mutex_t debug_osformat_mtx = MUTEX_INITIALIZER; //static bool g_format_usable = FALSE; static int format_handler_compare(const char* str1, s32 str1_len, const char* str2, s32 str2_len) { s32 len = MIN(str1_len, str2_len); int ret = memcmp(str1, str2, len); if(ret == 0) { ret = str1_len - str2_len; } return ret; } static int format_handler_qsort_compare(const void* a_, const void* b_) { format_handler_descriptor* a = (format_handler_descriptor*)a_; format_handler_descriptor* b = (format_handler_descriptor*)b_; return format_handler_compare(a->name, a->name_len, b->name, b->name_len); } static const format_handler_descriptor* format_get_format_handler(const char* name, u32 name_len) { #if 0 /* fix */ #else if(format_handler_descriptor_table.data == NULL) { return NULL; /* Not initialized */ } format_handler_descriptor* fh = NULL; u32 low = 0; u32 high = format_handler_descriptor_table.offset + 1; while(high - low > 3) { u32 mid = (high + low) / 2; fh = format_handler_descriptor_table.data[mid]; int cmp = format_handler_compare(name, name_len, fh->name, fh->name_len); if(cmp == 0) { return fh; } if(cmp > 0) { low = mid + 1; } else { high = mid; } } for(; low < high; low++) { fh = format_handler_descriptor_table.data[low]; int cmp = format_handler_compare(fh->name, fh->name_len, name, name_len); if(cmp == 0) { return fh; } } return NULL; #endif } /* Example of custom format handler -> */ /* * The dummy format handler simply prints the pointer in hexadecimal / lo-case */ static void dummy_format_handler_method(const void* val, output_stream* stream, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters) { (void)reserved_for_method_parameters; intptr ival = (intptr)val; format_hex_u64_lo(ival, stream, padding, pad_char, left_justified); } static format_handler_descriptor dummy_format_handler_descriptor = { "Unsupported", 11, dummy_format_handler_method }; /* <- Example of custom format handler */ static void format_grow_hash_table(); void format_class_init() { if(format_handler_descriptor_table.data != NULL) { return; } ptr_vector_init(&format_handler_descriptor_table); format_grow_hash_table(); } void format_class_finalize() { ptr_vector_destroy(&format_handler_descriptor_table); free((void*)format_handler_descriptor_hash_table); format_handler_descriptor_hash_table = NULL; } bool format_available() { return format_handler_descriptor_table.data != NULL; } static void format_grow_hash_table() { bool retry; do { if(format_handler_descriptor_hash_table != NULL) { free((void*)format_handler_descriptor_hash_table); int next = (format_handler_descriptor_hash_table_size * 2) | 1; for(int i = 3; i < next; i += 2) { if((next % i) == 0) { next += 2; i = 1; } } format_handler_descriptor_hash_table_size = next; } else { format_handler_descriptor_hash_table_size = 1117; // prime } retry = FALSE; MALLOC_OBJECT_ARRAY_OR_DIE(format_handler_descriptor_hash_table, const format_handler_descriptor*, format_handler_descriptor_hash_table_size, FMTHDESC_TAG); ZEROMEMORY((void*)format_handler_descriptor_hash_table, format_handler_descriptor_hash_table_size * sizeof(format_handler_descriptor*)); for(int i = 0; i <= ptr_vector_last_index(&format_handler_descriptor_table); ++i) { const format_handler_descriptor* fhd = (format_handler_descriptor*)ptr_vector_get(&format_handler_descriptor_table, i); hashcode code = hash_chararray(fhd->name, fhd->name_len); int slot = code % format_handler_descriptor_hash_table_size; if(format_handler_descriptor_hash_table[slot] != NULL) { retry = TRUE; break; } format_handler_descriptor_hash_table[slot] = fhd; // VS false positive: slot is unsigned and limited by the modulo of the size of the table } } while(retry); } ya_result format_registerclass(const format_handler_descriptor* fhd) { if(format_get_format_handler(fhd->name, fhd->name_len) != NULL) { return FORMAT_ALREADY_REGISTERED; /* Already registered */ } ptr_vector_append(&format_handler_descriptor_table, (format_handler_descriptor*)fhd); ptr_vector_qsort(&format_handler_descriptor_table, format_handler_qsort_compare); hashcode code = hash_chararray(fhd->name, fhd->name_len); int slot = code % format_handler_descriptor_hash_table_size; if(format_handler_descriptor_hash_table[slot] == NULL) { format_handler_descriptor_hash_table[slot] = fhd; } else { format_grow_hash_table(); } return SUCCESS; } /*typedef size_t formatter(char* output, size_t max_chars, bool left-aligned, void* value_to_convert,int arg_count,va_list args);*/ typedef void u64_formatter_function(u64, output_stream*, s32, char, bool); static const char __HEXA__[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; static const char __hexa__[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; static void do_padding(output_stream* stream, s32 padding, char pad_char) { output_stream_write_method* os_write = stream->vtbl->write; while(padding-- > 0) { os_write(stream, (u8*) & pad_char, 1); } } static void format_unsigned(const char* input, size_t size, output_stream* stream, s32 padding, char pad_char, bool left_justified) { padding -= size; if(left_justified) { output_stream_write(stream, (const u8*)input, size); do_padding(stream, padding, pad_char); } else { do_padding(stream, padding, pad_char); output_stream_write(stream, (const u8*)input, size); } /* Done */ } static void format_signed(const char* input, size_t size, output_stream* stream, s32 padding, char pad_char, bool left_justified, bool sign) { padding -= size; if(left_justified) { if(sign) { output_stream_write(stream, STRMINUS, 1); } output_stream_write(stream, (const u8*)input, size); do_padding(stream, padding, pad_char); } else { if(sign && pad_char == '0') { output_stream_write(stream, STRMINUS, 1); } do_padding(stream, padding, pad_char); if(sign && pad_char != '0') { output_stream_write(stream, STRMINUS, 1); } output_stream_write(stream, (const u8*)input, size); } /* Done */ } static void format_hex_u64_common(const char* hexa_table, u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified) { char tmp[__SIZEOF_LONG_LONG__ * 2]; char* next = &tmp[sizeof(tmp)]; do { *--next = hexa_table[val & 0x0f]; val >>= 4; } while(val != 0); format_unsigned(next, &tmp[sizeof(tmp)] - next, stream, padding, pad_char, left_justified); } void format_oct_u64(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified) { char tmp[20]; char* next = &tmp[sizeof(tmp)]; do { *--next = '0' + (val & 7); val >>= 3; } while(val != 0); /* next points at the first char of the 10-based representation of the integer */ format_unsigned(next, &tmp[sizeof(tmp)] - next, stream, padding, pad_char, left_justified); } void format_dec_u64(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified) { char tmp[20]; char* next = &tmp[sizeof(tmp)]; do { *--next = '0' + (val % 10); val /= 10; } while(val != 0); /* next points at the first char of the 10-based representation of the integer */ format_unsigned(next, &tmp[sizeof(tmp)] - next, stream, padding, pad_char, left_justified); } void format_dec_s64(s64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified) { char tmp[20]; char* next = &tmp[sizeof(tmp)]; bool sign; if((sign = (val < 0))) { val = -val; } u64 uval = (u64)val; do { *--next = '0' + (uval % 10); uval /= 10; } while(uval != 0); format_signed(next, &tmp[sizeof(tmp)] - next, stream, padding, pad_char, left_justified, sign); } void format_hex_u64_lo(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified) { format_hex_u64_common(__hexa__, val, stream, padding, pad_char, left_justified); } void format_hex_u64_hi(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified) { format_hex_u64_common(__HEXA__, val, stream, padding, pad_char, left_justified); } static void format_double_make_format(char* p, s32 padding, s32 float_padding, char pad_char, bool left_justified, bool long_double) { *p++ = '%'; if(!left_justified) { *p++ = '-'; } if(pad_char != ' ') { *p++ = pad_char; } if(padding >= 0) { p += sprintf(p, "%i", padding); } if(float_padding >= 0) { *p++ = '.'; p += sprintf(p, "%i", float_padding); } if(long_double) { *p++ = 'L'; } *p++ = 'f'; *p++ = CHR0; } static void format_longdouble(long double val, output_stream* stream, s32 padding, s32 float_padding, char pad_char, bool left_justified) { char fmt[32]; char tmp[64]; format_double_make_format(fmt, padding, float_padding, pad_char, left_justified, TRUE); int len = snprintf(tmp, sizeof(tmp), fmt, val); output_stream_write(stream, (const u8*)tmp, len); } static void format_double(double val, output_stream* stream, s32 padding, s32 float_padding, char pad_char, bool left_justified) { char fmt[32]; char tmp[64]; format_double_make_format(fmt, padding, float_padding, pad_char, left_justified, FALSE); int len = snprintf(tmp, sizeof(tmp), fmt, val); output_stream_write(stream, (const u8*)tmp, len); } void format_asciiz(const char* val, output_stream* stream, s32 padding, char pad_char, bool left_justified) { if(val == NULL) { val = NULL_STRING_SUBSTITUTE; } size_t val_len = strlen(val); padding -= val_len; if(left_justified) { output_stream_write(stream, (const u8*)val, val_len); do_padding(stream, padding, pad_char); } else { do_padding(stream, padding, pad_char); output_stream_write(stream, (const u8*)val, val_len); } } ya_result vosformat(output_stream* os_, const char* fmt, va_list args) { counter_output_stream_data cosd; output_stream os; counter_output_stream_init(os_, &os, &cosd); const char* next = fmt; s32 padding = -1; s32 float_padding = -1; u8 type_size = sizeof(int); u8 size_modifier_count = 0; char pad_char = ' '; bool left_justified = TRUE; char c; for(;;) { c = *next; if(c == 0) { /* copy the rest, return */ size_t size = next - fmt; output_stream_write(&os, (const u8*)fmt, size); ya_result ret; if(ISOK(cosd.result)) { ret = cosd.write_count; } else { ret = cosd.result; } /** * NOTE: counter_output_stream has changed a bit since its first version. * * * It does not closes the fitlered stream on "close" * It does not flushes the filtered stream on "close" either. * It only flushes the filtered stream when explicitly asked with "flush" * * It is thus useless to call close here (we just loose the time for the call) * */ /* output_stream_close(&os); */ return ret; } if(c == SENTINEL) { size_modifier_count = 0; /* copy the rest, format */ size_t size = next - fmt; output_stream_write(&os, (const u8*)fmt, size); next++; fmt += size; /* format */ c = *next++; if(c == '%') { /* * warning: ‘char’ is promoted to ‘int’ when passed through ‘...’ * (so you should pass ‘int’ not ‘char’ to ‘va_arg’) * if this code is reached, the program will abort * * => int */ format_asciiz("%", &os, padding, pad_char, left_justified); fmt = next; padding = 0; type_size = sizeof(int); pad_char = ' '; left_justified = TRUE; continue; } /* Justify */ if(c == '-') { left_justified = FALSE; c = *next++; } /* Padding */ if(c == '0') { pad_char = c; left_justified = FALSE; c = *next++; } /* Padding */ if(isdigit(c)) { char padding_string[10]; char* p = padding_string; int n = 9; do { *p++ = c; c = *next++; } while(isdigit(c) && (n > 0)); *p = CHR0; padding = atoi(padding_string); } if(c == '.') { char padding_string[10]; char* p = padding_string; int n = 9; c = *next++; do { *p++ = c; c = *next++; } while(isdigit(c) && (n > 0)); *p = CHR0; float_padding = atoi(padding_string); } /* Type size */ if(c == 'h') { c = *next++; type_size = sizeof(u16); if(c == 'h') { c = *next++; type_size = sizeof(u8); } } else if(c == 'l') { c = *next++; type_size = sizeof(u32); size_modifier_count = 1; if(c == 'l') { c = *next++; type_size = sizeof(u64); size_modifier_count = 2; } } else if(c == 'L') { c = *next++; type_size = sizeof(long double); } /* Type */ switch(c) { case 'i': { s64 val; switch(type_size) { case sizeof(s8): { /* * warning: ‘u8’ is promoted to ‘int’ when passed through ‘...’ * (so you should pass ‘int’ not ‘u8’ to ‘va_arg’) * if this code is reached, the program will abort * * => int */ val = (s8)va_arg(args, int); break; } case sizeof(s16): { /* * warning: ‘u16’ is promoted to ‘int’ when passed through ‘...’ * (so you should pass ‘int’ not ‘u16’ to ‘va_arg’) * if this code is reached, the program will abort * * => int */ val = (s16)va_arg(args, int); break; } case sizeof(s32): { val = (s32)va_arg(args, s32); break; } case sizeof(s64): { val = va_arg(args, s64); break; } default: { /* Invalid formatting : FULL STOP */ flushout(); flusherr(); fprintf(stderr, "Invalid type size '%i' in string '%s'", type_size, fmt); /* Keep native */ fflush(stderr); abort(); } } format_dec_s64(val, &os, padding, pad_char, left_justified); break; } case 'r': { ya_result val = va_arg(args, ya_result); error_writetext(&os, val); break; } case 'x': case 'X': case 'u': case 'd': case 'o': { u64_formatter_function* formatter; u64 val; if(c == 'u' || c == 'd') { formatter = format_dec_u64; } else if(c == 'X') { formatter = format_hex_u64_hi; } else if(c == 'x') { formatter = format_hex_u64_lo; } else { formatter = format_oct_u64; } switch(type_size) { case sizeof(u8): { /* * warning: ‘u8’ is promoted to ‘int’ when passed through ‘...’ * (so you should pass ‘int’ not ‘u8’ to ‘va_arg’) * if this code is reached, the program will abort * * => int */ val = va_arg(args, int); break; } case sizeof(u16): { /* * warning: ‘u16’ is promoted to ‘int’ when passed through ‘...’ * (so you should pass ‘int’ not ‘u16’ to ‘va_arg’) * if this code is reached, the program will abort * * => int */ val = va_arg(args, int); break; } case sizeof(u32): { val = va_arg(args, u32); break; } case sizeof(u64): { val = va_arg(args, u64); break; } default: { /* Invalid formatting : FULL STOP */ flushout(); flusherr(); fprintf(stderr, "Invalid type size '%i' in string '%s'", type_size, fmt); /* Keep native */ fflush(stderr); abort(); } } formatter(val, &os, padding, pad_char, left_justified); break; } case 'P': { intptr val = va_arg(args, intptr); #if HAS_DLADDR_SUPPORT Dl_info info; if(val != 0) { if(dladdr((void*)val, &info) != 0) { if(info.dli_sname != NULL) { format_asciiz(info.dli_sname, &os, padding, pad_char, left_justified); break; } else if(info.dli_fname != NULL) { format_asciiz(info.dli_fname, &os, padding, pad_char, left_justified); val -= (intptr)info.dli_fbase; output_stream_write_u8(&os, (u8)':'); } } } #endif format_hex_u64_hi(val, &os, __SIZEOF_POINTER__ * 2, '0', FALSE); break; } case 'p': { intptr val = va_arg(args, intptr); format_hex_u64_hi(val, &os, __SIZEOF_POINTER__ * 2, '0', FALSE); break; } case 'f': { if(type_size == sizeof(long double)) { long double val = va_arg(args, long double); format_longdouble(val, &os, padding, float_padding, pad_char, left_justified); } else { double val = va_arg(args, double); format_double(val, &os, padding, float_padding, pad_char, left_justified); } break; } case 's': { const char* val; val = va_arg(args, const char*); format_asciiz(val, &os, padding, pad_char, left_justified); break; } case 'c': { /* I'm using the string formatter. It's slower than it could but ... */ char tmp[2]; tmp[1] = CHR0; /* * warning: ‘char’ is promoted to ‘int’ when passed through ‘...’ * (so you should pass ‘int’ not ‘char’ to ‘va_arg’) * if this code is reached, the program will abort * * => int */ tmp[0] = va_arg(args, int); format_asciiz(tmp, &os, padding, pad_char, left_justified); break; } case '{': { const char* type_name = next; do { c = *next++; if(c == 0) { flushout(); flusherr(); fprintf(stderr, "PANIC: Invalid format type in string '%s' : '}' expected.", fmt); /* Keep native */ fflush(stderr); abort(); } } while(c != '}'); /* type_name -> next contains the type name and arguments * arguments can be integers */ size_t type_name_len = next - 1 - type_name; const format_handler_descriptor* desc = format_get_format_handler(type_name, type_name_len); if(desc == NULL) { /* Uses the "dummy" handler */ desc = &dummy_format_handler_descriptor; } void* ptr = va_arg(args, void*); desc->format_handler(ptr, &os, padding, pad_char, left_justified, NULL); break; } case 'w': { void* ptr = va_arg(args, void*); format_writer *fw = (format_writer*)ptr; fw->callback(fw->value, &os, padding, pad_char, left_justified, NULL); break; } case 't': { int val = (int)va_arg(args, int); do_padding(&os, val, '\t'); break; } case 'S': { int val = (int)va_arg(args, int); do_padding(&os, val, ' '); break; } case 'T': { switch(size_modifier_count) { case 0: { s64 val = (s64)va_arg(args, u32); localepoch_format_handler_method((void*)(intptr)val, &os, 0, 0, FALSE, NULL); break; } case 1: { s64 val = (s64)va_arg(args, s64); localdatetime_format_handler_method((void*)(intptr)val, &os, 0, 0, FALSE, NULL); break; } case 2: { s64 val = (s64)va_arg(args, s64); localdatetimeus_format_handler_method((void*)(intptr)val, &os, 0, 0, FALSE, NULL); break; } default: { abort(); } } break; } case 'U': { switch(size_modifier_count) { case 0: { s64 val = (s64)va_arg(args, u32); epoch_format_handler_method((void*)(intptr)val, &os, 0, 0, FALSE, NULL); break; } case 1: { s64 val = (s64)va_arg(args, s64); datetime_format_handler_method((void*)(intptr)val, &os, 0, 0, FALSE, NULL); break; } case 2: { s64 val = (s64)va_arg(args, s64); datetimeus_format_handler_method((void*)(intptr)val, &os, 0, 0, FALSE, NULL); break; } default: { abort(); } } break; } } fmt = next; padding = -1; float_padding = -1; type_size = sizeof(int); pad_char = ' '; left_justified = TRUE; continue; } next++; /* look for the sentinel */ } } ya_result osprint(output_stream* stream, const char* text) { return output_stream_write(stream, (const u8*)text, strlen(text)); } ya_result osprintln(output_stream* stream, const char* text) { ya_result n = strlen(text); output_stream_write(stream, (const u8*)text, n); output_stream_write(stream, STREOL, 1); return n + 1; } ya_result osformat(output_stream* stream, const char* fmt, ...) { va_list args; va_start(args, fmt); ya_result err = vosformat(stream, fmt, args); va_end(args); return err; } ya_result osformatln(output_stream* stream, const char* fmt, ...) { va_list args; va_start(args, fmt); ya_result err1 = vosformat(stream, fmt, args); va_end(args); if(ISOK(err1)) { ya_result err2 = output_stream_write(stream, STREOL, 1); if(ISOK(err2)) { return err1 + err2; } return err2; } return err1; } ya_result debug_osformatln(output_stream* stream, const char* fmt, ...) { s64 now = timeus(); mutex_lock(&debug_osformat_mtx); localdatetimeus_format_handler_method((void*)(intptr)now, stream, 0, 0, FALSE, NULL); output_stream_write(stream, STRSEPARATOR, sizeof(STRSEPARATOR)); format_dec_u64(getpid(), stream, 0, 0, FALSE); output_stream_write(stream, STRSEPARATOR, sizeof(STRSEPARATOR)); format_hex_u64_lo((u64)(intptr)pthread_self(), stream, 0, 0, FALSE); output_stream_write(stream, STRSEPARATOR, sizeof(STRSEPARATOR)); va_list args; va_start(args, fmt); ya_result err1 = vosformat(stream, fmt, args); va_end(args); output_stream_write(stream, STREOL, 1); mutex_unlock(&debug_osformat_mtx); return err1; } ya_result debug_println(const char* text) { s64 now = timeus(); mutex_lock(&debug_osformat_mtx); localdatetimeus_format_handler_method((void*)(intptr)now, termout, 0, 0, FALSE, NULL); output_stream_write(termout, STRSEPARATOR, sizeof(STRSEPARATOR)); format_dec_u64(getpid(), termout, 0, 0, FALSE); output_stream_write(termout, STRSEPARATOR, sizeof(STRSEPARATOR)); format_hex_u64_lo((u64)(intptr)pthread_self(), termout, 0, 0, FALSE); output_stream_write(termout, STRSEPARATOR, sizeof(STRSEPARATOR)); ya_result n = strlen(text); output_stream_write(termout, (const u8*)text, n); output_stream_write(termout, STREOL, 1); mutex_unlock(&debug_osformat_mtx); return n + 1; } ya_result print(const char* text) { return output_stream_write(termout, (const u8*)text, strlen(text)); } ya_result println(const char* text) { ya_result n = strlen(text); output_stream_write(termout, (const u8*)text, n); output_stream_write(termout, STREOL, 1); return n + 1; } int format(const char* fmt, ...) { va_list args; va_start(args, fmt); ya_result err = vosformat(termout, fmt, args); va_end(args); return err; } ya_result formatln(const char* fmt, ...) { va_list args; va_start(args, fmt); ya_result err1 = vosformat(termout, fmt, args); va_end(args); if(ISOK(err1)) { ya_result err2 = output_stream_write(termout, STREOL, 1); if(ISOK(err2)) { return err1 + err2; } return err2; } return err1; } int vsnformat(char* out, size_t out_size, const char* fmt, va_list args) { if(out_size == 0) { return 0; } output_stream baos; bytearray_output_stream_context baos_context; bytearray_output_stream_init_ex_static(&baos, (u8*)out, out_size - 1, 0, &baos_context); int ret = vosformat(&baos, fmt, args); if(ret < (int)out_size) { out[ret] = CHR0; } else { out[out_size - 1] = CHR0; } output_stream_close(&baos); return ret; } /** * This formatter will return an allocated (malloc) string as a result of the format * * @param outp * @param out_size * @param fmt * @param args * @return */ int vasnformat(char** outp, size_t out_size, const char* fmt, va_list args) { output_stream baos; bytearray_output_stream_context baos_context; bytearray_output_stream_init_ex_static(&baos, NULL, out_size, 0, &baos_context); int ret = vosformat(&baos, fmt, args); if(ISOK(ret) && ((out_size == 0) || (ret < (int)out_size))) { output_stream_write_u8(&baos, 0); *outp =(char*)bytearray_output_stream_dup(&baos); } else { *outp = NULL; } output_stream_close(&baos); return ret; } /** * This formatter will return an allocated (malloc) string as a result of the format * * @param outp * @param out_size * @param fmt * @param ... * @return */ int asnformat(char** outp, size_t out_size, const char* fmt, ...) { int ret; va_list args; va_start(args, fmt); ret = vasnformat(outp, out_size, fmt, args); va_end(args); return ret; } /** * This formatter will return an allocated (malloc) string as a result of the format * * @param outp * @param fmt * @param ... * @return */ int asformat(char** outp, const char* fmt, ...) { int ret; va_list args; va_start(args, fmt); ret = vasnformat(outp, 0, fmt, args); va_end(args); return ret; } int snformat(char* out, size_t out_size, const char* fmt, ...) { int ret; va_list args; va_start(args, fmt); ret = vsnformat(out, out_size, fmt, args); va_end(args); return ret; } int osprint_base64(output_stream* os, const u8* rdata_pointer, u32 rdata_size) { char buffer[65]; int total = 0; u32 n; while(rdata_size > 48) { n = base64_encode(rdata_pointer, 48, buffer); buffer[n++] = ' '; output_stream_write(os, (u8*)buffer, n); total += n; rdata_pointer += 48; rdata_size -= 48; } n = base64_encode(rdata_pointer, rdata_size, buffer); output_stream_write(os, (u8*)buffer, n); total += n; return total; } int osprint_base16(output_stream* os, const u8* rdata_pointer, u32 rdata_size) { char buffer[65]; int total = 0; u32 n; while(rdata_size > 32) { n = base16_encode(rdata_pointer, 32, buffer); buffer[n++] = ' '; output_stream_write(os, (u8*)buffer, n); total += n; rdata_pointer += 32; rdata_size -= 32; } n = base16_encode(rdata_pointer, rdata_size, buffer); output_stream_write(os, (u8*)buffer, n); total += n; return total; } int fformat(FILE* out, const char* fmt, ...) { char tmp[4096]; #if DEBUG memset(tmp, '!', sizeof(tmp)); #endif int ret; va_list args; va_start(args, fmt); ret = vsnformat(tmp, sizeof(tmp), fmt, args); fputs(tmp, out); va_end(args); return ret; } /*------------------------------------------------------------------------------ * FUNCTIONS */ void osprint_u32(output_stream* os, u32 value) { format_dec_u64(value, os, 9, ' ', FALSE); } void osprint_u16(output_stream* os, u16 value) { format_dec_u64(value, os, 5, ' ', FALSE); } void osprint_u32_hex(output_stream* os, u32 value) { format_hex_u64_common(__hexa__, value, os, 8, '0', FALSE); } void print_char(char value) { char tmp[1]; tmp[0] = value; output_stream_write(&__termout__, (u8*)tmp, 1); } void osprint_char(output_stream* os, char value) { char tmp[1]; tmp[0] = value; output_stream_write(os, (u8*)tmp, 1); } void osprint_char_times(output_stream *os, char value, int times) { char tmp[32]; if(times < 0) { return; } if(times > 32) { memset(tmp, value, 32); do { output_stream_write(os, tmp, 32); times -= 32; } while(times >= 32); output_stream_write(os, tmp, times); } else { memset(tmp, value, times); output_stream_write(os, tmp, times); } } ya_result osprint_type_bitmap(output_stream* os, const u8* rdata_pointer, u16 rdata_size) { /* * WindowIndex + WindowSize + bits => a minimum of 3 bytes */ while(rdata_size >= 3) { u16 type_hi = *rdata_pointer++; u8 count = *rdata_pointer++; rdata_size -= 2; if(rdata_size < count) { return INCORRECT_RDATA; } rdata_size -= count; /*type_hi <<= 8;*/ u16 type_lo = 0; while(count-- > 0) { u8 bitmap = *rdata_pointer++; u32 b; for(b = 8; b > 0; b--) { if((bitmap & 0x80) != 0) { /* Enabled */ u16 type = type_hi + type_lo; osformat(os, " %{dnstype}", &type); } bitmap <<= 1; type_lo+=0x100; } } } return SUCCESS; } static const u32 loc_pow10[10] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; static const char loc_ns[2] = {'N','S'}; static const char loc_ew[2] = {'E','W'}; static bool loc_float(u8 v, u32* out_value) { u32 m = v >> 4; u32 e = v & 0x0f; if(!((m > 9) || (e > 9) || ((m == 0) && (e != 0)))) { *out_value = m * loc_pow10[e]; return TRUE; } else { return FALSE; } } struct loc_coordinate { int secfrac; int sec; int min; int deg; int cardinal_index; // N S // E W }; static void loc_coordinate_init(struct loc_coordinate* c, s32 val) { val -= (s32)0x80000000LU; if(val < 0) { val = -val; c->cardinal_index = 1; } else { c->cardinal_index = 0; } c->secfrac = val % 1000; val /= 1000; c->sec = val % 60; val /= 60; c->min = val % 60; val /= 60; c->deg = val; } ya_result osprint_rdata(output_stream* os, u16 type, const u8* rdata_pointer, u16 rdata_size) { char tmp[16]; switch(type) { case TYPE_A: { if(rdata_size == 4) { osformat(os, "%d.%d.%d.%d", rdata_pointer[0], rdata_pointer[1], rdata_pointer[2], rdata_pointer[3]); return SUCCESS; } return INCORRECT_RDATA; } case TYPE_AAAA: { u16* rdata_u16 = (u16*)rdata_pointer; if(rdata_size == 16) { char ip6txt[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, rdata_u16, ip6txt, sizeof(ip6txt)); osprint(os, ip6txt); return SUCCESS; } return INCORRECT_RDATA; } case TYPE_MX: case TYPE_KX: case TYPE_LP: case TYPE_AFSDB: osformat(os, "%hd ", ntohs(GET_U16_AT(*rdata_pointer))); rdata_pointer += 2; rdata_size -= 2; FALLTHROUGH // fall through case TYPE_NS: case TYPE_CNAME: case TYPE_DNAME: case TYPE_PTR: case TYPE_MB: case TYPE_MD: case TYPE_MF: case TYPE_MG: case TYPE_MR: { /* ONE NAME record */ if(rdata_size > 0) { output_stream_write_dnsname_text(os, rdata_pointer); return SUCCESS; } return INCORRECT_RDATA; } case TYPE_PX: { if(rdata_size >= 4) { osformat(os, "%hd ", ntohs(GET_U16_AT(*rdata_pointer))); rdata_pointer += 2; rdata_size -= 2; } else { return INCORRECT_RDATA; } } FALLTHROUGH // fall through case TYPE_TALINK: { if(rdata_size >= 2) { u32 len = output_stream_write_dnsname_text(os, rdata_pointer); rdata_size -= len; if(rdata_size > 0) { rdata_pointer += len; len = output_stream_write_dnsname_text(os, rdata_pointer); rdata_size -= len; if(rdata_size == 0) { return SUCCESS; } } } return INCORRECT_RDATA; } case TYPE_WKS: { if(rdata_size >= 6) { osformat(os, "%d.%d.%d.%d", rdata_pointer[0], rdata_pointer[1], rdata_pointer[2], rdata_pointer[3]); rdata_pointer += 4; rdata_size -= 4; ya_result len = protocol_id_to_name(rdata_pointer[0], tmp + 1, sizeof(tmp) - 1); if(len < 0) { return len; } tmp[0] = ' '; output_stream_write(os, tmp, len + 1); rdata_pointer++; rdata_size--; for(int index = 0; index < rdata_size; ++index) { u8 m; if((m = *rdata_pointer) != 0) { for(int i = 7; i >= 0; --i) { if((m & (1 << i)) != 0) { u16 port = (u16) ((index << 3) + 7 - i); len = server_port_to_name(port, tmp + 1, sizeof(tmp) - 1); if(len < 0) { return len; } output_stream_write(os, tmp, len + 1); } } } } return SUCCESS; } return INCORRECT_RDATA; } case TYPE_GPOS: { const u8 *limit = &rdata_pointer[rdata_size]; for(int i = 0; i < 3; ++i) { u8 len = *rdata_pointer++; if(len == 0) { return INCORRECT_RDATA; } if(&rdata_pointer[len] >= limit) { return INCORRECT_RDATA; } output_stream_write_u8(os, (u8)'"'); output_stream_write(os, rdata_pointer, len); output_stream_write_u8(os, (u8)'"'); rdata_pointer += len; } return SUCCESS; } case TYPE_LOC: { /* * VERSION: This must be zero. * Implementations are required to check this field and make * no assumptions about the format of unrecognized versions. */ if(rdata_size != 16 || rdata_pointer[0] != 0) { return INCORRECT_RDATA; } /* * SIZE: The diameter of a sphere enclosing the described entity, in centimeters * format is a pair of four-bit unsigned integers, each ranging from zero to nine * This allows sizes from 0e0 (<1cm) to 9e9 (90,000km) to be expressed. * Four-bit values greater than 9 are undefined, as are values with a base of zero and a non-zero exponent */ u32 size, horizp, vertp; if(!loc_float(rdata_pointer[1], &size) || !loc_float(rdata_pointer[2], &horizp) || !loc_float(rdata_pointer[3], &vertp)) { return INCORRECT_RDATA; } /* * LATITUDE */ struct loc_coordinate loc_latitude; loc_coordinate_init(&loc_latitude, ntohl(GET_U32_AT(rdata_pointer[4]))); /* * LONGITUDE */ struct loc_coordinate loc_longitude; loc_coordinate_init(&loc_longitude, ntohl(GET_U32_AT(rdata_pointer[8]))); /* * ALTITUDE */ const u32 wgs84_reference = 10000000; // cm u32 altitude = ntohl(GET_U32_AT(rdata_pointer[12])); int altfrac; if(altitude < wgs84_reference) { altitude = wgs84_reference - altitude; altfrac = altitude % 100; altitude /= -100; } else { altitude = altitude - wgs84_reference; altfrac = altitude % 100; altitude /= 100; } osformat(os, "%u %u %u.%03u %c %u %u %u.%03u %c %d.%02um %dm %dm %dm", loc_latitude.deg, // degrees latitude [0 .. 90] loc_latitude.min, // minutes latitude [0 .. 59] loc_latitude.sec, // seconds latitude [0 .. 59] loc_latitude.secfrac, // fractions of seconds of latitude] loc_ns[loc_latitude.cardinal_index],// ['N' / 'S'] loc_longitude.deg, // degrees longitude [0 .. 90] loc_longitude.min, // minutes longitude [0 .. 59] loc_longitude.sec, // seconds longitude [0 .. 59] loc_longitude.secfrac, // fractions of seconds of longitude] loc_ew[loc_longitude.cardinal_index],// ['E' / 'W'] altitude, // altitude in meters [-100000.00 .. 42849672.95] altfrac, size, horizp, vertp); return SUCCESS; } case TYPE_CSYNC: { if(rdata_size > 6) { osformat(os, "%u %hu ", ntohl(GET_U32_AT(rdata_pointer[0])), ntohs(GET_U16_AT(rdata_pointer[4])) ); rdata_pointer += 6; rdata_size -= 6; return osprint_type_bitmap(os, rdata_pointer, rdata_size); } return INCORRECT_RDATA; } case TYPE_OPENPGPKEY: { if(rdata_size > 0) { return osprint_base64(os, rdata_pointer, rdata_size); } return INCORRECT_RDATA; } case TYPE_HINFO: case TYPE_MINFO: { /* Two Pascal String records */ /* * is a single length octet followed by that number * of characters. is treated as binary information, * and can be up to 256 characters in length (including the length octet). * */ int i; for(i = 0; i < 2; i++) { u32 len = (*rdata_pointer) + 1; if(len > rdata_size) { return INCORRECT_RDATA; } osformat(os, "%{dnslabel}", rdata_pointer); rdata_size -= len; rdata_pointer += len; } return SUCCESS; } case TYPE_SOA: { static u8 dot = (u8)'.'; static u8 space = (u8)' '; static u8 escape = (u8)'\\'; output_stream_write_dnsname_text(os, rdata_pointer); output_stream_write(os, &space, 1); u32 len = dnsname_len(rdata_pointer); rdata_size -= len; if(rdata_size > 0) { rdata_pointer += len; const u8 *label = rdata_pointer; u8 label_len = *label; if(label_len > 0) { label++; do { do { if(!dnsname_is_charspace(*label)) { output_stream_write(os, &escape, 1); } output_stream_write(os, label++, 1); } while(--label_len > 0); output_stream_write(os, &dot, 1); label_len = *label++; } while(label_len > 0); len = label - rdata_pointer; } else { output_stream_write(os, &dot, 1); len = 1; } rdata_size -= len; if(rdata_size == 20) { rdata_pointer += len; osformat(os, " %u %u %u %u %u", ntohl(GET_U32_AT(rdata_pointer[ 0])), ntohl(GET_U32_AT(rdata_pointer[ 4])), ntohl(GET_U32_AT(rdata_pointer[ 8])), ntohl(GET_U32_AT(rdata_pointer[12])), ntohl(GET_U32_AT(rdata_pointer[16]))); return SUCCESS; } } return INCORRECT_RDATA; } case TYPE_RRSIG: { struct tm exp; struct tm inc; time_t t = (time_t)ntohl(GET_U32_AT(rdata_pointer[8])); gmtime_r(&t, &exp); t = (time_t)ntohl(GET_U32_AT(rdata_pointer[12])); gmtime_r(&t, &inc); u16 covered_type = (GET_U16_AT(rdata_pointer[0])); /** @note NATIVETYPE */ osformat(os, "%{dnstype} %u %u %u %04u%02u%02u%02u%02u%02u %04u%02u%02u%02u%02u%02u %u ", &covered_type, U8_AT(rdata_pointer[2]), U8_AT(rdata_pointer[3]), ntohl(GET_U32_AT(rdata_pointer[4])), exp.tm_year + 1900, exp.tm_mon + 1, exp.tm_mday, exp.tm_hour, exp.tm_min, exp.tm_sec, inc.tm_year + 1900, inc.tm_mon + 1, inc.tm_mday, inc.tm_hour, inc.tm_min, inc.tm_sec, ntohs(GET_U16_AT(rdata_pointer[16]))); rdata_pointer += RRSIG_RDATA_HEADER_LEN; rdata_size -= RRSIG_RDATA_HEADER_LEN; output_stream_write_dnsname_text(os, rdata_pointer); u32 len = dnsname_len(rdata_pointer); output_stream_write_u8(os, ' '); rdata_pointer += len; rdata_size -= len; if(rdata_size > 0) { osprint_base64(os, rdata_pointer, rdata_size); } return SUCCESS; } case TYPE_DNSKEY: case TYPE_KEY: case TYPE_CDNSKEY: { osformat(os, "%u %u %u ", ntohs(GET_U16_AT(rdata_pointer[0])), U8_AT(rdata_pointer[2]), U8_AT(rdata_pointer[3])); rdata_pointer += 4; rdata_size -= 4; osprint_base64(os, rdata_pointer, rdata_size); return SUCCESS; } case TYPE_DS: case TYPE_CDS: { osformat(os, "%u %u %u ", ntohs(GET_U16_AT(rdata_pointer[0])), U8_AT(rdata_pointer[2]), U8_AT(rdata_pointer[3])); rdata_pointer += 4; rdata_size -= 4; while(rdata_size-- > 0) { osformat(os, "%02X", *rdata_pointer++); } return SUCCESS; } case TYPE_NSEC: { output_stream_write_dnsname_text(os, rdata_pointer); u32 len = dnsname_len(rdata_pointer); output_stream_write_u8(os, ' '); rdata_pointer += len; rdata_size -= len; ya_result ret; if(ISOK(ret = osprint_type_bitmap(os, rdata_pointer, rdata_size))) { return SUCCESS; } return ret; } case TYPE_NSEC3: case TYPE_NSEC3PARAM: { osformat(os, "%hhd %hhd %hd ", rdata_pointer[0], (type != TYPE_NSEC3PARAM) ? rdata_pointer[1] : 0, ntohs(GET_U16_AT(rdata_pointer[2]))); u8 len = rdata_pointer[4]; rdata_pointer += 5; rdata_size -= 5; if(len == 0) { osprint(os, "-"); } else { rdata_size -= len; while(len-- > 0) { osformat(os, "%02x", *rdata_pointer++); } } if(type == TYPE_NSEC3) { output_stream_write_u8(os, ' '); len = *rdata_pointer++; rdata_size -= 1 + len; ya_result return_code; if(FAIL(return_code = output_stream_write_base32hex(os, rdata_pointer, len))) { return return_code; } rdata_pointer += len; return_code = osprint_type_bitmap(os, rdata_pointer, rdata_size); return return_code; } return SUCCESS; } case TYPE_TLSA: { osformat(os, "%hhd %hhd %hhd ", rdata_pointer[0], rdata_pointer[1], rdata_pointer[2]); return osprint_base16(os, &rdata_pointer[3], rdata_size - 3); } case TYPE_SSHFP: { osformat(os, "%hhd %hhd ", rdata_pointer[0], rdata_pointer[1]); return osprint_base16(os, &rdata_pointer[2], rdata_size - 2); } case TYPE_NID: case TYPE_L64: { if(rdata_size == 10) { osformat(os, "%hu %04x:%04x:%04x:%04x", ntohs(GET_U16_AT(rdata_pointer[0])), ntohs(GET_U16_AT(rdata_pointer[2])), ntohs(GET_U16_AT(rdata_pointer[4])), ntohs(GET_U16_AT(rdata_pointer[6])), ntohs(GET_U16_AT(rdata_pointer[8])) ); return SUCCESS; } return INCORRECT_RDATA; } case TYPE_L32: { if(rdata_size == 6) { osformat(os, "%hu %hhu.%hhu.%hhu.%hhu", ntohs(GET_U16_AT(rdata_pointer[0])), rdata_pointer[2], rdata_pointer[3], rdata_pointer[4], rdata_pointer[5] ); return SUCCESS; } return INCORRECT_RDATA; } case TYPE_EUI48: { if(rdata_size == 6) { osformat(os, "%02x-%02x-%02x-%02x-%02x-%02x", rdata_pointer[0], rdata_pointer[1], rdata_pointer[2], rdata_pointer[3], rdata_pointer[4], rdata_pointer[5] ); return SUCCESS; } return INCORRECT_RDATA; } case TYPE_EUI64: { if(rdata_size == 8) { osformat(os, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", rdata_pointer[0], rdata_pointer[1], rdata_pointer[2], rdata_pointer[3], rdata_pointer[4], rdata_pointer[5], rdata_pointer[6], rdata_pointer[7] ); return SUCCESS; } return INCORRECT_RDATA; } case TYPE_SRV: { u16 priority = GET_U16_AT(rdata_pointer[0]); u16 weight = GET_U16_AT(rdata_pointer[2]); u16 port = GET_U16_AT(rdata_pointer[4]); const u8 *fqdn = (const u8*)&rdata_pointer[6]; return osformat(os, "%hd %hd %hd %{dnsname}", priority, weight, port, fqdn); } case TYPE_ZONE_TYPE: { u8 zone_type = rdata_pointer[0]; char *txt; switch(zone_type) { case ZT_HINT: { txt = "hint"; break; } case ZT_MASTER: { txt = "master"; break; } case ZT_SLAVE: { txt = "slave"; break; } case ZT_STUB: { txt = "stub"; break; } default: { txt = "undefined"; break; } } return osprint(os, txt); } case TYPE_ZONE_MASTER: case TYPE_ZONE_SLAVES: case TYPE_ZONE_NOTIFY: { u8 flags = rdata_pointer[0]; const u8 *src = &rdata_pointer[1]; ya_result total = 0; switch(flags & 0x0f) { case 4: { // 4 bytes total += osformat(os, "%d.%d.%d.%d", src[0], src[1], src[2], src[3]); src += 4; break; } case 6: { // 16 bytes char ip6txt[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &src, ip6txt, sizeof(ip6txt)); total += osprint(os, ip6txt); src += 16; break; } } if((flags & REMOTE_SERVER_FLAGS_PORT_MASK) != 0) { u16 port = GET_U16_AT(*src); total += osformat(os, " %hd", port); src += 2; } if((flags & REMOTE_SERVER_FLAGS_KEY_MASK) != 0) { total += osformat(os, " %{dnsname}", src); } return total; } case TYPE_TXT: case TYPE_SPF: { u8 c; if(rdata_size > 0) { for(;;) { c = *rdata_pointer++; if(c > 0) { c = MIN(c, rdata_size); output_stream_write(os, (u8*)"\"", 1); output_stream_write(os, rdata_pointer, c); output_stream_write(os, (u8*)"\"", 1); } rdata_size--; rdata_pointer += c; rdata_size -= c; if(rdata_size == 0) { break; } output_stream_write(os, (u8*)" ", 1); } } return SUCCESS; } case TYPE_CTRL_ZONEFREEZE: case TYPE_CTRL_ZONEUNFREEZE: case TYPE_CTRL_ZONENOTIFY: case TYPE_CTRL_ZONERELOAD: case TYPE_CTRL_ZONECFGRELOAD: { /* ONE NAME record */ if(rdata_size > 0) { ya_result ret = output_stream_write_dnsname_text(os, rdata_pointer); return ret; } return SUCCESS; } case TYPE_CTRL_SRVLOGLEVEL: case TYPE_CTRL_SRVQUERYLOG: { if(rdata_size == 1) { format_hex_u64_lo(rdata_pointer[0], os, 2, '0', FALSE); return SUCCESS; } return INCORRECT_RDATA; } case TYPE_CTRL_ZONESYNC: { /* ONE NAME record */ if(rdata_size > 0) { format_hex_u64_lo(rdata_pointer[0], os, 2, '0', FALSE); if(rdata_size > 1) { output_stream_write_u8(os, (u8)' '); ya_result ret = output_stream_write_dnsname_text(os, rdata_pointer + 1); if(ISOK(ret)) { return ret + 3; } else { return ret; } } } return SUCCESS; } case TYPE_TSIG: { const u8 *limit = &rdata_pointer[rdata_size]; ya_result ret = output_stream_write_dnsname_text(os, rdata_pointer); if(FAIL(ret)) { return ret; } rdata_pointer += ret; if(limit - rdata_pointer < 16) { return ERROR; } u16 time_hi = ntohs(GET_U16_AT(rdata_pointer[0])); u32 time_lo = ntohl(GET_U32_AT(rdata_pointer[2])); u16 fudge = ntohs(GET_U16_AT(rdata_pointer[6])); u16 mac_size = ntohs(GET_U16_AT(rdata_pointer[8])); rdata_pointer += 10; if(limit - rdata_pointer < mac_size + 6) { return ERROR; } u64 epoch = time_hi; epoch <<= 32; epoch |= time_lo; osformat(os, " %u %hu %hu", epoch, fudge, mac_size); if(mac_size > 0) { osprint_char(os, ' '); osprint_base64(os, rdata_pointer, mac_size); rdata_pointer += mac_size; } u16 oid = ntohs(GET_U16_AT(rdata_pointer[0])); u16 error = ntohs(GET_U16_AT(rdata_pointer[2])); u16 olen = ntohs(GET_U16_AT(rdata_pointer[4])); rdata_pointer += 6; if(limit - rdata_pointer != olen) { return ERROR; } osformat(os, " %i %s %i ", ntohs(oid), dns_message_rcode_get_name(error), olen); for(; rdata_pointer < limit; ++rdata_pointer) { osformat(os, "%02x", rdata_pointer[0]); } break; } case TYPE_A6: case TYPE_IXFR: case TYPE_AXFR: case TYPE_SIG: case TYPE_ANY: default: osformat(os, "\\# %u ", rdata_size); /* rfc 3597 */ osprint_base16(os, rdata_pointer, rdata_size); return SUCCESS; } return INCORRECT_RDATA; } #if 0 static int osprint_rdata_count_escapes(const u8* name, size_t name_len) { int ret = 0; for(size_t i = 0; i < name_len; ++i) { const char c = name[i]; for(size_t j = 0; j < sizeof(ESCAPE_CHARS); ++j) { if(c == ESCAPE_CHARS[j]) { ++ret; } } } return ret; } #endif ya_result osprint_rdata_escaped(output_stream* os, u16 type, const u8* rdata_pointer, u16 rdata_size) { switch(type) { case TYPE_MX: case TYPE_KX: case TYPE_LP: case TYPE_AFSDB: osformat(os, "%hd ", ntohs(GET_U16_AT(*rdata_pointer))); rdata_pointer += 2; rdata_size -= 2; FALLTHROUGH // fall through case TYPE_NS: case TYPE_CNAME: case TYPE_DNAME: case TYPE_PTR: case TYPE_MB: case TYPE_MD: case TYPE_MF: case TYPE_MG: case TYPE_MR: { /* ONE NAME record */ if(rdata_size > 0) { output_stream_write_dnsname_text_escaped(os, rdata_pointer); return SUCCESS; } return INCORRECT_RDATA; } case TYPE_TALINK: { if(rdata_size >= 2) { u32 len = output_stream_write_dnsname_text_escaped(os, rdata_pointer); rdata_size -= len; if(rdata_size > 0) { rdata_pointer += len; len = output_stream_write_dnsname_text_escaped(os, rdata_pointer); rdata_size -= len; if(rdata_size == 0) { return SUCCESS; } } } return INCORRECT_RDATA; } case TYPE_HINFO: case TYPE_MINFO: { /* Two Pascal String records */ /* * is a single length octet followed by that number * of characters. is treated as binary information, * and can be up to 256 characters in length (including the length octet). * */ int i; for(i = 0; i < 2; i++) { u32 len = (*rdata_pointer) + 1; if(len > rdata_size) { return INCORRECT_RDATA; } output_stream_write_dnslabel_text_escaped(os, rdata_pointer); rdata_size -= len; rdata_pointer += len; } return SUCCESS; } case TYPE_SOA: { output_stream_write_dnsname_text_escaped(os, rdata_pointer); output_stream_write_u8(os, ' '); u32 len = dnsname_len(rdata_pointer); rdata_size -= len; if(rdata_size > 0) { rdata_pointer += len; output_stream_write_dnsname_text_escaped(os, rdata_pointer); output_stream_write_u8(os, ' '); len = dnsname_len(rdata_pointer); rdata_size -= len; if(rdata_size == 20) { rdata_pointer += len; osformat(os, " %u %u %u %u %u", ntohl(GET_U32_AT(rdata_pointer[ 0])), ntohl(GET_U32_AT(rdata_pointer[ 4])), ntohl(GET_U32_AT(rdata_pointer[ 8])), ntohl(GET_U32_AT(rdata_pointer[12])), ntohl(GET_U32_AT(rdata_pointer[16]))); return SUCCESS; } } return INCORRECT_RDATA; } case TYPE_RRSIG: { struct tm exp; struct tm inc; time_t t = (time_t)ntohl(GET_U32_AT(rdata_pointer[8])); gmtime_r(&t, &exp); t = (time_t)ntohl(GET_U32_AT(rdata_pointer[12])); gmtime_r(&t, &inc); u16 covered_type = (GET_U16_AT(rdata_pointer[0])); /** @note NATIVETYPE */ osformat(os, "%{dnstype} %u %u %u %04u%02u%02u%02u%02u%02u %04u%02u%02u%02u%02u%02u %u ", &covered_type, U8_AT(rdata_pointer[2]), U8_AT(rdata_pointer[3]), ntohl(GET_U32_AT(rdata_pointer[4])), exp.tm_year + 1900, exp.tm_mon + 1, exp.tm_mday, exp.tm_hour, exp.tm_min, exp.tm_sec, inc.tm_year + 1900, inc.tm_mon + 1, inc.tm_mday, inc.tm_hour, inc.tm_min, inc.tm_sec, ntohs(GET_U16_AT(rdata_pointer[16]))); rdata_pointer += RRSIG_RDATA_HEADER_LEN; rdata_size -= RRSIG_RDATA_HEADER_LEN; output_stream_write_dnsname_text_escaped(os, rdata_pointer); u32 len = dnsname_len(rdata_pointer); output_stream_write_u8(os, ' '); rdata_pointer += len; rdata_size -= len; if(rdata_size > 0) { osprint_base64(os, rdata_pointer, rdata_size); } return SUCCESS; } case TYPE_NSEC: { output_stream_write_dnsname_text_escaped(os, rdata_pointer); u32 len = dnsname_len(rdata_pointer); output_stream_write_u8(os, ' '); rdata_pointer += len; rdata_size -= len; ya_result ret; if(ISOK(ret = osprint_type_bitmap(os, rdata_pointer, rdata_size))) { return SUCCESS; } return ret; } case TYPE_SRV: { u16 priority = GET_U16_AT(rdata_pointer[0]); u16 weight = GET_U16_AT(rdata_pointer[2]); u16 port = GET_U16_AT(rdata_pointer[4]); const u8 *fqdn = (const u8*)&rdata_pointer[6]; osformat(os, "%hd %hd %hd ", priority, weight, port); ya_result ret = output_stream_write_dnsname_text_escaped(os, fqdn); return ret; } case TYPE_TXT: case TYPE_SPF: { u8 pascal_string_size; int space_len = 0; while(rdata_size > 0) { pascal_string_size = *rdata_pointer++; if(pascal_string_size > 0) { output_stream_write(os, (u8*)" ", space_len); pascal_string_size = MIN(pascal_string_size, rdata_size); output_stream_write(os, STRQUOTE, 1); for(int i = 0; i < pascal_string_size; ++i) { u8 escape_type = TXT_ESCAPE_TYPE[rdata_pointer[i]]; switch(escape_type) { case TXT_ESCAPE_TYPE_NONE: { output_stream_write(os, &rdata_pointer[i], 1); break; } case TXT_ESCAPE_TYPE_CHAR: { output_stream_write(os, STRESCAPE, 1); output_stream_write(os, &rdata_pointer[i], 1); break; } case TXT_ESCAPE_TYPE_OCTL: { u8 decimal[4]; decimal[0] = '\\'; decimal[1] = ((rdata_pointer[i] / 100) % 10) + '0'; decimal[2] = ((rdata_pointer[i] / 10) % 10) + '0'; decimal[3] = (rdata_pointer[i] % 10) + '0'; output_stream_write(os, decimal, 4); break; } } } output_stream_write(os, STRQUOTE, 1); } else { output_stream_write(os, "\"\"", 2); } space_len = 1; rdata_size--; rdata_pointer += pascal_string_size; rdata_size -= pascal_string_size; } return SUCCESS; } default: { ya_result ret = osprint_rdata(os, type, rdata_pointer, rdata_size); return ret; } } return INCORRECT_RDATA; } ya_result print_rdata(u16 type, u8* rdata_pointer, u16 rdata_size) { return osprint_rdata(termout, type, rdata_pointer, rdata_size); } void osprint_dump_with_base(output_stream *os, const void* data_pointer_, size_t size_, size_t line_size, u32 flags, const void* base_pointer_) { const u8* data_pointer = (const u8*)data_pointer_; size_t size = size_; bool offset = (flags & OSPRINT_DUMP_OFFSET) != 0; bool address = (flags & OSPRINT_DUMP_ADDRESS) != 0; bool hex = (flags & OSPRINT_DUMP_HEX) != 0; bool text = (flags & OSPRINT_DUMP_TEXT) != 0; bool squeeze_zeroes = (flags & OSPRINT_DUMP_SQUEEZE_ZEROES) != 0; size_t group = flags & OSPRINT_DUMP_LAYOUT_GROUP_MASK; group >>= OSPRINT_DUMP_LAYOUT_GROUP_SHIFT; size_t separator = flags & OSPRINT_DUMP_LAYOUT_SEPARATOR_MASK; separator >>= OSPRINT_DUMP_LAYOUT_SEPARATOR_SHIFT; s32 offset_width = 2 * 2; if(offset) { if(size_ > MAX_U16) { if(size_ <= MAX_U32) { offset_width = 4 * 2; } else { offset_width = 8 * 2; } } } size_t dump_size; size_t i; s64 zeroes_count = 0; char hexbyte[2]; do { if(line_size != 0) { dump_size = MIN(line_size, size); } else { dump_size = size; } const u8* data; if(squeeze_zeroes && (dump_size == line_size)) { if(base_pointer_ < (const void*)data_pointer) { bool zeroes = TRUE; for(int i = 0; i < (int)line_size; ++i) { if(data_pointer[i] != 0) { zeroes = FALSE; break; } } if(zeroes) { zeroes_count += line_size; data_pointer += dump_size; size -= dump_size; continue; } else if(zeroes_count > 0) { osformatln(os,"\t\t... %lli zeroes ...", zeroes_count); zeroes_count = 0; } } } if(address) { format_hex_u64_hi((intptr)data_pointer, os, __SIZEOF_POINTER__ * 2, '0', FALSE); output_stream_write(os, (const u8*)" | ", 3); } if(offset) { format_hex_u64_hi((intptr)data_pointer - (intptr)base_pointer_, os, offset_width, '0', FALSE); output_stream_write(os, (const u8*)" | ", 3); } if(hex) { data = data_pointer; for(i = 0; i < dump_size; i++) { u8 val = *data++; hexbyte[0] = __hexa__[val >> 4]; hexbyte[1] = __hexa__[val & 0x0f]; output_stream_write(os, (u8*)hexbyte, 2); if((i & group) == group) { output_stream_write_u8(os, (u8)' '); } if((i & separator) == separator) { output_stream_write_u8(os, (u8)' '); } } for(; i < line_size; i++) { output_stream_write(os, (const u8*)" ", 2); // these are two spaces if((i & group) == group) { output_stream_write_u8(os, (u8)' '); } if((i & separator) == separator) { output_stream_write_u8(os, (u8)' '); } } } if(text) { if(hex) { output_stream_write(os, (const u8*)" | ", 4); } data = data_pointer; for(i = 0; i < dump_size; i++) { char c = *data++; if(c < ' ') { c = '.'; } output_stream_write_u8(os, (u8)c); } } data_pointer += dump_size; size -= dump_size; if(size != 0) { output_stream_write_u8(os, (u8)'\n'); } } while(size > 0); } void osprint_dump(output_stream *os, const void* data_pointer_, size_t size_, size_t line_size, u32 flags) { osprint_dump_with_base(os, data_pointer_, size_, line_size, flags, data_pointer_); } void osprint_question(output_stream* os, u8* qname, u16 qclass, u16 qtype) { osformat(os, ";; QUESTION SECTION:\n%{dnsname} %{dnsclass} %{dnstype}\n\n", qname, &qclass, &qtype); } void print_question(u8* qname, u16 qclass, u16 qtype) { osprint_question(termout, qname, qclass, qtype); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/hash.c0000644000000000000000000000013114505005532020416 xustar000000000000000029 mtime=1695812442.44798226 30 atime=1695812445.794030182 30 ctime=1695812494.578728877 yadifa-2.6.5-11201/lib/dnscore/src/hash.c0000664000374500037450000001635014505005532020366 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Functions used to hash a dns formatted string * * Implements the functions used to hash a dns formatted string. * There functions require the call to an initialization function (hash_init); * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/hash.h" #define ZDBHTBL_TAG 0x4c42544842445a /* * [-] * [0;9] * [a;z] * * [2D] * [30;38] * [61;7A] * */ /** * * ['0';'9'] + ['A'/'a';'Z'/'z'] + ['-'] = 37 * */ #define DNSCORE_HASH_TABLE_CHAR_SET_SIZE 37 extern const u32 DNSCORE_HASH_TABLE[256][DNSCORE_HASH_TABLE_CHAR_SET_SIZE]; // start of generated tables const u32 DNSCORE_HASH_TABLE_MAP[256] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x07, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x00, 0x06, }; const hashcode WILD_HASH = 0xcf6798dc; // end of generated tables const u8* WILD_LABEL = (u8*)"\001*"; /** @brief Initializes the hash functions * * Initializes the hash function */ void hash_init() { // nothing to do } /** @brief Compute the hash code of a pascal name * * Compute the hash code of a pascal name. * The function hash_init() MUST be called once first. (This requirement will be lifted later) * An interesting thing about a dnsname label : it's a pascal string. * * @param[in] pascal_name the name in pascal form * * @return the hash code as a 32 bits integer */ hashcode hash_pascalname(const u8* pascal_name) { assert(pascal_name != NULL); u32 idx = 1; /* idx points into the HASH_TABLE */ /* I could initialize it to a hiher value (ie: 255) and * decrease it instead of the current behaviour. * This would allow to put a cpu-cheap limit on the * amount of chars taken in account in the hash computation. */ u32 len = *pascal_name++; u32 hash = DNSCORE_HASH_TABLE[len][0]; while(len-- > 0) { hash += DNSCORE_HASH_TABLE[idx++][DNSCORE_HASH_TABLE_MAP[*pascal_name++]]; } return hash; } /** @brief Compute the hash code of an asciiz name * * Compute the hash code of a pascal name from its asciiz form. * The function hash_init() MUST be called once first. (This requirement will be lifted later) * * @param[in] asciiz_name the name in asciiz form * * @return the hash code as a 32 bits integer */ hashcode hash_asciizname(const char* asciiz_name) { assert(asciiz_name != NULL); u32 idx = 1; /* idx points into the HASH_TABLE */ /* I could initialize it to a hiher value (ie: 255) and * decrease it instead of the current behaviour. * This would allow to put a cpu-cheap limit on the * amount of chars taken in account in the hash computation. */ u32 len = (u32)strlen(asciiz_name); u32 hash = DNSCORE_HASH_TABLE[len][0]; while(len-- > 0) { hash += DNSCORE_HASH_TABLE[idx++][DNSCORE_HASH_TABLE_MAP[(u8)(*asciiz_name++)]]; } return hash; } /** @brief Compute the hash code of a char array * * Compute the hash code of a pascal name from its asciiz form. * The function hash_init() MUST be called once first. (This requirement will be lifted later) * * @param[in] ascii char array * @param[in] len number of chars in the array * * @return the hash code as a 32 bits integer */ hashcode hash_chararray(const char* ascii, size_t len) { assert(ascii != NULL); u32 idx = 1; /* idx points into the HASH_TABLE */ /* I could initialize it to a hiher value (ie: 255) and * decrease it instead of the current behaviour. * This would allow to put a cpu-cheap limit on the * amount of chars taken in account in the hash computation. */ u32 hash = DNSCORE_HASH_TABLE[len][0]; while(len-- > 0) { hash += DNSCORE_HASH_TABLE[idx++][DNSCORE_HASH_TABLE_MAP[(u8)(*ascii++)]]; } return hash; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/hash-table-values.c0000644000000000000000000000013214505005532023001 xustar000000000000000030 mtime=1695812442.481982747 30 atime=1695812445.795030196 30 ctime=1695812494.580728906 yadifa-2.6.5-11201/lib/dnscore/src/hash-table-values.c0000664000374500037450000034640214505005532022754 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Hash table used to hash the dns names. * * Hash table used to hash the dns names. * * @{ */ #include "dnscore/dnscore-config.h" #include /** * @note I've tried the transposed hash table to see what would be faster: * * [0](0) : 33572985/s * [0](T) : 28201308/s * [1](0) : 17625817/s * [1](T) : 16023470/s * * [0](ORIGINAL) ayiuoez9 : 89285714/s * [0](TRANSPOS) ayiuoez9 : 76923076/s * [1](ORIGINAL) aeiouyz0 : 88495575/s * [1](TRANSPOS) aeiouyz0 : 78740157/s * [2](ORIGINAL) aeio : 178571428/s * [2](TRANSPOS) aeio : 126582278/s * [3](ORIGINAL) m : 434782608/s * [3](TRANSPOS) m : 357142857/s * [4](ORIGINAL) : 714285714/s * [4](TRANSPOS) : 666666666/s * * The original one is the fastest with both the old and the new algorithm. * */ /* Hash Values */ const u32 DNSCORE_HASH_TABLE[256][37] = { {0xD885253C, 0x099128C1, 0xED616222, 0xFBBDF883, 0x068A4C7C, 0xF67E891C, 0xC677F8A4, 0x66CA897F, 0x12E738AB, 0x72A0BE2B, 0x11993499, 0x721556B1, 0x705D9504, 0x1871489D, 0x368E67DF, 0x41529873, 0x3C543C6F, 0xF309AAF5, 0xCAB1BEA5, 0x68CE1DBF, 0x4AA2A113, 0xDC25905E, 0x62414D91, 0xC2F014D1, 0xE7626577, 0x7707D6B7, 0xFA082FCF, 0xD62E4D5D, 0xFA106A65, 0x7910F6E8, 0x852D4222, 0xD0BF0B0B, 0x9D9DED71, 0x81111D09, 0x8D789900, 0xC54486B5, 0x10D50D72}, {0xA2491394, 0xCC2B1C8D, 0x150567B0, 0xC492F934, 0xD6F1BF73, 0x2D1E8548, 0x58422644, 0x716148CE, 0x78E95C1B, 0x173F5E66, 0xD3206569, 0xB62603D0, 0xF0EC1CFF, 0x0AA221A6, 0xF1664A6C, 0x16318678, 0x03E6D82A, 0x219FCA53, 0xC230E1AC, 0xC8EDB62C, 0x15E1898C, 0xB47F0AAE, 0x57049F3D, 0x6696233C, 0x0D5BA666, 0xCCFFA387, 0x00ACEC12, 0xF9834B21, 0x9E146B14, 0x1B5B813F, 0x979F0C04, 0x1E31AE5D, 0xFA9A6309, 0xDE2848E3, 0xF8E07777, 0xF183C9AA, 0xF946ACDF}, {0x3D4AEC7E, 0x99A882B2, 0x48555C8B, 0x93F5A31F, 0x2E180A28, 0x16E840B8, 0x2482CEBC, 0x31A6ED1B, 0x230F22B0, 0x8DADB3C4, 0xA9C2AFB0, 0x077B0300, 0x088FF2F4, 0xB9947644, 0xB775505C, 0x2769A2DC, 0xD48966B4, 0x7D488DAA, 0x1C7A01EE, 0x785D9285, 0x2423CE62, 0x8443A91E, 0xE60C3BBA, 0xB426DCFB, 0xD9FE0411, 0x1D1D7569, 0x18A0E08E, 0xC367805F, 0xD9603669, 0x9608F952, 0xC9DB7D94, 0x335B6305, 0x21568518, 0xE4A3A305, 0xDE663512, 0xA373935E, 0x4C2BA61C}, {0x5320BF91, 0x46B97147, 0xA661442E, 0x7B99D786, 0xA4992356, 0x63DFD36B, 0x8BDED2EA, 0xF4D581ED, 0x8EB9C4E1, 0xB25C94DD, 0xB9B6FD62, 0xCA117B01, 0x8ACF553E, 0x28E5C3A6, 0x69D8E108, 0xD6553C51, 0x89CC0635, 0x8E4D3109, 0xD0F2A698, 0x20C3B5CA, 0x6B185697, 0xF15EC427, 0x5143E302, 0xDC208CBF, 0x4CE40E31, 0x640D6365, 0x1DD81DA6, 0x3C19F9A7, 0xCBDF28EB, 0xDE235A7F, 0x1BD4F443, 0xC56317FA, 0x587EA1D3, 0x4744603D, 0xAF8C3D83, 0xD0FD7229, 0xDDE6EBCC}, {0x4AEF7B3E, 0x67475872, 0xB9174BDE, 0xABDECF1A, 0xE486D79F, 0x0A8CF93E, 0xEE4E8E99, 0x5FEC125B, 0x9502FA02, 0xECD50BCA, 0x4DC485F2, 0x3E12FF9E, 0xFF74EC95, 0xFEEAE032, 0x3EA99AFD, 0x90A4DE00, 0xB0BFC059, 0x1609AA78, 0xF4BC7936, 0x4F202FE9, 0xA22992E7, 0x34A1267C, 0x406AB625, 0x009F8F47, 0x6C316B8D, 0xE40E8218, 0x407255B0, 0x12017B30, 0xB1BE5052, 0x6777EE94, 0x0C60B1B7, 0x313229FC, 0x8341F8FD, 0x57F8854E, 0xBEC773E8, 0x19662938, 0xB76E142B}, {0x5CF777FB, 0x4E962996, 0x7ED09551, 0xE0AA3C02, 0x252BE4EB, 0x974EF663, 0x54DF80A7, 0x16115A3F, 0x2721838C, 0xCD813B11, 0xB1A52503, 0xF4F645FD, 0xBBE5DFAE, 0x2724C441, 0xEBC55FF6, 0x2984B0C0, 0x16BCD529, 0x2EB8DC8F, 0x02E5D931, 0x501F8047, 0xD0E6EA24, 0x0C6A014F, 0xDEA06675, 0xFAC56253, 0x67DD573A, 0xF6462E03, 0x1E28241A, 0xEBFBD5E1, 0xD825130B, 0xE339D315, 0x0DA46324, 0x5CE9B3D6, 0x81E0A9EF, 0xB1A9C3DB, 0xBF7AD38A, 0x039A8FB5, 0x4C9A77A4}, {0x668C91BD, 0xDE6B5641, 0xBAA14EA8, 0x047FED27, 0xEB96B51D, 0x0BAB2C44, 0xF022C7DF, 0xAC9026C4, 0x67FE3EAA, 0xF2E994E9, 0x4825DBCA, 0xB037E49B, 0x2005DA9E, 0xE4873DA2, 0xE0F08ADE, 0x84C3153C, 0x58C3B7DA, 0xB1E59747, 0xD3694882, 0xDE570D81, 0x8E2B9FAE, 0xADEEA492, 0x54292E36, 0x580BD4C9, 0xDCBA370C, 0xE04A6FCB, 0x557C21C7, 0xF30371C0, 0x1043CD6B, 0xC5F01E33, 0x52A3AC37, 0xC7EC9ECA, 0x6D432432, 0x06CB13BB, 0x6C564C7A, 0x4A12148E, 0x4B7F404B}, {0x9BDB1482, 0x048EC261, 0x3D1B8FDB, 0x78F05475, 0x1B80E5BA, 0xA890593B, 0xDF690678, 0x9F5EF12D, 0x28BFE37E, 0xFA491DAF, 0xAA1546DB, 0x069FA750, 0x3967BC58, 0x938DC293, 0x01E549D7, 0x34EE7EFB, 0xBF480AC3, 0x9FECFBD4, 0xECEFDB6F, 0x25E9AD0E, 0x5493A192, 0xC0AD627A, 0x62046635, 0xC1612124, 0x71AC3E8D, 0x805D5B6F, 0xA3E44C56, 0xAC192888, 0x7072B105, 0x58C504E0, 0x7B44F21C, 0xBBFDE1C2, 0x5602A037, 0x3D0341F6, 0xE2DD035F, 0x374021E7, 0x19105191}, {0xD2134A33, 0xDE18E8A0, 0xB414D965, 0x229D9CEF, 0xAE925137, 0x31D1641A, 0x0DBB8E44, 0xADF0AE51, 0xA7D920A2, 0x7DB74E6A, 0xD4512728, 0x8B90EB06, 0xEE56F37B, 0x75BEC3F3, 0x96E95EBD, 0x6CED8699, 0x6CDF6345, 0x378E6405, 0xD33DDCFC, 0x9B5C98A0, 0x10358257, 0x2EDA506C, 0x3E7D70AE, 0x99C21853, 0x545A2DA8, 0xB446D08C, 0x93AFE46D, 0x72F8A9D5, 0xD29B25C5, 0x051E29B5, 0x309424B4, 0x0B6A6BB4, 0x5F861964, 0x770E74C2, 0xB1BD9EC9, 0x95224FA1, 0x515C04A9}, {0x9000698C, 0x82B8B42C, 0x1E23E486, 0x676813B4, 0x08F291DB, 0x377F32C9, 0xED9FBED8, 0x1A6AB46E, 0x8C735C50, 0xB2B31FD5, 0xFA404624, 0x1071139D, 0x37B633C9, 0x943FC3AF, 0x2CBFBCBB, 0xC3D0D3CA, 0x9E625661, 0x973176D2, 0x2E10CBB6, 0x8D49AFBC, 0x62A5519E, 0x75DD0F0F, 0x43B7328F, 0xA408E248, 0xE94F9350, 0xCE860573, 0x9423CB42, 0x853A50CA, 0xE46D0292, 0xD44A52DB, 0xDBFDDCC7, 0xA4407C03, 0x2B4C425F, 0x2D29A766, 0x45F1E52C, 0x3AEB6F11, 0x5330CCAC}, {0x76BFBF07, 0xE684CFD2, 0x05431C0F, 0x7EFA79B6, 0xDF3B2DDB, 0x3C3B3ABC, 0xA400BF3D, 0xDD095A2B, 0x7A455760, 0xC54D3A68, 0x17EE161D, 0x3F42E066, 0x2713B8A3, 0x0553DE0F, 0xBC3F48DD, 0x8865D9A7, 0x4CA2E449, 0x51F88F57, 0x7069CB5B, 0x4B14366A, 0x4BFA4D55, 0x3FF0981D, 0x923EC9CD, 0xD94AFCD5, 0xC9C0C874, 0xA0A06A9A, 0xF744A314, 0xFE383B39, 0xCEEE5993, 0xA86EB6A6, 0x102088B4, 0xDC1D72E6, 0x71F97D53, 0xD6C42CFF, 0xAC9FE0E7, 0x352114D1, 0xA64E38C8}, {0x2FA7725C, 0x5BE73F35, 0x6EFE4BAD, 0x7184BF60, 0x9C29C2DB, 0x8DE48EB8, 0xEED5F58E, 0x330DA68C, 0x256F7E5A, 0x7419E8E3, 0x0BBD42B1, 0xAB17E7D5, 0x9B2E5472, 0x2CB5EAA4, 0x40DBEEE7, 0x3335CC7E, 0x06FF0A37, 0x1047797D, 0x25FCD2E1, 0xEABBCCDF, 0x1EB309B2, 0xF79FBE57, 0xB7467E44, 0x51D6EF89, 0x218CA588, 0xC850142C, 0x7C1A80BA, 0x34D39476, 0xB48922F0, 0x155B53AD, 0x27B53A4D, 0x464E7667, 0x23982914, 0xA94D3128, 0xEB560A54, 0x468C007A, 0xBF3F34C8}, {0x23A52E98, 0x4E9B4773, 0x3C9F662C, 0xB517FEEC, 0x270F4188, 0xA7504D8E, 0x45C33387, 0x18F1E537, 0xD7B186E8, 0x5772A5AA, 0x361747FC, 0x0CC8A293, 0xA2DD99E1, 0x5E2CCBD7, 0x3AEF54BB, 0x432BB4E2, 0x03F54A89, 0x82BA0987, 0xD215E742, 0xE76C76AB, 0xC928216E, 0x7DAAAB61, 0xBF7B15F4, 0xC124A10E, 0xCCCB931D, 0xC7A9986F, 0x49C69A27, 0x8B46A085, 0x94FE667F, 0xD23C9C37, 0x9D71C5F8, 0xCF1AC6AB, 0x9D05D458, 0x897645EB, 0x6BC45A56, 0x502E204E, 0x732C5136}, {0xCBA11C51, 0x8836F44B, 0x91C3980D, 0x42A82946, 0xA6FA2BDE, 0x6085A76F, 0x74D7452A, 0xA1C2E971, 0x0508DE5D, 0x8A3DBA4D, 0x3F8EEEB8, 0xB13D58A7, 0x27D72E34, 0x1AC7755E, 0x855F3E47, 0x1DEF7AFE, 0xF278D75D, 0x1BF0B875, 0x71C7BAA4, 0x375C2BCC, 0xE20360BD, 0xEA964E79, 0x38EBD6A6, 0x612613E6, 0xA9970CCF, 0x03B1484C, 0xCFD01C3A, 0xA645F8CB, 0x82980428, 0x7B68B294, 0x05597AFE, 0x5B641235, 0xD6B3DF3E, 0x899B896E, 0x771F9286, 0xAA9AEAF7, 0x4679FB37}, {0x9CB57F89, 0xE91DE720, 0x8CFD7D3A, 0xDB4005DC, 0x0C8198D2, 0xA388B79D, 0xDA0D3862, 0x0DFFC4EA, 0xAC3096EE, 0x3AACAD45, 0x0B452C37, 0x6F6114A5, 0xF7EE9566, 0x10329CA7, 0x4BA654F9, 0x35492AEC, 0x3AC3A53C, 0xC8D14C2E, 0xC17E387B, 0xCC57F0EB, 0x842DA76A, 0x1F0CD704, 0x1608EBD5, 0xD4EFB465, 0xF50F72AD, 0xF27270FA, 0x8C40F36F, 0x2D225C13, 0x7AAAA1E9, 0x98916391, 0x3A8B64A5, 0x826660A7, 0x3BA3F8E5, 0x378A9815, 0xB396302B, 0x3E30B3C2, 0x4EE1A91F}, {0x2DF0ECD0, 0x12B333C4, 0x9C541A74, 0x19421C37, 0x9DC3BC82, 0x4BF79A88, 0xCCFDF726, 0xEFF014FD, 0x0A7B8F73, 0x55EFFCF5, 0xFFEB81B7, 0x10D1651A, 0x51BBFEDA, 0xAD019A49, 0x4609E0FF, 0x89D1C25A, 0xF33A6007, 0x53EAC4F4, 0xCE40BD0D, 0x5EBD4D2D, 0xFE5D883C, 0x843C4F0D, 0x6681F4DF, 0x6A32CCDE, 0x137CE3EE, 0xAFEBD12F, 0xDC556527, 0x2C76EE4E, 0x4C7A062E, 0xD108610D, 0x6CC87CC6, 0x8352559E, 0x63C7297A, 0xDE76E562, 0x668F4E87, 0x78208FF5, 0x61EC64CE}, {0x79C953D7, 0x36B0A00C, 0x47DE99BE, 0x6AF532FE, 0xD593F790, 0x7CF2E4A4, 0xBF7BAFE5, 0x186FB65F, 0x201760B5, 0xD228CC03, 0x19E8EC8B, 0x514346CC, 0xE84BA45F, 0x77C93EB6, 0xB30F30E5, 0x46D334FC, 0x9EE5D985, 0xAF31CB1B, 0x88D3C5F7, 0x65BF04BB, 0x0C788FCC, 0x442A4D73, 0x8B0325AD, 0x3C792A03, 0x060F192D, 0xAD5C2463, 0x141B2BBE, 0x292D9C47, 0x21B6D27B, 0x2D7A264B, 0x98EF0DB4, 0xA6ECBF71, 0xE6F9565A, 0x24FE9F33, 0xDFB875D1, 0x70121197, 0x6E4F8E16}, {0x03BF81D0, 0xCE741340, 0x0FAEC483, 0x618EEE98, 0xE55C6259, 0x9C7EAAA9, 0x6351E282, 0x88FB4CC2, 0x8C460F1E, 0xBF8A1BC6, 0xE819D8D3, 0xD3BDF593, 0x7F1763CE, 0x41146EA2, 0xB0056809, 0x6CB6F389, 0x0FD5FCEE, 0xCF1D75D6, 0x01BD935E, 0xD89DCAB5, 0x314AD29C, 0x7DCA5CDB, 0xA91559B8, 0x49F5E92D, 0x0043CE81, 0x58355888, 0x697C051A, 0x94D0AF60, 0x69DB44C8, 0xCE438107, 0x133530C1, 0xF691C557, 0xCDD18634, 0xCBF8FDC3, 0xBC669C1A, 0x8BDFA83A, 0x17AFE9C8}, {0xC4F29786, 0x55BC48FE, 0xE2F486C0, 0xA43AEC74, 0x3D574BD5, 0x308747BD, 0xCC254739, 0x0BB39211, 0xF7D472DC, 0x9B96AE41, 0x5BE53336, 0x6947FB44, 0xB3EC1B1D, 0x6557EB4E, 0x4A904192, 0x6039E9E9, 0xE7DF3721, 0x2D3DC0EF, 0x3DF37128, 0x52ADD676, 0x3A891C83, 0x955BA477, 0x7608920C, 0x63F66B84, 0x89245BF4, 0x84C35891, 0xEBB17BA2, 0x2EE23E6F, 0xD7E2AE29, 0x6F517BDF, 0x9E758F74, 0x6C31CA6F, 0xAE6EE2F1, 0xE39492F9, 0xE459308D, 0xEC5401DA, 0xDE273F8A}, {0x76972B4A, 0x834C6929, 0x7FC6B6D4, 0x6938B3AF, 0x8AC97047, 0xA795A7FC, 0x68FED4B7, 0xAF7D6323, 0xC14938A3, 0x10448F83, 0xC23A71D5, 0x7C129684, 0x61258A43, 0x58E2687D, 0x3849C7DA, 0x887A27B5, 0x08D7BC75, 0x1FBD688C, 0xB8F1B363, 0xBA530790, 0x634D32A5, 0x5921F197, 0x29F5319D, 0x89F72CE9, 0x7A7F98E7, 0x59D79A52, 0x38F801C1, 0x9189A4C7, 0xB28F48B9, 0xB09774C5, 0x2FD7C8FF, 0xF6073A90, 0x4BA1B4F7, 0x87F8BD46, 0x5D93668C, 0xDB25E918, 0x6071FB3E}, {0xDC8D5C7F, 0xE9B946C7, 0xC33F961E, 0x76B40B05, 0x7229BEE5, 0xA578494B, 0xD193EED2, 0x634B3767, 0xA1A65BA4, 0xB2A18235, 0x774E87A1, 0x6C8ADE9F, 0x78B46ADF, 0x407207E6, 0xB32BE3AC, 0x3C2AB33A, 0xC859B31C, 0x5455D4E3, 0x6A75F655, 0x30FF62CD, 0xBA638A5B, 0x29A0B2E4, 0xB956976C, 0x7F48B1C1, 0x4FFF27C2, 0x0E964ED4, 0x2F520E8F, 0x0FA8F0AB, 0x6CD557C4, 0xBB84490C, 0x276708EA, 0xE01D97C3, 0x24FB5A86, 0xED21132C, 0xD21372B0, 0x81F19CDD, 0x5E5E8460}, {0xFFCAE46D, 0xB98757A7, 0x51D63497, 0xE5DF95A3, 0xBDD6478B, 0x2EA1FFD4, 0xABCBA456, 0xDC6ECA92, 0xEA167D0C, 0x3715AF06, 0x2B86317D, 0x535C8C2D, 0x397763D6, 0xFF949AA1, 0xAEBE24BB, 0x059BB8CA, 0x2C78A456, 0xA040F26F, 0x3D30E1E0, 0x9D13C549, 0x0E0CEB7D, 0x45956EE4, 0xF987526A, 0xB89F88ED, 0x028AE881, 0x76D914A5, 0x44237D8E, 0x56263328, 0x120D7AAC, 0xA2D7FC89, 0x485A2163, 0x7AB65F15, 0x49EA029E, 0xCD019A18, 0x3C954E8D, 0x41138BCE, 0xF1636DC9}, {0xA8DA5479, 0xF274D9D3, 0x58584D14, 0x9DD05A48, 0x588391AA, 0x2D9C5D08, 0xBB2A229A, 0xAEDDCE59, 0x947E8C0C, 0x921AA6B0, 0x859077E0, 0xD3E07D58, 0x5811D762, 0x23B0636B, 0xF7CC5429, 0xE64B42D2, 0xEE5F9EA7, 0x879F94D8, 0xF770D695, 0xDB67E31D, 0xF00E3CB2, 0xC6F70C2D, 0xB71E95C2, 0x1A3836BF, 0x91405CE5, 0xF6E5AB42, 0xEA25B8A9, 0xC7FDFE5E, 0x9C9EDB98, 0xFCBEE52E, 0xA097519D, 0x597C2EB0, 0x3529A37D, 0xD1004D1B, 0x6D172B46, 0xD7CCE7CC, 0xF3244EAA}, {0x7B84EB7E, 0x13EE01B3, 0x1999758A, 0x82E51C1A, 0x1DBC0715, 0x9F4E6A49, 0xB216CC8D, 0xD7D82BED, 0x2FF36E0E, 0x77107DD9, 0x0FEBD72E, 0x1283A686, 0xBD5A4935, 0x623E9F54, 0xB087F32D, 0xCFD89761, 0xBFFE31BA, 0x277E82EE, 0xDE0788DD, 0x5844BE6D, 0x134DF11A, 0x34DD936F, 0x92192354, 0xBC1C835B, 0x076ACF0C, 0xB4F48855, 0xAD3F367F, 0xCE8E104D, 0x1E0BFE6A, 0xB98D386F, 0x2A004912, 0x8D55C0C2, 0x089A10ED, 0xFC7F202C, 0xC969F5C4, 0xF181680B, 0x6D727DF1}, {0x357786BB, 0xEBFFA61E, 0x43582E82, 0x5B315B5E, 0x93993D96, 0x5C4DD85A, 0x03ECD45B, 0x07A82EC4, 0xF8389AC6, 0x315636C5, 0xF196985B, 0x9AB97A91, 0xA3BF113F, 0xA5028C88, 0x4B665550, 0x765309E3, 0x54C5E6D0, 0xC96F43C5, 0x71B8D322, 0x22631A18, 0xA16E6C83, 0x431C3476, 0x638BEBE3, 0x8C7B2D40, 0x45864744, 0xE1C7A748, 0x7010429F, 0xFCE8ACA0, 0x4529CF75, 0x4941483D, 0x0E585CBD, 0x17EFD999, 0x644BEC64, 0x565FCE57, 0xDA9A2FF0, 0x1E95C6C5, 0x5D82260F}, {0x9740DBF4, 0x5CAAFAFA, 0xE0781578, 0x2577EB5E, 0xE2203046, 0xA94BF2E5, 0x79A612DB, 0x10F94313, 0xF6983D99, 0xE47F681A, 0xBD6641EA, 0xB3620DEB, 0x92C503DE, 0x873CBA35, 0x6028D617, 0xD0929BD7, 0x5CA57C25, 0x70B2872C, 0x325F24B7, 0x9FEE662F, 0x655FAF73, 0x205D1E1F, 0x979D5D76, 0xBB39D090, 0xC74451CC, 0xF249B44D, 0x59413684, 0x78E99106, 0x3025110C, 0xCC602C86, 0x93CFFAAA, 0x8B3A3723, 0x5C46CF21, 0x1AE33E88, 0xEB9FD840, 0x8D56725A, 0x7DB70AED}, {0x9B105C95, 0x90607C64, 0xA4C03E0A, 0x4501B61E, 0xB5AEC5BF, 0xFB6D4B84, 0xD8513A75, 0x45C3A38E, 0x4B229625, 0x1248A03D, 0xCD4B95BD, 0x39FAEFD1, 0x9512C46A, 0xAC15BAFD, 0x9C6EBBF5, 0x1D5C5A3E, 0xBCF07AB8, 0x773FAC88, 0xBA2AA4F2, 0x796DC8C9, 0x1579913B, 0xD2C94654, 0x56937ACB, 0x87ED1382, 0xF96B6734, 0xE538E83F, 0x2FBF6651, 0x99F906FF, 0x56A0DE52, 0x51C87788, 0x0E2E73F7, 0x311863C1, 0x88627FA4, 0x75BDAC47, 0x4F91DC25, 0x65EAB074, 0xFB223A35}, {0x100A7345, 0xFBE038D2, 0x8D1F78AF, 0x22CCD951, 0x97672AAD, 0xD9F8A87A, 0x7C088D40, 0x2C370160, 0x90E14768, 0x55EB59E5, 0xE5CED485, 0x49C1D53B, 0x946FF420, 0xF6D692C3, 0xE975887A, 0x3F904803, 0x6309D281, 0xE45EA2E4, 0x8BC54B46, 0x9F5ABE00, 0xE86FC80A, 0x02617BBC, 0x0C99335D, 0x69133A45, 0x272C8A86, 0xE958EC72, 0x205803F5, 0x39467437, 0x87145369, 0xEC018595, 0xE64F2DA3, 0x70194301, 0xCD59F6ED, 0x7E4217EE, 0x648D093C, 0x2C294305, 0x16F697B7}, {0xB1B3EFF1, 0x606D21AA, 0x431CBF9D, 0x5AED97C1, 0x9353520F, 0xF006DEF3, 0x5FDC34C5, 0xEEDB20C2, 0x841F7843, 0xD185480C, 0xE2032F52, 0x9D565FAA, 0x68FD323F, 0x96A649DD, 0x0B77AD33, 0x63B6B315, 0x2FE9D0E1, 0x84A92C8C, 0x6D3E8EDC, 0xA6DCA4E3, 0xED0C6BA0, 0x67CE7956, 0x8F6E1455, 0xCF61B06D, 0x3F874B5C, 0x2A233586, 0x2011A762, 0x4AE0C327, 0xD7983D3F, 0x62ACD15D, 0x900E9EA6, 0xEB749CB8, 0xD15AF322, 0x210B89D1, 0x064D6934, 0x3B0C8F57, 0x3420F11C}, {0x7D8A9FF7, 0x08F1B9B4, 0x24ACBC49, 0x8AA2831D, 0xB8A8AE49, 0xB283ED38, 0x022FCDBE, 0xC243A109, 0x253C7F85, 0xC27DEA5F, 0xF417CC89, 0x82608798, 0xD4A7BBCB, 0x33700BA3, 0x901C3641, 0x64D8F603, 0x7C515EB3, 0xD1C7CE0B, 0xE7F4A2CD, 0x823AC760, 0xA7B0F961, 0x37D8BBDC, 0x603CF9C9, 0xD9F15C8C, 0x97764CF1, 0x2674800D, 0xB466FE93, 0x6F277CD4, 0x54FF4CA8, 0x2C7FD159, 0xD3CA6E35, 0x0A89316E, 0xE7AF6B75, 0x064E5DA4, 0x9EC433F1, 0x1976FE95, 0xE77F45ED}, {0x3A60FD52, 0x95F413F8, 0x387CFBD3, 0xA4BEA704, 0x8C252DA4, 0x4E947E3A, 0x81E8BF58, 0x0A297D88, 0xEFCD2549, 0xEA107720, 0x3A729CAB, 0x5B00ADFD, 0x59192E1E, 0xD6E32A28, 0xF2F4AC0F, 0xA439D94E, 0x52C0DD0A, 0x2C0DB3ED, 0x65976D81, 0x7B74AFC9, 0x888A5225, 0xF3E9DD6C, 0xE4D950BC, 0x5B08D44E, 0xB8B89D02, 0x4C0F5BCD, 0x23E7528A, 0x6A74631C, 0x32CEBF8C, 0xB6B3F91A, 0x24F5E4EA, 0x91EEE30F, 0x703B9D96, 0x37EE5806, 0x59539C69, 0x16871230, 0x19518348}, {0x92AAACF7, 0x963F837C, 0x9FFBBBB8, 0x267DBAB0, 0xE0355406, 0xCEA99FC7, 0xC0944C8F, 0x99A3D9B7, 0xC9C5AF82, 0xB421EA6F, 0x037D1FE2, 0xB4C819A7, 0x61719630, 0xB0D1FD01, 0x194A1121, 0xDA5B198A, 0xE0C245C1, 0xFA277523, 0x4ABDF545, 0x6F84062F, 0x168533B7, 0x8933835E, 0xC51012F8, 0xA0CD469F, 0x54DF3902, 0x5A5A8C4A, 0x9B24E67A, 0x209E5DBD, 0x8CDB97E7, 0xC9787ABA, 0x0B7E6C91, 0xF543DFB9, 0x28C2C779, 0x37DE8895, 0x920B99FC, 0x785FF132, 0x083204B8}, {0xDDA027A3, 0xC51AFB37, 0xCD9A3345, 0xA846243D, 0x3C2F56B6, 0x62A34DAA, 0x5B0DE142, 0x471B3B91, 0x6AF4BC34, 0x785A4F5F, 0x4ACF9132, 0xBDB392A0, 0x048AC4F5, 0x760E3CBF, 0x1BED9EE7, 0xC93F365B, 0x6FFBEC8E, 0xD4BBA12D, 0x590D33F8, 0xA81AD3CE, 0xB9E47136, 0x45CDA3F6, 0x99525C3E, 0x789604C6, 0xC1C124E1, 0xE7F5F0CF, 0xF2F5C175, 0xBB05A900, 0xE3D2853D, 0x180A0ACF, 0x163286AB, 0x58FE58BF, 0x953DE4A8, 0x09C6B8E4, 0x96DE0C2E, 0xC8ACB2E7, 0x37244EA5}, {0x4D594763, 0x56FC0696, 0xAC29E39B, 0x538FFF12, 0x164F3A03, 0x29B2B9D3, 0xA2C3FB7D, 0xBB14B942, 0xF88748DD, 0x365DADA6, 0xDEB734DE, 0x6ED860D4, 0x5E759942, 0x93E6BFA2, 0xF4B32040, 0x3651C389, 0x7F9EA5C5, 0xD7A6E0BE, 0x94D0CD8E, 0xA28289C8, 0xAAF5B3D2, 0x2C9EB3A4, 0x99BDA39C, 0xD6F7EE01, 0x0FCFB369, 0x459E5B83, 0x6262B205, 0x39707C6D, 0xA39293CC, 0xD6E737FC, 0x2163BCD6, 0xECFC5278, 0x11452A33, 0x5E1416BD, 0x6060B11A, 0x3E5B7005, 0xC2AC8CC2}, {0x9F2F5D81, 0xE89ED7FD, 0x1790939A, 0xE08549B0, 0x0FFDC897, 0xFB892726, 0xFF4AF729, 0x112D7EBE, 0xC103F753, 0xEB01EBFC, 0x9E0F0815, 0xEBDCDABE, 0xBFACA699, 0x0599EDF2, 0xF4910EF0, 0xBEB65D73, 0xDB7ED377, 0x33362688, 0xBBC3E750, 0x6B1EE572, 0xB27A6884, 0x1C69992B, 0x2B27220B, 0xFF939791, 0xB98A99A0, 0xF5A6BB01, 0xE0E301E4, 0x058EB273, 0x5EC6AEBA, 0xE31BF8A1, 0x16D62D0F, 0x391CF6D0, 0x7F48A3E6, 0x69F19A2A, 0xB0BD07E2, 0x549B6D95, 0x495E9C28}, {0xCE8465DF, 0x3651A299, 0x7AB47212, 0xB3EF0514, 0xF6392B79, 0x5A7A9CD0, 0x8DEEA124, 0x60639CB7, 0xA4294BA0, 0xACA4B328, 0x54F083EA, 0x7BEDD4DA, 0xE0235AB5, 0xBA60A198, 0x130025FE, 0x08AC3E8A, 0x8A089264, 0x1E1BB1B4, 0xD5DC988A, 0x3952CC3B, 0xAC33390F, 0xB6685FD2, 0xD5AF46DE, 0xED02EF9B, 0x4E08432E, 0x933C787D, 0x94EA3008, 0x26212B28, 0xEBD6E1A4, 0xE68E6F68, 0xC58378FE, 0xF0CC193F, 0x8824584A, 0x92861B78, 0x08FDC657, 0x82BABD9B, 0x9CB18A73}, {0x4E761F73, 0xE33AFB8E, 0x0994B970, 0x81D447AE, 0x2ADB5C7E, 0x3C1E5938, 0xE6351A60, 0xAC5CF756, 0xA492CA00, 0x1C6BB463, 0x0B0DED0D, 0x86C267A2, 0x444E414F, 0xC8CFD8A9, 0x1BF8BA97, 0x6511E0A5, 0x3BA69841, 0x44E534B0, 0x4A689E5B, 0xAEC18F0C, 0x898710CB, 0xED426FF7, 0xB23EB8EE, 0x8F4632B0, 0x6982EB46, 0x689D7087, 0xDC57CCA5, 0x8AF1D313, 0xAA6D7148, 0x6CE3C820, 0x98804417, 0x65666359, 0x7A5AF3DA, 0xE1B65AB1, 0x6DD9341F, 0x032CFC0D, 0x41920723}, {0x72A8128D, 0xC92433A8, 0xEEEC873D, 0x6A28C77A, 0x38BB6CE6, 0x191C21AC, 0xD85179AC, 0xC3F100C9, 0x289DE6A7, 0x1877D9E7, 0x9E8E8821, 0x5CAAD0A9, 0xE46CF441, 0x54588372, 0x29D9F2E3, 0x0360CB8A, 0x9CD52BED, 0xAC84821A, 0x2B9E4BCE, 0xA52F4A81, 0x7FFF30C9, 0x0F7CB7AB, 0x5AE37CEF, 0x6E19C8F3, 0x06DF9580, 0x380D8A7D, 0xD467D3A3, 0x2B966652, 0x15376B9E, 0xA3583E24, 0xF0770119, 0x3A23CB2B, 0xE28FC2E2, 0x4F69E1FF, 0x877FBDFA, 0x780A7186, 0x1FB4E106}, {0xB0D15B88, 0xC1AC90EC, 0x32DF98C5, 0x4A307A34, 0x0DA93FC7, 0x40CAE13D, 0xF1E5EA82, 0xCD59163F, 0xBEFF4371, 0xE00FC8D0, 0x35ED09C8, 0x3B5CC867, 0x28B23D0A, 0x312E740D, 0xE1AB35B6, 0x7FDC599A, 0x9B5D2C7A, 0xE43D149B, 0xBCD05047, 0x132926F5, 0xBD1F1511, 0x2FBDAE43, 0xD363596A, 0x935F43D0, 0x8F54EEAF, 0xCCAC9CC5, 0xD7528F30, 0x602B5B86, 0x3250DF81, 0x1C44B613, 0xF877AD17, 0xAE67E4C6, 0x47BF87A8, 0xAB3CE250, 0x4DB81AF2, 0x1E9C9D74, 0x480924D0}, {0xEA7F9E16, 0xA7516208, 0xC24A20A1, 0x17034D23, 0x6833978F, 0x7D953357, 0x7456A139, 0xB3097F4D, 0xBF41283E, 0x8F1EFB54, 0xF888AD56, 0x303CE840, 0x4031B220, 0xA475BA4B, 0x5E018F7B, 0x81D4720B, 0xE6414F31, 0xEF1CD8FE, 0x0E95910C, 0x09E92A73, 0x7C74DF69, 0x159E7E35, 0x0BFF973C, 0x841EB0DA, 0xA7822C9D, 0xA10BC00B, 0xA8D80B9C, 0x03727BB6, 0xD38FF5E3, 0xFC5957FB, 0xD75E52C9, 0x38D1B837, 0xB25E16F0, 0xA05B823E, 0xB6BF1EB3, 0x6BA9565E, 0xC43F258A}, {0xF0B81CEE, 0xEF7F5717, 0xB818C8E4, 0x5F5F6372, 0x9C0DD3E5, 0xC14DB857, 0x07628392, 0x3AD947CC, 0xE2F0B311, 0x847D589C, 0xD059DA66, 0x90731CA6, 0x52934F7E, 0x4C5F8457, 0x8F2CFDE0, 0x1A2147B4, 0x10B672A4, 0x67E4E7C8, 0x09F8DCDD, 0xD45E5113, 0x030B3F9B, 0x7BDDADE1, 0x64E97C43, 0xDE7DDB80, 0x2B698569, 0x72E32384, 0x11996106, 0xE2F89055, 0xBB8A5041, 0x1A531F5B, 0x27C9B8EB, 0x432579D5, 0xE88D2669, 0x9DBB1754, 0xF48A1D20, 0x0FE376F9, 0x81E7CAE0}, {0x313A0918, 0x06982C55, 0xBC8BFAFD, 0x093F5EC9, 0x3F4C421A, 0x015434C1, 0x5BE3B687, 0x8FA9609D, 0x1825F1B6, 0xB80F29A8, 0x5981631C, 0x8299145E, 0xED5B977B, 0xAF73D38E, 0xA523FACF, 0xACFA7987, 0xF0E2E124, 0x44EBF8D8, 0xEBFCEADE, 0x642E5399, 0xB9136F11, 0x3BE452F5, 0x8007A3F2, 0xD2B3CB5C, 0x6627F1BB, 0x663DB62A, 0x61A83DF8, 0x0EB2BC42, 0x3E2FBDFF, 0x529C0FA8, 0x0E37E309, 0xC7ADD149, 0xCA83D0D2, 0xD46478D1, 0x280E41F3, 0xC9515589, 0xB5E3637B}, {0x58870877, 0xD3A6C2A4, 0x1ECA5CD3, 0x925CA0D5, 0xA7D0763C, 0x45D16D06, 0x924127D6, 0x7AFED91A, 0x1CFA06F7, 0xC59A9E11, 0x2DADA5EF, 0x50F4A3F1, 0x10256892, 0x126983E6, 0x7EA3A461, 0xBA733099, 0x31567D97, 0x7798DC85, 0x9138D0DE, 0x4C826E3C, 0x1B7AFD84, 0x39E989A0, 0x258BBAD2, 0x919B9453, 0x8B2D8A98, 0x8BA3068D, 0x53F544C0, 0x3631B4B0, 0x0ED8FBFF, 0x58CB4524, 0xA0E452C6, 0x16281413, 0x30E553C5, 0x32A11D45, 0x84DF1015, 0x6B800D2B, 0xF48087B4}, {0x7A24E789, 0x65A88E86, 0x3A872AF5, 0xF8CE8F7C, 0xF9D044FD, 0xE8B474DA, 0x2495012B, 0x06D51F2F, 0x120D9F58, 0xDB2AC8A0, 0x1CE23804, 0xB3370DD7, 0x6BB4410C, 0xCC4199E6, 0x0C45B7A7, 0xD2A77EE1, 0x878C282C, 0x666E4D8C, 0x0A710531, 0x44B48A44, 0x3458945C, 0xD02CEE44, 0x46D0C196, 0xD7D5CF61, 0xB89B4080, 0xA370AF69, 0x65564C82, 0x131B197B, 0xDA58E4E1, 0xEDA59945, 0x4B43CB78, 0xB9084780, 0x806F00C9, 0xD9063E03, 0xA9A26CFC, 0x47982BA5, 0x47C46582}, {0xF8B34C48, 0x29D6D682, 0xE8049DB1, 0xB596973E, 0x047357F1, 0x82856DC0, 0x97210791, 0x52800BE6, 0xDE870640, 0xCEA99DD5, 0xFB31F4DD, 0x549E94B0, 0xD7C6F8CD, 0xDDAF9165, 0xAD9623F2, 0x35397C6E, 0xE3FA49DF, 0x195197EC, 0x203D0ED9, 0x6A18E6C0, 0x31A436CC, 0x232B9408, 0x76C6B064, 0x2993D7AA, 0xE7618E50, 0x62BEA422, 0x7DBDD918, 0xAE0F7241, 0x5915EC0F, 0xB4CEADC5, 0x81C5E39D, 0x8C986044, 0xB965CAC3, 0xFBA4B214, 0x542961AF, 0x38D521C9, 0x5793CF2E}, {0xCA5EF7A9, 0xADF4290D, 0xA9FF841F, 0x47662859, 0xFD5F54A5, 0xE159DA89, 0x233B9B3F, 0xDE7ACD16, 0xC58CAFB0, 0x71EDF824, 0x19EB8852, 0x682E64B4, 0xBAF48F30, 0xC429C9BD, 0x3D76A501, 0x5AF164C1, 0x12373AB6, 0xBBA5B4C8, 0x672B5905, 0x62BA39D5, 0xD849AF94, 0x8C13D1C5, 0x250D39F1, 0x79A0F29D, 0xB24988D6, 0x3CCB5825, 0x4E34F2BC, 0x3DDECA14, 0x56C1727A, 0xD661CA75, 0x65A92E05, 0xBAF6481F, 0x1689311B, 0xEB37D1C8, 0xB7F2992B, 0xF31E925A, 0x216D7238}, {0x6313B4E3, 0x07C875B1, 0xBA76165D, 0xB70F5547, 0xF7C4C3A9, 0xB5253995, 0x7703C523, 0xEF436F91, 0xF9BC6DAB, 0xC0243580, 0xD77BF62B, 0xC3264635, 0x8DCDC1AF, 0xDE4F108B, 0x8CC2E295, 0xBDCEDC68, 0x52CA75D9, 0x975CE27D, 0x40EE466B, 0x7BDF6B56, 0x962AB313, 0x74409B19, 0x181774D4, 0x35F55052, 0x8B8F007B, 0xA25E9ABA, 0xF59A7118, 0xDA9E2C18, 0xDF41EE80, 0x48603A10, 0x62F629C5, 0x6A7513B7, 0x01151E73, 0x3CCCC716, 0x275BACF3, 0x1EEF767D, 0xD5FD94BC}, {0x12C90D32, 0x144E86B7, 0x4CF4ACEF, 0x0804E0E3, 0x507DC67F, 0x462A2AE0, 0xDBC8C2EC, 0x0E7CB0B3, 0x7A794546, 0x724E01EA, 0x7ADAC0C9, 0xE14B57DD, 0x33F9317B, 0xBD780745, 0x618101AF, 0x7C849958, 0x44EAE313, 0x1F916CBD, 0x44B602E9, 0xCD419908, 0x92D62982, 0x076866AA, 0x9C0B81B2, 0xB2ED5462, 0x6785CBB3, 0xB6592909, 0xA284EA61, 0x88872834, 0x725BE6F7, 0x81A47789, 0x3F878EA6, 0x506E0603, 0x071034B3, 0x7A75A1CE, 0x9EA13F87, 0xA562C0AF, 0x2B65AB14}, {0xC8B1DF78, 0x19EBB4DF, 0x655BEB14, 0x1CD47BFC, 0x320D3BD7, 0x7DDEC14A, 0x7CECD374, 0xBBF5FF62, 0x040FCF8D, 0x77F37889, 0xE1223C26, 0x43C9E773, 0x7B4691D2, 0xDA4B53A4, 0x2AC2AA66, 0x6479E22E, 0xDCA8FA0C, 0x4B3D627C, 0x1745AF1D, 0x035B9F22, 0x79C1C86C, 0x4300F4F8, 0x4476D08E, 0x34441892, 0xCCDB434C, 0x09AF5D82, 0xE0096AC7, 0xEA733FD1, 0x5BD50D70, 0x7A0BADE0, 0xE5E545F0, 0xDB1E177E, 0xA0E00F70, 0xA1D1B3D9, 0xE4907571, 0x14E26A89, 0x2718C5F2}, {0xD3D440AE, 0xAA077F2D, 0xB6E49842, 0x99B0716A, 0x30820256, 0xB70BB020, 0x74FFD1AB, 0xA0661A1A, 0xBC59D72A, 0xD781BD62, 0x4C8BAC95, 0xAF44493E, 0x5E4D492D, 0x8E4D5B14, 0xD44742ED, 0xE6549603, 0x3EE732CE, 0xF6BD8C19, 0x0ED76D72, 0xB40B38F4, 0x2720A384, 0x8AC36F70, 0x80851F6B, 0xFA3F7875, 0xE31F7070, 0x6CEC7FBA, 0x0FE5C4A1, 0xBCBEFAE4, 0x53EDF6B3, 0x9AB2D6E2, 0x1413513E, 0x77D7270C, 0x12F56B41, 0xDF168243, 0xB2EC1700, 0x48202EE9, 0x8B538B0D}, {0x7CF6BB0D, 0x576A54C2, 0x001CCACA, 0x49BD2167, 0xEB87E36F, 0xE3147E95, 0x34667F9F, 0x3DD2F9EA, 0x374E77C6, 0xB4FA792C, 0x88A0E977, 0x40253643, 0xE21D5035, 0x72E17F89, 0x041E51F2, 0x4AC1FF84, 0xB6E5DF23, 0x524F2E8C, 0xDD1B0551, 0x27F1C4EC, 0x4A1D995F, 0x223FD2D8, 0xCD2FC1A8, 0x0A0EDF55, 0x054736F8, 0xC2410B69, 0x36701F7B, 0x6FFF8087, 0x62E187FB, 0xCEFDF3DA, 0x01560CBA, 0x0E26F0D0, 0x386482D8, 0x5119162D, 0xB2976C94, 0x9E3A4F2D, 0xF3CAC2F0}, {0x6CD946B5, 0x8C32236B, 0xB77DF4DD, 0xF1018A96, 0x678D46F5, 0xF29A818F, 0x9A32BF58, 0x08DC0188, 0xED8C8C77, 0xFF61817B, 0x23C8FFF3, 0x0676E69C, 0x79E41C5C, 0x3F1DB313, 0xDD15280C, 0x06188152, 0x9BD7F4AD, 0x4EA7B92E, 0x3BD6236D, 0xCA12A5AD, 0xDF9BF84C, 0x7C91445F, 0x0022A88A, 0x15ECBC73, 0x2A33876F, 0xD086B197, 0xF5093A03, 0xEF98B509, 0x09F30FCD, 0xEE776C5B, 0x25E6D73B, 0x093D3559, 0x969AAB95, 0xB26E7A2C, 0x00E84107, 0x82ECED3F, 0x542E9C40}, {0x9AA143F0, 0xB76B2FF3, 0x14582467, 0x4B95D497, 0x5CBD2912, 0xFBCD9A21, 0x309951B0, 0x6E1574D2, 0xF901FAAC, 0x8BE17FC3, 0xFF929BBB, 0x450F0D77, 0x899E0C2E, 0x79AFBD00, 0x51907DB6, 0x0F4BD89D, 0x5D52FE3F, 0xA2134499, 0x79949B4C, 0x77CD1D94, 0x3B3D137C, 0xF194A31C, 0x8C9A330C, 0x0CE859C2, 0x13D9A3EF, 0x22E3C70A, 0xB037C39B, 0x79A822CF, 0x8DA360A0, 0x71ED2690, 0x1B18A8BD, 0xD2667330, 0x655C5133, 0x2D4B38F5, 0xA8212396, 0x930B2473, 0x46A7DF6B}, {0xD3E13862, 0x96AD8A7B, 0xC93B026F, 0x2316A444, 0xE53DCF11, 0x141CFD83, 0x3CFD5FA6, 0xD46A8F76, 0x7BF42BCA, 0xF68AA65E, 0x9B24698E, 0xB2160E20, 0xD634EF29, 0x33726A9F, 0xD70459E9, 0x866E0C29, 0xE0B5B2A4, 0x777B0E34, 0x528C0E21, 0xEFEFE15C, 0xB64510FF, 0x0F2931E8, 0xDA8A8152, 0x0622C5B3, 0xB2466D7E, 0x1731C40C, 0x6066A9CB, 0x192D66FC, 0x3852FEF6, 0x55F7E1FF, 0xDAA995C4, 0xFFFDB3A2, 0xBBDBAC44, 0x1559F5DA, 0xA199FDE7, 0x65095CCE, 0x4CE9505B}, {0xC28B7225, 0x14856E42, 0x4059EEF6, 0x0168BBDF, 0x72A25425, 0x10B7920B, 0xEC13B381, 0xEC285976, 0x56CB9345, 0xA7BED63A, 0x1D6E21B3, 0x44211D3D, 0xF8126934, 0x74EDE685, 0xE48EA508, 0x10D1E5CC, 0xA18BC7CE, 0xFCB04B31, 0x578D4509, 0x714DECD4, 0xD36A17DF, 0x2F911135, 0xF8D3557A, 0x8230671D, 0x08C0B856, 0xE0E699A2, 0xE0436F83, 0x1A4362AC, 0xBB272DA6, 0xE13D2CB5, 0x7A459563, 0x09779CF7, 0x3DF1EA05, 0x32486446, 0xD3BE168B, 0x7F3C83CE, 0x244C7AB6}, {0x55BFC9D9, 0x48BC1867, 0xD55F6149, 0xAD38C7C5, 0xBCC48476, 0xAB8356C7, 0x59047F3D, 0x596983C5, 0xF87458A2, 0xBE0236D7, 0x5B20A311, 0x01E735AA, 0x89A881D5, 0xEA587335, 0xF30989CC, 0xBAAEB91F, 0x5D3FE815, 0x51B1E0A6, 0x5AA03AD9, 0x9FBF0803, 0x17115048, 0x3F0F7EDE, 0x0FFD1FB8, 0x6EE3BCF6, 0x5C235E91, 0x30E37686, 0x28B3FAD5, 0xC0FC5EF2, 0x50E89E68, 0x8D0EB044, 0xA0EE924C, 0xF4B5F98C, 0x5649015B, 0x27ECA424, 0xCE2ED97B, 0xABC7FCAB, 0xA13E4151}, {0x1020CEF6, 0xBD689576, 0x2856C33D, 0xB8459FB0, 0x25905FA1, 0xE5D50F51, 0x0D0613EE, 0x2153B644, 0xD181B86F, 0x8F0CFA68, 0xBE385BCB, 0xA3BA53E2, 0xA974A6B7, 0x2DFA4A34, 0x948FA559, 0x1DFFD943, 0x858A8CB3, 0xB03FD94A, 0x46B47618, 0x64D816B5, 0x38F90501, 0xB94BBDDB, 0xAA9FE4B1, 0xDCDD38E0, 0x55889794, 0x676282E2, 0x157421B1, 0x6AEF205F, 0x47364182, 0x8C90335E, 0x618DC969, 0xB5A7B45B, 0x2926C70E, 0x4FD9CF20, 0x7560AF5B, 0x30C0F4A9, 0xB3C3FE19}, {0xDFEA6F50, 0x2818CBDC, 0x64F0F0C4, 0xA016843D, 0x39A9EC1C, 0xE47945E2, 0xF6EB7E02, 0xE4706B9F, 0x76936CEA, 0x9F12F06E, 0x0D24A2EE, 0x5FFF8F62, 0xDD067681, 0x8D3D966A, 0xCE7B77E4, 0x1BDF6401, 0x77BCFA0B, 0xDD3930DF, 0x66299486, 0x85C4443C, 0x876B786C, 0x5B7830A2, 0x11CEC30B, 0x9EFAFF07, 0x6FFF4684, 0xE9084A98, 0xE65F3EA9, 0xBAD86267, 0x43D31557, 0xBD29D399, 0xBD308156, 0x975BBC74, 0x8A6636CD, 0xCDEF5351, 0x7E222850, 0x874132FA, 0x9667FEEF}, {0xA0F573E9, 0x43F6C249, 0xF8CB1FC2, 0x85D38E5D, 0x5B46CE25, 0x54C6BED4, 0xCE421D59, 0x1BDBEB19, 0x54194712, 0x152CF8F8, 0x50D9DAF0, 0x40A46C30, 0xDC7E24E2, 0x632BC0F5, 0xD888702E, 0x0524D889, 0xEE780C51, 0xF1C8B145, 0x773B7C9D, 0x00D8DF6F, 0x0E7DDC14, 0xE4565037, 0x53CABD97, 0xBE38B7F2, 0xECC554C3, 0xE2E2F61B, 0xB19ADD23, 0x2691870B, 0x6BD53A5E, 0x37971655, 0x630B7BD7, 0xFA2C20E3, 0xFC25D8DA, 0xDFD79A20, 0xF3E1F036, 0x9F47A4EE, 0xB0B2FB61}, {0x5E1DE654, 0xB95F1014, 0x7780B690, 0xD97D7DFE, 0x9A6192C5, 0x57071F56, 0x59B48225, 0x1157782B, 0xBD4CEBFC, 0x944A32F9, 0xF8D1BCDD, 0x1113796F, 0x13B15892, 0x4E960652, 0xB67F8027, 0xFF47AF65, 0x0C1379EF, 0x30D8B7B7, 0xCFC4C878, 0x0D0A2AD6, 0xB4C94DDB, 0x5F382A55, 0x5FC5B7F1, 0xCF01A8D5, 0x61874246, 0xA4EF39C8, 0xB5CD4DEA, 0xEB7D1C45, 0xB49DB456, 0x959388A8, 0xA58790E8, 0xC96B29E9, 0xC9CE2479, 0x3B259620, 0x5D1E7142, 0x5ECA651C, 0x608A597B}, {0x6A4AF458, 0x393C7AED, 0x2980A266, 0x87624706, 0x91D65092, 0xD0B1F145, 0x871EEDF4, 0xC7BD2135, 0xDBFF3DAF, 0x519DBA5E, 0x3FC950DE, 0xFF7B52FF, 0x9FD3B28A, 0x2B0DD9DD, 0x18B79457, 0x623456AB, 0xF1FC67A4, 0x416ED857, 0xE739F8B4, 0x9E693A1E, 0x4A0A9D43, 0xA7750CBC, 0x6EBE7DDE, 0x74EB6372, 0xDB8B1935, 0xF3F0BD18, 0xCFF5FE4A, 0xE44BEF93, 0x3CEC7118, 0x416E0BD5, 0x8ABFFC23, 0xED382F4B, 0xC307B6D9, 0x4C3651A6, 0xBD4F0FAD, 0xB35A93D4, 0xAF111F15}, {0x54DBBE22, 0xF64E8BD8, 0xC1445C83, 0x2BD859C5, 0x4BCBFEC2, 0x1E493E2B, 0x9CCBEBC8, 0xC240352B, 0x4C3B9F2C, 0x4C445523, 0x30A2FEAE, 0x8B274592, 0x75BDD1EE, 0x4C5F9A85, 0x053D17EA, 0xAD67ED4B, 0x6D9A6ABA, 0xF5286BCA, 0x12B45A48, 0x6F393424, 0xE5698639, 0x51B68BAF, 0x121788EA, 0x4CD37059, 0x6E5F3BB5, 0x4810773C, 0x60F24874, 0xC7D864C4, 0x6B9EB4E0, 0x7CE45BA0, 0xBB3ABDB7, 0xC09483B9, 0x0DA2A952, 0xDBB617A2, 0x8AA57D3D, 0xC6D82DB8, 0x205D8E42}, {0x152DADE6, 0xD675E877, 0x8D8C114D, 0x7DF045E6, 0xCE4B4050, 0x87DD732C, 0x2580CDB6, 0xCBCBF5A9, 0x6C6181A0, 0xE9F7867C, 0xE6FB5F69, 0x2676FFFC, 0x902FEDBE, 0xB1234099, 0x26878C9B, 0x98B291EF, 0x83F45B7F, 0x08C51883, 0xC1FF7874, 0xF169BB70, 0x869631E6, 0x8CE026CA, 0x1F234BC6, 0x75F3EC67, 0x10E295C0, 0x8032541A, 0xEC16E7AC, 0x91982EE3, 0xCFB2891B, 0x4EA8A154, 0xDE79AAF5, 0x24885B9F, 0xB284E30A, 0xC162D760, 0x05967BC9, 0x7ABF38BC, 0x171B591F}, {0xA81A654C, 0x1B8A2885, 0xB0900634, 0xEC569F2F, 0xFA0D173B, 0xB276E487, 0x012AAC52, 0x21BEB825, 0x0DD26D7B, 0x1BBFD031, 0xAE387C5A, 0xF20E5653, 0xB6657F21, 0xB323733C, 0xB1956D85, 0xA5115A52, 0x27D422A7, 0xA40A1D3A, 0xCF0BDD34, 0xE796C068, 0x8D78A06B, 0x3B317AF2, 0xB3E86B60, 0x24C8B023, 0x1378CED1, 0xB7EA96D9, 0x3138332C, 0x9E30465B, 0x8B841187, 0x2F5DA4DF, 0xAD22015C, 0xF0ECF1C5, 0x77C84A2C, 0x880035A6, 0xF01E1E54, 0x6505E592, 0xB9BE8AB8}, {0x9DBFB3B8, 0x2279B27E, 0x480F3EA7, 0x2D85BFDA, 0x30682319, 0x6492C674, 0x2D736ABD, 0x3C40681B, 0xE19CF0EF, 0x409B55A8, 0xD040B7BF, 0x494D99BF, 0x5BAAC02A, 0x92A1AAAD, 0xFFC3A440, 0xA067C014, 0x45540DD4, 0x7FD1C560, 0x4983F62A, 0xE11C858D, 0xE42E537B, 0x1224D508, 0xD32A67BD, 0xF4BA1F59, 0x74820E48, 0xCD7B9712, 0x11083EA0, 0xCE3A4020, 0x97AA25B4, 0xD7B4BBAC, 0xA9B346CC, 0x30C47EE9, 0x0AB6F105, 0x912E8E98, 0x05C750FA, 0x8597C472, 0x09DCB75A}, {0xBB031198, 0xB2DADB21, 0x08A5E184, 0xD7BB0AEA, 0xA14D4F1D, 0xAF5F03B2, 0x07109441, 0xC175F8B4, 0xF9EF0A05, 0xD8377F1D, 0xFFE57930, 0xC1BE6C3A, 0x4D450CD1, 0xF2A9E0CD, 0xE8E9BC1B, 0x86404CA8, 0xB3667DF0, 0xB8175350, 0x236C37A1, 0x1B242E2B, 0xA5280698, 0x800B4956, 0x6B26589A, 0x503F1068, 0x9149FCC1, 0x1A1B921A, 0xEF402BC7, 0x726327F8, 0xE84179AE, 0xEAC18012, 0x836C9489, 0xB3FEE097, 0xCC993D39, 0x35A269D4, 0xC7102AB3, 0x5341DBCF, 0xA55CC71B}, {0xE9944ABE, 0x9B51F6BA, 0xA8872BEE, 0xFE88B2BE, 0x43A7AC04, 0x7ED6F4CF, 0xA727DA60, 0xF8681B3D, 0xEB507489, 0xC5951DE5, 0xFEFB92CC, 0x8BEAE2D6, 0xBA4F1C28, 0x2C48F619, 0xA4BA8A8C, 0x710341EC, 0xF75C9120, 0x8B85EA23, 0x718C3B23, 0x23524B50, 0x85DDBFD1, 0x1893977C, 0xC0D871A1, 0x70ADB4E3, 0x4980AA7F, 0x6BC712D8, 0x9E264ABD, 0x8BCB9D16, 0x53D15B3B, 0xACE47468, 0x94B73C97, 0x4731BF6C, 0x291FED9C, 0xEDDDBC4A, 0x642DCCD0, 0xEF5682AE, 0xA1D4A00C}, {0x149705B6, 0x9B86E0CF, 0x01E51FDD, 0xB0CAB317, 0x1CEC9477, 0x00B7D4F6, 0xF6F7105A, 0xC229875D, 0x2A0E8AC1, 0xDC8EA9A1, 0x8187877B, 0x540069CC, 0xD2A6119F, 0x0EFD408E, 0x23489746, 0x84B9F4DB, 0xF530E119, 0x0EAB024F, 0xFB8DC5CD, 0x04004988, 0xF02C684E, 0x2847956F, 0xCF7A078F, 0xA93D7B85, 0x7CB2F899, 0xC882B8DC, 0xEB4050A8, 0x1995109E, 0x75726BE7, 0xF6301DDE, 0x5899873B, 0xAF4602BB, 0xA6E9E17D, 0x011CA231, 0xED257328, 0x73522956, 0xFF307703}, {0x1A22722E, 0x86E35586, 0x09C74027, 0x733C3533, 0xE9CBB096, 0x1A6F14FE, 0x29837C91, 0xB0F81407, 0xF7B053D1, 0xD6E90714, 0x28EC5AF1, 0x31C9BD82, 0x65566546, 0x83DE8BD1, 0x960E02F9, 0x6305CC9E, 0x798627BC, 0x20F65A05, 0x3341B9AE, 0x00D8C52A, 0x28A156DD, 0x216F564D, 0x2B897C8B, 0xAAB3B316, 0x8B160826, 0xCB15C9B9, 0xA1D973BB, 0x2CDD66D4, 0x03FE8222, 0x082B523A, 0x903E3DE7, 0x8CED51ED, 0x278D6284, 0xB70F4D0D, 0x2FF0215F, 0x8324F666, 0xB775560D}, {0x9FBB1F5C, 0x023268F1, 0xB1F35B0F, 0x3CBE6594, 0x20D27239, 0x62634C31, 0xAE1BC45F, 0x5780B3E3, 0x87B9E51E, 0xC8A27A48, 0x886A1E53, 0xB2BFCBEB, 0x1FACB990, 0xEABE010E, 0xA5380A74, 0xC91869AE, 0x75057E52, 0xA946AEE2, 0xC3A93A52, 0x777475F5, 0xB2CBD31C, 0x9F13CB84, 0xB2614852, 0x4DE5E973, 0x831F234D, 0xF33085B2, 0xB87F493F, 0x7A658C19, 0xA1198853, 0x37F77300, 0x295AAEB3, 0xA0901340, 0x8303E7FD, 0xBD916596, 0x060F8612, 0xAD9A6050, 0x8475A778}, {0x20FE87C9, 0x13D1592E, 0x22CE4553, 0xF5D2A2DA, 0x6ACA8331, 0xB963FB92, 0x8C8A4385, 0x45646817, 0xA3922B88, 0x4C3C4C15, 0x2CDF0410, 0x7791BFE3, 0x8DF5EF4D, 0x85CF3FF3, 0xEAF22E29, 0x0DBBD744, 0x1A87C469, 0x4F268786, 0xB3E8370B, 0x75CBDEB6, 0x603B298B, 0x398BA81B, 0x44966028, 0xB9346698, 0xF3CF6DE0, 0x09E50280, 0xCD027A4F, 0x39EFF780, 0xC65FD3C0, 0xCED394E0, 0xFD4F353C, 0x6EE4AC25, 0x81AE2ED6, 0xAD057958, 0x9794F8DE, 0x34F8D3A2, 0x42BA7025}, {0xE10DF81B, 0x78DA3879, 0xE141A1BE, 0xF98FFBE3, 0x9F45E869, 0x99DE2040, 0x55DF0E95, 0x527686FD, 0x9B2219E0, 0x389D4CB0, 0x0615D485, 0x4B42E23A, 0xC7560E98, 0xF7005C57, 0xB1B0E417, 0xB65D74AE, 0xA4C5B30C, 0x5D68FC1F, 0xE4C24E74, 0x8A72EB5C, 0xEE16DB7F, 0xBD005C59, 0xEC5AA7B6, 0x69148304, 0xB395F1DC, 0x9646CDB9, 0xC349362C, 0x3D62E3CC, 0x0CFA458E, 0x03B7F0F3, 0xCA3D1E73, 0xB690FC27, 0x9B8C7E36, 0x5EBE117A, 0xB0C80247, 0x777DD04E, 0x02D5B582}, {0x55FB01B1, 0xA60C90F4, 0xADDDA069, 0x7AA6729D, 0x30FA2AF5, 0x375F4C8A, 0xD2CB2E57, 0x51336659, 0xFAFC94DA, 0x662183CC, 0x2A220CFD, 0x12E28D11, 0x1DD9E71E, 0xF0F72C38, 0xD64A3256, 0x984C29B9, 0xF9FA4CC2, 0x1799BB6C, 0xA4EE5BE7, 0x62F14571, 0x0B7D4E67, 0x2537FA9F, 0x4D429514, 0x36EBD5C3, 0x228BCB03, 0x772B7D7C, 0xDF4AEF46, 0xAD276A9B, 0x200621DB, 0xAD3BCFCD, 0x63877554, 0xD20A3269, 0xB6502B29, 0x9DBAAE88, 0x3E352CC3, 0xA0557AE2, 0xB3794E4C}, {0xBCDF6FF9, 0x82FDDE11, 0x302BB814, 0x5A837560, 0x940A2BE5, 0x8D668B80, 0x0D6084A8, 0xC98492C5, 0x75BA5C68, 0xA55A8659, 0x6B82041E, 0xA1267439, 0x6428C7EE, 0x610FF88D, 0xDF34BF8A, 0x2E9102A3, 0xDBBD6D35, 0x90646016, 0xBE5CB362, 0x8E00E44D, 0x3CB48501, 0xD809D2F7, 0x2144FE74, 0x6C55DE64, 0x695FFEE4, 0xA9A10C69, 0x95125084, 0x038A229A, 0x2AE69CE1, 0xB149BADA, 0x118A5D40, 0xC6C9E5DC, 0x0F37BAE9, 0x5A72C716, 0x5AD980F4, 0xA5603797, 0x65ABAF1D}, {0x2A2F5EE0, 0x4E6F3202, 0x84456AD0, 0x0D7B34E2, 0xE592B4D7, 0x6FEE012C, 0x8F24A63E, 0xA68CEE97, 0x74DCDEA9, 0x26E293F3, 0x22574790, 0xD71E9AFC, 0x4768A5C9, 0xFC0DC4A8, 0xEBC03C2F, 0xF2C34D37, 0xEA4E8E16, 0x0852DCB4, 0xCC4DD35C, 0x17107B88, 0x70242D12, 0xD435D13F, 0x678193B2, 0x08E8D469, 0x9D25A819, 0xC6CBDA13, 0xB9F993E9, 0x458C7F6F, 0xF76FE226, 0x15C817ED, 0x245AF255, 0xE879BEDF, 0xAAA72F2F, 0xD9D58F6C, 0xC5F43731, 0x86C79F88, 0x4AD7D179}, {0x71C8E659, 0xF4898843, 0xCF89C432, 0xB9B71989, 0x581F0E0D, 0xD1618215, 0x922A86CE, 0xFBEF05F0, 0xB716E8BA, 0x6FC89A02, 0x0AFA1CB2, 0x6DCD4434, 0xCDF48DDF, 0xEA22EDE7, 0x8DF93388, 0x05C279ED, 0x876AE483, 0xA9F8F0A6, 0x9A3D4CC9, 0x16AE8F18, 0xAB6E9DBB, 0xEA8D2B42, 0x3CC0169C, 0x767B576A, 0x10E59937, 0x1AEE13A6, 0x5F7A14A3, 0xD71A9901, 0x56636BD8, 0xB4EC7391, 0x836980C5, 0x30995022, 0x53549581, 0xB563283C, 0x9887304B, 0xF227AD57, 0x9CADF482}, {0xE6A3D964, 0xB989C82E, 0x7DFBD74E, 0xFEC4C9D3, 0x6C1BD1F7, 0x0EC84575, 0x34F78B9C, 0x798D0166, 0x1B102A40, 0x03688C95, 0x543E5812, 0x3AE6A363, 0xE21A9546, 0x72086FE6, 0x0C55CE76, 0x0BE2FD89, 0x7C6000B0, 0xC917F9A9, 0x71278D56, 0xCBAEEC53, 0x982E8180, 0x3C428A8E, 0xC9826D37, 0x56317D3B, 0x37641B8F, 0xD515D389, 0xC660F466, 0x30273115, 0x35A35DDA, 0x355FD4E7, 0x8CA77939, 0x263808C9, 0x3F2C5FB9, 0xAA824B33, 0x15BEC70F, 0xEACA78F4, 0xB866678C}, {0xBE39631B, 0xDC0029C3, 0xBEE7B2F0, 0xE8035CCF, 0xB68BE6D1, 0xB9B7F1C1, 0x281851B5, 0x3ABA2C98, 0xB4BEABD2, 0x85D11E5A, 0xE0ABCA08, 0x1C07BF13, 0xCD8AD0F9, 0x886BE581, 0x9A331C21, 0x098BCEEB, 0xB23AC580, 0x939F6B5F, 0x4ABD19F6, 0x632BA5C1, 0xF9D8F978, 0x1CE65E90, 0x287E7CE9, 0xE40F2629, 0x207E0204, 0x0BF80BB8, 0x95066834, 0x3F0DC027, 0x1710865E, 0xFADCF580, 0x3BC5899F, 0x0148F042, 0x4FD09ECB, 0xAE08E78E, 0x5F0DA2B8, 0x80B04691, 0x30731ADD}, {0x95A8E184, 0x984E3774, 0xB5F17E64, 0x30585900, 0x3BB2C27F, 0xB585D053, 0x12B8C399, 0x7107D164, 0x67C95C8C, 0x120A64E0, 0x2FADA4CA, 0x5EA2080F, 0x1BA6ED8F, 0x4A1852C3, 0x28049969, 0x838F8422, 0x773FA6A3, 0x25DD22D3, 0x6BF99E17, 0x661DD59C, 0xFD2E2265, 0x88D8EFB9, 0xAC44BD0C, 0xAB28313F, 0xB5E7F150, 0x0DAD3C08, 0xC2E6E380, 0x77BB3CA2, 0x7E34A58F, 0x488A9222, 0x76AEE784, 0xEEBFD7E5, 0x57676BCF, 0x75243656, 0x6D617D37, 0x1163DD18, 0xAFBCC060}, {0x77E4EF37, 0x9BC73CA0, 0x3E27B28D, 0x8DBAA090, 0x59A321C1, 0xC2B74DDD, 0xD43918E2, 0x43A8F4BB, 0x6950E980, 0xBCD45367, 0x98FB8A75, 0xFF7B5FEF, 0x63A5A515, 0xDD2A4F63, 0x339AD8D9, 0x5EF6954E, 0x20D50381, 0x82D81CD5, 0x41EEF0BE, 0x107539CB, 0xDF39D64E, 0x7E500513, 0x03D41E23, 0xBECD598F, 0x3E311275, 0xC9A82474, 0xBB63EB86, 0xAB83A078, 0xC74284F6, 0xCE5C3CA1, 0x11BACD3A, 0xBB10EB20, 0xB72A6278, 0xC1BB7910, 0x99EFF903, 0x7C1D91D9, 0xA6D1AEDD}, {0xD68B1CDD, 0xDBE65AA5, 0x5BFD3013, 0x6A52C4A8, 0x3CF6AE91, 0x2C8521E2, 0x9C0E742B, 0x1247BE0A, 0x8CDDA2DB, 0xBA04814E, 0x71861F03, 0x157CC265, 0x6A154937, 0x72DCCD63, 0xE0E50A5B, 0x4C8FAA8F, 0x52EDC973, 0x31B56B06, 0x67A6DF5E, 0x2E439197, 0xAF80903A, 0x6F45A28C, 0x5699D608, 0xAC80392C, 0xA27C5FE8, 0x6A0747A7, 0x8A03B6B4, 0xF4619E70, 0xFDA16280, 0x29585F37, 0x7E8359D3, 0xBD886D98, 0x3000A31A, 0xBA96BA0D, 0xA20A6BA7, 0xD57F8EC0, 0x138CCCF0}, {0xD5B6CB91, 0x82B506D9, 0x07FBDE4C, 0x63382250, 0xB47904C1, 0xA73D837A, 0x6593FF1B, 0x1B04625E, 0xFAA2441D, 0x52743F3B, 0x5993A4F2, 0xF2E2AF51, 0xFCF26251, 0xE2A970F8, 0x3068B2DD, 0x2171EB4E, 0xE4EB64C0, 0xFC150B47, 0x65A14F2E, 0x8D1E5D40, 0x743573D9, 0x951FBD1D, 0x5393D468, 0x632922CA, 0xC101E9F6, 0xB66B32C7, 0x127F1A4A, 0x6F5D12FC, 0x58144991, 0x338A513B, 0x8CBA8F78, 0xFD606AAB, 0xFFC39EC1, 0xA283937E, 0x1CE135B4, 0x80320A72, 0x0F872B00}, {0xBA2B66EB, 0xC571A72F, 0x55CA57B2, 0xD8F454E3, 0x17E72B73, 0x281244FA, 0x51E88500, 0x0A60AA8D, 0x0C3ED18A, 0x4DE70F90, 0xEE97F088, 0xE9FD6EAD, 0xEDAE2F10, 0x5D60DF88, 0x5B908F80, 0x59CDB7AB, 0x3254BC47, 0x2EBCB06D, 0x11AC6743, 0x9EECA2AB, 0xFA0D095C, 0xE4628FC9, 0xC3641C86, 0xEB056992, 0x0A1CC4A3, 0x616DF2CD, 0xA10F3132, 0x9A619167, 0xC7FD10BA, 0x1F9437EF, 0xE6BC3B64, 0x0E7CC07D, 0x000797AF, 0xE3B3C82B, 0x1CF3859D, 0x8D8CD8CA, 0x98ED93B3}, {0x031E5197, 0xA752D6C5, 0x24682582, 0xFEFC9CCE, 0x97492147, 0x7D9AACB4, 0xC0BD8A14, 0x93E2B611, 0xE0F9B053, 0x289B34B1, 0xFFDF8A79, 0x5F75ADE7, 0xB3A13473, 0xD34AC7CB, 0x7D4C3B2F, 0xAF199350, 0x85C254F3, 0xFDDEFEED, 0x92BF01B5, 0xF4738727, 0x746E80BC, 0x75AE9A77, 0x94389B62, 0x36B3F199, 0xF7E2BEEC, 0x5962405F, 0xEC3A7CD4, 0x250B7B72, 0xC677528C, 0x3CCD569B, 0x00FB0388, 0x61F11273, 0xE9F7A0A8, 0x9813CD13, 0x57C4502D, 0xEFC4CB10, 0x51A9EBF8}, {0xD7FF9B11, 0x744FCD0A, 0xF527AC9F, 0x05931F42, 0xC1A471A6, 0x5AA593F1, 0x15A3742B, 0xC4FAFCF5, 0xCC93AFA7, 0xC75C6198, 0x7F3BD7ED, 0x141C3B85, 0xCCB34A72, 0x6A25623B, 0x81132A99, 0xC6A65586, 0x31656505, 0x7C630898, 0x7030F582, 0x69F74E3E, 0x9E9976EF, 0xD858BAC2, 0x40A17057, 0xA92B9879, 0x20DD03F8, 0xE83C5201, 0x5E434304, 0x29E0B787, 0xE3A1A90D, 0x643A53E9, 0xB374FCA0, 0x72EF02F1, 0xA4606AFD, 0x4CE5C561, 0x96D005A6, 0x6B19E7E8, 0x5BC1F210}, {0x8DE45E60, 0x138E996A, 0x557B91FD, 0x5A1D1954, 0xA30D7795, 0xF6F57B3B, 0x4E7A1CFF, 0xB729E83D, 0x06419B28, 0x5D9B6268, 0x06B9BFF1, 0xD0289A32, 0x66FCEAC2, 0x36CA984C, 0x2599BC4B, 0xF55A6AF5, 0xB8720CD4, 0xAFF14877, 0xE38C92EE, 0x205B1071, 0xE41A779D, 0x9BC303CF, 0xB35DE416, 0x8C44C606, 0xA2A62B00, 0xC307348E, 0xA030B6C1, 0xDAB10621, 0x95A4CD1B, 0x8A1EEEE9, 0x349296D4, 0xBEA73086, 0xCD4EE813, 0xBADA9E72, 0xE1483653, 0x92DBDAD5, 0x0EB804CD}, {0xCA1E8E1F, 0xEC973A1D, 0x0609F8DD, 0x80D25A35, 0x23A8915D, 0x85F4DA95, 0xF7CEE84C, 0x15F7560A, 0xED4F3353, 0xC095F150, 0x90461656, 0xFD806545, 0xDB0DEC25, 0x81FB306B, 0x1916B13B, 0xC52D632A, 0x4810298A, 0xB14B423D, 0x30BC11C1, 0xB93D69C0, 0xEA8638EC, 0x84A0DBAD, 0x93B507FC, 0x35EF323C, 0x99FF9F6E, 0x926AB176, 0xEB6BCFF1, 0x78BEE4CC, 0x32A8BAE8, 0x08A29566, 0x7CFFAB78, 0x946A59FA, 0xFE953281, 0x8D453F1D, 0x32577972, 0xF20FE794, 0xFD59968E}, {0xAAD94587, 0x6F6ADB0B, 0xCE309287, 0x55C99EF7, 0x72023F25, 0xE45D4412, 0x94206632, 0x6E87D8EB, 0x53DC34EF, 0x67462315, 0xC7030FDF, 0x6BE11570, 0x070B9636, 0x88B14325, 0xD2D5830A, 0xC067831E, 0x46D4852C, 0xB0FCE7F5, 0x5AA0B7E1, 0xDA9AA2A4, 0xDAE36F6C, 0xAD3C6099, 0xD72FA3C7, 0x51C0CC98, 0x6E55929C, 0x6F2CF934, 0x9182DEBA, 0xFBA122C5, 0x631A1CE4, 0xD55F269E, 0x1200239F, 0xD25F4B50, 0x872BDEBD, 0xFDC28608, 0xC06882AE, 0xD0F2361F, 0xDF42C009}, {0xA1E4AE45, 0x4E8D39DC, 0xA2B2B308, 0x834219B3, 0x8DC299BA, 0xE57FEA1C, 0x55F57FA6, 0x59502DF5, 0x6B7BF64B, 0x9D25CF20, 0x4C968F71, 0xE58E0948, 0x9B8350F1, 0xDD003AC1, 0x6B6F66AB, 0xBAFA6841, 0xB15DFE3C, 0x0C8EC81F, 0x86B968F4, 0x9D1BD557, 0xF677DBEE, 0x047964B8, 0x645F330A, 0x9D0D9409, 0x22B857E6, 0x362C0BE1, 0xFD24479F, 0x9F04AE41, 0xA3454545, 0xAD26E466, 0x50529497, 0x166529FF, 0x8A6E4A2E, 0xBFBF1CC6, 0xC1E0FD79, 0xA86235D9, 0x95DF6894}, {0x9785AEF1, 0x70D13941, 0x72740888, 0xA072159F, 0x1C3FE5F8, 0x494F9ADD, 0x4B1111B8, 0x9382346F, 0xFF67B053, 0xE5639A9B, 0xCCA10603, 0x1329A007, 0xF110F1CC, 0xD3325426, 0x50DC2AFF, 0xC5FB1163, 0x61059019, 0x9C47AC21, 0x56887B98, 0x7267F394, 0xED1E039C, 0x0563EC08, 0x733DA614, 0x2A3206A7, 0xB33458D7, 0x5CC11243, 0xFA4F7E97, 0x3C949109, 0x291F68C7, 0x6EE4DE70, 0xA8EFD620, 0x31C30B96, 0x6C9F60D4, 0x0820AC46, 0xE23CB2FA, 0x3F4DF95E, 0xCA0C6477}, {0x04AE4641, 0x2EAAC8E6, 0xA21A2757, 0xEB89E797, 0xEC499B26, 0xDB8BE0BC, 0xF45F503D, 0x920368E0, 0x7D249561, 0x9E9A171A, 0x84DC3A8E, 0xAE99DF3A, 0x434E8599, 0x244D847D, 0x4C7143E3, 0xEF19492F, 0x5DD480D9, 0xEF62386C, 0x6F21D732, 0x4D3815CC, 0x42BF52DA, 0x82666524, 0x958E2C1B, 0x9685B619, 0x3E14D10C, 0x46B7F996, 0x46437CD6, 0x6F6A1994, 0xA27735F6, 0x0CEF03CC, 0xB7E3B27E, 0x2540FA3E, 0x7239032C, 0xC17EABC4, 0x1E676171, 0xD609A948, 0xE193B699}, {0x77E31BF0, 0x02D74F07, 0xAA5997FC, 0xA652A675, 0x3A263F68, 0x4935A819, 0xAE813D17, 0x9743D6C6, 0xD55F370D, 0x3C5BD9BA, 0xD3BFB2AA, 0xE0333F2B, 0xDA23460A, 0x64EAC5D0, 0xD1F60C91, 0x5DAA38F6, 0xFE2698DB, 0x6E0F162E, 0x8B8AC782, 0x67FA4BD3, 0x0A5E239C, 0x2EC299EE, 0x33EC2F1B, 0xFB9D7380, 0x0D06E502, 0x8ACE5CCD, 0xC16CFA42, 0xDA588BE3, 0xD20D0AA5, 0x7A465010, 0xA88FD11C, 0x66E75FBC, 0x617556E7, 0x5BFE7437, 0xB10EB50F, 0x74809232, 0x2988A883}, {0x37A34CE1, 0xD85776FD, 0xD474D839, 0x4D97F895, 0x709BFF5C, 0xF575B91C, 0xA55D19A0, 0x53FEF3CF, 0x5E56571D, 0x088DA979, 0x100F834D, 0x1870C068, 0x47523EBE, 0xEB3976BB, 0x19F2CABB, 0x1C34D9B7, 0xDE95F0A8, 0xB7613A64, 0x3E1728B5, 0xA8EB7C43, 0x1C74FA5C, 0xF9AB6317, 0x93D3DA75, 0x36814DD2, 0x762D8B53, 0x54D386DC, 0xE0742193, 0xA4414406, 0x46505E34, 0x991AE5D2, 0x40EB92DC, 0xAF32E681, 0x3D6A4192, 0x0802E36B, 0x55DBAF9D, 0x11B9BEE1, 0x865C9712}, {0x35FC6D27, 0x8372D70C, 0xF23902E2, 0x1CCF21F1, 0x597643B3, 0xBB69A507, 0x41CA2AA4, 0x6FB2C701, 0x9F0861D1, 0xF33947BE, 0x9228728E, 0x57B46F8A, 0xED298496, 0x0857A65B, 0x8F0DEE19, 0x0D547A0A, 0xA8AEAE6F, 0x9643C874, 0x81443A02, 0x1192CC11, 0xAF714E11, 0x167FC846, 0x23579D4C, 0xEB75DE7F, 0x17F910E3, 0xFBD03FF9, 0x48A8B34E, 0xE2E774A4, 0x70BFB947, 0x6AE8C6BC, 0x368D9AB3, 0xFEE75395, 0x37EDB729, 0x39A67562, 0xFD276142, 0xBA32D7CF, 0xB77D23C5}, {0x5D5B69AA, 0xC6348906, 0xF9F1C026, 0x17C55876, 0xFB2C6B16, 0x5516640A, 0xAACB2482, 0xCF625806, 0x708B273C, 0x8069068E, 0x2A8C61D5, 0x1E07BE12, 0xA711DF1D, 0x833F2D5C, 0x1ED0E475, 0xE4F1E41D, 0x3F70407D, 0x1272296F, 0x8FAC80FF, 0x7851C89D, 0x5C33458A, 0xD54C4CFB, 0x58389725, 0xAA927B5B, 0xB2157D56, 0x46DA2947, 0xC7408D83, 0x5E7FE305, 0xEBD8AF39, 0x55B5758B, 0x86E663F4, 0x5C87ED13, 0x688A6549, 0x54661492, 0x5A521EC1, 0xFA7213DB, 0x4CEE6A43}, {0x4E9945D8, 0xD210AB74, 0x077E15D2, 0x9BA49B84, 0xA3515A82, 0x94655FC9, 0x23294878, 0x236E1CA5, 0x01531E9D, 0x9951A703, 0xD940FB2C, 0x95B48B26, 0xBD70DF91, 0xBDFDCD93, 0x28399A7B, 0xFD279D37, 0xA6483FB2, 0x47D373D4, 0xDF36B400, 0x60056314, 0x952F9FB0, 0x95F3CD51, 0x6359A012, 0x50249DA1, 0xD4F5AF1B, 0xE862ACE0, 0x7D6F80E6, 0x748E5D6D, 0x5DD8737F, 0x25DE3C07, 0x50E45166, 0x52DA0109, 0xDEFF1AE3, 0x103FB79F, 0xE1EDFF8D, 0x88E3A974, 0xE47BFD40}, {0x6CE4825F, 0x48721D73, 0x4B0A2B88, 0x71BAA292, 0xA8254FA3, 0xBE54BAEA, 0xFDDF176D, 0x13B802A2, 0x36F63936, 0x51A803D5, 0xD6A990DB, 0x47745034, 0xF0DDC8A1, 0x7ECF212B, 0xB82EDC2E, 0xA56CC339, 0x2D31B7BC, 0x043B2179, 0xEEB3A6AD, 0x41D5FBA7, 0xAC8AC3C0, 0x3C5161CB, 0x50D45B9D, 0xB76AA4F3, 0x55944F6F, 0x8F0CBCA6, 0x0A3F86AD, 0xAB8D0892, 0x5A601630, 0x72AF6BC1, 0xB28EDED4, 0xA4CDED33, 0x74D77AE7, 0xDA576086, 0x1348306F, 0xBFAE5B05, 0x7D203F02}, {0xFE7296A0, 0xAF7677D3, 0xF3506729, 0x323F5E82, 0x7B8D3650, 0xD319F17C, 0xFDEFA604, 0x2E19A191, 0x314F7C94, 0x00ED0AD5, 0x581A3AE2, 0xA62182A6, 0x5A1D8ED4, 0x60728B4F, 0xB8D0A409, 0xF40771D8, 0xBC743425, 0xE87F584C, 0x230BCAF6, 0xA4CD27BC, 0x9B624B3F, 0x335EFE85, 0x898C6708, 0xD6B41FE0, 0xE57A1CF3, 0x7D8E7865, 0x9933AF2B, 0xB7E5A3E3, 0xD473126D, 0x453E8D29, 0x3553F741, 0xA2D1EC55, 0xAD0FB55B, 0x860760ED, 0xDA8361DD, 0xF10F7069, 0xB7134699}, {0x3AC8473F, 0x567E481E, 0x4973A6C3, 0x7391F93C, 0xB35C0152, 0x9F187C84, 0xBEE910B7, 0x0F3D7FA1, 0x9B789759, 0x379FEE58, 0x838D1817, 0x444C8BA8, 0x3141EEB8, 0x0FFC473C, 0xF8056826, 0xF29F245D, 0x4925E88B, 0x87C5D1B2, 0x07E31DD1, 0x9B521BFE, 0x840ADBFF, 0x4217662F, 0x92BB6545, 0x0D859DEA, 0x84B6C125, 0x496A9B0C, 0xCE7E52F4, 0x37821EA5, 0x6E114C8F, 0x4AFADC1B, 0x3EFB5A3A, 0xEC9C649D, 0x282921A5, 0xCB90D05D, 0x331900D5, 0xD384762D, 0x51C60340}, {0x05A6A9A8, 0xF0921B7F, 0x90FC7748, 0x7072DCB1, 0x715FCD96, 0xFB10DB5B, 0xD78AFD3B, 0x4C6087A6, 0x565729BF, 0x184A8E81, 0xDB54D46A, 0x7E6D03BC, 0x82DA6547, 0x54E32905, 0x98638C14, 0xDC2C3A2F, 0xF4FB2F0C, 0x42FCC515, 0x3F7439DA, 0x3F06AF79, 0x699D0193, 0x32984E2C, 0x4BC7F213, 0xAD49166F, 0x1BF3778B, 0xC1870AF6, 0x59FB593C, 0x0F056271, 0xB09E66A5, 0xCA519618, 0xFAD1484A, 0xD6790857, 0x9D69D1FE, 0x18B87E4C, 0x0710C1A3, 0x99B2EB8E, 0xC85BBD01}, {0x640B2527, 0xAEE3177E, 0x3B2A7E5D, 0x1CA96047, 0xBF57F6B7, 0xA98D87EB, 0x30C95D17, 0x81535D68, 0x91FC9ADE, 0xFAAB623B, 0xB2F5069B, 0x43053C72, 0x4445E536, 0xF88A4E19, 0x7BBEF10E, 0x561C6B74, 0xCC465462, 0xF7CE2A11, 0x5B41E8FF, 0x1ED272F7, 0x518D9306, 0x942C92A3, 0x4F17C875, 0x0799A4A8, 0x7FF141DD, 0x26D7CA82, 0xF8F1E455, 0x9CD4019D, 0x6F6857B5, 0x597AFE8C, 0xE64F862C, 0xC857D0D6, 0x3395E288, 0x570ADF0A, 0xBEA416F4, 0xFC297A67, 0x03C359BE}, {0xFABBA607, 0x8DE6FE3B, 0x19635B3E, 0x905F65EA, 0xDA3B6A06, 0x345944DF, 0x7895B27D, 0xA2C1B783, 0xA6C96B1C, 0x6F33BED8, 0xB0BB6495, 0x7214E4FB, 0x1D9CA72A, 0x35B32E5B, 0x37EFB052, 0xD2DB596C, 0x862DBD87, 0xFB4B9283, 0xDD8062D8, 0x6C350BF4, 0xA7B131F0, 0xC2A19824, 0xCBD85198, 0x8C913509, 0xC5E4666A, 0x7294F15B, 0x1AE03D2C, 0xD0471B3C, 0x2C834A7A, 0x534EB482, 0x26CCB1FC, 0xA2C493CE, 0x26462806, 0xA8C6BA2F, 0x8F8EFC8B, 0x091FD578, 0xE76B152F}, {0xA2153053, 0x331E1674, 0xCD15102F, 0xF403E59C, 0x2C1BBD16, 0x7E688DBC, 0xEAD5AC8D, 0x9E0DC719, 0x8E5952FA, 0x087494E8, 0x3D004BE0, 0xDEF85680, 0xB7C67713, 0x45EF015F, 0xAFFCB312, 0xF0FDAF84, 0x3CB8F3B1, 0xA1687293, 0xF15C90ED, 0x0D5347EE, 0xE2FB21A8, 0x60440FAB, 0x1F6B5D15, 0x1124B85F, 0x10EE3774, 0xFB18E8AE, 0x3E3AB86F, 0x8DC0B504, 0x0CC52922, 0x57EC96D1, 0x467DBE13, 0xB16F8511, 0x1E90564B, 0x4D659DB1, 0x4D8B5559, 0xACE315D7, 0x066E83D7}, {0x984802D5, 0x880EF765, 0xC86C62A4, 0x4D149184, 0xDBDCDBE6, 0xFA25FD75, 0xD99BEDBD, 0x52B2FE5B, 0x4A92E976, 0x66D3F23A, 0x90919986, 0x18A084CE, 0x14FC5E1A, 0x99115594, 0xF3AE4150, 0xA0542257, 0x0C18128C, 0xFAAB30BF, 0x3C1FE2B8, 0xABD2E8EF, 0xFBEAD8B3, 0x91C70F61, 0xF86CEFB5, 0xBF6CDEFD, 0x6CE8A434, 0x69C62876, 0x4DD3B3DD, 0xB0A525C9, 0x9FDD0FB2, 0x9E93B77E, 0x44DA3ACC, 0xA3F9D36E, 0x6AF9D851, 0x180D6192, 0x7E7E169C, 0x74AE2FAF, 0x651E661A}, {0xA38F7D74, 0x09672B86, 0xD801E609, 0x8BD1D538, 0x02453D0E, 0xE43D2B66, 0xE85B1B82, 0x2210895F, 0x2D1E358A, 0x84C39499, 0xC137C965, 0x31F538FC, 0x49C38062, 0xE5F7B263, 0x2B65E37E, 0x6FA685CA, 0x5C6231BF, 0x7DF09031, 0xDC4CE949, 0xF9ED6BAB, 0x5526F0E7, 0xDBCC0779, 0xB1C8A38E, 0xE5449682, 0x2A8BB0D1, 0x94515874, 0x5188D5A3, 0x287B8741, 0x88A015B8, 0x4B23CC72, 0x41E24DF8, 0xA48C82FA, 0x42F540B6, 0x728AA3DE, 0x6CDA023D, 0x31FA1887, 0x68A86EFD}, {0x221E23E3, 0xD9019D7D, 0xD9DA4F9F, 0xFA159929, 0x4E2EC6E9, 0x96E848E4, 0x599D1BBD, 0x6D53E1A1, 0x8A90A63E, 0x14268279, 0xD92F0B38, 0x2D243352, 0x3A88AA5F, 0x88AEB8F3, 0x643037FA, 0x6CECC201, 0x12A1CAA8, 0x06C52D4F, 0xC956784A, 0x924066AC, 0x2B6435DB, 0x9A1C2E47, 0x0B05F4CC, 0x3D2AD9D5, 0xB7A018D0, 0x3D122C9D, 0x47483BD0, 0xBBBCDAC0, 0x182F57B5, 0x02B73F31, 0x9D4B9D56, 0x0707AC31, 0x0B7FE526, 0xB6243F18, 0x3A78E8D1, 0x75C76A63, 0x54703CBA}, {0xB583A5AC, 0xF9E68596, 0xF3D9AC16, 0x13550FCA, 0x37D358BA, 0xC42C75D5, 0xAE169470, 0x79932F36, 0x8FC43E6B, 0xBE81991C, 0x95F1DACC, 0x6F19FDE8, 0xE99786CF, 0xDAB865F3, 0xA8D91C30, 0x8CE7BE1D, 0xE1F2C82A, 0xBBCFEBAE, 0x07973B0A, 0xE34EAECC, 0xAF1DF6EE, 0xFF024AD9, 0xE3400A6F, 0x3157B46A, 0xE307DABD, 0x8E63675C, 0x8459D697, 0x4898D46B, 0xCA9B210F, 0xC2C6D9CD, 0x328B8F0A, 0x7E77BDA5, 0x97E1E91E, 0xB8DB1D24, 0x16AC4269, 0x342536AC, 0x12CF47A1}, {0x40C66BD8, 0xBE8FF639, 0xFE7F6B95, 0x8A231FF1, 0x561DCC90, 0xD39BDCD5, 0xC235D991, 0x9D53A4F8, 0x639B4A87, 0x51715067, 0xC0DD5B98, 0xFDA35981, 0x9FF34AB7, 0x4D2E46F7, 0x3277FC26, 0x8E10F50F, 0x07C1E535, 0xB6D42619, 0x89EA428D, 0x165B3FB0, 0x08258FD9, 0x564091F3, 0xD5716D0C, 0xC2EDEE98, 0x0A45317C, 0x2B9E87FE, 0xFF78D44E, 0x707E514A, 0xC50B0F88, 0x78BFFA56, 0xAF319824, 0x3F31041F, 0xBAC8440C, 0x0EF757EC, 0xBADDDB63, 0xC73500BF, 0x5896D57D}, {0x2110F0F5, 0x33A4F2A1, 0x64C1B419, 0x5EA76769, 0xF97839E1, 0x0B94DD7D, 0x6D6EF85D, 0x4FA87BC5, 0xE48C8C13, 0x3D10C850, 0xFBE56279, 0x5C257F3E, 0xAC352BBA, 0xEB10CB53, 0x4169D04F, 0x96C0B9F5, 0x3280CEA8, 0xC4E3406B, 0x91C6D2AC, 0x4E3DAF19, 0x09DD09C8, 0xF66DDBDD, 0x9C49168E, 0xFE262E86, 0x7C842891, 0x3FBF2C3C, 0x8F92D062, 0x4169BB8C, 0xF9C9666A, 0x11489C25, 0x8F09126E, 0xA7955217, 0x558DC2ED, 0xCCD929F4, 0x478162FD, 0x6DD458C4, 0x06E46F9A}, {0x267E907B, 0xB967E2C6, 0xD9361CC5, 0x4EDB8F7E, 0x717904BA, 0x01D6F356, 0xEDA02D48, 0x492D19D2, 0x0EA61A19, 0xF836FC98, 0x8FF9E574, 0x7227D0AE, 0x10EC1A8C, 0xE700882E, 0x2F485D1E, 0x2D2E4849, 0x8E0566BB, 0x00CDC5B8, 0x7445A207, 0x2EC1ABEF, 0xE7B43E6D, 0x5BF7CFD2, 0x3DB5659C, 0xA91763E7, 0x99A8D5C3, 0x29608C5D, 0x006E9103, 0x1E159167, 0xCAC176E2, 0xAE79217D, 0x5A65E39C, 0x8D07C419, 0xE2DE71FD, 0x71F59736, 0x52032BE2, 0xE7BB97D4, 0x14809E74}, {0x45070BDD, 0x844E4E13, 0x47F0B0C8, 0x07DAD52E, 0xC04DF7A7, 0xF083846F, 0xF6C14CE1, 0xF906A0D0, 0x12581B92, 0x3710AD53, 0x2C31BA4E, 0xF7EF066C, 0xB57192AA, 0xBA9D9333, 0xB0A3C8F9, 0x67DC87BF, 0x431FDFED, 0xA4A8968E, 0x9BBFC898, 0x13439F79, 0x48CF29EF, 0x2DA04139, 0x0DA3BEBA, 0x9208ED36, 0xB06B15A5, 0xA897D064, 0x85199F32, 0x942E28DA, 0x099DFD2C, 0x9556E777, 0xCF1A869C, 0xE4A5D7D0, 0xBF5F919A, 0xF8794304, 0x0A81436C, 0x9446C6AD, 0xBBB67CA0}, {0x3F02A4DC, 0x77F398D5, 0x5CA9E0D5, 0xA8DD3CC9, 0x41FC2887, 0xA7790ECA, 0x584C8248, 0xD7168B5E, 0x62F17C6A, 0x16293D55, 0x98D8FBE0, 0xF6A8A2BB, 0x8673181D, 0x55A40A87, 0x496D9CAC, 0xEE11ABC9, 0xB0D77707, 0x52671EFE, 0xB9F87AD8, 0x834D880D, 0xB06A3691, 0x585169AC, 0x2BB806B4, 0x414E1780, 0x1C2916B4, 0x568E55F7, 0x3BDA42C0, 0xCE92E0A5, 0x480C7D0E, 0xB6B67EAC, 0x690AAC22, 0xC9130908, 0xB104BEA0, 0xAE012092, 0xF698785B, 0x02148E32, 0xB5BF4EBB}, {0x2FE5061A, 0xAAD70FC2, 0x13633F89, 0x94F4B949, 0x4F752D53, 0x0574A2E7, 0xF589AE92, 0xEB6D3F4A, 0x28751B82, 0x87969FA5, 0xDD927192, 0x070DDE93, 0x74025481, 0x6634D33A, 0x8503B221, 0x6D9B8E56, 0x4E74FC3C, 0x1F822737, 0x8908259A, 0xAE01B7D8, 0x4141CC94, 0xBFDC05D0, 0x68336B52, 0x4506D6E5, 0xB9133F0F, 0xBEFB8AF2, 0x833F8FAA, 0xC16EA47F, 0xCDE1DA7B, 0x027D8438, 0x192010D2, 0x2EE7E4E9, 0x75CFE418, 0x09EB064D, 0xB6594544, 0x00487A75, 0xF51D6C91}, {0x837F9C78, 0x062E13F7, 0xB74216E8, 0x5A71DAE8, 0x059AA690, 0xE557038A, 0x50158372, 0xE674CDCF, 0x6334BFC8, 0x6369092B, 0xC0587620, 0xBD0C9D19, 0x1E13F6CC, 0x2F01FB91, 0x59BCC185, 0x860FD042, 0xC1ABFE73, 0x62C29FD3, 0x7CA184D4, 0x7ADC8927, 0xC753D37A, 0xCEEA2CCD, 0x73C631F0, 0x60F65443, 0x49337EDC, 0x8E046764, 0x188B7066, 0x44E41D51, 0x72C3BD05, 0xA36FBE26, 0x8391AF36, 0x7E761A1B, 0x2292C2B4, 0x285B495F, 0xBE5908A4, 0xDD278719, 0x29CA9F70}, {0xF01C567B, 0xF3A54001, 0x701A3DA8, 0x0F5FBDC1, 0x45FCD76F, 0x850536ED, 0x751077C3, 0x3C7D1E57, 0xB3E3BB4E, 0x1ED414BD, 0x0CF9B9B6, 0xDD02DECF, 0x088B7A5A, 0xD2F56540, 0xF7F32438, 0x08CEB7A9, 0xE5EBAD56, 0x6209BCBA, 0x638EB6FC, 0x3A810C39, 0x7B6B9DC1, 0x2D6C87D5, 0x7B149D5D, 0x6703DFE6, 0xF61C1D07, 0x1C3E5997, 0x279DCDD8, 0xB9E78DC3, 0x60B617E3, 0x333C7AA1, 0xA99524C1, 0xB2DE73C5, 0xD5E11F42, 0x33A7816B, 0x4CF186A1, 0xC3C722D6, 0x6D9550C5}, {0xB9AEF79B, 0x0155452B, 0x9DC7CC8F, 0x9057B700, 0x80528B4F, 0xD731656D, 0x72DEA06B, 0xB0FCB7DF, 0x5DC56826, 0xC772296C, 0x90FE3425, 0xE8DD2C4C, 0x08CAB581, 0x4E149D2D, 0xDF1D0EEF, 0xC8DA6AB6, 0x8239452D, 0xBB520C08, 0xD82659B6, 0x78ED101B, 0xBA07698F, 0xBE2801A0, 0xB27909E1, 0xA7B07FF6, 0xAB936A94, 0x14C6B239, 0x8DA6DC13, 0xF552E247, 0x4D0B4359, 0xBBC9BDEE, 0x3F45D604, 0xDDE7D292, 0xC1EA6692, 0x48C0C381, 0x2E711C2B, 0x64235F26, 0x2FCDC4F8}, {0xF51B4F70, 0x157A8BEA, 0xC208EFDA, 0xD2867C25, 0xD3B08736, 0x001F9793, 0xD6070C0A, 0x0F6CA79B, 0xD866A587, 0x256F8506, 0x10847B01, 0x1D439474, 0xE2FEF733, 0xFF38FA7C, 0x41548195, 0xCC2F1864, 0x3E84CB66, 0x912FB755, 0x0C665371, 0x809FC42F, 0x5FD6142C, 0x1C0891A2, 0xC30C2315, 0xB4C6E990, 0xE3716E0E, 0xC4043AFC, 0x5FF81C19, 0xDACCFF0F, 0xFA83E1C8, 0x92038D4C, 0x58572776, 0xE0EB272C, 0xE1FE1B01, 0x4AE38BA7, 0x2E7B876F, 0x4D55BD25, 0x91EAC958}, {0xE04F8D6C, 0x3646750A, 0x9D52E13E, 0xB45CDDB2, 0xDAB38DC0, 0x42387533, 0x111E2570, 0xC70441C3, 0xE3F094F8, 0x65756EAA, 0x91295044, 0xD94D666D, 0xF1427897, 0x2E445D42, 0x43E60447, 0x4DC27224, 0x6AB31C8F, 0xDCB4B7CD, 0xCF1A7CA4, 0x559C680D, 0xB4C402FD, 0xE086084A, 0x4B2A4BBE, 0x2CE47B68, 0x7C28FA36, 0x010D0B0B, 0xEA20ACC9, 0xF2ED977F, 0x6028D172, 0xFC728ACE, 0x85554585, 0x47DBF0B8, 0x4F89022C, 0xB0F9B62F, 0xEE9781D0, 0xCB552CCE, 0xE032C249}, {0x79CD16F9, 0x854A611E, 0xD8250A5E, 0xC1E5A5A5, 0x7888D2B9, 0x7936796A, 0x673B5932, 0xE04D879D, 0x1951ECFD, 0xCBAEEB87, 0xED31B528, 0xE4B380D1, 0xF81E74E7, 0x2FD09F9C, 0x183C1575, 0xC0C5D480, 0x8C2F01C8, 0x969A8AF3, 0x402EAD48, 0x39424AAF, 0x033A8C84, 0x22AEE979, 0x72617515, 0xD8904503, 0x61AAA1CB, 0xEC1A9CE5, 0xC6A94A75, 0x40B32BF1, 0x3AC3AD64, 0x89E43378, 0xF4640E1E, 0x5DE8BEE9, 0x82E24FB8, 0xFD08C6EE, 0x00238A50, 0x73421DF4, 0x46AE8A12}, {0x3E69A909, 0xB7A7DDE6, 0x38F7FD98, 0xDC399BD7, 0x81AF6BE5, 0xA21A5C34, 0x634C7303, 0xDC1A31AF, 0xB1C7F889, 0xA2BF2F43, 0x621A60A9, 0x3D30F0BF, 0xA0126B24, 0x9714F7FE, 0xBD459359, 0x275FFA75, 0xCE20C735, 0x5C16603E, 0x9D212EFD, 0x0AC6399D, 0x4C960FDA, 0x7BE606C2, 0x5973D334, 0x397EDA92, 0xD973B184, 0x386EDF7D, 0x0B40DB6B, 0xAA83D02C, 0x5FEDB174, 0x113133A7, 0x7B43A963, 0x241A2B2E, 0xAB4E5B4E, 0x8158DFEB, 0x8F24BE12, 0xE59897DD, 0xEF93CBA3}, {0x53E48B71, 0x00DD1DCB, 0xE0969EFB, 0x25301CA9, 0x0A533CBA, 0x7E588A09, 0xEB316AA9, 0x0B52A036, 0xBAC2F5AE, 0xECDA52F1, 0x6673FF9B, 0xE039E95A, 0xC643DDF9, 0x5D8538E4, 0xCBF865D6, 0x3551DE84, 0x7A51E6E5, 0xBCBCF18B, 0x015B0E76, 0x94807C5E, 0xEFDBE9BC, 0xE60E7178, 0x9AE40E7E, 0x1E84BC10, 0x6718E7D7, 0x0E136F72, 0xFCC77B44, 0x2E4BF433, 0x7D292864, 0x776B9D41, 0xACAD2F19, 0xD1389A47, 0x8E691F1B, 0x61FE50BF, 0xE61B46B1, 0xD43231E8, 0x4695F372}, {0xC28C1A75, 0xCD9E6AFA, 0xA36EDF5F, 0x614A0367, 0xEFE34CDC, 0x76755F32, 0x0CFF295F, 0x37B56B6A, 0xD0EF22A3, 0xF8DF2171, 0x010C556C, 0xB06B0F76, 0x9A7685CF, 0x5F5534F3, 0x4AAA0487, 0xFCFE632C, 0xCCC3E31E, 0xC5324E1A, 0x7566ECD5, 0x822FE12E, 0x19D53FFD, 0x55B5D8CC, 0x0EEA8855, 0x12EF55C1, 0xD9E20705, 0x4FC83381, 0x50F61379, 0xDAE2A7C6, 0xC4945EFB, 0x9DDB7E9F, 0xD88D9367, 0x7B7905FF, 0x10CE298A, 0x7A549BCA, 0xB7F86D0D, 0xB4822508, 0xF8CB24B7}, {0x9E1ADC78, 0x2884E372, 0x54F85D27, 0x3A4380CF, 0x50B2BD2B, 0xF8C017B1, 0x098D6FFF, 0x5C4E3226, 0x5E4C3922, 0x557CD2FE, 0x490D854C, 0x61C9B0E6, 0x29920280, 0x0A08C7D3, 0x547CD385, 0xAB00EA1E, 0xF5DFDBAC, 0xCC09B215, 0xF9E5597D, 0xB666DA00, 0xE2355B6E, 0xE4F3D35B, 0xDE864228, 0xE0535CDE, 0x123CA186, 0xCA77365E, 0x8279A275, 0xDE365D4B, 0xE7C36736, 0x945F6C27, 0xE4D52B1D, 0x42070322, 0xF1FA9C05, 0x39BBA440, 0x2D66CFD1, 0x0D23B5F9, 0xF47D10B6}, {0x8D89BA53, 0x85EA4347, 0xBC5F27A6, 0x0BBB1463, 0x53DD10A0, 0x2AB26708, 0x140F828A, 0x227AD6AF, 0x76D2644F, 0x9E513D54, 0x32E1851D, 0x06817CDD, 0x8664A2A7, 0x6ADDE963, 0xA27A583D, 0xD5E73FD6, 0x812BE542, 0xB3A4E592, 0x32211DA3, 0xC53FF8BA, 0x62C7D52D, 0x25D8443E, 0x3B16295B, 0x019CA2EF, 0xF4D46117, 0xCB5F1143, 0x4E577405, 0xE727E302, 0x5A716F40, 0x5F02D61E, 0x705E66CE, 0x98448DAA, 0x0208E262, 0x941462E3, 0x93699848, 0x100A5D91, 0xC0CF7392}, {0x98E51D76, 0xBB268773, 0x31D68459, 0xD27B72B7, 0xDE3544AE, 0x9CB29868, 0xFB359269, 0xD3F441E2, 0x4FE14A59, 0x9CBF4EBE, 0xF7E8F1F8, 0x3072ECDF, 0xBFAF4935, 0x23D3589F, 0x2D52C10C, 0xE8823826, 0xAB9B10DE, 0xF69E7D60, 0x0A494C59, 0x91CEFAB5, 0xAD11FA07, 0xA39AEF0C, 0xEDB487ED, 0x18056499, 0xA643FE4F, 0x213F7AAA, 0x0BC5AA76, 0xC046D051, 0x2933FE79, 0xD8A25D93, 0x00AD6C0D, 0xCDE824FD, 0x94E1DB3E, 0xF477DB15, 0xE3A4FBB4, 0xF5CD5438, 0xA43A7F95}, {0x80D8E585, 0xA2242B63, 0x5747A219, 0x58FC1857, 0x9D7701CC, 0x6AABC4AB, 0x02B0FD42, 0x7FF2341A, 0x7464899F, 0xB91A9E41, 0xC6165D05, 0xC3B9D4F8, 0x05A2D7CB, 0x63536E5F, 0xBB015C1B, 0xC91450D4, 0xE1215460, 0x06F74ACA, 0xE740A7F7, 0x0C2CD7BE, 0xEAE93A68, 0x7029902A, 0x94479C20, 0xD6C0E13F, 0xFF2B0C42, 0xB077C7BB, 0xDBF303EC, 0xB263FA3A, 0x09D95D6C, 0x4E892551, 0xD73BE643, 0x3CFA7262, 0x96C3B9E7, 0x75259973, 0x6DEC3BED, 0xA340192F, 0x768D28A6}, {0xC61E7CCD, 0x83A2B467, 0xF00F7A30, 0x1DAB2EE9, 0x248EE246, 0x1D8A0E2C, 0x17881FA7, 0x302F4B5E, 0xE771BB2E, 0x59A5F091, 0x6D029A2D, 0x7C211FFF, 0x95E49092, 0xDA2B3CCE, 0x2D7C60F1, 0xC4B0D77D, 0x58164182, 0x494031F6, 0x65B53032, 0x62AB21E6, 0x86D1EAE5, 0x8C56ED70, 0xEEB19411, 0x2D923D73, 0x448C9DA4, 0x2E5235B6, 0x445EDDFB, 0x55E33BE5, 0x48A2CE92, 0x2B64DA27, 0x171DEB88, 0x648D58EF, 0x9D5509BB, 0x6C28571A, 0x7C3D044A, 0xC88FB99F, 0xDBCDFDB7}, {0x8530E29B, 0x51C36566, 0x8F8EEBFC, 0xC920AB9E, 0x09F3C5F4, 0xD2B55A95, 0x6DC6F9FC, 0x33284F8E, 0x7941FD5C, 0x5B311964, 0x26BC851D, 0xB2DA0FE7, 0x3F53143A, 0x14269D46, 0xEBE73C6E, 0x0B3E5F89, 0xE90B9DFB, 0xFD201343, 0x5DFE2231, 0x31F44B04, 0x974739B5, 0xE64072A8, 0x9942400C, 0xE4426ED3, 0xF0C5EFC5, 0x5E827273, 0xDDCF2B1A, 0x12830ACC, 0xBBAA4B50, 0xAD5FF7ED, 0x2E1CBCD8, 0xDEE4DA5A, 0x98F54CAA, 0xAE01D6E6, 0xCBD3CBEE, 0xF79DF834, 0x661340F4}, {0x69A6D127, 0x2AFCFE62, 0xF58EFD93, 0x56B14DDB, 0xA86CC22C, 0x6B563AE1, 0x5302944D, 0x33B4BE65, 0x8D9835DA, 0x48E8D973, 0xBC313962, 0xF06057C0, 0x643E71DD, 0x59EB908D, 0x64F123DD, 0xC0CAA67F, 0x16FC58D3, 0x4A30D556, 0xA34997E6, 0x092348A6, 0x6EEB1B6E, 0xFBDF96E6, 0xC24B4D9A, 0x42DA09B9, 0xE899C1F2, 0xB20D988B, 0x169AEB29, 0x15EB0E98, 0x779EA79B, 0xD4ADCB1B, 0x03CB9537, 0x6AE929C2, 0x0D89F9C0, 0x1B85B948, 0x4543334F, 0x6FF8E1EE, 0xB8330188}, {0x7427052A, 0x79F760EF, 0x54CB3D37, 0x27DACA7A, 0xB5DC2ADB, 0xFE4EB5B5, 0x32A4081D, 0x7B39DAFD, 0x30CB4C7A, 0xDB036A8C, 0x0E765D34, 0x053D3422, 0x9F0B8404, 0x73B8D39B, 0x8EF77E0E, 0xB5F145EC, 0xE00CA0CE, 0xF7F1120C, 0x45AFA4FE, 0x872E6545, 0xABF8D9C5, 0x4C8A253C, 0x933FC365, 0x85DF7694, 0xE372AD8F, 0x218E80AC, 0x845E56BA, 0x5634716F, 0x5C7AE834, 0x05CC8BA4, 0x4F1E491F, 0x0B742F6B, 0xCAA48663, 0xF7185A6B, 0xCB4A975C, 0x2D323250, 0x63315415}, {0x572B975B, 0x16F47525, 0xA0470A2A, 0x5CEBF471, 0x1055873B, 0x389995C9, 0x592EE10B, 0xBFC4A4B4, 0x673EDB8A, 0xD6890A67, 0xA33771C3, 0x9FB6D0B8, 0x1FA70E5E, 0x0F26EEFB, 0x1A641DED, 0x32D96D70, 0x1FCE400A, 0x41AA7952, 0x7EFD4EA5, 0xBB6F1FF3, 0xFD773644, 0xDFDC53E3, 0x8A00327B, 0x157D3AF8, 0x07DADA40, 0x4147D482, 0xD7D36E6C, 0xA63110AD, 0xA839CE60, 0x5110C355, 0x5E7A42E0, 0x6C324D06, 0x9135E247, 0x3AE10B3A, 0x85DEBFCE, 0x9D7AFDBC, 0x4FCB4661}, {0x079B1127, 0x4D24C131, 0x8AF6FF6E, 0xF3B29BF5, 0x9A44A289, 0xCE1F8DCC, 0x0E0CD025, 0x35646A36, 0xCE8583DD, 0x3AA163E2, 0xE9C3D218, 0xD4A3216F, 0x603A5E0C, 0x6E66CE40, 0xCE006D79, 0xE25EB57C, 0xE7F62AE0, 0x0D5CD5B8, 0x46E72D87, 0x16B903AD, 0xEF215AED, 0x86D77253, 0x31716973, 0x4B015FD2, 0x6B1BBCEF, 0xFAA745C3, 0x29572222, 0x149ADB60, 0x06DC7868, 0x1D7A1BE4, 0x42F71B55, 0xDAA5303A, 0x2AB35EAE, 0xDD578B3C, 0x2EDA300E, 0x8A809E9A, 0xB12809BF}, {0x1F94523F, 0x40EE4196, 0xCC1FEF2A, 0x6DAD0FE9, 0xEC8F2F9C, 0xE1F47258, 0x8234024C, 0x8494AF00, 0x5F06BD30, 0xC966A83F, 0x5F965E14, 0xC72B5B01, 0x89AE8118, 0x43515D9C, 0x7C0D7C69, 0xEC71E0A0, 0xB204284D, 0xF2437DD3, 0xF9021504, 0xA8D29CD7, 0x5D33FC9D, 0x310761EF, 0x70149CF7, 0x30CDB896, 0x9074CB73, 0x9FD9793E, 0x86291B7C, 0x0A9D67E5, 0x6C6C6410, 0x1B63143C, 0xD8EEA9F2, 0xB7BF1074, 0x21D4040B, 0x331BB797, 0x8AEA22B9, 0x399A0041, 0xC5253CF4}, {0x775F9E49, 0x610C2997, 0xD89F5D87, 0x12D60B08, 0xA2B77D05, 0x595D63ED, 0x97232D62, 0x14387C50, 0x06D0AC1E, 0x6CFCB913, 0x553A9CAC, 0x2B5A5C53, 0x5976BB27, 0x6420F3C2, 0x75A2AF6E, 0xD60DD93A, 0xEF2D6AB0, 0xFF6D5F5B, 0x0614E0AE, 0x12C1945F, 0x10EA4EB8, 0x6BA6491A, 0x9FFBB2CC, 0x0B68E70A, 0xAA22DE93, 0x6EF6CFBD, 0xD6BF400C, 0x673EDFE9, 0xCE5FE3FE, 0x40013F16, 0x95BE70F0, 0xD9783744, 0x95BDDEF4, 0x7BE7E522, 0xAEA8F7F3, 0x1A29E609, 0x223F06EC}, {0xB6F396DE, 0x7ADE9C5D, 0xDAEAC722, 0x9DBE635E, 0x8932C951, 0xCBCB26A5, 0xC311628E, 0xC16CF204, 0xACD48D8F, 0xF638CEDD, 0xAD1A7BC7, 0x7D002FA0, 0x19325A49, 0x47901639, 0xEA4ACD84, 0xA6638DCA, 0xB337B7FE, 0x9D31DB37, 0xE59D6E72, 0x146BE4D3, 0xD94372C5, 0xD4E34170, 0xD3DB2215, 0x3F7E49B3, 0xB2888CB4, 0x9E9BD7E5, 0xE33BD59C, 0x9A51C244, 0x1A6FCF42, 0xBA05E71E, 0x665EA467, 0x380D3A7E, 0xB2DCFD9A, 0x66834EA0, 0x0F65CB5B, 0x60D749A0, 0x12B1C14A}, {0x69246CC6, 0x1421E3C3, 0x4F4AD5CB, 0x237C04A8, 0xF9F0D0DC, 0x030797AD, 0xAE0F3148, 0x1AE7F307, 0x297C1CDC, 0xBE4ECB0C, 0x43874E3B, 0x77E0F13C, 0x63BF1C43, 0x41994798, 0x7975FC4A, 0x798ADB3C, 0x01D4AF7F, 0xD5DA05A8, 0x0F0A924F, 0xB30263CF, 0x5CDCB9E5, 0xC5DF7D65, 0x6F44001E, 0x6C8D1A6E, 0x384016E1, 0x276C3EC2, 0xEE90E8D1, 0xF0A5AB45, 0xA994E23C, 0x6F72991D, 0xAB4A8723, 0x79B456F8, 0xF3235BD3, 0xF743DFCA, 0x53C641E1, 0x7ADA4240, 0xF72177BF}, {0x7451D784, 0x18D318D5, 0x87A1DF65, 0xF87EEE6B, 0x399FF741, 0xA24FEBED, 0x610AE096, 0xA58D1070, 0x9742FCEA, 0x539E62DC, 0x90528258, 0x63B5907D, 0x13FD9BB7, 0x25E19480, 0x0D959C47, 0xCCF4050E, 0xD211B9A6, 0x022B5FB3, 0x983B358B, 0xB8CD1D91, 0x309C7F5A, 0xA453EC62, 0xDDC8E6B3, 0x11BA247C, 0xA6C741EB, 0x5F579501, 0x725C634A, 0x2AF323F9, 0x7A3D090E, 0xA03B28CE, 0xEFF9370C, 0xBABDC3DA, 0x221FE410, 0xB524D45C, 0x05B9B0D9, 0x9ED276F2, 0x99CB125B}, {0x9184D5B1, 0xAE6990B3, 0x09FE6157, 0x6538AC90, 0x3466E51C, 0x411991ED, 0xF4ECB478, 0x754DC5B9, 0x96E63734, 0xADA6EAED, 0x5A333CDE, 0xDC8CEBDF, 0xEA4AE3B4, 0x6B034956, 0xBB1CFB44, 0x7BA35112, 0x4123592F, 0x51233293, 0xDBC20C36, 0xB54D6F5C, 0xB2776A57, 0x31BB48DC, 0xE7A57D46, 0xD1467D89, 0xAD5244BD, 0xE8FA9AD9, 0xFA6AA917, 0x4564E9BC, 0x0DD02FD2, 0x3920DC1B, 0x62D3423E, 0xD846080C, 0x626007BF, 0x54FC6558, 0x973D504E, 0x1999C0B5, 0x985A8EB0}, {0xF437F9CD, 0xDF20F179, 0x05453F2D, 0xE86FB803, 0x2A8CD496, 0x5290BFFB, 0xE4993D5C, 0xB398DFB7, 0xE25E4456, 0x6D3D0A29, 0x3AD2DDA7, 0x6197079D, 0x37F35C9A, 0x02DF13F5, 0x5D2A054F, 0xD908948F, 0x4D1B49EF, 0xD96856EC, 0x2F38E1C7, 0x2847CA82, 0x10475AEF, 0xB36B3FD7, 0xBE0BAA2C, 0x7D4611D3, 0xDA76E37C, 0xD5CA94D1, 0xFCEA9AAB, 0xB0763FC6, 0x7C230A0B, 0x0B8A20A0, 0x0F189C69, 0xA57CF84A, 0xA87C6B06, 0xADC43164, 0x742D5882, 0x03C62337, 0xC0AA0528}, {0xCCAF1C0A, 0xD3E25622, 0xCD10D341, 0x15FA73C9, 0x1294AF47, 0xAC227E12, 0x59C33FDF, 0x83ACB129, 0x3BEB3407, 0x89379EF9, 0xAD56EC26, 0x4230AB6A, 0x35B36957, 0x0320C9DA, 0x77C7BE15, 0x90085500, 0x432A38C8, 0x960563D4, 0xA0744D3D, 0x4984A7E5, 0xF31AD010, 0x0108789C, 0x8F6B3E08, 0x7BEA35B7, 0xAC369B64, 0xDD1E5B26, 0xAC357C7E, 0x2E92F104, 0xF9BC2499, 0x2E00F57E, 0xB7DF5AAD, 0xBEE86455, 0x45BE7F96, 0x9FF01B1B, 0xF5BEEFF3, 0x17952278, 0xEF1C3893}, {0xA131BE6B, 0x04D37455, 0xED3D8FDF, 0x4CB17D2B, 0xC218B582, 0xD29E0E8D, 0x2E786AE5, 0xF36FBD70, 0x384154F1, 0x93D5D548, 0xFB6E1DDF, 0x0E0F5184, 0x4848F1DE, 0x7A9346FB, 0xC0F3B940, 0x8109275A, 0x2E97E643, 0xAAF0EAA8, 0x872821B8, 0xE102D09B, 0xB19733F8, 0x702F4DA2, 0x98BCA0AA, 0x81DC2392, 0x3FE91C23, 0x24C4EB3D, 0xF2C6B4CF, 0x3510EA6B, 0x1847174E, 0x67C9EA78, 0xB1046EA7, 0x03ACB007, 0xD811D8C6, 0xCF3E0C2A, 0xCA280A4E, 0x24995C8D, 0x855CBD89}, {0x90C8BDB6, 0xA34A1094, 0x11D43443, 0xDA192944, 0x76FF83A2, 0xBA0D9485, 0xD5801790, 0x30FC2D2B, 0x4035D04E, 0x7B0219B7, 0xF89036FA, 0x7C317FCF, 0xAB22C4BF, 0xFEED3EE1, 0x512AAAD8, 0x526B3E8C, 0x5A20E80D, 0x3B4314C3, 0x34C1C2B3, 0x841FEB6A, 0x65BA0E16, 0x2F3DBEE8, 0xD49E3699, 0xCEEBA4C3, 0x51B77A62, 0x748E420F, 0x96C7F281, 0x60600CA9, 0x232BBF22, 0x7654B7C5, 0x11F45BC5, 0x99F89998, 0xACCFA29F, 0x36D9D53B, 0xF8BB2738, 0xBE6404DB, 0x0DCBE4E3}, {0xB940E21C, 0x7C02ACC8, 0xF522292A, 0xB2E96260, 0x5691731A, 0x89FDAB2C, 0xDB8DD0D9, 0x7A29518E, 0x02D9E550, 0x5D95E2C5, 0x91FB6225, 0x8CD1E5C8, 0xB7BCCDD9, 0x917E8CA4, 0x6FDF062E, 0x29A8AC07, 0xF81C28E1, 0xF3BDB95C, 0x6B4E329B, 0xDBC18A31, 0x6E6A7F3C, 0x47C079CB, 0xAE72373D, 0x4920D95C, 0x5626ACFB, 0xAD52C44A, 0xBEE4DAD9, 0xC2EA88DA, 0xFD4CFF9B, 0xEAF4CB98, 0x8E0C0F3C, 0x721E5EA7, 0x40485D4F, 0xE2A4625E, 0xCC0D0437, 0xC5B23A7B, 0xD7B6012F}, {0x3992B53D, 0xC7289CDA, 0x2B251944, 0x90B4B90A, 0xBB2D6B04, 0xD2DEE748, 0xFAD9D19A, 0x8CB129DA, 0x5A89E453, 0xC9272659, 0x92241CF8, 0xA60563FE, 0xF3B31E62, 0x61E37986, 0x5774AF4A, 0xB456FC85, 0xB2010731, 0x8B257545, 0x18E9DA09, 0x33EC0A71, 0x6495AA09, 0x19D0DD24, 0x223347ED, 0x4F7418EF, 0xB2FE109A, 0xEFE2CC4A, 0x46635A90, 0xB1E6E4B9, 0x2C0B0CD7, 0x2CDC00D7, 0xCF0325BC, 0x8D8EA776, 0xD5CF7D13, 0xF73D0C53, 0x08356C1A, 0xB666927E, 0xA1A2D320}, {0xF1676F1D, 0x0384B46D, 0x039EF62A, 0x20A56EFC, 0x08CA70B7, 0x3DC3F9C0, 0xB71DF1F0, 0x2CBE2F34, 0xABD5C8C4, 0xF51C86F3, 0x0C0B3648, 0x6484608F, 0x529DAFA3, 0xA325C293, 0xADABC4DA, 0x447E1CB8, 0x599F87C0, 0xA296C9C4, 0xDC71CDAA, 0xA3A7E1C0, 0xAC307A3A, 0x0472662A, 0x269E60CE, 0xFB062D02, 0xD3891B9A, 0xEE01C9AE, 0x38C638F6, 0xD48A8D9A, 0x81EDB4D6, 0x66D0728A, 0x799286AD, 0x96A4AAAF, 0xE6087B80, 0xDF9A5851, 0xB2F519CC, 0xCFBC56CC, 0xD98C07FE}, {0xF2110AC7, 0xE674EF39, 0x11E05ED1, 0x18E0A6F7, 0x84D48750, 0x7250A73F, 0x9799A488, 0x5CD2D94B, 0xC9541CAC, 0xD8B7F874, 0xED66BA86, 0x93B8EBA6, 0x9216BC10, 0x18F62CC0, 0x4769B4C7, 0x8D864A52, 0x91A5B304, 0xC8E79F3D, 0x8A11769E, 0xF94B27CA, 0x6A00A478, 0xEFDF65D7, 0x5031677B, 0x458684CE, 0xB1CA0C1E, 0x6411A339, 0xBF2B831E, 0x3F7B1EDC, 0xF74FE18A, 0xA34D53EA, 0xBB261E3E, 0x6C772D66, 0x5C60F986, 0x62202131, 0x260E1D22, 0x03DA2CF1, 0x668666C8}, {0x7EF6DD43, 0x715F6B57, 0x3371014C, 0xBA3237EB, 0xE10CC0B0, 0x0CC59E77, 0xA5B3EF0F, 0xE2D01757, 0xD8245C53, 0xFEFD7C94, 0xE3B3C81A, 0x77E44729, 0xF0ABE12C, 0xE03F3D72, 0xDCD8B489, 0x0438FA90, 0x12F7298D, 0x43ED88A5, 0x3942EF5F, 0xED4913A3, 0x0FCE1B14, 0x7FA9AD22, 0xB0DE3238, 0x303C6A0C, 0x8FD9A158, 0xC62BFF7D, 0x065E4EBE, 0x404D7302, 0x91F9B4F6, 0x2B7EBDF3, 0x318B5922, 0xCFC788FA, 0x185344EA, 0xFE19F20F, 0xAC1CF775, 0xE7C62117, 0x9D6604BF}, {0x9CBE1B12, 0xE6294FFD, 0xBB3E8C70, 0x48C654AE, 0x5C0977B1, 0xF92CA674, 0x626113F5, 0x4B2149C7, 0xE5B10CDD, 0x3FDE0C76, 0x8897724F, 0x321F032C, 0x75BB5617, 0x414735FC, 0xD2BAF17B, 0x25727DB2, 0x95D05717, 0xCCFD35C0, 0xD15DCA48, 0x8719EDF7, 0x4BE7B2D3, 0x9D08E019, 0x36707AB7, 0x70EB2AA5, 0x9CE6F85E, 0x965E540A, 0x74E7BE83, 0x45904731, 0x51F86D86, 0xCB7E6F2C, 0x5F0967EF, 0x7D150DBC, 0x04DB2A81, 0xD5660FF7, 0x2B65C6B1, 0x2079D22F, 0x8081B43F}, {0x3BCB1D9D, 0x9B41B4BA, 0xE264204A, 0xBA8EC0F2, 0x9E29734E, 0x8EA21EFE, 0xAFE8723E, 0xC89E8189, 0xA14FC1AB, 0xAAD1CD2F, 0xE40793C2, 0xA8044BD4, 0xF227DD86, 0xA3A7E772, 0x2397F4AE, 0xCC72647A, 0x60436135, 0x075CB43C, 0x28B25CDA, 0xD034C5CE, 0xBD665B60, 0xE7717A62, 0x7F8D16A2, 0xEB68A53F, 0x1A86148D, 0xCFAC4021, 0x8B65220C, 0xF6C7BC7B, 0x1C316E8D, 0xDA0493E7, 0x57628938, 0x7CA0B3CF, 0x36A7DFC2, 0xEDF1B1C6, 0x7E660268, 0x8A133BFF, 0x7D2BA431}, {0xAD495822, 0xF035F3D9, 0x7757AA36, 0xB1E214DB, 0xEE1D0E5F, 0x897CC5E9, 0xD269772F, 0xF985866F, 0xD6EC06F0, 0x64719CF7, 0x0ED33D98, 0xF031A97C, 0xBE79EEF1, 0x1A0DB802, 0x4F8D8158, 0xBB802376, 0x6E1E72C1, 0x91AEAC95, 0x92FD26D5, 0x6071D050, 0xA13BCBC9, 0x1E70CD33, 0xC2EBAE0D, 0x88FEE85E, 0x20526ECD, 0xDCC0C3EE, 0xAF184541, 0x5BB9CAB7, 0x2772EED0, 0x6495AAB2, 0xE670B18A, 0x8A9A9156, 0x61C26648, 0x7D574169, 0x343D2BBB, 0x957E9C54, 0x53C3836B}, {0xFC111846, 0xBFD560EB, 0xEE9F8CD7, 0xEFEE20F5, 0xBB7584C9, 0x157E4079, 0x90DB0965, 0x47DB79B2, 0xA6EEB0E6, 0x696CF73C, 0xE7492B42, 0x69A3BBCB, 0x9A4AABCF, 0x07932D52, 0xF70DBDEC, 0xC1254B48, 0x14CBB77D, 0xAFBC3EB8, 0x24D6C7ED, 0xD9081975, 0xF3C1EC1F, 0xA0096AF5, 0x83713A88, 0xF5811E30, 0xB6A4C568, 0x0A59151C, 0x2AAF11E9, 0x9E2EBFD4, 0x7B276F0A, 0x17FED9CC, 0x04C69704, 0xF31CD56A, 0xBA0F3949, 0x3A1E061C, 0xBD598149, 0xBF76D75F, 0xA38E5926}, {0x2A7A9254, 0xE2E5ABAF, 0x30E23420, 0x894A3DED, 0x4A4C4965, 0xE45FAEB3, 0xBD94747E, 0xA23447C4, 0xAFB7CDF4, 0xB856E7B4, 0x2B69428B, 0x72B446F8, 0xE4DCDA76, 0x5AA0ECE9, 0x36DC757C, 0x3A82C2DF, 0x5FCB6229, 0x6D5996ED, 0xB8368BE7, 0x697FE838, 0xD8BDEC25, 0x6E7EC630, 0x69AAC756, 0x0F727C23, 0x671252B9, 0x32CDA6F7, 0x9F2FF941, 0x1DA6498B, 0xC5783B45, 0xED207B82, 0x168E4265, 0xC9D62D31, 0x7BC9A0D5, 0x56EA875B, 0x9C8A4D66, 0xD5F00849, 0x3F38BA19}, {0xD628591A, 0xBFF9AEED, 0x308F087F, 0x66D66E55, 0x666FA65F, 0x59FC30EF, 0xBFC2D69F, 0x0F7B136D, 0x5985189D, 0x2A8CD4D1, 0x5C8088BF, 0xD8F0525A, 0xAE0A8972, 0x78704DE4, 0xEEE46972, 0x19C3A8FF, 0x1727286C, 0x9C3AED51, 0x1079B161, 0x99614F04, 0x3EC31B57, 0x4354210C, 0x583544F9, 0x1CC8C5FA, 0xB704D274, 0x64147580, 0x5F3D9CA5, 0x21BD3590, 0x17D2536C, 0x77C72C05, 0x47D4E782, 0x512CE9BD, 0x539E4D3C, 0xB932E0DB, 0x1EEDEDF2, 0xC60FDEC5, 0xA141A4C1}, {0x0EFD8B69, 0xBB7D1832, 0x40CE93EF, 0x0CAAF48D, 0x2B888E46, 0xA392042E, 0xF7802A3C, 0x8BDD0DBF, 0xC11BD12B, 0xC53C4C47, 0xDBDFAD37, 0x54B20285, 0x5D84EA3F, 0xBEA5F97A, 0x7449F045, 0x02DECA11, 0xB4EAFCB7, 0x48F75125, 0x33494243, 0x915997CE, 0xA4A3C86F, 0x87942D1C, 0x68814271, 0xF1B8DBC0, 0x37789DC1, 0xFB6D02D4, 0x3ECC20C8, 0x375F5D6C, 0xAC844756, 0xC622AF54, 0x4083A75F, 0xF60F10A2, 0xA0ECDD35, 0x7E915018, 0xCC0BA920, 0x596B0237, 0x7E208D1A}, {0x3FD7CB00, 0x12FFCB64, 0x8A460E2E, 0x29E42524, 0x368396CE, 0x6489E25B, 0x8924B43D, 0x8796D41D, 0xA35D9186, 0xC7C36207, 0xB607F970, 0xC1FB9734, 0x1A5C4401, 0xAF24D106, 0xC34B8D9B, 0x1439CC3A, 0xDB482FC8, 0xF9E785E6, 0x5DADF604, 0xE05862B4, 0xC0A0AE34, 0xFB3C8990, 0x7765A1DF, 0x6F3D618E, 0x1D1149C1, 0xECC2A459, 0xB78A55F8, 0x2D6F3575, 0x02E2A241, 0x1B26E51E, 0xA1975E02, 0x2905E84C, 0x79022D04, 0xDA5C630E, 0xD0D5F648, 0xF239A92E, 0x97466814}, {0xEE9D3520, 0xBAB69353, 0xA50A1A1F, 0x5ACEE1A8, 0xB050A106, 0x8266A03A, 0xBE0AE7C5, 0xEC73BAE9, 0x32804617, 0xA1FCFA6A, 0x8C67E7CC, 0xB80C39B6, 0x2DF53DF0, 0x82BC21AE, 0xFA0E8840, 0x40890F69, 0x57E65720, 0x58FEAE37, 0xC414C240, 0x88180834, 0xD37EA0FB, 0x314825E6, 0xD8A436B6, 0x4438B74E, 0x98E651FA, 0x372190C1, 0x081CFD49, 0xF45A1D56, 0x649902D0, 0x360296A9, 0x206D9A0F, 0x94646528, 0xA19D3701, 0x4E34A944, 0x91182CB0, 0x7809D5EB, 0x46A1B067}, {0xB0FEF4FB, 0xB4513961, 0xBBCB86CB, 0x2E3BF8D0, 0x4E812154, 0x1F5DCE5D, 0x49DA4187, 0x07CA12A8, 0x303E7C7A, 0x37779F7C, 0x9794BA65, 0xF4A50052, 0x0A3B2B8E, 0xF6F69F5A, 0x349D25A6, 0x2F084B70, 0x596F4297, 0x435D2DA7, 0xC5812342, 0x4E0B6CAC, 0x78062509, 0xD0491DF1, 0x5A7C6E0D, 0x9FC45C7D, 0x10F6F9A6, 0x5A3CA7B8, 0xC60C5A41, 0x437AD272, 0xA00E2A35, 0xC91C8E2D, 0x79F48275, 0xDF434825, 0xE4766899, 0xDFCC9BC5, 0x4C64ADD5, 0xD6D946F7, 0x5483FDFB}, {0x5DFCE4F4, 0xB3BC0E39, 0xD5686328, 0x88CC7C42, 0x1A90C59B, 0x79D42AB0, 0x56847A79, 0x002B3195, 0x382745FE, 0xC36F0857, 0xC91BE201, 0xD0B64C5F, 0xFFB8655B, 0xDF99494A, 0x61B9B984, 0x18E7DA96, 0x89E35296, 0xDFA6475F, 0xB74528D4, 0x32FF0EFC, 0xC0774F71, 0xED686E51, 0xB865CE5D, 0xDC34163B, 0x05F155EA, 0x9B1697F4, 0x03DD27C1, 0x57D66706, 0xA9B3245D, 0xDB20A949, 0x2AF9A49F, 0xAA21B848, 0xD9C87BAC, 0x3F6DEFEC, 0x508EB539, 0x5E9D979B, 0x31C7DBFB}, {0xDC18222D, 0xFA7DE485, 0x4E6516FD, 0xB19C1246, 0x29951E62, 0xD42CA1AC, 0x0F21CF76, 0x2D040D67, 0x56EF3F4B, 0x6B101B07, 0xF98BFA0A, 0x88C94E5D, 0xB35DB34E, 0x9E8E3721, 0xFA3D959C, 0xAB98D7C1, 0xBC4AE2A8, 0x2A41B9BB, 0xFB514AB0, 0xA8F4F078, 0x55C39522, 0xECDB0BBE, 0x4498148A, 0x91E93750, 0x947F5AC2, 0x1496F490, 0x0E38AAB1, 0x9332B875, 0x84619046, 0xFE2FBE43, 0xD48F8657, 0xD0ED5155, 0x347D575D, 0x9979D411, 0x1B55758E, 0x4EC065E7, 0x0250E824}, {0x4351A408, 0xABDAB10C, 0x31A4F70D, 0x73B7979C, 0xD60C55CD, 0xD2D681CD, 0xD321407E, 0x0A8BCA35, 0x5B2A3A67, 0xFBD568FA, 0xD486DBE7, 0xE41990A9, 0x305B2835, 0x0B45A04C, 0xED904CDB, 0xF3CBBE7E, 0x236F1FB6, 0xFD7AD037, 0xEF4C8CB6, 0x413320BF, 0xB96BF56F, 0xA22C1B54, 0x7F965953, 0x0641A14F, 0xA024A0CB, 0xE3AC760B, 0xB24EF75D, 0x035907D2, 0x312611FE, 0x97BD2A9E, 0x31A9BAE0, 0x9315EA40, 0x8441FC49, 0x0330A00B, 0x7C7AF1A5, 0xA3AC3CB7, 0xEE5F69B3}, {0x3B77B924, 0xC24288C9, 0x04F53001, 0xBD5ED85E, 0xF2513282, 0x50EB67BF, 0x044746C5, 0x5163617D, 0xDCD788C8, 0x8756CCC5, 0x9BA7E61B, 0x3AA23923, 0x840708AC, 0xFB09E2B1, 0x07F93D25, 0x3B6A7E3E, 0x253B5669, 0x7841DC7D, 0x79725A0B, 0xBD82F5E5, 0xDBFDF536, 0x8A656D95, 0x210AB020, 0x61EB5C19, 0x2677FE69, 0x2C8B84E8, 0x4BD0F536, 0x3BDCBCBB, 0x59B8C8BC, 0xEFC7FBC7, 0xE059E1FE, 0x41FFAD4E, 0x9AFE8C69, 0x2B119B17, 0xE20A89C8, 0x732305E6, 0x20769BA7}, {0x8B145FAF, 0x004E6933, 0x13DA7D6A, 0x7AC71A79, 0x62A9B67E, 0xC27DF902, 0x0290D9D8, 0xD25AD73F, 0x615A2A2C, 0xF8B8D005, 0xA099BDBD, 0xA46B5969, 0x333281BB, 0xEA8302AD, 0x9D7654CA, 0x22EDC9B4, 0xAA5B68BF, 0x6DE71742, 0xCD380BB5, 0xE63022E8, 0xEAC6DDA4, 0x486432C8, 0x15590868, 0x0A14D624, 0x47FECB99, 0x56D9F96E, 0x44236C82, 0xA9FC9BE6, 0x2BD2A718, 0x9DE93A96, 0x5520A386, 0xED2EB35B, 0x1F772456, 0x29D7B44D, 0xE055F18C, 0x2D982C39, 0x557F9637}, {0xA29620CA, 0x5C12AEB0, 0x845A906B, 0x798305FA, 0xCC7F72D9, 0x02A84439, 0xEA59C663, 0xC4C34053, 0xF939E2D2, 0x87FFF0F9, 0x6182BA5E, 0x423C132C, 0x022FB1A9, 0xA095AFAB, 0x95A5AE63, 0x09084186, 0xE5CDFAC5, 0x9E6A8CB4, 0x874476CC, 0xF86B2806, 0xF33EE3EA, 0x86698DD2, 0x47335B7F, 0x94F9F723, 0x7AA447D0, 0x8919EE6B, 0xC93CA98D, 0x902EC307, 0xCA352BDB, 0xDAF9B52F, 0x02A51C4D, 0x27B05892, 0x3992E5A8, 0xF0C6E482, 0x26EC08D4, 0x0169F9B4, 0x018A9982}, {0x6EBA4D7A, 0x146E8D7A, 0x3985F7A0, 0x0E696856, 0x6593D6D5, 0xDCA1ECBE, 0x39858C09, 0xC865AD51, 0x6F1D4645, 0x5425AE5E, 0xDF213897, 0x54D2805E, 0xFBC2FF3E, 0xF8D3B942, 0x704964FA, 0x27511138, 0xA6982C63, 0xB35624AD, 0x4B8F1229, 0xF73C6192, 0x24A66D44, 0xE5D96AF5, 0xF86B1C84, 0xA2400F12, 0x6A2C0316, 0x89B271C9, 0x78C9E756, 0xC0366782, 0xA50DD274, 0x7214AF0D, 0xF7671D63, 0x16AC7571, 0x555668C6, 0x8715E885, 0x280BBE87, 0xF531F58F, 0x9B89D7C8}, {0x41EBE5EF, 0xDBDFEE46, 0x28BFF1D4, 0x03B10304, 0x8944BE2C, 0x28CA6066, 0x711544B6, 0xB5D80D49, 0x709D665E, 0x04F5B926, 0xBDF4EAE3, 0x4E8BB54E, 0xBE7FFBD3, 0xB28FDD1C, 0xE0AF523E, 0xC638426C, 0xDF50BC55, 0xB6726CC9, 0xC5545A19, 0x4C768C26, 0xCAF434C6, 0x31187B00, 0x49B7D7F0, 0x491C673F, 0x45AFB7A0, 0xCDC11E5D, 0x67B4D51C, 0xE6F4C79D, 0x2C5E1D11, 0xD356EE90, 0x4598CFAE, 0xF1271366, 0xC7CD1AA2, 0xC5800941, 0xED84DE5A, 0x71B966AC, 0x3E996898}, {0x401D8FBE, 0x0FBAC0BE, 0x87F0DF66, 0xF704714A, 0x6A9882D6, 0xF2F0386D, 0x47890BD6, 0x52355601, 0x797BAB30, 0x83EDCC2F, 0x5AA6D2DD, 0x79279BF9, 0x0C22976E, 0x0EF0265E, 0x342176D5, 0x30E0CCA1, 0x8EEF51BE, 0x489C6182, 0x1E318618, 0x9D5CD930, 0xCCD31AB5, 0xE230FD5C, 0x93EDABEC, 0x000BB7BB, 0x37214977, 0x87EFD6C4, 0x272664F0, 0x0D74F10C, 0xC8FFEC76, 0xB9CD2B55, 0xA4C3F3BB, 0x577B0836, 0xF85F14E4, 0xE4137AEF, 0x2E494DF8, 0x15B4A72F, 0x57F818F3}, {0x2A51AC64, 0x55EA1D25, 0x73F63ABD, 0x1393A0EF, 0xA41BD017, 0xEB53F626, 0xE59A5BBB, 0x93E8D794, 0xE5E56CFB, 0x6D6455D5, 0xDFA95ED7, 0xAC225ADD, 0x1F3C8A9A, 0x0C0EEA4B, 0x14D8453B, 0x2367CEC3, 0x8B968283, 0x981D9FC6, 0xFCAD1C5F, 0x33DC6568, 0x8C921FE8, 0xD8448018, 0x4F689F54, 0x2D644973, 0x75A3CEF4, 0x2FD03C12, 0xE5BA1C78, 0xB67F8964, 0x8C6D9C21, 0x22E3B11A, 0x97726796, 0xB33800E2, 0x152433E1, 0x80EA2788, 0x4C612B5A, 0xFDD45F6B, 0x0036773D}, {0xB22C61D1, 0xD4A42BCE, 0x5EF01DC7, 0x62F9CEB6, 0xAA581620, 0x16796B17, 0xE78FF9C6, 0xF340FF57, 0xC36A5288, 0x25B7C151, 0x16AB4497, 0x73976A98, 0x7CF745FC, 0x8E83E6DD, 0x7F78E6E0, 0x0E86CD8C, 0xFA59F4FC, 0x652846FC, 0x70B86ED9, 0x356FB4A8, 0x13ACDDB7, 0x3E5AA108, 0xE24D7623, 0x670F4C96, 0x7C79B748, 0xFAC4A127, 0x5E4B8ECE, 0x52C7ABD0, 0xD2EAF1C5, 0x975FF704, 0x08703B09, 0x113E1A31, 0xB97B35FF, 0x01D87FE2, 0xAC51C60E, 0x7430093F, 0xB3497846}, {0xEBF4C72B, 0x320A6BB1, 0x6B36911E, 0x4DEEF783, 0xBF6768DC, 0x8C58F99B, 0x922E383C, 0x2BE30204, 0x65CD3C81, 0xC3365F95, 0x4A29E97B, 0xADCEF01E, 0xAABB8AD8, 0x10C83346, 0x6EF7D292, 0xBF96453B, 0xDBB5D9C5, 0x2CABF9DA, 0x5C0B9180, 0x2ACAC4AE, 0xFBBE28EE, 0xEAEFFB5F, 0x8A1CE852, 0xB6E57C22, 0x48DB6796, 0x3152B861, 0x2A1B8BDB, 0xC6A327F4, 0x345CFBC7, 0xF88A409B, 0xC5F5EFAB, 0xFAFA126B, 0x3579E67B, 0x98293BFC, 0xB46E5053, 0x7FF28536, 0x1A3154BB}, {0x70BB502D, 0x4AEC05FD, 0x32A06654, 0x5FA54917, 0xB2F20082, 0x02E9AAD4, 0xD9BBD33A, 0x086BD423, 0x7AB2731E, 0x810691FE, 0xFC7FD17C, 0x834F2BFD, 0x7E5CF291, 0xFF690C69, 0x48323915, 0x73F92343, 0x6ADB2A80, 0xBF274E56, 0x8A75C426, 0x8BCB9754, 0x85E3145F, 0x7C8DE9CF, 0x97C16BC8, 0xD03E0747, 0x9266E3DC, 0x997D01B5, 0xF4625D54, 0xC34D31B3, 0x13569E89, 0x8AF65908, 0x0ED221EF, 0x2356E831, 0xBEC005D1, 0xC315D354, 0x05574F86, 0x5FD8C68B, 0x3651053E}, {0xA6EB2E46, 0xC57B4832, 0xB095B99F, 0x5B0435E2, 0xA27432DF, 0xFB170336, 0x7309BA75, 0x999C33A1, 0xEA2B6032, 0xDB245387, 0xCE89EDDA, 0x2DE5BAFE, 0xC276A632, 0x033B278C, 0xA6976078, 0xEFE96244, 0x904A6BA2, 0x6FDC3467, 0x9EC4BF67, 0xC43D1C74, 0x1740D627, 0xAF8A99DC, 0xDD297C57, 0x245E6863, 0xC6FBC7FB, 0xB0DE45B1, 0x78E5FAB9, 0xEBFF7AB4, 0x9298E679, 0xAEBA925C, 0xDF16138D, 0x94C8C6D9, 0x6C0F6CCF, 0xB5555874, 0xC1942FDA, 0xAEE24590, 0x91EA4A10}, {0x9FC70E3F, 0xBB1BCC37, 0x425589C4, 0x821A1725, 0x3C67E94F, 0x8C6739A2, 0x2A4CC345, 0x93723CDC, 0xBB58B71F, 0xFEB4D91E, 0xE71B044B, 0xEC001111, 0x2BCEF86F, 0xEE950642, 0x4946DDB6, 0xDE3196EA, 0xD922AE7B, 0x2CF9A2A0, 0x6DC36BA3, 0xE91FB01F, 0x846921BB, 0xC95A6D7A, 0x30602F50, 0x70217F98, 0x049D0839, 0x6CFAE590, 0x8A2BCCA1, 0x60CD95DC, 0xEE946FC7, 0x1330A5F7, 0x0DED7CF1, 0x9742AD16, 0x39D4AE76, 0xEB37EC32, 0x002F2777, 0x202978C0, 0x0DF73BBD}, {0x6FB35DF5, 0x52BA4246, 0x492C020D, 0xD14888E7, 0xF8FFF2A7, 0x10622E26, 0xF82FDF0B, 0x572BC4D3, 0x3E6EA194, 0xB5BC2D8B, 0x80E74BFD, 0x438EA3B4, 0x5CCA0DA3, 0x0E3C1585, 0xEE186446, 0xC459FDF5, 0x6FE7891B, 0x13C9585F, 0x1647A5F8, 0x5AF12514, 0x8AC87135, 0x016C7578, 0x134D5C1F, 0x9746051B, 0x0A24EA61, 0x4E284497, 0xD279DE99, 0x91255074, 0xEC67AE55, 0xF99C9DD7, 0xFE530769, 0xDE147527, 0xC8A67B28, 0x90668D3C, 0xC1C5EB50, 0x797506D0, 0xE37218F2}, {0x12FA8749, 0x3E092444, 0xEECFAB98, 0x3B4DAC87, 0x6F793235, 0x4356602A, 0x2EB6CFFA, 0x25D4914B, 0xC51056D6, 0x1806A5C7, 0x6401E4CC, 0x9E544662, 0xBC2BFA25, 0x814558A9, 0x37B5CAFF, 0xD5BDCCD9, 0x96473844, 0x405DFECD, 0xFB6C9968, 0x70784E77, 0x72FD667C, 0x5EE44E70, 0xE67D0D9F, 0xC1279713, 0xF2912A9F, 0xF5A20056, 0x9A804815, 0x70B63B4D, 0x4D7190CC, 0x28718097, 0xA49013CB, 0xDF7368D0, 0xAD9B6AD3, 0xE3DD7BD1, 0xECF1098D, 0xB62CCD81, 0xBDC7CCD1}, {0x42A7D845, 0xAE816DDF, 0xFD186BB1, 0xA929B325, 0xB1C28DB8, 0x33807D06, 0x68F7E569, 0xB920AC6E, 0xC749A738, 0x83C8FD76, 0x6E995FE9, 0xB4185D4C, 0x58112E28, 0x5DAA5A00, 0x99BEB688, 0xBAE16866, 0xAB316CF8, 0x84853B00, 0x721CAC7F, 0x0D12AA6B, 0xF1B05D1C, 0x5D2045E2, 0x8FDD7B2D, 0x0E4C034B, 0x37D503DE, 0xDD801F89, 0x8259F5C7, 0xF53FF251, 0x9AA2BCA4, 0x47B7CD0F, 0x2C1F8761, 0xB947BCEA, 0xC9394765, 0x29FB5B05, 0x91D4E7A2, 0x802B0004, 0x7F7C5789}, {0x62324F61, 0x8B657126, 0xA37478B0, 0xBB686485, 0x029310B9, 0x60946B35, 0x8316048A, 0x02F66AAF, 0x1A0A0A31, 0xC231E951, 0x25A67284, 0x94379E14, 0x2FBF7C94, 0xF743D053, 0x55BB8AEC, 0xB26DBE19, 0x697F4FAB, 0x0465D0E0, 0x6B1B73FE, 0x10134F16, 0x9189D9C8, 0x1811C019, 0x45B97131, 0x4C131CFC, 0xC2A7642C, 0x57D7667D, 0xEA7FBF25, 0xEB22AE17, 0xADDEC146, 0x52AF48ED, 0xC416AD97, 0x4F265526, 0x5440C640, 0x1C96E8D2, 0x3B81D254, 0x4687E447, 0x2859C70F}, {0x1A4E65F8, 0x0BCD1F17, 0xC0DC3A67, 0xA11D9870, 0x204ADED5, 0xF5DB1845, 0xDDCDE427, 0xD888B8E8, 0xDEEFF252, 0xC48C75C3, 0xCB3A2177, 0x54742A0D, 0xF65CA5B1, 0xF4A4B813, 0x67CECB8F, 0x2D14B087, 0x415C8A06, 0xB5966EA1, 0x1DAC2857, 0x653FD5B0, 0x260F52C1, 0x7788095B, 0x020BBA7F, 0x9358D07F, 0xD48617DC, 0xB26B4073, 0xAB6DBE8A, 0x9258F3EC, 0xC85E9447, 0xB5BA17E5, 0x7DB63962, 0xB5EA495D, 0xCB4C631D, 0x358FA9A3, 0x3D5E23EF, 0x3F09A770, 0xA8305620}, {0x07C27742, 0x08FBF9CC, 0x0FAE7FC0, 0x679F5557, 0xE58B0291, 0xF53FB79F, 0x7A1B467D, 0xBE675AF9, 0x935991AF, 0x53D801B1, 0x12B683F2, 0x71489C77, 0xEA404266, 0xD2F59F5B, 0x436962CB, 0xDC41A387, 0x598A12E9, 0x393FD780, 0x22D7D0D7, 0xD4B7B3B2, 0x71C733C0, 0xB9294FC6, 0xEF82697E, 0x7B7480D3, 0x9A6DEE75, 0x1A2EF122, 0xAE86B34E, 0x9DD2A443, 0x03772D70, 0xFA5C32CC, 0x642220FF, 0xA1D0D227, 0x78EA9DFA, 0xA0AECEB1, 0x1C3BF351, 0xF65122BB, 0x3C707FFB}, {0x8C2A542E, 0x712C76CE, 0x20F8C69E, 0xD813E9C5, 0x1CA0BB68, 0xEECDD3F2, 0xE8BD79CF, 0x5F35E1F4, 0xBA16B9B8, 0x5866BCE9, 0x5F575709, 0x377CA185, 0xC378B942, 0x71247643, 0xC7E26CF3, 0x3C32DDF0, 0xA3A834EE, 0x48D9F31C, 0x58D484E7, 0xBEE20A44, 0x5341C703, 0xF75C7BD6, 0x0D71EA00, 0xDC569EF8, 0xED1A8539, 0xACF1C672, 0x2D6AC356, 0x1D4E77FF, 0x978AD28F, 0x401DA261, 0xC91C0838, 0x37242F40, 0x08348236, 0x2DD66A25, 0xC2A92601, 0x8B1B3662, 0x50715199}, {0x911E06FF, 0xC4026969, 0xE15195FA, 0xDCA8FCB3, 0xFB3ABEEB, 0xCCFADEA2, 0xE64FD99E, 0x4FC0A8A2, 0x4F760445, 0x6B5E8842, 0x0DE756BB, 0xA1C29CD1, 0x4DE78041, 0xE456F497, 0x22E99107, 0x98FF2237, 0x785E6C4B, 0x15F0CA98, 0x838CB878, 0x3A2EA31A, 0x93F418DF, 0xCB0DA3F4, 0x0F294C5A, 0x2277505E, 0xD4530493, 0xFC08D337, 0xB05E7D2A, 0x1061B79A, 0x4C76B691, 0x0DEB5EFF, 0xB5D2D35B, 0x35C14A00, 0x30A2E2ED, 0x7C506EA6, 0x07174596, 0x8A420FE0, 0xEC14306B}, {0xBBF7EE2D, 0x51A00B0D, 0x4C4F0016, 0xFFE03EF7, 0xA91001AB, 0x42DAC641, 0x7FE2DB36, 0x86D40E7D, 0x226AAFEA, 0x2074F757, 0x5ADFCDD2, 0xF5566354, 0x9732E077, 0x82A2F6C4, 0x872DF023, 0xC49695D4, 0x4DC39A39, 0x2C858C99, 0xB17EC565, 0xAD9BFC95, 0xCB33C8E4, 0xA22E6087, 0x1D1B3EBF, 0x8FCD8803, 0x564761E8, 0x657A482D, 0xC81F441F, 0x16902B19, 0x4491AFFE, 0xF1EF34DE, 0x5217FF93, 0xEE5320AB, 0xBC05BC99, 0x13649675, 0x26F8CC82, 0x0640334D, 0xEAFE8B8F}, {0xD91D5C30, 0xE3E9E02C, 0x445346D5, 0xB16317B6, 0xADF94844, 0x02E3CE3D, 0xE9942620, 0xFF850889, 0x9014A418, 0x0306BCC6, 0x5E666F42, 0xE7832C50, 0xA51ECE32, 0x177AD47C, 0x3F03FD8D, 0x922123A2, 0x28E99092, 0x0BC649B7, 0x22AF4FFD, 0x77A45AD4, 0x4707577A, 0xFF9BA95B, 0xE6CE1022, 0xAE52E672, 0xEDF149A2, 0x144491AE, 0xA73F03B2, 0x86135EA7, 0x56C4945C, 0x0F1D7F0E, 0xBEA107A5, 0xEC5F0B49, 0xFB3CA351, 0xF5432AE5, 0xD2286DA5, 0x842827D0, 0x25262C60}, {0x96D1F5B6, 0xBB070F3B, 0x28CAD4C3, 0x95E4043E, 0x4D8DA18D, 0x30A380FD, 0x9B94B359, 0x324AC88E, 0x03197C48, 0xE70841D4, 0xC925ABFC, 0x3FF52919, 0x59CA146F, 0x9766043E, 0xF871EBCD, 0xC46EEAB2, 0x3314CA24, 0xD7F83508, 0x33200B58, 0xB216983B, 0x57CAA057, 0xF2A05E8B, 0x7589FCEE, 0x4811F7DD, 0xB5EA14D8, 0x303ACE6F, 0x0918F848, 0x09751CD9, 0x6A874323, 0x8D95EF20, 0x626D35C5, 0x8F5BA9F7, 0x41060F9A, 0x115CD712, 0x6EA16A8C, 0xFD6357FF, 0x9E922BAD}, {0x29F03778, 0x6D3A6FDC, 0x7FE8404F, 0x14B4098F, 0x7933DFCB, 0x2775AF8E, 0x7AAFBABB, 0x9ECCAB4D, 0x987E8066, 0x4261E21A, 0x0750E975, 0xD5D3BA85, 0x70D34D98, 0x601417A8, 0x8E720C36, 0x75CBD64A, 0x7152C716, 0xD024CA9D, 0xB3121EF5, 0xA1032D43, 0xE7BDA34F, 0xE7FCF957, 0x8C3EE28D, 0x3D895552, 0xB0B466E0, 0x6480D4F9, 0xE3A31A0A, 0x2B8D41B0, 0x9FFB99AC, 0xC09C0239, 0x95CB3D8A, 0xB43A5F62, 0xA693DA5E, 0x6AB0EDCE, 0x4F7CDE51, 0xDB793ADC, 0x0573488B}, {0x8F052C3D, 0x7D5B30AD, 0x6938465B, 0xD046F2C5, 0x7CEBD0FF, 0x5B41A4F3, 0xFAA481B4, 0x41776844, 0x49C089FE, 0x47E2E1E5, 0x4114E8B7, 0xDC2CB5B8, 0xD7B95677, 0x1DAFC1D7, 0x17AD5FE4, 0x1D6C9A5C, 0x89AD03CA, 0x62827ED5, 0x7F2E7004, 0xC5D09259, 0x78888430, 0xE7CA5D4C, 0x46722456, 0x27224063, 0x77AF8453, 0x17153294, 0xEE5CF911, 0xB6283C83, 0xA34BB723, 0xB2C79B61, 0xC7846E75, 0xA0F652F6, 0x55360874, 0xCFA197FF, 0xC8112E4F, 0x52931336, 0x6920EF6D}, {0xB0346D53, 0x602B8423, 0x7A878432, 0x1E57C0AA, 0x533C9089, 0xA7497C76, 0x6F3A45B6, 0xDEC65599, 0x2375996C, 0x47A74EFF, 0x9E8C0AC6, 0xE538178A, 0x7272287B, 0x5D06845B, 0x8AAAD01E, 0xF185C646, 0xA6AFF9C6, 0x7866F191, 0x2C8FD825, 0xB46F53D0, 0xDE4FE828, 0xD684351A, 0xC45EFDEC, 0x823A43DB, 0x1615C5DA, 0xD8D045F1, 0x0AE67446, 0xB3417159, 0x65A02242, 0xC50B45FD, 0xDC158020, 0xF14D3A58, 0xDC3374E3, 0x71B75FC5, 0x7124E32F, 0xACC13DAA, 0x252FB4BE}, {0x1D6BF290, 0xECDA0463, 0x03462A4A, 0x7AC220E7, 0x1A555C49, 0xD4FA7170, 0xAF570804, 0xD8D2B2AD, 0xBC22261B, 0x50B165A7, 0x6E9F5D06, 0xFFACFDF9, 0x5490CD01, 0x4DA8C562, 0xE9C10BD7, 0x4DCC7574, 0x6EF8C0F5, 0xEDD012F4, 0xE15BAC48, 0xF61F8BA0, 0xCEBB61AE, 0xECAE90BD, 0xCB809669, 0xFD18BD7D, 0x92943C15, 0x658D2F6F, 0x5F2FBEBA, 0x193F0850, 0x29B01C70, 0x06CD4FA4, 0xD8110260, 0x700535FA, 0xF025046D, 0xB776ACB5, 0x25E42E6F, 0x33CC46C4, 0xB65AC414}, {0xF3E71979, 0xB104D5F9, 0xFAB1844C, 0x3FA9F592, 0x931F6BB9, 0x754E2361, 0x3BFC41CD, 0xB481F67B, 0x5FCAB99B, 0x8365B425, 0xC10DDB20, 0x94A94287, 0x86ADE790, 0xFB614A68, 0xE6AED9A6, 0xF018FF03, 0x3ECF7650, 0xDFBD85B3, 0x600DC9F0, 0x7A4C63BA, 0x7C3BF0C5, 0x850DCD86, 0xD67D48A1, 0x7815F195, 0xCE902CD9, 0xF91DA3D9, 0x844EDB6C, 0x1AE80057, 0x006F847D, 0xF41FC7B5, 0x2ADED5E8, 0x400F8F68, 0x927C2FDB, 0x191494B0, 0x7F4585CE, 0xDFCC7276, 0x1045493D}, {0x6000AA82, 0x72981436, 0x94949516, 0x18441C9C, 0x29D88BB9, 0x0824CE75, 0x5C73C342, 0x2D0BBD81, 0x5088310A, 0xB25B950C, 0xC138A826, 0xD9F73D05, 0x7F35B0B9, 0x17DC9E04, 0x249AD5B9, 0xF45C018E, 0x8453DF7B, 0x1518D000, 0xEFA60740, 0x530560B5, 0x0D716455, 0xA2EDB6DF, 0x5D2DADD3, 0x0945F7EC, 0x509DC46D, 0x50716F31, 0xD87D4235, 0x7DA4FD4C, 0xBD7A189F, 0xE7EFB2D1, 0xD341026F, 0x11EF0D64, 0x45E164A5, 0x47087E9E, 0xFF2C5F5F, 0xFE9B3757, 0xB86AD126}, {0xE02503FC, 0x41CCA4CB, 0xF12CCD50, 0x1AC7C6ED, 0xDF36D318, 0x57A748B2, 0x9BD0BF93, 0xC9E20162, 0x71A796B2, 0x6653FF5C, 0x8D3CB6F1, 0xC1E99228, 0xAD8B4DF8, 0xE09ACAE0, 0x50301789, 0x81D6284C, 0x7CFCC690, 0x9463E5B5, 0x286ACA45, 0xEA7CE9B4, 0x03EB2A99, 0xA3079B15, 0x499B1674, 0xC02ECFB6, 0x6E53D545, 0x1EE839BB, 0x3EA54F10, 0xFDE2819F, 0x97AF95D6, 0xCF757D38, 0x6C373715, 0x92F0A958, 0x1CEF9586, 0x8DD84F81, 0x5C669E1E, 0x01ECB720, 0x969909E6}, {0x2D1FB241, 0x4F0E0C46, 0x4747304D, 0x7BCEE5CC, 0x63667506, 0xA6CA6BDB, 0x755E7929, 0x65CF2772, 0x310637BF, 0x205BAB6F, 0xAFF1ADCE, 0x64A1E05E, 0xF67A1D73, 0xE406B87A, 0x44F341E1, 0x2CBD9F95, 0x0FD0AF20, 0xF293EE03, 0x899FDA8A, 0xE67DD678, 0xBF376D9A, 0xBB069E3D, 0x0F88BF9E, 0x817994CC, 0x32943F3E, 0xF0C8E14F, 0x5BCF3011, 0x3FD2BEBB, 0x714F208C, 0xBD067165, 0x4A957439, 0xBC590C03, 0xCBA6B2B8, 0x22D5A77B, 0xBD71011B, 0xF8910497, 0x02A732C8}, {0x7B8F04D2, 0x987AFD06, 0xD2649A8C, 0xA0141A26, 0x7D8A51FE, 0xC2C775E8, 0xC33B8030, 0xBA583DB8, 0x9A7718B8, 0xFBA77061, 0xB14FAC50, 0x94BE7F2A, 0x4FC21B53, 0xFB2B3008, 0xA8BA27A8, 0x5E889551, 0x6E458F30, 0xCF5D23D6, 0x0B7AE76E, 0x493AA165, 0xF5B66827, 0x0474298C, 0x69815307, 0x0BB955BF, 0x0AF44E2F, 0xAF09F7E0, 0xCB70DAD2, 0x1F533744, 0x0A95BA05, 0xCD5C9BDA, 0x6E9E046E, 0xDA5C524E, 0xA2FDCA13, 0x2CD88903, 0x985491BA, 0x0FAEE46B, 0x451E6BAD}, {0x86E2D326, 0x97A927D5, 0x224E9F7C, 0x2E61EE1A, 0xFE52C52C, 0x1E0D8866, 0xAA921877, 0x16DD2BA2, 0x6C2A81B5, 0xA45879B5, 0xACF26BE4, 0x3C236B92, 0x2C63A6EA, 0x0B29669C, 0x164D1CB1, 0x59720A81, 0x2889A7DA, 0x0F23345E, 0x34BA951D, 0x10342C7C, 0x87DA6DB0, 0x0E4FB8C8, 0x2B4B9081, 0xA07DDE1E, 0x777F4984, 0xBD248EB2, 0xB787440D, 0xC000BDAE, 0xC0230404, 0x4A211BCE, 0x14DEB28F, 0x1DE2AAD6, 0xD7724A60, 0xE3125EFE, 0x8111E938, 0x67BAB9FA, 0x1D2B2EC0}, {0x3C388BA5, 0xDCC673D8, 0x65AB8ED1, 0x63FAF73C, 0x3C738632, 0x6F100AE9, 0x75671766, 0xF885D05B, 0xBC9156D7, 0x69D2F8D2, 0xA734A4E4, 0x8B35F56E, 0xF23FEFD7, 0x18EB28BF, 0x0534D95E, 0xAB95C453, 0x4CB7B57D, 0x506C79E7, 0x68E5667F, 0x45D28F01, 0x097543D8, 0xC9CC3421, 0x316443E0, 0xE337FF96, 0x883075B9, 0xB2FCF3E8, 0x1320B2E5, 0xC00A6C1A, 0x81FC8F2A, 0x012DC719, 0x4895C61E, 0xCA8D27B7, 0xA2C6B219, 0xFE132FDE, 0x7D768D5A, 0xD8E3B807, 0xE518A515}, {0x940CD418, 0x6ABB97E6, 0xF9688B86, 0xE63AE360, 0xF6932BBE, 0x1414A186, 0xF6F5EFC8, 0xC164AE8E, 0x1F648031, 0xAF12E70D, 0x29D3B2C8, 0xF3EDF9A8, 0xE8C0D0D0, 0x2C81A9EF, 0x05DEB9E6, 0x66803FEB, 0x542CEB28, 0xEB3811D8, 0x6B42E705, 0xDB1CEBDD, 0x00BE85B8, 0x88DC7E01, 0x69E20C12, 0x4EA346CB, 0xFBB0C3EB, 0xFC3FC996, 0x6B9B6EE7, 0xEF0F84E0, 0xC991FAA6, 0x09B4DA9E, 0xCBF85F7E, 0x20631336, 0x359D4DB7, 0x0B3D9270, 0x4F7F845D, 0x9BC56853, 0xEDEB1BCE}, {0xA14790F7, 0x5673B0A0, 0xE3BED709, 0x3DCA5E6E, 0x392B4EEB, 0x7BB39FF4, 0x56BD376D, 0x1836D3AC, 0x6994E304, 0xB3B19F56, 0xFE972B4C, 0xC624A1E8, 0x4881257E, 0x6411A846, 0x36B967AE, 0xBB0C8014, 0xBED2218F, 0xEF9DEA26, 0x82EBCE2E, 0x93AD05CA, 0x5A2CD29F, 0x9A249BFC, 0x7AE88791, 0x28A5E503, 0x634F7929, 0xD2B6AB7E, 0x2E20612A, 0x8DE8FBEC, 0x2A95C9F2, 0x87B4E9C9, 0xB6F5F6BA, 0x5BAEFDC0, 0xD99C2FBF, 0x6F56A241, 0xE18F6716, 0xB2CB598C, 0x96898D80}, {0x600C5B7B, 0x6B0FB589, 0x716D5A4E, 0x559881CE, 0x93C870DB, 0x4EDB62C5, 0xCAFA0E1D, 0xFFBF0ACE, 0xF1E3406E, 0x9099E608, 0x1C3A3BFF, 0x7C8FD481, 0x7E7FCED3, 0xA7DCE690, 0x62D25F77, 0xB2A4E431, 0xB907C58D, 0xE02914DE, 0xFA16AD08, 0x47EE3704, 0xF24D2899, 0xB8DE2CCF, 0xF99FBB6A, 0xFE041157, 0x89EA9D4E, 0xF6FACDAC, 0xB8D394D2, 0xDF495392, 0x54C1CE45, 0xF9D44BF3, 0x8E5A60DC, 0x66AA4AA9, 0x44A3E0DA, 0x8221CEB8, 0xF5CDDA85, 0xF1688C7D, 0x72EEBA6C}, {0xE053BA71, 0xF342AEF9, 0x43B9611F, 0x8C536C10, 0xA90E858C, 0x8A825DC3, 0x44933D2B, 0xF2F53A99, 0xD2AAD392, 0xB286EB51, 0xF8C92CB0, 0x1E47F397, 0xDB2BC5A8, 0xE87AC0DF, 0x37B5F6CF, 0x1679CACF, 0x4A10EDA1, 0xCA4E05E3, 0x4E25E482, 0x2D23ECC5, 0x379DE179, 0x53B803A6, 0x39C6C484, 0xCA5AA813, 0x3F0D505C, 0x0C424AE4, 0x4F2EF279, 0x10E22958, 0x8017134A, 0xFEFC221E, 0x6A0C5262, 0x902557DC, 0x727583FC, 0x9FC69217, 0xD63A07B8, 0xB193AB86, 0x27E0CDD5}, {0xE4ACC0D7, 0xA8DC3F76, 0xCB316F92, 0x6D43E961, 0xE0F83FE6, 0xD6B72780, 0xB255CF65, 0x78F2992F, 0xAC94D465, 0xE424EDAC, 0xD988D90D, 0xAAD096FF, 0x9A3AD365, 0xE49502B0, 0xA94A2490, 0xF5BCA82B, 0x3E6C47DE, 0x5F5F3760, 0x1A6302AE, 0xD2B9F7E6, 0x05D3231F, 0x92BCAEB1, 0x1B5B28B3, 0x1F528C4F, 0x8EB8B125, 0xCA09EAAF, 0x9ED58EEB, 0xDDBCE516, 0xA6874D12, 0xF46F9F7C, 0x4179D4B1, 0x44C4E4B4, 0x43489CDF, 0x684DED90, 0xF10A986A, 0xE8F879B7, 0x08B9BF73}, {0x2A5895FE, 0x56CE6CC1, 0x5E7ED45E, 0xCA8C2331, 0x52EB2FD5, 0xE3D38FDB, 0x99403E77, 0x58995171, 0x8DF6E00F, 0x01937BA3, 0xA1F7AB7F, 0xE45BC89D, 0x9104F992, 0x83DC8307, 0x9FC35EF3, 0x734BF964, 0xA02D67F4, 0x7403AF0F, 0x2D9C5BED, 0x8106579E, 0x598312A1, 0x7EAF7F16, 0x61FD33AA, 0x201A97D1, 0xE89178CF, 0xD1CD20EA, 0x55C7A0EB, 0x2290B7D2, 0xF502AA37, 0x20B406D1, 0xB8ECDFE1, 0x1680F194, 0x4E248E3A, 0xE71994A5, 0xBC275FC7, 0x4A130313, 0xC88115A6}, {0x646DF035, 0x52A0B8B3, 0x17CF09F0, 0x952A675E, 0xB7F51121, 0xDAAD4E86, 0x4E77BA5E, 0x138DD4C0, 0xEEAE0D91, 0x06818DA5, 0xD48B5B52, 0x9B2BB0BB, 0x5545D4E5, 0xC1752A6D, 0xFB1CB8CE, 0xB0BAFFCB, 0xB5B822F7, 0x8A2275E2, 0xFFF9ED8B, 0x21EE5F16, 0x81A0553B, 0xAC356172, 0x92178AEC, 0x604E8F86, 0x4E4A291F, 0xF8AB0966, 0x745DA2A1, 0x9B9F5965, 0x9C715F26, 0xBB47C27B, 0x2E4559D5, 0x7019D572, 0x06117836, 0x4516CB91, 0x54CAF4F2, 0xCE156DF5, 0x665E61D5}, {0x9841114C, 0xC739EF2A, 0x14B83062, 0x243EAA97, 0x05016119, 0x236B6D51, 0x9F568A46, 0x4E7BA066, 0xCDB83963, 0x1DCEB36A, 0xC82D4452, 0x17DDFE65, 0x512F49B9, 0xAD49B7F5, 0x9AF0D8F0, 0x106974B6, 0x2BC99EDA, 0x23EEB3AB, 0x9FA054BD, 0xBEAFB817, 0x6410B667, 0xCF604B9C, 0x45963838, 0xDA94C599, 0xF5640582, 0x46D09940, 0x733068D9, 0xC8637801, 0x5E9710F1, 0x53B71D31, 0xCFD7B87D, 0x8D847D05, 0x8E680E06, 0x21949C66, 0x08DA9039, 0x9E0C3D49, 0xCDC76277}, {0x0303B940, 0x03920AF7, 0xAB58346D, 0x58D75886, 0xF3E3190A, 0xBAD8520E, 0x623DBDA7, 0x69B025BF, 0xCADCC444, 0xB7500FC7, 0x696CFEB5, 0x8752B53D, 0x08DFD774, 0xCD1BEECD, 0x469B8BEF, 0x91E92609, 0xDC7A4E2A, 0x4ACC5E6D, 0xEA7E60ED, 0x8A2F8F23, 0x42A81674, 0x309CBAAD, 0xC2D2AACE, 0x676B6968, 0x1C325AD8, 0xABB3177C, 0xF3847A04, 0x9C24A27B, 0xDB39F99A, 0x2C94F092, 0x6A2953FD, 0xA8687F67, 0xD3B4EF39, 0x5B7A65DD, 0x3841CC06, 0xF1CD03C8, 0xE56EF64E}, {0xAD7670D0, 0x863B8C42, 0xFBDE1207, 0x44AFEEFD, 0x1BF4B706, 0xF79E7152, 0x2F489BAA, 0x918C9807, 0xAD72FD00, 0x875CF555, 0xEC201427, 0xAF8C317B, 0x3EA42AFF, 0x39E1186A, 0xDB2613FF, 0x57725925, 0xDBD3BCAB, 0xCABB5927, 0xC35F1079, 0xFA3F72E5, 0x111C506A, 0x8CB431E1, 0x9D90EA60, 0xD93FDED1, 0x1AC5BF2A, 0xE4014502, 0xA9A43890, 0xA3D65D68, 0x13A5CC24, 0x6E3ABCC4, 0x9A513106, 0x5CB45B33, 0x3A4ABC3C, 0x28111F9A, 0x04880B4E, 0x740BE57E, 0xCD197B2B}, {0xBFAE7AD4, 0xCF36EDA6, 0xB6EEA600, 0x574741FC, 0xB99B99F4, 0x97C321D8, 0x91402DE2, 0x95005F34, 0xFBDAAF56, 0xC521F253, 0x6D5EF39F, 0x34FD0D8D, 0x0E9E671F, 0xD9A3F670, 0x6594C416, 0x521B4AA1, 0x8EEA51BF, 0xB3F62301, 0x1234626A, 0x61FF1F3D, 0xAF4443A0, 0xEC77DE9B, 0xE4807B34, 0xE6F61F38, 0x01F3645B, 0x8ACA6258, 0x932D4DA0, 0x5C8F64BB, 0x275FC2AA, 0x102D0B98, 0x704BFF2D, 0x920A86EB, 0xDD3126A7, 0x15942B55, 0xC53B68BC, 0x1F181708, 0xBB2F2BAC}, {0x6978C189, 0xE276AB06, 0x45CC0887, 0xE5166291, 0xDE5F1398, 0xD0F3413D, 0xB82A9AE9, 0xD541E85B, 0x9CC8BC79, 0x276119C3, 0x77E81288, 0xC593AEF2, 0xB7D2137F, 0xC2A27B58, 0xF658E3A2, 0xE0F7A50C, 0x1F789DF6, 0xBF461BDA, 0x992318C4, 0x55F7B611, 0x568DDF95, 0x40408342, 0xDF532AB5, 0xE4FCD050, 0xDC4D9C28, 0x13B10EFB, 0xD5471960, 0x2C56F542, 0x59CFCAD2, 0x53419764, 0x55D3CC78, 0x9A18E28B, 0x8372799C, 0xB7A810A9, 0x73B02096, 0xEBE88C9B, 0x8D142B07}, {0x0ACB736B, 0x59C4B340, 0x98898F87, 0x71E26AB1, 0xE847F78F, 0xDF3ADCA5, 0x06144E9F, 0x012FD1D1, 0x87A7CCA7, 0xD7C28A65, 0x68023FEA, 0xBA79DD5F, 0x3D2F972C, 0xD188B10C, 0x3E9F2BCF, 0xB0F895A1, 0x7A533B37, 0x1C7B73AE, 0x84A3EC05, 0x68638A32, 0x9BC3CF73, 0x1D31043D, 0xCD841B3B, 0x680E4FF9, 0x7C3E6FAF, 0x41A2EDF2, 0x4DBF60F9, 0x5BE28884, 0x60002992, 0xD64CDC27, 0xEEB2DB46, 0x1009C715, 0xB3376EEB, 0xFC78EA63, 0x0F3F5DA2, 0x454316E3, 0x395D2C0A}, {0x737848AC, 0x7D9D3DC1, 0xB9925CCE, 0x75BBB020, 0x656F525A, 0xA8991680, 0x2672D881, 0xA28E81E7, 0xD465C5C4, 0x7550726C, 0x931248D1, 0x00832875, 0x2539E86B, 0xE8DC0BBF, 0x48203C63, 0x96EE3C29, 0xFE82FCE1, 0x81BE894C, 0x7C78D9E9, 0x632C18D2, 0x36459F6D, 0x851E239A, 0xEEA230B7, 0x3803ADA1, 0x674AA785, 0x2B7C0445, 0x1770B321, 0xD30DC314, 0xC7FDD289, 0x7BB54A09, 0xB50141CA, 0xEAAB6F50, 0x3ED219BE, 0xB2451B7B, 0x59921640, 0x56A63082, 0xBE02A09A}, {0xF1104B21, 0xD41E5659, 0x325B408F, 0x4C1F0B69, 0xCC28570E, 0x7F234110, 0xE6752CD2, 0x7325C0A7, 0x7CF454EB, 0xD53C85A2, 0x129F3E8A, 0x4D70F86C, 0xDC23328C, 0x1DE25626, 0xCF344FF9, 0xC49C3D22, 0x668441EC, 0xE286900D, 0x51F1C0BC, 0xAF07A355, 0x92E318A4, 0xE5575714, 0x95440706, 0xF5A1C83E, 0xC3458F16, 0xC323B7B7, 0x9EDA7B28, 0x89BAA3C5, 0xF044A6A1, 0x2B4FD669, 0xF397694B, 0x95FA0176, 0xF87C0EB1, 0x65207897, 0xBB9FF64D, 0xDD8919C2, 0x5EB0F04A}, {0x9289DE6F, 0xF3F25CD4, 0x9E17CCBC, 0xF1B5E865, 0x0CE58250, 0x31A16A9A, 0xC9D0AC65, 0x448C5F53, 0x367B28EE, 0x5A76DFB2, 0xA9A8CAF3, 0x15DE8FD2, 0x90B72B33, 0x3A233E37, 0x58B58320, 0x3630EAFF, 0xDB457148, 0xF1D040F8, 0x677A7FBE, 0xA069CDDC, 0x3382CB00, 0xDC64DDA8, 0xC302B55F, 0xD8C609EF, 0x0CC666D5, 0x23B96DDA, 0x69E7CB6E, 0x4E6AFF1E, 0xC821772A, 0xBCD258CB, 0x617E713D, 0xFA87A14F, 0x6EDFA280, 0x053B9023, 0xC9F571AB, 0xCA868F17, 0x6F4075F9}, {0x5D28BACA, 0xD8E8E550, 0xC1450196, 0x4A58BBFE, 0x05AD30ED, 0x2CA781C5, 0xFA9FC941, 0xB15F53CD, 0x5925EB67, 0x32175731, 0xA2E63AAA, 0x8BBF326B, 0xF34A9400, 0xAD7B7749, 0x5B93CDBD, 0x82E459B1, 0x994E5887, 0x2B89B597, 0xDFE0E4C5, 0xA11E8542, 0xF9BF2C1C, 0x58A460BC, 0x101C572D, 0x41829642, 0x6F6BC678, 0xCC50019A, 0x5CF0989C, 0x58EEB02E, 0x333A8EC2, 0x2FFE8B45, 0xE59B5647, 0x4ECCE197, 0xF1D0021D, 0xA4905513, 0xF08CA613, 0xF02529AA, 0x083F35C2}, {0x52191549, 0x7E237119, 0x156ABCA5, 0xB6D68DB3, 0xD7EB8811, 0x82E114CD, 0x48588521, 0x460FB492, 0xEAA820AC, 0xFC510DB8, 0x5C808A2F, 0x643D135E, 0xD5581316, 0x3DE90520, 0xB0E337BB, 0xFB2BF84B, 0x183D48ED, 0xCED95E9D, 0x2C550933, 0x507BBFC5, 0x3C5BF2A0, 0x68197BA5, 0xC8847FDE, 0x50C07AE5, 0x612A2F1C, 0x1FB43D3D, 0x5812CED6, 0x4AB2E45C, 0x2A0E8AA3, 0x0D84E62F, 0x724CB6BC, 0x019DD736, 0xAF620A91, 0x8EBF0585, 0xC30B5191, 0x0E8B0846, 0x75C1DE88}, {0x9CAA40F7, 0xD0AAF5C9, 0x8032F141, 0xADD08797, 0x30301AEE, 0x89284228, 0x0378ED2D, 0xCE75AE05, 0x164DA2F7, 0xDD75424D, 0x2BA7E112, 0x3673EC13, 0x13CDC6D3, 0x6D4AE72F, 0xB0F4B68F, 0x9263994F, 0x8A3A93AA, 0x30927E0F, 0x2FA41CFE, 0xE423BE50, 0x60BBE11C, 0x196DF642, 0x5B214C95, 0xAD67FF62, 0x1880925E, 0x14D24735, 0xE11D9268, 0x0758209E, 0xDFE17901, 0x9D77FBD4, 0xC45F2FEC, 0xA5491920, 0x66D7AF64, 0xF8D9427D, 0x610AFCC8, 0x537ED573, 0x0893A5A7}, {0x5DFD7359, 0xA8C0316B, 0x233450E6, 0xA0916CAA, 0xB331FE40, 0x36803B22, 0xA07C70DB, 0x817D92DD, 0xE5F20876, 0xCA972A48, 0x31D6A608, 0x837445D3, 0xF86FD16C, 0x96217983, 0x75CB3F78, 0xA506A973, 0x587F9465, 0x9760238D, 0xD3C05E4B, 0x992C4429, 0xD140EF6F, 0x8F14FD45, 0x66BCB4D6, 0xBAB14670, 0x68F2EA45, 0x3A1246B2, 0x8B178611, 0x7860C8DA, 0x6F40B5E4, 0x2C515E4F, 0x5A315A85, 0x51E51745, 0x2CA115F8, 0xDDACE164, 0x232475E4, 0xEFAF52A4, 0x287D8744}, {0x3C855DA8, 0xE288C105, 0x739583AF, 0xF71992C4, 0x4E437D6D, 0x86689586, 0xEE48412B, 0x5B71E654, 0xD21E49C8, 0xF17D6EC7, 0xA00074FF, 0xA69B7D4D, 0xC3145A7A, 0x89083E87, 0x947D35A6, 0xC04DBB6C, 0x60E9D531, 0xD93FBE15, 0x1B5B9BFD, 0x48B168F9, 0x76387167, 0x5A120655, 0xDDB846BC, 0x7A11F6B9, 0xFDF40EFC, 0xDDA8676C, 0x73BBED52, 0x69D3DF3F, 0x825A0597, 0xFE702C04, 0x80DFECAC, 0x7C282309, 0xA77864D6, 0x9E1635E0, 0x4064E46A, 0x8DCD9CDD, 0x4C9BD52B}, {0xD2834820, 0x8BB31A14, 0x5B1BA700, 0xFA6F74A3, 0x5A7963DA, 0x70AF02DF, 0x67A3EE05, 0xACF66316, 0xED8810E5, 0x6D9C3A9B, 0xDE5700F2, 0xCAA15C04, 0x1216D779, 0x70EC52DD, 0x52E4848F, 0x113195C5, 0x2A767B66, 0x045996B2, 0x08F38E9D, 0x871D34A1, 0x3BDB0114, 0x1A5BBAC6, 0x4FB89653, 0x0116C79A, 0xE1DDC68E, 0x47A1B243, 0x86F00C39, 0xC220C567, 0x7FE08843, 0x007C712F, 0xD1FFC893, 0x06351AA0, 0x9F560023, 0x62A98700, 0xF8D57BCE, 0xACFC3AF4, 0xA9DFB6A2}, {0x336F863F, 0x3A375259, 0xF5C6A327, 0x1E345224, 0xC372DD35, 0x2DB21041, 0x2911ACBF, 0x5388E8A1, 0x9E60D14F, 0xD9FFFBCF, 0xEBD01FC4, 0x65320FB5, 0xEA2A2A60, 0x9A7568DA, 0x4BB02D10, 0x4DDD9FB1, 0x4B65A72D, 0xFD7BDD39, 0xEA3B0F85, 0xB2E4375A, 0xC0427919, 0xCBB1E844, 0x2AAA5C33, 0xFEB4E727, 0x207A1F20, 0xA090CF8A, 0x5C727232, 0x5FECB8C3, 0x000B94E7, 0x76AB4A28, 0xB7213ABC, 0x12A89C26, 0xEEBE517D, 0x76CC2BC2, 0x03DE934C, 0x0DB13437, 0x2814CF39}, {0xF98981CE, 0x38D0C86B, 0x5E50A50F, 0xAC0B8790, 0x9894ACFF, 0x6F6B74D5, 0xC1BBE67C, 0x7AF6D00F, 0x8CAE8C82, 0xFCE050D0, 0xECC57D74, 0xE078F27F, 0xD65F00E2, 0xCB4270DA, 0x0AE340F3, 0x3331C02F, 0x1B7CD2C8, 0x15B73279, 0xDB320A68, 0x001E7A86, 0xE060BCFA, 0x8429DFAF, 0x493D40F3, 0x07907BBB, 0x5A265D96, 0x36D26EDC, 0xA44E4DF8, 0x4CD28267, 0xF06FA170, 0x91620626, 0x253AC674, 0xBFC9864F, 0xD2D88AF5, 0x629677B2, 0xE752AB2D, 0xF622F3E7, 0x43DD2A68}, {0xE46C53FD, 0xC42C1706, 0x660BDCBF, 0x8890B768, 0x80A67C66, 0x628E8B95, 0x9D8ACA7A, 0xBF062D7B, 0x75E415DD, 0x7F37BA75, 0x439A397B, 0x9D22952D, 0x4CC6A807, 0x411B21E0, 0x151C720C, 0x07F019AF, 0xF76792E1, 0x99450CE3, 0xBF921EF8, 0x581D7AFC, 0x78ED4C0E, 0xAD41E084, 0x767890DC, 0x78A245C4, 0x74E16729, 0x5225859E, 0x8806FEC8, 0xD1BE84C3, 0xBCA094F4, 0xB61610A1, 0x7F44F90F, 0xE5BF5E3C, 0xAC2B82CB, 0xBDA02D0D, 0xFE8113FF, 0x88385F45, 0x4DB9AE16}, {0x5EA26E30, 0xE788AEF2, 0xA9399CB3, 0x8166483B, 0x2645FE21, 0xD71CDF7A, 0xCE8E50E1, 0x6EA02194, 0xC7FA3D6E, 0xC708FD21, 0x2546BA0E, 0x94FF591D, 0xDE301CCC, 0x188AFC49, 0xDC3F5BB9, 0x69F21397, 0x865E7ABB, 0x58EDCE62, 0x48DBF1BD, 0x4E45747F, 0xF7BF50B6, 0xF83EC20E, 0x0C6DC058, 0xFFBC4448, 0xC7F6518A, 0x6D2F97DD, 0x15497CAA, 0x2B54167D, 0x6DB67369, 0xECB74B69, 0x2B7818FA, 0x381AC6C3, 0xF3FF9E14, 0xB13B0827, 0xBEF94E1A, 0x9D14B3BD, 0x9E6B0E64}, {0xC97DF2E3, 0x707DAC88, 0x9AFB9612, 0xF3C19831, 0xCBB71DED, 0xE28C99F3, 0x1B88CDB5, 0x4E6B5D08, 0xC8F9B95A, 0x4AF75C1F, 0x64987020, 0x866E0500, 0x76FA8B29, 0xA4D54A8C, 0x38CECD31, 0x73AE3B45, 0xD6B31263, 0x3ADFC51A, 0x97B8826F, 0xB1E561EB, 0xBA1E5902, 0x8A65F5AB, 0xFADE26F3, 0xD74D679B, 0xB6BD5834, 0x7B682E31, 0xC9401168, 0x8C255444, 0x6BFADC3C, 0x78A013A9, 0x92ED6649, 0x52C1BFEF, 0xDBC397A7, 0x37B3F311, 0xD75B948F, 0x2FED937E, 0x4724A822}, {0x498E4B2B, 0x31ADC5E5, 0xAEE46216, 0x062D5A01, 0xAB785ECE, 0x729F8425, 0xE0A49126, 0x770E4EF5, 0xAC968C3C, 0x6F80635A, 0x34D7142E, 0x8A236044, 0xA75DB49E, 0xF8BF2F60, 0x8993ECFA, 0xFD139627, 0x18A5B6D2, 0x45089B0E, 0xD0863D4D, 0x75BBFD75, 0x7D2BCC27, 0x19D49389, 0x129ABCFC, 0x78CD7D08, 0xE162E158, 0xBD4E65AD, 0x338BD0A5, 0x2E3702C6, 0x63B726CE, 0x17334EB0, 0xE01432B8, 0x0EBD97D6, 0x09EB3286, 0x9CD3BECE, 0x62EF89B0, 0x65228160, 0xB5955FBA}, {0xE5794628, 0x32B95161, 0x537EE11E, 0xBD46BFF2, 0x28A4E1A0, 0xBFAAB842, 0x034AD384, 0x8DEC7BB9, 0x9AEDDFE2, 0x18BA6C3B, 0x24FB1618, 0x7A0D674E, 0x6E9A4C16, 0xDA8E7078, 0xEB3E175B, 0x591FD375, 0x6698B75F, 0xD949D569, 0x2CDBB04C, 0x07E7FE4C, 0x50302076, 0x8E358F52, 0x73D792BF, 0x9A9C20FD, 0x0A16D061, 0x4085AB9E, 0x23BF06A1, 0xB3F8C223, 0xA7AD458D, 0x6FEA9A3D, 0x3F7CC0E3, 0xF430E240, 0x4AE4EA0F, 0x6C9FE91C, 0xB32D7B13, 0x4D926135, 0x77954D33}, {0x8D4DEA61, 0x059B2D8B, 0x63B97A54, 0xBC8437B8, 0x3BFA3A82, 0x91B59107, 0xBA2E40A9, 0x5FACA42E, 0xF377D74C, 0xA4BCFABC, 0x4B9F462B, 0x68C5BE21, 0x1737D6BA, 0x030569F2, 0x200629F6, 0xF872C87D, 0x92783E02, 0x85BDF641, 0x8BD4D0AD, 0xDF326677, 0x443DB3C2, 0x02353E34, 0xB9759C19, 0xBE029608, 0x3F48E101, 0x70B59FE7, 0x25B32129, 0x9B2774CE, 0x8D4F9DE3, 0xB4B38F33, 0x65D5E77F, 0x34E6E767, 0xBCFCBB81, 0xB86FF9F0, 0xD68313E6, 0x3C7F330B, 0x58EBB0C4}, {0x962534DE, 0xD43C0010, 0xA1276577, 0x9523283D, 0x2F98CF40, 0x54C45EEA, 0xB386C860, 0x2DB305F2, 0xF128C55D, 0x88138BBB, 0xFB139983, 0x7F71CD9F, 0x75074986, 0x5D6F0FF8, 0xF58FF8A4, 0xE96537A3, 0xC3B09F26, 0x737DCD6C, 0x8FFD581E, 0x9FC49B45, 0x2F13EA85, 0x63A6E555, 0xA4D85A94, 0x1974EA76, 0xF5DB0583, 0x59E0C514, 0xAACCA253, 0x88FA1E3D, 0xB0F2E158, 0x7DCDED4C, 0x2F3E02F6, 0x9D3D2401, 0x06A3E450, 0x9FF1B209, 0x8B5F2CD9, 0x3E49ED41, 0xB7469E24}, {0x244D1C44, 0x7109E99C, 0xE8AB44BD, 0xB8757397, 0xE03C8B8F, 0x964DD476, 0x3B17E99B, 0x3ADFC2FC, 0x16841685, 0x34DC1841, 0x60712879, 0xDED4FD68, 0xDCCB55AB, 0x437BCF50, 0x1DBAC670, 0x74612094, 0x9EEE2401, 0xCD3CD201, 0xF86F7563, 0x19F24161, 0x09E5D659, 0xCD920B92, 0xE6E709CC, 0x7E0DFDF7, 0x8A37BD95, 0x1DDB269C, 0x8A194C6C, 0x9360FC48, 0xF160A93E, 0x6BE0EA2B, 0x4BEB1D39, 0x94AF218A, 0x02807D3B, 0xC3039D44, 0x34F83B7D, 0x4CB8EE84, 0xC7B49EE6}, {0x7FD8A488, 0xAA50AEAC, 0x3BBC09F9, 0x0D6BCF62, 0x75DE5E1A, 0x27A2AA2E, 0x1E0E6778, 0xDBDAD274, 0x19D48B4C, 0x03FB284F, 0x07813D48, 0xCC1B638F, 0x6C54CC4F, 0x9D758586, 0x7DCA5ED2, 0x6B1BEC71, 0x5C290259, 0xE2C9A153, 0xC37E2808, 0x2D303C91, 0xEC29E6DC, 0x02C221FE, 0x16200655, 0x9CD178C2, 0x90B865B2, 0xF0085067, 0x69898A53, 0x64CCD518, 0x915C2D15, 0xE2C688DF, 0x3A8E9475, 0xEE619A24, 0x39AE75A9, 0x31CDFECA, 0x99144079, 0x26C9A62E, 0x92119094}, {0x3FF53D66, 0x0FAACF12, 0x790170D3, 0x7948B7BB, 0xCC34309D, 0xA5A63240, 0x14DD44B5, 0xE0F20471, 0xE6865375, 0xFD595A36, 0xCE990BDA, 0x12C95E92, 0x5B06F963, 0x7D955183, 0x872B3654, 0x8D0665E4, 0xFC279DED, 0x4D5EF6BE, 0x9AD0C205, 0x3EDE3B65, 0x2A1AADF2, 0x835098B5, 0xB7E8D066, 0x068D3716, 0x7A8B483D, 0xC910922C, 0xC36F0FBB, 0xC43B2F63, 0xCCA819D1, 0x9E3E7C00, 0x3170DC11, 0x6D086538, 0xEC88005D, 0x00AED685, 0xA938B7A5, 0x452432B4, 0xC2780F91}, {0x0F024247, 0x951ED321, 0x6D49574F, 0x598CAAED, 0xD09C0B49, 0x6B55D201, 0xE7F9E2DA, 0xC26ABD16, 0xC4C1A7EB, 0x1791D6A5, 0xB3637B71, 0x2A17657E, 0x95EE8417, 0x6E13CA76, 0x953BE33D, 0x888A1412, 0xFBDFB22C, 0x5409D489, 0xDFFCB1FD, 0x5C85CF46, 0x68E3F41F, 0x10916344, 0x3920DF7A, 0xD573D166, 0xA7C012AD, 0xCD21A277, 0xF340CAFC, 0xF1FD0E17, 0xD486AD06, 0x458ED915, 0x6DF127C9, 0xEDDF5E52, 0x5815AB3C, 0x32904192, 0xD5BF6802, 0xE8BC2880, 0xE3E01AE2}, {0xF7969B39, 0x607E7701, 0xDE888A4D, 0x0C6163FB, 0x5D397EBF, 0x67B4D2A7, 0x085780A8, 0xC732C810, 0xE1E79EDF, 0xFBE072A5, 0x1FF90795, 0xD525CE15, 0x467725B1, 0xA003D89E, 0x4A845D2B, 0x6A8907DB, 0xB985A881, 0x2DE6E8AB, 0xB9FBBD44, 0x9D39DDBA, 0xB19A67FB, 0x78CBA1D7, 0x9B1C704D, 0x883EF871, 0x8BAEF511, 0x6D62D532, 0x2B693923, 0xE133B2AE, 0x868AA2B5, 0x531AD5DE, 0x2A9C4298, 0x696AE1AC, 0x1C2AB4F3, 0x3714E891, 0x0859CA95, 0xB9A49E56, 0xD344189F}, {0xDBA34A46, 0x525E2F5D, 0x425AC32C, 0x5C8C2998, 0x857A327F, 0xBBAD7F54, 0xDF0B977B, 0x30A8F52B, 0x5D5A87ED, 0xF3FF5165, 0x04028D39, 0x2A013C6B, 0x99864956, 0x4C92514D, 0x9B0F688A, 0xA9B3862B, 0x6090BC63, 0x8CB6F3F6, 0xFC104E02, 0x79D74F76, 0x45098B12, 0x1EC99EBB, 0x0B25C8E2, 0x760375BB, 0xB370E685, 0x22615F26, 0x52FC67B5, 0x7DA33688, 0xB8255106, 0x7A05EF2F, 0x373CFB3B, 0x290A077E, 0x43C0B57D, 0x4A370821, 0x064C1B0D, 0x8BDB6399, 0x97071926}, {0x48AD399F, 0x0787CCA3, 0x6E1B8AF8, 0x97282AD3, 0x14EB25B8, 0x686A15E1, 0xD3C7487B, 0xB4029D97, 0x1EB7AB3B, 0x25B9E580, 0xE089C35E, 0xF296B4CA, 0xBA9A3888, 0x4ACD6363, 0x3F4857E0, 0xEA0E6553, 0xD58EB585, 0x707C9C27, 0x2F07A081, 0xC4E55800, 0x2D97C374, 0xF13FB446, 0x5A05256E, 0x0C83AB1D, 0xB3E2C494, 0x42D49027, 0xF5291785, 0x278BE1A4, 0x72D15DC4, 0x45AB3260, 0xC083C6A0, 0xFCD1863E, 0x2EDF9796, 0x4392C20E, 0x4862EA8D, 0xCF403752, 0x49D2AD36}, {0x279950BE, 0x53EC6405, 0x96165890, 0xB091A77B, 0x1CE39EA2, 0xDC46972E, 0x480C0B39, 0x79DD8A2E, 0x215FF5BB, 0x1B6A6B0C, 0x9E5501C9, 0x5008030B, 0xAB667687, 0x1763B54F, 0x104DCD25, 0xAFFAFFAF, 0x42B8FB93, 0x6161C266, 0xBBD17E3B, 0x3359C8E8, 0xA4B9F194, 0x67D1CE13, 0xC1B04259, 0x2E70E492, 0xDC5504AC, 0x07D7E04B, 0xB9EFE988, 0xDCF3C85B, 0x426DB7D8, 0xB9EE2CF9, 0x258AC253, 0xA2D138DF, 0x57190F78, 0xEFE2E960, 0xF669F638, 0xAD0D122D, 0x586FF633}, {0x3AA445C5, 0x82121A38, 0xA53708B0, 0x65EBB7A7, 0x7E40F2A0, 0xD45C01E0, 0x4C135B64, 0x4483C683, 0x8B908363, 0x3060F6F4, 0x8DD7B5FA, 0x110EFCED, 0x7217D5C9, 0x1F42CA09, 0xA45A6A01, 0xF45068D3, 0x899DA5D3, 0x8D9C2A6E, 0xD6BBAC2E, 0x10DF6E91, 0x49FBC07B, 0x1B6BBFBF, 0x5916C6F2, 0x3CA37EE1, 0x561EA9D4, 0xCEEFDA2C, 0x05E82C9E, 0xB8B64F9A, 0x5B8E38A4, 0x3CA4266A, 0x816927C6, 0x4E3933DC, 0x85F8A507, 0xD07445B3, 0x2C4C169B, 0x6A2C6C33, 0xF80E95C6}, {0x10668FFE, 0xABDD162E, 0x065E1F2A, 0x41D00404, 0x9FDA8555, 0xB78413E6, 0x038AEEE2, 0x8CCF48C2, 0xB67099FD, 0x7FAA17E1, 0x02159424, 0x86C66F3E, 0x85F81B0A, 0x5D6EE998, 0xEDF1CBEC, 0xD0853AC9, 0x15D68A47, 0x930249D4, 0x421CF02D, 0xA2474696, 0xDBCAA082, 0x71DD02F7, 0x419C99D9, 0x6C2EB812, 0xC55577DF, 0x46E2C20E, 0x12F8C3D2, 0xF51C5CDD, 0x638C6841, 0xFD41B200, 0x874010CB, 0xEA7691C8, 0xAFCFE37F, 0x67F61CE6, 0x19004414, 0x0FD9CD59, 0xCB4074DC}, {0xDE9227D2, 0xB3795C38, 0x962A57AA, 0xC0E6A70F, 0xDAC95877, 0xA294F421, 0xBAAB6840, 0xC2BC1EA8, 0x801778B0, 0xE654E1B0, 0xF355C3D7, 0xC1F9C216, 0xBE234AE7, 0x76F738D5, 0x3892A48A, 0xD43E12FA, 0x3AF53B97, 0xFA7FB3EA, 0xC2CE1C25, 0xE80C854D, 0xDD5D55BA, 0x19CAC0B3, 0x70E634CA, 0x31D75E04, 0x511CDEE9, 0x8328D6B4, 0x09DE4759, 0x345B879D, 0x8DA9C94D, 0x1EE4004E, 0x759316E6, 0xA8491E35, 0x6445CCB8, 0x15B6F7E8, 0xCB639A2C, 0xEBE83DBD, 0x90AF65E6}, {0xF4CA0086, 0x09DA11C5, 0x6C94C74D, 0x5C5E3080, 0xB7DF63A7, 0x5F212E84, 0xF32BACDC, 0xA446472C, 0x65814C27, 0x4417784A, 0x47D4D043, 0x179BA479, 0x74D39DA2, 0xDBDC4A4C, 0x2619ADC3, 0xF6D44E53, 0x33714F0A, 0xA2488ACF, 0x3B0971B3, 0x8A7DC9ED, 0x9B3CA3EE, 0xDFD95018, 0x6CB74E4B, 0xFE088ED7, 0xE685BD03, 0x8D3CD380, 0x93B25780, 0x8556CDE9, 0x24D9AC0F, 0xF727F9FC, 0x1E31F736, 0xB232B542, 0x85357F85, 0x25076674, 0x4D02443F, 0x98313DD6, 0xE69659EC}, {0xF6843837, 0x91E6E323, 0xA7044159, 0xFC084237, 0x83B46317, 0xEEC42D73, 0xF887CE2A, 0xB867CBFB, 0x1048E50A, 0xDC531AA9, 0x5196D992, 0x9ADC4932, 0xD7B39954, 0xD1E5368F, 0x3965BAA3, 0x798CC085, 0xF5463286, 0x0CA49F86, 0xFAED57A4, 0x1662BD6A, 0x465880D5, 0x3DCEC41E, 0x6E0B831A, 0x14A220B2, 0x4559F9AE, 0x39EC421F, 0xB9757889, 0x5B7AC1BE, 0xF6B93106, 0xE18E0A82, 0xCFD2409A, 0x11EB2351, 0x5F8C898C, 0x51B7D124, 0xFE8213F5, 0xEF315329, 0x48065118}, {0xFDEA39E4, 0xFC060DE0, 0x27F056DF, 0x3D412695, 0x557B6E30, 0x1053AB0E, 0xD8F2D8A1, 0x8033EB16, 0x4D9F8252, 0x92DB5EB6, 0x652124DD, 0x30D35B8B, 0x3BFC52BD, 0x5142E79C, 0x46C4A360, 0x58E7F1A2, 0x60A2489E, 0x15EB320F, 0x2E206A72, 0xC3D3D391, 0x20B00E02, 0x8FCF90E0, 0xA040B0E5, 0x9F6EB05C, 0x7A29BB05, 0x1EEEE732, 0xA1CD3E44, 0x5A8AE34A, 0x7FC98E40, 0x9D1361FE, 0xA76FA685, 0xBD825724, 0xCBED467E, 0x25CCC97D, 0x0C6DAED7, 0x04F9B50B, 0xB3FC465E}, {0xA1E9ED49, 0xBD52045C, 0x6FC6321C, 0xB3D8CAFB, 0x9675AB8B, 0x5B92E81F, 0x927BBBD0, 0xBD651670, 0xDB23F118, 0x648AB78E, 0x8A9663CE, 0xEC8D4E2D, 0x977976D9, 0x0BE30247, 0x79451F8D, 0xDC985389, 0x02830FD5, 0x62CADFA6, 0x176DC515, 0xF261AAAF, 0xB74EAD64, 0x108DC582, 0x92843B18, 0x0DC14C32, 0x60685DE2, 0x558C7F82, 0xC4BB0A82, 0xAB33A47F, 0x3BC99611, 0x2BA78298, 0xE6970964, 0x41296FC5, 0x299C2548, 0xB7FDCD2A, 0xFEB4097E, 0xBED156C2, 0xCC458AEB}, {0x678782BA, 0xE609F550, 0xDB413C47, 0xAFF47725, 0xF0EDE797, 0x3F22BA40, 0xA858550B, 0x3CE3F3DE, 0x1EB0737C, 0x89D7C765, 0x6BF2898C, 0x3149D8E5, 0x170E5471, 0x1B531BE7, 0x46F341D1, 0x67B9D033, 0xB777E210, 0xA0030F60, 0x004C65FA, 0xF45F4906, 0x6AACD5F2, 0x3DFC77AF, 0xF23FDE19, 0x873A25C1, 0xCDCCE709, 0x46039BF5, 0x7C80C056, 0x2C7F2015, 0x54E4C8D0, 0xA3EBAC3C, 0x34E51E4B, 0x7A9A2408, 0xDD077383, 0x5C139470, 0xDFC431C0, 0x4BD6C7A3, 0x24BE74D6}, {0x907FB31B, 0xB2E9015B, 0x6AC9D8E9, 0xB293E235, 0x1F163074, 0xF6EE902C, 0xF45831C6, 0x00A140ED, 0xB3485BB9, 0x76AC8E58, 0xD5E9BA0F, 0x1EFF75C2, 0x418B67A0, 0xE43FEE88, 0xE4D04FD0, 0x8661A694, 0x30AADC99, 0x86DF6C37, 0xFDAB09CD, 0x78EAE5B4, 0xA0853281, 0xA15D0DEB, 0xC46B5D12, 0x8D2CFB47, 0xA79F9BD5, 0xFCBCA89F, 0x0615B8DD, 0x53E2734B, 0xCA9C2F8B, 0x7240F139, 0xF3533D4D, 0x82E611CE, 0x040D1675, 0x53B62A44, 0xB6D6ED64, 0x60A78388, 0xEBA54BBD}, {0xB51B412E, 0x7C35E35B, 0xB639210E, 0x23F2693B, 0xD4CD19BA, 0xB0EE647A, 0xB726C1F6, 0x905D60B1, 0xF04E7ED2, 0x2426915F, 0xEECCC94C, 0x4C3E330B, 0x13826C9C, 0x9964F7DE, 0x3334544A, 0x4FFCA9AB, 0xE8EE0B55, 0x233C24A3, 0x6221B29F, 0xA977BB4F, 0xF6620B48, 0xD6E41FCC, 0x64D53A97, 0x98D3F870, 0x3C4BF89F, 0xC6F26354, 0xC1FA36D7, 0xF0D3F20A, 0x54145C69, 0x39898169, 0x7D1EB796, 0x08C7CCF1, 0x54DAB192, 0x70CB8984, 0xCA81E7B3, 0x26B5179A, 0x38BD2380}, {0x11164ABA, 0x1E157B1C, 0x8F33977D, 0x75BE4C72, 0xEDAF817F, 0x2BC84FAB, 0xD26332B7, 0x0F6B7604, 0x39A4BB17, 0x60870C55, 0xAF809D3C, 0x5F20658E, 0xFC57A8A2, 0x5463055C, 0xCF9D841A, 0x60693904, 0x3EFA8818, 0xA0C6D057, 0x4EEEEBF6, 0xFA9E8465, 0x6B0F3B99, 0xC4AD3B5B, 0xB70D55A6, 0xB16600B1, 0xFD1B2D93, 0x8184BC2C, 0xBB45115C, 0x95AD621F, 0x998F4BE0, 0x57E469B8, 0x1D9D6947, 0x1739FDD2, 0xAC2F5207, 0x09A72355, 0x102C7990, 0xB36F38E8, 0xAEE3F95E}, {0xF0BE5584, 0xE3BAC577, 0xA67C271F, 0xFE8AD256, 0x6557E671, 0x82900BD2, 0xD8989856, 0xC2F66CDB, 0xB3D9C85C, 0x12721679, 0x3ED9E157, 0x353B5D80, 0x01139C46, 0x2D8293C9, 0x50E84CD3, 0xA200796F, 0xE920F2B5, 0x0FEA17AB, 0x37AF7CC0, 0xA5C1A47D, 0xE432E5E5, 0x652244B4, 0x3B3F9B37, 0xB45A46A9, 0x6C5C102F, 0x8AAD0736, 0x17CDA8B5, 0xE1CE973D, 0xF26987DE, 0x44F60361, 0xE02BB20C, 0x47A7C27C, 0x071A4F93, 0x322DD615, 0xF90C5A41, 0x23E51C22, 0x6168FE01}, {0xCBC7FD98, 0xC5D2E0F2, 0x6125DE3D, 0x8945FCDA, 0x3860E540, 0xF3D2C799, 0x818D4B65, 0x8EEF66FD, 0x7B329435, 0x9953BFEF, 0xE823AF52, 0xA2B97B26, 0x3EC9D193, 0x40734D58, 0xE9E571AC, 0x4D83C5A4, 0x3BAB0D12, 0x11437879, 0x598BEC34, 0xA3F118D1, 0xE52DCCDD, 0x35EC08DE, 0x9EA69A46, 0xAE28E4CE, 0x9F32658F, 0x107F53F5, 0x7276E445, 0x716D66ED, 0xF5E2E825, 0x1A0D1A43, 0xE8B36C19, 0x867D3FC4, 0xC64C1882, 0xEA2ECBC2, 0x901E929A, 0xDA847CC8, 0x2AFF7969}, {0x9F9F67F4, 0x0D46956C, 0xF4A7C477, 0x21B98410, 0xBD1D7BE4, 0x791A5DF3, 0xC3E5D38C, 0xD93B36DB, 0x4552C062, 0x4BEE6B1F, 0xD021B6EB, 0x33B8E793, 0xBA9DC9CB, 0xADEC6B19, 0x81486D28, 0xD33A27D1, 0x8A7F6F7B, 0x10CDA228, 0xA12790B0, 0x9F751D20, 0x40AB17BC, 0x0760B657, 0xA34D3688, 0x7F85B329, 0x70AA1876, 0xE1A109A2, 0x7231E067, 0x68801124, 0x7C7D22EA, 0xAE92C39C, 0x6F98EEB4, 0x8EEB4ABF, 0xBFB8C8C7, 0xB15DCC46, 0x61F60440, 0xAC7BE5A7, 0x5AA1402E}, {0x342415DD, 0x1D3B1C22, 0xBB19BA2F, 0xC58DC5B0, 0x11B36D5B, 0xB5B67B50, 0x6C01EED5, 0xB1610BFC, 0x05F23A4A, 0x474CE3E5, 0x08BE4B69, 0xCAB4A0DB, 0x290AA645, 0x97EE09AB, 0xA21A05FF, 0x7E803EDF, 0x3692A08B, 0xDA49464C, 0x233C62ED, 0x2B8BD2CB, 0x2BB1C60D, 0x984D9AA4, 0xD2B7DB97, 0xF7991BE9, 0x9558DB93, 0x7248EC4B, 0xB12D0831, 0xA85DDF18, 0x0B27B05B, 0x2B6DFE29, 0x0E1462F0, 0xC9CC99AF, 0xFF89F292, 0x30BEE433, 0x0D04BE76, 0x3CD3EFCB, 0x7A68D00F}, {0x2AB9FD4E, 0xD388FBE6, 0x0815DCCA, 0xCA773140, 0x5F72763F, 0x5AD1581E, 0x61282867, 0x3932B16C, 0xB17E4429, 0x06001140, 0xBB3F2DD6, 0x747A1C9E, 0xECB29646, 0x1CF17CD5, 0x0F909FAF, 0x6E6764B0, 0xBDB4E233, 0x77A835BB, 0x1D49A8C6, 0xE0A0C588, 0x01169042, 0x8D0136C4, 0x21037751, 0x30902A5D, 0x59357B03, 0x2AF8CA37, 0x1AC84486, 0x6B7ADA98, 0xCA6934F4, 0x1E16C29E, 0xE9B91DDD, 0xB3204082, 0xB194000A, 0xAC8E3D27, 0x8AD441F1, 0x906B6DCF, 0x97265F85}, {0x2E5A58D9, 0x6BDA61D6, 0x05DF64D0, 0xA2B97225, 0x25798FAF, 0x9C65625B, 0x65A6AE07, 0x04CB7F39, 0xA527774C, 0x33859061, 0xAD320F04, 0xF3218C5F, 0x0DDA64DC, 0x2827BE8B, 0x7C77F660, 0x7A4C3BBF, 0xFE927CB4, 0x190C280F, 0x42B634F5, 0xDEB84CE0, 0xF05DC4E8, 0x5FB57455, 0xF6F30E95, 0x377D41E9, 0x3215BA39, 0x1725E820, 0xBFA8A318, 0x2FBF89D7, 0x33DA7C71, 0xB26EC1F2, 0xA4DA15A4, 0x8000A783, 0xAB8587D4, 0x1806E80C, 0x03D1E2A1, 0x4348B12D, 0x18F4BF3C}, {0x14389E67, 0x5016EEEC, 0x76B6F802, 0xE3840C8E, 0x2BF72A9B, 0xF1EF0C56, 0x8B630051, 0xD553E09C, 0x2B0FB4ED, 0xD37DF1B2, 0xC999CB73, 0xAB86E2E2, 0x9624180C, 0x06947CFB, 0x3FBF289D, 0x2F374651, 0xA913A1E2, 0xCEDE77B6, 0xD077929D, 0x958FA4E8, 0x3054F6A8, 0x96DB8CC9, 0xABF35F54, 0x03F4F512, 0xD40A434B, 0xA92F1DB9, 0xDFC9431B, 0x88A7008B, 0x891F4942, 0xC76BEBE1, 0xEF3E21D4, 0x5BDD570A, 0x45C0C894, 0x59DA07B7, 0xA48C011E, 0x3E82589F, 0x6F9F4EA0}, {0x0EF7CBC4, 0xE4846CA8, 0x369D90E4, 0xF0B8B768, 0xDE0498B8, 0xAC998767, 0xCB8C3020, 0x32AFC1E6, 0x761113D4, 0x644D556F, 0xCA53911E, 0x43C12E68, 0x514A9448, 0xA42C3D3E, 0x22396BAF, 0xADB1AADC, 0x371F9A3E, 0x5B93123A, 0xDD32ECC7, 0xB1333F88, 0x961AABAE, 0x1F52C631, 0xC102AD12, 0x6D51F880, 0x6967E3E8, 0xC2C9120D, 0x54049859, 0xD564EE7E, 0x2259051C, 0xA4D94C7D, 0xCE7724D5, 0xFD8A5B70, 0x4C4A2794, 0x86676797, 0x0EFD17A1, 0xA61D8DD2, 0xA68F774A}, {0xB2E07D39, 0x7C8670B6, 0x5DFABCF0, 0x526C8C2D, 0x4053E94D, 0x818563BB, 0x3EA42129, 0x3353FB57, 0x92C75C7E, 0x046C5D38, 0xB054331C, 0x3797AD10, 0xBB392667, 0x517B1A0C, 0xCBE0E6E7, 0x402FD418, 0x1DA297A2, 0xC657C508, 0x0308BB0C, 0x46E8F3A5, 0x4B7EB7F5, 0xEDB4D83A, 0xD430D0C7, 0x00D30EDA, 0xCBB4E36B, 0xBF98C913, 0x83600293, 0x217B73DF, 0xA2B07FF9, 0xC57989F7, 0x8DBD48EE, 0x4BA283CA, 0x4395C8AE, 0xB955ABB0, 0x1F003456, 0x72CC786A, 0xFF80AFDC}, {0xE7DFD8A9, 0xA0C938EB, 0x2590445F, 0xD967BB6E, 0x2686734E, 0x7959B9F2, 0x091517CE, 0x28D7115E, 0x46904894, 0x9581AD38, 0x0EDC248D, 0x9C738C76, 0x3E02CD68, 0xC463760D, 0xFA387D69, 0x70FCF8FC, 0xA7C5EB2F, 0xF7CECB25, 0xE85DF7B5, 0x844C8F74, 0xB54B0E56, 0x954868BA, 0x9F06B3B4, 0xF0BE675D, 0x9DE1DD9E, 0x5EACB7A9, 0x1BF61CDE, 0x6B58D57B, 0xA60C60AC, 0x04F50D0D, 0xCD947E88, 0xDAAF407B, 0x403D6F08, 0x7F014E16, 0x926C1BC1, 0xDD30B3E8, 0x1A986C11}, {0xAA930E29, 0x848683C9, 0xE3AA7B87, 0x3BE5B89D, 0xD39DC7B4, 0x30E7C58C, 0xF931E1AD, 0xA2783313, 0x20672D65, 0x3F5F6F1F, 0x4DAEE61A, 0xA8E34D70, 0x34779795, 0x74649E22, 0x7F9C9D2F, 0x3840CF0A, 0x0ABA5004, 0x1033B6E5, 0xE4350FF0, 0x0068F852, 0x3180E3A2, 0x320AF903, 0x17AE2116, 0xE0C5E6B5, 0x1DABCF69, 0xE721EE3C, 0x4D60FD82, 0xC95CAC40, 0x6D43DA02, 0x1EBE34A9, 0xD58396AD, 0x13A5DBAC, 0xF4681DFF, 0xDAC4A329, 0x3F7FA690, 0x5A472781, 0x2E082433}, {0x08497910, 0x0B5E2FA0, 0xA4DFA944, 0x6AD7A8E8, 0x7918042C, 0x453E22B8, 0x1FA5094B, 0x4B71A3C9, 0x258D12AB, 0xE71D1E8B, 0x4515C213, 0x5D50E264, 0xD223F155, 0x40F5B3A5, 0x76EDE533, 0x697792CA, 0x348677EF, 0xE19B319D, 0x4441B1EA, 0xCF270DDD, 0xAE1CF7F4, 0xE39D11F3, 0xF90BEA58, 0x702FBB25, 0xD1C6F588, 0x2F4D111E, 0x06B705BC, 0x518B5A78, 0x2B697EFE, 0x4051AD14, 0xA2035F8A, 0x32E3CE3E, 0xF0B18866, 0xCE00C274, 0xCDF904F0, 0x78064A99, 0x1424378D}, }; /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/hmac-openssl.c0000644000000000000000000000013214505005532022065 xustar000000000000000030 mtime=1695812442.433982059 30 atime=1695812445.794030182 30 ctime=1695812494.582728934 yadifa-2.6.5-11201/lib/dnscore/src/hmac-openssl.c0000664000374500037450000001514514505005532022035 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup hmac * @ingroup dnscore * @brief * * @{ */ #include "dnscore/dnscore-config.h" #include "dnscore/zalloc.h" #include "dnscore/hmac.h" #include "dnscore/logger.h" #include "dnscore/openssl.h" #include #ifndef SSL_API #error "SSL_API not defined" #endif #define LOG_HMAC_OPENSSL 0 // 1 2 3 #if SSL_API_LT_110 // ie: 0.9.x struct hmac_openssl_t { const struct hmac_vtbl *vtbl; HMAC_CTX hmac; }; #else struct hmac_openssl_t { const struct hmac_vtbl *vtbl; HMAC_CTX *hmac; }; #endif typedef struct hmac_openssl_t* hmac_openssl_t; static HMAC_CTX* hmac_openssl_hmac(tsig_hmac_t hmac) { #if SSL_API_LT_110 // ie: 0.9.x return &((hmac_openssl_t)hmac)->hmac; #else return ((hmac_openssl_t)hmac)->hmac; #endif } static const EVP_MD * hmac_get_EVP_MD(u8 algorithm) { switch(algorithm) { #ifndef OPENSSL_NO_MD5 case HMAC_MD5: return EVP_md5(); #endif #ifndef OPENSSL_NO_SHA case HMAC_SHA1: return EVP_sha1(); #endif #ifndef OPENSSL_NO_SHA256 case HMAC_SHA224: return EVP_sha224(); case HMAC_SHA256: return EVP_sha256(); #endif #ifndef OPENSSL_NO_SHA512 case HMAC_SHA384: return EVP_sha384(); case HMAC_SHA512: return EVP_sha512(); #endif default: return EVP_md_null(); } } /** * Allocates an HMAC_CTX * This layer has been added for openssl-1.1.0 compatibility */ #define HMACCTX_TAG 0x58544343414d48 /** * Frees an HMAC_CTX * This layer has been added for openssl-1.1.0 compatibility */ static void hmac_openssl_free(tsig_hmac_t t) { hmac_openssl_t hmac_openssl = (hmac_openssl_t)t; #if SSL_API_LT_110 HMAC_CTX_cleanup(hmac_openssl_hmac(t)); #else HMAC_CTX_free(hmac_openssl_hmac(t)); #endif ZFREE_OBJECT(hmac_openssl); } static void hmac_openssl_reset(tsig_hmac_t t) { HMAC_CTX *hmac = hmac_openssl_hmac(t); #if SSL_API_LT_110 HMAC_CTX_cleanup(hmac); HMAC_CTX_init(hmac); #else HMAC_CTX_reset(hmac); #endif } static ya_result hmac_openssl_init(tsig_hmac_t t, const void *key, int len, u8 algorithm) { #if LOG_HMAC_OPENSSL != 0 // not a boolean log_debug("tsig_hmac_init(%p, %p, %i, %i)", t, key, len, algorithm); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, key, len, 32); #endif const EVP_MD *evp_md = hmac_get_EVP_MD(algorithm); if(evp_md != NULL) { HMAC_CTX *hmac = hmac_openssl_hmac(t); if(hmac != NULL) { int ret; #if SSL_API_LT_100 ret = HMAC_Init(hmac, key, len, evp_md); #else ret = HMAC_Init_ex(hmac, key, len, evp_md, NULL); #endif if(ret == 1) { return SUCCESS; } } } return ERROR; } static int hmac_openssl_update(tsig_hmac_t t, const void *data, size_t len) { #if LOG_HMAC_OPENSSL != 0 // not a boolean log_debug("tsig_hmac_update(%p, %p, %i)", t, data, len); #endif #if LOG_HMAC_OPENSSL >= 3 log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, key, len, 32); #elif LOG_HMAC_OPENSSL >= 2 if(len <= 64) { log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, data, len, 32); } else { log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, data, 32, 32); log_debug("..."); const u8 *data_byte = (const u8*)data; log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, &data_byte[len - 32], 32, 32); } #endif #if SSL_API_LT_100 HMAC_Update(hmac_openssl_hmac(t), (const unsigned char*)data, len); return 1; #else int ret = HMAC_Update(hmac_openssl_hmac(t), (const unsigned char*)data, len); return ret; #endif } static int hmac_openssl_final(tsig_hmac_t t, void *out_data, unsigned int *out_len) { #if SSL_API_LT_100 HMAC_Final(hmac_openssl_hmac(t), (unsigned char*)out_data, out_len); #if LOG_HMAC_OPENSSL != 0 // not a boolean log_debug("tsig_hmac_final(%p, %p, %i)", t, out_data, *out_len); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, out_data, *out_len, 32); #endif return 1; #else int ret = HMAC_Final(hmac_openssl_hmac(t), (unsigned char*)out_data, out_len); #if LOG_HMAC_OPENSSL != 0 // not a boolean log_debug("tsig_hmac_final(%p, %p, %i)", t, out_data, *out_len); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, out_data, *out_len, 32); #endif return ret; #endif } static const struct hmac_vtbl hmac_openssl_vtbl = { hmac_openssl_update, hmac_openssl_final, hmac_openssl_reset, hmac_openssl_init, hmac_openssl_free }; tsig_hmac_t tsig_hmac_allocate() { hmac_openssl_t hmac; ZALLOC_OBJECT_OR_DIE(hmac, struct hmac_openssl_t, HMACCTX_TAG); hmac->vtbl = &hmac_openssl_vtbl; #if SSL_API_LT_110 // ie: 0.9.x HMAC_CTX_init(&hmac->hmac); #else hmac->hmac = HMAC_CTX_new(); #endif return (tsig_hmac_t)hmac; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/host_address.c0000644000000000000000000000013214505005532022156 xustar000000000000000030 mtime=1695812442.504983076 30 atime=1695812445.797030225 30 ctime=1695812494.584728963 yadifa-2.6.5-11201/lib/dnscore/src/host_address.c0000664000374500037450000007741714505005532022140 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoretools Generic Tools * @ingroup dnscore * @brief host address (list) functions * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include "dnscore/host_address.h" #include "dnscore/tsig.h" #include "dnscore/zalloc.h" #include "dnscore/format.h" /*------------------------------------------------------------------------------ * FUNCTIONS */ host_address *host_address_alloc() { host_address *new_address; ZALLOC_OBJECT_OR_DIE( new_address, host_address, HOSTADDR_TAG); new_address->version = 0; new_address->next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT new_address->tsig = NULL; #endif return new_address; } /** * Clears the content of a host_address (mostly : deletes the dname if it's * what it contains. * * @param the host address */ void host_address_clear(host_address *address) { if(address->version == HOST_ADDRESS_DNAME) { free(address->ip.dname.dname); } address->version = 0; } /** * Deletes a host addresse * * @param the host address */ void host_address_delete(host_address *address) { if(address->version == HOST_ADDRESS_DNAME) { #if DEBUG memset(address->ip.dname.dname, 0xff, dnsname_len(address->ip.dname.dname)); #endif free(address->ip.dname.dname); } #if DEBUG memset(address, 0xff, sizeof(host_address)); #endif ZFREE_OBJECT(address); } /** * Deletes a list of host addresses * * @param the first host address in the list */ void host_address_delete_list(host_address *address) { while(address != NULL) { host_address *next = address->next; host_address_delete(address); address = next; } } host_address * host_address_copy(const host_address *address) { host_address clone_head; #if DEBUG memset(&clone_head, 0xff, sizeof(clone_head)); #endif /* no need to set TSIG */ clone_head.next = NULL; clone_head.version = HOST_ADDRESS_NONE; if(address != NULL) { host_address_append_host_address(&clone_head, address); // copy made, or may fail if address is not supported } return clone_head.next; } host_address * host_address_copy_list(const host_address *address) { host_address clone_head; #if DEBUG memset(&clone_head, 0xff, sizeof(clone_head)); #endif /* no need to set TSIG */ clone_head.next = NULL; clone_head.version = HOST_ADDRESS_NONE; host_address *clone = &clone_head; while(address != NULL) { if(ISOK(host_address_append_host_address(clone, address))) // copy made, or may fail is address is not supported { clone = clone->next; } address = address->next; } return clone_head.next; } u32 host_address_count(const host_address *address) { u32 n = 0; while(address != NULL) { n++; address = address->next; } return n; } ya_result host_address2allocated_sockaddr(const host_address *address, struct sockaddr **sap) { switch(address->version) { case HOST_ADDRESS_IPV4: { struct sockaddr_in *sa_in; MALLOC_OBJECT_OR_DIE(sa_in, struct sockaddr_in, SOCKADD4_TAG); // no ZALLOC ZEROMEMORY(sa_in, sizeof(struct sockaddr_in)); memcpy(&sa_in->sin_addr.s_addr, address->ip.v4.bytes, 4); //sa_in->sin_addr.s_addr = htonl(sa_in->sin_addr.s_addr); sa_in->sin_port = address->port; sa_in->sin_family = AF_INET; #if HAS_SOCKADDR_IN_SIN_LEN sa_in->sin_len = sizeof(struct sockaddr_in); #endif *sap = (struct sockaddr*)sa_in; return sizeof(struct sockaddr_in); } case HOST_ADDRESS_IPV6: { struct sockaddr_in6 *sa_in6; MALLOC_OBJECT_OR_DIE(sa_in6, struct sockaddr_in6, SOCKADD6_TAG); // no ZALLOC ZEROMEMORY(sa_in6, sizeof(struct sockaddr_in6)); memcpy(&sa_in6->sin6_addr, address->ip.v6.bytes, 16); sa_in6->sin6_port = address->port; sa_in6->sin6_family = AF_INET6; #if HAS_SOCKADDR_IN6_SIN6_LEN sa_in6->sin6_len = sizeof(struct sockaddr_in6); #endif *sap = (struct sockaddr*)sa_in6; return sizeof(struct sockaddr_in6); } default: { return IP_VERSION_NOT_SUPPORTED; /* unsupported ip version */ } } } ya_result host_address2sockaddr(const host_address *address, socketaddress *sap) { switch(address->version) { case HOST_ADDRESS_IPV4: { struct sockaddr_in *sa_in = (struct sockaddr_in*)sap; ZEROMEMORY(sa_in, sizeof(struct sockaddr_in)); memcpy(&sa_in->sin_addr.s_addr, address->ip.v4.bytes, 4); sa_in->sin_port = address->port; sa_in->sin_family = AF_INET; #if HAS_SOCKADDR_IN_SIN_LEN sa_in->sin_len = sizeof(struct sockaddr_in); #endif return sizeof(struct sockaddr_in); } case HOST_ADDRESS_IPV6: { struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6*)sap; ZEROMEMORY(sa_in6, sizeof(struct sockaddr_in6)); memcpy(&sa_in6->sin6_addr, address->ip.v6.bytes, 16); sa_in6->sin6_port = address->port; sa_in6->sin6_family = AF_INET6; #if HAS_SOCKADDR_IN6_SIN6_LEN sa_in6->sin6_len = sizeof(struct sockaddr_in6); #endif return sizeof(struct sockaddr_in6); } default: { return IP_VERSION_NOT_SUPPORTED; /* unsupported ip version */ } } } void host_address_set_default_port_value(host_address *address, u16 port) { /* set the default port on any unset port */ while(address != NULL) { if(address->port == 0) { address->port = port; } address = address->next; } } void host_address_set_port_value(host_address *address, u16 port) { /* set the default port on any unset port */ while(address != NULL) { address->port = port; address = address->next; } } ya_result host_address2addrinfo(const host_address *address, struct addrinfo **addrp) { struct addrinfo *addr; ya_result ret; MALLOC_OBJECT_OR_DIE(addr, struct addrinfo, ADDRINFO_TAG); // no ZALLOC (yet) addr->ai_flags = AI_PASSIVE; addr->ai_protocol = 0; /* IPPROTO_UDP | IPPROTO_TCP */ addr->ai_socktype = 0; /* SOCK_DGRAM SOCK_STREAM */ addr->ai_canonname = NULL; addr->ai_next = NULL; switch(address->version) { case HOST_ADDRESS_IPV4: { addr->ai_family = AF_INET; break; } case HOST_ADDRESS_IPV6: { addr->ai_family = AF_INET6; break; } default: { free(addr); return IP_VERSION_NOT_SUPPORTED; } } if(ISOK(ret = host_address2allocated_sockaddr(address, &addr->ai_addr))) { addr->ai_addrlen = ret; *addrp = addr; } else { free(addr); } return ret; } ya_result host_address_set_with_sockaddr(host_address *address, const socketaddress *sa) { switch(sa->sa.sa_family) { case AF_INET: { const struct sockaddr_in *sain = (const struct sockaddr_in*)sa; address->tsig = NULL; address->version = HOST_ADDRESS_IPV4; address->port = sain->sin_port; address->ip.v4.value = sain->sin_addr.s_addr; return SUCCESS; } case AF_INET6: { const struct sockaddr_in6 *sain6 = (const struct sockaddr_in6*)sa; address->tsig = NULL; address->version = HOST_ADDRESS_IPV6; address->port = sain6->sin6_port; memcpy(address->ip.v6.bytes, &sain6->sin6_addr, 16); return SUCCESS; } default: { return IP_VERSION_NOT_SUPPORTED; } } } bool host_address_list_contains_ip(const host_address *address_list, const socketaddress *sa) { host_address address; #if DEBUG memset(&address, 0xff, sizeof(address)); #endif /* no need to set NEXT nor TSIG */ if(ISOK(host_address_set_with_sockaddr(&address, sa))) { switch(address.version) { case HOST_ADDRESS_IPV4: { while(address_list != NULL) { if(address_list->version == HOST_ADDRESS_IPV4) { if(address_list->ip.v4.value == address.ip.v4.value) { return TRUE; } } address_list = address_list->next; } break; } case HOST_ADDRESS_IPV6: { while(address_list != NULL) { if(address_list->version == HOST_ADDRESS_IPV6) { if((address_list->ip.v6.lohi[0] == address.ip.v6.lohi[0]) && (address_list->ip.v6.lohi[1] == address.ip.v6.lohi[1])) { return TRUE; } } address_list = address_list->next; } break; } default: { break; } } } return FALSE; } #if DNSCORE_HAS_TSIG_SUPPORT bool host_address_list_contains_ip_tsig(const host_address *address_list, const socketaddress *sa, const tsig_item *tsig) { host_address address; #if DEBUG memset(&address, 0xff, sizeof(address)); #endif /* no need to set NEXT nor TSIG */ if(ISOK(host_address_set_with_sockaddr(&address, sa))) { switch(address.version) { case HOST_ADDRESS_IPV4: { while(address_list != NULL) { if(address_list->version == HOST_ADDRESS_IPV4) { if(address_list->ip.v4.value == address.ip.v4.value) { if(address_list->tsig == tsig) { return TRUE; } } } address_list = address_list->next; } break; } case HOST_ADDRESS_IPV6: { while(address_list != NULL) { if(address_list->version == HOST_ADDRESS_IPV6) { if((address_list->ip.v6.lohi[0] == address.ip.v6.lohi[0]) && (address_list->ip.v6.lohi[1] == address.ip.v6.lohi[1])) { if(address_list->tsig == tsig) { return TRUE; } } } address_list = address_list->next; } break; } default: { break; } } } return FALSE; } #endif bool host_address_list_contains_host(const host_address *address_list, const host_address *address) { switch(address->version) { case HOST_ADDRESS_IPV4: { while(address_list != NULL) { if(address_list->version == HOST_ADDRESS_IPV4) { if(address_list->ip.v4.value == address->ip.v4.value) { #if DNSCORE_HAS_TSIG_SUPPORT if(address_list->tsig == address->tsig) { return TRUE; } #else return TRUE; #endif } } address_list = address_list->next; } break; } case HOST_ADDRESS_IPV6: { while(address_list != NULL) { if(address_list->version == HOST_ADDRESS_IPV6) { if((address_list->ip.v6.lohi[0] == address->ip.v6.lohi[0]) && (address_list->ip.v6.lohi[1] == address->ip.v6.lohi[1])) { #if DNSCORE_HAS_TSIG_SUPPORT if(address_list->tsig == address->tsig) { return TRUE; } #else return TRUE; #endif } } address_list = address_list->next; } break; } default: { break; } } return FALSE; } void host_address_set_ipv4(host_address *address, const u8 *ipv4, u16 port) { memcpy(address->ip.v4.bytes, ipv4, 4); address->port = port; address->version = HOST_ADDRESS_IPV4; } void host_address_set_ipv6(host_address *address, const u8 *ipv6, u16 port) { memcpy(address->ip.v6.bytes, ipv6, 16); address->port = port; address->version = HOST_ADDRESS_IPV6; } void host_address_set_dname(host_address *address, const u8 *dname, u16 port) { address->ip.dname.dname = dnsname_dup(dname); address->port = port; address->version = HOST_ADDRESS_DNAME; } ya_result host_address_append_ipv4(host_address *address, const u8 *ipv4, u16 port) { for(;;) { if((address->version == HOST_ADDRESS_IPV4) && (address->port == port)) { if(memcmp(address->ip.v4.bytes, ipv4, 4) == 0) { /* dup */ return COLLECTION_DUPLICATE_ENTRY; } } if(address->next == NULL) { break; } address = address->next; } host_address *new_address; ZALLOC_OBJECT_OR_DIE( new_address, host_address, HOSTADDR_TAG); new_address->next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT new_address->tsig = NULL; #endif host_address_set_ipv4(new_address, ipv4, port); address->next = new_address; return SUCCESS; } ya_result host_address_append_ipv6(host_address *address, const u8 *ipv6, u16 port) { for(;;) { if((address->version == HOST_ADDRESS_IPV6) && (address->port == port)) { if(memcmp(address->ip.v6.bytes, ipv6, 16) == 0) { /* dup */ return COLLECTION_DUPLICATE_ENTRY; } } if(address->next == NULL) { break; } address = address->next; } host_address *new_address; ZALLOC_OBJECT_OR_DIE( new_address, host_address, HOSTADDR_TAG); new_address->next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT new_address->tsig = NULL; #endif host_address_set_ipv6(new_address, ipv6, port); address->next = new_address; return SUCCESS; } ya_result host_address_append_dname(host_address *address, const u8 *dname, u16 port) { int dname_len = dnsname_len(dname); for(;;) { if((address->version == HOST_ADDRESS_DNAME) && (address->port == port)) { if(memcmp(address->ip.dname.dname, dname, dname_len) == 0) { /* dup */ return COLLECTION_DUPLICATE_ENTRY; } } if(address->next == NULL) { break; } address = address->next; } host_address *new_address; ZALLOC_OBJECT_OR_DIE( new_address, host_address, HOSTADDR_TAG); new_address->next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT new_address->tsig = NULL; #endif host_address_set_dname(new_address, dname, port); address->next = new_address; return SUCCESS; } /** * Makes a copy of the host_address* ha. */ ya_result host_address_append_host_address(host_address *address, const host_address *ha) { switch(ha->version) { case HOST_ADDRESS_IPV4: { for(;;) { if((address->version == ha->version) && (address->port == ha->port)) { if(address->ip.v4.value == ha->ip.v4.value) { /* dup */ return COLLECTION_DUPLICATE_ENTRY; } } if(address->next == NULL) { break; } address = address->next; } host_address *new_address; ZALLOC_OBJECT_OR_DIE( new_address, host_address, HOSTADDR_TAG); new_address->next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT new_address->tsig = ha->tsig; #endif host_address_set_ipv4(new_address, ha->ip.v4.bytes, ha->port); address->next = new_address; break; } case HOST_ADDRESS_IPV6: { for(;;) { if((address->version == ha->version) && (address->port == ha->port)) { if((address->ip.v6.lohi[0] == ha->ip.v6.lohi[0]) && (address->ip.v6.lohi[1] == ha->ip.v6.lohi[1])) { /* dup */ return COLLECTION_DUPLICATE_ENTRY; } } if(address->next == NULL) { break; } address = address->next; } host_address *new_address; ZALLOC_OBJECT_OR_DIE( new_address, host_address, HOSTADDR_TAG); new_address->next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT new_address->tsig = ha->tsig; #endif host_address_set_ipv6(new_address, ha->ip.v6.bytes, ha->port); address->next = new_address; break; } case HOST_ADDRESS_DNAME: { int dname_len = dnsname_len(ha->ip.dname.dname); for(;;) { if((address->version == ha->version) && (address->port == ha->port)) { if(memcmp(address->ip.dname.dname, ha->ip.dname.dname, dname_len) == 0) { /* dup */ return COLLECTION_DUPLICATE_ENTRY; } } if(address->next == NULL) { break; } address = address->next; } host_address *new_address; ZALLOC_OBJECT_OR_DIE( new_address, host_address, HOSTADDR_TAG); new_address->next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT new_address->tsig = ha->tsig; #endif host_address_set_dname(new_address, ha->ip.dname.dname, ha->port); address->next = new_address; break; } default: { return IP_VERSION_NOT_SUPPORTED; } } return SUCCESS; } ya_result host_address_append_sockaddr(host_address *address, const socketaddress *sa) { if(sa != NULL) { ya_result ret; host_address new_address; new_address.next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT new_address.tsig = NULL; #endif if(ISOK(ret = host_address_set_with_sockaddr(&new_address, sa))) { if(ISOK(ret = host_address_append_host_address(address, &new_address))) { return ret; } } return ret; } return UNEXPECTED_NULL_ARGUMENT_ERROR; } ya_result host_address_append_sockaddr_with_port(host_address *address, const socketaddress *sa, u16 port) { if(sa != NULL) { ya_result ret; host_address new_address; new_address.next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT new_address.tsig = NULL; #endif if(ISOK(ret = host_address_set_with_sockaddr(&new_address, sa))) { new_address.port = port; if(ISOK(ret = host_address_append_host_address(address, &new_address))) { return ret; } else { if(ret == COLLECTION_DUPLICATE_ENTRY) { ret = SUCCESS; } } } return ret; } return UNEXPECTED_NULL_ARGUMENT_ERROR; } ya_result host_address_append_hostent(host_address *address, struct hostent *he, u16 port) { if(he != NULL) { switch(he->h_addrtype) { case AF_INET: { char **addr = he->h_addr_list; while(*addr != NULL) { host_address_append_ipv4(address, (u8*)addr, port); addr++; } return SUCCESS; } case AF_INET6: { char **addr = he->h_addr_list; while(*addr != NULL) { host_address_append_ipv6(address, (u8*)addr, port); addr++; } return SUCCESS; } default: { break; } } } return UNEXPECTED_NULL_ARGUMENT_ERROR; } bool host_address_equals(const host_address *a, const host_address *b) { if(a->version == b->version && a->port == b->port) { switch(a->version) { case HOST_ADDRESS_IPV4: { return a->ip.v4.value == b->ip.v4.value; } case HOST_ADDRESS_IPV6: { return a->ip.v6.lohi[0] == b->ip.v6.lohi[0] && a->ip.v6.lohi[1] == b->ip.v6.lohi[1]; } case HOST_ADDRESS_DNAME: { return dnsname_equals(a->ip.dname.dname, b->ip.dname.dname); } } } return FALSE; } bool host_address_list_equals(const host_address *a, const host_address *b) { while((a != NULL) && (b != NULL)) { if(a == b) { return TRUE; } if(!host_address_equals(a, b)) { return FALSE; } a = a->next; b = b->next; } return (a == b); } /** * Moves the first item at the end of the list. * * @param firstp pointer to pointer to the first item of the list */ void host_address_list_roll(host_address **firstp) { host_address *first = *firstp; host_address *next = first->next; if(next != NULL) { *firstp = next; first->next = NULL; while(next->next != NULL) { next = next->next; } next->next = first; } } s32 host_address_compare(const host_address *a, const host_address *b) { s32 v = (s32)a->version - (s32)b->version; if(v == 0) { switch(a->version) { case HOST_ADDRESS_IPV4: { s32 d = memcmp(a->ip.v4.bytes, b->ip.v4.bytes, 4); if(d != 0) { return d; } break; } case HOST_ADDRESS_IPV6: { s32 d = memcmp(a->ip.v6.bytes, b->ip.v6.bytes, 16); if(d != 0) { return d; } break; } case HOST_ADDRESS_DNAME: { s32 d = dnsname_compare(a->ip.dname.dname, b->ip.dname.dname); if(d != 0) { return d; } break; } } return (s32)a->port - (s32)b->port; } else { return v; } } bool host_address_match(const host_address *a, const host_address *b) { if(a->version == b->version && ((a->port == b->port) || (b->port == 0) || (a->port == 0)) ) { switch(a->version) { case HOST_ADDRESS_IPV4: { return a->ip.v4.value == b->ip.v4.value; } case HOST_ADDRESS_IPV6: { return a->ip.v6.lohi[0] == b->ip.v6.lohi[0] && a->ip.v6.lohi[1] == b->ip.v6.lohi[1]; } case HOST_ADDRESS_DNAME: { return dnsname_equals(a->ip.dname.dname, b->ip.dname.dname); } } } return FALSE; } /** * Removes the matching host_address from the list * * @param address * @param ha * @return */ host_address * host_address_remove_host_address(host_address **address, host_address *ha_match) { host_address **ha_prev = address; host_address *ha = *ha_prev; while(ha != NULL) { if(host_address_equals(ha, ha_match)) { *ha_prev = ha->next; ha->next = NULL; return ha; } ha_prev = &ha->next; ha = *ha_prev; } return NULL; } bool host_address_update_host_address_list(host_address **dp, const host_address *s) { host_address* d = *dp; bool changed = FALSE; // if the first list is empty (NULL) // and the second one is not null // put a copy of the second one in the first one // else // do nothing and it's an error // else // ... if(d == NULL) { if(s != NULL) { d = host_address_copy_list(s); *dp = d; return TRUE; // d has changed } else { return FALSE; // d hasn't changed } } if(s == NULL) { return FALSE; // d hasn't changed } // *dp is not NULL // ... // // for each ha in d // not in s -> remove from d // // now d is smaller, test what it still contains // // for each ha in s // not in d -> add to d // for(host_address *ha = d; ha != NULL; ha = ha->next) { if(!host_address_list_contains_host(s, ha)) { // remove from d host_address *removed = host_address_remove_host_address(&d, ha); // cannot return NULL in this case (only returns NULL if ha is not found in d) // release it host_address_delete(removed); // if d was ha (a list with only element, it being ha), then d is now empty if(d == NULL) { d = host_address_copy_list(s); *dp = d; return TRUE; } ha = d; changed = TRUE; } } /// @note host_address_append_host_address checks for duplicate before putting a copy for(const host_address *ha = s; ha != NULL; ha = ha->next) { if(ISOK(host_address_append_host_address(d, ha))) // copy made { changed = TRUE; } } // this is not a leak, the head of the list may have changed so this fixes it if(changed) { *dp = d; } return changed; } ya_result host_address_to_str(const host_address *ha, char *str, int len, u8 flags) { char *limit = &str[len]; char *p = str; char port_separator; switch(ha->version) { case HOST_ADDRESS_IPV4: { port_separator = ':'; if(inet_ntop(AF_INET, ha->ip.v4.bytes, p, limit - p) == NULL) { *p = '\0'; return ERRNO_ERROR; } p += strlen(p); break; } case HOST_ADDRESS_IPV6: { port_separator = '#'; if(inet_ntop(AF_INET6, ha->ip.v6.bytes, p, limit - p) == NULL) { *p = '\0'; return ERRNO_ERROR; } p += strlen(p); break; } case HOST_ADDRESS_DNAME: { s32 n; port_separator = ':'; *p = '\0'; if(FAIL(n = snformat(p, len, "%{dnsname}", ha->ip.dname.dname))) { // it failed, and n is the error code return n; } p += n; break; } default: { port_separator = ':'; *p = '\0'; break; } } if((ha->port != 0) && (flags & HOST_ADDRESS_TO_STR_SHOW_PORT_ZERO)) { if(flags & (HOST_ADDRESS_TO_STR_FULLPORT|HOST_ADDRESS_TO_STR_PORT)) { s32 n; if(flags & HOST_ADDRESS_TO_STR_FULLPORT) { n = snformat(p, limit - p, " port %i", ntohs(ha->port)); } else { n = snformat(p, limit - p, "%c%i", port_separator, ntohs(ha->port)); } if(FAIL(n)) { // it failed, and n is the error code return n; } p += n; } } #if DNSCORE_HAS_TSIG_SUPPORT if((ha->tsig != NULL) && (ha->tsig->name != NULL)) { s32 n = 0; if(flags & HOST_ADDRESS_TO_STR_TSIG) { n = snformat(p, limit - p, "*%{dnsname}", ha->tsig->name); } else if(flags & HOST_ADDRESS_TO_STR_FULLTSIG) { n = snformat(p, limit - p, "key %{dnsname}", ha->tsig->name); } if(FAIL(n)) { // it failed, and n is the error code return n; } p += n; } #endif return p - str; } bool host_address_is_any(const host_address *ha) { //bool is_any; if(ha->version == HOST_ADDRESS_IPV4) { return ha->ip.v4.value == INADDR_ANY; } else if(ha->version == HOST_ADDRESS_IPV6) { return (ha->ip.v6.lohi[0]|ha->ip.v6.lohi[1]) == 0; } else { // no supported, so no return FALSE; } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/hsdllist.c0000644000000000000000000000013214505005532021322 xustar000000000000000030 mtime=1695812442.415981801 30 atime=1695812445.793030168 30 ctime=1695812494.586728991 yadifa-2.6.5-11201/lib/dnscore/src/hsdllist.c0000664000374500037450000001032714505005532021267 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include "dnscore/hsdllist.h" static void hsdllist_free_nothing(void *data) { (void)data; } void hsdllist_init(hsdllist_s *lst) { lst->first.next = &lst->last; lst->first.prev = NULL; lst->first.data = NULL; lst->last.prev = &lst->first; lst->last.next = NULL; lst->last.data = NULL; lst->size = 0; lst->node_allocator = &libc_allocator; lst->data_free_callback = hsdllist_free_nothing; } void hsdllist_destroy(hsdllist_s *lst) { hsdllist_node_s *node = lst->first.next; for(u32 n = lst->size; n > 0; n--) { hsdllist_node_s *next_node = node->next; void *data = node->data; afree(lst->node_allocator, node); lst->data_free_callback(data); node = next_node; } lst->first.next = &lst->last; lst->last.prev = &lst->first; lst->size = 0; } void hsdllist_append(hsdllist_s *lst, void *data) { hsdllist_node_s *new_node = aalloc(lst->node_allocator,sizeof(hsdllist_node_s)); new_node->next = &lst->last; new_node->prev = lst->last.prev; new_node->data = data; lst->last.prev = new_node; lst->size++; } void hsdllist_insert(hsdllist_s *lst, void *data) { hsdllist_node_s *new_node = aalloc(lst->node_allocator,sizeof(hsdllist_node_s)); new_node->next = lst->first.next; new_node->prev = &lst->first; new_node->data = data; lst->first.next = new_node; lst->size++; } u32 hsdllist_size(hsdllist_s *lst) { return lst->size; } void* hsdllist_remove_last(hsdllist_s *lst) { if(lst->size > 0) { lst->size--; hsdllist_node_s *node = lst->last.prev; lst->last.prev = node->prev; node->prev->next = &lst->last; void *data = node->data; afree(lst->node_allocator, node); return data; } return NULL; } void* hsdllist_remove_first(hsdllist_s *lst) { if(lst->size > 0) { lst->size--; hsdllist_node_s *node = lst->first.next; lst->first.next = node->next; node->next->prev = &lst->first; void *data = node->data; afree(lst->node_allocator, node); return data; } return NULL; } /** * @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/identity.c0000644000000000000000000000013214505005532021325 xustar000000000000000030 mtime=1695812442.434982073 30 atime=1695812445.794030182 30 ctime=1695812494.589729034 yadifa-2.6.5-11201/lib/dnscore/src/identity.c0000664000374500037450000001166714505005532021302 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include "dnscore/sys_types.h" #include "dnscore/logger.h" #include "dnscore/file_output_stream.h" #include #include #if HAVE_GRP_H #include #endif /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ #define MODULE_MSG_HANDLE g_system_logger /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ /** \brief Change uid and gid of the program * * @param[in] config is a config_data structure * * @return an error code */ ya_result identity_change(uid_t new_uid, gid_t new_gid) { #if __unix__ ya_result return_code; uid_t uid = getuid(); uid_t euid = getuid(); gid_t gid = getgid(); gid_t egid = getegid(); bool is_admin = (uid==0)||(euid==0)||(gid==0)||(egid==0); /* ------------------------------------------------------------ */ if( is_admin && ((uid != new_uid) || (gid != new_gid) || (euid != new_uid) || (egid != new_gid))) { log_info("changing identity to %d:%d (current: %d:%d)", new_uid, new_gid, uid, gid); } if(((0 != new_gid) || (0 != new_gid)) && is_admin) // if we need to change to something else than admin and we are admin ... { #if HAVE_GRP_H && HAS_SETGROUPS if(setgroups(0, NULL) < 0) { log_warn("could not relinquish all groups : %r", ERRNO_ERROR); } #endif if(setgid(new_gid) < 0) { return_code = ERRNO_ERROR; log_err("error switching to gid %i: %r", new_gid, return_code); return return_code;; } if(setegid(new_gid) < 0) { return_code = ERRNO_ERROR; log_err("error switching to egid %i: %r", new_gid, return_code); return return_code;; } } if(((0 != new_uid) || (0 != new_uid)) && is_admin) // if we need to change to something else than admin and we are admin ... { #if HAVE_GRP_H && HAS_SETGROUPS if(setgroups(0, NULL) < 0) { log_warn("could not relinquish all groups : %r", ERRNO_ERROR); } #endif if(setuid(new_uid) < 0) { return_code = ERRNO_ERROR; log_err("could not change uid to %i: %r", new_uid, return_code); return return_code;; } if(seteuid(new_uid) < 0) { return_code = ERRNO_ERROR; log_err("could not change euid to %i: %r", new_uid, return_code); return return_code;; } } #if DEBUG output_stream os; if(ISOK(file_output_stream_create(&os, "/tmp/test-uid-gid", 0644))) { osformatln(&os, "uid=%u gid=%u euid=%u egid=%u\n", uid, gid, euid, egid); output_stream_close(&os); } #endif return SUCCESS; #else return FEATURE_NOT_IMPLEMENTED_ERROR; #endif } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/input_stream.c0000644000000000000000000000013114505005532022205 xustar000000000000000030 mtime=1695812442.483982775 29 atime=1695812445.79603021 30 ctime=1695812494.591729063 yadifa-2.6.5-11201/lib/dnscore/src/input_stream.c0000664000374500037450000002561614505005532022162 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include /* or netinet/in.h */ #include "dnscore/input_stream.h" #include "dnscore/rfc.h" #include "dnscore/logger.h" #include "dnscore/dnscore.h" #define MODULE_MSG_HANDLE g_system_logger ya_result input_stream_read_fully(input_stream *stream, void* buffer_start, u32 len_start) { input_stream_read_method* readfunc = stream->vtbl->read; u32 len = len_start; u8* buffer = (u8*)buffer_start; ya_result ret; while(len > 0) { if(FAIL(ret = readfunc(stream, buffer, len))) { return ret; } if(ret == 0) /* eof */ { break; } buffer += ret; len -= ret; // cppcheck: false positive } /* If we only read a partial it's wrong. * If we were aked to read nothing it's ok. * If we read nothing at all we were on EOF and its still ok */ if(len > 0) { return UNABLE_TO_COMPLETE_FULL_READ; } return (ya_result)(buffer - (u8*)buffer_start); } ya_result input_stream_skip_fully(input_stream *stream, u32 len_start) { input_stream_skip_method* skipfunc = stream->vtbl->skip; u32 len = len_start; ya_result ret; while(len > 0) { if(FAIL(ret = skipfunc(stream, len))) { return ret; } if(ret == 0) /* eof */ { break; } len -= ret; // cppcheck: false positive } /* If we only read a partial it's wrong. * If we were aked to read nothing it's ok. * If we read nothing at all we were on EOF and its still ok */ if(len > 0) { return UNABLE_TO_COMPLETE_FULL_READ; } return len_start; } ya_result input_stream_read_nu32(input_stream *stream, u32 *output) { u32 data; ya_result err; if(ISOK(err = input_stream_read_fully(stream, &data, 4))) { *output = ntohl(data); } return err; } ya_result input_stream_read_nu16(input_stream *stream, u16 *output) { u16 data; ya_result err; if(ISOK(err = input_stream_read_fully(stream, &data, 2))) { *output = ntohs(data); } return err; } ya_result input_stream_read_u32(input_stream *stream, u32 *output) { u32 data; ya_result err; if(ISOK(err = input_stream_read_fully(stream, &data, 4))) { *output = data; } return err; } ya_result input_stream_read_s32(input_stream *stream, s32 *output) { u32 data; ya_result err; if(ISOK(err = input_stream_read_fully(stream, &data, 4))) { *output = data; } return err; } ya_result input_stream_read_u16(input_stream *stream, u16 *output) { u16 data; ya_result err; if(ISOK(err = input_stream_read_fully(stream, &data, 2))) { *output = data; } return err; } union t32 { u8 bytes[4]; u32 value; }; ya_result input_stream_read_pu32(input_stream* is, u32 *output) { ya_result ret; u32 value = 0; union t32 buffer; buffer.value = 0; ya_result n = 0; u8 s = 0; for(;;) { #if WORDS_BIGENDIAN if(FAIL(ret = input_stream_read(is, &buffer.bytes[3], 1))) { return ret; } #else if(FAIL(ret = input_stream_read(is, &buffer.bytes[0], 1))) { return ret; } #endif value |= (buffer.value & 127) << s; ++n; if(buffer.value < 128) { *output = value; return n; } s += 7; } } union t64 { u8 bytes[8]; u64 value; }; ya_result input_stream_read_pu64(input_stream* is, u64 *output) { ya_result ret; u64 value = 0; union t64 buffer; buffer.value = 0; ya_result n = 0; u8 s = 0; for(;;) { #if WORDS_BIGENDIAN if(FAIL(ret = input_stream_read(is, &buffer.bytes[7], 1))) { return ret; } #else if(FAIL(ret = input_stream_read(is, &buffer.bytes[0], 1))) { return ret; } #endif value |= (buffer.value & 127) << s; ++n; if(buffer.value < 128) { *output = value; return n; } s += 7; } } ya_result input_stream_read_dnsname(input_stream *stream, u8 *output_buffer) { u8 *output = output_buffer; const u8 * const limit = &output_buffer[MAX_DOMAIN_LENGTH - 1]; /* -1 because the limit is computed after the terminator */ for(;;) { int n; if(FAIL(n = input_stream_read_fully(stream, output, 1))) { return (output == output_buffer) ? 0 /* eof*/ : n; } if((n = *output++) == 0) { break; } if(n > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } u8* tmp = output; output += n; if(output >= limit) { return DOMAIN_TOO_LONG; } if(FAIL(n = input_stream_read_fully(stream, tmp, n))) { return n; } /* 0x012a = 01 '*' = wildcard */ /*if(GET_U16_AT(tmp[-1]) != NU16(0x012a))*/ { if(!dnslabel_locase_verify_charspace(&tmp[-1])) { return INVALID_CHARSET; } } } return (ya_result)(output - output_buffer); } ya_result input_stream_read_rname(input_stream *stream, u8 *output_buffer) { u8 *output = output_buffer; const u8 * const limit = &output_buffer[MAX_DOMAIN_LENGTH - 1]; /* -1 because the limit is computed after the terminator */ for(;;) { int n; if(FAIL(n = input_stream_read_fully(stream, output, 1))) { return (output == output_buffer) ? 0 /* eof*/ : n; } if((n = *output++) == 0) { break; } if(n > MAX_LABEL_LENGTH) { return LABEL_TOO_LONG; } u8* tmp = output; output += n; if(output >= limit) { return DOMAIN_TOO_LONG; } if(FAIL(n = input_stream_read_fully(stream, tmp, n))) { return n; } } return (ya_result)(output - output_buffer); } ya_result input_stream_read_line(input_stream *stream, char *output_, int max_len) { const char * const limit = &output_[max_len]; char *output = output_; /* * Cache the method */ input_stream_read_method *read_method = stream->vtbl->read; while(output < limit) { ya_result n = read_method(stream, (u8*)output, 1); if(n <= 0) { if(n == 0) { n = ((ya_result)(output - output_)); } return n; } if(*output++ == '\n') { return ((ya_result)(output - output_)); } } return max_len; } static ya_result input_stream_void_read(input_stream *stream, void* in_buffer,u32 in_len) { (void)stream; (void)in_buffer; (void)in_len; log_err("tried to read a closed stream"); return INVALID_STATE_ERROR; } static ya_result input_stream_void_skip(input_stream *stream, u32 byte_count) { (void)stream; (void)byte_count; log_err("tried to skip a closed stream"); return INVALID_STATE_ERROR; } static void input_stream_void_close(input_stream *stream) { (void)stream; log_err("tried to close a closed stream"); #if DEBUG logger_flush(); abort(); #endif } static const input_stream_vtbl void_input_stream_vtbl ={ input_stream_void_read, input_stream_void_skip, input_stream_void_close, "void_input_stream", }; /** * This tools allows a safer misuse (and detection) of closed streams * It sets the stream to a sink that warns abouts its usage and for which every call that can fail fails. */ void input_stream_set_void(input_stream* is) { yassert(is != NULL); is->data = NULL; is->vtbl = &void_input_stream_vtbl; } static ya_result input_stream_sink_read(input_stream *stream, void* in_buffer,u32 in_len) { (void)stream; (void)in_buffer; (void)in_len; return -1; } static ya_result input_stream_sink_skip(input_stream *stream, u32 byte_count) { (void)stream; return byte_count; } static void input_stream_sink_close(input_stream *stream) { (void)stream; } static const input_stream_vtbl sink_input_stream_vtbl ={ input_stream_sink_read, input_stream_sink_skip, input_stream_sink_close, "sink_input_stream", }; /** * Used to temporarily initialise a stream with a sink that can be closed safely. * Typically used as pre-init so the stream can be closed even if the function * setup failed before reaching stream initialisation. * * @param is */ void input_stream_set_sink(input_stream* is) { yassert(is != NULL); is->data = NULL; is->vtbl = &sink_input_stream_vtbl; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/json.c0000644000000000000000000000013114505005532020444 xustar000000000000000030 mtime=1695812442.500983019 29 atime=1695812445.79603021 30 ctime=1695812494.593729092 yadifa-2.6.5-11201/lib/dnscore/src/json.c0000664000374500037450000002604314505005532020414 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnspacket DNS Messages * @ingroup dnscore * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #include #define JSON_C_ 1 #include "dnscore/sys_types.h" #include "dnscore/ptr_set.h" #include "dnscore/ptr_vector.h" #include "dnscore/zalloc.h" #include "dnscore/format.h" #define JSON_TAG 0x4e4f534a struct json_value_array { intptr type; ptr_vector array; }; struct json_value_object { intptr type; ptr_set map; }; struct json_value_string { intptr type; char *text; size_t text_size; }; struct json_value_number { intptr type; double value; }; struct json_value_bool { intptr type; bool value; }; #include "dnscore/json.h" union json { enum json_type type; struct json_value_bool boolean; struct json_value_number number; struct json_value_string string; struct json_value_array array; struct json_value_object map; }; static json json_type_new_intance(enum json_type type) { json ret; ZALLOC_OBJECT_OR_DIE(ret, union json, JSON_TAG); ret->type = type; return ret; } json json_object_new_instance() { json ret = json_type_new_intance(JSON_OBJECT); ptr_set_init(&ret->map.map); ret->map.map.compare = ptr_set_asciizp_node_compare; return ret; } json json_array_new_instance() { json ret = json_type_new_intance(JSON_ARRAY); ptr_vector_init(&ret->array.array); return ret; } json json_string_new_instance() { json ret = json_type_new_intance(JSON_STRING); ret->string.text = NULL; ret->string.text_size = 0; return ret; } json json_number_new_instance() { json ret = json_type_new_intance(JSON_NUMBER); ret->number.value = 0; return ret; } json json_boolean_new_instance() { json ret = json_type_new_intance(JSON_BOOLEAN); ret->boolean.value = FALSE; return ret; } enum json_type json_type_get(const json j) { return j->type; } bool json_boolean_get(const json j) { yassert(j->type == JSON_BOOLEAN); return j->boolean.value; } void json_boolean_set(json j, bool value) { yassert(j->type == JSON_BOOLEAN); j->boolean.value = value; } double json_number_get(const json j) { yassert(j->type == JSON_NUMBER); return j->number.value; } void json_number_set(json j, double value) { yassert(j->type == JSON_NUMBER); j->number.value = value; } const char * json_string_get(const json j) { yassert(j->type == JSON_STRING); return j->string.text; } size_t json_string_size_get(const json j) { yassert(j->type == JSON_STRING); return j->string.text_size; } void json_string_set(json j, const char* text) { yassert(j->type == JSON_STRING); j->string.text = strdup(text); j->string.text_size = strlen(text); } json json_array_get(json j, size_t index) { yassert(j->type == JSON_ARRAY); json ret = (json)ptr_vector_get(&j->array.array, (u32)index); return ret; } void json_array_add(const json j, json item) { yassert(j->type == JSON_ARRAY); ptr_vector_append(&j->array.array, item); } json json_object_get(json j, const char *name) { yassert(j->type == JSON_OBJECT); ptr_node *node = ptr_set_find(&j->map.map, name); if(node != NULL && node->value != NULL) { return (json)node->value; } else { return NULL; } } bool json_object_add(const json j, const char *key, json item) { yassert(j->type == JSON_OBJECT); ptr_node *node = ptr_set_insert(&j->map.map, (void*)key); if(node->value == NULL) { node->key = strdup(key); node->value = item; return TRUE; } else { return FALSE; } } ya_result json_write_to(json j, output_stream *os); struct json_write_forall_callback_args { output_stream *os; ya_result ret; bool comma; }; static int json_write_forall_callback(ptr_node *node, void *args_) { struct json_write_forall_callback_args *args = (struct json_write_forall_callback_args*)args_; output_stream *os = args->os; ya_result ret = 0; if(!args->comma || ((ret = output_stream_write(os, ",", 1)) == 1)) { ya_result ret0; ret0 = osformat(os, "\"%s\": ", node->key); if(ISOK(ret0)) { ya_result ret1; if(ISOK(ret1 = json_write_to((json)node->value, os))) { ret += ret0 + ret1; args->ret += ret; args->comma = TRUE; } else { ret = ret1;; } } else { ret = ret0; } } return ret; } ya_result json_write_to(json j, output_stream *os) { ya_result ret; switch(j->type) { case JSON_BOOLEAN: { if(j->boolean.value) { ret = output_stream_write(os, "true", 4); } else { ret = output_stream_write(os, "false", 5); } break; } case JSON_NUMBER: { ret = osformat(os, "%f", j->number.value); break; } case JSON_STRING: { ya_result ret_tmp; if((ret_tmp = output_stream_write(os, "\"", 1)) == 1) { if(ISOK(ret = output_stream_write(os, j->string.text, (u32)j->string.text_size))) { if((ret_tmp = output_stream_write(os, "\"", 1)) == 1) { ret += 2; } else { ret = ret_tmp; } } } else { ret = ret_tmp; } break; } case JSON_ARRAY: { ya_result t = 2; ret = output_stream_write_u8(os, '['); if(ISOK(ret)) { int last_index = ptr_vector_last_index(&j->array.array); if(last_index >= 0) { if(ISOK(ret = json_write_to((json)ptr_vector_get(&j->array.array, 0), os))) { t += ret; for(int i = 1; i <= last_index; ++i) { if(FAIL(ret = output_stream_write_u8(os, ','))) { break; } if(FAIL(ret = json_write_to((json)ptr_vector_get(&j->array.array, i), os))) { break; } t += ret; } t += last_index; // for the commas if(ISOK(ret)) { if(ISOK(ret = output_stream_write_u8(os, ']'))) { ret += t; } } } } } break; } case JSON_OBJECT: { ret = output_stream_write_u8(os, '{'); if(ISOK(ret)) { struct json_write_forall_callback_args args = { os, 2, FALSE}; ptr_set_forall(&j->map.map, json_write_forall_callback, &args); if(ISOK(args.ret)) { if(ISOK(ret = output_stream_write_u8(os, '}'))) { ret = args.ret; } } } break; } default: { ret = INVALID_STATE_ERROR; break; } } // switch(j->type) return ret; } void json_delete(json j); static void json_delete_forall_callback(ptr_node *node) { free(node->key); json_delete((json)node->value); } void json_delete(json j) { switch(j->type) { case JSON_STRING: free(j->string.text); FALLTHROUGH // fall through case JSON_BOOLEAN: //FALLTHROUGH // fall through case JSON_NUMBER: { ZFREE_OBJECT(j); break; } case JSON_ARRAY: { int last_index = ptr_vector_last_index(&j->array.array); for(int i = 0; i <= last_index; ++i) { json_delete((json)ptr_vector_get(&j->array.array, i)); } break; } case JSON_OBJECT: { ptr_set_callback_and_destroy(&j->map.map, json_delete_forall_callback); break; } default: { // ERROR; break; } } // switch(j->type) } ya_result json_size(json j) { output_stream os; output_stream_set_sink(&os); ya_result ret = json_write_to(j, &os); return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/limited_input_stream.c0000644000000000000000000000013114505005532023714 xustar000000000000000030 mtime=1695812442.427981973 30 atime=1695812445.793030168 29 ctime=1695812494.59572912 yadifa-2.6.5-11201/lib/dnscore/src/limited_input_stream.c0000664000374500037450000001027314505005532023662 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/limited_input_stream.h" #include "dnscore/zalloc.h" #define LIMITED_INPUT_STREAM_TAG 0x53494454494d494c /* LIMITDIS */ #define MODULE_MSG_HANDLE g_database_logger typedef struct limited_input_stream_data limited_input_stream_data; struct limited_input_stream_data { input_stream filtered; u64 remaining; }; static ya_result limited_read(input_stream* stream, void* buffer, u32 len) { limited_input_stream_data* data = (limited_input_stream_data*)stream->data; if(data->remaining > 0) { len = MIN(len, data->remaining); ya_result return_value = input_stream_read(&data->filtered, buffer, len); if(ISOK(return_value)) { data->remaining -= len; } return return_value; } else { return -1; /* EOF */ } } static void limited_close(input_stream* stream) { limited_input_stream_data* data = (limited_input_stream_data*)stream->data; input_stream_close(&data->filtered); ZFREE_OBJECT(data); input_stream_set_void(stream); } static ya_result limited_skip(input_stream* stream, u32 len) { limited_input_stream_data* data = (limited_input_stream_data*)stream->data; len = MIN(len, data->remaining); ya_result return_value = input_stream_skip(&data->filtered, len); if(ISOK(return_value)) { data->remaining -= len; } return return_value; } static const input_stream_vtbl limited_input_stream_vtbl = { limited_read, limited_skip, limited_close, "limited_input_stream" }; void limited_input_stream_init(input_stream* filtered, input_stream *stream, u64 stream_size) { limited_input_stream_data* data; yassert(filtered->vtbl != NULL); ZALLOC_OBJECT_OR_DIE( data, limited_input_stream_data, LIMITED_INPUT_STREAM_TAG); data->filtered.data = filtered->data; data->filtered.vtbl = filtered->vtbl; filtered->data = NULL; filtered->vtbl = NULL; data->remaining = stream_size; stream->data = data; stream->vtbl = &limited_input_stream_vtbl; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/limiter.c0000644000000000000000000000013114505005532021140 xustar000000000000000030 mtime=1695812442.496982961 29 atime=1695812445.79603021 30 ctime=1695812494.597729149 yadifa-2.6.5-11201/lib/dnscore/src/limiter.c0000664000374500037450000001527314505005532021113 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include "dnscore/limiter.h" #include "dnscore/timems.h" #include "dnscore/logger.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define DUMP 0 void limiter_init(limiter_t *r, limiter_count_t rate_max) { r->time_base = timeus(); r->last_time = 0; r->wait_time = 0; r->window_current = 0; r->rate_max = rate_max; for(int i = 0; i < LIMITER_WINDOW_COUNT; ++i) { r->window[i] = 0; /*rate_max / LIMITER_WINDOW_COUNT;*/ } } void limiter_finalize(limiter_t *r) { (void)r; } void limiter_set_wait_time(limiter_t *r, u64 time_to_wait_between_two) { r->wait_time = time_to_wait_between_two; } u64 limiter_quota(limiter_t *r, limiter_count_t amount_to_add, limiter_count_t* quota_available_now, u64* time_to_wait_for_more) { limiter_count_t avail; u64 ttw; u64 now = timeus(); // d is the time elapsed since last measurement in us if(now - r->last_time > r->wait_time) { u64 delta_time_us = now - r->time_base; // get the window index u32 absolute_window = (u32)(delta_time_us / LIMITER_WINDOW_DURATION); #if LIMITER_WINDOW_COUNT > 1 u32 clear_from = r->window_current + 1; u32 clear_until = r->window_current + MIN(absolute_window, LIMITER_WINDOW_COUNT); #if DUMP formatln("limiter: %-9u.%6u clear from %u to %u", (u32)(delta_time_us / 1000000ULL), (u32)(delta_time_us % 1000000ULL), clear_from, clear_until); #endif for(u32 i = clear_from; i < clear_until; ++i) { r->window[i % LIMITER_WINDOW_COUNT] = 0; } r->window_current = absolute_window; #if DUMP format("limiter: current window: %u [ ", r->window_current); #endif limiter_count_t current_amount = 0; for(u32 i = 0; i < LIMITER_WINDOW_COUNT; ++i) { current_amount += r->window[i]; #if DUMP format("%9llu ", r->window[i]); #endif } #if DUMP format("] = %llu", current_amount); #endif #else // LIMITER_WINDOW_COUNT <= 1 limiter_count_t current_amount; if(absolute_window == r->window_current) { current_amount = r->window[0]; } else { r->window[0] = 0; current_amount = 0; r->time_base = now; r->window_current = 0; } #endif if(r->rate_max > current_amount) { avail = r->rate_max - current_amount; if(avail < amount_to_add) { ttw = 0; } else { avail = amount_to_add; ttw = LIMITER_WINDOW_DURATION - (delta_time_us % LIMITER_WINDOW_DURATION); } } else { avail = 0; ttw = LIMITER_WINDOW_DURATION - (delta_time_us % LIMITER_WINDOW_DURATION); } #if DUMP formatln(" available = %9llu, time to wait = %9llu", avail, ttw); #endif } else { avail = 0; ttw = r->wait_time - (now - r->last_time); } if(quota_available_now != NULL) { *quota_available_now = avail; } if(time_to_wait_for_more != NULL) { *time_to_wait_for_more = ttw; } return now; } void limiter_add(limiter_t *r, limiter_count_t amount_to_add, limiter_count_t* amount_added, u64* time_to_wait_for_more) { limiter_count_t tmp; if(amount_added == NULL) { amount_added = &tmp; } u64 now = limiter_quota(r, amount_to_add, amount_added, time_to_wait_for_more); if(*amount_added > 0) { r->last_time = now; r->window[r->window_current % LIMITER_WINDOW_COUNT] += *amount_added; } } void limiter_add_anyway(limiter_t *r, limiter_count_t amount_to_add, limiter_count_t* amount_added, u64* time_to_wait_for_more) { limiter_count_t tmp_added; u64 tmp_time; if(amount_added == NULL) { amount_added = &tmp_added; } if(time_to_wait_for_more == NULL) { time_to_wait_for_more = &tmp_time; } u64 now = limiter_quota(r, amount_to_add, amount_added, time_to_wait_for_more); r->last_time = now; r->window[r->window_current % LIMITER_WINDOW_COUNT] += *amount_added; } void limiter_wait(limiter_t *r, limiter_count_t amount_to_add) { limiter_count_t amount_added; u64 time_to_wait_for_more; for(;;) { limiter_add(r, amount_to_add, &amount_added, &time_to_wait_for_more); if(amount_added >= amount_to_add) { break; } amount_to_add -= amount_added; #if DUMP format("limiter: waiting %llu [ ", time_to_wait_for_more + 10); #endif usleep(time_to_wait_for_more + 10); } } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/list-dl.c0000644000000000000000000000013214505005532021044 xustar000000000000000030 mtime=1695812442.458982417 30 atime=1695812445.794030182 30 ctime=1695812494.599729178 yadifa-2.6.5-11201/lib/dnscore/src/list-dl.c0000664000374500037450000002256114505005532021014 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A node-based single linked list * * A node-based single linked list */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include "dnscore/list-dl.h" /*------------------------------------------------------------------------------ * FUNCTIONS */ /** * Remove the first item that points to data; * * @param list * @param data * @return TRUE if an item has been deleted */ bool list_dl_remove(list_dl_s *list, const void *data) { list_dl_node_s *node = list->head_sentinel.next; while(node->next != NULL) { if(data == node->data) { node->prev->next = node->next; node->next->prev = node->prev; list->size--; ZFREE_OBJECT(node); return TRUE; } node = node->next; } return FALSE; } void list_dl_move_to_first_position(list_dl_s *list, void *data) { list_dl_node_s *node = list->head_sentinel.next; // seek for the data while(node->next != NULL) { if(data == node->data) { // ensure it's not already at the first position if(node->prev != (list_dl_node_s*)&list->head_sentinel) { // remove part node->prev->next = node->next; node->next->prev = node->prev; // end of the remove part // insert part node->next = list->head_sentinel.next; node->prev = (list_dl_node_s*)&list->head_sentinel; list->head_sentinel.next->prev = node; list->head_sentinel.next = node; // end of the insert part } return; } node = node->next; } list_dl_insert(list, data); } /** * Removes the node from the list, the node is not freed * * @param list * @param node */ void list_dl_remove_node(list_dl_s *list, list_dl_node_s *node) { node->prev->next = node->next; node->next->prev = node->prev; node->next = NULL; node->prev = NULL; list->size--; } bool list_dl_remove_matching_ptr(list_dl_s *list, void *ptr) { list_dl_node_s *node = list->head_sentinel.next; while(node->next != NULL) { if(node->data == ptr) { node->prev->next = node->next; node->next->prev = node->prev; list->size--; ZFREE_OBJECT(node); return TRUE; } node = node->next; } return FALSE; } bool list_dl_remove_matching(list_dl_s *list, result_callback_function *match, void *args) { list_dl_node_s *node = list->head_sentinel.next; while(node->next != NULL) { ya_result ret = match(node->data, args); if(ret != 0) { node->prev->next = node->next; node->next->prev = node->prev; list->size--; ZFREE_OBJECT(node); return TRUE; } node = node->next; } return FALSE; } bool list_dl_remove_all_matching(list_dl_s *list, result_callback_function *match, void *args) { list_dl_node_s *node = list->head_sentinel.next; list_dl_node_s *node_next; while((node_next = node->next) != NULL) { ya_result ret = match(node->data, args); if(ret != 0) { node->prev->next = node->next; node->next->prev = node->prev; list->size--; ZFREE_OBJECT(node); } node = node_next; } return FALSE; } /** * Remove all items from the list. * Deletes the nodes but not the data. * * @param list */ void list_dl_clear(list_dl_s *list) { list_dl_node_s *node = list->head_sentinel.next; while(node->next != NULL) { list_dl_node_s *tmp = node; node = node->next; ZFREE_OBJECT(tmp); } list->head_sentinel.next = (list_dl_node_s*)&list->tail_sentinel; list->size = 0; } /** * Iterates through the nodes of the function, calling the comparator. * * The comparator must return: * * COLLECTION_ITEM_SKIP : go to next item * COLLECTION_ITEM_STOP : stop processing, return NULL * COLLECTION_ITEM_PROCESS_THEN_STOP : stop processing, return node data * * @param list * @param comparator * * @return a matching node or NULL */ void *list_dl_search(list_dl_s *list, result_callback_function *comparator, void *parm) { list_dl_node_s *node = list->head_sentinel.next; while(node->next != NULL) { void *data = node->data; node = node->next; ya_result ret = comparator(data, parm); if((ret & COLLECTION_ITEM_STOP) != 0) { if((ret & COLLECTION_ITEM_PROCESS) != 0) { return data; } else { return NULL; } } } return NULL; } /** * * Returns the index of that specific pointer into the list * Linear search (slow) * * @param list * @param comparator * @return the index in the list or -1 if the item is wasn't found */ ya_result list_dl_indexof(list_dl_s *list, void *data) { list_dl_node_s *node = list->head_sentinel.next; ya_result index = 0; while(node->next != NULL) { if(node->data == data) { return index; } ++index; node = node->next; } return -1; } void * list_dl_get(list_dl_s *list, s32 index) { list_dl_node_s *node = list->head_sentinel.next; if((u32)index < list->size) { while(index != 0) { node = node->next; index--; } return node->data; } else { return NULL; } } ya_result list_dl_foreach(list_dl_s *list, result_callback_function *callback, void *caller_data) { list_dl_node_s *node = list->head_sentinel.next; while(node->next != NULL) { void *data = node->data; node = node->next; ya_result ret = callback(data, caller_data); if(FAIL(ret)) { return ret; } if(ret == COLLECTION_ITEM_STOP) { break; } } return SUCCESS; } /** * Inserts data BEFORE the current node * * @param iter * @return */ bool list_dl_iterator_insert(list_dl_iterator_s *iter, void *data) { if(iter->current_node != (list_dl_node_s*)&iter->list->head_sentinel) { list_dl_node_s *node; ZALLOC_OBJECT_OR_DIE( node, list_dl_node_s, LISTDLND_TAG); node->data = data; node->next = iter->current_node; node->prev = iter->current_node->prev; iter->current_node->prev = node; node->prev->next = node; ++iter->list->size; return TRUE; } return FALSE; } /** * Inserts data BEFORE the current node * * @param iter * @return */ bool list_dl_iterator_append(list_dl_iterator_s *iter, void *data) { if(iter->current_node != (list_dl_node_s*)&iter->list->tail_sentinel) { list_dl_node_s *node; ZALLOC_OBJECT_OR_DIE( node, list_dl_node_s, LISTDLND_TAG); node->data = data; node->next = iter->current_node->next; node->prev = iter->current_node; iter->current_node->next = node; node->next->prev = node; ++iter->list->size; return TRUE; } return FALSE; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/list-sl.c0000644000000000000000000000013114505005532021062 xustar000000000000000029 mtime=1695812442.41798183 30 atime=1695812445.793030168 30 ctime=1695812494.601729206 yadifa-2.6.5-11201/lib/dnscore/src/list-sl.c0000664000374500037450000001334214505005532021030 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A node-based single linked list * * A node-based single linked list * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include "dnscore/list-sl.h" #define LISTDATA_TAG 0x415441445453494c /*------------------------------------------------------------------------------ * FUNCTIONS */ /** * Remove the first item that points to data; * * @param list * @param data * @return TRUE if an item has been deleted */ bool list_sl_remove(list_sl_s *list, void *data) { list_sl_node_s **nodep = &list->first; list_sl_node_s *node = list->first; while(node != (list_sl_node_s*)&list->sentinel) { if(data == node->data) { *nodep = node->next; list->size--; free(node); return TRUE; } nodep = &node->next; node = node->next; } return FALSE; } /** * Remove all items from the list. * Deletes the nodes but not the data. * * @param list */ void list_sl_clear(list_sl_s *list) { list_sl_node_s *node = list->first; while(node != (list_sl_node_s*)&list->sentinel) { list_sl_node_s *tmp = node; node = node->next; free(tmp); } list->first = (list_sl_node_s *)&list->sentinel; list->size = 0; } /** * Iterates through the nodes of the function, calling the comparator. * * The comparator must return: * * COLLECTION_ITEM_SKIP : go to next item * COLLECTION_ITEM_STOP : stop processing, return NULL * COLLECTION_ITEM_PROCESS_THEN_STOP : stop processing, return node data * * @param list * @param comparator * * @return a matching node or NULL */ void *list_sl_search(list_sl_s *list, result_callback_function *comparator, void *parm) { list_sl_node_s *node = list->first; while(node != (list_sl_node_s*)&list->sentinel) { ya_result ret = comparator(node->data, parm); if((ret & COLLECTION_ITEM_STOP) != 0) { if((ret & COLLECTION_ITEM_PROCESS) != 0) { return node->data; } else { return NULL; } } node = node->next; } return NULL; } /** * Iterates through the nodes of the function, calling the comparator. * * The comparator must return: * * < 0 : stop processing, return NULL * = 0 : no match * > 0 : stop processing, return node data * * @param list * @param comparator * * @return a matching node or NULL */ bool list_sl_remove_match(list_sl_s *list, result_callback_function *comparator, void *parm) { list_sl_node_s **nodep = &list->first; list_sl_node_s *node = list->first; bool matched = FALSE; while(node != (list_sl_node_s*)&list->sentinel) { ya_result ret = comparator(node->data, parm); if((ret & COLLECTION_ITEM_PROCESS) != 0) { list_sl_node_s* next = node->next; *nodep = node->next; list->size--; free(node); matched = TRUE; if((ret & COLLECTION_ITEM_STOP) != 0) { break; } node = next; // node is assigned its next value (stored in *nodep), it's not using freed memory with this. nodep = &node->next; continue; } if((ret & COLLECTION_ITEM_STOP) != 0) { break; } node = *nodep; // node is assigned its next value (stored in *nodep), it's not using freed memory with this. nodep = &node->next; } return matched; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/list-sl-debug.c0000644000000000000000000000013214505005532022147 xustar000000000000000030 mtime=1695812442.460982446 30 atime=1695812445.795030196 30 ctime=1695812494.603729235 yadifa-2.6.5-11201/lib/dnscore/src/list-sl-debug.c0000664000374500037450000001521214505005532022112 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A node-based single linked list * * A node-based single linked list * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include "dnscore/list-sl-debug.h" #define LISTDATA_TAG 0x415441445453494c #undef malloc #undef free #undef realloc #undef calloc #undef debug_mtest #undef debug_stat #undef debug_mallocated /*------------------------------------------------------------------------------ * FUNCTIONS */ void list_sl_debug_insert(list_sl_debug_s *list, void *data) { list_sl_debug_node_s *node; node = (list_sl_debug_node_s*)debug_malloc_unmonitored(sizeof(list_sl_debug_node_s)); node->next = list->first; node->data = data; list->first = node; list->size++; } /** * Remove the first item from the list. * Deletes the node but not the data. * The data is returned. * * @param list * @return the data or NULL if the list is empty */ void* list_sl_debug_remove_first(list_sl_debug_s *list) { if(list->size > 0) { list_sl_debug_node_s *node = list->first; void *data = node->data; list->first = node->next; list->size--; debug_free_unmonitored(node); return data; } else { return NULL; } } /** * Remove the first item that points to data; * * @param list * @param data * @return TRUE if an item has been deleted */ bool list_sl_debug_remove(list_sl_debug_s *list, void *data) { list_sl_debug_node_s **nodep = &list->first; list_sl_debug_node_s *node = list->first; while(node->next != NULL) { if(data == node->data) { *nodep = node->next; list->size--; free(node); return TRUE; } nodep = &node->next; node = node->next; } return FALSE; } /** * Remove all items from the list. * Deletes the nodes but not the data. * * @param list */ void list_sl_debug_clear(list_sl_debug_s *list) { list_sl_debug_node_s *node = list->first; while(node->next != NULL) { list_sl_debug_node_s *tmp = node; node = node->next; free(tmp); } list->first = (list_sl_debug_node_s *)&list->sentinel; list->size = 0; } /** * Iterates through the nodes of the function, calling the comparator. * * The comparator must return: * * COLLECTION_ITEM_SKIP : go to next item * COLLECTION_ITEM_STOP : stop processing, return NULL * COLLECTION_ITEM_PROCESS_THEN_STOP : stop processing, return node data * * @param list * @param comparator * * @return a matching node or NULL */ void *list_sl_debug_search(list_sl_debug_s *list, result_callback_function *comparator, void *parm) { list_sl_debug_node_s *node = list->first; while(node->next != NULL) { ya_result ret = comparator(node->data, parm); if((ret & COLLECTION_ITEM_STOP) != 0) { if((ret & COLLECTION_ITEM_PROCESS) != 0) { return node->data; } else { return NULL; } } node = node->next; } return NULL; } /** * Iterates through the nodes of the function, calling the comparator. * * The comparator must return: * * < 0 : stop processing, return NULL * = 0 : no match * > 0 : stop processing, return node data * * @param list * @param comparator * * @return a matching node or NULL */ bool list_sl_debug_remove_match(list_sl_debug_s *list, result_callback_function *comparator, void *parm) { list_sl_debug_node_s **nodep = &list->first; list_sl_debug_node_s *node = list->first; bool matched = FALSE; while(node->next != NULL) { ya_result ret = comparator(node->data, parm); if((ret & COLLECTION_ITEM_PROCESS) != 0) { list_sl_debug_node_s* next = node->next; *nodep = node->next; list->size--; free(node); matched = TRUE; if((ret & COLLECTION_ITEM_STOP) != 0) { break; } node = next; // node is assigned its next value (stored in *nodep), it's not using freed memory with this. nodep = &node->next; continue; } if((ret & COLLECTION_ITEM_STOP) != 0) { break; } node = *nodep; // node is assigned its next value (stored in *nodep), it's not using freed memory with this. nodep = &node->next; } return matched; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/logger-output-stream.c0000644000000000000000000000013114505005532023601 xustar000000000000000030 mtime=1695812442.496982961 29 atime=1695812445.79603021 30 ctime=1695812494.605729264 yadifa-2.6.5-11201/lib/dnscore/src/logger-output-stream.c0000664000374500037450000001465714505005532023561 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/logger_handle.h" #include "dnscore/zalloc.h" /* * This structure is supposed to match the output_stream one * It helps using the void* data as an int without a INT_AT(x) kind of macro */ typedef struct logger_output_stream_data logger_output_stream_data; #define LGOSDATA_TAG 0x41544144534f474c #define LGOSLINE_TAG 0x454e494c534f474c struct logger_output_stream_data { logger_handle *handle; char *line; u32 line_offset; u32 line_size; u32 level; }; typedef struct logger_output_stream logger_output_stream; struct logger_output_stream { logger_output_stream_data *data; const output_stream_vtbl *vtbl; }; static ya_result logger_output_stream_write(output_stream* stream_, const u8* buffer, u32 len_) { logger_output_stream* stream = (logger_output_stream*)stream_; u32 len = len_; for(;;) { const u8 *eol = (const u8*)memchr(buffer, '\n', len); if(eol == NULL) { break; } u32 line_len = eol - buffer; // merge with the buffer if it exists if(stream->data->line_offset == 0) { logger_handle_msg_text(stream->data->handle, stream->data->level, (const char*)buffer, line_len); ++line_len; buffer += line_len; len -= line_len; } else { // merge with the buffer int remaining = stream->data->line_size - stream->data->line_offset; if(remaining >= (int)line_len) { memcpy(&stream->data->line[stream->data->line_offset], buffer, line_len); stream->data->line_offset += line_len; logger_handle_msg_text(stream->data->handle, stream->data->level, stream->data->line, stream->data->line_offset); } else { memcpy(&stream->data->line[stream->data->line_offset], buffer, remaining); stream->data->line_offset += remaining; logger_handle_msg_text(stream->data->handle, stream->data->level, stream->data->line, stream->data->line_offset); line_len -= remaining; logger_handle_msg_text(stream->data->handle, stream->data->level, (const char*)buffer, line_len); } ++line_len; buffer += line_len; len -= line_len; stream->data->line_offset = 0; } } // no EOL, try to flush what remains while(len > 0) { int remaining = stream->data->line_size - stream->data->line_offset; if(remaining >= (int)len) { memcpy(&stream->data->line[stream->data->line_offset], buffer, len); stream->data->line_offset += len; break; } else { memcpy(&stream->data->line[stream->data->line_offset], buffer, remaining); logger_handle_msg_text(stream->data->handle, stream->data->level, stream->data->line, stream->data->line_size); stream->data->line_offset = 0; len -= remaining; } } return len_; } static ya_result logger_output_stream_flush(output_stream* stream_) { (void)stream_; //logger_flush(); return SUCCESS; } static void logger_output_stream_close(output_stream* stream_) { logger_output_stream* stream = (logger_output_stream*)stream_; free(stream->data->line); ZFREE_OBJECT(stream->data); output_stream_set_void(stream_); } static const output_stream_vtbl logger_output_stream_vtbl = { logger_output_stream_write, logger_output_stream_flush, logger_output_stream_close, "logger_output_stream", }; ya_result logger_output_stream_open(output_stream* stream, logger_handle *handle, u16 level, u32 max_line_len) { if(stream == NULL || handle == NULL || level == 0 || max_line_len < 64 || max_line_len > 65536) { return INVALID_ARGUMENT_ERROR; } logger_output_stream_data *data; ZALLOC_OBJECT_OR_DIE( data, logger_output_stream_data, LGOSDATA_TAG); data->handle = handle; data->level = level; MALLOC_OR_DIE(char*, data->line, max_line_len, LGOSLINE_TAG); data->line_offset = 0; data->line_size = max_line_len; stream->data = data; stream->vtbl = &logger_output_stream_vtbl; return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/logger.c0000644000000000000000000000013114505005532020752 xustar000000000000000030 mtime=1695812442.485982804 29 atime=1695812445.79603021 30 ctime=1695812494.607729292 yadifa-2.6.5-11201/lib/dnscore/src/logger.c0000664000374500037450000001317414505005532020723 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/bytearray_output_stream.h" #include "dnscore/logger.h" #include "dnscore/format.h" static u32 log_memdump_ex_layout_mask = 0x000003ff; void log_memdump_set_layout(u32 group_mask, u32 separator_mask) { log_memdump_ex_layout_mask = ((group_mask << OSPRINT_DUMP_LAYOUT_GROUP_SHIFT) & OSPRINT_DUMP_LAYOUT_GROUP_MASK) | ((separator_mask << OSPRINT_DUMP_LAYOUT_SEPARATOR_SHIFT) & OSPRINT_DUMP_LAYOUT_SEPARATOR_MASK); } void log_memdump_ex(logger_handle* hndl, u32 level, const void* data_pointer_, ssize_t size_, ssize_t line_size, u32 flags) { /* * ensure there is an output for this handle/level */ if((hndl == NULL) || (level >= MSG_LEVEL_COUNT) || (hndl->channels[level].offset < 0)) { return; } output_stream os; bytearray_output_stream_context os_context; char buffer[1024]; #if DEBUG assert(line_size > 0); assert(line_size < (ssize_t)sizeof(buffer) / 8); memset(buffer, 0xba, sizeof(buffer)); #endif flags |= log_memdump_ex_layout_mask; bytearray_output_stream_init_ex_static(&os, (u8*)buffer, sizeof(buffer), 0, &os_context); const u8* data_pointer = (const u8*)data_pointer_; ssize_t size = size_; while(size > line_size) { osprint_dump_with_base(&os, data_pointer, line_size, line_size, flags, data_pointer_); u32 buffer_size = bytearray_output_stream_size(&os); logger_handle_msg_text(hndl, level, buffer, buffer_size); bytearray_output_stream_reset(&os); data_pointer += line_size; size -= line_size; } if(size > 0) { osprint_dump(&os, data_pointer, size, line_size, flags); u32 buffer_size = bytearray_output_stream_size(&os); logger_handle_msg_text(hndl, level, buffer, buffer_size); } output_stream_close(&os); } void log_memdump(logger_handle* hndl, u32 level, const void* data_pointer_, ssize_t size_, ssize_t line_size) { log_memdump_ex(hndl, level, data_pointer_, size_, line_size, OSPRINT_DUMP_HEXTEXT); } #if __unix__ void log_msghdr(logger_handle* hndl, u32 level, struct msghdr *hdr) { logger_handle_msg(hndl, level, "udp message header:"); if(hdr->msg_name != NULL ) { logger_handle_msg(hndl, level, "msg_name: %{sockaddr}", (struct sockaddr*)hdr->msg_name); log_memdump_ex(hndl, level, hdr->msg_name, hdr->msg_namelen, 32, OSPRINT_DUMP_BUFFER); } else { logger_handle_msg(hndl, level, "msg_name is NULL"); } if(hdr->msg_iov != NULL) { for(size_t i = 0; i < (size_t)hdr->msg_iovlen; i++) { struct iovec *msg_iov = &hdr->msg_iov[i]; if(msg_iov->iov_base != NULL) { logger_handle_msg(hndl, level, "msg_iov[%i]:", i); log_memdump_ex(hndl, level, msg_iov->iov_base, msg_iov->iov_len, 32, OSPRINT_DUMP_BUFFER); } else { logger_handle_msg(hndl, level, "msg_iov[%i] is NULL", i); } } } else { logger_handle_msg(hndl, level, "msg_iov is NULL"); } if(hdr->msg_control != NULL) { logger_handle_msg(hndl, level, "msg_control:"); log_memdump_ex(hndl, level, hdr->msg_control, hdr->msg_controllen, 32, OSPRINT_DUMP_BUFFER); } else { logger_handle_msg(hndl, level, "msg_control is NULL"); } logger_handle_msg(hndl, level, "msg_flags: %x", hdr->msg_flags); } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/logger_channel_file.c0000644000000000000000000000013214505005532023442 xustar000000000000000030 mtime=1695812442.439982145 30 atime=1695812445.794030182 30 ctime=1695812494.609729321 yadifa-2.6.5-11201/lib/dnscore/src/logger_channel_file.c0000664000374500037450000004101714505005532023407 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #include #include "dnscore/logger_channel_file.h" #include "dnscore/buffer_output_stream.h" #include "dnscore/file_output_stream.h" #include "dnscore/format.h" #include "dnscore/chroot.h" #include "dnscore/fdtools.h" #include "dnscore/thread_pool.h" #include "dnscore/process.h" /* * The new logger model does not requires MT protection on the channels */ #define FILE_CHANNEL_BUFFER_SIZE 65536 #define DEBUG_LOG_CHANNEL 0 typedef struct file_data file_data; struct file_data { output_stream os; char *file_name; int fd; uid_t uid; gid_t gid; u16 mode; bool force_flush; }; static ya_result logger_channel_file_constmsg(logger_channel* chan, int level, char* text, u32 text_len, u32 date_offset) { (void)level; (void)date_offset; file_data* sd = (file_data*)chan->data; output_stream_write(&sd->os, (const u8*)text, text_len); ya_result ret = output_stream_write(&sd->os, (const u8*)"\n", 1); if(sd->force_flush) { output_stream_flush(&sd->os); } return ret; } static ya_result logger_channel_file_vmsg(logger_channel* chan, int level, char* text, va_list args) { (void)level; file_data* sd = (file_data*)chan->data; vosformat(&sd->os, text, args); ya_result ret = output_stream_write(&sd->os, (const u8*)"\n", 1); if(sd->force_flush) { output_stream_flush(&sd->os); } return ret; } static ya_result logger_channel_file_msg(logger_channel* chan, int level, char* text, ...) { va_list args; va_start(args, text); ya_result ret = logger_channel_file_vmsg(chan, level, text, args); va_end(args); return ret; } static void logger_channel_file_flush(logger_channel* chan) { file_data* sd = (file_data*)chan->data; output_stream_flush(&sd->os); } static void logger_channel_file_close(logger_channel* chan) { file_data* sd = (file_data*)chan->data; output_stream_flush(&sd->os); output_stream_close(&sd->os); #if __unix__ chroot_unmanage_path(&sd->file_name); #endif free(sd->file_name); chan->vtbl = NULL; sd->os.data = NULL; sd->os.vtbl = NULL; free(chan->data); chan->data = NULL; } static ya_result logger_channel_file_append(const char *fullpath, uid_t uid, gid_t gid, u16 mode, file_data* sd) { #if DEBUG_LOG_CHANNEL osformatln(termerr, "logger_channel_file_append(%s, %i, %i, %o, %p)", fullpath, uid, gid, mode, sd); #endif output_stream errlog_os; output_stream buffered_errlog_os; ya_result return_code; if(FAIL(return_code = file_output_stream_open_ex_nolog( &errlog_os, fullpath, O_CREAT|O_APPEND|O_RDWR|O_CLOEXEC, mode))) { #if DEBUG_LOG_CHANNEL osformatln(termerr, "logger_channel_file_append(%s, %i, %i, %o, %p) failed at open", fullpath, uid, gid, mode, sd); #endif sd->fd = -1; return return_code; } /* * Change ownership of the file here. */ int fd = fd_output_stream_get_filedescriptor(&errlog_os); #if __unix__ if((getuid() != uid) || (getgid() != gid)) { if(fchown(fd, uid, gid) < 0) { #if DEBUG_LOG_CHANNEL osformatln(termerr, "logger_channel_file_append(%s, %i, %i, %o, %p) failed at fchown", fullpath, uid, gid, mode, sd); #endif return_code = ERRNO_ERROR; output_stream_close(&errlog_os); sd->fd = -1; return return_code; } } #endif sd->fd = fd; if(FAIL(return_code = buffer_output_stream_init(&buffered_errlog_os, &errlog_os, FILE_CHANNEL_BUFFER_SIZE))) { #if DEBUG_LOG_CHANNEL osformatln(termerr, "logger_channel_file_append(%s, %i, %i, %o, %p) failed at buffering", fullpath, uid, gid, mode, sd); #endif output_stream_close(&errlog_os); sd->fd = -1; return return_code; } sd->os.data = buffered_errlog_os.data; sd->os.vtbl = buffered_errlog_os.vtbl; return SUCCESS; } static ya_result logger_channel_file_reopen(logger_channel* chan) { ya_result return_code; file_data* sd = (file_data*)chan->data; struct timeval tv; struct tm t; #if DEBUG_LOG_CHANNEL osformatln(termerr, "logger_channel_file_reopen(%s)", sd->file_name); #endif #if DNSCORE_HAS_LOG_THREAD_TAG char thread_tag_buffer[9]; #endif output_stream_flush(&sd->os); sd->uid = logger_get_uid(); sd->gid = logger_get_gid(); /// /* open a new file stream */ output_stream errlog_os; if(FAIL(return_code = file_output_stream_open_ex_nolog( &errlog_os, sd->file_name, O_CREAT|O_APPEND|O_RDWR|O_CLOEXEC, sd->mode))) { #if DEBUG_LOG_CHANNEL osformatln(termerr, "failed to file_output_stream_open_ex_nolog(os,%s,CREATE+APPEND+RDWR,%o)", sd->file_name, sd->mode ); #endif logger_channel_file_flush(chan); gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &t); logger_channel_file_msg(chan, LOG_NOTICE, "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | %08x | %8s | N | unable to reopen '%s': %r, resuming on original", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, tv.tv_usec, getpid_ex(), thread_self(), "system", sd->file_name, return_code); logger_channel_file_flush(chan); return return_code; } /* change ownership of the file */ int fd = fd_output_stream_get_filedescriptor(&errlog_os); #if DEBUG_LOG_CHANNEL if(fd < 0) { osformatln(termerr, "failed to file_output_stream_open_ex_nolog(os,%s,CREATE+APPEND+RDWR,%o), got fd=-1 when everyting else looked fine", sd->file_name, sd->mode ); } #endif #if __unix__ if((getuid() != sd->uid) || (getgid() != sd->gid)) { if(fchown(fd, sd->uid, sd->gid) < 0) { #if DEBUG_LOG_CHANNEL osformatln(termerr, "failed to chown(%i,%i,%i)", fd, sd->uid, sd->gid ); #endif return_code = ERRNO_ERROR; output_stream_close(&errlog_os); logger_channel_file_flush(chan); gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &t); logger_channel_file_msg(chan, LOG_NOTICE, "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | %08x | %8s | N | unable to fchown '%s': %r, resuming on original", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, tv.tv_usec, getpid_ex(), thread_self(), "system", sd->file_name, return_code); logger_channel_file_flush(chan); return return_code; } } #endif logger_channel_file_flush(chan); gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &t); #if DNSCORE_HAS_LOG_THREAD_TAG thread_copy_tag_with_pid_and_tid(getpid_ex(), thread_self(), thread_tag_buffer); #endif logger_channel_file_msg(chan, LOG_NOTICE, #if (DEBUG || HAS_LOG_PID) && DNSCORE_HAS_LOG_THREAD_TAG "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-6i | %s | %8s | I | reopening '%s'", #elif DEBUG || (HAS_LOG_PID && HAS_LOG_THREAD_ID) "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-6i | %08x | %8s | I | reopening '%s'", #elif DNSCORE_HAS_LOG_THREAD_TAG "%04d-%02d-%02d %02d:%02d:%02d.%06d | %s | %8s | I | reopening '%s'", #elif HAS_LOG_THREAD_ID "%04d-%02d-%02d %02d:%02d:%02d.%06d | %08x | %8s | I | reopening '%s'", #elif HAS_LOG_PID "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-6i | %8s | I | reopening '%s'", #else "%04d-%02d-%02d %02d:%02d:%02d.%06d | %8s | I | reopening '%s'", #endif t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, tv.tv_usec, #if DEBUG || HAS_LOG_PID getpid_ex(), #endif #if DNSCORE_HAS_LOG_THREAD_TAG thread_tag_buffer, #else #if DEBUG || HAS_LOG_THREAD_ID thread_self(), #endif #endif "system", sd->file_name); logger_channel_file_flush(chan); #if DEBUG_LOG_CHANNEL osformatln(termerr, "so far so good: will exchange fds %i and %i in the channel", fd, sd->fd); #endif output_stream* fos = buffer_output_stream_get_filtered(&sd->os); /* exchange the file descriptors */ fd_output_stream_attach(fos, fd); fd_output_stream_attach(&errlog_os, sd->fd); sd->fd = fd; #if DEBUG_LOG_CHANNEL osformatln(termerr, "closing the stream supposed to contain", sd->fd); #endif file_output_stream_close_nolog(&errlog_os); // and NOT output_stream_close(&errlog_os); logger_channel_file_flush(chan); gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &t); logger_channel_file_msg(chan, LOG_NOTICE, #if (DEBUG || HAS_LOG_PID) && DNSCORE_HAS_LOG_THREAD_TAG "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-6i | %s | %8s | I | reopened '%s'", #elif DEBUG || (HAS_LOG_PID && HAS_LOG_THREAD_ID) "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-6i | %08x | %8s | I | reopened '%s'", #elif DNSCORE_HAS_LOG_THREAD_TAG "%04d-%02d-%02d %02d:%02d:%02d.%06d | %s | %8s | I | reopened '%s'", #elif HAS_LOG_THREAD_ID "%04d-%02d-%02d %02d:%02d:%02d.%06d | %08x | %8s | I | reopened '%s'", #elif HAS_LOG_PID "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-6i | %8s | I | reopened '%s'", #else "%04d-%02d-%02d %02d:%02d:%02d.%06d | %8s | I | reopened '%s'", #endif t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, tv.tv_usec, #if DEBUG || HAS_LOG_PID getpid_ex(), #endif #if DNSCORE_HAS_LOG_THREAD_TAG thread_tag_buffer, #else #if DEBUG || HAS_LOG_THREAD_ID thread_self(), #endif #endif "system", sd->file_name); logger_channel_file_flush(chan); return return_code; } static void logger_channel_file_sink(logger_channel* chan) { file_data* sd = (file_data*)chan->data; // fcntl(fd, F_GETFD); struct stat st; st.st_nlink = 0; fstat(sd->fd, &st); #if DEBUG_LOG_CHANNEL osformatln(termerr, "logger_channel_file_sink(%s = %i) (going to /dev/null): %r", sd->file_name, sd->fd, ERRNO_ERROR); #endif if(st.st_nlink == 0) { int ret = 0; // deleted // close and open /dev/null instead int dev_null = open_ex("/dev/null", O_WRONLY); if(dev_null >= 0) { #if DEBUG_LOG_CHANNEL osformatln(termerr, "logger_channel_file_sink(%s) file is not referenced anymore: sinking it to /dev/null with fd=%i", sd->file_name, dev_null); #endif if(ISOK(ret = dup2_ex(dev_null, sd->fd))) { close_ex(dev_null); /* if(ret < 0) { close_ex(sd->fd); sd->fd = -1; } */ } else { #if DEBUG_LOG_CHANNEL osformatln(termerr, "logger_channel_file_sink(%s) dup_ex(%i,%i) failed (%r)", sd->file_name, ret); #endif // more involved work #if DEBUG_LOG_CHANNEL osformatln(termerr, "instead will put fd %i in the channel, replacing %i", dev_null, sd->fd); #endif output_stream* fos = buffer_output_stream_get_filtered(&sd->os); /* exchange the file descriptors */ fd_output_stream_attach(fos, dev_null); if(sd->fd >= 0) { #if DEBUG_LOG_CHANNEL osformatln(termerr, "closing the contained file descriptor %i", sd->fd); #endif close_ex(sd->fd); } sd->fd = dev_null; } } else { #if DEBUG_LOG_CHANNEL osformatln(termerr, "logger_channel_file_sink(%s) failed to open /dev/null : cannot sink the output", sd->file_name, ret); #endif } } else { #if DEBUG_LOG_CHANNEL osformatln(termerr, "logger_channel_file_sink(%s) file has still %i references", sd->file_name, st.st_nlink); #endif } } static const logger_channel_vtbl stream_vtbl = { logger_channel_file_constmsg, logger_channel_file_msg, logger_channel_file_vmsg, logger_channel_file_flush, logger_channel_file_close, logger_channel_file_reopen, logger_channel_file_sink, "file_channel" }; ya_result logger_channel_file_open(const char *fullpath, uid_t uid, gid_t gid, u16 mode, bool forceflush, logger_channel* chan) { if(chan == NULL) { osformatln(termerr, "tried to open file '%s' on uninitialised channel", fullpath); return OBJECT_NOT_INITIALIZED; } ya_result return_code; file_data* sd; MALLOC_OBJECT_OR_DIE(sd, file_data, 0x4d5254534e414843); /* CHANSTRM */ if(ISOK(return_code = logger_channel_file_append(fullpath, uid, gid, mode, sd))) { sd->file_name = strdup(fullpath); #if __unix__ chroot_manage_path(&sd->file_name, fullpath, FALSE); #endif sd->uid = uid; sd->gid = gid; sd->mode = mode; sd->force_flush = forceflush; chan->data = sd; chan->vtbl = &stream_vtbl; } else { free(sd); } return return_code; } ya_result logger_channel_file_rename(logger_channel *chan, const char *newpath) { file_data* sd = (file_data*)chan->data; if(sd != NULL) { if(strcmp(sd->file_name, newpath) != 0) { free(sd->file_name); sd->file_name = strdup(newpath); return SUCCESS; } } return INVALID_STATE_ERROR; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/logger_channel_pipe.c0000644000000000000000000000013214505005532023460 xustar000000000000000030 mtime=1695812442.415981801 30 atime=1695812445.793030168 30 ctime=1695812494.611729349 yadifa-2.6.5-11201/lib/dnscore/src/logger_channel_pipe.c0000664000374500037450000002560714505005532023434 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #include #include "dnscore/logger_channel_pipe.h" #include "dnscore/buffer_output_stream.h" #include "dnscore/file_output_stream.h" #include "dnscore/format.h" #include "dnscore/chroot.h" #include "dnscore/fdtools.h" #include "dnscore/thread_pool.h" #include "dnscore/popen-output-stream.h" #include "dnscore/process.h" #define PIPE_CHANNEL_BUFFER_SIZE 65536 struct pipe_data { output_stream os; char *command; bool force_flush; }; typedef struct pipe_data pipe_data; static ya_result logger_channel_pipe_append(const char *command, pipe_data* sd); static ya_result logger_channel_pipe_constmsg(logger_channel* chan, int level, char* text, u32 text_len, u32 date_offset) { (void)level; (void)date_offset; pipe_data* sd = (pipe_data*)chan->data; output_stream_write(&sd->os, (const u8*)text, text_len); ya_result ret = output_stream_write(&sd->os, (const u8*)"\n", 1); if(ret == MAKE_ERRNO_ERROR(EPIPE)) { output_stream_flush(&sd->os); output_stream_close(&sd->os); output_stream_set_sink(&sd->os); if(ISOK(ret = logger_channel_pipe_append(sd->command, sd))) { output_stream_write(&sd->os, (const u8*)text, text_len); ret = output_stream_write(&sd->os, (const u8*)"\n", 1); if(ret == MAKE_ERRNO_ERROR(EPIPE)) { output_stream_flush(&sd->os); output_stream_close(&sd->os); output_stream_set_sink(&sd->os); // no third chance } } else { output_stream_set_sink(&sd->os); } } if(sd->force_flush) { output_stream_flush(&sd->os); } return ret; } static ya_result logger_channel_pipe_vmsg(logger_channel* chan, int level, char* text, va_list args) { (void)level; pipe_data* sd = (pipe_data*)chan->data; vosformat(&sd->os, text, args); ya_result ret = output_stream_write(&sd->os, (const u8*)"\n", 1); if(ret == MAKE_ERRNO_ERROR(EPIPE)) { // the child is probably dead as the connection has been closed // close our side output_stream_flush(&sd->os); output_stream_close(&sd->os); // sink it for now output_stream_set_sink(&sd->os); // try to pipe again if(ISOK(ret = logger_channel_pipe_append(sd->command, sd))) { vosformat(&sd->os, text, args); ret = output_stream_write(&sd->os, (const u8*)"\n", 1); if(ret == MAKE_ERRNO_ERROR(EPIPE)) { output_stream_flush(&sd->os); output_stream_close(&sd->os); output_stream_set_sink(&sd->os); // no third chance } } else { // sink output_stream_set_sink(&sd->os); } } if(sd->force_flush) { output_stream_flush(&sd->os); } return ret; } static ya_result logger_channel_pipe_msg(logger_channel* chan, int level, char* text, ...) { va_list args; va_start(args, text); ya_result ret = logger_channel_pipe_vmsg(chan, level, text, args); va_end(args); return ret; } static void logger_channel_pipe_flush(logger_channel* chan) { pipe_data* sd = (pipe_data*)chan->data; output_stream_flush(&sd->os); } static void logger_channel_pipe_close(logger_channel* chan) { pipe_data* sd = (pipe_data*)chan->data; output_stream_flush(&sd->os); output_stream_close(&sd->os); #if __unix__ chroot_unmanage_path(&sd->command); #endif free(sd->command); chan->vtbl = NULL; sd->os.data = NULL; sd->os.vtbl = NULL; free(chan->data); chan->data = NULL; } static ya_result logger_channel_pipe_append(const char *command, pipe_data* sd) { // fork & exec popen_output_stream_parameters params; params.uid = logger_get_uid(); params.gid = logger_get_gid(); ya_result ret = popen_output_stream_ex(&sd->os, command, ¶ms); if(ISOK(ret)) { ret = buffer_output_stream_init(&sd->os, &sd->os, PIPE_CHANNEL_BUFFER_SIZE); } return ret; } static ya_result logger_channel_pipe_reopen(logger_channel* chan) { ya_result ret; pipe_data* sd = (pipe_data*)chan->data; struct timeval tv; struct tm t; #if DNSCORE_HAS_LOG_THREAD_TAG char thread_tag_buffer[9]; #endif logger_channel_pipe_flush(chan); gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &t); #if DNSCORE_HAS_LOG_THREAD_TAG thread_copy_tag_with_pid_and_tid(getpid_ex(), thread_self(), thread_tag_buffer); #endif logger_channel_pipe_msg(chan, LOG_NOTICE, #if (DEBUG || HAS_LOG_PID) && DNSCORE_HAS_LOG_THREAD_TAG "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | %s | %8s | I | reopening '%s'", #elif DEBUG || (HAS_LOG_PID && HAS_LOG_THREAD_ID) "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | %08x | %8s | I | reopening '%s'", #elif DNSCORE_HAS_LOG_THREAD_TAG "%04d-%02d-%02d %02d:%02d:%02d.%06d | %s | %8s | I | reopening '%s'", #elif HAS_LOG_THREAD_ID "%04d-%02d-%02d %02d:%02d:%02d.%06d | %08x | %8s | I | reopening '%s'", #elif HAS_LOG_PID "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | %8s | I | reopening '%s'", #else "%04d-%02d-%02d %02d:%02d:%02d.%06d | %8s | I | reopening '%s'", #endif t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, tv.tv_usec, // t is initialized at line 338 (localtime_r) #if DEBUG || HAS_LOG_PID getpid(), #endif #if DNSCORE_HAS_LOG_THREAD_TAG thread_tag_buffer, #else #if DEBUG || HAS_LOG_THREAD_ID thread_self(), #endif #endif "system", sd->command); logger_channel_pipe_flush(chan); output_stream_flush(&sd->os); output_stream_close(&sd->os); output_stream_set_sink(&sd->os); if(FAIL(ret = logger_channel_pipe_append(sd->command, sd))) { output_stream_set_sink(&sd->os); } gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &t); logger_channel_pipe_msg(chan, LOG_NOTICE, #if (DEBUG || HAS_LOG_PID) && DNSCORE_HAS_LOG_THREAD_TAG "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | %s | %8s | I | reopened '%s'", #elif DEBUG || (HAS_LOG_PID && HAS_LOG_THREAD_ID) "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | %08x | %8s | I | reopened '%s'", #elif DNSCORE_HAS_LOG_THREAD_TAG "%04d-%02d-%02d %02d:%02d:%02d.%06d | %s | %8s | I | reopened '%s'", #elif HAS_LOG_THREAD_ID "%04d-%02d-%02d %02d:%02d:%02d.%06d | %08x | %8s | I | reopened '%s'", #elif HAS_LOG_PID "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | %8s | I | reopened '%s'", #else "%04d-%02d-%02d %02d:%02d:%02d.%06d | %8s | I | reopened '%s'", #endif t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, tv.tv_usec, #if DEBUG || HAS_LOG_PID getpid(), #endif #if DNSCORE_HAS_LOG_THREAD_TAG thread_tag_buffer, #else #if DEBUG || HAS_LOG_THREAD_ID thread_self(), #endif #endif "system", sd->command); logger_channel_pipe_flush(chan); return ret; } static void logger_channel_pipe_sink(logger_channel* chan) { pipe_data* sd = (pipe_data*)chan->data; // (void)sd; } static const logger_channel_vtbl stream_vtbl = { logger_channel_pipe_constmsg, logger_channel_pipe_msg, logger_channel_pipe_vmsg, logger_channel_pipe_flush, logger_channel_pipe_close, logger_channel_pipe_reopen, logger_channel_pipe_sink, "pipe_channel" }; ya_result logger_channel_pipe_open(const char *fullpath, bool forceflush, logger_channel* chan) { if(chan == NULL) { osformatln(termerr, "tried to open pipe '%s' on uninitialised channel", fullpath); return OBJECT_NOT_INITIALIZED; } ya_result ret; pipe_data* sd; MALLOC_OBJECT_OR_DIE(sd, pipe_data, 0x4d5254534e414843); /* CHANSTRM */ if(ISOK(ret = logger_channel_pipe_append(fullpath, sd))) { sd->command = strdup(fullpath); //chroot_manage_path(&sd->command, fullpath, FALSE); sd->force_flush = forceflush; chan->data = sd; chan->vtbl = &stream_vtbl; } else { free(sd); } return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/logger_channel_stream.c0000644000000000000000000000013214505005532024016 xustar000000000000000030 mtime=1695812442.400981587 30 atime=1695812445.792030153 30 ctime=1695812494.613729378 yadifa-2.6.5-11201/lib/dnscore/src/logger_channel_stream.c0000664000374500037450000001244214505005532023763 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/logger_channel_stream.h" #include "dnscore/logger_handle.h" #include "dnscore/output_stream.h" #include "dnscore/format.h" /* * The new logger model does not requires MT protection on the channels */ typedef struct stream_data stream_data; struct stream_data { output_stream os; bool force_flush; }; static ya_result logger_channel_stream_constmsg(logger_channel* chan, int level, char* text, u32 text_len, u32 date_offset) { (void)level; (void)date_offset; stream_data* sd = (stream_data*)chan->data; output_stream_write(&sd->os, (const u8*)text, text_len); ya_result ret = output_stream_write(&sd->os, (const u8*)"\n", 1); if(sd->force_flush) { output_stream_flush(&sd->os); } return ret; } static ya_result logger_channel_stream_vmsg(logger_channel* chan, int level, char* text, va_list args) { (void)level; stream_data* sd = (stream_data*)chan->data; vosformat(&sd->os, text, args); ya_result ret = output_stream_write(&sd->os, (const u8*)"\n", 1); if(sd->force_flush) { output_stream_flush(&sd->os); } return ret; } static ya_result logger_channel_stream_msg(logger_channel* chan, int level, char* text, ...) { va_list args; va_start(args, text); ya_result ret = logger_channel_stream_vmsg(chan, level, text, args); va_end(args); return ret; } static void logger_channel_stream_flush(logger_channel* chan) { stream_data* sd = (stream_data*)chan->data; output_stream_flush(&sd->os); } static void logger_channel_stream_close(logger_channel* chan) { stream_data* sd = (stream_data*)chan->data; output_stream_flush(&sd->os); output_stream_close(&sd->os); chan->vtbl = NULL; sd->os.data = NULL; sd->os.vtbl = NULL; free(chan->data); chan->data = NULL; } static ya_result logger_channel_stream_reopen(logger_channel* chan) { stream_data* sd = (stream_data*)chan->data; // there is no way to reopen a steam, simply flush its current contents output_stream_flush(&sd->os); return SUCCESS; } static void logger_channel_steam_sync(logger_channel* chan) { (void)chan; } static const logger_channel_vtbl stream_vtbl = { logger_channel_stream_constmsg, logger_channel_stream_msg, logger_channel_stream_vmsg, logger_channel_stream_flush, logger_channel_stream_close, logger_channel_stream_reopen, logger_channel_steam_sync, "stream_channel" }; /* * Takes ownership of the stream. * The stream will be unusable by the caller at the return of this function */ void logger_channel_stream_open(output_stream* os, bool forceflush, logger_channel* chan) { if(chan == NULL) { osformatln(termerr, "tried to open stream on uninitialised channel"); return; } stream_data* sd; MALLOC_OBJECT_OR_DIE(sd, stream_data, 0x4d5254534e414843); /* CHANSTRM */ sd->os.data = os->data; sd->os.vtbl = os->vtbl; sd->force_flush = forceflush; /* NOTE: Do NOT use a black hole. * Let the application crashes if it tries to use a stream it does not own anymore */ os->data = NULL; os->vtbl = NULL; chan->data = sd; chan->vtbl = &stream_vtbl; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/logger_channel_syslog.c0000644000000000000000000000013114505005532024042 xustar000000000000000030 mtime=1695812442.497982976 29 atime=1695812445.79603021 30 ctime=1695812494.615729407 yadifa-2.6.5-11201/lib/dnscore/src/logger_channel_syslog.c0000664000374500037450000001323114505005532024005 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #define LOGGER_CHANNEL_SYSLOG_MULTITHREADED 0 #define SYSLOG_IS_THREADSAFE 0 #if !LOGGER_CHANNEL_SYSLOG_MULTITHREADED #undef SYSLOG_IS_THREADSAFE #define SYSLOG_IS_THREADSAFE 1 #endif #if !SYSLOG_IS_THREADSAFE #include #endif #include "dnscore/logger_channel_syslog.h" #include "dnscore/sys_types.h" #include "dnscore/format.h" #define SYSLOG_MAX_LINE_SIZE 1024 #define SYSLOG_FORMATTING_ERROR_TEXT "internal syslog formatting error" #define SYSLOG_FORMATTING_ERROR_TEXT_LENGTH 33 struct logger_syslog_data { char* ident; int options; int facility; }; typedef struct logger_syslog_data logger_syslog_data; static ya_result logger_channel_syslog_constmsg(logger_channel* chan, int level, char* text, u32 text_len, u32 date_offset) { (void)chan; (void)text_len; if(level > LOG_DEBUG) { level = LOG_DEBUG; } syslog(level, "%s", &text[date_offset]); /* don't worry about not being a string literal */ return SUCCESS; } static ya_result logger_channel_syslog_msg(logger_channel* chan, int level, char* text, ...) { (void)chan; char tmp[SYSLOG_MAX_LINE_SIZE]; va_list args; va_start(args, text); ya_result return_code = vsnformat(tmp, sizeof(tmp), text, args); if(FAIL(return_code)) { memcpy(tmp, SYSLOG_FORMATTING_ERROR_TEXT, SYSLOG_FORMATTING_ERROR_TEXT_LENGTH); return_code = SYSLOG_FORMATTING_ERROR_TEXT_LENGTH; } syslog(level, "%s", tmp); va_end(args); return return_code; } static ya_result logger_channel_syslog_vmsg(logger_channel* chan, int level, char* text, va_list args) { (void)chan; char tmp[SYSLOG_MAX_LINE_SIZE]; ya_result return_code = vsnformat(tmp, sizeof(tmp), text, args); if(FAIL(return_code)) { memcpy(tmp, SYSLOG_FORMATTING_ERROR_TEXT, SYSLOG_FORMATTING_ERROR_TEXT_LENGTH); return_code = SYSLOG_FORMATTING_ERROR_TEXT_LENGTH; } /* * NOTE: LOG_DEBUG is the last supported level */ syslog(level & LOG_PRIMASK, "%s", tmp); return return_code; } static void logger_channel_syslog_flush(logger_channel* chan) { /* NOP */ (void)chan; } static void logger_channel_syslog_close(logger_channel* chan) { logger_syslog_data *sd = (logger_syslog_data*)chan->data; free(sd->ident); free(sd); closelog(); chan->data = NULL; chan->vtbl = NULL; } static ya_result logger_channel_syslog_reopen(logger_channel* chan) { logger_syslog_data *sd = (logger_syslog_data*)chan->data; closelog(); openlog(sd->ident, sd->options, sd->facility); return SUCCESS; } static void logger_channel_syslog_sync(logger_channel* chan) { (void)chan; } static const logger_channel_vtbl syslog_vtbl = { logger_channel_syslog_constmsg, logger_channel_syslog_msg, logger_channel_syslog_vmsg, logger_channel_syslog_flush, logger_channel_syslog_close, logger_channel_syslog_reopen, logger_channel_syslog_sync, "syslog_channel" }; void logger_channel_syslog_open(const char* ident, int options, int facility, logger_channel* chan) { if(chan == NULL) { osformatln(termerr, "tried to open syslog (%s) on uninitialised channel", ident); return; } logger_syslog_data *sd; MALLOC_OBJECT_OR_DIE(sd, logger_syslog_data, 0x4d5254534e414843); /* CHANSTRM */ sd->ident = strdup(ident); sd->options = options; sd->facility = facility; chan->data = sd; chan->vtbl = &syslog_vtbl; openlog(sd->ident, options, facility); } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/logger_handle.c0000644000000000000000000000012714505005532022272 xustar000000000000000029 mtime=1695812442.49198289 29 atime=1695812445.79603021 29 ctime=1695812494.61872945 yadifa-2.6.5-11201/lib/dnscore/src/logger_handle.c0000664000374500037450000043542114505005532022241 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logger Logging functions * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #if HAS_PTHREAD_SETNAME_NP #if DEBUG #define _GNU_SOURCE 1 #endif #endif #include #include #include #include #include #include #include #include #include #include #include "dnscore/logger_handle.h" #include "dnscore/logger_channel_stream.h" #include "dnscore/ptr_vector.h" #include "dnscore/zalloc.h" #include "dnscore/file_output_stream.h" #include "dnscore/file_input_stream.h" #include "dnscore/bytearray_output_stream.h" #include "dnscore/format.h" #include "dnscore/dnscore.h" #include "dnscore/process.h" #include "dnscore/async.h" #include "dnscore/ptr_set.h" #include "dnscore/thread_pool.h" #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED #include "dnscore/shared-circular-buffer.h" #include "dnscore/shared-heap.h" #include "dnscore/shared-heap-bytearray-output-stream.h" #else #include "dnscore/bytezarray_output_stream.h" #include "dnscore/threaded_queue.h" #include "dnscore/ipc.h" #endif #include "dnscore/buffer_output_stream.h" #include "dnscore/buffer_input_stream.h" #define LOGGER_HANDLE_TAG 0x4c444e48474f4c /* LOGHNDL */ #define LOGCHAN_TAG 0x4e414843474f4c /* LOGCHAN */ // If the logger thread queues a log message, and the log queue is full (ie: because the disk is full) a dead-lock may ensue. // So queued-logging is to be avoided in the logger thread // That being said, DEBUG_LOG_HANDLER and DEBUG_LOG_MESSAGES may trigger this issue as it is a debug, dev-only, feature. #if DNSCORE_HAS_LOG_THREAD_TAG void thread_tag_push_tags(); #endif #define DEBUG_LOG_HANDLER 0 // can be: 0 1 2, don't use for production #define DEBUG_LOG_MESSAGES 0 #define DEBUG_LOG_REGISTRATIONS 0 #if DEBUG_LOG_MESSAGES # pragma message("DEBUG_LOG_MESSAGES") // the space after the '#' is to ignore it on #pragma search #endif #define COLUMN_SEPARATOR " | " #define COLUMN_SEPARATOR_SIZE 3 #define MODULE_MSG_HANDLE g_system_logger #define LOGRMSG_TAG 0x47534d52474f4c #define LOGRTEXT_TAG 0x5458455452474f4c struct logger_handle; #define LOGGER_MESSAGE_TYPE_TEXT 0 // send a text to output #define LOGGER_MESSAGE_TYPE_STOP 1 // stop the service #define LOGGER_MESSAGE_TYPE_CHANNEL_FLUSH_ALL 2 // flush all channels #define LOGGER_MESSAGE_TYPE_CHANNEL_REOPEN_ALL 3 // reopen all channels #define LOGGER_MESSAGE_TYPE_CHANNEL_CLOSE_ALL 4 // close all channels #define LOGGER_MESSAGE_TYPE_CHANNEL_SINK_ALL 5 // sink all channels #define LOGGER_MESSAGE_TYPE_IGNORE 6 // no operation #define LOGGER_MESSAGE_TYPE_CHANNEL_GET_USAGE_COUNT 7 // grabs the number of uses of the channel, or -1 if not registered #define LOGGER_MESSAGE_TYPE_CHANNEL_REGISTER 8 // register a new channel #define LOGGER_MESSAGE_TYPE_CHANNEL_UNREGISTER 9 // unregister a channel #define LOGGER_MESSAGE_TYPE_HANDLE_CREATE 10 // open a new handle #define LOGGER_MESSAGE_TYPE_HANDLE_CLOSE 11 // close a handle #define LOGGER_MESSAGE_TYPE_HANDLE_NAME_ADD_CHANNEL 12 // add a channel to a handle identified by its name #define LOGGER_MESSAGE_TYPE_HANDLE_NAME_REMOVE_CHANNEL 13 // remove a channel from a handle identified by its name #define LOGGER_MESSAGE_TYPE_HANDLE_NAME_COUNT_CHANNELS 14 // return the number of channels linked to this logger #define LOGGER_MESSAGE_TYPE_THREAD_SET_TAG 15 // sets the tag for a thread ( + pid) #define LOGGER_MESSAGE_TYPE_THREAD_CLEAR_TAG 16 // clears the tag for a thread ( + pid) #define LOGGER_DISPATCHED_THREAD_STOPPED 0 #define LOGGER_DISPATCHED_THREAD_STARTED 1 #define LOGGER_DISPATCHED_THREAD_READY 2 #define LOGGER_DISPATCHED_THREAD_STOPPING 3 #define LOGGER_MESSAGE_SINK_FAKE ((logger_message*) 1) #define LOGGER_HANDLE_COUNT_MAX 16 #define LOGGER_HANDLE_SHARED_TABLE_SIZE (((sizeof(logger_handle) + 63) & ~63) * LOGGER_HANDLE_COUNT_MAX) static smp_int logger_thread_state = SMP_INT_INITIALIZER; struct logger_handle LOGGER_HANDLE_SINK_; struct logger_handle *LOGGER_HANDLE_SINK_PTR = &LOGGER_HANDLE_SINK_; static logger_handle *g_logger_handle_shared_table = NULL; struct logger_handle LOGGER_HANDLE_SINK_ = { {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U}, { PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY, PTR_VECTOR_EMPTY }, "SINK", "sink", 4, &LOGGER_HANDLE_SINK_PTR #if DEBUG , LOGGER_HANDLE_MAGIC_CHECK #endif }; struct logger_message_text_s { u8 type; // 0 0 u8 level; // u16 flags; // u16 text_length; // u16 text_buffer_length; // align 64 struct logger_handle *handle; // 8 8 u8 *text; // 12 16 #if SIZEOF_TIMEVAL <= 8 struct timeval tv; // 16 24 #else s64 timestamp; #endif const u8* prefix; // 24 32 u16 prefix_length; // 28 40 #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED s16 rc; // 30 42 reference count for the repeats #if DEBUG || HAS_LOG_PID pid_t pid; // 32 44 #endif #endif #if DEBUG || DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED || HAS_LOG_THREAD_ID || DNSCORE_HAS_LOG_THREAD_TAG thread_t thread_id; // 36 48 #endif // 40 56 }; struct logger_message_channel_flush_all_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; thread_t tid; // only used for debugging purposes }; struct logger_message_channel_reopen_all_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; }; struct logger_message_channel_sink_all_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; }; struct logger_message_channel_get_usage_count_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; const char* channel_name; s32 *countp; }; struct logger_message_channel_register_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; const char* channel_name; struct logger_channel *channel; }; struct logger_message_channel_unregister_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; const char* channel_name; }; /// @note no need for reopen struct logger_message_stop_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; }; /// @note no need for ignore struct logger_message_handle_create_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; const char *logger_name; logger_handle **handle_holder; }; struct logger_message_handle_close_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; const char *logger_name; }; struct logger_message_handle_add_channel_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; const char *logger_name; const char *channel_name; u16 level; }; struct logger_message_handle_remove_channel_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; const char *logger_name; const char *channel_name; }; struct logger_message_handle_count_channels_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; const char *logger_name; s32 *countp; }; #if DNSCORE_HAS_LOG_THREAD_TAG struct logger_message_thread_set_tag_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; char tag[THREAD_TAG_SIZE]; thread_t tid; }; struct logger_message_thread_clear_tag_s { u8 type; u8 val8; u16 val16; u32 val32; // align 64 async_wait_s *aw; thread_t tid; }; #endif struct logger_message { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED u8 reserved_for_the_queue; u8 align0; u16 align1; pid_t pid; // 4 4 #endif union { u8 type; struct logger_message_text_s text; struct logger_message_stop_s stop; // no specific data for ignore struct logger_message_channel_flush_all_s channel_flush_all; struct logger_message_channel_reopen_all_s channel_reopen_all; struct logger_message_channel_sink_all_s channel_sink_all; struct logger_message_channel_get_usage_count_s get_usage_count; struct logger_message_channel_register_s channel_register; struct logger_message_channel_unregister_s channel_unregister; struct logger_message_handle_create_s handle_create; struct logger_message_handle_close_s handle_close; struct logger_message_handle_add_channel_s handle_add_channel; struct logger_message_handle_remove_channel_s handle_remove_channel; struct logger_message_handle_count_channels_s handle_count_channels; #if DNSCORE_HAS_LOG_THREAD_TAG struct logger_message_thread_set_tag_s thread_set_tag; struct logger_message_thread_clear_tag_s thread_clear_tag; #endif }; }; typedef struct logger_message logger_message; /// tree set initialised empty with a comparator for ASCIIZ char* keys static ptr_set logger_channels = PTR_SET_ASCIIZ_EMPTY; static ptr_vector logger_handles = PTR_VECTOR_EMPTY; static mutex_t logger_mutex = MUTEX_INITIALIZER; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED struct shared_circular_buffer* logger_shared_queue = NULL; #else static threaded_queue logger_commit_queue = THREADED_QUEUE_EMPTY; #endif struct logger_shared_space_s { logger_message *_logger_sink_request_message; logger_message *_logger_reopen_request_message; }; typedef struct logger_shared_space_s logger_shared_space_t; static logger_shared_space_t logger_shared_space_null = {NULL, NULL}; static logger_shared_space_t *logger_shared_space = &logger_shared_space_null; static thread_t logger_thread_id = 0; static pid_t logger_thread_pid = -1; static u32 exit_level = MSG_CRIT; static const char acewnid[16 + 1] = "!ACEWNID1234567"; static volatile pid_t logger_handle_owner_pid = 0; static volatile bool _logger_started = FALSE; static volatile bool _logger_initialised = FALSE; #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED static volatile bool logger_is_client = FALSE; #endif static volatile bool logger_queue_initialised = FALSE; static volatile bool logger_handle_init_done = FALSE; static volatile u8 logger_level = MSG_ALL; static u8 logger_shared_heap_id = 0; static bool logger_initialised() { mutex_lock(&logger_mutex); bool ret = _logger_initialised; mutex_unlock(&logger_mutex); return ret; } static bool logger_started() { mutex_lock(&logger_mutex); bool ret = _logger_started; mutex_unlock(&logger_mutex); return ret; } static bool logger_initialised_and_started() { mutex_lock(&logger_mutex); bool ret = _logger_started && _logger_initialised; mutex_unlock(&logger_mutex); return ret; } #if DEBUG_LOG_MESSAGES static smp_int allocated_messages_count = SMP_INT_INITIALIZER; static time_t allocated_messages_count_stats_time = 0; #endif static void logger_handle_trigger_emergency_shutdown() { flusherr(); logger_flush(); abort(); } /******************************************************************************* * * Logger message functions * *******************************************************************************/ static inline logger_message* logger_message_alloc() { #ifdef NDEBUG size_t sizeof_logger_message = sizeof(logger_message); assert(sizeof_logger_message <= 64); (void)sizeof_logger_message; #endif logger_message* message; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message = (logger_message*)shared_circular_buffer_prepare_enqueue(logger_shared_queue); #if DEBUG memset(((u8*)message) + 1, 'Q', sizeof(logger_message) - 1); #endif #else ZALLOC_OBJECT_OR_DIE( message, logger_message, LOGRMSG_TAG); #if DEBUG memset(message, 'Q', sizeof(logger_message)); #endif #endif #if DEBUG_LOG_MESSAGES smp_int_inc(&allocated_messages_count); #endif return message; } #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED static inline logger_message* logger_message_try_alloc() { logger_message* message; message = (logger_message*)shared_circular_buffer_try_prepare_enqueue(logger_shared_queue); #if DEBUG if(message != NULL) { memset(&((u8*)message)[1], 'q', sizeof(logger_message) - 1); } #endif return message; } #endif #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED static inline void logger_message_free(logger_message *message) { ZFREE_OBJECT(message); #if DEBUG_LOG_MESSAGES smp_int_dec(&allocated_messages_count); #endif } #endif static inline void logger_message_post(void* message) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_enqueue(logger_shared_queue, message); #else threaded_queue_enqueue(&logger_commit_queue, message); #endif } /******************************************************************************* * * Logger handle functions * *******************************************************************************/ static ya_result logger_service_handle_remove_channel(logger_handle *handle, const char *channel_name); static void logger_service_handle_remove_all_channel(logger_handle *handle); /** * Returns true iff the current thread is the logger. * * @return true iff the current thread is the logger. */ bool logger_is_self() { return logger_thread_id == thread_self(); } #if 0 static int logger_handle_compare(const void* a, const void* b) { logger_handle* ha = (logger_handle*)a; logger_handle* hb = (logger_handle*)b; if(ha == hb) { return 0; } return strcmp(ha->name, hb->name); } #endif static int logger_handle_compare_match(const void* key, const void* value) { const char* hkey = (const char*)key; const logger_handle* hvalue = (const logger_handle*)value; return strcmp(hkey, hvalue->name); } static void logger_handle_free(void* ptr) { logger_handle* handle = (logger_handle*)ptr; #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_handle_free(%s@%p)", handle->name, ptr); flushout(); #endif logger_service_handle_remove_all_channel(handle); for(u8 lvl = 0; lvl < MSG_LEVEL_COUNT; lvl++) { ptr_vector_destroy(&handle->channels[lvl]); } if(handle->global_reference == NULL) { debug_osformatln(termerr, "bug: logger handle '%s' must be initialised to LOGGER_HANDLE_SINK but is set to NULL", handle->name); flusherr(); abort(); return; } if(*handle->global_reference != LOGGER_HANDLE_SINK) { *handle->global_reference = LOGGER_HANDLE_SINK; } #if DEBUG memset((char*)handle->formatted_name, 0xfe, strlen(handle->formatted_name)); #endif #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED free((char*)handle->formatted_name); #endif #if DEBUG memset((char*)handle->name, 0xfe, strlen(handle->name)); #endif #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED free((char*)handle->name); #endif #if DEBUG memset(handle, 0xfe, sizeof(logger_handle)); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED //shared_heap_free(handle); #else free(handle); #endif } /******************************************************************************* * * Logger channel functions * *******************************************************************************/ #define LOGGER_CHANNEL_COUNT_MAX 128 static logger_channel* logger_channel_shared_memory = NULL; static size_t logger_channel_shared_memory_avail = 0; static u8 logger_channel_allocated[LOGGER_CHANNEL_COUNT_MAX/8]; static inline size_t logger_channel_shared_memory_size() { return (LOGGER_CHANNEL_COUNT_MAX * sizeof(logger_channel) + 0xfff) & ~0xfff; } logger_channel* logger_channel_alloc() { if(logger_handle_owner_pid == 0) // don't know our pid yet { logger_handle_owner_pid = getpid_ex(); // update it, set us as the logger process } else if(logger_handle_owner_pid != getpid_ex()) // if we are not the logger process, this is very wrong { // no can do debug_osformatln(termerr, "logger_channel_alloc() cannot be called from this process"); return NULL; } if(logger_channel_shared_memory == NULL) { void *ptr = mmap(NULL, logger_channel_shared_memory_size(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); if(ptr == MAP_FAILED) { int err = ERRNO_ERROR; debug_osformatln(termerr, "logger_channel_alloc() shared memory allocation failed: %r", err); return NULL; } yassert(ptr != NULL); logger_channel_shared_memory = (logger_channel*)ptr; memset(logger_channel_shared_memory, 0U, logger_channel_shared_memory_size()); logger_channel_shared_memory_avail = logger_channel_shared_memory_size() / sizeof(logger_channel); memset(logger_channel_allocated, 0U, sizeof(logger_channel_allocated)); } logger_channel* chan; #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_channel_alloc()"); flushout(); #endif if(logger_channel_shared_memory_avail == 0) { return NULL; } chan = NULL; for(int i = 0; i < LOGGER_CHANNEL_COUNT_MAX/8; ++i) { if(logger_channel_allocated[i] != MAX_U8) { for(int j = 0; j < 8; ++j) { if((logger_channel_allocated[i] & (1 << j)) == 0) { logger_channel_allocated[i] |= 1 << j; chan = &logger_channel_shared_memory[(i << 3) + j]; chan->data = NULL; chan->vtbl = NULL; #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED /* dummy to avoid a NULL test */ logger_message* last_message = logger_message_alloc(); last_message->pid = getpid_ex(); last_message->type = LOGGER_MESSAGE_TYPE_TEXT; ZALLOC_ARRAY_OR_DIE(u8*, last_message->text.text, 1, LOGRTEXT_TAG); *last_message->text.text = '\0'; last_message->text.text_length = 1; last_message->text.text_buffer_length = 1; last_message->text.flags = 0; last_message->text.rc = 1; last_message->text.thread_id = thread_self(); chan->last_message = last_message; chan->last_message_count = 0; #endif chan->linked_handles = 0; return chan; } } } } return NULL; } static void logger_channel_free(logger_channel *channel) { if((channel == NULL) || (channel < logger_channel_shared_memory)) { return; } #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_channel_free(%p), linked to %d", channel, channel->linked_handles); flushout(); #endif size_t slot = (channel - logger_channel_shared_memory); if(slot > (sizeof(logger_channel_allocated) * 8)) { return; } if((logger_channel_allocated[slot >> 3] & (1 << (slot & 7))) == 0) { return; } assert(channel->linked_handles == 0); // don't yassert assert(logger_handle_owner_pid == getpid_ex()); #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED logger_message* last_message = channel->last_message; if(--last_message->text.rc == 0) { ZFREE_ARRAY(last_message->text.text, last_message->text.text_buffer_length); logger_message_free(last_message); } #endif if(channel->vtbl != NULL) { logger_channel_close(channel); channel->vtbl = NULL; } logger_channel_allocated[slot >> 3] &= ~(1 << (slot & 7)); ++logger_channel_shared_memory_avail; } static logger_channel* logger_service_channel_get(const char *channel_name) { logger_channel *channel = NULL; ptr_node *node = ptr_set_find(&logger_channels, channel_name); if(node != NULL) { channel = (logger_channel*)node->value; } #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_channel_get(%s) = %p", channel_name, channel); flushout(); #endif return channel; } static ya_result logger_service_channel_register(const char *channel_name, logger_channel *channel) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_channel_register(%s,%p)", channel_name, channel); flushout(); #endif if(channel->linked_handles != 0) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_channel_register(%s,%p) ALREADY LINKED", channel_name, channel); flushout(); #endif return LOGGER_CHANNEL_HAS_LINKS; } if(logger_service_channel_get(channel_name) != NULL) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_channel_register(%s,%p) NAME ALREADY USED", channel_name, channel); flushout(); #endif logger_channel_free(channel); return LOGGER_CHANNEL_ALREADY_REGISTERED; } ptr_node *node = ptr_set_insert(&logger_channels, strdup(channel_name)); node->value = channel; return SUCCESS; } static ya_result logger_service_channel_unregister(const char *channel_name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_channel_unregister(%s)", channel_name); flushout(); #endif logger_channel *channel; ptr_node *node = ptr_set_find(&logger_channels, channel_name); if(node == NULL) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_channel_unregister(%s) NAME NOT USED", channel_name); flushout(); #endif return LOGGER_CHANNEL_NOT_REGISTERED; } channel = (logger_channel*)node->value; if(channel->linked_handles != 0) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_channel_unregister(%s) STILL LINKED", channel_name); flushout(); #endif return LOGGER_CHANNEL_HAS_LINKS; } char *key = (char*)node->key; ptr_set_delete(&logger_channels, channel_name); free(key); // remove the channel from all the handles for(s32 i = 0; i < ptr_vector_size(&logger_handles); i++) { logger_handle *handle = (logger_handle*)ptr_vector_get(&logger_handles, i); logger_service_handle_remove_channel(handle, channel_name); } logger_channel_free(channel); return SUCCESS; } static void logger_service_channel_unregister_all() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_channel_unregister_all()"); flushout(); #endif // for all channels ptr_vector logger_channel_list = PTR_VECTOR_EMPTY; ptr_vector logger_name_list = PTR_VECTOR_EMPTY; ptr_set_iterator iter; ptr_set_iterator_init(&logger_channels, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); logger_channel *channel = (logger_channel*)node->value; char *channel_name = (char*)node->key; ptr_vector_append(&logger_name_list, channel_name); ptr_vector_append(&logger_channel_list, channel); } for(int i = 0; i <= ptr_vector_last_index(&logger_name_list); ++i) { char *channel_name = (char*)ptr_vector_get(&logger_name_list, i); #if DEBUG_LOG_HANDLER logger_channel *channel = (logger_channel*)ptr_vector_get(&logger_channel_list, i); debug_osformatln(termout, "logger_service_channel_unregister_all() : channel %s@%p", channel_name, channel); flushout(); #endif // for all handles for(s32 i = 0; i <= ptr_vector_last_index(&logger_handles); i++) { logger_handle *handle = (logger_handle*)ptr_vector_get(&logger_handles, i); #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_channel_unregister_all() : channel %s@%p : handle %s@%p", channel_name, channel, handle->name, handle); flushout(); #endif // remove channel from handle logger_service_handle_remove_channel(handle, channel_name); } #if DEBUG_LOG_HANDLER assert(channel->linked_handles == 0); #endif } for(int i = 0; i <= ptr_vector_last_index(&logger_name_list); ++i) { char *channel_name = (char*)ptr_vector_get(&logger_name_list, i); logger_channel *channel = (logger_channel*)ptr_vector_get(&logger_channel_list, i); logger_channel_free(channel); free(channel_name); } ptr_set_destroy(&logger_channels); ptr_vector_destroy(&logger_channel_list); ptr_vector_destroy(&logger_name_list); } /** * Used to find a channel in the channel array in a handle */ static int logger_handle_channel_compare_match(const void *a, const void *b) { const logger_channel* channel_a = (const logger_channel*)a; const logger_channel* channel_b = (const logger_channel*)b; if(channel_a == channel_b) { return 0; } return 1; } /** * INTERNAL: used by the service */ static logger_handle* logger_service_handle_create(const char *name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "[%i] logger_service_handle_create(%s)", getpid(), name); flushout(); #endif size_t name_len = strlen(name); if(name_len > LOGGER_HANDLE_NAME_SIZE_MAX) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "[%i] logger_service_handle_create(%s) : name is too big", getpid(), name); flushout(); #endif return NULL; } logger_handle* handle = (logger_handle*)ptr_vector_linear_search(&logger_handles, name, logger_handle_compare_match); if(handle == NULL) { s32 handle_index = ptr_vector_size(&logger_handles); assert(handle_index < LOGGER_HANDLE_COUNT_MAX); handle = &g_logger_handle_shared_table[handle_index]; memcpy(handle->name, name, name_len + 1); memset(handle->formatted_name, ' ', LOGGER_HANDLE_FORMATTED_NAME_SIZE_MAX); memcpy(handle->formatted_name, name, MIN(name_len, LOGGER_HANDLE_FORMATTED_NAME_SIZE_MAX)); handle->formatted_name[LOGGER_HANDLE_FORMATTED_NAME_SIZE_MAX] = '\0'; handle->enabled = TRUE; #if DEBUG handle->magic_check = LOGGER_HANDLE_MAGIC_CHECK; #endif int i; for(i = 0; i < MSG_LEVEL_COUNT; i++) { handle->active[i] = 0; ptr_vector_init(&handle->channels[i]); } ptr_vector_append(&logger_handles, handle); // this is a collection to keep track of the handles, not their storage } else { if(handle->enabled) { #if DEBUG_LOG_HANDLER debug_osformatln(termerr, "[%i] logger_service_handle_create(%s) : handle already created at %p", getpid(), name, handle); flusherr(); #endif } else { handle->enabled = TRUE; } } #if DEBUG_LOG_HANDLER debug_osformatln(termout, "[%i] logger_service_handle_create(%s) = %p", getpid(), name, handle); flushout(); #endif return handle; } static void logger_service_handle_close(const char *name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_handle_close(%s)", name); flushout(); #endif //logger_handle* handle = (logger_handle*)ptr_vector_search(&logger_handles, name, logger_handle_compare_match); logger_handle* handle = (logger_handle*)ptr_vector_linear_search(&logger_handles, name, logger_handle_compare_match); if(handle != NULL) { if(!handle->enabled) { return; } if(*handle->global_reference != LOGGER_HANDLE_SINK) { *handle->global_reference = LOGGER_HANDLE_SINK; // but the handle will still exist, only disabled } // decrement references for all channels used memset(handle->active, 0, sizeof(handle->active)); for(int lvl = 0; lvl < MSG_LEVEL_COUNT; lvl++) { for(s32 idx = 0; idx < ptr_vector_size(&handle->channels[lvl]); idx++) { logger_channel *channel = (logger_channel*)ptr_vector_get(&handle->channels[lvl], idx); ptr_vector_end_swap(&handle->channels[lvl], idx); ptr_vector_pop(&handle->channels[lvl]); channel->linked_handles--; } ptr_vector_destroy(&handle->channels[lvl]); } handle->enabled = FALSE; } // else the handle never existed } #if 0 static void logger_service_handle_close_all() { } #endif static inline logger_handle* logger_service_handle_get(const char *name) { logger_handle* handle = (logger_handle*)ptr_vector_linear_search(&logger_handles, name, logger_handle_compare_match); if((handle != NULL) && (!handle->enabled)) { handle = NULL; } return handle; } /** * INTERNAL: used by the service */ static ya_result logger_service_handle_add_channel(logger_handle *handle, int level, const char *channel_name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_handle_add_channel(%s@%p, %x, %s)", handle->name, handle, level, channel_name); flushout(); #endif assert(level >= 0 && level <= MSG_ALL_MASK); int lvl; int level_mask; logger_channel *channel = logger_service_channel_get(channel_name); if(channel == NULL) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_handle_add_channel(%s@%p, %x, %s) UNKNOWN CHANNEL", handle->name, handle, level, channel_name); flushout(); #endif return LOGGER_CHANNEL_NOT_REGISTERED; } // add the channel in every level required by the level mask for(lvl = 0U, level_mask = 1; level_mask <= MSG_ALL_MASK; lvl++, level_mask <<= 1) { if((level & level_mask) != 0) { if(ptr_vector_linear_search(&handle->channels[lvl], channel, logger_handle_channel_compare_match) == NULL) { ptr_vector_append(&handle->channels[lvl], channel); channel->linked_handles++; handle->active[lvl] = 1; } } } return SUCCESS; } static ya_result logger_service_handle_remove_channel(logger_handle *handle, const char *channel_name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_handle_remove_channel(%s@%p, %s)", handle->name, handle, channel_name); flushout(); #endif logger_channel *channel = logger_service_channel_get(channel_name); if(channel == NULL) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_handle_remove_channel(%s@%p, %s) UNKNOWN CHANNEL", handle->name, handle, channel_name); flushout(); #endif return LOGGER_CHANNEL_NOT_REGISTERED; } for(u8 lvl = 0; lvl <= MSG_ALL; lvl++) { s32 idx = ptr_vector_index_of(&handle->channels[lvl], channel, logger_handle_channel_compare_match); if(idx >= 0) { ptr_vector_end_swap(&handle->channels[lvl], idx); ptr_vector_pop(&handle->channels[lvl]); channel->linked_handles--; if(ptr_vector_isempty(&handle->channels[lvl])) { handle->active[lvl] = 0; } } } return SUCCESS; } static void logger_service_handle_remove_all_channel(logger_handle *handle) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_handle_remove_all_channel(%s@%p)", handle->name, handle); flushout(); #endif memset(handle->active, 0, sizeof(handle->active)); for(u8 lvl = 0; lvl < MSG_LEVEL_COUNT; lvl++) { for(s32 idx = 0; idx < ptr_vector_size(&handle->channels[lvl]); idx++) { logger_channel *channel = (logger_channel*)ptr_vector_get(&handle->channels[lvl], idx); channel->linked_handles--; } ptr_vector_clear(&handle->channels[lvl]); } } static ya_result logger_service_handle_count_channels(logger_handle *handle) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_handle_count_channels(%s@%p)", handle->name, handle); flushout(); #endif s32 sum = 0; for(u8 lvl = 0; lvl <= MSG_ALL; lvl++) { sum += ptr_vector_size(&handle->channels[lvl]); } return sum; } /** * INTERNAL: used inside the service (2) */ static void logger_service_flush_all_channels() { #if DEBUG_LOG_HANDLER > 1 debug_osformatln(termout, "logger_service_flush_all_channels()"); flushout(); #endif ptr_set_iterator iter; ptr_set_iterator_init(&logger_channels, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); logger_channel *channel = (logger_channel*)node->value; logger_channel_flush(channel); } } /** * INTERNAL: used inside the service (1) */ static void logger_service_reopen_all_channels() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_reopen_all_channels()"); flushout(); #endif ptr_set_iterator iter; ptr_set_iterator_init(&logger_channels, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); logger_channel *channel = (logger_channel*)node->value; ya_result return_code = logger_channel_reopen(channel); if(FAIL(return_code)) { log_try_err("could not reopen logger channel '%s': %r", STRNULL((char*)node->key), return_code); } } } /** * INTERNAL: used inside the service (1) */ static void logger_service_sink_all_channels() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_service_sink_all_channels()"); flushout(); #endif ptr_set_iterator iter; ptr_set_iterator_init(&logger_channels, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); logger_channel *channel = (logger_channel*)node->value; logger_channel_sink(channel); } } /** * * Create the handle tables * * INTERNAL: used at initialisation the service */ void logger_handle_exit_level(u32 level) { if(level <= MSG_CRIT) { debug_osformatln(termerr, "message level too low: %u < %u", level, MSG_CRIT); flusherr(); return; } exit_level = level; } #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED static void* logger_client_dispatcher_thread(void* context) { #if DNSCORE_HAS_LOG_THREAD_TAG static char loggercl_thread_tag[9] = "loggercl"; logger_handle_set_thread_tag(loggercl_thread_tag); #endif int sockfd; for(;;) { if((sockfd = ipc_client_connect("logger")) >= 0) { break; } } output_stream los; input_stream lis; fd_output_stream_attach_noclose(&los, sockfd); //buffer_output_stream_init(&los, &los, 4096); fd_input_stream_attach_noclose(&lis, sockfd); bool must_run = TRUE; while(must_run) { logger_message* message = (logger_message*)threaded_queue_try_dequeue(&logger_commit_queue); if(message == NULL) { output_stream_flush(&los); sleep(1); continue; } switch(message->type) { case LOGGER_MESSAGE_TYPE_TEXT: { struct logger_message_text_s *logger_message_text = (struct logger_message_text_s*)message; output_stream_write(&los, logger_message_text, offsetof(struct logger_message_text_s, text)); output_stream_write(&los, &logger_message_text->tv, sizeof(struct logger_message_text_s) - offsetof(struct logger_message_text_s, tv)); int len = strlen((const char*)logger_message_text->text); output_stream_write_u16(&los, len); output_stream_write(&los, logger_message_text->text, len); ZFREE_ARRAY(message->text.text, message->text.text_buffer_length); logger_message_free(message); break; } case LOGGER_MESSAGE_TYPE_STOP: { must_run = threaded_queue_size(&logger_commit_queue) > 0; if(must_run) { // repost logger_message_post(message); break; } u8 tmp; output_stream_write_u8(&los, message->type); input_stream_read_u8(&lis, &tmp); // process the sync (flush + process) async_wait_s *awp = message->stop.aw; logger_message_free(message); async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_CHANNEL_FLUSH_ALL: case LOGGER_MESSAGE_TYPE_CHANNEL_REOPEN_ALL: case LOGGER_MESSAGE_TYPE_CHANNEL_CLOSE_ALL: case LOGGER_MESSAGE_TYPE_CHANNEL_SINK_ALL: { u8 tmp; output_stream_write_u8(&los, message->type); input_stream_read_u8(&lis, &tmp); // process the sync (flush + process) async_wait_s *awp = message->channel_flush_all.aw; logger_message_free(message); async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_IGNORE: { logger_message_free(message); break; } default: { abort(); break; } } } output_stream_close(&los); input_stream_close(&lis); ipc_client_close(sockfd); logger_started = FALSE; return NULL; } static void* logger_server_dispatcher_client_thread(void* context) { output_stream los; input_stream lis; int *sockfdp = (int*)context; int sockfd = *sockfdp; ZFREE_OBJECT(sockfdp); fd_input_stream_attach_noclose(&lis, sockfd); //buffer_input_stream_init(&lis, &lis, 4096); fd_output_stream_attach_noclose(&los, sockfd); bool must_run = TRUE; logger_message* message = logger_message_alloc(); while(must_run) { if(input_stream_read_u8(&lis, &message->type) == 0) { continue; } switch(message->type) { case LOGGER_MESSAGE_TYPE_TEXT: { struct logger_message_text_s *logger_message_text = (struct logger_message_text_s*)message; input_stream_read(&lis, &logger_message_text->level, offsetof(struct logger_message_text_s, text) - 1); input_stream_read(&lis, &logger_message_text->tv, sizeof(struct logger_message_text_s) - offsetof(struct logger_message_text_s, tv)); u16 text_size = 0; input_stream_read_u16(&lis, &text_size); ZALLOC_ARRAY_OR_DIE(u8*, logger_message_text->text, logger_message_text->text_buffer_length, BYTE_ARRAY_OUTPUT_STREAM_BUFF_TAG); input_stream_read(&lis, logger_message_text->text, text_size); logger_message_post(message); message = logger_message_alloc(); break; } case LOGGER_MESSAGE_TYPE_STOP: { must_run = FALSE; /* must_run = threaded_queue_size(&logger_commit_queue) > 0; if(must_run) { // repost logger_message_post(message); message = logger_message_alloc(); } async_wait_progress(message->handle_close.aw, 1); */ break; } case LOGGER_MESSAGE_TYPE_CHANNEL_FLUSH_ALL: case LOGGER_MESSAGE_TYPE_CHANNEL_REOPEN_ALL: case LOGGER_MESSAGE_TYPE_CHANNEL_CLOSE_ALL: case LOGGER_MESSAGE_TYPE_CHANNEL_SINK_ALL: { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); message->channel_flush_all.aw = aw; #else async_wait_s aw; async_wait_init(&aw, 1); message->channel_flush_all.aw = &aw; #endif logger_message_post(message); while(logger_initialised_and_started()) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED if(async_wait_timeout(aw, ONE_SECOND_US)) { async_wait_destroy_shared(aw); break; } #else if(async_wait_timeout(&aw, ONE_SECOND_US)) { async_wait_finalize(&aw); break; } #endif } message = logger_message_alloc(); output_stream_write_u8(&los, 1); break; } default: { abort(); } } } logger_message_free(message); ipc_client_close(sockfd); return NULL; } static void* logger_server_dispatcher_thread(void* context) { #if DNSCORE_HAS_LOG_THREAD_TAG static char loggersr_thread_tag[9] = "loggersr"; logger_handle_set_thread_tag(loggersr_thread_tag); #endif int sockfd = ipc_server_listen("logger"); int ret; for(;;) { int clientfd = ipc_server_accept(sockfd); if(clientfd >= 0) { int *clientfdp; ZALLOC_OBJECT_OR_DIE(clientfdp, int, GENERIC); *clientfdp = clientfd; if((ret = thread_create(&logger_thread_id, logger_server_dispatcher_client_thread, clientfdp)) != 0) { } } } ipc_server_close(sockfd); return NULL; } #endif static void* logger_dispatcher_thread(void* context) { (void)context; #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger: dispatcher starting"); flushout(); #endif if(!smp_int_setifequal(&logger_thread_state, LOGGER_DISPATCHED_THREAD_STOPPED, LOGGER_DISPATCHED_THREAD_STARTED)) { debug_osformatln(termout, "logger_dispatcher_thread(%p) state expected to be LOGGER_DISPATCHED_THREAD_STOPPED", context); return NULL; } #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_dispatcher_thread(%p) started", context); flushout(); #endif thread_set_name("logger", 0U, 0); #if DNSCORE_HAS_LOG_THREAD_TAG thread_set_tag_with_pid_and_tid(getpid_ex(), thread_self(), "logger"); #endif output_stream baos; bytearray_output_stream_context baos_context; bytearray_output_stream_init_ex_static(&baos, NULL, 1024, BYTEARRAY_DYNAMIC, &baos_context); /* * Since I'll use this virtual call a lot, it's best to cache it. * (Actually it would be even better to use the static method) */ output_stream_write_method *baos_write = baos.vtbl->write; #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED char repeat_text[128]; #if DNSCORE_HAS_LOG_THREAD_TAG char thread_tag_buffer[12]; #endif #endif if(!smp_int_setifequal(&logger_thread_state, LOGGER_DISPATCHED_THREAD_STARTED, LOGGER_DISPATCHED_THREAD_READY)) { debug_osformatln(termout, "logger_dispatcher_thread(%p) state expected to be LOGGER_DISPATCHED_THREAD_STARTED", context); return NULL; } bool must_run = TRUE; while(must_run) { #if DEBUG_LOG_HANDLER > 1 debug_osformatln(termout, "logger: waiting for message"); flushout(); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED struct shared_circular_buffer_slot* slot = shared_circular_buffer_prepare_dequeue(logger_shared_queue); logger_message* message = (logger_message*)slot; #else logger_message* message = (logger_message*)threaded_queue_dequeue(&logger_commit_queue); #endif assert(message != NULL); #if DEBUG_LOG_HANDLER #if DEBUG_LOG_HANDLER > 1 debug_osformatln(termout, "logger: got message %p (%i) from %i:%p", message, message->type, message->pid, message->text.thread_id); flushout(); #else if(logger_thread_pid != getpid_ex()) { debug_osformatln(termout, "logger: got message %p (%i) from %i:%p", message, message->type, message->pid, message->text.thread_id); flushout(); } #endif if(kill(message->pid, 0) < 0) { debug_osformatln(termerr, "logger: got message %p (%i) from %i:%p : PID doesn't exist", message, message->type, message->pid, message->text.thread_id); flusherr(); } #endif /* * Reopen is not a message per se. * It has to be done "now" (ie: the disk is full, files have to be moved) * But if it was handled as a message, it would need to clear the queue before having an effect. * So instead a flag is used0 */ { mutex_lock(&logger_mutex); logger_message *logger_sink_request_message = logger_shared_space->_logger_sink_request_message; if(logger_sink_request_message != NULL) { logger_shared_space->_logger_sink_request_message = NULL; } logger_message *logger_reopen_request_message = logger_shared_space->_logger_reopen_request_message; if(logger_reopen_request_message != NULL) { logger_shared_space->_logger_reopen_request_message = NULL; } mutex_unlock(&logger_mutex); if(((intptr)logger_sink_request_message | (intptr)logger_reopen_request_message) != 0) { if(logger_sink_request_message != NULL) { logger_service_sink_all_channels(); if(logger_sink_request_message != LOGGER_MESSAGE_SINK_FAKE) { if(logger_sink_request_message->channel_sink_all.aw != NULL) { async_wait_progress(logger_sink_request_message->channel_sink_all.aw, 1); } logger_sink_request_message->channel_sink_all.aw = NULL; } } if(logger_reopen_request_message != NULL) { logger_service_reopen_all_channels(); if(logger_reopen_request_message->channel_sink_all.aw != NULL) { async_wait_progress(logger_reopen_request_message->channel_reopen_all.aw, 1); logger_reopen_request_message->channel_reopen_all.aw = NULL; } } } } switch(message->type) { case LOGGER_MESSAGE_TYPE_TEXT: { #if DEBUG_LOG_MESSAGES { time_t now = time(NULL); if(now - allocated_messages_count_stats_time > 10) { allocated_messages_count_stats_time = now; int val = smp_int_get(&allocated_messages_count); //debug_osformatln(termerr, "messages allocated count = %d", val); //flusherr(); osformat(&baos, "[LOGGER: %i messages allocated]\n", val); } } #endif logger_handle *handle = message->text.handle; u32 level = message->text.level; s32 channel_count = handle->channels[level].offset; if(channel_count < 0) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_free(message->text.text); shared_circular_buffer_commit_dequeue(logger_shared_queue); #else ZFREE_ARRAY(message->text.text, message->text.text_buffer_length); logger_message_free(message); #endif continue; } u32 date_header_len; if(message->text.flags == 0) { struct tm t; #if SIZEOF_TIMEVAL <= 8 localtime_r(&message->text.tv.tv_sec, &t); osformat(&baos, "%04d-%02d-%02d %02d:%02d:%02d.%06d", t.tm_year + 1900U, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, message->text.tv.tv_usec); #else time_t tv_sec = message->text.timestamp / ONE_SECOND_US; localtime_r(&tv_sec, &t); osformat(&baos, "%04d-%02d-%02d %02d:%02d:%02d.%06d", t.tm_year + 1900U, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, message->text.timestamp % ONE_SECOND_US); #endif baos_write(&baos, (const u8*)COLUMN_SEPARATOR, COLUMN_SEPARATOR_SIZE); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED format_dec_u64(message->pid, &baos, 6, ' ', FALSE); baos_write(&baos, (const u8*)COLUMN_SEPARATOR, COLUMN_SEPARATOR_SIZE); #else #if DEBUG || HAS_LOG_PID format_dec_u64(message->text.pid, &baos, 6, ' ', FALSE); baos_write(&baos, (const u8*)COLUMN_SEPARATOR, COLUMN_SEPARATOR_SIZE); #endif #endif #if DEBUG || HAS_LOG_THREAD_ID || DNSCORE_HAS_LOG_THREAD_TAG #if DNSCORE_HAS_LOG_THREAD_TAG baos_write(&baos, (const u8*)thread_get_tag_with_pid_and_tid(message->pid, message->text.thread_id), 8); #else osprint_u32_hex(&baos, (u32)message->text.thread_id); #endif baos_write(&baos, (const u8*)COLUMN_SEPARATOR, COLUMN_SEPARATOR_SIZE); #endif baos_write(&baos, (u8*)handle->formatted_name, LOGGER_HANDLE_FORMATTED_NAME_SIZE_MAX); baos_write(&baos, (const u8*)COLUMN_SEPARATOR, COLUMN_SEPARATOR_SIZE); osprint_char(&baos, acewnid[message->text.level & 15]); baos_write(&baos, (const u8*)COLUMN_SEPARATOR, COLUMN_SEPARATOR_SIZE); date_header_len = 29; } else { /* shortcut : assume both ones on since that's the only used case */ assert( (message->text.flags & (LOGGER_MESSAGE_TIMEMS | LOGGER_MESSAGE_PREFIX)) == (LOGGER_MESSAGE_TIMEMS | LOGGER_MESSAGE_PREFIX)); struct tm t; #if SIZEOF_TIMEVAL <= 8 localtime_r(&message->text.tv.tv_sec, &t); osformat(&baos, "%04d-%02d-%02d %02d:%02d:%02d.%03d", t.tm_year + 1900U, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, message->text.tv.tv_usec / 1000); baos_write(&baos, message->text.prefix, message->text.prefix_length); #else time_t tv_sec = message->text.timestamp / ONE_SECOND_US; localtime_r(&tv_sec, &t); osformat(&baos, "%04d-%02d-%02d %02d:%02d:%02d.%03d", t.tm_year + 1900U, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, (message->text.timestamp % ONE_SECOND_US) / 1000ULL); baos_write(&baos, message->text.prefix, message->text.prefix_length); #endif date_header_len = 24; } baos_write(&baos, message->text.text, message->text.text_length); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_free(message->text.text); shared_circular_buffer_commit_dequeue(logger_shared_queue); #endif output_stream_write_u8(&baos, 0); size_t size = bytearray_output_stream_size(&baos) - 1; char* buffer = (char*)bytearray_output_stream_buffer(&baos); logger_channel** channelp = (logger_channel**)handle->channels[level].data; do { logger_channel* channel = *channelp; ya_result return_code; #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED if((channel->last_message->text.text_length == message->text.text_length) && (memcmp(channel->last_message->text.text, message->text.text, message->text.text_length) == 0)) { /* match, it's a repeat */ channel->last_message_count++; } else { /* no match */ if(channel->last_message_count > 0) { /* log the repeat count */ /* If the same line is outputted twice : filter it to say 'repeated' instead of sending everything */ struct tm t; #if SIZE_TIMEVAL <= 8 localtime_r(&message->text.tv.tv_sec, &t); #else localtime_r(&message->text.timestamp / 1000000ULL, &t); #endif #if 1 #if DNSCORE_HAS_LOG_THREAD_TAG thread_copy_tag(channel->last_message->text.thread_id, thread_tag_buffer); #endif return_code = snformat(repeat_text, sizeof(repeat_text), #if (DEBUG || HAS_LOG_PID) && DNSCORE_HAS_LOG_THREAD_TAG "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | %s | -------- | N | last message repeated %d times", #elif DEBUG || (HAS_LOG_PID && HAS_LOG_THREAD_ID) "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | %08x | -------- | N | last message repeated %d times", #elif DNSCORE_HAS_LOG_THREAD_TAG "%04d-%02d-%02d %02d:%02d:%02d.%06d | %s | -------- | N | last message repeated %d times", #elif HAS_LOG_THREAD_ID "%04d-%02d-%02d %02d:%02d:%02d.%06d | %08x | -------- | N | last message repeated %d times", #elif HAS_LOG_PID "%04d-%02d-%02d %02d:%02d:%02d.%06d | %-5i | -------- | N | last message repeated %d times", #else "%04d-%02d-%02d %02d:%02d:%02d.%06d | -------- | N | last message repeated %d times", #endif t.tm_year + 1900U, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, #if SIZE_TIMEVAL <= 8 message->text.tv.tv_usec #else message->text.timestamp % ONE_SECOND_US #endif , #if DEBUG || HAS_LOG_PID getpid_ex(), #endif #if DNSCORE_HAS_LOG_THREAD_TAG thread_tag_buffer, #else #if DEBUG || HAS_LOG_THREAD_ID channel->last_message->text.thread_id, #endif #endif channel->last_message_count); #else return_code = snformat(repeat_text, sizeof(repeat_text), "%04d-%02d-%02d %02d:%02d:%02d.%06d" COLUMN_SEPARATOR #if DEBUG "%-5d" COLUMN_SEPARATOR "%08x" COLUMN_SEPARATOR #endif "--------" COLUMN_SEPARATOR "N" COLUMN_SEPARATOR "last message repeated %d times", t.tm_year + 1900U, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, #if SIZE_TIMEVAL <= 8 message->text.tv.tv_usec #else message->text.timestamp % ONE_SECOND_US #endif , #if DEBUG || HAS_LOG_PID channel->last_message->text.pid, #endif #if DEBUG || HAS_LOG_THREAD_ID || DNSCORE_HAS_LOG_THREAD_TAG channel->last_message->text.thread_id, #endif channel->last_message_count); #endif if(ISOK(return_code)) { while(FAIL(return_code = logger_channel_msg(channel, level, repeat_text, return_code, 29))) { if(stdstream_is_tty(termerr)) { debug_osformatln(termerr, "message write failed on channel: %r", return_code); flusherr(); } if(return_code == MAKE_ERRNO_ERROR(EBADF) || return_code == MAKE_ERRNO_ERROR(ENOSPC)) { logger_sink_requested = TRUE; } if(logger_sink_requested || logger_reopen_requested) { if(logger_sink_requested) { logger_service_sink_all_channels(); logger_sink_requested = FALSE; } if(logger_reopen_requested) { logger_service_reopen_all_channels(); logger_reopen_requested = FALSE; } } if(dnscore_shuttingdown()) { // message will be lost break; } sleep(1); } } else { if(stdstream_is_tty(termerr)) { debug_osformatln(termerr, "message formatting failed on channel: %r", return_code); flusherr(); } } } /* cleanup */ if(--channel->last_message->text.rc == 0) { /* free the message */ #if DEBUG_LOG_MESSAGES debug_osformatln(termout, "message rc is 0 (%s)", channel->last_message->text.text); flushout(); #endif ZFREE_ARRAY(channel->last_message->text.text, channel->last_message->text.text_buffer_length); logger_message_free(channel->last_message); } #if DEBUG_LOG_MESSAGES else { debug_osformatln(termout, "message rc decreased to %d (%s)", channel->last_message->text.rc, channel->last_message->text.text); flushout(); } channel->last_message = message; channel->last_message_count = 0; message->text.rc++; #endif #if DEBUG_LOG_MESSAGES debug_osformatln(termout, "message rc is %d (%s)", channel->last_message->text.rc, channel->last_message->text.text); flushout(); #endif #endif // !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED (no repeat compression) while(FAIL(return_code = logger_channel_msg(channel, level, buffer, size, date_header_len))) { if(stdstream_is_tty(termerr)) { debug_osformatln(termerr, "message write failed on channel: %r", return_code); flusherr(); } bool logger_sink_requested = FALSE; if((return_code == MAKE_ERRNO_ERROR(EBADF)) || (return_code == MAKE_ERRNO_ERROR(ENOSPC))) { logger_sink_requested = TRUE; } mutex_lock(&logger_mutex); logger_message *logger_sink_request_message = logger_shared_space->_logger_sink_request_message; if(logger_sink_request_message != NULL) { logger_shared_space->_logger_sink_request_message = NULL; } logger_message *logger_reopen_request_message = logger_shared_space->_logger_reopen_request_message; if(logger_reopen_request_message != NULL) { logger_shared_space->_logger_reopen_request_message = NULL; } mutex_unlock(&logger_mutex); if(logger_sink_request_message != NULL) { logger_service_sink_all_channels(); //logger_sink_requested = FALSE; if(logger_sink_request_message != LOGGER_MESSAGE_SINK_FAKE) { if(logger_sink_request_message->channel_sink_all.aw != NULL) { async_wait_progress(logger_sink_request_message->channel_sink_all.aw, 1); } logger_sink_request_message->channel_sink_all.aw = NULL; } } else if(logger_sink_requested) { logger_service_sink_all_channels(); //logger_sink_requested = FALSE; } if(logger_reopen_request_message != NULL) { logger_service_reopen_all_channels(); if(logger_reopen_request_message->channel_sink_all.aw != NULL) { async_wait_progress(logger_reopen_request_message->channel_reopen_all.aw, 1); logger_reopen_request_message->channel_reopen_all.aw = NULL; } } if(dnscore_shuttingdown()) { // message will be lost break; } sleep(1); } #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED } #endif channelp++; } while(--channel_count >= 0); #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED if(message->text.rc == 0) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "message has not been used (full dup): '%s'", message->text.text); flushout(); #endif ZFREE_ARRAY(message->text.text, message->text.text_buffer_length); logger_message_free(message); } #endif bytearray_output_stream_reset(&baos); break; } case LOGGER_MESSAGE_TYPE_CHANNEL_CLOSE_ALL: { async_wait_s *awp = message->channel_flush_all.aw; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif logger_service_flush_all_channels(); //logger_service_close_all_channels(); logger_service_channel_unregister_all(); async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_STOP: { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED must_run = shared_circular_buffer_size(logger_shared_queue) > 1; if(must_run) { // repost logger_message* new_message = (logger_message*)shared_circular_buffer_prepare_enqueue(logger_shared_queue); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED new_message->pid = getpid_ex(); #endif new_message->type = LOGGER_MESSAGE_TYPE_STOP; new_message->stop.aw = message->stop.aw; shared_circular_buffer_commit_dequeue(logger_shared_queue); shared_circular_buffer_commit_enqueue(logger_shared_queue, (struct shared_circular_buffer_slot*)new_message); } else { async_wait_s *awp = message->handle_close.aw; shared_circular_buffer_commit_dequeue(logger_shared_queue); // destroys the message but not the synchronisation structure. async_wait_progress(awp, 1); } #else must_run = threaded_queue_size(&logger_commit_queue) > 0; if(must_run) { // repost logger_message_post(message); } else { async_wait_s *awp = message->handle_close.aw; async_wait_progress(awp, 1); } #endif break; } /// @note fall through by design case LOGGER_MESSAGE_TYPE_CHANNEL_FLUSH_ALL: { async_wait_s *awp = message->channel_flush_all.aw; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif logger_service_flush_all_channels(); async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_CHANNEL_REOPEN_ALL: { // reopen is activated by a flag // this structure is just a way to fire the event async_wait_s *awp = message->channel_reopen_all.aw; if(awp != NULL) { if(stdstream_is_tty(termerr)) { debug_osformatln(termerr, "logger: unexpected synchronization point in reopen"); flusherr(); } async_wait_progress(awp, 1); } #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif break; } case LOGGER_MESSAGE_TYPE_CHANNEL_SINK_ALL: { // sink is activated by a flag // this structure is just a way to fire the event async_wait_s *awp = message->channel_sink_all.aw; if(awp != NULL) { if(stdstream_is_tty(termerr)) { debug_osformatln(termerr, "logger: unexpected synchronization point in sink"); flusherr(); } async_wait_progress(awp, 1); } #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif break; } case LOGGER_MESSAGE_TYPE_IGNORE: { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif break; } case LOGGER_MESSAGE_TYPE_CHANNEL_GET_USAGE_COUNT: { async_wait_s *awp = message->get_usage_count.aw; const char *channel_name = message->get_usage_count.channel_name; s32 *countp = message->get_usage_count.countp; assert(countp != NULL); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif logger_channel *channel = logger_service_channel_get(channel_name); if(channel != NULL) { *countp = channel->linked_handles; } else { *countp = -1; } async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_CHANNEL_REGISTER: { async_wait_s *awp = message->channel_register.aw; const char *channel_name = message->channel_register.channel_name; logger_channel *channel = message->channel_register.channel; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif logger_service_channel_register(channel_name, channel); async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_CHANNEL_UNREGISTER: { async_wait_s *awp = message->channel_unregister.aw; const char *channel_name = message->channel_unregister.channel_name; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif logger_service_channel_unregister(channel_name); async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_HANDLE_CREATE: { async_wait_s *awp = message->handle_create.aw; const char *name = message->handle_create.logger_name; logger_handle **handlep = message->handle_create.handle_holder; logger_handle* handle = logger_service_handle_create(name); handle->global_reference = handlep; *handlep = handle; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_HANDLE_CLOSE: { async_wait_s *awp = message->handle_close.aw; const char *name = message->handle_close.logger_name; //u32 name_len = message->text_length; logger_service_handle_close(name); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_HANDLE_NAME_ADD_CHANNEL: { logger_handle *handle; async_wait_s *awp = message->handle_add_channel.aw; const char *name = message->handle_add_channel.logger_name; int level = message->handle_add_channel.level; const char *channel_name = message->handle_add_channel.channel_name; handle = logger_service_handle_get(name); if(handle != NULL) { logger_service_handle_add_channel(handle, level, channel_name); } #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_HANDLE_NAME_REMOVE_CHANNEL: { logger_handle *handle; async_wait_s *awp = message->handle_remove_channel.aw; const char *name = message->handle_remove_channel.logger_name; const char *channel_name = message->handle_remove_channel.channel_name; handle = logger_service_handle_get(name); if(handle != NULL) { logger_service_handle_remove_channel(handle, channel_name); } #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_HANDLE_NAME_COUNT_CHANNELS: { logger_handle *handle; async_wait_s *awp = message->handle_count_channels.aw; const char *name = message->handle_count_channels.logger_name; handle = logger_service_handle_get(name); *message->handle_count_channels.countp = 0; if(handle != NULL) { *message->handle_count_channels.countp = logger_service_handle_count_channels(handle); } #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif async_wait_progress(awp, 1); break; } #if DNSCORE_HAS_LOG_THREAD_TAG case LOGGER_MESSAGE_TYPE_THREAD_SET_TAG: { async_wait_s *awp = message->thread_set_tag.aw; #if DEBUG #if DEBUG_LOG_REGISTRATIONS printf("logger: registering: pid=%i thread=%p tag=%c%c%c%c%c%c%c%c (printf)\n", message->pid, (void*)(intptr_t)message->thread_set_tag.tid, message->thread_set_tag.tag[0],message->thread_set_tag.tag[1],message->thread_set_tag.tag[2],message->thread_set_tag.tag[3], message->thread_set_tag.tag[4],message->thread_set_tag.tag[5],message->thread_set_tag.tag[6],message->thread_set_tag.tag[7]); debug_osformatln(termout, "logger: registering: pid=%i thread=%p tag=%c%c%c%c%c%c%c%c (printf)", message->pid, (void*)(intptr_t)message->thread_set_tag.tid, message->thread_set_tag.tag[0],message->thread_set_tag.tag[1],message->thread_set_tag.tag[2],message->thread_set_tag.tag[3], message->thread_set_tag.tag[4],message->thread_set_tag.tag[5],message->thread_set_tag.tag[6],message->thread_set_tag.tag[7]); #endif #endif #if DEBUG #if DEBUG_LOG_REGISTRATIONS log_try_debug("logger: registering: pid=%i thread=%p tag=%c%c%c%c%c%c%c%c (log_try_debug)", message->pid, message->thread_set_tag.tid, message->thread_set_tag.tag[0],message->thread_set_tag.tag[1],message->thread_set_tag.tag[2],message->thread_set_tag.tag[3], message->thread_set_tag.tag[4],message->thread_set_tag.tag[5],message->thread_set_tag.tag[6],message->thread_set_tag.tag[7]); #endif #endif thread_set_tag_with_pid_and_tid(message->pid, message->thread_set_tag.tid, message->thread_set_tag.tag); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif async_wait_progress(awp, 1); break; } case LOGGER_MESSAGE_TYPE_THREAD_CLEAR_TAG: { async_wait_s *awp = message->thread_clear_tag.aw; thread_clear_tag_with_pid_and_tid(message->pid, message->thread_clear_tag.tid); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_commit_dequeue(logger_shared_queue); #else logger_message_free(message); #endif async_wait_progress(awp, 1); break; } #endif default: { if(stdstream_is_tty(termerr)) { debug_osformatln(termerr, "unexpected message type %u in log queue", message->type); flusherr(); } break; } } } // while must run if(!smp_int_setifequal(&logger_thread_state, LOGGER_DISPATCHED_THREAD_READY, LOGGER_DISPATCHED_THREAD_STOPPING)) { debug_osformatln(termout, "logger_dispatcher_thread(%p) state expected to be LOGGER_DISPATCHED_THREAD_READY", context); return NULL; } // flush everything logger_service_flush_all_channels(); // close everything output_stream_close(&baos); #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_dispatcher_thread(%p) END", context); flushout(); #endif #if DNSCORE_HAS_LOG_THREAD_TAG thread_clear_tag_with_pid_and_tid(getpid_ex(), thread_self()); #endif if(!smp_int_setifequal(&logger_thread_state, LOGGER_DISPATCHED_THREAD_STOPPING, LOGGER_DISPATCHED_THREAD_STOPPED)) { debug_osformatln(termout, "logger_dispatcher_thread(%p) state expected to be LOGGER_DISPATCHED_THREAD_STOPPING", context); //return NULL; } return NULL; } s32 logger_channel_get_usage_count(const char* channel_name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_channel_get_usage_count(%s) ", channel_name); flushout(); #endif s32 count = -2; if(logger_is_running()) { logger_message *message = logger_message_alloc(); // ZEROMEMORY(message, sizeof(logger_message)); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_CHANNEL_GET_USAGE_COUNT; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->get_usage_count.aw = aw; #else message->get_usage_count.aw = &aw; #endif message->get_usage_count.channel_name = channel_name; message->get_usage_count.countp = &count; logger_message_post(message); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); #else async_wait(&aw); async_wait_finalize(&aw); #endif } else { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_lock(logger_shared_queue); #else mutex_lock(&logger_commit_queue.mutex); #endif logger_channel *channel = logger_service_channel_get(channel_name); if(channel != NULL) { count = channel->linked_handles; } else { count = -1; } #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_unlock(logger_shared_queue); #else mutex_unlock(&logger_commit_queue.mutex); #endif } return count; } void logger_channel_register(const char* channel_name, struct logger_channel *channel) { if((channel == NULL) || (channel->vtbl == NULL)) { debug_osformatln(termerr, "tried to register channel on uninitialised channel"); return; } #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_channel_register(%s,%p) ", channel_name, channel); flushout(); #endif if(logger_is_running()) { logger_message *message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_CHANNEL_REGISTER; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->channel_register.aw = aw; #else message->channel_register.aw = &aw; #endif message->channel_register.channel_name = channel_name; message->channel_register.channel = channel; logger_message_post(message); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); #else async_wait(&aw); async_wait_finalize(&aw); #endif } else { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_lock(logger_shared_queue); #else mutex_lock(&logger_commit_queue.mutex); #endif logger_service_channel_register(channel_name, channel); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_unlock(logger_shared_queue); #else mutex_unlock(&logger_commit_queue.mutex); #endif } } void logger_channel_unregister(const char* channel_name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_channel_unregister(%s) ", channel_name); flushout(); #endif logger_message *message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_CHANNEL_UNREGISTER; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->channel_unregister.aw = aw; #else message->channel_unregister.aw = &aw; #endif message->channel_unregister.channel_name = channel_name; logger_message_post(message); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); #else async_wait(&aw); async_wait_finalize(&aw); #endif } void logger_handle_create(const char *logger_name, logger_handle **handle_holder) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_handle_create(%s,%p) ", logger_name, handle_holder); flushout(); #endif if(logger_is_running()) { logger_message *message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_HANDLE_CREATE; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->handle_create.aw = aw; #else message->handle_create.aw = &aw; #endif message->handle_create.logger_name = logger_name; message->handle_create.handle_holder = handle_holder; logger_message_post(message); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); #else async_wait(&aw); async_wait_finalize(&aw); #endif } else { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_lock(logger_shared_queue); #else mutex_lock(&logger_commit_queue.mutex); #endif logger_handle* handle = logger_service_handle_create(logger_name); handle->global_reference = handle_holder; *handle_holder = handle; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_unlock(logger_shared_queue); #else mutex_unlock(&logger_commit_queue.mutex); #endif } } void logger_handle_close(const char *logger_name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_handle_close(%s) ", logger_name); flushout(); #endif logger_message *message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_HANDLE_CLOSE; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->handle_close.aw = aw; #else message->handle_close.aw = &aw; #endif message->handle_close.logger_name = logger_name; logger_message_post(message); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); #else async_wait(&aw); async_wait_finalize(&aw); #endif } void logger_handle_add_channel(const char *logger_name, int level, const char *channel_name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_handle_add_channel(%s,%x,%s) ", logger_name, level, channel_name); flushout(); #endif if(logger_is_running()) { logger_message *message = logger_message_alloc(); ZEROMEMORY(message, sizeof(logger_message)); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_HANDLE_NAME_ADD_CHANNEL; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->handle_add_channel.aw = aw; #else message->handle_add_channel.aw = &aw; #endif message->handle_add_channel.logger_name = logger_name; message->handle_add_channel.level = level; message->handle_add_channel.channel_name = channel_name; logger_message_post(message); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); #else async_wait(&aw); async_wait_finalize(&aw); #endif } else { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_lock(logger_shared_queue); #else mutex_lock(&logger_commit_queue.mutex); #endif logger_handle *handle = logger_service_handle_get(logger_name); if(handle != NULL) { logger_service_handle_add_channel(handle, level, channel_name); } #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_unlock(logger_shared_queue); #else mutex_unlock(&logger_commit_queue.mutex); #endif } } void logger_handle_remove_channel(const char *logger_name, const char *channel_name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_handle_remove_channel(%s,%s) ", logger_name, channel_name); flushout(); #endif logger_message *message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_HANDLE_NAME_REMOVE_CHANNEL; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->handle_remove_channel.aw = aw; #else message->handle_remove_channel.aw = &aw; #endif message->handle_remove_channel.logger_name = logger_name; message->handle_remove_channel.channel_name = channel_name; logger_message_post(message); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); #else async_wait(&aw); async_wait_finalize(&aw); #endif } /** * * Helper function. * Creates a logger for the given file descriptor (typically 1/stdout or 2/stderr) * * @param logger_name name of the logger * @param mask the mask to use (ie: MSG_ALL_MASK) * @param fd the file descriptor */ void logger_handle_create_to_fd(const char *logger_name, int mask, int fd) { logger_channel* channel = logger_channel_alloc(); output_stream stdout_os; fd_output_stream_attach(&stdout_os, dup(fd)); logger_channel_stream_open(&stdout_os, FALSE, channel); logger_channel_register("stdout", channel); logger_handle_create(logger_name, &g_system_logger); logger_handle_add_channel(logger_name, mask, "stdout"); } s32 logger_handle_count_channels(const char *logger_name) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_handle_count_channels(%s)", logger_name); flushout(); #endif logger_message *message = logger_message_alloc(); s32 ret = -2; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_HANDLE_NAME_COUNT_CHANNELS; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->handle_count_channels.aw = aw; #else message->handle_count_channels.aw = &aw; #endif message->handle_count_channels.logger_name = logger_name; message->handle_count_channels.countp = &ret; logger_message_post(message); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); #else async_wait(&aw); async_wait_finalize(&aw); #endif return ret; } #if DNSCORE_HAS_LOG_THREAD_TAG void logger_handle_set_thread_tag_with_pid_and_tid(pid_t pid, thread_t tid, const char tag[THREAD_TAG_SIZE]) { (void)pid; #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_handle_set_thread_tag_with_pid_and_tid(%i,%p) ", pid, tid, tag[0],tag[1],tag[2],tag[3], tag[4],tag[5],tag[6],tag[7]); flushout(); #endif logger_message *message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_THREAD_SET_TAG; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->thread_set_tag.aw = aw; #else message->thread_set_tag.aw = &aw; #endif memcpy(message->thread_set_tag.tag, tag, THREAD_TAG_SIZE); message->thread_set_tag.tid = tid; logger_message_post(message); #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_handle_set_thread_tag_with_pid_and_tid(%i,%p) (posted)", pid, tid, tag[0],tag[1],tag[2],tag[3], tag[4],tag[5],tag[6],tag[7]); flushout(); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); // does the finalize call #else async_wait(&aw); async_wait_finalize(&aw); #endif #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_handle_set_thread_tag_with_pid_and_tid(%i,%p) (synced, done)", pid, tid, tag[0],tag[1],tag[2],tag[3], tag[4],tag[5],tag[6],tag[7]); flushout(); #endif } void logger_handle_clear_thread_tag_with_pid_and_tid(pid_t pid, thread_t tid) { (void)pid; #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_handle_clear_thread_tag_with_pid_and_tid(%i,%p) ", pid, tid); flushout(); #endif logger_message *message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_THREAD_CLEAR_TAG; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->thread_clear_tag.aw = aw; #else message->thread_clear_tag.aw = &aw; #endif message->thread_clear_tag.tid = tid; logger_message_post(message); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); #else async_wait(&aw); async_wait_finalize(&aw); #endif } void logger_handle_set_thread_tag(const char tag[THREAD_TAG_SIZE]) { char clean_tag[THREAD_TAG_SIZE + 1]; memset(clean_tag, 0U, sizeof(clean_tag)); strcpy_ex(clean_tag, tag, sizeof(clean_tag)); if(logger_is_running()) { logger_handle_set_thread_tag_with_pid_and_tid(getpid_ex(), thread_self(), clean_tag); } else { thread_set_tag_with_pid_and_tid(getpid_ex(), thread_self(), clean_tag); } } void logger_handle_clear_thread_tag() { if(logger_is_running()) { logger_handle_clear_thread_tag_with_pid_and_tid(getpid_ex(), thread_self()); } else { thread_clear_tag_with_pid_and_tid(getpid_ex(), thread_self()); } } #endif static u32 logger_queue_size = LOG_QUEUE_DEFAULT_SIZE; #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED u32 logger_set_queue_size(u32 n) { if(n < LOG_QUEUE_MIN_SIZE) { n = LOG_QUEUE_MIN_SIZE; } else if(n > LOG_QUEUE_MAX_SIZE) { n = LOG_QUEUE_MAX_SIZE; } if(logger_queue_initialised && (logger_queue_size != n)) { logger_queue_size = n; logger_queue_size = threaded_queue_set_maxsize(&logger_commit_queue, logger_queue_size); } return logger_queue_size; } #endif void logger_init_ex(u32 queue_size, size_t shared_heap_size) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_init_ex(%u)", queue_size); flushout(); #endif if(!logger_initialised()) { logger_thread_pid = getpid_ex(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_init(); if(shared_heap_size == 0) { shared_heap_size = 0x4000000 + LOGGER_HANDLE_SHARED_TABLE_SIZE; // 64MB } for(;;) { ya_result ret; if(ISOK(ret = shared_heap_create(shared_heap_size))) { logger_shared_heap_id = (u8)ret; break; } if(shared_heap_size < 0x10000) { debug_osformatln(termerr, "logger: unable to allocate enough shared memory: %r", ret); flusherr(); exit(1); } shared_heap_size <<= 1; } g_logger_handle_shared_table = shared_heap_alloc(logger_shared_heap_id, LOGGER_HANDLE_SHARED_TABLE_SIZE); if(g_logger_handle_shared_table == NULL) { debug_osformatln(termerr, "logger: unable to allocate handle table"); flusherr(); exit(1); } memset(g_logger_handle_shared_table, 0U, LOGGER_HANDLE_SHARED_TABLE_SIZE); for(int i = 0; i < LOGGER_HANDLE_COUNT_MAX; ++i) { for(int j = 0; j < MSG_LEVEL_COUNT; ++j) { ptr_vector_init_empty(&g_logger_handle_shared_table[i].channels[j]); } } #endif if(!logger_queue_initialised) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED if(queue_size == 0) { logger_queue_size = 1024 * 1024; } logger_shared_queue = shared_circular_buffer_create_ex(20U, sizeof(logger_shared_space_t)); if(logger_shared_queue == NULL) { debug_osformatln(termerr, "logger: unable to allocate shared buffer: %r", ERRNO_ERROR); flusherr(); exit(1); } logger_shared_space = (logger_shared_space_t*)shared_circular_buffer_additional_space_ptr(logger_shared_queue); #else if(queue_size != 0) { logger_queue_size = queue_size; } threaded_queue_init(&logger_commit_queue, logger_queue_size); // not used anymore (replaced by a shared queue) #endif logger_queue_initialised = TRUE; } if(!logger_handle_init_done) { logger_handle_init_done = TRUE; ptr_vector_init(&logger_handles); format_class_init(); } #if __unix__ logger_set_uid(getuid()); logger_set_gid(getgid()); #endif logger_handle_create("system", &g_system_logger); mutex_lock(&logger_mutex); _logger_initialised = TRUE; mutex_unlock(&logger_mutex); } else { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_init_ex(%u) : already initialised", logger_queue_size); flushout(); #endif } } void logger_init() { logger_init_ex(logger_queue_size, 0 ); } void logger_start() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start() "); flushout(); #endif ya_result return_code; if(!logger_initialised()) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start() : not initialised yet : calling"); flushout(); #endif logger_init(); } if(logger_thread_pid != getpid_ex()) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start() : not initialised by the same process"); flushout(); #endif #if DNSCORE_HAS_LOG_THREAD_TAG // push all tags to the logger process thread_tag_push_tags(); #endif return; } mutex_lock(&logger_mutex); if(!_logger_started) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start() : starting"); flushout(); #endif if((return_code = thread_create(&logger_thread_id, logger_dispatcher_thread, NULL)) != 0) { mutex_unlock(&logger_mutex); debug_osformatln(termerr, "logger_start: pthread_create: %r", return_code); DIE(LOGGER_INITIALISATION_ERROR); } _logger_started = TRUE; mutex_unlock(&logger_mutex); } else { mutex_unlock(&logger_mutex); #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start() : already started"); flushout(); #endif } #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start() : started"); flushout(); #endif } #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED static thread_t logger_server_id = 0; void logger_start_server() { if(logger_initialised_and_started()) { int ret; if((ret = thread_create(&logger_server_id, logger_server_dispatcher_thread, NULL)) != 0) { debug_osformatln(termerr, "logger_start_server: pthread_create: %r", ret); DIE(LOGGER_INITIALISATION_ERROR); } } } void logger_stop_server() { pthread_cancel(logger_server_id); } void logger_start_client() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start_client() "); flushout(); #endif ya_result ret; if(!logger_initialised()) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start_client() : not initialised yet : calling"); flushout(); #endif logger_init(); } if(!logger_started()) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start_client() : starting"); flushout(); #endif if((ret = thread_create(&logger_thread_id, logger_client_dispatcher_thread, NULL)) != 0) { debug_osformatln(termerr, "logger_start: pthread_create: %r", ret); DIE(LOGGER_INITIALISATION_ERROR); } logger_is_client = TRUE; logger_started = TRUE; } else { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start_client() : already started"); flushout(); #endif } #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_start_client() : started"); flushout(); #endif } void logger_stop_client() { logger_stop(); //pthread_cancel(logger_thread_id); } #endif static void logger_send_message_stop_wait() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_send_message_stop_wait()"); flushout(); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif logger_message* message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_STOP; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->stop.aw = aw; #else message->stop.aw = &aw; #endif logger_message_post(message); #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_send_message_stop_wait() : waiting"); flushout(); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait(aw); async_wait_destroy_shared(aw); #else async_wait(&aw); async_wait_finalize(&aw); #endif #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_send_message_stop_wait() : should be stopped"); flushout(); #endif } u8 logger_set_shared_heap(u8 id) { u8 ret = logger_shared_heap_id; logger_shared_heap_id = id; return ret; } void logger_stop() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_stop()"); flushout(); #endif if(logger_initialised_and_started()) { // send the stop order if(logger_thread_pid == getpid_ex()) { logger_send_message_stop_wait(); #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_stop() : joining"); flushout(); #endif // wait for the end ya_result return_code; if((return_code = thread_join(logger_thread_id, NULL)) != 0) { flushout(); flusherr(); debug_osformatln(termerr, "logger_stop: thread_join: %r", return_code); flusherr(); } logger_thread_id = 0; mutex_lock(&logger_mutex); _logger_started = FALSE; mutex_unlock(&logger_mutex); } else { // not the owner } } #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_stop() : stopped"); flushout(); #endif } void logger_finalize() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize()"); flushout(); #endif if(logger_thread_pid != getpid_ex()) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize() : not owner"); flushout(); #endif return; } if(!logger_initialised()) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize() : not initialised"); flushout(); #endif return; } #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED if(!shared_circular_buffer_empty(logger_shared_queue)) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize() : queue is not empty : starting & flushing"); flushout(); #endif if(!logger_started()) { logger_start(); if(logger_wait_started()) { logger_flush(); } } else { logger_flush(); } } #else if(threaded_queue_size(&logger_commit_queue) > 0) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize() : queue is not empty : starting & flushing"); flushout(); #endif logger_start(); logger_flush(); } #endif if(logger_started()) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize() : still running : stopping"); flushout(); #endif logger_stop(); } /* * Ensure there is nothing left at all in the queue */ #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED while(!shared_circular_buffer_empty(logger_shared_queue)) { logger_message* message = (logger_message*)shared_circular_buffer_prepare_dequeue(logger_shared_queue); if(message->type == LOGGER_MESSAGE_TYPE_TEXT) { shared_heap_free(message->text.text); } shared_circular_buffer_commit_dequeue(logger_shared_queue); } #else while(threaded_queue_size(&logger_commit_queue) > 0) { logger_message* message = threaded_queue_dequeue(&logger_commit_queue); #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize() : freeing message of type %u", message->type); flushout(); #endif if(message->type == LOGGER_MESSAGE_TYPE_TEXT) { ZFREE_ARRAY(message->text.text, message->text.text_buffer_length); } logger_message_free(message); } #endif if(logger_handle_init_done) { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize() : flushing all channels"); flushout(); #endif logger_service_flush_all_channels(); // closes all handles if(logger_thread_pid == getpid_ex()) // logger_handle_owner_pid { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize() : closing all handles"); flushout(); #endif ptr_vector_callback_and_clear(&logger_handles, logger_handle_free); ptr_vector_destroy(&logger_handles); // closes all channels #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize() : closing all channels"); flushout(); #endif logger_service_channel_unregister_all(); } logger_handle_init_done = FALSE; } if(logger_queue_initialised) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_circular_buffer_destroy(logger_shared_queue); #else threaded_queue_finalize(&logger_commit_queue); #endif logger_queue_initialised = FALSE; } memset(g_logger_handle_shared_table, 0U, LOGGER_HANDLE_SHARED_TABLE_SIZE); logger_set_path(NULL); mutex_lock(&logger_mutex); _logger_initialised = FALSE; mutex_unlock(&logger_mutex); #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_finalize() : finalised"); flushout(); #endif } void logger_flush() { #if DEBUG_LOG_HANDLER > 1 debug_osformatln(termout, "logger_flush()"); flushout(); #endif if(logger_initialised_and_started()) { if(logger_thread_id != thread_self()) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif logger_message* message = logger_message_alloc(); #if DEBUG message->align0 = 0xde; message->align1 = 0xf00d; #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->channel_flush_all.tid = thread_self(); message->type = LOGGER_MESSAGE_TYPE_CHANNEL_FLUSH_ALL; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->channel_flush_all.aw = aw; #else message->channel_flush_all.aw = &aw; #endif logger_message_post(message); // avoid being stuck forever if the service is down while(logger_initialised_and_started()) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED if(async_wait_timeout(aw, ONE_SECOND_US)) { //async_wait_destroy_shared(aw); break; } #else if(async_wait_timeout(&aw, ONE_SECOND_US)) { async_wait_finalize(&aw); break; } #endif } async_wait_destroy_shared(aw); } else { logger_service_flush_all_channels(); } } #if DEBUG_LOG_HANDLER else { debug_osformatln(termout, "logger_flush() : i=%i s=%i", logger_initialised, logger_started()); flushout(); } #endif } void logger_channel_close_all() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_close_all_channels()"); flushout(); #endif if(logger_initialised_and_started()) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif logger_message* message = logger_message_alloc(); #if DEBUG ZEROMEMORY(message, sizeof(logger_message)); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_CHANNEL_CLOSE_ALL; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->channel_flush_all.aw = aw; #else message->channel_flush_all.aw = &aw; #endif logger_message_post(message); // avoid being stuck forever if the service is down while(logger_initialised_and_started()) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED formatln("logger_channel_close_all"); if(async_wait_timeout(aw, ONE_SECOND_US)) { //async_wait_destroy_shared(aw); break; } #else if(async_wait_timeout(&aw, ONE_SECOND_US)) { async_wait_finalize(&aw); break; } #endif } async_wait_destroy_shared(aw); } #if DEBUG_LOG_HANDLER else { debug_osformatln(termout, "logger_close_all_channels() : i=%i s=%i", logger_initialised, logger_started()); flushout(); } #endif } void logger_reopen() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_reopen()"); flushout(); #endif if(logger_initialised_and_started()) { // even for a lflag, the message NEEDS to be enqueued because // 1) it activates the service // 2) synchronises the memory between the threads (memory wall) #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif logger_message* message = logger_message_alloc(); #if DEBUG ZEROMEMORY(message, sizeof(logger_message)); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_CHANNEL_REOPEN_ALL; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->channel_reopen_all.aw = aw; #else message->channel_reopen_all.aw = &aw; #endif mutex_lock(&logger_mutex); logger_shared_space->_logger_reopen_request_message = message; mutex_unlock(&logger_mutex); logger_message_post(message); while(logger_initialised_and_started()) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED #if DEBUG_LOG_HANDLER formatln("logger_reopen"); #endif if(async_wait_timeout(aw, ONE_SECOND_US)) { //async_wait_destroy_shared(aw); break; } #else if(async_wait_timeout(&aw, ONE_SECOND_US)) { async_wait_finalize(&aw); break; } #endif } async_wait_destroy_shared(aw); } #if DEBUG_LOG_HANDLER else { debug_osformatln(termout, "logger_reopen() : i=%i s=%i", logger_initialised, logger_started()); flushout(); } #endif } void logger_sink_noblock() { mutex_lock(&logger_mutex); logger_shared_space->_logger_sink_request_message = LOGGER_MESSAGE_SINK_FAKE; mutex_unlock(&logger_mutex); } void logger_sink() { #if DEBUG_LOG_HANDLER debug_osformatln(termout, "logger_reopen()"); flushout(); #endif if(logger_initialised_and_started()) { // even for a lflag, the message NEEDS to be enqueued because // 1) it activates the service // 2) synchronises the memory between the threads (memory wall) #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED async_wait_s *aw = async_wait_create_shared(logger_shared_heap_id, 1); #else async_wait_s aw; async_wait_init(&aw, 1); #endif logger_message* message = logger_message_alloc(); #if DEBUG ZEROMEMORY(message, sizeof(logger_message)); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_CHANNEL_SINK_ALL; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->channel_sink_all.aw = aw; #else message->channel_sink_all.aw = &aw; #endif mutex_lock(&logger_mutex); logger_shared_space->_logger_sink_request_message = message; mutex_unlock(&logger_mutex); logger_message_post(message); while(logger_initialised_and_started()) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED #if DEBUG formatln("logger_sink"); #endif if(async_wait_timeout(aw, ONE_SECOND_US)) { //async_wait_destroy_shared(aw); break; } #else if(async_wait_timeout(&aw, ONE_SECOND_US)) { async_wait_finalize(&aw); break; } #endif #if DEBUG mutex_lock(&logger_mutex); bool stop_looping = logger_shared_space->_logger_sink_request_message != NULL; mutex_unlock(&logger_mutex); if(stop_looping) { formatln("_logger_sink_requested is FALSE but the synchronization hasn't been released yet"); } #endif } async_wait_destroy_shared(aw); } #if DEBUG_LOG_HANDLER else { debug_osformatln(termout, "logger_reopen() : i=%i s=%i", logger_initialised, logger_started()); flushout(); } #endif } bool logger_is_running() { return logger_started(); } void logger_handle_vmsg(logger_handle* handle, u32 level, const char* fmt, va_list args) { /* * check that the handle has got a channel for the level */ #if DEBUG if((handle == NULL) || (handle->magic_check != LOGGER_HANDLE_MAGIC_CHECK)) { #if DEBUG_LOG_HANDLER debug_stacktrace_print(termout, debug_stacktrace_get()); debug_stacktrace_print(termerr, debug_stacktrace_get()); flushout(); flusherr(); #endif abort(); } if(level >= MSG_LEVEL_COUNT) { debug_osformatln(termerr, "bad message level %u", level); logger_handle_trigger_emergency_shutdown(); return; } if(level <= MSG_ERR) { sleep(0); } #endif if(handle == NULL) { if(level <= exit_level) { logger_handle_trigger_emergency_shutdown(); } return; } if(level > logger_level) { return; } s32 channel_count = handle->channels[level].offset; if(channel_count < 0) /* it's count-1 actually */ { return; } /** * @note At this point we KNOW we have to print something. */ output_stream baos; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_context shos_context; #else bytezarray_output_stream_context baos_context; #endif /* * DEFAULT_MAX_LINE_SIZE is the base size. * * The output stream has the BYTEARRAY_DYNAMIC flag set in order to allow * bigger sentences. * */ /* Will use the tmp buffer, but alloc a bigger one if required. */ #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_init_ex_static(&baos, logger_shared_heap_id, NULL, 48, SHARED_HEAP_DYNAMIC, &shos_context); #else bytezarray_output_stream_init_ex_static(&baos, NULL, DEFAULT_MAX_LINE_SIZE, BYTEARRAY_DYNAMIC, &baos_context); #endif if(FAIL(vosformat(&baos, fmt, args))) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_reset(&baos); #else bytezarray_output_stream_reset(&baos); #endif osprint(&baos, "*** ERROR : MESSAGE FORMATTING FAILED ***"); } output_stream_write_u8(&baos, 0); logger_message* message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_TEXT; message->text.level = level; message->text.flags = 0; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.text_length = shared_heap_output_stream_size(&baos) - 1; message->text.text_buffer_length = shared_heap_output_stream_buffer_size(&baos); #else message->text.text_length = bytezarray_output_stream_size(&baos) - 1; message->text.text_buffer_length = bytezarray_output_stream_buffer_size(&baos); #endif message->text.handle = handle; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.text = shared_heap_output_stream_detach(&baos); #else message->text.text = bytezarray_output_stream_detach(&baos); #endif #if SIZEOF_TIMEVAL <= 8 gettimeofday(&message->text.tv, NULL); #else message->text.timestamp = timeus(); #endif #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED // prefix // prefix_len message->text.rc = 0; #if DEBUG || HAS_LOG_PID message->text.pid = getpid_ex(); #endif #endif #if DEBUG || DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED || HAS_LOG_THREAD_ID || DNSCORE_HAS_LOG_THREAD_TAG message->text.thread_id = thread_self(); #endif logger_message_post(message); output_stream_close(&baos); /* Frees the memory */ if(level <= exit_level) { logger_handle_trigger_emergency_shutdown(); } } void logger_handle_msg_nocull(logger_handle* handle, u32 level, const char* fmt, ...) { /** * @note At this point we KNOW we have to print something. */ #if DEBUG if((handle == NULL) || (handle->magic_check != LOGGER_HANDLE_MAGIC_CHECK)) { #if DEBUG_LOG_HANDLER debug_stacktrace_print(termout, debug_stacktrace_get()); debug_stacktrace_print(termerr, debug_stacktrace_get()); flushout(); flusherr(); #endif abort(); } #ifdef NDEBUG size_t sizeof_logger_message = sizeof(logger_message); size_t sizeof_logger_message_text_s = sizeof(struct logger_message_text_s); assert(sizeof_logger_message_text_s <= 64); assert(sizeof_logger_message <= 64); (void)sizeof_logger_message; (void)sizeof_logger_message_text_s; #endif #endif output_stream baos; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_context shos_context; #else bytezarray_output_stream_context baos_context; #endif /* * DEFAULT_MAX_LINE_SIZE is the base size. * * The output stream has the BYTEARRAY_DYNAMIC flag set in order to allow * bigger sentences. * */ va_list args; va_start(args, fmt); /* Will use the tmp buffer, but alloc a bigger one if required. */ #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_init_ex_static(&baos, logger_shared_heap_id, NULL, 48, SHARED_HEAP_DYNAMIC, &shos_context); #else bytezarray_output_stream_init_ex_static(&baos, NULL, DEFAULT_MAX_LINE_SIZE, BYTEARRAY_DYNAMIC, &baos_context); #endif if(FAIL(vosformat(&baos, fmt, args))) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_reset(&baos); #else bytezarray_output_stream_reset(&baos); #endif osprint(&baos, "*** ERROR : MESSAGE FORMATTING FAILED ***"); } output_stream_write_u8(&baos, 0); logger_message* message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_TEXT; message->text.level = level; message->text.flags = 0; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.text_length = shared_heap_output_stream_size(&baos) - 1; message->text.text_buffer_length = shared_heap_output_stream_buffer_size(&baos); #else message->text.text_length = bytezarray_output_stream_size(&baos) - 1; message->text.text_buffer_length = bytezarray_output_stream_buffer_size(&baos); #endif message->text.handle = handle; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.text = shared_heap_output_stream_detach(&baos); #else message->text.text = bytezarray_output_stream_detach(&baos); #endif assert(message->text.text != NULL); #if SIZEOF_TIMEVAL <= 8 gettimeofday(&message->text.tv, NULL); #else message->text.timestamp = timeus(); #endif // prefix // prefix_len #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.rc = 0; #if DEBUG || HAS_LOG_PID message->text.pid = getpid_ex(); #endif #endif #if DEBUG || DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED || HAS_LOG_THREAD_ID || DNSCORE_HAS_LOG_THREAD_TAG message->text.thread_id = thread_self(); #endif logger_message_post(message); va_end(args); output_stream_close(&baos); /* Frees the memory */ } void logger_handle_msg(logger_handle* handle, u32 level, const char* fmt, ...) { /* * check that the handle has got a channel for the level */ #if DEBUG if((handle == NULL) || (handle->magic_check != LOGGER_HANDLE_MAGIC_CHECK)) { #if DEBUG_LOG_HANDLER debug_stacktrace_print(termout, debug_stacktrace_get()); debug_stacktrace_print(termerr, debug_stacktrace_get()); flushout(); flusherr(); #endif abort(); } if(level >= MSG_LEVEL_COUNT) { debug_osformatln(termerr, "bad message level %u", level); logger_handle_trigger_emergency_shutdown(); return; } if(level <= MSG_ERR) { sleep(0); } #endif if(handle == NULL) { if(level <= exit_level) { logger_handle_trigger_emergency_shutdown(); } return; } if(level > logger_level) { return; } s32 channel_count = handle->channels[level].offset; if(channel_count < 0) /* it's count-1 actually */ { return; } /** * @note At this point we KNOW we have to print something. */ output_stream baos; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_context baos_context; #else bytezarray_output_stream_context baos_context; #endif /* * DEFAULT_MAX_LINE_SIZE is the base size. * * The output stream has the BYTEARRAY_DYNAMIC flag set in order to allow * bigger sentences. * */ va_list args; va_start(args, fmt); /* Will use the tmp buffer, but alloc a bigger one if required. */ #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_init_ex_static(&baos, logger_shared_heap_id, NULL, DEFAULT_MAX_LINE_SIZE, SHARED_HEAP_DYNAMIC, &baos_context); #else bytezarray_output_stream_init_ex_static(&baos, NULL, DEFAULT_MAX_LINE_SIZE, BYTEARRAY_DYNAMIC, &baos_context); #endif if(FAIL(vosformat(&baos, fmt, args))) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_reset(&baos); #else bytezarray_output_stream_reset(&baos); #endif osprint(&baos, "*** ERROR : MESSAGE FORMATTING FAILED ***"); } output_stream_write_u8(&baos, 0); logger_message* message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_TEXT; message->text.level = level; message->text.flags = 0; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.text_length = shared_heap_output_stream_size(&baos) - 1; message->text.text_buffer_length = shared_heap_output_stream_buffer_size(&baos); #else message->text.text_length = bytezarray_output_stream_size(&baos) - 1; message->text.text_buffer_length = bytezarray_output_stream_buffer_size(&baos); #endif message->text.handle = handle; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.text = shared_heap_output_stream_detach(&baos); #else message->text.text = bytezarray_output_stream_detach(&baos); #endif assert(message->text.text != NULL); #if SIZEOF_TIMEVAL <= 8 gettimeofday(&message->text.tv, NULL); #else message->text.timestamp = timeus(); #endif // prefix // prefix_len #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.rc = 0; #if DEBUG || HAS_LOG_PID message->text.pid = getpid_ex(); #endif #endif #if DEBUG || DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED || HAS_LOG_THREAD_ID || DNSCORE_HAS_LOG_THREAD_TAG message->text.thread_id = thread_self(); #endif logger_message_post(message); va_end(args); output_stream_close(&baos); /* Frees the memory */ if(level <= exit_level) { exit_level = 0; if(!dnscore_shuttingdown()) { logger_handle_trigger_emergency_shutdown(); } } } void logger_handle_msg_text(logger_handle* handle, u32 level, const char* text, u32 text_len) { /* * check that the handle has got a channel for the level */ #if DEBUG if((handle == NULL) || (handle->magic_check != LOGGER_HANDLE_MAGIC_CHECK)) { #if DEBUG_LOG_HANDLER debug_stacktrace_print(termout, debug_stacktrace_get()); debug_stacktrace_print(termerr, debug_stacktrace_get()); flushout(); flusherr(); #endif abort(); } if(level >= MSG_LEVEL_COUNT) { debug_osformatln(termerr, "bad message level %u", level); logger_handle_trigger_emergency_shutdown(); return; } if(level <= MSG_ERR) { sleep(0); } #endif if(handle == NULL) { if(level <= exit_level) { logger_handle_trigger_emergency_shutdown(); } return; } if(level > logger_level) { return; } s32 channel_count = handle->channels[level].offset; if(channel_count < 0) /* it's count-1 actually */ { return; } logger_message* message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_TEXT; message->text.level = level; message->text.flags = 0; message->text.text_length = text_len; message->text.text_buffer_length = text_len; message->text.handle = handle; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.text = (u8*)shared_heap_wait_alloc(logger_shared_heap_id, text_len); #else ZALLOC_ARRAY_OR_DIE(u8*, message->text. text, text_len, LOGRTEXT_TAG); #endif assert(message->text.text != NULL); memcpy(message->text.text, text, text_len); #if SIZEOF_TIMEVAL <= 8 gettimeofday(&message->text.tv, NULL); #else message->text.timestamp = timeus(); #endif // prefix // prefix_len #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.rc = 0; #if DEBUG || HAS_LOG_PID message->text.pid = getpid_ex(); #endif #endif #if DEBUG || DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED || HAS_LOG_THREAD_ID || DNSCORE_HAS_LOG_THREAD_TAG message->text.thread_id = thread_self(); #endif logger_message_post(message); if(level <= exit_level) { logger_handle_trigger_emergency_shutdown(); } } void logger_handle_msg_text_ext(logger_handle* handle, u32 level, const char* text, u32 text_len, const char* prefix, u32 prefix_len, u16 flags) { /* * check that the handle has got a channel for the level */ #if DEBUG if((handle == NULL) || (handle->magic_check != LOGGER_HANDLE_MAGIC_CHECK)) { #if DEBUG_LOG_HANDLER debug_stacktrace_print(termout, debug_stacktrace_get()); debug_stacktrace_print(termerr, debug_stacktrace_get()); flushout(); flusherr(); #endif abort(); } if(level >= MSG_LEVEL_COUNT) { debug_osformatln(termerr, "bad message level %u", level); logger_handle_trigger_emergency_shutdown(); return; } if(level <= MSG_ERR) { sleep(0); } #endif if(handle == NULL) { if(level <= exit_level) { logger_handle_trigger_emergency_shutdown(); } return; } if(level > logger_level) { return; } s32 channel_count = handle->channels[level].offset; if(channel_count < 0) /* it's count-1 actually */ { return; } logger_message* message = logger_message_alloc(); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_TEXT; message->text.level = level; message->text.flags = flags; message->text.text_length = text_len; message->text.text_buffer_length = text_len; message->text.handle = handle; ZALLOC_ARRAY_OR_DIE(u8*, message->text.text, text_len, LOGRTEXT_TAG); memcpy(message->text.text, text, text_len); #if SIZEOF_TIMEVAL <= 8 gettimeofday(&message->text.tv, NULL); #else message->text.timestamp = timeus(); #endif message->text.prefix = (const u8*)prefix; message->text.prefix_length = prefix_len; #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.rc = 0; #if DEBUG || HAS_LOG_PID message->text.pid = getpid_ex(); #endif #endif #if DEBUG || DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED || HAS_LOG_THREAD_ID || DNSCORE_HAS_LOG_THREAD_TAG message->text.thread_id = thread_self(); #endif logger_message_post(message); if(level <= exit_level) { logger_handle_trigger_emergency_shutdown(); } } void logger_handle_try_msg(logger_handle* handle, u32 level, const char* fmt, ...) { /* * check that the handle has got a channel for the level */ #if DEBUG if((handle == NULL) || (handle->magic_check != LOGGER_HANDLE_MAGIC_CHECK)) { #if DEBUG_LOG_HANDLER debug_stacktrace_print(termout, debug_stacktrace_get()); debug_stacktrace_print(termerr, debug_stacktrace_get()); flushout(); flusherr(); #endif abort(); } if(level >= MSG_LEVEL_COUNT) { debug_osformatln(termerr, "bad message level %u", level); logger_handle_trigger_emergency_shutdown(); return; } if(level <= MSG_ERR) { sleep(0); } #endif if(handle == NULL) { if(level <= exit_level) { logger_handle_trigger_emergency_shutdown(); } return; } if(level > logger_level) { return; } s32 channel_count = handle->channels[level].offset; if(channel_count < 0) /* it's count-1 actually */ { return; } logger_message* message = logger_message_try_alloc(); if(message == NULL) { return; } /** * @note At this point we KNOW we have to print something. */ output_stream baos; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_context baos_context; #else bytezarray_output_stream_context baos_context; #endif /* * DEFAULT_MAX_LINE_SIZE is the base size. * * The output stream has the BYTEARRAY_DYNAMIC flag set in order to allow * bigger sentences. * */ va_list args; va_start(args, fmt); /* Will use the tmp buffer, but alloc a bigger one if required. */ #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_init_ex_static(&baos, logger_shared_heap_id, NULL, DEFAULT_MAX_LINE_SIZE, SHARED_HEAP_DYNAMIC, &baos_context); #else bytezarray_output_stream_init_ex_static(&baos, NULL, DEFAULT_MAX_LINE_SIZE, BYTEARRAY_DYNAMIC, &baos_context); #endif if(FAIL(vosformat(&baos, fmt, args))) { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED shared_heap_output_stream_reset(&baos); #else bytezarray_output_stream_reset(&baos); #endif osprint(&baos, "*** ERROR : MESSAGE FORMATTING FAILED ***"); } output_stream_write_u8(&baos, 0); #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_TEXT; message->text.level = level; message->text.flags = 0; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.text_length = shared_heap_output_stream_size(&baos) - 1; message->text.text_buffer_length = shared_heap_output_stream_buffer_size(&baos); #else message->text.text_length = bytezarray_output_stream_size(&baos) - 1; message->text.text_buffer_length = bytezarray_output_stream_buffer_size(&baos); #endif message->text.handle = handle; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.text = shared_heap_output_stream_detach(&baos); #else message->text.text = bytezarray_output_stream_detach(&baos); #endif assert(message->text.text != NULL); #if SIZEOF_TIMEVAL <= 8 gettimeofday(&message->text.tv, NULL); #else message->text.timestamp = timeus(); #endif // prefix // prefix_len #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.rc = 0; #if DEBUG || HAS_LOG_PID message->text.pid = getpid_ex(); #endif #endif #if DEBUG || DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED || HAS_LOG_THREAD_ID || DNSCORE_HAS_LOG_THREAD_TAG message->text.thread_id = thread_self(); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED logger_message_post(message); #else if(!threaded_queue_try_enqueue(&logger_commit_queue, message)) { // could not enqueue ZFREE_ARRAY(message->text.text, message->text.text_buffer_length); logger_message_free(message); } #endif va_end(args); output_stream_close(&baos); /* Frees the memory */ if(level <= exit_level) { exit_level = 0; if(!dnscore_shuttingdown()) { logger_handle_trigger_emergency_shutdown(); } } } void logger_handle_try_msg_text(logger_handle* handle, u32 level, const char* text, u32 text_len) { /* * check that the handle has got a channel for the level */ #if DEBUG if((handle == NULL) || (handle->magic_check != LOGGER_HANDLE_MAGIC_CHECK)) { #if DEBUG_LOG_HANDLER debug_stacktrace_print(termout, debug_stacktrace_get()); debug_stacktrace_print(termerr, debug_stacktrace_get()); flushout(); flusherr(); #endif abort(); } if(level >= MSG_LEVEL_COUNT) { debug_osformatln(termerr, "bad message level %u", level); logger_handle_trigger_emergency_shutdown(); return; } if(level <= MSG_ERR) { sleep(0); } #endif if(handle == NULL) { if(level <= exit_level) { logger_handle_trigger_emergency_shutdown(); } return; } if(level > logger_level) { return; } s32 channel_count = handle->channels[level].offset; if(channel_count < 0) /* it's count-1 actually */ { return; } #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED logger_message* message = logger_message_try_alloc(); #else logger_message* message = logger_message_alloc(); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->pid = getpid_ex(); #endif message->type = LOGGER_MESSAGE_TYPE_TEXT; message->text.level = level; message->text.flags = 0; message->text.text_length = text_len; message->text.text_buffer_length = text_len; message->text.handle = handle; #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.text = (u8*)shared_heap_wait_alloc(logger_shared_heap_id, text_len); #else ZALLOC_ARRAY_OR_DIE(u8*, message->text.text, text_len, LOGRTEXT_TAG); #endif assert(message->text.text != NULL); memcpy(message->text.text, text, text_len); #if SIZEOF_TIMEVAL <= 8 gettimeofday(&message->text.tv, NULL); #else message->text.timestamp = timeus(); #endif // prefix // prefix_len #if !DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED message->text.rc = 0; #if DEBUG || HAS_LOG_PID message->text.pid = getpid_ex(); #endif #endif #if DEBUG || DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED || HAS_LOG_THREAD_ID || DNSCORE_HAS_LOG_THREAD_TAG message->text.thread_id = thread_self(); #endif #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED logger_message_post(message); #else if(!threaded_queue_try_enqueue(&logger_commit_queue, message)) { // could not enqueue ZFREE_ARRAY(message->text.text, message->text.text_buffer_length); logger_message_free(message); } #endif if(level <= exit_level) { logger_handle_trigger_emergency_shutdown(); } } bool logger_queue_fill_critical() { #if DNSCORE_LOGGER_SHARED_QUEUE_SUPPORT_ENABLED int size = shared_circular_buffer_size(logger_shared_queue); int room = shared_circular_buffer_avail(logger_shared_queue); #else int size = threaded_ringbuffer_cw_size(&logger_commit_queue); int room = threaded_ringbuffer_cw_room(&logger_commit_queue); #endif int maxsize = size + room; if(maxsize > 0) { float ratio = ((float)size) / ((float)maxsize); return (ratio > 0.5f); } else { return TRUE; } } static const char LOGGER_PATH_DEFAULT[] = ""; static const char *g_logger_path = LOGGER_PATH_DEFAULT; static uid_t g_logger_uid = 0; static gid_t g_logger_gid = 0; void logger_set_path(const char *path) { if(g_logger_path != LOGGER_PATH_DEFAULT) { free((char*)g_logger_path); } if(path != NULL) { g_logger_path = strdup(path); } else { g_logger_path = LOGGER_PATH_DEFAULT; } } void logger_release_ownership() { if(logger_thread_pid != -1) { logger_thread_pid = -1; } if(logger_handle_owner_pid != -1) { logger_handle_owner_pid = -1; } } void logger_take_ownership(pid_t new_owner) { if(logger_thread_pid == -1) { logger_thread_pid = new_owner; } if(logger_handle_owner_pid == -1) { logger_handle_owner_pid = new_owner; } } const char* logger_get_path() { return g_logger_path; } void logger_set_uid(uid_t uid) { g_logger_uid = uid; } uid_t logger_get_uid() { return g_logger_uid; } void logger_set_gid(uid_t gid) { g_logger_gid = gid; } gid_t logger_get_gid() { return g_logger_gid; } void logger_set_level(u8 level) { logger_level = MIN(level, MSG_ALL); } bool logger_wait_started() { for(int countdown = 50; countdown > 0; --countdown) { int value = smp_int_get(&logger_thread_state); if(value == LOGGER_DISPATCHED_THREAD_STARTED) { return TRUE; } usleep_ex(100000); } return FALSE; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/message-buffer.c0000644000000000000000000000013214505005532022367 xustar000000000000000030 mtime=1695812442.472982618 30 atime=1695812445.795030196 30 ctime=1695812494.620729479 yadifa-2.6.5-11201/lib/dnscore/src/message-buffer.c0000664000374500037450000001744414505005532022343 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifa * @ingroup ### * @brief */ #include "dnscore/dnscore-config.h" #include "dnscore/packet_reader.h" #include "dnscore/message.h" #include "dnscore/message-viewer.h" ya_result message_buffer_processor(message_viewer *mv, const u8 *buffer, u16 length) { ya_result return_value; packet_unpack_reader_data purd; u8 record_wire[MAX_DOMAIN_LENGTH + 10 + 65535]; u16 count[4]; /* ------------------------------------------------------------ */ /* 1. get values of the sections and added them with the totols */ count[0] = ntohs(MESSAGE_QD(buffer)); count[1] = ntohs(MESSAGE_AN(buffer)); count[2] = ntohs(MESSAGE_NS(buffer)); count[3] = ntohs(MESSAGE_AR(buffer)); if(mv->view_mode_with & MESSAGE_VIEWER_WITH_HEADER) { /* 2. go thru the buffer and do what is needed for output or calculations */ message_viewer_header(mv, buffer); } // ;; WARNING: recursion requested but not available const u8 *opt_record = NULL; const u8 *tsig_record = NULL; packet_reader_init_at(&purd, buffer, length, DNS_HEADER_LENGTH); for(u32 n = count[0]; n > 0; --n) { if(FAIL(return_value = packet_reader_skip_zone_record(&purd))) { return return_value; } } for(u32 section_idx = 1; section_idx < 4; section_idx++) { for(u16 n = count[section_idx]; n > 0; n--) { // Get next record and put the packet reader offset on the next record // note: packet_reader_read_record unpacks the name if(FAIL(return_value = packet_reader_read_record(&purd, record_wire, sizeof(record_wire)))) { return return_value; } if(section_idx == 3) { s32 len = dnsname_len_checked_with_size(record_wire, sizeof(record_wire)); if(FAIL(len)) { return len; } if(return_value - len < 10) // type class ttl rdata_size { return MAKE_RCODE_ERROR(FP_RCODE_FORMERR); } const u8 *p = record_wire + len; u16 record_type = GET_U16_AT_P(p); if(record_type == TYPE_OPT) { opt_record = record_wire; --count[3]; message_viewer_pseudosection_record(mv, record_wire); } else if(record_type == TYPE_TSIG) { tsig_record = record_wire; --count[3]; } } } } /* SECTION QUESTION */ u32 section_idx = 0; bool show_question_section = message_viewer_requires_section(0, mv->view_mode_with); if(show_question_section) { /* Print SECTION name */ message_viewer_section_header(mv, section_idx, count[section_idx]); } /* init packet reader with buffer. length and offset in the buffer */ packet_reader_init_at(&purd, buffer, length, DNS_HEADER_LENGTH); for(u16 n = count[section_idx]; n > 0; n--) { /* 1. GET EVERYTHING FROM THE BUFFER FOR QUESTION + OFFSET packet reader */ if(FAIL(return_value = packet_reader_read_zone_record(&purd, record_wire, sizeof(record_wire)))) { return return_value; } s32 len = dnsname_len_checked_with_size(record_wire, sizeof(record_wire)); if(FAIL(len)) { return len; } if(return_value - len != 4) { return MAKE_RCODE_ERROR(FP_RCODE_FORMERR); } const u8 *p = record_wire + len; /* Retrieve QTYPE from packet reader */ u16 rtype = GET_U16_AT_P(p); p += 2; /* Retrieve QCLASS from packet reader */ u16 rclass = GET_U16_AT_P(p);; //p += 2; if(show_question_section) { /* Print everything from QUESTION SECTION */ message_viewer_question_record(mv, record_wire, rclass, rtype); } } if(show_question_section) { message_viewer_section_footer(mv, section_idx, count[section_idx]); } /* SECTIONS WITHOUT QUESTION */ for(u32 section_idx = 1; section_idx < 4; section_idx++) { bool show_section = message_viewer_requires_section(section_idx, mv->view_mode_with) && (count[section_idx] > 0); bool print_footer = show_section; if(show_section) { message_viewer_section_header(mv, section_idx, count[section_idx]); } for(u16 n = count[section_idx]; n > 0; n--) { // Get next record and put the packet reader offset on the next record // note: packet_reader_read_record unpacks the name if(FAIL(return_value = packet_reader_read_record(&purd, record_wire, sizeof(record_wire)))) { return return_value; } if(show_section) { /* Initialize the values needed for printing */ message_viewer_section_record(mv, record_wire, section_idx); } } if(print_footer) { message_viewer_section_footer(mv, section_idx, count[section_idx]); } } if(opt_record) { --count[3]; if(FAIL(return_value = packet_reader_read_record(&purd, record_wire, sizeof(record_wire)))) { return return_value; } } if(tsig_record) { --count[3]; if(FAIL(return_value = packet_reader_read_record(&purd, record_wire, sizeof(record_wire)))) { return return_value; } message_viewer_pseudosection_record(mv, record_wire); } // here handle extraneous bytes return 0; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/message-viewer.c0000644000000000000000000000013214505005532022417 xustar000000000000000030 mtime=1695812442.401981601 30 atime=1695812445.792030153 30 ctime=1695812494.622729507 yadifa-2.6.5-11201/lib/dnscore/src/message-viewer.c0000664000374500037450000001047614505005532022371 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include static u8 message_viewer_requires_section_with_view_with_mode[4] = { MESSAGE_VIEWER_WITH_QUESTION, MESSAGE_VIEWER_WITH_ANSWER, MESSAGE_VIEWER_WITH_AUTHORITY, MESSAGE_VIEWER_WITH_ADDITIONAL }; bool message_viewer_requires_section(int section, int view_with_mode) { if((section >= 0) && (section <= 3)) { return (message_viewer_requires_section_with_view_with_mode[section] & view_with_mode) != 0; } return FALSE; } static void message_viewer_default_three(message_viewer *view, const u8 *buffer) { printf("three!\n"); } static void message_viewer_default_four(message_viewer *view) { printf("four!\n"); } static void message_viewer_default_five(message_viewer *viewer, long time_duration) { printf("five!\n"); } static void message_viewer_default_six(message_viewer *viewer, u32 section_idx, u16 count) { printf("six!\n"); } static void message_viewer_default_seven(message_viewer *viewer, u32 section_idx, u16 count) { printf("seven!\n"); } static void message_viewer_default_eight(message_viewer *viewer, const u8 *record_wire, u16 rclass, u16 rtype) { printf("eight!\n"); } static void message_viewer_default_nine(message_viewer *viewer, const u8 *record_wire, u8 view_mode_with) { printf("nine!\n"); } static ya_result message_viewer_default_pseudosection_record(message_viewer *mv, const u8 *record_wire) { (void)mv; (void)record_wire; return 0; } static const message_viewer_vtbl default_viewer_vtbl = { message_viewer_default_three, message_viewer_default_four, message_viewer_default_five, message_viewer_default_six, message_viewer_default_seven, message_viewer_default_eight, message_viewer_default_nine, message_viewer_default_pseudosection_record, "message_viewer_default", }; void message_viewer_set_default(message_viewer *view) { view->data = NULL; view->vtbl = &default_viewer_vtbl; } void message_viewer_init(message_viewer *view) { view->bytes = 0; view->data = NULL; view->messages = 0; view->os = NULL; view->resource_records_total[0] = 0; view->resource_records_total[1] = 0; view->resource_records_total[2] = 0; view->resource_records_total[3] = 0; view->view_mode_with = 0; view->host = NULL; view->vtbl = &default_viewer_vtbl; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/message.c0000644000000000000000000000013214505005532021120 xustar000000000000000030 mtime=1695812442.378981272 30 atime=1695812445.791030139 30 ctime=1695812494.624729536 yadifa-2.6.5-11201/lib/dnscore/src/message.c0000664000374500037450000036415714505005532021102 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnspacket DNS Messages * @ingroup dnscore * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/message.h" #include "dnscore/logger.h" #include "dnscore/dnscore.h" #include "dnscore/format.h" #include "dnscore/fingerprint.h" #include "dnscore/packet_reader.h" #include "dnscore/packet_writer.h" #include "dnscore/tsig.h" #include "dnscore/fdtools.h" #include "dnscore/tcp_io_stream.h" #include "dnscore/counter_output_stream.h" #include "dnscore/network.h" #include "dnscore/thread_pool.h" #if DNSCORE_HAS_CTRL #include "dnscore/ctrl-rfc.h" #endif /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define SA_LOOP 3 #define SA_PRINT 4 /*------------------------------------------------------------------------------ * FUNCTIONS */ u16 edns0_maxsize = EDNS0_MAX_LENGTH; double g_message_data_minimum_troughput_default = 0; void message_set_minimum_troughput_default(double rate) { if(rate >= 0) { g_message_data_minimum_troughput_default = rate; } } void message_edns0_setmaxsize(u16 maxsize) { edns0_maxsize = maxsize; } u16 message_edns0_getmaxsize() { return edns0_maxsize; } // Handles OPT and TSIG static inline void message_process_adjust_buffer_size(message_data *mesg, u16 edns0_size) { u32 mesg_buffer_size = message_get_buffer_size_max(mesg); u32 query_buffer_size = edns0_size; if(mesg_buffer_size > query_buffer_size) { mesg_buffer_size = query_buffer_size; if(mesg_buffer_size < EDNS0_MIN_LENGTH) { mesg_buffer_size = EDNS0_MIN_LENGTH; } } message_set_buffer_size(mesg, mesg_buffer_size); } static ya_result message_process_additionals(message_data *mesg, u8* s, u16 ar_count) { (void)s; /* * @note: I've moved this in the main function (the one calling this one) */ //yassert(ar_count != 0 && ar_count == message_get_additional_count(mesg)); u8 *buffer = mesg->_buffer; ya_result ret; ar_count = ntohs(MESSAGE_AR(buffer)); /* * rfc2845 * * If there is a TSIG then * _ It must be put aside, safely * _ It must be removed from the query * _ It must be processed * * rfc2671 * * Handle OPT * */ /* * Read DNS name (decompression on) * Read type (TSIG = 250) * Read class (ANY) * Read TTL (0) * Read RDLEN * */ u32 query_end = message_get_size(mesg); packet_unpack_reader_data purd; purd.packet = buffer; purd.packet_size = query_end; if(mesg->_ar_start == NULL) { u32 ar_index = ntohs(MESSAGE_AN(buffer)) + ntohs(MESSAGE_NS(buffer)); purd.offset = DNS_HEADER_LENGTH; // header packet_reader_skip_fqdn(&purd); // checked below if(FAIL(packet_reader_skip(&purd, 4))) // type class { message_set_status(mesg, FP_ERROR_READING_QUERY); return UNPROCESSABLE_MESSAGE; } while(ar_index > 0) /* Skip all until AR records */ { /* * It should be in this kind of processing that we read the EDNS0 flag */ if(FAIL(ret = packet_reader_skip_record(&purd))) { message_set_status(mesg, FP_ERROR_READING_QUERY); return UNPROCESSABLE_MESSAGE; } ar_index--; } query_end = purd.offset; // ready to remove all additionals in one fell swoop mesg->_ar_start = &mesg->_buffer[purd.offset]; } else { purd.offset = message_get_additional_section_ptr(mesg) - mesg->_buffer; } /* We are now at the start of the ar */ struct type_class_ttl_rdlen tctr; u8 tsigname[MAX_DOMAIN_LENGTH]; #if DNSCORE_HAS_TSIG_SUPPORT u32 record_offset; #endif while(ar_count-- > 0) { #if DNSCORE_HAS_TSIG_SUPPORT record_offset = purd.offset; #endif if(FAIL(packet_reader_read_fqdn(&purd, tsigname, sizeof(tsigname)))) { /* oops */ message_set_status(mesg, FP_ERROR_READING_QUERY); return UNPROCESSABLE_MESSAGE; } if(packet_reader_read(&purd, &tctr, 10) == 10 ) // exact { /* * EDNS (0) */ if(tctr.qtype == TYPE_OPT) { /** * Handle EDNS */ if((tctr.ttl & NU32(0x00ff0000)) == 0) /* ensure version is 0 */ { u32 rdlen = ntohs(tctr.rdlen); #if DNSCORE_HAS_NSID_SUPPORT if(rdlen != 0) { u32 next = purd.offset + rdlen; for(s32 remain = (s32)rdlen; remain >= 4; remain -= 4) { u32 opt_type_size; if(ISOK(packet_reader_read_u32(&purd, &opt_type_size))) // read the option-code and the option-length in one operation { if(opt_type_size == NU32(0x00030000)) // check if it's NSID { // nsid mesg->_nsid = TRUE; break; } u32 opt_type_len = ntohl(opt_type_size) & 0xffff; if(FAIL(packet_reader_skip(&purd, opt_type_len))) // skip the data { return UNPROCESSABLE_MESSAGE; } remain -= opt_type_len; } else { break; } } if(FAIL(packet_reader_skip(&purd, next - purd.offset))) { return UNPROCESSABLE_MESSAGE; } } #else if(FAIL(packet_reader_skip(&purd, rdlen))) { return UNPROCESSABLE_MESSAGE; } #endif if(tsigname[0] == '\0') { message_process_adjust_buffer_size(mesg, ntohs(tctr.qclass)); mesg->_edns = TRUE; mesg->_rcode_ext = tctr.ttl; #if DEBUG log_debug("EDNS: udp-size=%d rcode-ext=%08x desc=%04x", message_get_size(mesg), tctr.ttl, rdlen); #endif continue; } #if DEBUG log_debug("OPT record is not processable (broken)"); #endif return UNPROCESSABLE_MESSAGE; } else { message_set_status(mesg, FP_EDNS_BAD_VERSION); message_process_adjust_buffer_size(mesg, ntohs(tctr.qclass)); mesg->_edns = TRUE; mesg->_rcode_ext = 0; #if DEBUG log_debug("OPT record is not processable (not supported)"); #endif return MAKE_DNSMSG_ERROR(FP_EDNS_BAD_VERSION); } } #if DNSCORE_HAS_TSIG_SUPPORT /* * TSIG */ else if(tctr.qtype == TYPE_TSIG) { if(ar_count == 0) { /* * It looks like a TSIG ... */ ya_result return_code; if(message_isquery(mesg)) { if(FAIL(return_code = tsig_process_query(mesg, &purd, record_offset, tsigname, &tctr))) { #if DEBUG // this should be reported above log_notice("%r query error from %{sockaddr}", return_code, message_get_sender_sa(mesg)); #endif return return_code; } } else { tsig_item *key = tsig_get(tsigname); if(key != NULL) { if(FAIL(return_code = tsig_process(mesg, &purd, record_offset, key, &tctr))) { #if DEBUG // this should be reported above log_notice("%r answer error from %{sockaddr}", return_code, message_get_sender_sa(mesg)); #endif return return_code; } } else { log_notice("answer error from %{sockaddr}: TSIG when none expected", message_get_sender_sa(mesg)); message_set_status(mesg, FP_TSIG_UNEXPECTED); return MAKE_DNSMSG_ERROR(FP_TSIG_UNEXPECTED); } } break; /* we know there is no need to loop anymore */ } else { /* * Error: TSIG is not the last AR record */ #if DEBUG log_debug("TSIG record is not the last AR"); #endif message_set_status(mesg, FP_TSIG_IS_NOT_LAST); return UNPROCESSABLE_MESSAGE; } } #endif else { /* Unhandled AR TYPE */ log_debug("unhandled AR type %{dnstype}", &tctr.qtype); message_set_status(mesg, FP_UNEXPECTED_RR_IN_QUERY); return UNPROCESSABLE_MESSAGE; } } } /* While there are AR to process */ message_set_additional_count_ne(mesg, 0); message_set_size(mesg, query_end); return SUCCESS; } /** * Handles the OPT and TSIG records of an answer. * * @param mesg * @param ar_count * @return */ static ya_result message_process_answer_additionals(message_data *mesg, u16 ar_count /* network order */ ) { /* * @note: I've moved this in the main function (the one calling this one) */ yassert(ar_count != 0 && ar_count == message_get_additional_count_ne(mesg)); u8 *buffer = message_get_buffer(mesg); ar_count = ntohs(ar_count); /* * rfc2845 * * If there is a TSIG then * _ It must be put aside, safely * _ It must be removed from the query * _ It must be processed * * rfc2671 * * Handle OPT * */ /* * Read DNS name (decompression on) * Read type (TSIG = 250) * Read class (ANY) * Read TTL (0) * Read RDLEN * */ u32 message_size = message_get_size(mesg); packet_unpack_reader_data purd; purd.packet = buffer; purd.packet_size = message_size; u16 ar_sub = 0; if(mesg->_ar_start == NULL) { u32 ar_index = ntohs(MESSAGE_AN(buffer)) + ntohs(MESSAGE_NS(buffer)); purd.offset = DNS_HEADER_LENGTH; // header packet_reader_skip_fqdn(&purd); // checked below if(FAIL(packet_reader_skip_bytes(&purd, 4))) // type class { return UNPROCESSABLE_MESSAGE; } while(ar_index > 0) /* Skip all until AR records */ { /* * It should be in this kind of processing that we read the EDNS0 flag */ if(FAIL(packet_reader_skip_record(&purd))) { return UNPROCESSABLE_MESSAGE; } ar_index--; } message_size = purd.offset; mesg->_ar_start = &mesg->_buffer[purd.offset]; } else { purd.offset = message_get_additional_section_ptr(mesg) - mesg->_buffer; // size up to additional sections } /* We are now at the start of the ar */ struct type_class_ttl_rdlen tctr; u8 tsigname[MAX_DOMAIN_LENGTH]; #if DNSCORE_HAS_TSIG_SUPPORT u32 record_offset; #endif while(ar_count-- > 0) { #if DNSCORE_HAS_TSIG_SUPPORT record_offset = purd.offset; #endif if(FAIL(packet_reader_read_fqdn(&purd, tsigname, sizeof(tsigname)))) { /* oops */ message_set_status(mesg, FP_ERROR_READING_QUERY); return UNPROCESSABLE_MESSAGE; } if(packet_reader_read(&purd, &tctr, 10) == 10 ) // exact { /* * EDNS (0) */ if(tctr.qtype == TYPE_OPT) { /** * Handle EDNS */ if((tctr.ttl & NU32(0x00ff0000)) == 0) /* ensure version is 0 */ { if(tsigname[0] == '\0') { ++ar_sub; mesg->_edns = TRUE; mesg->_rcode_ext = tctr.ttl; log_debug("EDNS: udp-size=%d rcode-ext=%08x desc=%04x", message_get_buffer_size(mesg), tctr.ttl, ntohs(tctr.rdlen)); continue; } } else { mesg->_edns = TRUE; mesg->_rcode_ext = tctr.ttl; } log_debug("OPT record is not processable (broken or not supported)"); return UNPROCESSABLE_MESSAGE; } #if DNSCORE_HAS_TSIG_SUPPORT /* * TSIG */ else if(tctr.qtype == TYPE_TSIG) { if(ar_count == 0) { /* * It looks like a TSIG ... */ ya_result return_code; if(message_isquery(mesg)) { if(FAIL(return_code = tsig_process_query(mesg, &purd, record_offset, tsigname, &tctr))) { log_err("%r query error from %{sockaddr}", return_code, message_get_sender_sa(mesg)); return UNPROCESSABLE_MESSAGE; } } else // not a query (an answer) { if(message_has_tsig(mesg)) { if(dnsname_equals(tsigname, message_tsig_get_name(mesg))) { if(FAIL(return_code = tsig_process_answer(mesg, &purd, record_offset, &tctr))) { log_err("%r answer error from %{sockaddr}", return_code, message_get_sender_sa(mesg)); return UNPROCESSABLE_MESSAGE; } } else { log_err("TSIG name mismatch from %{sockaddr}", message_get_sender_sa(mesg)); return UNPROCESSABLE_MESSAGE; } } else // no tsig { log_err("answer error from %{sockaddr}: TSIG when none expected", message_get_sender_sa(mesg)); message_set_status(mesg, FP_TSIG_UNEXPECTED); return UNPROCESSABLE_MESSAGE; } } break; /* we know there is no need to loop anymore */ } else { /* * Error: TSIG is not the last AR record */ log_debug("TSIG record is not the last AR"); message_set_status(mesg, FP_TSIG_IS_NOT_LAST); return UNPROCESSABLE_MESSAGE; } } #endif else { /* Unhandled AR TYPE */ #if DEBUG log_debug("skipping AR type %{dnstype}", &tctr.qtype); #endif purd.offset += ntohs(tctr.rdlen); message_size = purd.offset; } } } /* While there are AR to process */ //message_sub_additional_count(mesg, 1); message_set_additional_count_ne(mesg, 0); message_set_size(mesg, message_size); return SUCCESS; } /** \brief Processing DNS packet * * @param mesg * * @retval OK * @return status of message is written in message_get_status(mesg) */ /* Defines a mask and the expected result for the 4 first 16 bits of the header */ #ifdef WORDS_BIGENDIAN #define MESSAGE_HEADER_MASK (( (u64) 0 ) | \ ( ((u64) ( QR_BITS | AA_BITS | RA_BITS | TC_BITS )) << 40 ) | \ ( ((u64) ( RA_BITS | RCODE_BITS )) << 32 ) | \ ( ((u64) 1LL) << 16 )) #define MESSAGE_HEADER_RESULT ( ((u64) 1LL) << 16 ) /* Bind gives "RA" here (seems irrelevant, nonsense, but we need to accept it) */ #define NOTIFY_MESSAGE_HEADER_MASK (( (u64) 0LL ) | \ ( ((u64) ( TC_BITS )) << 40 ) | \ ( ((u64) 1LL) << 16 )) #define NOTIFY_MESSAGE_HEADER_RESULT ( ((u64) 1LL) << 16 ) #else #define MESSAGE_HEADER_MASK (( (u64) 0LL ) | \ ( ((u64) ( QR_BITS | AA_BITS | RA_BITS | TC_BITS )) << 16 ) | \ ( ((u64) ( RA_BITS | RCODE_BITS )) << 24 ) | \ ( ((u64) 1LL) << 40 )) #define MESSAGE_HEADER_RESULT ( ((u64) 1LL) << 40 ) /* Bind gives "RA" here (seems irrelevant, nonsense, but we need to accept it) */ #define NOTIFY_MESSAGE_HEADER_MASK (( (u64) 0LL ) | \ ( ((u64) ( TC_BITS )) << 16 ) | \ ( ((u64) 1LL) << 40 )) #define NOTIFY_MESSAGE_HEADER_RESULT ( ((u64) 1LL) << 40 ) #endif /* EDF: this takes about 150 cycles [144;152] with peaks at 152 */ /** * Canonises the query: * _ copies the query fqdn lowercase * _ copies the query type and class for easy access * * (should be renamed to message_query_canonise or something of that effect) * * @param mesg * @return a pointer to the answer section (or more accurately, just after the class of the (first) query */ static inline u8* message_process_copy_fqdn(message_data *mesg) { u8 *src = message_get_query_section_ptr(mesg); u8 *dst = &mesg->_canonised_fqdn[0]; u8 *base = dst; u32 len; for(;;) { len = *src++; *dst++ = len; if(len == 0) { break; } if( (len & 0xC0) == 0 ) { const u8 * const limit = dst + len; if(limit - base < MAX_DOMAIN_LENGTH) { do { *dst++ = LOCASE(*src++); /* Works with the dns character set */ } while(dst < limit); } else { message_set_status(mesg, FP_NAME_TOO_LARGE); DERROR_MSG("FP_NAME_TOO_LARGE"); return NULL; } } else { message_set_status(mesg, ((len & 0xC0)==0xC0)?FP_QNAME_COMPRESSED:FP_NAME_FORMAT_ERROR); return NULL; } } /* Get qtype & qclass */ mesg->_query_type = GET_U16_AT(src[0]); /** @note : NATIVETYPE */ mesg->_query_class = GET_U16_AT(src[2]); /** @note : NATIVECLASS */ // the next section starts at &src[4] return &src[4]; } ya_result message_process_query(message_data *mesg) { u8 *buffer = message_get_buffer(mesg); /** CHECK DNS HEADER */ /** Drop dns packet if query is answer or does not have correct header length */ /* * +5 <=> 1 qd record ar least */ u64 *h64 = (u64*)buffer; u64 m64 = MESSAGE_HEADER_MASK; u64 r64 = MESSAGE_HEADER_RESULT; if((message_get_size(mesg) < DNS_HEADER_LENGTH + 5) || (( *h64 & m64) != r64 ) ) { /** Return if QDCOUNT is not 1 * * @note Previous test was actually testing if QDCOUNT was > 1 * I assumed either 0 or >1 is wrong for us so I used the same trick than for QCCOUNT */ if(MESSAGE_QR(buffer)) { message_set_status(mesg, FP_QR_BIT_SET); return INVALID_MESSAGE; } MESSAGE_FLAGS_AND(buffer, OPCODE_BITS|RD_BITS, 0); if(NETWORK_ONE_16 != MESSAGE_QD(buffer)) { if(0 == MESSAGE_QD(buffer)) { DERROR_MSG("FP_QDCOUNT_IS_0"); message_set_status(mesg, FP_QDCOUNT_IS_0); return INVALID_MESSAGE; /* will be dropped */ } else { DERROR_MSG("FP_QDCOUNT_BIG_1"); message_set_status(mesg, FP_QDCOUNT_BIG_1); } } else if(MESSAGE_NS(buffer) != 0) { message_set_status(mesg, FP_NSCOUNT_NOT_0); } else { message_set_status(mesg, FP_PACKET_DROPPED); } return UNPROCESSABLE_MESSAGE; } /** * @note Past this point, a message could be processable. * It's the right place to reset the message's defaults. * */ message_reset_buffer_size(mesg); mesg->_ar_start = NULL; #if DNSCORE_HAS_TSIG_SUPPORT mesg->_tsig.tsig = NULL; #endif mesg->_rcode_ext = 0; mesg->_edns = FALSE; #if DNSCORE_HAS_NSID_SUPPORT mesg->_nsid = FALSE; #endif u8 *s = message_process_copy_fqdn(mesg); if(s == NULL) { message_set_status(mesg, FP_NAME_FORMAT_ERROR); return UNPROCESSABLE_MESSAGE; } /* * Handle the OPT and TSIG records */ { ya_result return_code; u32 nsar_count; if((nsar_count = MESSAGE_NSAR(buffer)) != 0) { if(FAIL(return_code = message_process_additionals(mesg, s, nsar_count))) { //message_set_size(mesg, s - buffer); return return_code; } } if(message_get_query_type(mesg) != TYPE_IXFR) { message_set_size(mesg, s - buffer); } } /* cut the trash here */ /* At this point the TSIG has been computed and removed */ /* Clear zome bits */ message_apply_mask(mesg, ~(QR_BITS|TC_BITS|AA_BITS), ~(Z_BITS|AD_BITS|CD_BITS|RA_BITS|RCODE_BITS)); //MESSAGE_LOFLAGS(buffer) &= ~(Z_BITS|AD_BITS|CD_BITS|RCODE_BITS); message_set_status(mesg, FP_MESG_OK); return SUCCESS; } int message_process(message_data *mesg) { u8 *buffer = message_get_buffer(mesg); switch(MESSAGE_OP(buffer)) { case OPCODE_QUERY: { /** CHECK DNS HEADER */ /** Drop dns packet if query is answer or does not have correct header length */ /* * +5 <=> 1 qd record ar least */ u64 *h64 = (u64*)buffer; u64 m64 = MESSAGE_HEADER_MASK; u64 r64 = MESSAGE_HEADER_RESULT; if( (message_get_size(mesg) < DNS_HEADER_LENGTH + 5) || (( *h64 & m64) != r64 ) ) { /** Return if QDCOUNT is not 1 * * @note Previous test was actually testing if QDCOUNT was > 1 * I assumed either 0 or >1 is wrong for us so I used the same trick than for QCCOUNT */ if(MESSAGE_QR(buffer)) { message_set_status(mesg, FP_QR_BIT_SET); return INVALID_MESSAGE; } MESSAGE_FLAGS_AND(buffer, OPCODE_BITS|RD_BITS, 0); if(NETWORK_ONE_16 != MESSAGE_QD(buffer)) { if(0 == MESSAGE_QD(buffer)) { DERROR_MSG("FP_QDCOUNT_IS_0"); message_set_status(mesg, FP_QDCOUNT_IS_0); return INVALID_MESSAGE; /* will be dropped */ } else { message_set_status(mesg, FP_QDCOUNT_BIG_1); DERROR_MSG("FP_QDCOUNT_BIG_1"); } } else if( MESSAGE_NS(buffer) != 0) { message_set_status(mesg, FP_NSCOUNT_NOT_0); } else { message_set_status(mesg, FP_PACKET_DROPPED); } return UNPROCESSABLE_MESSAGE; } /** * @note Past this point, a message could be processable. * It's the right place to reset the message's defaults. * */ message_reset_buffer_size(mesg); mesg->_ar_start = NULL; #if DNSCORE_HAS_TSIG_SUPPORT mesg->_tsig.tsig = NULL; #endif mesg->_rcode_ext = 0; mesg->_edns = FALSE; #if DNSCORE_HAS_NSID_SUPPORT mesg->_nsid = FALSE; #endif u8 *s = message_process_copy_fqdn(mesg); if(s == NULL) { message_set_status(mesg, FP_NAME_FORMAT_ERROR); return UNPROCESSABLE_MESSAGE; } /* * Handle the OPT and TSIG records */ { ya_result return_code; u32 nsar_count; if((nsar_count = MESSAGE_NSAR(buffer)) != 0) { if(FAIL(return_code = message_process_additionals(mesg, s, nsar_count))) { message_set_size(mesg, s - buffer); return return_code; } } if(message_get_query_type(mesg) != TYPE_IXFR) { message_set_size(mesg, s - buffer); } } /* At this point the TSIG has been computed and removed */ /* Clear zome bits */ message_apply_mask(mesg, ~(QR_BITS|TC_BITS|AA_BITS), ~(Z_BITS|RA_BITS|AD_BITS|CD_BITS|RCODE_BITS)); message_set_status(mesg, FP_MESG_OK); return OK; } case OPCODE_NOTIFY: { MESSAGE_LOFLAGS(buffer) &= ~(Z_BITS|AD_BITS|CD_BITS); /* ------------------------------------------------------------ */ /** CHECK DNS HEADER */ /** Drop dns packet if query is answer or does not have correct header length */ /* * +5 <=> 1 qd record ar least */ u64 *h64 = (u64*)buffer; u64 m64 = NOTIFY_MESSAGE_HEADER_MASK; u64 r64 = NOTIFY_MESSAGE_HEADER_RESULT; /* ... A400 0001 ... */ if( (message_get_size(mesg) < DNS_HEADER_LENGTH + 5) || (( *h64 & m64) != r64 ) ) { /** Return if QDCOUNT is not 1 * * @note Previous test was actually testing if QDCOUNT was > 1 * I assumed either 0 or >1 is wrong for us so I used the same trick than for QCCOUNT */ MESSAGE_FLAGS_AND(buffer, OPCODE_BITS, 0); if(NETWORK_ONE_16 != MESSAGE_QD(buffer)) { if(0 == MESSAGE_QD(buffer)) { DERROR_MSG("FP_QDCOUNT_IS_0"); message_set_status(mesg, FP_QDCOUNT_IS_0); return INVALID_MESSAGE; } else { message_set_status(mesg, FP_QDCOUNT_BIG_1); DERROR_MSG("FP_QDCOUNT_BIG_1"); } } else { message_set_status(mesg, FP_PACKET_DROPPED); } return UNPROCESSABLE_MESSAGE; } u8 *s = message_process_copy_fqdn(mesg); if(s == NULL) { message_set_status(mesg, FP_NAME_FORMAT_ERROR); return UNPROCESSABLE_MESSAGE; } /** * @note Past this point, a message could be processable. * It's the right place to reset the message's defaults. * */ message_reset_buffer_size(mesg); mesg->_ar_start = NULL; #if DNSCORE_HAS_TSIG_SUPPORT mesg->_tsig.tsig = NULL; #endif mesg->_rcode_ext = 0; mesg->_edns = FALSE; #if DNSCORE_HAS_NSID_SUPPORT mesg->_nsid = FALSE; #endif /* * If there is a TSIG, it is here ... */ #if DNSCORE_HAS_TSIG_SUPPORT { ya_result return_code; u16 ar_count; if((ar_count = MESSAGE_AR(buffer)) != 0) { if(FAIL(return_code = message_process_additionals(mesg, s, ar_count))) { return return_code; } } } #endif /* At this point the TSIG has been computed and removed */ message_set_status(mesg, FP_MESG_OK); return OK; } case OPCODE_UPDATE: { MESSAGE_LOFLAGS(buffer) &= ~(Z_BITS|AD_BITS|CD_BITS|RCODE_BITS); /* ------------------------------------------------------------ */ /** CHECK DNS HEADER */ /** Drop dns packet if query is answer or does not have correct header length */ /* * +5 <=> 1 qd record ar least */ u64 *h64 = (u64*)buffer; u64 m64 = MESSAGE_HEADER_MASK; u64 r64 = MESSAGE_HEADER_RESULT; if( (message_get_size(mesg) < DNS_HEADER_LENGTH + 5) || (( *h64 & m64) != r64 ) ) { /** Return if QDCOUNT is not 1 * * @note Previous test was actually testing if QDCOUNT was > 1 * I assumed either 0 or >1 is wrong for us so I used the same trick than for QCCOUNT */ if(MESSAGE_QR(buffer)) { message_set_status(mesg, FP_QR_BIT_SET); return INVALID_MESSAGE; } MESSAGE_FLAGS_AND(buffer, OPCODE_BITS, 0); if(NETWORK_ONE_16 != MESSAGE_QD(buffer)) { if(0 == MESSAGE_QD(buffer)) { DERROR_MSG("FP_QDCOUNT_IS_0"); message_set_status(mesg, FP_QDCOUNT_IS_0); return INVALID_MESSAGE; } else { DERROR_MSG("FP_QDCOUNT_BIG_1"); message_set_status(mesg, FP_QDCOUNT_BIG_1); } return UNPROCESSABLE_MESSAGE; } message_set_status(mesg, FP_PACKET_DROPPED); return UNPROCESSABLE_MESSAGE; } u8 *s = message_process_copy_fqdn(mesg); if(s == NULL) { message_set_status(mesg, FP_NAME_FORMAT_ERROR); return UNPROCESSABLE_MESSAGE; } /** * @note Past this point, a message could be processable. * It's the right place to reset the message's defaults. * */ message_reset_buffer_size(mesg); mesg->_ar_start = NULL; #if DNSCORE_HAS_TSIG_SUPPORT mesg->_tsig.tsig = NULL; #endif mesg->_rcode_ext = 0; mesg->_edns = FALSE; #if DNSCORE_HAS_NSID_SUPPORT mesg->_nsid = FALSE; #endif /* * If there is a TSIG, it is here ... */ #if DNSCORE_HAS_TSIG_SUPPORT { ya_result return_code; u16 ar_count; if((ar_count = MESSAGE_AR(buffer)) != 0) { if(FAIL(return_code = message_process_additionals(mesg, s, ar_count))) { return return_code; } } } #endif /* At this point the TSIG has been computed and removed */ message_apply_mask(mesg, ~(QR_BITS|TC_BITS|AA_BITS), ~(RA_BITS|RCODE_BITS)); message_set_status(mesg, FP_MESG_OK); return OK; } #if DNSCORE_HAS_CTRL case OPCODE_CTRL: { MESSAGE_LOFLAGS(buffer) &= ~(Z_BITS|AD_BITS|CD_BITS|RCODE_BITS); /* rdtsc_init(&mpb); */ /* ------------------------------------------------------------ */ /** CHECK DNS HEADER */ /** Drop dns packet if query is answer or does not have correct header length */ /* * +5 <=> 1 qd record ar least */ u64 *h64 = (u64*)buffer; u64 m64 = MESSAGE_HEADER_MASK; u64 r64 = MESSAGE_HEADER_RESULT; if( (message_get_size(mesg) < DNS_HEADER_LENGTH + 5) || (( *h64 & m64) != r64 ) ) { /** Return if QDCOUNT is not 1 * * @note Previous test was actually testing if QDCOUNT was > 1 * I assumed either 0 or >1 is wrong for us so I used the same trick than for QCCOUNT */ if(MESSAGE_QR(buffer)) { message_set_status(mesg, FP_QR_BIT_SET); return INVALID_MESSAGE; } MESSAGE_FLAGS_AND(buffer, OPCODE_BITS, 0); if(NETWORK_ONE_16 != MESSAGE_QD(buffer)) { if(0 == MESSAGE_QD(buffer)) { DERROR_MSG("FP_QDCOUNT_IS_0"); message_set_status(mesg, FP_QDCOUNT_IS_0); return INVALID_MESSAGE; } else { DERROR_MSG("FP_QDCOUNT_BIG_1"); message_set_status(mesg, FP_QDCOUNT_BIG_1); } return UNPROCESSABLE_MESSAGE; } message_set_status(mesg, FP_PACKET_DROPPED); return UNPROCESSABLE_MESSAGE; } u8 *s = message_process_copy_fqdn(mesg); if(s == NULL) { message_set_status(mesg, FP_NAME_FORMAT_ERROR); return UNPROCESSABLE_MESSAGE; } /** * @note Past this point, a message could be processable. * It's the right place to reset the message's defaults. * */ message_reset_buffer_size(mesg); mesg->_ar_start = NULL; #if DNSCORE_HAS_TSIG_SUPPORT message_tsig_clear_key(mesg); #endif mesg->_rcode_ext = 0; mesg->_edns = FALSE; #if DNSCORE_HAS_NSID_SUPPORT mesg->_nsid = FALSE; #endif /* * If there is a TSIG, it is here ... */ #if DNSCORE_HAS_TSIG_SUPPORT { ya_result return_code; u16 ar_count; if((ar_count = MESSAGE_AR(buffer)) != 0) { if(FAIL(return_code = message_process_additionals(mesg, s, ar_count))) { return return_code; } } } #endif /* At this point the TSIG has been computed and removed */ message_apply_mask(mesg, ~(QR_BITS|TC_BITS|AA_BITS), ~(RA_BITS|RCODE_BITS)); message_set_status(mesg, FP_MESG_OK); return OK; } #endif // HAS_CTRL default: { u8 hf = MESSAGE_HIFLAGS(buffer); if((hf & QR_BITS) == 0) { MESSAGE_LOFLAGS(buffer) &= ~(Z_BITS|AD_BITS|CD_BITS|RCODE_BITS); MESSAGE_FLAGS_AND(buffer, OPCODE_BITS, 0); message_reset_buffer_size(mesg); mesg->_ar_start = NULL; #if DNSCORE_HAS_TSIG_SUPPORT mesg->_tsig.tsig = NULL; #endif mesg->_rcode_ext = 0; mesg->_edns = FALSE; #if DNSCORE_HAS_NSID_SUPPORT mesg->_nsid = FALSE; #endif message_set_status(mesg, FP_NOT_SUPP_OPC); message_set_size(mesg, DNS_HEADER_LENGTH); SET_U32_AT(mesg->_buffer[4],0); /* aligned to 32 bits, so two 32 bits instead of one 64 */ SET_U32_AT(mesg->_buffer[8],0); /* reserved for future use */ return UNPROCESSABLE_MESSAGE; } else { message_set_status(mesg, FP_PACKET_DROPPED); return INVALID_MESSAGE; } } } } int message_process_lenient(message_data *mesg) { if(message_get_size(mesg) < DNS_HEADER_LENGTH) { return UNPROCESSABLE_MESSAGE; } /* if(message_istruncated(mesg)) { return MESSAGE_TRUNCATED; } */ u8 *s = message_process_copy_fqdn(mesg); if(s == NULL) { return UNPROCESSABLE_MESSAGE; } /** * @note Past this point, a message could be processable. * It's the right place to reset the message's defaults. * */ message_reset_buffer_size(mesg); mesg->_ar_start = NULL; mesg->_rcode_ext = 0; mesg->_edns = FALSE; #if DNSCORE_HAS_NSID_SUPPORT mesg->_nsid = FALSE; #endif /* * Handle the OPT and TSIG records */ { ya_result return_code; u16 ar_count_ne; if((ar_count_ne = message_get_additional_count_ne(mesg)) != 0) { if(FAIL(return_code = message_process_answer_additionals(mesg, ar_count_ne))) { return return_code; } } #if DNSCORE_HAS_TSIG_SUPPORT else { mesg->_tsig.tsig = NULL; /* cut the trash here */ /*message_set_size(mesg, s - buffer);(*/ } #endif } /* At this point the TSIG has been computed and removed */ //message_set_status(mesg, FP_MESG_OK); message_set_status(mesg, (mesg->_buffer[3] & 0xf)); return SUCCESS; } static ya_result message_answer_verify_additionals(message_data *mesg, packet_unpack_reader_data *purd, int ar_count) { /* We are now at the start of the ar */ struct type_class_ttl_rdlen *tctr; #if DNSCORE_HAS_TSIG_SUPPORT u32 record_offset; u8 fqdn[MAX_DOMAIN_LENGTH]; #endif while(ar_count-- > 0) { #if DNSCORE_HAS_TSIG_SUPPORT record_offset = purd->offset; #endif if(FAIL(packet_reader_read_fqdn(purd, fqdn, sizeof(fqdn)))) { /* oops */ message_set_status(mesg, FP_ERROR_READING_QUERY); return UNPROCESSABLE_MESSAGE; } if(packet_reader_available(purd) < 10) { message_set_status(mesg, FP_ERROR_READING_QUERY); return UNPROCESSABLE_MESSAGE; } tctr = (struct type_class_ttl_rdlen*)packet_reader_get_next_u8_ptr_const(purd); purd->offset += 10; switch(tctr->qtype) { /* * EDNS (0) */ case TYPE_OPT: { /** * Handle EDNS */ message_sub_additional_count(mesg, 1); if((tctr->ttl & NU32(0x00ff0000)) == 0) /* ensure version is 0 */ { if(fqdn[0] == '\0') { message_set_buffer_size(mesg, edns0_maxsize); /* our own limit, taken from the config file */ mesg->_edns = TRUE; mesg->_rcode_ext = tctr->ttl; log_debug("EDNS: udp-size=%d rcode-ext=%08x desc=%04x", message_get_size(mesg), tctr->ttl, ntohs(tctr->rdlen)); continue; } } else { message_set_status(mesg, FP_EDNS_BAD_VERSION); message_set_buffer_size(mesg, edns0_maxsize); mesg->_edns = TRUE; mesg->_rcode_ext = 0; break; } log_debug("OPT record is not processable (broken or not supported)"); return UNPROCESSABLE_MESSAGE; } #if DNSCORE_HAS_TSIG_SUPPORT /* * TSIG */ case TYPE_TSIG: { if(ar_count == 0) { /* * It looks like a TSIG ... */ ya_result return_code; if(message_has_tsig(mesg)) { if(dnsname_equals(fqdn, message_tsig_get_name(mesg))) { if(FAIL(return_code = tsig_process_answer(mesg, purd, record_offset, tctr))) { log_err("%r answer error from %{sockaddr}", return_code, message_get_sender_sa(mesg)); return return_code; } } else { log_err("TSIG name mismatch from %{sockaddr}", message_get_sender_sa(mesg)); return UNPROCESSABLE_MESSAGE; } } else // no tsig { log_err("answer error from %{sockaddr}: TSIG when none expected", message_get_sender_sa(mesg)); message_set_status(mesg, FP_TSIG_UNEXPECTED); return UNPROCESSABLE_MESSAGE; } return SUCCESS; /* we know there is no need to loop anymore */ } else { /* * Error: TSIG is not the last AR record */ log_debug("TSIG record is not the last AR"); message_set_status(mesg, FP_TSIG_IS_NOT_LAST); return UNPROCESSABLE_MESSAGE; } } #endif default: { /* Unhandled AR TYPE */ #if DEBUG log_debug("skipping AR type %{dnstype}", &tctr->qtype); #endif purd->offset += ntohs(tctr->rdlen); break; } } } /* While there are AR to process */ return SUCCESS; } int message_answer_verify(message_data *mesg) { if(message_get_size(mesg) < DNS_HEADER_LENGTH) { return UNPROCESSABLE_MESSAGE; } u8 *after_query_section; if(message_get_query_count_ne(mesg) != 0) { after_query_section = message_process_copy_fqdn(mesg); // canonises the query fqdn and fetches its type and class if(after_query_section == NULL) { return UNPROCESSABLE_MESSAGE; } } else { if(mesg->_tcp_serial == 0) // needed at the beginning of the stream { return UNPROCESSABLE_MESSAGE; } after_query_section = message_get_query_section_ptr(mesg); // as there is no query section } /** * @note Past this point, a message could be processable. * It's the right place to reset the message's defaults. * */ u16 ar_count_ne; if((ar_count_ne = message_get_additional_count_ne(mesg)) != 0) { // find the additional section packet_unpack_reader_data purd; purd.packet = message_get_buffer_const(mesg); purd.packet_size = message_get_size(mesg); purd.offset = after_query_section - purd.packet; // skip all records before the additional section for(int ar_index = message_get_answer_count(mesg) + message_get_authority_count(mesg); ar_index > 0; --ar_index) { if(FAIL(packet_reader_skip_record(&purd))) { return UNPROCESSABLE_MESSAGE; } } mesg->_ar_start = &mesg->_buffer[purd.offset]; // ar_start is ready message_answer_verify_additionals(mesg, &purd, ntohs(ar_count_ne)); } else { mesg->_ar_start = NULL; mesg->_rcode_ext = 0; mesg->_edns = FALSE; #if DNSCORE_HAS_NSID_SUPPORT mesg->_nsid = FALSE; #endif } message_set_status(mesg, FP_MESG_OK); return OK; } void message_transform_to_error(message_data *mesg) { if(!mesg->_edns) { message_set_answer(mesg); message_or_rcode(mesg, message_get_status(mesg)); if(message_get_status(mesg) == RCODE_FORMERR) { SET_U32_AT(mesg->_buffer[4],0); /* aligned to 32 bits, so two 32 bits instead of one 64 */ SET_U32_AT(mesg->_buffer[8],0); message_set_size(mesg, DNS_HEADER_LENGTH); } else { } } else { /* 00 0029 0200 EE 00 00000000 */ if(message_get_status(mesg) == RCODE_FORMERR) { SET_U32_AT(mesg->_buffer[4],0); /* aligned to 32 bits, so two 32 bits instead of one 64 */ SET_U32_AT(mesg->_buffer[8],0); message_set_size(mesg, DNS_HEADER_LENGTH); } else { message_set_size(mesg, message_get_additional_section_ptr(mesg) - mesg->_buffer); } message_set_answer(mesg); message_set_rcode(mesg, message_get_status(mesg) & 15); /* #AR = 1 */ mesg->_buffer[DNS_HEADER_LENGTH - 1] = 1; /* AR count was 0, now it is 1 */ /* append opt *//* */ u8 *buffer = message_get_buffer_limit(mesg); buffer[ 0] = 0; buffer[ 1] = 0; buffer[ 2] = 0x29; buffer[ 3] = edns0_maxsize>>8; buffer[ 4] = edns0_maxsize; buffer[ 5] = message_get_status(mesg) >> 4; // status is updated here buffer[ 6] = mesg->_rcode_ext >> 16; buffer[ 7] = mesg->_rcode_ext >> 8; buffer[ 8] = mesg->_rcode_ext; #if DNSCORE_HAS_NSID_SUPPORT if(!message_has_nsid(mesg)) { buffer[ 9] = 0; buffer[10] = 0; buffer += EDNS0_RECORD_SIZE; } else { buffer += EDNS0_RECORD_SIZE - 2; memcpy(buffer, edns0_rdatasize_nsid_option_wire, edns0_rdatasize_nsid_option_wire_size); buffer += edns0_rdatasize_nsid_option_wire_size; } #else buffer[ 9] = 0; buffer[10] = 0; buffer += EDNS0_RECORD_SIZE; #endif message_set_size(mesg, buffer - mesg->_buffer); } } void message_transform_to_signed_error(message_data *mesg) { message_transform_to_error(mesg); if(message_has_tsig(mesg)) { tsig_sign_answer(mesg); } } void message_make_query(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass) { #ifdef WORDS_BIGENDIAN SET_U64_AT(mesg->_buffer[0], 0x0000000000010000LL); SET_U32_AT(mesg->_buffer[8], 0); #else SET_U64_AT(mesg->_buffer[0], 0x0000010000000000LL); SET_U32_AT(mesg->_buffer[8], 0); #endif message_set_id(mesg, id); dnsname_canonize(qname, mesg->_canonised_fqdn); ya_result qname_len = dnsname_len(qname); u8 *tc = message_get_query_section_ptr(mesg); memcpy(tc, qname, qname_len); tc += qname_len; SET_U16_AT(tc[0], qtype); tc += 2; SET_U16_AT(tc[0], qclass); tc += 2; #if DNSCORE_HAS_TSIG_SUPPORT mesg->_tsig.tsig = NULL; #endif mesg->_ar_start = tc; message_reset_buffer_size(mesg); message_set_size(mesg, tc - message_get_buffer_const(mesg)); message_set_status(mesg, FP_MESG_OK); mesg->_rcode_ext = 0; } void message_make_query_ex(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass, u16 flags) { #ifdef WORDS_BIGENDIAN SET_U64_AT(mesg->_buffer[0], 0x0000000000010000LL); SET_U32_AT(mesg->_buffer[8], 0); #else SET_U64_AT(mesg->_buffer[0], 0x0000010000000000LL); SET_U32_AT(mesg->_buffer[8], 0); #endif message_set_id(mesg, id); dnsname_canonize(qname, mesg->_canonised_fqdn); ya_result qname_len = dnsname_len(qname); u8 *tc = message_get_query_section_ptr(mesg); memcpy(tc, qname, qname_len); tc += qname_len; SET_U16_AT(tc[0], qtype); tc += 2; SET_U16_AT(tc[0], qclass); tc += 2; mesg->_ar_start = tc; message_set_size(mesg, tc - message_get_buffer_const(mesg)); mesg->_rcode_ext = 0; message_set_status(mesg, FP_MESG_OK); #if DNSCORE_HAS_TSIG_SUPPORT message_tsig_clear_key(mesg); #endif if(mesg->_edns || (flags != 0)) { message_set_additional_count_ne(mesg, NETWORK_ONE_16); mesg->_rcode_ext |= MESSAGE_EDNS0_DNSSEC; u8 *buffer = message_get_buffer_limit(mesg); buffer[ 0] = 0; buffer[ 1] = 0; // TYPE buffer[ 2] = 0x29; // buffer[ 3] = edns0_maxsize >> 8; // CLASS = SIZE buffer[ 4] = edns0_maxsize; // buffer[ 5] = message_get_status(mesg) >> 4; // extended RCODE & FLAGS buffer[ 6] = mesg->_rcode_ext >> 16; buffer[ 7] = mesg->_rcode_ext >> 8; buffer[ 8] = mesg->_rcode_ext; buffer[ 9] = 0; // RDATA descriptor buffer[10] = 0; message_increase_size(mesg, 11); } } void message_make_query_ex_with_edns0(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass, u32 edns0_ttl) { #ifdef WORDS_BIGENDIAN SET_U64_AT(mesg->_buffer[0], 0x0000000000010000LL); SET_U32_AT(mesg->_buffer[8], 0); #else SET_U64_AT(mesg->_buffer[0], 0x0000010000000000LL); SET_U32_AT(mesg->_buffer[8], 0); #endif message_set_id(mesg, id); dnsname_canonize(qname, mesg->_canonised_fqdn); ya_result qname_len = dnsname_len(qname); u8 *tc = message_get_query_section_ptr(mesg); memcpy(tc, qname, qname_len); tc += qname_len; SET_U16_AT(tc[0], qtype); tc += 2; SET_U16_AT(tc[0], qclass); tc += 2; mesg->_ar_start = tc; message_set_size(mesg, tc - message_get_buffer_const(mesg)); mesg->_rcode_ext = edns0_ttl; message_set_status(mesg, FP_MESG_OK); #if DNSCORE_HAS_TSIG_SUPPORT message_tsig_clear_key(mesg); #endif message_set_additional_count_ne(mesg, NETWORK_ONE_16); // mesg->_rcode_ext |= MESSAGE_EDNS0_DNSSEC; u8 *buffer = message_get_buffer_limit(mesg); buffer[ 0] = 0; buffer[ 1] = 0; // TYPE buffer[ 2] = 0x29; // buffer[ 3] = edns0_maxsize >> 8; // CLASS = SIZE buffer[ 4] = edns0_maxsize; // buffer[ 5] = message_get_status(mesg) >> 4; // extended RCODE & FLAGS buffer[ 6] = edns0_ttl >> 16; buffer[ 7] = edns0_ttl >> 8; buffer[ 8] = edns0_ttl; buffer[ 9] = 0; // RDATA descriptor buffer[10] = 0; message_increase_size(mesg, 11); } void message_make_message(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass, packet_writer *uninitialised_packet_writer) { assert(uninitialised_packet_writer != NULL); assert(packet_writer_get_offset(uninitialised_packet_writer) <= message_get_buffer_size_max(mesg)); #ifdef WORDS_BIGENDIAN SET_U64_AT(mesg->_buffer[0], 0x0000000000010000LL); SET_U32_AT(mesg->_buffer[8], 0); #else SET_U64_AT(mesg->_buffer[0], 0x0000010000000000LL); SET_U32_AT(mesg->_buffer[8], 0); #endif message_set_id(mesg, id); dnsname_canonize(qname, mesg->_canonised_fqdn); packet_writer_create(uninitialised_packet_writer, message_get_buffer(mesg), DNSPACKET_MAX_LENGTH); packet_writer_add_fqdn(uninitialised_packet_writer, qname); packet_writer_add_u16(uninitialised_packet_writer, qtype); packet_writer_add_u16(uninitialised_packet_writer, qclass); #if DNSCORE_HAS_TSIG_SUPPORT message_tsig_clear_key(mesg); #endif message_set_size(mesg, packet_writer_get_offset(uninitialised_packet_writer)); mesg->_ar_start = message_get_buffer_limit(mesg); message_reset_buffer_size(mesg); message_set_status(mesg, FP_MESG_OK); } void message_make_notify(message_data *mesg, u16 id, const u8 *qname, u16 qtype, u16 qclass) { #ifdef WORDS_BIGENDIAN SET_U64_AT(mesg->_buffer[0], 0x0000240000010000LL); // notify + AA SET_U32_AT(mesg->_buffer[8], 0); #else SET_U64_AT(mesg->_buffer[0], 0x0000010000240000LL); // notify + AA SET_U32_AT(mesg->_buffer[8], 0); #endif message_set_id(mesg, id); dnsname_canonize(qname, mesg->_canonised_fqdn); ya_result qname_len = dnsname_len(qname); u8 *tc = message_get_query_section_ptr(mesg); memcpy(tc, qname, qname_len); tc += qname_len; SET_U16_AT(tc[0], qtype); tc += 2; SET_U16_AT(tc[0], qclass); tc += 2; #if DNSCORE_HAS_TSIG_SUPPORT message_tsig_clear_key(mesg); #endif message_set_size(mesg, tc - message_get_buffer_const(mesg)); mesg->_ar_start = tc; message_set_status(mesg, FP_MESG_OK); } void message_make_ixfr_query(message_data *mesg, u16 id, const u8 *qname, u32 soa_ttl, u16 soa_rdata_size, const u8 *soa_rdata) { packet_writer pw; #ifdef WORDS_BIGENDIAN SET_U64_AT(mesg->_buffer[0], 0x0000000000010000LL); SET_U32_AT(mesg->_buffer[8], 0x00010000); #else SET_U64_AT(mesg->_buffer[0], 0x0000010000000000LL); SET_U32_AT(mesg->_buffer[8], 0x00000100); #endif message_set_id(mesg, id); dnsname_canonize(qname, mesg->_canonised_fqdn); packet_writer_create(&pw, message_get_buffer(mesg), message_get_buffer_size_max(mesg)); packet_writer_add_fqdn(&pw, qname); packet_writer_add_u16(&pw, TYPE_IXFR); packet_writer_add_u16(&pw, CLASS_IN); packet_writer_add_fqdn(&pw, qname); packet_writer_add_u16(&pw, TYPE_SOA); packet_writer_add_u16(&pw, CLASS_IN); packet_writer_add_u32(&pw, htonl(soa_ttl)); packet_writer_add_rdata(&pw, TYPE_SOA, soa_rdata, soa_rdata_size); #if DNSCORE_HAS_TSIG_SUPPORT message_tsig_clear_key(mesg); #endif mesg->_ar_start = &mesg->_buffer[packet_writer_get_offset(&pw)]; message_reset_buffer_size(mesg); message_set_size(mesg, packet_writer_get_offset(&pw)); message_set_status(mesg, FP_MESG_OK); } #if DNSCORE_HAS_TSIG_SUPPORT ya_result message_sign_query_by_name(message_data *mesg, const u8 *tsig_name) { const tsig_item *key = tsig_get(tsig_name); return message_sign_query(mesg, key); } ya_result message_sign_query_by_name_with_epoch_and_fudge(message_data *mesg, const u8 *tsig_name, s64 epoch, u16 fudge) { const tsig_item *key = tsig_get(tsig_name); return message_sign_query_with_epoch_and_fudge(mesg, key, epoch, fudge); } ya_result message_sign_answer(message_data *mesg) { ya_result ret = tsig_sign_answer(mesg); return ret; } ya_result message_sign_query(message_data *mesg, const tsig_item *key) { if(key != NULL) { ZEROMEMORY(&mesg->_tsig, sizeof(message_tsig)); mesg->_tsig.tsig = key; mesg->_tsig.mac_size = mesg->_tsig.tsig->mac_size; u64 now = time(NULL); mesg->_tsig.timehi = htons((u16)(now >> 32)); mesg->_tsig.timelo = htonl((u32)now); mesg->_tsig.fudge = htons(300); /* 5m */ mesg->_tsig.mac_algorithm = key->mac_algorithm; mesg->_tsig.original_id = message_get_id(mesg); // mesg->tsig.error = 0; zeromem // mesg->tsig.other_len = 0; zeromem return tsig_sign_query(mesg); } return TSIG_BADKEY; } ya_result message_sign_query_with_epoch_and_fudge(message_data *mesg, const tsig_item *key, s64 epoch, u16 fudge) { if(key != NULL) { ZEROMEMORY(&mesg->_tsig, sizeof(message_tsig)); mesg->_tsig.tsig = key; mesg->_tsig.mac_size = mesg->_tsig.tsig->mac_size; mesg->_tsig.timehi = htons((u16)(epoch >> 32)); mesg->_tsig.timelo = htonl((u32)epoch); mesg->_tsig.fudge = htons(fudge); /* 5m */ mesg->_tsig.mac_algorithm = key->mac_algorithm; mesg->_tsig.original_id = message_get_id(mesg); // mesg->tsig.error = 0; zeromem // mesg->tsig.other_len = 0; zeromem return tsig_sign_query(mesg); } return TSIG_BADKEY; } #endif void message_make_error(message_data *mesg, u16 error_code) { MESSAGE_FLAGS_OR(mesg->_buffer, QR_BITS, error_code); #ifdef WORDS_BIGENDIAN SET_U32_AT(mesg->_buffer[4], 0x00010000); SET_U32_AT(mesg->_buffer[8], 0x00000000); #else SET_U32_AT(mesg->_buffer[4], 0x00000100); SET_U32_AT(mesg->_buffer[8], 0x00000000); #endif message_reset_buffer_size(mesg); // + 4 is for TYPE + CLASS message_set_size(mesg, DNS_HEADER_LENGTH + 4 + dnsname_len(message_get_query_section_ptr(mesg))); mesg->_ar_start = message_get_buffer_limit(mesg); message_set_status(mesg, (finger_print)error_code); } void message_make_signed_error(message_data *mesg, u16 error_code) { message_make_error(mesg, error_code); if(message_has_tsig(mesg)) { tsig_sign_answer(mesg); } } ya_result message_make_error_and_reply_tcp(message_data *mesg, u16 error_code, int tcpfd) { ya_result ret; message_make_signed_error(mesg, error_code); if(ISOK(ret = message_send_tcp(mesg, tcpfd))) { // } else { tcp_set_abortive_close(tcpfd); } return ret; } ssize_t message_make_error_and_reply_tcp_with_default_minimum_throughput(message_data *mesg, u16 error_code, int tcpfd) { ssize_t ret; message_make_signed_error(mesg, error_code); ret = message_update_length_send_tcp_with_default_minimum_throughput(mesg, tcpfd); return ret; } /** * Creates an answer with an OPT error code */ void message_make_error_ext(message_data *mesg, u32 error_code) { MESSAGE_FLAGS_OR(mesg->_buffer, QR_BITS, error_code & 0x0f); #ifdef WORDS_BIGENDIAN SET_U32_AT(mesg->_buffer[4], 0x00010000); SET_U32_AT(mesg->_buffer[8], 0x00000000); #else SET_U32_AT(mesg->_buffer[4], 0x00000100); SET_U32_AT(mesg->_buffer[8], 0x00000000); #endif message_reset_buffer_size(mesg); // + 4 is for TYPE + CLASS size_t query_section_size = DNS_HEADER_LENGTH + 4 + dnsname_len(message_get_query_section_ptr(mesg)); mesg->_ar_start = &mesg->_buffer[query_section_size]; // the upper 8 bits of the error code are to be put in OPT u8 *edns0 = mesg->_ar_start; edns0[0] = 0; SET_U16_AT(edns0[1], TYPE_OPT); SET_U16_AT(edns0[3], htons(message_edns0_getmaxsize())); SET_U32_AT(edns0[5], (((error_code & 0xff0) << 24) | (message_get_rcode_ext(mesg) & 0x00ffffff))); SET_U16_AT(edns0[9], 0); message_set_size(mesg, query_section_size + 11); message_set_status(mesg, (finger_print)error_code); } ya_result message_query_tcp(message_data *mesg, const host_address *server) { /* connect the server */ ya_result return_value; if(ISOK(return_value = message_set_sender_from_host_address(mesg, server))) { int sockfd; if((sockfd = socket(message_get_sender_sa(mesg)->sa_family, SOCK_STREAM, 0)) >=0) { fd_setcloseonexec(sockfd); socklen_t sa_len = return_value; if(connect(sockfd, message_get_sender_sa(mesg), sa_len) == 0) { #if DEBUG log_debug("sending %d+2 bytes to %{sockaddr} (tcp)", message_get_size(mesg), message_get_sender(mesg)); log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT); #endif if(message_send_tcp(mesg, sockfd) == (ssize_t)message_get_size(mesg) + 2) { u16 tcp_len; shutdown(sockfd, SHUT_WR); if(readfully(sockfd, &tcp_len, 2) == 2) { tcp_len = ntohs(tcp_len); if(readfully(sockfd, message_get_buffer(mesg), tcp_len) == tcp_len) { /* * test the answser * test the TSIG if any */ message_set_size(mesg, tcp_len); #if DEBUG log_debug("received %d bytes from %{sockaddr} (tcp)", message_get_size(mesg), message_get_sender(mesg)); log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT); #endif return_value = message_process_lenient(mesg); } } } } else { // Linux quirk ... if(errno != EINPROGRESS) { return_value = ERRNO_ERROR; } else { return_value = MAKE_ERRNO_ERROR(ETIMEDOUT); } } shutdown(sockfd, SHUT_RDWR); tcp_set_abortive_close(sockfd); close_ex(sockfd); } else { return_value = ERRNO_ERROR; } } return return_value; } ya_result message_query_tcp_ex(message_data *mesg, const host_address *bindto, const host_address *server, message_data *answer) { /* connect the server */ ya_result ret; socklen_t sa_len; socketaddress sa; if((mesg == NULL) || (server == NULL) || (answer == NULL)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } if(bindto != NULL) { ret = host_address2sockaddr(bindto, &sa); if(FAIL(ret)) { return ret; } sa_len = (socklen_t)ret; } if(ISOK(ret = message_set_sender_from_host_address(mesg, server))) { int sockfd; if((sockfd = socket(message_get_sender_sa(mesg)->sa_family, SOCK_STREAM, 0)) >=0) { fd_setcloseonexec(sockfd); if(bindto != NULL) { int on = 1; if(FAIL(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)))) { ret = ERRNO_ERROR; close(sockfd); return ret; } #ifdef SO_REUSEPORT if(FAIL(setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (void *) &on, sizeof(on)))) { ret = ERRNO_ERROR; close(sockfd); return ret; } #endif if(bind(sockfd, &sa.sa, sa_len) < 0) { ret = ERRNO_ERROR; close_ex(sockfd); return ret; } } if(connect(sockfd, message_get_sender_sa(mesg), message_get_sender_size(mesg)) == 0) { #if DEBUG log_debug("sending %d bytes to %{sockaddr} (tcp)", message_get_size(mesg), message_get_sender(mesg)); log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT); #endif if(message_send_tcp(mesg, sockfd) == (ssize_t)message_get_size(mesg) + 2) { u16 tcp_len; shutdown(sockfd, SHUT_WR); if(readfully(sockfd, &tcp_len, 2) == 2) { tcp_len = ntohs(tcp_len); if(readfully(sockfd, message_get_buffer(answer), tcp_len) == tcp_len) { /* * test the answser * test the TSIG if any */ message_set_size(answer, tcp_len); #if DNSCORE_HAS_TSIG_SUPPORT message_tsig_copy_from(answer, mesg); #endif message_copy_sender_from(answer, mesg); #if DEBUG log_debug("received %d bytes from %{sockaddr} (tcp)", message_get_size(answer), message_get_sender_sa(answer)); log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(answer), message_get_size(answer), 16, OSPRINT_DUMP_HEXTEXT); #endif ret = message_process_lenient(answer); } } } } else { // Linux quirk ... if(errno != EINPROGRESS) { ret = ERRNO_ERROR; } else { ret = MAKE_ERRNO_ERROR(ETIMEDOUT); } } shutdown(sockfd, SHUT_RDWR); tcp_set_abortive_close(sockfd); close_ex(sockfd); } else { ret = ERRNO_ERROR; } } return ret; } ya_result message_query_tcp_with_timeout(message_data *mesg, const host_address *address, u8 to_sec) { ya_result ret; if((mesg == NULL) || (address == NULL)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } input_stream is; output_stream os; if(ISOK(ret = tcp_input_output_stream_connect_host_address(address, &is, &os, to_sec))) { int sockfd = fd_input_stream_get_filedescriptor(&is); tcp_set_sendtimeout(sockfd, to_sec, 0); tcp_set_recvtimeout(sockfd, to_sec, 0); if(ISOK(ret = message_write_tcp(mesg, &os))) { output_stream_flush(&os); shutdown(sockfd, SHUT_WR); u16 id = message_get_id(mesg); #if DEBUG message_debug_trash_buffer(mesg); #endif u16 len; #if DEBUG len = ~0; #endif if(ISOK(ret = input_stream_read_nu16(&is, &len))) { if (ISOK(ret = input_stream_read_fully(&is, message_get_buffer(mesg), len))) { message_set_size(mesg, ret); if(message_get_id(mesg) != id) { ret = MESSAGE_HAS_WRONG_ID; } else if(!message_isanswer(mesg)) { ret = MESSAGE_IS_NOT_AN_ANSWER; } else if(message_get_rcode(mesg) != RCODE_NOERROR) { ret = MAKE_DNSMSG_ERROR(message_get_rcode(mesg)); } } else { message_set_size(mesg, 0); } } } shutdown(sockfd, SHUT_RDWR); tcp_set_abortive_close(sockfd); output_stream_close(&os); output_stream_close(&is); } return ret; } ya_result message_query_tcp_with_timeout_ex(message_data *mesg, const host_address *server, message_data *answer, u8 to_sec) { /* connect the server */ ya_result return_value; if(ISOK(return_value = message_set_sender_from_host_address(mesg, server))) { int sockfd; if((sockfd = socket(message_get_sender_sa(mesg)->sa_family, SOCK_STREAM, 0)) >=0) { fd_setcloseonexec(sockfd); socklen_t sa_len = return_value; if(connect(sockfd, message_get_sender_sa(mesg), sa_len) == 0) { #if 1 // DEBUG log_debug("sending %d bytes to %{sockaddr} (tcp)", message_get_size(mesg), message_get_sender(mesg)); log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT); #endif tcp_set_sendtimeout(sockfd, to_sec, 0); tcp_set_recvtimeout(sockfd, to_sec, 0); ssize_t n = message_send_tcp(mesg, sockfd); if(n == (ssize_t)message_get_size(mesg) + 2) { u16 tcp_len; shutdown(sockfd, SHUT_WR); n = readfully(sockfd, &tcp_len, 2); if(n == 2) { tcp_len = ntohs(tcp_len); n = readfully(sockfd, message_get_buffer(answer), tcp_len); if(n == tcp_len) { /* * test the answser * test the TSIG if any */ message_set_size(answer, tcp_len); #if DNSCORE_HAS_TSIG_SUPPORT message_tsig_copy_from(answer, mesg); #endif message_copy_sender_from(answer, mesg); #if DEBUG log_debug("received %d bytes from %{sockaddr} (tcp)", message_get_size(answer), message_get_sender_sa(answer)); log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(answer), message_get_size(answer), 16, OSPRINT_DUMP_HEXTEXT); #endif return_value = message_process_lenient(answer); } else { return_value = UNEXPECTED_EOF; } } else { return_value = UNEXPECTED_EOF; } } else { return_value = UNABLE_TO_COMPLETE_FULL_WRITE; } } else { // Linux quirk ... if(errno != EINPROGRESS) { return_value = ERRNO_ERROR; } else { return_value = MAKE_ERRNO_ERROR(ETIMEDOUT); } } shutdown(sockfd, SHUT_RDWR); tcp_set_abortive_close(sockfd); close_ex(sockfd); } else { return_value = ERRNO_ERROR; } } return return_value; } ya_result message_query_udp(message_data *mesg, const host_address *server) { ya_result return_code = SUCCESS; int seconds = 0; int useconds = 500000; yassert(mesg != NULL); yassert(server != NULL); return_code = message_query_udp_with_timeout(mesg, server, seconds, useconds); return return_code; } ya_result message_query_udp_with_timeout_and_retries(message_data *mesg, const host_address *server, int seconds, int useconds, u8 retries, u8 flags) { ya_result return_value = SUCCESS; random_ctx rndctx = thread_pool_get_random_ctx(); u16 id; for(u8 countdown = retries; countdown > 0; ) { if (flags & MESSAGE_QUERY_UDP_FLAG_RESET_ID) { id = (u16)random_next(rndctx); message_set_id(mesg, id); } else { id = message_get_id(mesg); } if(ISOK(return_value = message_query_udp_with_timeout(mesg, server, seconds, useconds))) { if(message_get_id(mesg) != id) { return_value = MESSAGE_HAS_WRONG_ID; } else if(!message_isanswer(mesg)) { return_value = MESSAGE_IS_NOT_AN_ANSWER; } else if(message_get_rcode(mesg) != RCODE_NOERROR) { return_value = MAKE_DNSMSG_ERROR(message_get_rcode(mesg)); } break; } if(return_value == MAKE_ERRNO_ERROR(EINTR)) { continue; } if(return_value != MAKE_ERRNO_ERROR(EAGAIN) || countdown <= 0) { /* * Do not retry for any other kind of error */ break; } countdown--; usleep_ex(10000); /* 10 ms */ /* if (flags & CHANGE_NAME_SERVER) { } */ } return return_value; } ya_result message_query_udp_with_timeout(message_data *mesg, const host_address *server, int seconds, int useconds) { yassert(mesg != NULL); yassert(server != NULL); /* connect the server */ ya_result ret; u16 id; bool has_fqdn = FALSE; u8 fqdn[MAX_DOMAIN_LENGTH + 1]; if(ISOK(ret = message_set_sender_from_host_address(mesg, server))) { int sockfd; if((sockfd = socket(message_get_sender_sa(mesg)->sa_family, SOCK_DGRAM, 0)) >=0) { fd_setcloseonexec(sockfd); tcp_set_recvtimeout(sockfd, seconds, useconds); /* half a second for UDP is a lot ... */ int send_size = message_get_size(mesg); ssize_t n; if((n = message_send_udp(mesg, sockfd)) == send_size) { id = message_get_id(mesg); if(message_get_query_count_ne(mesg) != 0) { has_fqdn = TRUE; dnsname_copy(fqdn, message_get_buffer_const(mesg) + 12); } message_data_with_buffer recv_mesg_buff; message_data *recv_mesg = message_data_with_buffer_init(&recv_mesg_buff); //recv_mesg._tsig.hmac = mesg->_tsig.hmac; s64 time_limit = seconds; time_limit *= ONE_SECOND_US; time_limit += useconds; time_limit += timeus(); ret = SUCCESS; while((n = message_recv_udp(recv_mesg, sockfd)) >= 0) { #if DEBUG log_memdump_ex(g_system_logger, MSG_DEBUG5, message_get_buffer_const(recv_mesg), n, 16, OSPRINT_DUMP_HEXTEXT); #endif // check the id is right if(message_get_id(recv_mesg) == id) { // check that the sender is the one we spoke to if(sockaddr_equals(message_get_sender_sa(mesg), message_get_sender_sa(recv_mesg))) { message_tsig_copy_from(recv_mesg, mesg); if(ISOK(ret = message_process_lenient(recv_mesg))) { // check the domain is right if(!has_fqdn || dnsname_equals(fqdn, message_get_canonised_fqdn(recv_mesg))) { // everything checks up message_copy_sender_from(mesg, recv_mesg); mesg->_ar_start = &mesg->_buffer[recv_mesg->_ar_start - recv_mesg->_buffer]; mesg->_iovec.iov_len = recv_mesg->_iovec.iov_len; mesg->_rcode_ext = recv_mesg->_rcode_ext; mesg->_status = recv_mesg->_status; if(mesg->_buffer_size < mesg->_iovec.iov_len) { mesg->_buffer_size = mesg->_iovec.iov_len; } mesg->_query_type = recv_mesg->_query_type; mesg->_query_class = recv_mesg->_query_class; mesg->_edns = recv_mesg->_edns; mesg->_nsid = recv_mesg->_nsid; if((mesg->_control_buffer_size = recv_mesg->_control_buffer_size) > 0) { memcpy(mesg->_msghdr_control_buffer, recv_mesg->_msghdr_control_buffer, recv_mesg->_control_buffer_size); } dnsname_copy(mesg->_canonised_fqdn, recv_mesg->_canonised_fqdn); memcpy(mesg->_buffer, recv_mesg->_buffer, recv_mesg->_iovec.iov_len); break; } else { ret = MESSAGE_UNEXPECTED_ANSWER_DOMAIN; } } // ret is set to an error } else { ret = INVALID_MESSAGE; } } else { ret = MESSAGE_HAS_WRONG_ID; } s64 time_now = timeus(); if(time_now >= time_limit) { ret = MAKE_ERRNO_ERROR(EAGAIN); break; } s64 time_remaining = time_limit - time_now; tcp_set_recvtimeout(sockfd, time_remaining / 1000000ULL, time_remaining % 1000000ULL); /* half a second for UDP is a lot ... */ } message_finalize(recv_mesg); //recv_mesg._tsig.hmac = NULL; if((n < 0) && ISOK(ret)) { ret = ERRNO_ERROR; } /* timeout */ } else { ret = (n < 0)?n:ERROR; } close_ex(sockfd); } else { ret = ERRNO_ERROR; } } return ret; } ya_result message_query(message_data *mesg, const host_address *server) { ya_result ret; size_t size; u8 header_copy[12]; // keep a copy of the state, in case there is truncation size = message_get_size(mesg); memcpy(header_copy, mesg->_buffer, sizeof(header_copy)); if(ISOK(ret = message_query_udp_with_timeout_and_retries(mesg, server, 1, 0, 3, 0))) { if(message_istruncated(mesg)) { message_set_size(mesg, size); memcpy(mesg->_buffer, header_copy, sizeof(header_copy)); ret = message_query_tcp_with_timeout(mesg, server, 3); } } return ret; } ya_result message_ixfr_query_get_serial(const message_data *mesg, u32 *serial) { packet_unpack_reader_data purd; ya_result return_value; u8 domain_fqdn[MAX_DOMAIN_LENGTH]; u8 soa_fqdn[MAX_DOMAIN_LENGTH]; packet_reader_init_from_message(&purd, mesg); /* Keep only the query */ if(ISOK(return_value = packet_reader_read_fqdn(&purd, domain_fqdn, sizeof(domain_fqdn)))) { purd.offset += 4; /* Get the queried serial */ if(ISOK(return_value = packet_reader_read_fqdn(&purd, soa_fqdn, sizeof(soa_fqdn)))) { if(dnsname_equals(domain_fqdn, soa_fqdn)) { u16 soa_type; u16 soa_class; u32 soa_ttl; u16 soa_rdata_size; u32 soa_serial; if(ISOK(return_value = packet_reader_read_u16(&purd, &soa_type))) { if(soa_type == TYPE_SOA) { if(packet_reader_available(&purd) > 2 + 4 + 2) { packet_reader_read_u16_unchecked(&purd, &soa_class); // checked packet_reader_read_u32_unchecked(&purd, &soa_ttl); // checked packet_reader_read_u16_unchecked(&purd, &soa_rdata_size); // checked if(ISOK(return_value = packet_reader_skip_fqdn(&purd))) { if(ISOK(return_value = packet_reader_skip_fqdn(&purd))) { if(ISOK(return_value = packet_reader_read_u32(&purd, &soa_serial))) { *serial=ntohl(soa_serial); } } } } else { return_value = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } else { return_value = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } } else { return_value = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } } return return_value; } ya_result message_query_serial(const u8 *origin, const host_address *server, u32 *serial_out) { yassert(origin != NULL); yassert(server != NULL); yassert(serial_out != NULL); /* do an SOA query */ ya_result ret; random_ctx rndctx = thread_pool_get_random_ctx(); message_data_with_buffer soa_query_mesg_buff; message_data *soa_query_mesg = message_data_with_buffer_init(&soa_query_mesg_buff); for(u16 countdown = 5; countdown > 0; ) { u16 id = (u16)random_next(rndctx); message_make_query(soa_query_mesg, id, origin, TYPE_SOA, CLASS_IN); if(ISOK(ret = message_query_udp(soa_query_mesg, server))) { const u8 *buffer = message_get_buffer_const(soa_query_mesg); if(MESSAGE_QR(buffer)) { if(MESSAGE_ID(buffer) == id) { if(MESSAGE_RCODE(buffer) == RCODE_NOERROR) { if((MESSAGE_QD(buffer) == NETWORK_ONE_16) && ((MESSAGE_AN(buffer) == NETWORK_ONE_16) || (MESSAGE_NS(buffer) == NETWORK_ONE_16))) { packet_unpack_reader_data pr; packet_reader_init_from_message_at(&pr, soa_query_mesg, DNS_HEADER_LENGTH); // scan-build false positive: if message_query_udp returns no-error, then soa_query_mesg.received is set packet_reader_skip_fqdn(&pr); // checked below packet_reader_skip(&pr, 4); // checked below if(!packet_reader_eof(&pr)) { u8 tmp[MAX_DOMAIN_LENGTH]; /* read and expect an SOA */ if(ISOK(packet_reader_read_fqdn(&pr, tmp, sizeof(tmp)))) { if(dnsname_equals(tmp, origin)) { struct type_class_ttl_rdlen tctr; if(packet_reader_read(&pr, &tctr, 10) == 10) // exact { if((tctr.qtype == TYPE_SOA) && (tctr.qclass == CLASS_IN)) { if(ISOK(ret = packet_reader_skip_fqdn(&pr))) { if(ISOK(ret = packet_reader_skip_fqdn(&pr))) { if(packet_reader_read(&pr, tmp, 4) == 4) // exact { *serial_out = ntohl(GET_U32_AT(tmp[0])); return SUCCESS; } } } } else { ret = MESSAGE_UNEXPECTED_ANSWER_TYPE_CLASS; } } else { ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } else { ret = MESSAGE_UNEXPECTED_ANSWER_DOMAIN; } } else { ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } else { ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } else { ret = INVALID_MESSAGE; } } else { ret = MAKE_DNSMSG_ERROR(message_get_rcode(soa_query_mesg)); } } else { ret = MESSAGE_HAS_WRONG_ID; } } else { ret = MESSAGE_IS_NOT_AN_ANSWER; } break; } if(ret == MAKE_ERRNO_ERROR(EINTR)) { continue; } if(ret != MAKE_ERRNO_ERROR(EAGAIN) || countdown <= 0) { /* * Do not retry for any other kind of error */ break; } countdown--; usleep_ex(10000); /* 10 ms */ } return ret; // fake positive, ret has been initialised } #if MESSAGE_PAYLOAD_IS_POINTER void message_init_ex(message_data* mesg, u32 mesg_size, void *buffer, size_t buffer_size) { ZEROMEMORY(mesg, offsetof(message_data, _msghdr_control_buffer)); // includes the tsig structure mesg->_msghdr.msg_name = &mesg->_sender.sa; mesg->_msghdr.msg_namelen = sizeof(mesg->_sender); mesg->_msghdr.msg_iov = &mesg->_iovec; mesg->_msghdr.msg_iovlen = 1; #if __unix__ mesg->_msghdr.msg_control = NULL; mesg->_msghdr.msg_controllen = 0; #else mesg->_msghdr.msg_control.buf = NULL; mesg->_msghdr.msg_control.len = 0; #endif mesg->_msghdr.msg_flags = 0; //mesg->_msghdr.msg_control = mesg->_msghdr_control_buffer; //mesg->_msghdr.msg_controllen = sizeof(mesg->_msghdr_control_buffer); #if MESSAGE_PAYLOAD_IS_POINTER // #else mesg->_iovec.iov_base = mesg->_buffer; #endif mesg->_iovec.iov_len = buffer_size; #if MESSAGE_PAYLOAD_IS_POINTER mesg->_message_data_size = mesg_size; #endif mesg->_control_buffer_size = sizeof(mesg->_msghdr_control_buffer); mesg->_buffer_size = buffer_size; mesg->_buffer_size_limit = buffer_size; mesg->_tsig.hmac = NULL; #if MESSAGE_PAYLOAD_IS_POINTER mesg->_buffer = (u8*)buffer; mesg->_iovec.iov_base = mesg->_buffer; #if DEBUG memset(buffer,0x5a, buffer_size); #endif #else #if DEBUG memset(&mesg->_buffer,0x5a, mesg->_buffer_size_limit); #endif #endif } #else // MESSAGE_PAYLOAD_IS_POINTER void message_init(message_data* mesg) { ZEROMEMORY(mesg, offsetof(message_data, _msghdr_control_buffer)); mesg->_msghdr.msg_name = &mesg->_sender; mesg->_msghdr.msg_namelen = sizeof(mesg->_sender); mesg->_msghdr.msg_iov = &mesg->_iovec; mesg->_msghdr.msg_iovlen = 1; mesg->_msghdr.msg_control = NULL; mesg->_msghdr.msg_controllen = 0; mesg->_msghdr.msg_flags = 0; //mesg->_msghdr.msg_control = mesg->_msghdr_control_buffer; //mesg->_msghdr.msg_controllen = sizeof(mesg->_msghdr_control_buffer); mesg->_iovec.iov_base = mesg->_buffer; mesg->_iovec.iov_len = NETWORK_BUFFER_SIZE; mesg->_control_buffer_size = sizeof(mesg->_msghdr_control_buffer); mesg->_buffer_size = NETWORK_BUFFER_SIZE; mesg->_buffer_size_limit = NETWORK_BUFFER_SIZE; mesg->_tsig.hmac = NULL; #if DEBUG memset(&mesg->_buffer,0x5a, mesg->_buffer_size_limit); #endif } #endif /** * If pointer is NULL, the structure and buffer will be allocated together * Note that in the current implementation, 8 bytes are reserved for TCP */ message_data* message_new_instance_ex(void *ptr, u32 message_size) // should be size of edns0 or 64K for TCP { message_data *mesg; if(ptr == NULL) { u8 *tmp; size_t message_data_size = ((sizeof(message_data) + 7) & ~7) + message_size; MALLOC_OBJECT_ARRAY_OR_DIE(tmp, u8, message_data_size, MESGDATA_TAG); ptr = &tmp[(sizeof(message_data) + 7) & ~7]; mesg = (message_data*)tmp; message_init_ex(mesg, message_data_size, ptr, message_size); } else { MALLOC_OBJECT_OR_DIE(mesg, message_data, MESGDATA_TAG); // legit message_init_ex(mesg, sizeof(message_data), ptr, message_size); } return mesg; } message_data* message_new_instance() { message_data *mesg; mesg = message_new_instance_ex(NULL, 65536); return mesg; } void message_finalize(message_data *mesg) { if(mesg->_tsig.hmac != NULL) { hmac_free(mesg->_tsig.hmac); mesg->_tsig.hmac = NULL; } if(mesg->_tsig.other != NULL) { free(mesg->_tsig.other); } } void message_free(message_data *mesg) { if(mesg != NULL) { message_finalize(mesg); free(mesg); // legit } } /* * Does not clone the pool. */ message_data* message_dup(const message_data *mesg) { size_t message_size = message_get_size(mesg); if(message_size > mesg->_buffer_size_limit) { return NULL; } message_data *clone = message_new_instance_ex(NULL, mesg->_buffer_size_limit + 8); if(message_get_additional_section_ptr_const(mesg) != NULL) { message_set_additional_section_ptr(clone, &clone->_buffer[ message_get_additional_section_ptr_const(mesg) - message_get_buffer_const(mesg) ]); } memcpy(&clone->_rcode_ext, &mesg->_rcode_ext, offsetof(message_data, _msghdr_control_buffer) ); message_copy_sender_from(clone, mesg); #if __unix__ memcpy(clone->_msghdr_control_buffer, mesg->_msghdr_control_buffer, mesg->_msghdr.msg_controllen); #else memcpy(clone->_msghdr_control_buffer, mesg->_msghdr_control_buffer, mesg->_msghdr.msg_control.len); #endif dnsname_copy(clone->_canonised_fqdn, message_get_canonised_fqdn(mesg)); #if !MESSAGE_PAYLOAD_IS_POINTER SET_U16_AT(clone->_buffer_tcp_len[0], GET_U16_AT(mesg->_buffer_tcp_len[0])); #endif memcpy(message_get_buffer(clone), message_get_buffer_const(mesg), message_get_size(mesg)); message_set_size(clone, message_get_size(mesg)); return clone; } void message_log(logger_handle *logger, int level, const message_data *mesg) { ya_result ret; int index = 0; rdata_desc rrdesc = {0, 0, NULL}; struct type_class_ttl_rdlen *tctrp; u8 rr[32768]; logger_handle_msg(logger,level, "to: %{sockaddr}", message_get_sender_sa(mesg)); logger_handle_msg(logger,level, "id: %i ", message_get_id(mesg)); logger_handle_msg(logger,level, "flags: %02x %02x opcode: %s rcode: %s", message_get_flags_hi(mesg), message_get_flags_lo(mesg), dns_message_opcode_get_name(message_get_opcode(mesg) >> OPCODE_SHIFT), dns_message_rcode_get_name(message_get_rcode(mesg))); logger_handle_msg(logger,level, "qr: %i, an: %i, ns: %i, ar: %i", message_get_query_count(mesg), message_get_answer_count(mesg), message_get_authority_count(mesg), message_get_additional_count(mesg)); packet_unpack_reader_data pr; packet_reader_init_from_message(&pr, mesg); /* fqdn + type + class */ for(u16 qc = message_get_query_count(mesg); qc > 0; --qc) { if(FAIL(ret = packet_reader_read_zone_record(&pr, rr, sizeof(rr)))) { logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret); return; } u16 *type_class = (u16*)&rr[dnsname_len(rr)]; logger_handle_msg(logger,level, "Q%3i: %{dnsname} %{dnstype} %{dnsclass}", index++, rr, &type_class[0], &type_class[1]); } if((message_get_opcode(mesg) == OPCODE_QUERY) || (message_get_opcode(mesg) == OPCODE_NOTIFY)) { for(int section = 1; section <= 3; ++section) { index = 0; for(u16 sc = message_get_section_count(mesg, section); sc > 0; --sc) { if(FAIL(ret = packet_reader_read_record(&pr, rr, sizeof(rr)))) { logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret); return; } tctrp = (struct type_class_ttl_rdlen *)&rr[dnsname_len(rr)]; rrdesc.type = tctrp->qtype; rrdesc.len = ntohs(tctrp->rdlen); rrdesc.rdata = &((u8*)tctrp)[10]; logger_handle_msg(logger, level, "%c%3i: %{dnsname} %i %{typerdatadesc}", "QANa"[section], index++, rr, ntohl(tctrp->ttl), &rrdesc); } } } else if(message_get_opcode(mesg) == OPCODE_UPDATE) { for(int section = 1; section <= 3; ++section) { index = 0; for(u16 sc = message_get_section_count(mesg, section); sc > 0; --sc) { u8 *rdata_buffer; s32 rttl; u16 rtype; u16 rclass; u16 rdata_buffer_size; u16 rdata_size; if(FAIL(ret = packet_reader_read_fqdn(&pr, rr, sizeof(rr)))) { return; } rdata_buffer = &rr[ret]; rdata_buffer_size = sizeof(rr) - ret; if(FAIL(ret = packet_reader_read_u16(&pr, &rtype))) { logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret); return; } if(FAIL(ret = packet_reader_read_u16(&pr, &rclass))) { logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret); return;; } if(FAIL(ret = packet_reader_read_u32(&pr, (u32*)&rttl))) { logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret); return;; } rttl = ntohl(rttl); if(FAIL(ret = packet_reader_read_u16(&pr, &rdata_size))) { logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret); return;; } rdata_size = ntohs(rdata_size); if(rclass != TYPE_ANY) { if(FAIL(ret = packet_reader_read_rdata(&pr, rtype, rdata_size, rdata_buffer, rdata_buffer_size))) // fixed buffer { logger_handle_msg(logger, MSG_ERR, "failed to read zone record: %r", ret); return; } rrdesc.type = rtype; rrdesc.len = rdata_size; rrdesc.rdata = rdata_buffer; logger_handle_msg(logger, level, "%c%3i: %{dnsname} %i %{dnsclass} %{typerdatadesc}", "QANa"[section], index++, rr, rttl, &rclass, &rrdesc); } else { logger_handle_msg(logger, level, "%c%3i: %{dnsname} %i %{dnsclass} %{dnstype}", "QANa"[section], index++, rr, rttl, &rclass, &rtype); } } } } } ya_result message_get_ixfr_query_serial(message_data *mesg, u32 *serialp) { packet_unpack_reader_data purd; ya_result ret; u16 qtype; packet_reader_init_from_message(&purd, mesg); if(FAIL(ret = packet_reader_skip_fqdn(&purd))) { return ret; } if(FAIL(ret = packet_reader_read_u16(&purd, &qtype))) { return ret; } if(qtype != TYPE_IXFR) { return ERROR; // not an IXFR } if(FAIL(ret = packet_reader_skip(&purd, 2))) { return ret; } message_set_size(mesg, purd.offset); /* Get the queried serial */ if(FAIL(ret = packet_reader_skip_fqdn(&purd))) { return ret; } if(FAIL(ret = packet_reader_skip(&purd, 10))) { return ret; } if(FAIL(ret = packet_reader_skip_fqdn(&purd))) { return ret; } if(FAIL(ret = packet_reader_skip_fqdn(&purd))) { return ret; } if(serialp != NULL) { if(FAIL(ret = packet_reader_read_u32(&purd, serialp))) { return ret; } *serialp = ntohl(*serialp); } return SUCCESS; } #if DNSCORE_HAS_TSIG_SUPPORT ya_result message_terminate_then_write(message_data *mesg, output_stream *tcpos, tsig_tcp_message_position pos) #else ya_result message_terminate_then_write(message_data *mesg, output_stream *tcpos, int unused) #endif { ya_result ret; #if !DNSCORE_HAS_TSIG_SUPPORT #pragma message("TSIG SUPPORT HAS BEEN DISABLED") (void)unused; #endif if(message_is_edns0(mesg)) // Dig does a TCP query with EDNS0 { /* 00 00 29 SS SS rr vv 80 00 00 00 */ u8 *buffer = message_get_buffer_limit(mesg); buffer[ 0] = 0; buffer[ 1] = 0; buffer[ 2] = 0x29; buffer[ 3] = edns0_maxsize >> 8; buffer[ 4] = edns0_maxsize; buffer[ 5] = message_get_status(mesg) >> 4; buffer[ 6] = mesg->_rcode_ext >> 16; buffer[ 7] = mesg->_rcode_ext >> 8; buffer[ 8] = mesg->_rcode_ext; buffer[ 9] = 0; buffer[10] = 0; message_increase_size(mesg, 11); message_set_additional_count_ne(mesg, NU16(1)); } else { message_set_additional_count_ne(mesg, 0); } #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) { if(FAIL(ret = tsig_sign_tcp_message(mesg, pos))) { return ret; } } #endif ret = message_write_tcp(mesg, tcpos); return ret; } /** * Maps records in a message to easily access them afterward. * * @param map the message map to initialise * @param mesg the message to map * @param tight do two passes to use the least amount of memory possible * * @return an error code */ ya_result message_map_init(message_map *map, const message_data *mesg) { map->mesg = mesg; packet_unpack_reader_data purd; packet_reader_init_from_message(&purd, mesg); ya_result ret; u16 qc = message_get_query_count(mesg); u16 an = message_get_answer_count(mesg); u16 ns = message_get_authority_count(mesg); u16 ar = message_get_additional_count(mesg); int total = qc; total += an; total += ns; total += ar; ptr_vector_init_ex(&map->records, total); int i; for(i = 0; i < qc; ++i) { ptr_vector_append(&map->records, (void*)packet_reader_get_next_u8_ptr_const(&purd)); packet_reader_skip_fqdn(&purd); // checked below if(FAIL(ret = packet_reader_skip(&purd, 4))) { message_map_finalize(map); return ret; } } for(; i < total; ++i) { ptr_vector_append(&map->records, (void*)packet_reader_get_next_u8_ptr_const(&purd)); if(FAIL(ret = packet_reader_skip_record(&purd))) { message_map_finalize(map); return ret; } } ret = ptr_vector_size(&map->records); map->section_base[0] = 0; map->section_base[1] = message_get_section_count(map->mesg, 0) + map->section_base[0]; map->section_base[2] = message_get_section_count(map->mesg, 1) + map->section_base[1]; map->section_base[3] = message_get_section_count(map->mesg, 2) + map->section_base[2]; return ret; } /** * Gets the fqdn of the record at index * * @param map * @param index * @param fqdn * @param fqdn_size * * @return an error code */ ya_result message_map_get_fqdn(const message_map *map, int index, u8 *fqdn, int fqdn_size) { if((index >= 0) && (index <= ptr_vector_last_index(&map->records))) { if(dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), ptr_vector_get(&map->records, index), fqdn, fqdn_size) != NULL) { return SUCCESS; } } return ERROR; } /** * Gets the type class ttl rdata_size of the record at index * * @param map * @param index * @param tctr * * @return an error code */ ya_result message_map_get_tctr(const message_map *map, int index, struct type_class_ttl_rdlen *tctr) { if((index >= 0) && (index <= ptr_vector_last_index(&map->records))) { const u8 *p; if((p = dnsname_skip_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), ptr_vector_get(&map->records, index))) != NULL) { if(index >= map->section_base[1]) { if(message_get_buffer_limit_const(map->mesg) - p >= 10) { memcpy(tctr, p, 10); return SUCCESS; } } else { if(message_get_buffer_limit_const(map->mesg) - p >= 4) { memcpy(tctr, p, 4); tctr->ttl = 0; tctr->rdlen = 0; return SUCCESS; } } } } return ERROR; } /** * Gets the rdata of the record at index * * @param map * @param index * @param rdata * @param rdata_size * * @return the rdata size or an error code */ ya_result message_map_get_rdata(const message_map *map, int index, u8 *rdata, int rdata_size) { if((index >= (int)map->section_base[1]) && (index <= ptr_vector_last_index(&map->records))) { const u8 *p; if((p = dnsname_skip_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), ptr_vector_get(&map->records, index))) != NULL) { if(message_get_buffer_limit_const(map->mesg) - p >= 10) { const u8 *rdata_base = rdata; size_t d; u16 rtype = GET_U16_AT_P(p); p += 8; u16 n = ntohs(GET_U16_AT_P(p)); p += 2; if(message_get_buffer_limit_const(map->mesg) - p >= n) { switch(rtype) { /****************************************************************************** * The types that requires special handling (dname compression) ******************************************************************************/ case TYPE_MX: case TYPE_AFSDB: { if(rdata_size < 3) // minimal expected size { return INVALID_RECORD; } SET_U16_AT_P(rdata, GET_U16_AT_P(p)); rdata += 2; rdata_size -= 2; p += 2; } FALLTHROUGH // fall through case TYPE_NS: case TYPE_CNAME: case TYPE_DNAME: case TYPE_PTR: case TYPE_MB: case TYPE_MD: case TYPE_MF: case TYPE_MG: case TYPE_MR: { if((p = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), p, rdata, rdata_size)) != NULL) { return p - rdata_base; } return INVALID_RECORD; } case TYPE_SOA: { if((p = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), p, rdata, rdata_size)) != NULL) { d = dnsname_len(rdata); rdata += d; rdata_size -= d; if((p = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), p, rdata, rdata_size)) != NULL) { d = dnsname_len(rdata); rdata += d; rdata_size -= d; if(rdata_size >= 20) { memcpy(rdata, p, 20); return &rdata[20] - rdata_base; } } } return INVALID_RECORD; } case TYPE_RRSIG: /* not supposed to be compressed */ { if(rdata_size > RRSIG_RDATA_HEADER_LEN) { const u8 *p_base = p; memcpy(rdata, p, RRSIG_RDATA_HEADER_LEN); rdata += RRSIG_RDATA_HEADER_LEN; rdata_size -= RRSIG_RDATA_HEADER_LEN; p += RRSIG_RDATA_HEADER_LEN; if((p = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), p, rdata, rdata_size)) != NULL) { d = dnsname_len(rdata); rdata += d; //rdata_size -= d; d = p - p_base; memcpy(rdata, p, d); return &rdata[d] - rdata_base; } } return INVALID_RECORD; } case TYPE_NSEC: /* not supposed to be compressed */ { const u8 *p_base = p; if((p = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), p, rdata, rdata_size)) != NULL) { d = dnsname_len(rdata); rdata += d; //rdata_size -= d; d = p - p_base; memcpy(rdata, p, d); return &rdata[d] - rdata_base; } return INVALID_RECORD; } default: { if(rdata_size >= n) { memcpy(rdata, p, n); return n; } return INVALID_RECORD; } } // switch type } } } } return ERROR; } /** * Gets the type of the record at index * * @param map * @param index * * @return the record type or an error code */ ya_result message_map_get_type(const message_map *map, int index) { if((index >= 0) && (index <= ptr_vector_last_index(&map->records))) { const u8 *p; if((p = dnsname_skip_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), ptr_vector_get(&map->records, index))) != NULL) { if(message_get_buffer_limit_const(map->mesg) - p >= 2) { u16 rtype = GET_U16_AT_P(p); return rtype; } } } return ERROR; } /** * * @param map * * @return the number of records mapped */ int message_map_record_count(const message_map *map) { int size = ptr_vector_size(&map->records); return size; } /** * Returns the index of the next record with the given type * from, and including, a given index. * * @param map * @param index * @param type * @return */ int message_map_get_next_record_from(const message_map *map, int index, u16 type) { ya_result ret; for(;;) { ret = message_map_get_type(map, index); if(ret == type) { return index; } if(FAIL(ret)) { return ret; } ++index; } } /** * Returns the index of the next record with the given type * from, and including, a given index in a given section (0 to 3). * * @param map * @param index * @param type * @return */ int message_map_get_next_record_from_section(const message_map *map, int section, int index, u16 type) { if(index < 0) { return INVALID_ARGUMENT_ERROR; } u16 sc = message_get_section_count(map->mesg, section); if(index >= sc) { return INVALID_ARGUMENT_ERROR; } ya_result ret; do { ret = message_map_get_type(map, map->section_base[section] + index); if(ret == type) { return index; } if(FAIL(ret)) { return ret; } ++index; } while(index < sc); return ERROR; } /** * Releases the memory used by the map * * @param map */ void message_map_finalize(message_map *map) { ptr_vector_destroy(&map->records); } static int message_map_reorder_remap_type(int t, int ct) { int r; switch(t) { case TYPE_SOA: r = 0 << 1; break; case TYPE_NSEC: r = 0x7ffe << 1; break; case TYPE_NSEC3: r = 0x7fff << 1; break; case TYPE_RRSIG: r = message_map_reorder_remap_type(ct, 0) + 1; break; default: r = (ntohs(t) + 0x1000) << 1; break; } return r; } static int message_map_reorder_comparator(const void *rra, const void *rrb, void *ctx) { const u8 *pa = (const u8*)rra; const u8 *pb = (const u8*)rrb; message_map *map = (message_map *)ctx; struct type_class_ttl_rdlen tctra; struct type_class_ttl_rdlen tctrb; u16 ctypea; u16 ctypeb; u8 fqdna[256]; u8 fqdnb[256]; if(rra == rrb) { return 0; } pa = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), rra, fqdna, sizeof(fqdna)); memcpy(&tctra, pa, 10); pa += 10; if(tctra.qtype == TYPE_RRSIG) { ctypea = GET_U16_AT_P(pa); } else { ctypea = 0; } pa += 10; pb = dnsname_expand_compressed(message_get_buffer_const(map->mesg), message_get_size(map->mesg), rrb, fqdnb, sizeof(fqdnb)); memcpy(&tctrb, pb, 10); pb += 10; if(tctrb.qtype == TYPE_RRSIG) { ctypeb = GET_U16_AT_P(pb); } else { ctypeb = 0; } tctra.rdlen = ntohs(tctra.rdlen); tctrb.rdlen = ntohs(tctrb.rdlen); int rdata_size_d = tctra.rdlen; int rdata_size_min = MIN(tctra.rdlen, tctrb.rdlen); rdata_size_d -= tctrb.rdlen; int d; bool n3a = (tctra.qtype == TYPE_NSEC3) || (ctypea == TYPE_NSEC3); bool n3b = (tctrb.qtype == TYPE_NSEC3) || (ctypeb == TYPE_NSEC3); if(n3a) { if(n3b) { // both are NSEC3 related: normal sort } else { // the NSEC3 one is after the normal one return 1; } } else // the first one is not NSEC3 related { if(n3b) { // the second one is: it comes after the normal one return -1; } else { // none are NSEC3 related: normal sort } } d = dnsname_compare(fqdna, fqdnb); if(d == 0) { // let's avoid lot's of if-then-else int ta = message_map_reorder_remap_type(tctra.qtype, ctypea); int tb = message_map_reorder_remap_type(tctrb.qtype, ctypeb); d = ta - tb; if(d == 0) { d = memcmp(pa, pb, rdata_size_min); if(d == 0) { d = rdata_size_d; } } } return d; } /** * Sorts records by section so that: * _ SOA is first, * _ NSEC is last, * _ NSEC3 labels are at the end, * _ RRSIG follows its RRSET * * @param map */ void message_map_reorder(message_map *map) { // apply message_map_reorder_comparator to sections 1, 2 and 3. ptr_vector fakev; for(int section = 1; section < 4; ++section) { int sc = message_get_section_count(map->mesg, section); if(sc > 1) { fakev.data = &map->records.data[map->section_base[section]]; fakev.offset = sc - 1; fakev.size = fakev.offset + 1; ptr_vector_qsort_r(&fakev, message_map_reorder_comparator, map); } } } void message_map_print(const message_map *map, output_stream *os) { osformat(os, ";; opcode: %s, status: %s, id: %i, flags:", dns_message_opcode_get_name(message_get_opcode(map->mesg) >> OPCODE_SHIFT), dns_message_rcode_get_name(message_get_rcode(map->mesg)), ntohs(message_get_id(map->mesg))); u8 h = message_get_flags_hi(map->mesg); if(h & QR_BITS) output_stream_write(os, "qr ", 3); if(h & AA_BITS) output_stream_write(os, "aa ", 3); if(h & TC_BITS) output_stream_write(os, "tc ", 3); if(h & RD_BITS) output_stream_write(os, "rd ", 3); u8 l = message_get_flags_hi(map->mesg); if(l & RA_BITS) output_stream_write(os, "ra ", 3); if(l & AD_BITS) output_stream_write(os, "ad ", 3); if(l & CD_BITS) output_stream_write(os, "cd ", 3); osformatln(os, "\n;; SECTION: [%i ,%i, %i, %i]", message_get_section_count(map->mesg, 0), message_get_section_count(map->mesg, 1), message_get_section_count(map->mesg, 2), message_get_section_count(map->mesg, 3)); struct type_class_ttl_rdlen tctr; u8 tmp[1024]; int i = 0; for(int section = 0; section < 4; ++section) { osformatln(os, ";; SECTION %i:", section); for(int n = message_get_section_count(map->mesg, section); n > 0; --n) { message_map_get_fqdn(map, i, tmp, sizeof(tmp)); if(ISOK(message_map_get_tctr(map, i, &tctr))) { osformat(os, "%{dnsname} %9i %{dnsclass} %{dnstype} ", tmp, ntohl(tctr.ttl), &tctr.qclass, &tctr.qtype); if(section > 0) { int rdata_size = message_map_get_rdata(map, i, tmp, sizeof(tmp)); rdata_desc rd = {tctr.qtype, rdata_size, tmp}; osformat(os, "%{rdatadesc}", &rd); } osprintln(os, ""); ++i; } else { osformatln(os, "%{dnsname} READ FAILURE\n", tmp); break; } } osprintln(os, ""); } } s32 message_send_udp_debug(const message_data *mesg, int sockfd) { log_info("message_send_udp(%p, %i) through %{sockaddr}", mesg, sockfd, mesg->_msghdr.msg_name); s32 n; void** p = (void**)&mesg->_msghdr.msg_control; *p = NULL; while((n = sendmsg(sockfd, &mesg->_msghdr, 0)) < 0) { int err = errno; if(err != EINTR) { return MAKE_ERRNO_ERROR(err); } } return n; } ssize_t message_send_tcp(const message_data *mesg, int sockfd) { ssize_t ret; struct msghdr tcp_msghdr; struct iovec tcp_data[2]; u16 tcp_len = message_get_size_u16(mesg); u16 tcp_native_len = htons(tcp_len); tcp_data[0].iov_base = &tcp_native_len; tcp_data[0].iov_len = 2; tcp_data[1].iov_base = mesg->_buffer; tcp_data[1].iov_len = tcp_len; tcp_msghdr.msg_name = mesg->_msghdr.msg_name; tcp_msghdr.msg_namelen = mesg->_msghdr.msg_namelen; tcp_msghdr.msg_iov = &tcp_data[0]; tcp_msghdr.msg_iovlen = 2; tcp_msghdr.msg_control = mesg->_msghdr.msg_control; #if __unix__ tcp_msghdr.msg_controllen = mesg->_msghdr.msg_controllen; #endif tcp_msghdr.msg_flags = 0; s32 remain = tcp_len + 2; #if DEBUG s32 again = 0; #endif for(;;) { ret = sendmsg(sockfd, &tcp_msghdr, 0); if(ret < 0) { int err = ERRNO_ERROR; if(err == MAKE_ERRNO_ERROR(EINTR)) { continue; } if(err == MAKE_ERRNO_ERROR(EAGAIN)) { #if DEBUG ++again; #endif usleep(100); continue; } ret = err; break; } remain -= ret; if(remain == 0) { break; } while(tcp_msghdr.msg_iovlen > 0) { if((size_t)ret < tcp_msghdr.msg_iov[0].iov_len) { u8* p = (u8*)tcp_msghdr.msg_iov[0].iov_base; p += ret; tcp_msghdr.msg_iov[0].iov_base = p; tcp_msghdr.msg_iov[0].iov_len -= (size_t)ret; break; } else { ret -= (size_t)tcp_msghdr.msg_iov[0].iov_len; ++tcp_msghdr.msg_iov; --tcp_msghdr.msg_iovlen; if(ret == 0) { break; } } } } #if DEBUG if(again > 0) { log_debug("message_send_tcp: again=%i", again); } #endif return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/message_print_format_dig.c0000644000000000000000000000013214505005532024527 xustar000000000000000030 mtime=1695812442.435982088 30 atime=1695812445.794030182 30 ctime=1695812494.626729564 yadifa-2.6.5-11201/lib/dnscore/src/message_print_format_dig.c0000664000374500037450000002755014505005532024502 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore System core functions * @brief System core functions * * @{ */ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/counter_output_stream.h" #include "dnscore/format.h" #include "dnscore/message.h" #include "dnscore/packet_reader.h" static char* message_section_names[4] = { "QUESTION SECTION", "ANSWER SECTION", "AUTHORITY SECTION", "ADDITIONAL SECTION" }; static char* message_section_update_names[4] = { "ZONE", "PREREQUISITES", "UPDATE RECORDS", "ADDITIONAL RECORDS" }; static char* message_count_names[4] = { "QUERY", "ANSWER", "AUTHORITY", "ADDITIONAL" }; static char* message_count_update_names[4] = { "ZONE", "PREREQUISITES", "UPDATE", "ADDITIONAL" }; ya_result message_print_format_dig_buffer(output_stream *os_, const u8 *buffer, u32 length, u16 view_mode_with) { ya_result return_value; /* * There is no padding support for formats on complex types (padding is ignored) * Doing it would be relatively expensive for it's best doing it manually when needed (afaik: only here) */ counter_output_stream_data counters; output_stream cos; counter_output_stream_init(os_, &cos, &counters); output_stream *os = &cos; packet_unpack_reader_data purd; u8 record_wire[MAX_DOMAIN_LENGTH + 10 + 65535]; /* ------------------------------------------------------------ */ /* Init packet reader with buffer. length and offset in the buffer */ packet_reader_init_at(&purd, buffer, length, DNS_HEADER_LENGTH); /* 1. GET ID */ u16 id = MESSAGE_ID(buffer); /* 2. GET OPCODE AND RCODE */ u8 opcode_shifted= MESSAGE_OP(buffer); u8 opcode = opcode_shifted >> OPCODE_SHIFT; u8 rcode = MESSAGE_RCODE(buffer); const char *opcode_txt = dns_message_opcode_get_name(opcode); const char *status_txt = dns_message_rcode_get_name(rcode); /* 3. GET VALUES OF THE SECTIONS */ u16 count[4]; count[0] = ntohs(MESSAGE_QD(buffer)); count[1] = ntohs(MESSAGE_AN(buffer)); count[2] = ntohs(MESSAGE_NS(buffer)); count[3] = ntohs(MESSAGE_AR(buffer)); /* 4. GET THE NAMES FOR THE PRESENTATION */ char **count_name = (opcode_shifted != OPCODE_UPDATE)? message_count_names : message_count_update_names; char **section_name = (opcode_shifted != OPCODE_UPDATE)? message_section_names : message_section_update_names; /* 5. FILL THE STREAM */ /* fill the information of the header of a DNS packet */ osformat(os, ";; ->>HEADER<<- opcode: %s, status: %s, id: %hd\n", opcode_txt, status_txt, ntohs(id)); osformat(os, ";; flags: "); if(MESSAGE_QR(buffer) != 0) osprint(os, "qr "); if(MESSAGE_AA(buffer) != 0) osprint(os, "aa "); if(MESSAGE_TC(buffer) != 0) osprint(os, "tc "); if(MESSAGE_RD(buffer) != 0) osprint(os, "rd "); if(MESSAGE_RA(buffer) != 0) osprint(os, "ra "); if(MESSAGE_ZF(buffer) != 0) osprint(os, "zf "); if(MESSAGE_AD(buffer) != 0) osprint(os, "ad "); if(MESSAGE_CD(buffer) != 0) osprint(os, "cd "); osformat(os, "%s: %hd, %s: %hd, %s: %hd, %s: %hd\n", count_name[0], count[0], count_name[1], count[1], count_name[2], count[2], count_name[3], count[3] ); { u32 section_idx = 0; /* Print SECTION name */ if(message_viewer_requires_section(section_idx, view_mode_with)) { osformat(os, "\n;; %s:\n", section_name[section_idx]); } for(u16 n = count[section_idx]; n > 0; n--) { /* 1. GET EVERYTHING FROM THE BUFFER FOR QUESTION + OFFSET packet reader */ /* Retrieve QNAME from packet reader */ if(FAIL(return_value = packet_reader_read_fqdn(&purd, record_wire, sizeof(record_wire)))) { return return_value; } /* Retrieve QTYPE from packet reader */ u16 rtype; if(FAIL(return_value = packet_reader_read_u16(&purd, &rtype))) { return return_value; } /* Retrieve QCLASS from packet reader */ u16 rclass; if(FAIL(return_value = packet_reader_read_u16(&purd, &rclass))) { return return_value; } /* Print everything from QUESTION SECTION */ if(message_viewer_requires_section(section_idx, view_mode_with)) { u64 next = counters.write_count + 24 + 8; /* write NAME + alignment for next item */ osformat(os, ";%{dnsname}", record_wire); while(counters.write_count < next) { output_stream_write_u8(os, (u8)' '); } output_stream_write_u8(os, (u8)' '); next = counters.write_count + 7; /* write CLASS + alignment for next item */ osformat(os, "%7{dnsclass}", &rclass); while(counters.write_count < next) { output_stream_write_u8(os, (u8)' '); } output_stream_write_u8(os, (u8)' '); // next = counters.write_count + 7; /* write TYPE */ osformatln(os, "%7{dnstype}", &rtype); } } osprintln(os, ""); } for(u32 section_idx = 1; section_idx < 4; section_idx++) { if(message_viewer_requires_section(section_idx, view_mode_with)) { osformat(os, ";; %s:\n", section_name[section_idx]); } for(u16 n = count[section_idx]; n > 0; n--) { /* Get next record and put the packet reader offset on the next record */ if(FAIL(return_value = packet_reader_read_record(&purd, record_wire, sizeof(record_wire)))) { return return_value; } /* Initialize the values needed for printing */ u8 *rname = record_wire; u8 *rdata = rname + dnsname_len(rname); // points to {type class ttl rdata_size} u16 rtype = GET_U16_AT(rdata[0]); if(section_idx == 3) { if(rtype == TYPE_OPT) { continue; } else if(rtype == TYPE_TSIG) { continue; } } u16 rclass = GET_U16_AT(rdata[2]); u32 rttl = ntohl(GET_U32_AT(rdata[4])); u16 rdata_size = ntohs(GET_U16_AT(rdata[8])); rdata += 10; // skip the type class ttl rdata_len // test that rdata_size matches the record size if(&rdata[rdata_size] != &record_wire[return_value]) { // rdata_size doesn't exactly matches the returned size osformatln(os, ";; error reading the message"); return MAKE_RCODE_ERROR(RCODE_FORMERR); } u64 next = counters.write_count + 24; /* Starting printing */ if(message_viewer_requires_section(section_idx, view_mode_with)) { /* write NAME + alignment for next item */ osformat(os, "%{dnsname}", rname); while(counters.write_count < next) { output_stream_write_u8(os, (u8)' '); } output_stream_write_u8(os, (u8)' '); /* write TTL + alignment for next item */ osformat(os, "%7d", rttl); output_stream_write_u8(os, (u8)' '); next = counters.write_count + 7; /* write CLASS + alignment for next item */ osformat(os, "%7{dnsclass}", &rclass); while(counters.write_count < next) { output_stream_write_u8(os, (u8)' '); } output_stream_write_u8(os, (u8)' '); next = counters.write_count + 7; /* write TYPE + alignment for next item */ osformat(os, "%7{dnstype} ", &rtype); while(counters.write_count < next) { output_stream_write_u8(os, (u8)' '); } output_stream_write_u8(os, (u8)' '); /* write RDATA */ osprint_rdata(os, rtype, rdata, rdata_size); osprintln(os, ""); } } if(message_viewer_requires_section(section_idx, view_mode_with)) { osprintln(os, ""); } } return 0; } ya_result message_print_format_dig(output_stream *os, const u8 *buffer, u32 length, u16 view_mode_with, long time_duration) { ya_result return_value; time_t timep; /* ------------------------------------------------------------ */ osformat(os, ";; global options: \n"); osformat(os, ";; Got answer:\n"); if(FAIL(return_value = message_print_format_dig_buffer(os, buffer, length, view_mode_with))) { return return_value; } time(&timep); if(time_duration >= 0) { osformat(os, ";; Query time: %ld msec\n", time_duration); } /** @todo 20130530 gve -- still need to implemented the server viewable line */ // osformat(os, ";; SERVER: %{hostaddr}(%{hostaddr})\n", config->server, config->server); osformat(os, ";; WHEN: %s", ctime(&timep)); if(time_duration >= 0) { osformat(os, ";; MSG SIZE rcvd: %ld\n", length); } else { osformat(os, ";; MSG SIZE: %ld\n", length); } osformat(os, "\n"); return OK; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/message_verify_rrsig.c0000644000000000000000000000013214505005532023712 xustar000000000000000030 mtime=1695812442.426981959 30 atime=1695812445.793030168 30 ctime=1695812494.628729593 yadifa-2.6.5-11201/lib/dnscore/src/message_verify_rrsig.c0000664000374500037450000006203014505005532023655 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include "dnscore/sys_types.h" #include "dnscore/message_verify_rrsig.h" #include "dnscore/packet_reader.h" #include "dnscore/format.h" #include "dnscore/ptr_set.h" #include "dnscore/logger.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define TYPE_FQDN_HAS_RECORDS 1 #define TYPE_FQDN_HAS_SIGNATURES 2 //#define TYPE_FQDN_HAS_VERIFIED_SIGNATURES 4 //#define TYPE_FQDN_HAS_WRONG_SIGNATURES 8 //#define TYPE_FQDN_HAS_UNKNOWN_SIGNATURES 16 #define RRSVFQDN_TAG 0x4e44514656535252 #define MSGVRDTT_TAG 0x545444525647534d void message_verify_rrsig_format_handler(const void *result_u8_ptr, output_stream *os, s32 p0, char p1, bool p2, void* reserved_for_method_parameters) { (void)p0; (void)p1; (void)p2; (void)reserved_for_method_parameters; u8 flag = *(u8*)result_u8_ptr; static const char *separator = ","; int separator_size = 0; if(flag & MESSAGE_VERIFY_RRSIG_NOTSIGNED) { output_stream_write(os, "not-signed", 10); separator_size = 1; } if(flag & MESSAGE_VERIFY_RRSIG_WRONG) { output_stream_write(os, separator, separator_size); output_stream_write(os, "wrong", 5); separator_size = 1; } if(flag & MESSAGE_VERIFY_RRSIG_VERIFIED) { output_stream_write(os, separator, separator_size); output_stream_write(os, "verified", 8); separator_size = 1; } if(flag & MESSAGE_VERIFY_RRSIG_TIMEFRAME) { output_stream_write(os, separator, separator_size); output_stream_write(os, "wrong-time-frame", 16); separator_size = 1; } if(flag & MESSAGE_VERIFY_RRSIG_NOKEY) { output_stream_write(os, separator, separator_size); output_stream_write(os, "no-key", 6); } } static s32 message_verify_rrsig_compute_digest(const u8 *owner, u16 rtype, u16 rclass, const u8 *rrsig_rdata, u32 rrsig_rdata_size, ptr_vector *rrset_canonised_rdata, digest_s *ctx_ptr) { log_debug6("message_verify_rrsig_compute_digest(%{dnsname},%{dnstype},%{dnsclass},@%p,%u,@%p,@%p)", owner, &rtype, &rclass, rrsig_rdata, rrsig_rdata_size, rrset_canonised_rdata, ctx_ptr); u8 rr_header[2 + 2 + 4]; if(rrsig_rdata_size < RRSIG_RDATA_HEADER_LEN) { return INCORRECT_RDATA; } if(rtype != GET_U16_AT(rrsig_rdata[0])) { return RRSIG_COVERED_TYPE_DIFFERS; } s32 owner_len = dnsname_len(owner); u32 rttl = GET_U32_AT(rrsig_rdata[4]); SET_U16_AT(rr_header[0], rtype); SET_U16_AT(rr_header[2], rclass); SET_U32_AT(rr_header[4], rttl); ya_result err; if(FAIL(err = dnskey_digest_init(ctx_ptr, rrsig_rdata[2]))) { log_err("message_verify_rrsig_compute_digest: %r", err); return err; } /* * Type covered | algorithm | labels | original_ttl | exp | inception | tag | origin * */ u32 rrsig_rdata_prefix_size = RRSIG_RDATA_HEADER_LEN + dnsname_len(&rrsig_rdata[RRSIG_RDATA_HEADER_LEN]); digest_update(ctx_ptr, rrsig_rdata, rrsig_rdata_prefix_size); #if DEBUG log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, rrsig_rdata, rrsig_rdata_prefix_size, 32); #endif for(s32 i = 0; i <= rrset_canonised_rdata->offset; i++) { digest_update(ctx_ptr, owner, owner_len); #if DEBUG log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, owner, owner_len, 32); #endif digest_update(ctx_ptr, rr_header, sizeof(rr_header)); #if DEBUG log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, rr_header, sizeof(rr_header), 32); #endif u8 *rdata_size_rdata = (u8*)rrset_canonised_rdata->data[i]; u16 rdata_size = ntohs(GET_U16_AT(rdata_size_rdata[0])); digest_update(ctx_ptr, rdata_size_rdata, rdata_size + 2); #if DEBUG log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, rdata_size_rdata, rdata_size + 2, 32); #endif } /* * Retrieve the digest */ digest_final(ctx_ptr); #if DEBUG log_debug6("digest:"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG6, digest_get_digest_ptr(ctx_ptr), digest_get_size(ctx_ptr), 32); #endif #if RRSIG_DUMP log_debug5("rrsig: digest:"); log_memdump_ex(MODULE_MSG_HANDLE, MSG_DEBUG5, digest_out, out_digest_size, 32, OSPRINT_DUMP_HEX); #endif return digest_get_size(ctx_ptr); } static int message_verify_canonize_sort_rdata_compare(const void *a, const void *b) { u8* ptr_a = (u8*)a; u8* ptr_b = (u8*)b; u16 rr_a_size = ntohs(GET_U16_AT(ptr_a[0])); u16 rr_b_size = ntohs(GET_U16_AT(ptr_b[0])); int ret; ptr_a += 2; ptr_b += 2; int diff_len = rr_a_size; diff_len -= rr_b_size; if(diff_len != 0) { u16 len = MIN(rr_a_size, rr_b_size); ret = memcmp(ptr_a, ptr_b, len); if(ret == 0) { ret = diff_len; } } else { ret = memcmp(ptr_a, ptr_b, rr_a_size); } return ret; } static ya_result message_verify_rrsig_result_default_handler(const message_data *mesg, const struct dnskey_keyring *keyring, const message_verify_rrsig_result_s *result, void *args) { (void)mesg; (void)keyring; (void)result; (void)args; return MESSAGE_VERIFY_RRSIG_FEEDBACK_CONTINUE; } static void message_verify_rrsig_free_rrset(void *data) { free(data); } static int message_verify_rrsig_node_compare(const void *key_a, const void *key_b) { const u8 *fqdn_a = key_a; const u8 *fqdn_b = key_b; s32 type_a = GET_U16_AT_P(fqdn_a); s32 type_b = GET_U16_AT_P(fqdn_b); s32 ret = type_a - type_b; if(ret == 0) { fqdn_a += 2; fqdn_b += 2; ret = dnsname_compare(fqdn_a, fqdn_b); } return ret; } static void message_verify_rrsig_init(ptr_set *section_type_fqdn) { ptr_set_init(section_type_fqdn); section_type_fqdn->compare = message_verify_rrsig_node_compare; } static void message_verify_rrsig_set_flag(ptr_set *section_type_fqdn, const u8 *type_record_fqdn, u32 type_record_fqdn_len, u8 flag_bits) { // create the type-fqdn entry if needed ptr_node *type_fqdn_node = ptr_set_find(section_type_fqdn, type_record_fqdn); if(type_fqdn_node == NULL) { #if DEBUG log_debug7("message_verify_rrsig: new node %{dnsname} %{dnstype}", type_record_fqdn + 2, type_record_fqdn); #endif u8 *type_record_fqdn_copy; MALLOC_OR_DIE(u8*,type_record_fqdn_copy, type_record_fqdn_len, RRSVFQDN_TAG); memcpy(type_record_fqdn_copy, type_record_fqdn, type_record_fqdn_len); type_fqdn_node = ptr_set_insert(section_type_fqdn, type_record_fqdn_copy); type_fqdn_node->value = NULL; // has records, has verified signatures, has wrong signatures, has unknown signatures // the next phase will scan for each of there types instead } intptr flag = (intptr)type_fqdn_node->value; #if DEBUG log_debug7("message_verify_rrsig: set node %{dnsname} %{dnstype} %x => %x", type_record_fqdn + 2, type_record_fqdn, flag, flag | flag_bits); #endif flag |= flag_bits; type_fqdn_node->value = (void*)flag; } static void message_verify_rrsig_clear_callback(ptr_node *type_fqdn_node) { free(type_fqdn_node->key); } static void message_verify_rrsig_clear(ptr_set *section_type_fqdn) { // create the type-fqdn entry if needed ptr_set_callback_and_destroy(section_type_fqdn, message_verify_rrsig_clear_callback); } /** * * @param mesg * @param keyring * @param feedback see the definition of message_verify_rrsig_result * @param args argument for the feedback function * @return */ ya_result message_verify_rrsig(const message_data *mesg, struct dnskey_keyring *keyring, message_verify_rrsig_result *feedback, void *args) { // for the answer, authority and additional sections // count the RRSIG in the section for which we have a key // for all rrset but the RRSIG one // if the rrset has no signature // feedback ... // elseif the rrset has at least one signature that can be verified // for each non-verifiable signature // feedback ... // rof // canonize the rrset // for each verifiable signature // verify the signature // feedback ... // rof // fi // rof // rof if(keyring == NULL) { return 0; } message_verify_rrsig_result_s result; time_t now; u32 total_wrong_signatures = 0; ya_result return_code; packet_unpack_reader_data pr; ya_result feedback_result = MESSAGE_VERIFY_RRSIG_FEEDBACK_CONTINUE; u32 type_record_fqdn_len; u8 type_record_fqdn[2 + 256]; u8 record_buffer[8192]; if(feedback == NULL) { feedback = message_verify_rrsig_result_default_handler; } result.data.any = NULL; result.result_type = 0; result.section = 0; result.ctype = 0; packet_reader_init_from_message(&pr, mesg); if(FAIL(return_code = packet_reader_skip_fqdn(&pr))) { return return_code; } if(FAIL(return_code = packet_reader_skip(&pr, 4))) { return return_code; } now = time(NULL); // for sections for(u8 section = 1; section < 3; section++) // addtitionals are not processed { result.section = section; result.ctype = TYPE_NONE; u32 section_start = pr.offset; ptr_set section_type_fqdn; message_verify_rrsig_init(§ion_type_fqdn); for(u16 count = message_get_section_count(mesg, section); count > 0; --count) { // count RRSIG / types if(FAIL(return_code = packet_reader_read_fqdn(&pr, &type_record_fqdn[2], sizeof(type_record_fqdn) - 2))) { message_verify_rrsig_clear(§ion_type_fqdn); return return_code; } type_record_fqdn_len = return_code + 2; u16 rtype; if(FAIL(return_code = packet_reader_read_u16(&pr, &rtype))) { message_verify_rrsig_clear(§ion_type_fqdn); return return_code; } if(FAIL(return_code = packet_reader_skip(&pr, 2 + 4))) { message_verify_rrsig_clear(§ion_type_fqdn); return return_code; } // FQDN + TYPE ( + CLASS ) = key of what can be signed u16 rdata_size; if(FAIL(return_code = packet_reader_read_u16(&pr, &rdata_size))) { message_verify_rrsig_clear(§ion_type_fqdn); return return_code; } rdata_size = ntohs(rdata_size); if(rtype == TYPE_RRSIG) { if(rdata_size < RRSIG_RDATA_HEADER_LEN) { message_verify_rrsig_clear(§ion_type_fqdn); return INCORRECT_RDATA; } u16 ctype; if(FAIL(return_code = packet_reader_read(&pr, &ctype, 2))) // exact { message_verify_rrsig_clear(§ion_type_fqdn); return return_code; } if(ctype == TYPE_RRSIG) { message_verify_rrsig_clear(§ion_type_fqdn); return RRSIG_UNSUPPORTED_COVERED_TYPE; } if(FAIL(return_code = packet_reader_skip(&pr, rdata_size - 2))) { message_verify_rrsig_clear(§ion_type_fqdn); return return_code; } SET_U16_AT_P(type_record_fqdn, ctype); message_verify_rrsig_set_flag(§ion_type_fqdn, type_record_fqdn, type_record_fqdn_len, TYPE_FQDN_HAS_SIGNATURES); } else { if(FAIL(return_code = packet_reader_skip(&pr, rdata_size))) { message_verify_rrsig_clear(§ion_type_fqdn); return return_code; } SET_U16_AT_P(type_record_fqdn, rtype); message_verify_rrsig_set_flag(§ion_type_fqdn, type_record_fqdn, type_record_fqdn_len, TYPE_FQDN_HAS_RECORDS); } } // count // at most 5956 records (beside the query) in a message // all the records of the section have been parsed (once) // signatures have been counted (verifiable & unknown) // for each type encountered ... message_verify_rrsig_type_summary_s type_info = {0, 0, 0, 0}; ptr_set_iterator section_types_fqdn_iter; ptr_set_iterator_init(§ion_type_fqdn, §ion_types_fqdn_iter); while(ptr_set_iterator_hasnext(§ion_types_fqdn_iter)) { ptr_node *types_fqdn_node = ptr_set_iterator_next_node(§ion_types_fqdn_iter); const u8 * type_fqdn = (u8*)types_fqdn_node->key; u16 ctype = GET_U16_AT_P(type_fqdn); type_fqdn += 2; u8 flags = (u8)(intptr)types_fqdn_node->value; // double cast just to explicitly show what is happening #if DEBUG log_debug6("message_verify_rrsig: %{dnsname} %{dnstype} (%x)", type_fqdn, &ctype, flags); #endif result.ctype = ctype; if( (flags & (TYPE_FQDN_HAS_RECORDS | TYPE_FQDN_HAS_SIGNATURES)) != (TYPE_FQDN_HAS_RECORDS | TYPE_FQDN_HAS_SIGNATURES) ) { // no signatures or no records if(flags & TYPE_FQDN_HAS_SIGNATURES) { // not signed } else { // signature without record ? } continue; } // all/some verifiable : report the verified ones // build the RRSET (canonised) // verify // => // rewind to the beginning of the section pr.offset = section_start; ptr_vector rrset = PTR_VECTOR_EMPTY; for(u16 count = message_get_section_count(mesg, section); count > 0; --count) { // count RRSIG / types if(ISOK(return_code = packet_reader_read_record(&pr, record_buffer, sizeof(record_buffer)))) { u8 *fqdn = record_buffer; if(dnsname_equals(fqdn, type_fqdn)) { struct type_class_ttl_rdlen *tctr = (struct type_class_ttl_rdlen*)&fqdn[dnsname_len(fqdn)]; if(tctr->qtype == ctype) // and fqdn is good ... { // append the record data to the array u8 *rdata = (u8*)tctr; rdata += 10; u8 *rdata_network_size_rdata; u16 rdata_size = ntohs(tctr->rdlen); MALLOC_OR_DIE(u8*, rdata_network_size_rdata, rdata_size + 2, MSGVRDTT_TAG); SET_U16_AT(rdata_network_size_rdata[0], tctr->rdlen); memcpy(&rdata_network_size_rdata[2], rdata, rdata_size); ptr_vector_append(&rrset, rdata_network_size_rdata); } } } else { ptr_vector_callback_and_clear(&rrset, message_verify_rrsig_free_rrset); ptr_vector_destroy(&rrset); message_verify_rrsig_clear(§ion_type_fqdn); return return_code; // impossible at this point } } // rrset contains all the RDATA for the fqdn/type ptr_vector_qsort(&rrset, message_verify_canonize_sort_rdata_compare); #if DEBUG for(int i = 0; i <= rrset.offset; i++) { u8* rdata = rrset.data[i]; u16 rdata_size = ntohs(GET_U16_AT(rdata[0])); rdata += 2; rdata_desc rdatadesc = {ctype, rdata_size, rdata}; log_debug6(" + %{typerdatadesc}", &rdatadesc); } #endif // we know the label & cie // we have the rdata on canonized order // now ... verify u32 saved_offset = pr.offset; //u8 digest_buffer[DIGEST_BUFFER_SIZE]; digest_s digest_ctx; // rewind to the beginning of the section pr.offset = section_start; for(u16 count = message_get_section_count(mesg, section); count > 0; --count) { // get RRSIG covering RRSET if(ISOK(return_code = packet_reader_read_record(&pr, record_buffer, sizeof(record_buffer)))) { u8 *fqdn = record_buffer; struct type_class_ttl_rdlen *tctr = (struct type_class_ttl_rdlen*)&fqdn[dnsname_len(fqdn)]; if( (tctr->qtype == TYPE_RRSIG) && dnsname_equals(type_fqdn, fqdn) ) { // append the record data to the array u16 rdata_size = ntohs(tctr->rdlen); u8 *rdata = (u8*)tctr; rdata += 10; if((GET_U16_AT(rdata[0]) == ctype) && (rdata_size > RRSIG_RDATA_HEADER_LEN)) // if type covered is the one we are processing ... { #if DEBUG rdata_desc rdatadesc = {TYPE_RRSIG, rdata_size, rdata}; log_debug6("with %{dnsname} %{typerdatadesc}", fqdn, &rdatadesc); #endif message_verify_rrsig_detail_s rrsig_header; memcpy(&rrsig_header, rdata, RRSIG_RDATA_HEADER_LEN); rrsig_header.result = 0; rrsig_header.section = section; rrsig_header.signer_name = &rdata[RRSIG_RDATA_HEADER_LEN]; rrsig_header.fqdn = fqdn; result.data.detail = &rrsig_header; result.result_type = MESSAGE_VERIFY_RRSIG_RESULT_TYPE_VERIFY; u32 inception = ntohl(rrsig_header.inception); u32 expiration = ntohl(rrsig_header.expiration); if((now >= inception) && (now <= expiration)) { u16 tag = ntohs(rrsig_header.tag); dnssec_key *key = dnskey_keyring_acquire(keyring, rrsig_header.algorithm, tag, rrsig_header.signer_name); if(key != NULL) { type_info.verifiable_count++; s32 digest_size = message_verify_rrsig_compute_digest(fqdn, ctype, tctr->qclass, rdata, rdata_size, &rrset, &digest_ctx); assert(digest_size > 0); u32 rrsig_signer_name_len = dnsname_len(rrsig_header.signer_name); u32 rrsig_header_len = RRSIG_RDATA_HEADER_LEN + rrsig_signer_name_len; u8 *signature = &rdata[rrsig_header_len]; u32 signature_len = rdata_size - rrsig_header_len; void *digest_ptr; digest_get_digest(&digest_ctx, &digest_ptr); if(key->vtbl->dnssec_key_verify_digest(key, digest_ptr, digest_size, signature, signature_len)) { // verified signature with origin/algorithm/tag type_info.verified_count++; rrsig_header.result |= MESSAGE_VERIFY_RRSIG_VERIFIED; } else { // corrupted/wrong signature with origin/algorithm/tag total_wrong_signatures++; type_info.wrong_count++; rrsig_header.result |= MESSAGE_VERIFY_RRSIG_WRONG; } digest_finalise(&digest_ctx); dnskey_release(key); } else { type_info.unverifiable_count++; rrsig_header.result |= MESSAGE_VERIFY_RRSIG_NOKEY; } } else { // wrong time frame type_info.wrong_count++; rrsig_header.result |= MESSAGE_VERIFY_RRSIG_TIMEFRAME; } if(feedback(mesg, keyring, &result, args) != MESSAGE_VERIFY_RRSIG_FEEDBACK_CONTINUE) { break; } } } } } // for each signature covering the type // break goes here pr.offset = saved_offset; ptr_vector_callback_and_clear(&rrset, message_verify_rrsig_free_rrset); ptr_vector_destroy(&rrset); } // for all types/fqdn // summary of the results for the type result.data.summary = &type_info; result.result_type = MESSAGE_VERIFY_RRSIG_RESULT_TYPE_SUMMARY; if((feedback_result = feedback(mesg, keyring, &result, args)) != MESSAGE_VERIFY_RRSIG_FEEDBACK_CONTINUE) { // ends the section loop //section = 4; // breaks the current loop message_verify_rrsig_clear(§ion_type_fqdn); break; } // clear the types of the section message_verify_rrsig_clear(§ion_type_fqdn); } // for all sections // done if((total_wrong_signatures == 0) && (feedback_result != MESSAGE_VERIFY_RRSIG_FEEDBACK_ERROR)) { return SUCCESS; } else { return RRSIG_VERIFICATION_FAILED; } } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/message_dnsupdate.c0000644000000000000000000000013214505005532023167 xustar000000000000000030 mtime=1695812442.507983119 30 atime=1695812445.797030225 30 ctime=1695812494.630729622 yadifa-2.6.5-11201/lib/dnscore/src/message_dnsupdate.c0000664000374500037450000002541014505005532023133 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * @{ * *----------------------------------------------------------------------------*/ //#include "dnscore/message_dnsupdate.h" #include "dnscore/dnscore-config.h" #include "dnscore/message.h" #include "dnscore/format.h" #include "dnscore/packet_writer.h" #include "dnscore/dns_resource_record.h" #include "dnscore/logger.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger /* * RFC 2136 : * CLASS TYPE RDATA Meaning --------------------------------------------------------- ANY ANY empty Delete all RRsets from a name ANY rrset empty Delete an RRset NONE rrset rr Delete an RR from an RRset zone rrset rr Add to an RRset * */ /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ /** @brief Function ... * * ... * * @param ... * * @retval OK * @retval NOK */ void message_make_dnsupdate_init(message_data *mesg, u16 id, const u8 *origin, u16 zclass, u32 max_size, packet_writer *uninitialised_pw) { assert(uninitialised_pw != NULL); /* 1. INITIALIZE PACKET */ #ifdef WORDS_BIGENDIAN SET_U64_AT(mesg->_buffer[0], 0x0000280000010000LL); SET_U32_AT(mesg->_buffer[8], 0); #else SET_U64_AT(mesg->_buffer[0], 0x0000010000280000LL); SET_U32_AT(mesg->_buffer[8], 0); #endif message_set_id(mesg, id); mesg->_ar_start = NULL; #if DNSCORE_HAS_TSIG_SUPPORT mesg->_tsig.tsig = NULL; #endif message_set_buffer_size(mesg, max_size); mesg->_rcode_ext = 0; if(max_size > message_get_buffer_size_max(mesg)) { message_set_edns0(mesg, TRUE); } message_set_canonised_fqdn(mesg, origin); message_set_query_type(mesg, TYPE_SOA); message_set_query_class(mesg, zclass); packet_writer_create(uninitialised_pw, message_get_buffer(mesg), message_get_buffer_size(mesg)); // valid use of message_get_buffer_size() /* 2. DO ZONE SECTION */ packet_writer_add_fqdn(uninitialised_pw, origin); /* type in Zone Section must be SOA */ packet_writer_add_u16(uninitialised_pw, TYPE_SOA); packet_writer_add_u16(uninitialised_pw, zclass); message_set_size(mesg, uninitialised_pw->packet_offset); message_set_status(mesg, FP_MESG_OK); } ya_result message_make_dnsupdate_delete_all_rrsets(message_data *mesg, packet_writer *pw, const u8 *fqdn) { ya_result return_code; s32 offset = pw->packet_offset; if(ISOK(return_code = packet_writer_add_fqdn(pw, fqdn))) { if(packet_writer_get_remaining_capacity(pw) >= 10) { packet_writer_add_u16(pw, TYPE_ANY); // type packet_writer_add_u16(pw, CLASS_ANY); // class packet_writer_add_u32(pw, 0); // ttl = 0 packet_writer_add_u16(pw, 0); // empty rdata message_add_update_count(mesg, 1); return SUCCESS; } return_code = BUFFER_WOULD_OVERFLOW; } pw->packet_offset = offset; return return_code; } ya_result message_make_dnsupdate_delete_rrset(message_data *mesg, packet_writer *pw, const u8 *fqdn, u16 rtype) { ya_result return_code; s32 offset = pw->packet_offset; if(ISOK(return_code = packet_writer_add_fqdn(pw, fqdn))) { if(packet_writer_get_remaining_capacity(pw) >= 10) { packet_writer_add_u16(pw, rtype); // type packet_writer_add_u16(pw, CLASS_ANY); // class packet_writer_add_u32(pw, 0); // ttl = 0 packet_writer_add_u16(pw, 0); // empty rdata message_add_update_count(mesg, 1); return SUCCESS; } return_code = BUFFER_WOULD_OVERFLOW; } pw->packet_offset = offset; return return_code; } ya_result message_make_dnsupdate_delete_record(message_data *mesg, packet_writer *pw, const u8 *fqdn, u16 rtype, u16 rdata_size, const u8 *rdata) { ya_result return_code; s32 offset = pw->packet_offset; if(ISOK(return_code = packet_writer_add_fqdn(pw, fqdn))) { if(packet_writer_get_remaining_capacity(pw) >= 10 + rdata_size) { packet_writer_add_u16(pw, rtype); // type packet_writer_add_u16(pw, CLASS_NONE); // class packet_writer_add_u32(pw, 0); // ttl = 0 //packet_writer_add_u16(pw, htons(rdata_size)); // empty rdata if(ISOK(return_code = packet_writer_add_rdata(pw, rtype, rdata, rdata_size))) // empty rdata { message_add_update_count(mesg, 1); return SUCCESS; } } return_code = BUFFER_WOULD_OVERFLOW; } pw->packet_offset = offset; return return_code; } ya_result message_make_dnsupdate_delete_dns_resource_record(message_data *mesg, packet_writer *pw, const dns_resource_record *rr) { ya_result ret; ret = message_make_dnsupdate_delete_record(mesg, pw, rr->name, rr->tctr.qtype, rr->rdata_size, rr->rdata); return ret; } ya_result message_make_dnsupdate_add_record(message_data *mesg, packet_writer *pw, const u8 *fqdn, u16 rtype, u16 rclass, s32 rttl, u16 rdata_size, const u8 *rdata) { #if DEBUG if(rttl > 86400 * 31) { log_warn("message_make_dnsupdate_add_record: sending an invalid TTL of %u (%x)", rttl, rttl); } #endif yassert(rttl >= 0); /* 3. DO PREREQUISITE SECTION */ /* 4. DO UPDATE SECTION */ ya_result return_code; s32 offset = pw->packet_offset; if(ISOK(return_code = packet_writer_add_fqdn(pw, fqdn))) { if(packet_writer_get_remaining_capacity(pw) >= 10 + rdata_size) { packet_writer_add_u16(pw, rtype); // type packet_writer_add_u16(pw, rclass); // class packet_writer_add_u32(pw, htonl(rttl)); // rttl //packet_writer_add_u16(pw, htons(rdata_size)); // empty rdata if(ISOK(return_code = packet_writer_add_rdata(pw, rtype, rdata, rdata_size))) // empty rdata { message_add_update_count(mesg, 1); return SUCCESS; } } return_code = BUFFER_WOULD_OVERFLOW; } pw->packet_offset = offset; return return_code; } ya_result message_make_dnsupdate_add_dns_resource_record(message_data *mesg, packet_writer *pw, const dns_resource_record *rr) { ya_result ret; ret = message_make_dnsupdate_add_record(mesg, pw, rr->name, rr->tctr.qtype, rr->tctr.qclass, ntohl(rr->tctr.ttl), rr->rdata_size, rr->rdata); return ret; } ya_result message_make_dnsupdate_add_dnskey(message_data *mesg, packet_writer *pw, dnssec_key *key, s32 ttl) { ya_result ret; u8 buffer[8192]; ret = key->vtbl->dnssec_key_writerdata(key, buffer, sizeof(buffer)); ret = message_make_dnsupdate_add_record(mesg, pw, dnskey_get_domain(key), TYPE_DNSKEY, CLASS_IN, ttl, ret, buffer); return ret; } ya_result message_make_dnsupdate_delete_dnskey(message_data *mesg, packet_writer *pw, dnssec_key *key) { ya_result ret; u8 buffer[8192]; ret = key->vtbl->dnssec_key_writerdata(key, buffer, sizeof(buffer)); ret = message_make_dnsupdate_delete_record(mesg, pw, dnskey_get_domain(key), TYPE_DNSKEY, ret, buffer); return ret; } ya_result message_make_dnsupdate_finalize(message_data *mesg, packet_writer *pw) { message_set_size(mesg, pw->packet_offset); // handle EDNS0 if(message_is_edns0(mesg)) { if(packet_writer_get_remaining_capacity(pw) >= 11) { /* #AR = 1 */ // faster: // message_set_additional_count(mesg, NETWORK_U16_ONE); mesg->_buffer[DNS_HEADER_LENGTH - 1] = 1; /* AR count was 0, now it is 1 */ /* append opt *//* */ u8 *buffer = message_get_buffer_limit(mesg); buffer[ 0] = 0; buffer[ 1] = 0; buffer[ 2] = 0x29; buffer[ 3] = message_get_buffer_size(mesg) >> 8; // valid use of message_get_buffer_size() buffer[ 4] = message_get_buffer_size(mesg); // valid use of message_get_buffer_size() buffer[ 5] = message_get_status(mesg) >> 4; buffer[ 6] = mesg->_rcode_ext >> 16; buffer[ 7] = mesg->_rcode_ext >> 8; buffer[ 8] = mesg->_rcode_ext; buffer[ 9] = 0; buffer[10] = 0; // no NSID support here message_increase_size(mesg, 11); } else { return MESSAGE_CONTENT_OVERFLOW; } } return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/mapped-file.c0000644000000000000000000000013114505005532021656 xustar000000000000000030 mtime=1695812442.463982489 30 atime=1695812445.795030196 29 ctime=1695812494.63272965 yadifa-2.6.5-11201/lib/dnscore/src/mapped-file.c0000664000374500037450000003573414505005532021635 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #if HAS_MREMAP #define _GNU_SOURCE 1 #endif #include #include #include #include #include #include #include #include "dnscore/mapped-file.h" #include "dnscore/fdtools.h" #include "dnscore/zalloc.h" #include "dnscore/mutex.h" //extern logger_handle *g_system_logger; //#define MODULE_MSG_HANDLE g_system_logger #define MAPPED_FILE_TAG 0x454c494650414d4d // MMAPFILE_TAG ssize_t g_page_size = 0; ssize_t g_page_mask = 0; static void mapped_file_update_system_consts() { #if __unix__ if(g_page_size == 0) { g_page_size = sysconf(_SC_PAGE_SIZE); if(g_page_size < 0) { g_page_size = 4096; } g_page_mask = g_page_size - 1; } #else g_page_size = 4096; g_page_mask = g_page_size - 1; #endif } struct mapped_file_t_ // matches the file_t_ signature, appends its own { const struct file_vtbl *vtbl; u8 *address; ssize_t size; ssize_t real_size; // for non file-backed maps off_t position; group_mutex_t mtx; int fd; int prot; int flags; }; typedef struct mapped_file_t_* mapped_file_t; static int mapped_file_resize_internal(mapped_file_t mf, size_t required_new_size) { u8 *address; if((ssize_t)required_new_size <= mf->real_size) { mf->size = required_new_size; return SUCCESS; } size_t new_real_size = MAX(mf->real_size * 2, 0x1000000); #if HAS_MREMAP if(mf->address != NULL) { address = mremap(mf->address, mf->real_size, new_real_size, MREMAP_MAYMOVE); if(address == (u8*)MAP_FAILED) { return ERRNO_ERROR; } } else { address = mmap(mf->address, new_real_size, mf->prot, mf->flags, mf->fd, 0); if(address == (u8*)MAP_FAILED) { return ERRNO_ERROR; } } #else address = mmap(mf->address, new_real_size, mf->prot, mf->flags, mf->fd, 0); if(address == (u8*)MAP_FAILED) { return ERRNO_ERROR; } if(mf->address != NULL) { memcpy(address, mf->address, MIN(mf->size, (ssize_t)required_new_size)); munmap(mf->address, mf->size); } #endif mf->address = address; mf->size = required_new_size; mf->real_size = new_real_size; return SUCCESS; } static ssize_t mapped_file_read(file_t f, void *buffer, ssize_t size) { mapped_file_t mf = (mapped_file_t)f; if((mf->prot & PROT_READ) == 0) { return INVALID_STATE_ERROR; } group_mutex_double_lock(&mf->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); ssize_t avail = mf->size - mf->position; if(avail < size) { size = avail; } memcpy(buffer, &mf->address[mf->position], size); group_mutex_exchange_locks(&mf->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); mf->position += size; group_mutex_exchange_locks(&mf->mtx, GROUP_MUTEX_WRITE, GROUP_MUTEX_READ); group_mutex_double_unlock(&mf->mtx, GROUP_MUTEX_READ, GROUP_MUTEX_WRITE); return size; } static ssize_t mapped_file_write(file_t f, const void *buffer, ssize_t size) { mapped_file_t mf = (mapped_file_t)f; if((mf->prot & PROT_WRITE) == 0) { return INVALID_STATE_ERROR; } group_mutex_lock(&mf->mtx, GROUP_MUTEX_WRITE); ssize_t avail = mf->size - mf->position; if(avail < size) { // grow the file if(mf->fd >= 0) { ftruncate(mf->fd, mf->position + size); } ssize_t ret = mapped_file_resize_internal(mf, mf->position + size); if(FAIL(ret)) { group_mutex_unlock(&mf->mtx, GROUP_MUTEX_WRITE); return ret; } } memcpy(&mf->address[mf->position], buffer, size); mf->position += size; group_mutex_unlock(&mf->mtx, GROUP_MUTEX_WRITE); return size; } static ssize_t mapped_file_seek(file_t f, ssize_t position, int whence) { mapped_file_t mf = (mapped_file_t)f; if(mf->prot == PROT_NONE) { return INVALID_STATE_ERROR; } group_mutex_lock(&mf->mtx, GROUP_MUTEX_WRITE); switch(whence) { case SEEK_SET: { mf->position = position; group_mutex_unlock(&mf->mtx, GROUP_MUTEX_WRITE); return position; } case SEEK_CUR: { if(mf->position + position >= 0) { position = (mf->position += position); group_mutex_unlock(&mf->mtx, GROUP_MUTEX_WRITE); return position; } else { mf->position = 0; group_mutex_unlock(&mf->mtx, GROUP_MUTEX_WRITE); return 0; } } case SEEK_END: { if(mf->size + position >= 0) { position = mf->position = mf->size + position; group_mutex_unlock(&mf->mtx, GROUP_MUTEX_WRITE); return position; } else { mf->position = 0; group_mutex_unlock(&mf->mtx, GROUP_MUTEX_WRITE); return 0; } } default: { group_mutex_unlock(&mf->mtx, GROUP_MUTEX_WRITE); return ERROR; } } } static ssize_t mapped_file_tell(file_t f) { mapped_file_t mf = (mapped_file_t)f; if(mf->prot == PROT_NONE) { return INVALID_STATE_ERROR; } ssize_t ret; group_mutex_lock(&mf->mtx, GROUP_MUTEX_READ); ret = mf->position; group_mutex_unlock(&mf->mtx, GROUP_MUTEX_READ); return ret; } static ya_result mapped_file_flush(file_t f) { mapped_file_t mf = (mapped_file_t)f; if(mf->prot == PROT_NONE) { return INVALID_STATE_ERROR; } group_mutex_lock(&mf->mtx, GROUP_MUTEX_READ); int ret = msync(mf->address, mf->size, MS_SYNC); group_mutex_unlock(&mf->mtx, GROUP_MUTEX_READ); if(FAIL(ret)) { ret = ERRNO_ERROR; } return ret; } static int mapped_file_close(file_t f) { mapped_file_t mf = (mapped_file_t)f; if(mf->prot == PROT_NONE) { return INVALID_STATE_ERROR; } group_mutex_lock(&mf->mtx, GROUP_MUTEX_WRITE); if(mf->address != NULL) { munmap(mf->address, mf->real_size); mf->address = NULL; mf->size = 0; } group_mutex_unlock(&mf->mtx, GROUP_MUTEX_WRITE); if(mf->fd >= 0) { close_ex(mf->fd); mf->fd = -2; } mf->vtbl = NULL; ZFREE_OBJECT(mf); return SUCCESS; } static ssize_t mapped_file_size(file_t f) { mapped_file_t mf = (mapped_file_t)f; if(mf->prot == PROT_NONE) { return INVALID_STATE_ERROR; } ssize_t ret; group_mutex_lock(&mf->mtx, GROUP_MUTEX_READ); ret = mf->size; group_mutex_unlock(&mf->mtx, GROUP_MUTEX_READ); return ret; } static int mapped_file_resize(file_t f, ssize_t size) { mapped_file_t mf = (mapped_file_t)f; if(mf->prot == PROT_NONE) { return INVALID_STATE_ERROR; } ya_result ret = SUCCESS; group_mutex_lock(&mf->mtx, GROUP_MUTEX_WRITE); if(mf->size != size) { // grow the file if(mf->fd >= 0) { if(ISOK(ret = ftruncate(mf->fd, size))) { ret = mapped_file_resize_internal(mf, size); } } else { ret = mapped_file_resize_internal(mf, size); } } group_mutex_unlock(&mf->mtx, GROUP_MUTEX_WRITE); return ret; } static const struct file_vtbl mapped_file_vtbl = { mapped_file_read, mapped_file_write, mapped_file_seek, mapped_file_tell, mapped_file_flush, mapped_file_close, mapped_file_size, mapped_file_resize }; /* file_t mapped_file_open_ex(const char *filename, int flags, mode_t mode, ya_result *ret) */ ya_result mapped_file_open_ex(file_t *fp, const char *filename, int flags) { mapped_file_update_system_consts(); if(fp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } int fd = open_ex(filename, flags); if(FAIL(fd)) { return ERRNO_ERROR; } struct stat st; if(fstat(fd, &st) < 0) { close_ex(fd); return ERRNO_ERROR; } int prot; if((flags & O_RDWR) == O_RDWR) { prot = PROT_READ|PROT_WRITE; } else if((flags & O_RDONLY) == O_RDONLY) { prot = PROT_READ; } else if((flags & O_WRONLY) == O_WRONLY) { prot = PROT_WRITE; } else { prot = PROT_NONE; } int mmap_flags = MAP_SHARED; u8 *address = NULL; ssize_t real_size = 0; if(st.st_size > 0) { real_size = (st.st_size + 0xffffffLL) & ~0xffffffLL; address = mmap(NULL, real_size, prot, mmap_flags, fd, 0); if(address == (u8*)MAP_FAILED) { close_ex(fd); return ERRNO_ERROR; } } mapped_file_t mf; ZALLOC_OBJECT_OR_DIE(mf,struct mapped_file_t_, MAPPED_FILE_TAG); mf->vtbl = &mapped_file_vtbl; mf->address = address; mf->size = st.st_size; mf->real_size = real_size; mf->position = 0; group_mutex_init(&mf->mtx); mf->fd = fd; mf->prot = prot; mf->flags = mmap_flags; *fp = (file_t)mf; return SUCCESS; } ya_result mapped_file_create_ex(file_t *fp, const char *filename, int flags, mode_t mode) { mapped_file_update_system_consts(); if(fp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } int fd = open_create_ex(filename, flags, mode); if(FAIL(fd)) { return ERRNO_ERROR; } struct stat st; if(fstat(fd, &st) < 0) { close_ex(fd); return ERRNO_ERROR; } int prot; if((flags & O_RDWR) == O_RDWR) { prot = PROT_READ|PROT_WRITE; } else if((flags & O_RDONLY) == O_RDONLY) { prot = PROT_READ; } else if((flags & O_WRONLY) == O_WRONLY) { prot = PROT_WRITE; } else { prot = PROT_NONE; } int mmap_flags = MAP_SHARED; u8 *address = NULL; size_t real_size = 0; if(st.st_size > 0) { real_size = (st.st_size + 0xffffffLL) & ~0xffffffLL; address = mmap(NULL, real_size, prot, mmap_flags, fd, 0); if(address == (u8*)MAP_FAILED) { close_ex(fd); return ERRNO_ERROR; } } mapped_file_t mf; ZALLOC_OBJECT_OR_DIE(mf,struct mapped_file_t_, MAPPED_FILE_TAG); mf->vtbl = &mapped_file_vtbl; mf->address = address; mf->size = st.st_size; mf->real_size = real_size; mf->position = 0; group_mutex_init(&mf->mtx); mf->fd = fd; mf->prot = prot; mf->flags = mmap_flags; *fp = (file_t)mf; return SUCCESS; } ya_result mapped_file_create_volatile(file_t *fp, const char *filename, size_t base_size) { (void)filename; mapped_file_update_system_consts(); if(fp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } int fd = -1; int prot = PROT_READ|PROT_WRITE; int mmap_flags = MAP_ANONYMOUS|MAP_PRIVATE; u8 *address = NULL; size_t real_size = 0; if(base_size > 0) { real_size = (base_size + 0xffffffLL) & ~0xffffffLL; address = mmap(NULL, real_size, prot, mmap_flags, fd, 0); if(address == (u8*)MAP_FAILED) { close_ex(fd); return ERRNO_ERROR; } } mapped_file_t mf; ZALLOC_OBJECT_OR_DIE(mf,struct mapped_file_t_, MAPPED_FILE_TAG); mf->vtbl = &mapped_file_vtbl; mf->address = address; mf->size = 0; mf->real_size = real_size; mf->position = 0; group_mutex_init(&mf->mtx); mf->fd = fd; mf->prot = prot; mf->flags = mmap_flags; *fp = (file_t)mf; return SUCCESS; } ya_result mapped_file_get_buffer(file_t f, void **address, ssize_t *size) { mapped_file_t mf = (mapped_file_t)f; if(f->vtbl == &mapped_file_vtbl) { if(address != NULL) { *address = mf->address; } if(size != NULL) { *size = mf->size; } return SUCCESS; } else { return INVALID_ARGUMENT_ERROR; } } ya_result mapped_file_get_buffer_const(file_t f, const void **address, ssize_t *size) { mapped_file_t mf = (mapped_file_t)f; if(f->vtbl == &mapped_file_vtbl) { if(address != NULL) { *address = mf->address; } if(size != NULL) { *size = mf->size; } return SUCCESS; } else { return INVALID_ARGUMENT_ERROR; } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/mt_output_stream.c0000644000000000000000000000013214505005532023107 xustar000000000000000030 mtime=1695812442.370981157 30 atime=1695812445.791030139 30 ctime=1695812494.634729679 yadifa-2.6.5-11201/lib/dnscore/src/mt_output_stream.c0000664000374500037450000002056014505005532023054 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/mt_output_stream.h" #include "dnscore/mutex.h" #include "dnscore/bytearray_output_stream.h" #include "dnscore/ptr_vector.h" #include "dnscore/ptr_set_debug.h" #define MT_OUTPUT_STREAM_TAG 0x534F544D /* MTOS */ #define MTOSSTRM_TAG 0x4d525453534f544d #define MT_OUTPUT_STREAM_BUFFER_INITIAL_SIZE 128U typedef struct mt_output_stream_data mt_output_stream_data; struct mt_output_stream_data { output_stream filtered; mutex_t mutex; ptr_set_debug writers; /* mutex_t delayed_mutex; ptr_vector delayed_writes; */ }; static ya_result mt_write(output_stream *stream, const u8 *buffer, u32 len) { ya_result ret; mt_output_stream_data *data = (mt_output_stream_data *) stream->data; mutex_lock(&data->mutex); ptr_node_debug *writer_node = ptr_set_debug_insert(&data->writers, (void*)pthread_self()); output_stream* osp; if(writer_node->value != NULL) { osp = (output_stream*)writer_node->value; } else { MALLOC_OBJECT_OR_DIE(osp, output_stream, MTOSSTRM_TAG); bytearray_output_stream_init_ex(osp, NULL, MT_OUTPUT_STREAM_BUFFER_INITIAL_SIZE, BYTEARRAY_DYNAMIC); writer_node->value = osp; } mutex_unlock(&data->mutex); ret = len; ya_result err; ya_result written = 0; while(len > 0) { u8 *lfp = (u8*)memchr(buffer, '\n', len); if(lfp != NULL) { mutex_lock(&data->mutex); if(bytearray_output_stream_size(osp) > 0) { if(FAIL(err = output_stream_write(&data->filtered, bytearray_output_stream_buffer(osp), bytearray_output_stream_size(osp)))) { mutex_unlock(&data->mutex); if(written == 0) { return err; } else { return written; } } bytearray_output_stream_reset(osp); } ++lfp; size_t n = lfp - buffer; if(ISOK(err = output_stream_write(&data->filtered, buffer, n))) { written += err; } else { mutex_unlock(&data->mutex); if(written == 0) { return err; } else { return written; } } mutex_unlock(&data->mutex); buffer = lfp; len -= n; } else { mutex_lock(&data->mutex); err = output_stream_write(osp, buffer, len); mutex_unlock(&data->mutex); if(ISOK(err)) { return ret; } else { if(written == 0) { return err; } else { return written; } } } } return ret; } static ya_result mt_flush(output_stream *stream) { mt_output_stream_data *data = (mt_output_stream_data *) stream->data; ya_result ret = SUCCESS; mutex_lock(&data->mutex); FOREACH_PTR_SET_DEBUG(output_stream*,osp, &data->writers) { if(bytearray_output_stream_size(osp) > 0) { ret = output_stream_write(&data->filtered, bytearray_output_stream_buffer(osp), bytearray_output_stream_size(osp)); bytearray_output_stream_reset(osp); } } output_stream_flush(&data->filtered); mutex_unlock(&data->mutex); return ret; } static void mt_close(output_stream *stream) { mt_output_stream_data *data = (mt_output_stream_data *) stream->data; mutex_lock(&data->mutex); FOREACH_PTR_SET_DEBUG(output_stream*,osp, &data->writers) { if(bytearray_output_stream_size(osp) > 0) { output_stream_write(&data->filtered, bytearray_output_stream_buffer(osp), bytearray_output_stream_size(osp)); bytearray_output_stream_reset(osp); } output_stream_close(osp); free(osp); } ptr_set_debug_destroy(&data->writers); output_stream_set_void(stream); output_stream_close(&data->filtered); mutex_unlock(&data->mutex); mutex_destroy(&data->mutex); free(data); } static const output_stream_vtbl mt_output_stream_vtbl = { mt_write, mt_flush, mt_close, "mt_output_stream", }; ya_result mt_output_stream_init(output_stream *stream, output_stream *filtered) { mt_output_stream_data *data; if(filtered->vtbl == NULL) { return INVALID_STATE_ERROR; } MALLOC_OBJECT_OR_DIE(data, mt_output_stream_data, MT_OUTPUT_STREAM_TAG); data->filtered.data = filtered->data; data->filtered.vtbl = filtered->vtbl; data->writers.compare = ptr_set_debug_ptr_node_compare; data->writers.root = NULL; filtered->data = NULL; /* Clean the filtered BEFORE setting up the stream */ filtered->vtbl = NULL; mutex_init(&data->mutex); stream->data = data; stream->vtbl = &mt_output_stream_vtbl; return SUCCESS; } output_stream * mt_output_stream_get_filtered(output_stream *bos) { output_stream *ret; mt_output_stream_data *data = (mt_output_stream_data *) bos->data; mutex_lock(&data->mutex); ret = &data->filtered; mutex_unlock(&data->mutex); return ret; } void mt_output_stream_detach_filtered(output_stream *bos, output_stream *detached_filtered) { mt_output_stream_data *data = (mt_output_stream_data *) bos->data; mutex_lock(&data->mutex); *detached_filtered = data->filtered; output_stream_set_sink(&data->filtered); mutex_unlock(&data->mutex); } void mt_output_stream_set_filtered(output_stream *bos, output_stream *new_os, bool also_close) { output_stream *os; mt_output_stream_data *data = (mt_output_stream_data *) bos->data; mutex_lock(&data->mutex); os = &data->filtered; output_stream_flush(os); if(also_close) { output_stream_close(os); } data->filtered = *new_os; output_stream_set_sink(new_os); mutex_unlock(&data->mutex); } bool is_mt_output_stream(const output_stream* bos) { return (bos != NULL) && (bos->vtbl == &mt_output_stream_vtbl); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/mutex.c0000644000000000000000000000013214505005532020636 xustar000000000000000030 mtime=1695812442.407981687 30 atime=1695812445.792030153 30 ctime=1695812494.636729708 yadifa-2.6.5-11201/lib/dnscore/src/mutex.c0000664000374500037450000015114014505005532020602 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading mutexes, ... * @ingroup dnscore * @brief * * @{ * *----------------------------------------------------------------------------*/ // CentOS 5.9 requires this to have PTHREAD_MUTEX_RECURSIVE #define _GNU_SOURCE 1 #include "dnscore/dnscore-config.h" #include "dnscore/thread.h" #include #include #include "dnscore/ptr_set.h" #include "dnscore/timems.h" #include "dnscore/bytezarray_output_stream.h" #include "dnscore/format.h" #include "dnscore/thread-tag.h" #include "dnscore/process.h" #if __OpenBSD__0 #error "OpenBSD doesn't handle PTHREAD_PROCESS_SHARED" #endif #include "dnscore/logger.h" #include "dnscore/mutex.h" // export TSAN_OPTIONS=detect_deadlocks=1:second_deadlock_stack=1 // -sanitize=thread #define MTXCOBJ_TAG 0x4a424f4358544d #define MTXCPT_TAG 0x54504358544d #define MTXCTHRD_TAG 0x445248544358544d #define MTXCMON_TAG 0x4e4f4d5358544d #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT static void mutex_debug_logger_handle_msg(const void* handle, u32 level, const char* fmt, ...) { (void)handle; (void)level; format("%llT | %i | %p | ", timeus(), getpid(), thread_self()); output_stream baos; bytezarray_output_stream_context baos_context; va_list args; va_start(args, fmt); u8 text_buffer[512]; bytezarray_output_stream_init_ex_static(&baos, text_buffer, sizeof(text_buffer), 0, &baos_context); if(FAIL(vosformat(&baos, fmt, args))) { bytezarray_output_stream_reset(&baos); osprint(&baos, "*** ERROR : MESSAGE FORMATTING FAILED ***"); } //output_stream_write_u8(&baos, 0); output_stream_write(termout, bytezarray_output_stream_buffer(&baos), bytezarray_output_stream_buffer_offset(&baos)); output_stream_write_u8(termout, (u8)'\n'); } #endif void mutex_debug_stacktrace_log(void* handle, u32 level, stacktrace trace) { (void)handle; (void)level; debug_stacktrace_print(termout, trace); output_stream_write_u8(termout, (u8)'\n'); } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT static void mutex_debug_log_stacktrace(void* handle, u32 level, const char *prefix) { println(prefix); stacktrace trace = debug_stacktrace_get(); mutex_debug_stacktrace_log(handle, level, trace); } #define logger_handle_msg mutex_debug_logger_handle_msg #define debug_stacktrace_log mutex_debug_stacktrace_log #define debug_log_stacktrace mutex_debug_log_stacktrace #define logger_flush flushout #define MODULE_MSG_HANDLE NULL #define LOG_TEXT_PREFIX "" #define MSG_DEBUG7 0 #define MSG_DEBUG6 0 #define MSG_DEBUG5 0 #define MSG_DEBUG4 0 #define MSG_DEBUG3 0 #define MSG_DEBUG2 0 #define MSG_DEBUG1 0 #define MSG_DEBUG 0 #define MSG_WARNING 0 #define MSG_ERR 0 #define log_debug7(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug6(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug5(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug4(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug3(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug2(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug1(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_debug(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_notice(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_info(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_warn(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_err(...) logger_handle_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug7(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug6(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug5(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug4(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug3(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug2(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug1(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_debug(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_notice(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_info(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_warn(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #define log_try_err(...) logger_handle_try_msg(0,0,LOG_TEXT_PREFIX __VA_ARGS__) #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT volatile bool mutex_ultraverbose = FALSE; //volatile bool mutex_ultraverbose = TRUE; #if MUTEX_CONTENTION_MONITOR struct mutex_contention_point_s { stacktrace st; // stack trace to that point s64 lock_wait; // time spent waiting for the lock (but successfully acquired) s64 lock_loops; // loops made before acquiring the lock s64 owner_time; // time spent owning that mutex on that stack trace s64 use_count; s64 lock_fail; // try-locks that failed }; typedef struct mutex_contention_point_s mutex_contention_point_t; struct mutex_contention_object_s { void *mutex; ptr_set threads; // set of mutex_contention_monitor bool recursive; }; typedef struct mutex_contention_object_s mutex_contention_object_t; typedef ptr_set mutex_contention_thread_t; struct mutex_contention_monitor_s { thread_t owning_thread; mutex_contention_point_t *contention_point; // mutex_contention_object_t *mutex_object; mutex_contention_thread_t *mutex_thread; const char *type_name; s64 lock_begin_timestamp; s64 lock_wait_loops; s64 lock_end_timestamp; // 0 until the mutex is acquired s32 multi_lock_count; pid_t pid; bool used_by_condition; // true means not really locked }; typedef struct mutex_contention_monitor_s mutex_contention_monitor_t; void mutex_contention_monitor_lock_count_inc(mutex_contention_monitor_t *mcm) { //log_info("mutex_contention_monitor_lock_count_inc(%p) (%i -> %i)", mcm, mcm->multi_lock_count, mcm->multi_lock_count + 1); ++mcm->multi_lock_count; } bool mutex_contention_monitor_lock_count_dec(mutex_contention_monitor_t *mcm) { //log_info("mutex_contention_monitor_lock_count_dec(%p) (%i -> %i)", mcm, mcm->multi_lock_count, mcm->multi_lock_count - 1); assert(mcm->multi_lock_count > 0); return (--mcm->multi_lock_count == 0); } static pthread_mutex_t mutex_contention_mtx = PTHREAD_MUTEX_INITIALIZER; static ptr_set mutex_contention_mutex_to_threads_set = PTR_SET_PTR_EMPTY; // mutex -> mutex_contention_object_t static ptr_set mutex_contention_stacktrace_to_point_set = PTR_SET_EMPTY; // stacktrace -> mutex_contention_point_t static ptr_set mutex_contention_thread_to_monitor_set = PTR_SET_EMPTY; // thread -> mutex_contention_monitor_t static const char *mutex_type_name = "mutex_lock"; static const char *group_mutex_type_name = "group_mutex_lock"; static const char *shared_group_mutex_type_name = "shared_group_mutex_lock"; void mutex_contention_object_create(void *mutex_ptr, bool recursive) { mutex_contention_object_t *mcu; pthread_mutex_lock(&mutex_contention_mtx); ptr_node *mutex_node = ptr_set_insert(&mutex_contention_mutex_to_threads_set, mutex_ptr); if(mutex_node->value == NULL) { MALLOC_OBJECT_OR_DIE(mcu, mutex_contention_object_t, MTXCOBJ_TAG); mcu->mutex = mutex_ptr; ptr_set_init(&mcu->threads); mcu->threads.compare = ptr_set_ptr_node_compare; mcu->recursive = recursive; } else { logger_flush(); abort(); // already exists } pthread_mutex_unlock(&mutex_contention_mtx); } void mutex_contention_object_destroy(void *mutex_ptr) { pthread_mutex_lock(&mutex_contention_mtx); ptr_node *mutex_node = ptr_set_find(&mutex_contention_mutex_to_threads_set, mutex_ptr); if(mutex_node != NULL) { if(mutex_node->value != NULL) { mutex_contention_object_t *mcu = (mutex_contention_object_t*)mutex_node->value; s64 now = timeus(); if(!ptr_set_isempty(&mcu->threads)) { ptr_set_iterator iter; ptr_set_iterator_init(&mcu->threads, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); mutex_contention_monitor_t* other_mcm = (mutex_contention_monitor_t*)node->value; if(other_mcm->lock_end_timestamp == 0) { s64 other_wait_time = (now - other_mcm->lock_begin_timestamp); log_err("mutex-monitor: unsafe destruction: thread %p has also been waiting for mutex @%p for %llius (looped %lli)", other_mcm->owning_thread, other_mcm->mutex_object->mutex, other_wait_time, other_mcm->lock_wait_loops); mutex_debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_WARNING, other_mcm->contention_point->st); } else { s64 other_wait_time = (now - other_mcm->lock_end_timestamp); log_err("mutex-monitor: unsafe destruction: thread %p has been owning the mutex @%p for %llius (a)", other_mcm->owning_thread, other_mcm->mutex_object->mutex, other_wait_time, other_mcm->lock_wait_loops); mutex_debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_WARNING, other_mcm->contention_point->st); } } logger_flush(); abort(); } } ptr_set_delete(&mutex_contention_mutex_to_threads_set, mutex_ptr); } else { abort(); // already exists } pthread_mutex_unlock(&mutex_contention_mtx); } mutex_contention_monitor_t * mutex_contention_lock_begin(thread_t thread, void *mutex_ptr, stacktrace st, const char *type_name) { mutex_contention_object_t *mco; mutex_contention_point_t *mcp; mutex_contention_thread_t *mct; mutex_contention_monitor_t *mcm; pthread_mutex_lock(&mutex_contention_mtx); // insert/find mutex contention users // mutex->currently locking threads ptr_node *mutex_node = ptr_set_insert(&mutex_contention_mutex_to_threads_set, mutex_ptr); if(mutex_node->value != NULL) { mco = (mutex_contention_object_t*)mutex_node->value; } else { log_info("mutex monitor: %p has not been passed to mutex_contention_object_create(void*,bool): static?", mutex_ptr); MALLOC_OBJECT_OR_DIE(mco, mutex_contention_object_t, MTXCOBJ_TAG); mco->mutex = mutex_ptr; ptr_set_init(&mco->threads); mco->threads.compare = ptr_set_ptr_node_compare; mco->recursive = FALSE; mutex_node->value = mco; } // insert/find mutex contention points // stacktrace->lock statistics ptr_node *contention_node = ptr_set_insert(&mutex_contention_stacktrace_to_point_set, st); if(contention_node->value != NULL) { mcp = (mutex_contention_point_t*)contention_node->value; } else { MALLOC_OBJECT_OR_DIE(mcp, mutex_contention_point_t, MTXCPT_TAG); mcp->st = st; mcp->lock_wait = 0; mcp->lock_loops = 0; mcp->owner_time = 0; mcp->use_count = 0; mcp->lock_fail = 0; contention_node->value = mcp; } ++mcp->use_count; // insert/find threads using mutexes // thread->monitored mutexes set ptr_node *thread_node = ptr_set_insert(&mutex_contention_thread_to_monitor_set, (void*)thread); if(thread_node->value != NULL) { mct = (mutex_contention_thread_t*)thread_node->value; } else { MALLOC_OBJECT_OR_DIE(mct, mutex_contention_thread_t, MTXCTHRD_TAG); ptr_set_init(mct); mct->compare = ptr_set_ptr_node_compare; thread_node->value = mct; } // insert/find mutexes in the thread monitored set ptr_node *monitor_node = ptr_set_insert(mct, st); if(monitor_node->value != NULL) { mcm = (mutex_contention_monitor_t*)monitor_node->value; // double lock ... ? mutex_contention_monitor_lock_count_inc(mcm); } else { MALLOC_OBJECT_OR_DIE(mcm, mutex_contention_monitor_t, MTXCMON_TAG); mcm->owning_thread = thread; mcm->contention_point = mcp; mcm->mutex_object = mco; mcm->mutex_thread = mct; mcm->type_name = type_name; mcm->lock_begin_timestamp = timeus(); mcm->lock_end_timestamp = 0; mcm->lock_wait_loops = 0; mcm->multi_lock_count = 1; mcm->pid = getpid_ex(); monitor_node->value = mcm; mcm->used_by_condition = FALSE; } ptr_node *user_thread_node = ptr_set_insert(&mco->threads, (void*)thread); if(user_thread_node->value == NULL) { user_thread_node->value = mcm; } else { mutex_contention_monitor_t *old_mcm = (mutex_contention_monitor_t*)user_thread_node->value; log_err("lock monitor: mutex %p already locked by %p (old@%p now@%p)", mutex_ptr, old_mcm->lock_begin_timestamp, old_mcm, mcm); log_err("lock monitor: locked by"); mutex_debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_ERR, old_mcm->contention_point->st); log_err("lock monitor: failed by"); mutex_debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_ERR, mcm->contention_point->st); debug_stacktrace_print(termout, old_mcm->contention_point->st); debug_stacktrace_print(termout, mcm->contention_point->st); logger_flush(); flushout(); assert(user_thread_node->value == mcm); } pthread_mutex_unlock(&mutex_contention_mtx); return mcm; } void mutex_contention_lock_wait(mutex_contention_monitor_t *mcm) { // insert/find mutex_contention_users pthread_mutex_lock(&mutex_contention_mtx); ++mcm->lock_end_timestamp; if(mutex_contention_monitor_lock_count_dec(mcm)) { mcm->contention_point->owner_time += timeus() - mcm->lock_end_timestamp; mcm->used_by_condition = TRUE; } pthread_mutex_unlock(&mutex_contention_mtx); } void mutex_contention_lock_wait_with_mutex(thread_t thread, void *mutex_ptr) { mutex_contention_object_t *mco; mutex_contention_monitor_t *mcm; pthread_mutex_lock(&mutex_contention_mtx); ptr_node *mutex_node = ptr_set_find(&mutex_contention_mutex_to_threads_set, mutex_ptr); if(mutex_node == NULL) { log_err("mutex monitor: can't wait on %p as it has not been passed to mutex_contention_object_create(void*,bool)"); abort(); } mco = (mutex_contention_object_t*)mutex_node->value; ptr_node *monitor_node = ptr_set_find(&mco->threads, (void*)thread); if(monitor_node == NULL) { log_err("mutex monitor: can't wait on %p as it's not used by thread %p", thread); abort(); } mcm = (mutex_contention_monitor_t*)monitor_node->value; if(mutex_contention_monitor_lock_count_dec(mcm)) { mcm->contention_point->owner_time += timeus() - mcm->lock_end_timestamp; } mcm->used_by_condition = TRUE; pthread_mutex_unlock(&mutex_contention_mtx); } void mutex_contention_lock_resume(mutex_contention_monitor_t *mcm) { // insert/find mutex_contention_users pthread_mutex_lock(&mutex_contention_mtx); ++mcm->lock_end_timestamp; mutex_contention_monitor_lock_count_inc(mcm); mcm->used_by_condition = FALSE; pthread_mutex_unlock(&mutex_contention_mtx); } void mutex_contention_lock_resume_with_mutex(thread_t thread, void *mutex_ptr) { mutex_contention_object_t *mco; mutex_contention_monitor_t *mcm; pthread_mutex_lock(&mutex_contention_mtx); ptr_node *mutex_node = ptr_set_find(&mutex_contention_mutex_to_threads_set, mutex_ptr); if(mutex_node == NULL) { log_err("mutex monitor: can't wait on %p as it has not been passed to mutex_contention_object_create(void*,bool)"); abort(); } mco = (mutex_contention_object_t*)mutex_node->value; ptr_node *monitor_node = ptr_set_find(&mco->threads, (void*)thread); if(monitor_node == NULL) { log_err("mutex monitor: can't wait on %p as it's not used by thread %p", thread); abort(); } mcm = (mutex_contention_monitor_t*)monitor_node->value; assert(mcm->used_by_condition); mutex_contention_monitor_lock_count_inc(mcm); mcm->used_by_condition = FALSE; pthread_mutex_unlock(&mutex_contention_mtx); } void mutex_contention_lock_end(mutex_contention_monitor_t *mcm) { pthread_mutex_lock(&mutex_contention_mtx); mcm->lock_end_timestamp = timeus(); s64 wait_time = mcm->lock_end_timestamp - mcm->lock_begin_timestamp; mcm->contention_point->lock_wait += wait_time; mcm->contention_point->lock_loops += mcm->lock_wait_loops; pthread_mutex_unlock(&mutex_contention_mtx); } void mutex_contention_lock_fail(mutex_contention_monitor_t *mcm) { pthread_mutex_lock(&mutex_contention_mtx); mcm->lock_end_timestamp = timeus(); s64 wait_time = mcm->lock_end_timestamp - mcm->lock_begin_timestamp; mcm->contention_point->lock_wait += wait_time; mcm->contention_point->lock_loops += mcm->lock_wait_loops; ++mcm->contention_point->lock_fail; pthread_mutex_unlock(&mutex_contention_mtx); } void mutex_contention_unlock(thread_t thread, void *mutex_ptr) { mutex_contention_object_t *mco; mutex_contention_monitor_t *mcm; pthread_mutex_lock(&mutex_contention_mtx); ptr_node *mutex_node = ptr_set_find(&mutex_contention_mutex_to_threads_set, mutex_ptr); if(mutex_node == NULL) { log_err("mutex monitor: can't unlock %p as it has not been passed to mutex_contention_object_create(void*,bool)"); abort(); } mco = (mutex_contention_object_t*)mutex_node->value; ptr_node *monitor_node = ptr_set_find(&mco->threads, (void*)thread); if(monitor_node == NULL) { log_err("mutex monitor: can't unlock %p as it's not used by thread %p", thread); abort(); } mcm = (mutex_contention_monitor_t*)monitor_node->value; if(mutex_contention_monitor_lock_count_dec(mcm)) { mcm->contention_point->owner_time += timeus() - mcm->lock_end_timestamp; ptr_set_delete(&mco->threads, (void*)mcm->owning_thread); ptr_set_delete(mcm->mutex_thread, mcm->contention_point->st); free(mcm); } else { log_info("mutex monitor: mcm@%p multi_lock_count = %i", mcm, mcm->multi_lock_count); logger_flush(); flushout(); } pthread_mutex_unlock(&mutex_contention_mtx); } void mutex_contention_unlock_with_monitor(mutex_contention_monitor_t *mcm) { pthread_mutex_lock(&mutex_contention_mtx); thread_t tid = thread_self(); if(mcm->owning_thread != tid) { log_err("mutex-monitor: locked with %p, unlocked with %p", mcm->owning_thread, tid); } if(mutex_contention_monitor_lock_count_dec(mcm)) { mcm->contention_point->owner_time += timeus() - mcm->lock_end_timestamp; ptr_set_delete(&mcm->mutex_object->threads, (void*)mcm->owning_thread); ptr_set_delete(mcm->mutex_thread, mcm->contention_point->st); free(mcm); } pthread_mutex_unlock(&mutex_contention_mtx); } static smp_int mutex_contention_monitor_thread_should_stop = SMP_INT_INITIALIZER_AT(0); static pthread_mutex_t mutex_contention_monitor_thread_mtx = PTHREAD_MUTEX_INITIALIZER; static thread_t mutex_contention_monitor_thread_id = 0; static void* mutex_contention_monitor_thread(void* args_) { (void)args_; while(smp_int_get(&mutex_contention_monitor_thread_should_stop) == 0) { pthread_mutex_lock(&mutex_contention_mtx); ptr_set_iterator thread_iter; ptr_set_iterator monitor_iter; ptr_set_iterator other_iter; ptr_set_iterator_init(&mutex_contention_thread_to_monitor_set, &thread_iter); log_info("mutex-monitor: tick"); while(ptr_set_iterator_hasnext(&thread_iter)) { s64 now = timeus(); ptr_node *thread_node = ptr_set_iterator_next_node(&thread_iter); mutex_contention_thread_t *mct = (mutex_contention_thread_t*)thread_node->value; ptr_set_iterator_init(mct, &monitor_iter); while(ptr_set_iterator_hasnext(&monitor_iter)) { ptr_node *monitor_node = ptr_set_iterator_next_node(&monitor_iter); mutex_contention_monitor_t *mcm = (mutex_contention_monitor_t*)monitor_node->value; if(mcm->lock_end_timestamp == 0) { s64 wait_time = (now - mcm->lock_begin_timestamp); if(wait_time >= MUTEX_LOCKED_TOO_MUCH_TIME_US) { // not fine at all // tell this thread has been waiting for this node for quite some time // tell who is owning the mutex and since when log_warn("mutex-monitor: thread %p (%s) has been waiting for mutex @%p for %llius (looped %lli)", mcm->owning_thread, thread_get_tag_with_pid_and_tid(getpid_ex(), mcm->owning_thread), mcm->mutex_object->mutex, wait_time, mcm->lock_wait_loops); mutex_debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_WARNING, mcm->contention_point->st); ptr_set_iterator_init(&mcm->mutex_object->threads, &other_iter); while(ptr_set_iterator_hasnext(&other_iter)) { ptr_node *other_node = ptr_set_iterator_next_node(&other_iter); mutex_contention_monitor_t* other_mcm = (mutex_contention_monitor_t*)other_node->value; if(other_mcm->lock_end_timestamp == 0) { s64 other_wait_time = (now - other_mcm->lock_begin_timestamp); log_warn("mutex-monitor: thread %p (%s) has also been waiting for mutex @%p for %llius (looped %lli)", other_mcm->owning_thread, thread_get_tag_with_pid_and_tid(getpid_ex(), other_mcm->owning_thread), other_mcm->mutex_object->mutex, other_wait_time, other_mcm->lock_wait_loops); mutex_debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_WARNING, other_mcm->contention_point->st); } else { s64 other_wait_time = (now - other_mcm->lock_end_timestamp); log_warn("mutex-monitor: thread %p (%s) has been owning the mutex @%p for %llius (b)", other_mcm->owning_thread, thread_get_tag_with_pid_and_tid(getpid_ex(), other_mcm->owning_thread), other_mcm->mutex_object->mutex, other_wait_time, other_mcm->lock_wait_loops); mutex_debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_WARNING, other_mcm->contention_point->st); } } } } else { if(!mcm->used_by_condition) { s64 lock_time = (now - mcm->lock_end_timestamp); if(lock_time >= MUTEX_LOCKED_TOO_MUCH_TIME_US) { log_warn("mutex-monitor: thread %p (%s) has been owning the mutex @%p for %llius (looped %lli) (a long time)", mcm->owning_thread, thread_get_tag_with_pid_and_tid(getpid_ex(), mcm->owning_thread), mcm->mutex_object->mutex, lock_time, mcm->lock_wait_loops); mutex_debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_WARNING, mcm->contention_point->st); } } else { // mutex is used by a condition s64 wait_time = (now - mcm->lock_end_timestamp); if(wait_time >= MUTEX_WAITED_TOO_MUCH_TIME_US) { log_warn("mutex-monitor: thread %p (%s) has been waiting for %llius (looped %lli) (a long time)", mcm->owning_thread, thread_get_tag_with_pid_and_tid(getpid_ex(), mcm->owning_thread), wait_time, mcm->lock_wait_loops); mutex_debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_WARNING, mcm->contention_point->st); } } } } } pthread_mutex_unlock(&mutex_contention_mtx); sleep(1); } return NULL; } void mutex_contention_monitor_start() { pthread_mutex_lock(&mutex_contention_monitor_thread_mtx); if(mutex_contention_monitor_thread_id == 0) { thread_t tid; int ret = thread_create(&tid, mutex_contention_monitor_thread, NULL); if(ret == 0) { mutex_contention_monitor_thread_id = tid; } } pthread_mutex_unlock(&mutex_contention_monitor_thread_mtx); } void mutex_contention_monitor_stop() { pthread_mutex_lock(&mutex_contention_monitor_thread_mtx); if(mutex_contention_monitor_thread_id != 0) { smp_int_add(&mutex_contention_monitor_thread_should_stop, 1); thread_join(mutex_contention_monitor_thread_id, NULL); smp_int_sub(&mutex_contention_monitor_thread_should_stop, 1); mutex_contention_monitor_thread_id = 0; } pthread_mutex_unlock(&mutex_contention_monitor_thread_mtx); } #endif // !MUTEX_CONTENTION_MONITOR #endif int cond_init_process_shared(cond_t *cond) { #if !defined(__OpenBSD__) int ret; pthread_condattr_t attr; if((ret = pthread_condattr_init(&attr)) == 0) { if((ret = pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) == 0) { ret = pthread_cond_init(cond, &attr); if(ret != 0) { ret = MAKE_ERRNO_ERROR(ret); } } else { ret = MAKE_ERRNO_ERROR(ret); } pthread_condattr_destroy(&attr); } else { ret = MAKE_ERRNO_ERROR(ret); } return ret; #else (void)cond; return FEATURE_NOT_IMPLEMENTED_ERROR; #endif } /* * Group mutex lock */ void group_mutex_init(group_mutex_t* mtx) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: init mutex@%p", mtx); #endif #endif mutex_init(&mtx->mutex); cond_init(&mtx->cond); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_create(mtx, FALSE); #endif #endif mtx->count = 0; mtx->owner = GROUP_MUTEX_NOBODY; mtx->reserved_owner = GROUP_MUTEX_NOBODY; } bool group_mutex_islocked(group_mutex_t *mtx) { mutex_lock(&mtx->mutex); bool r = mtx->owner != 0; mutex_unlock(&mtx->mutex); return r; } void group_mutex_lock(group_mutex_t *mtx, u8 owner) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_t *mcm = mutex_contention_lock_begin(thread_self(), mtx, debug_stacktrace_get(), group_mutex_type_name); #endif #endif mutex_lock(&mtx->mutex); for(;;) { /* A simple way to ensure that a lock can be shared by similar entities or not. Sharable entities have their msb off. */ u8 co = mtx->owner & GROUP_MUTEX_LOCKMASK_FLAG; if(co == GROUP_MUTEX_NOBODY || co == owner) { yassert(mtx->count != MAX_S32); mtx->owner = owner & GROUP_MUTEX_LOCKMASK_FLAG; mtx->count++; break; } /* #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_wait(mcm); // counts the loops #endif #endif */ cond_wait(&mtx->cond, &mtx->mutex); } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif #endif mutex_unlock(&mtx->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: locked mutex@%p for %x", mtx, owner); #endif #endif } bool group_mutex_trylock(group_mutex_t *mtx, u8 owner) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: trying to lock mutex@%p for %x", mtx, owner); #endif #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_t *mcm = mutex_contention_lock_begin(thread_self(), mtx, debug_stacktrace_get(), group_mutex_type_name); #endif #endif mutex_lock(&mtx->mutex); u8 co = mtx->owner & GROUP_MUTEX_LOCKMASK_FLAG; if(co == GROUP_MUTEX_NOBODY || co == owner) { yassert(mtx->count != MAX_S32); mtx->owner = owner & GROUP_MUTEX_LOCKMASK_FLAG; mtx->count++; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif #endif mutex_unlock(&mtx->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: locked mutex@%p for %x", mtx, owner); #endif #endif return TRUE; } else { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_fail(mcm); #endif #endif mutex_unlock(&mtx->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: failed to lock mutex@%p for %x", mtx, owner); #endif #endif return FALSE; } } void group_mutex_unlock(group_mutex_t *mtx, u8 owner) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: unlocking mutex@%p for %x (owned by %x)", mtx, owner, mtx->owner); #endif #endif mutex_lock(&mtx->mutex); yassert(mtx->owner == (owner & GROUP_MUTEX_LOCKMASK_FLAG)); yassert(mtx->count != 0); (void)owner; mtx->count--; if(mtx->count == 0) { mtx->owner = GROUP_MUTEX_NOBODY; // wake up all the ones that were waiting for a clean ownership cond_notify(&mtx->cond); } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_unlock(thread_self(), mtx); #endif #endif mutex_unlock(&mtx->mutex); } void group_mutex_double_lock(group_mutex_t *mtx, u8 owner, u8 secondary_owner) { yassert(owner == GROUP_MUTEX_READ); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: double-locking mutex@%p for %x", mtx, secondary_owner); #endif #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_t *mcm = mutex_contention_lock_begin(thread_self(), mtx, debug_stacktrace_get(), group_mutex_type_name); #endif #endif mutex_lock(&mtx->mutex); for(;;) { /* * A simple way to ensure that a lock can be shared * by similar entities or not. * Sharable entities have their msb off. */ u8 so = mtx->reserved_owner & GROUP_MUTEX_LOCKMASK_FLAG; if(so == GROUP_MUTEX_NOBODY || so == secondary_owner) { u8 co = mtx->owner & GROUP_MUTEX_LOCKMASK_FLAG; if(co == GROUP_MUTEX_NOBODY || co == owner) { yassert(!SIGNED_VAR_VALUE_IS_MAX(mtx->count)); mtx->owner = owner & GROUP_MUTEX_LOCKMASK_FLAG; mtx->count++; mtx->reserved_owner = secondary_owner & GROUP_MUTEX_LOCKMASK_FLAG; break; } } else { // the secondary owner is already taken } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_wait(mcm); #endif #endif cond_wait(&mtx->cond, &mtx->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_resume(mcm); #endif #endif } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif #endif mutex_unlock(&mtx->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: double-locked mutex@%p for %x", mtx, secondary_owner); #endif #endif } void group_mutex_double_unlock(group_mutex_t *mtx, u8 owner, u8 secondary_owner) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: double-unlocking mutex@%p for %x (owned by %x)", mtx, secondary_owner, mtx->reserved_owner); #endif #endif yassert(owner == GROUP_MUTEX_READ); mutex_lock(&mtx->mutex); yassert(mtx->owner == (owner & GROUP_MUTEX_LOCKMASK_FLAG)); yassert(mtx->reserved_owner == (secondary_owner & GROUP_MUTEX_LOCKMASK_FLAG)); yassert(mtx->count != 0); (void)owner; (void)secondary_owner; mtx->reserved_owner = GROUP_MUTEX_NOBODY; --mtx->count; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: double-unlocked mutex@%p for %x,%x", mtx, owner, secondary_owner); #endif #endif yassert((mtx->owner & 0xc0) == 0); if(mtx->count == 0) { mtx->owner = GROUP_MUTEX_NOBODY; cond_notify(&mtx->cond); } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_unlock(thread_self(), mtx); #endif #endif mutex_unlock(&mtx->mutex); } void group_mutex_exchange_locks(group_mutex_t *mtx, u8 owner, u8 secondary_owner) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: exchanging-locks of mutex@%p %x,%x (", mtx, owner, secondary_owner, mtx->owner, mtx->reserved_owner); #endif #endif yassert(owner == GROUP_MUTEX_READ || secondary_owner == GROUP_MUTEX_READ); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #ifdef MODULE_MSG_HANDLE s64 start = timeus(); #endif mutex_lock(&mtx->mutex); if((mtx->owner != (owner & GROUP_MUTEX_LOCKMASK_FLAG)) || (mtx->reserved_owner != (secondary_owner & GROUP_MUTEX_LOCKMASK_FLAG)) || (mtx->count == 0)) { #ifdef MODULE_MSG_HANDLE debug_log_stacktrace(g_system_logger, MSG_ERR, "group_mutex_exchange_locks"); #endif abort(); } #else mutex_lock(&mtx->mutex); yassert(mtx->owner == (owner & GROUP_MUTEX_LOCKMASK_FLAG)); yassert(mtx->reserved_owner == (secondary_owner & GROUP_MUTEX_LOCKMASK_FLAG)); yassert(mtx->count != 0); #endif #if DEBUG if((mtx->owner != (owner & GROUP_MUTEX_LOCKMASK_FLAG)) || (mtx->count == 0)) { mutex_unlock(&mtx->mutex); yassert(mtx->owner == (owner & GROUP_MUTEX_LOCKMASK_FLAG)); yassert(mtx->count != 0); abort(); // unreachable } if(mtx->reserved_owner != (secondary_owner & GROUP_MUTEX_LOCKMASK_FLAG)) { mutex_unlock(&mtx->mutex); yassert(mtx->reserved_owner != (secondary_owner & GROUP_MUTEX_LOCKMASK_FLAG)); abort(); // unreachable } #endif // wait to be the last one while(mtx->count != 1) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #ifdef MODULE_MSG_HANDLE s64 d = timeus() - start; if(d > MUTEX_WAITED_TOO_MUCH_TIME_US) { log_warn("group_mutex_exchange_locks(%p,%x,%x) : waited for %llius already ...", mtx, owner, secondary_owner, d); debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_WARNING, "group_mutex_exchange_locks:"); } #endif #endif cond_timedwait(&mtx->cond, &mtx->mutex, 100); } mtx->owner = secondary_owner & GROUP_MUTEX_LOCKMASK_FLAG; mtx->reserved_owner = owner & GROUP_MUTEX_LOCKMASK_FLAG; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: exchanged locks of mutex@%p to %x, %x", mtx, secondary_owner, owner); #endif #endif if((secondary_owner & GROUP_MUTEX_EXCLUSIVE_FLAG) == 0) { cond_notify(&mtx->cond); } mutex_unlock(&mtx->mutex); } void group_mutex_destroy(group_mutex_t* mtx) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("group_mutex: destroy mutex@%p", mtx); #endif #endif mutex_lock(&mtx->mutex); yassert(mtx->count == 0); mutex_unlock(&mtx->mutex); group_mutex_lock(mtx, GROUP_MUTEX_DESTROY); group_mutex_unlock(mtx, GROUP_MUTEX_DESTROY); cond_notify(&mtx->cond); cond_finalize(&mtx->cond); mutex_destroy(&mtx->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_destroy(mtx); #endif #endif } void mutex_init_recursive(mutex_t *mtx) { int err; ZEROMEMORY(mtx, sizeof(mutex_t)); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_create(mtx, FALSE); #endif #endif pthread_mutexattr_t mta; err = pthread_mutexattr_init(&mta); if(err != 0) { #ifdef MODULE_MSG_HANDLE logger_handle_msg(g_system_logger,MSG_ERR, "mutex_init_recursive: attr %r", MAKE_ERRNO_ERROR(err)); #endif } err = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE); if(err != 0) { #ifdef MODULE_MSG_HANDLE logger_handle_msg(g_system_logger,MSG_ERR, "mutex_init_recursive: set %r", MAKE_ERRNO_ERROR(err)); #endif } err = pthread_mutex_init(mtx, &mta); if(err != 0) { #ifdef MODULE_MSG_HANDLE logger_handle_msg(g_system_logger,MSG_ERR, "mutex_init_recursive: %r", MAKE_ERRNO_ERROR(err)); #endif } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT if(mutex_ultraverbose) { logger_handle_msg(g_system_logger,MSG_DEBUG7, "mutex_init(%p)", mtx); } #endif pthread_mutexattr_destroy(&mta); } int mutex_init_process_shared(mutex_t *mtx) { #if !defined(__OpenBSD__) int ret; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_create(mtx, FALSE); #endif #endif pthread_mutexattr_t attr; if((ret = pthread_mutexattr_init(&attr)) == 0) { ret = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); if(ret == 0) { if((ret = pthread_mutex_init(mtx, &attr)) != 0) { ret = MAKE_ERRNO_ERROR(ret); } } else { ret = MAKE_ERRNO_ERROR(ret); } pthread_mutexattr_destroy(&attr); } else { ret = MAKE_ERRNO_ERROR(ret); } return ret; #else (void)mtx; return FEATURE_NOT_IMPLEMENTED_ERROR; #endif } void mutex_init(mutex_t *mtx) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_create(mtx, FALSE); #endif #endif int err = pthread_mutex_init(mtx, NULL); if(err != 0) { logger_handle_msg(g_system_logger,MSG_ERR, "mutex_init: %r", MAKE_ERRNO_ERROR(err)); } } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT void mutex_lock(mutex_t *mtx) { if(mutex_ultraverbose) { #ifdef MODULE_MSG_HANDLE logger_handle_msg(g_system_logger,MSG_DEBUG7, "mutex_lock(%p)", mtx); #endif } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_t *mcm = mutex_contention_lock_begin(thread_self(), mtx, debug_stacktrace_get(), mutex_type_name); #endif #endif pthread_mutex_lock(mtx); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif #endif if(mutex_ultraverbose) { #ifdef MODULE_MSG_HANDLE logger_handle_msg(g_system_logger,MSG_DEBUG7, "mutex_lock(%p): locked", mtx); #endif } } bool mutex_trylock(mutex_t *mtx) { if(mutex_ultraverbose) { logger_handle_msg(g_system_logger, MSG_DEBUG7, "mutex_trylock(%p)", mtx); } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_t *mcm = mutex_contention_lock_begin(thread_self(), mtx, debug_stacktrace_get(), mutex_type_name); #endif #endif int err = pthread_mutex_trylock(mtx); if((err != 0) && (err != EBUSY)) { logger_handle_msg(g_system_logger,MSG_ERR, "mutex_trylock(%p): %r", mtx, MAKE_ERRNO_ERROR(err)); logger_flush(); abort(); } if(err == 0) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif #endif } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR else { mutex_contention_lock_fail(mcm); } #endif #endif if(mutex_ultraverbose) { logger_handle_msg(g_system_logger,MSG_DEBUG7, "mutex_trylock(%p): %s", mtx, (err == 0)?"locked":"failed"); } return err == 0; } void mutex_unlock(mutex_t *mtx) { if(mutex_ultraverbose) { logger_handle_msg(g_system_logger,MSG_DEBUG7, "mutex_unlock(%p)", mtx); } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_unlock(thread_self(), mtx); #endif #endif int err = pthread_mutex_unlock(mtx); if(err != 0) { logger_handle_msg(g_system_logger, MSG_ERR, "mutex_unlock(%p) self=%p: %r", mtx, (intptr)thread_self(), MAKE_ERRNO_ERROR(err)); debug_stacktrace_log(g_system_logger, MSG_ERR, debug_stacktrace_get()); logger_flush(); abort(); } } int mutex_lock_unchecked(mutex_t *mtx) { if(mutex_ultraverbose) { #ifdef MODULE_MSG_HANDLE logger_handle_msg(g_system_logger,MSG_DEBUG7, "mutex_lock(%p)", mtx); #endif } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_t *mcm = mutex_contention_lock_begin(thread_self(), mtx, debug_stacktrace_get(), mutex_type_name); #endif #endif int ret = pthread_mutex_lock(mtx); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif #endif if(mutex_ultraverbose) { #ifdef MODULE_MSG_HANDLE logger_handle_msg(g_system_logger,MSG_DEBUG7, "mutex_lock(%p): locked", mtx); #endif } return ret; } int mutex_unlock_unchecked(mutex_t *mtx) { if(mutex_ultraverbose) { logger_handle_msg(g_system_logger,MSG_DEBUG7, "mutex_unlock(%p)", mtx); } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_unlock(thread_self(), mtx); #endif #endif int ret = pthread_mutex_unlock(mtx); if(ret != 0) { logger_handle_msg(g_system_logger, MSG_ERR, "mutex_unlock(%p) self=%p: %r", mtx, (intptr)thread_self(), MAKE_ERRNO_ERROR(ret)); debug_stacktrace_log(g_system_logger, MSG_ERR, debug_stacktrace_get()); logger_flush(); } return ret; } #endif void mutex_destroy(mutex_t *mtx) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT int ebusy_count = 0; if(mutex_ultraverbose) { #ifdef MODULE_MSG_HANDLE logger_handle_msg(g_system_logger,MSG_DEBUG7, "mutex_destroy(%p)", mtx); #endif } #endif for(;;) { int err = pthread_mutex_destroy(mtx); switch(err) { case 0: { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_destroy(mtx); #endif #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT if(ebusy_count > 0) { logger_handle_msg(g_system_logger,MSG_DEBUG7, "mutex_destroy: EBUSY #%i", ebusy_count); } #endif return; } case EBUSY: { usleep(1000); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT ebusy_count++; #ifdef MODULE_MSG_HANDLE if((ebusy_count & 0xfffff) == 0) { debug_stacktrace_log(g_system_logger, MSG_DEBUG7, debug_stacktrace_get()); } if((ebusy_count & 0xfff) == 0) { logger_handle_msg(g_system_logger,MSG_ERR, "mutex_destroy: EBUSY #%i", ebusy_count); } #endif #endif break; } default: { #ifdef MODULE_MSG_HANDLE logger_handle_msg(g_system_logger,MSG_ERR, "mutex_destroy: %r", MAKE_ERRNO_ERROR(err)); logger_flush(); #endif abort(); } } } } /////////////////////////////////////////////////////////////////////////////// /* * Group mutex lock */ void shared_group_shared_mutex_init(shared_group_shared_mutex_t* smtx) { mutex_init(&smtx->mutex); cond_init(&smtx->cond); smtx->rc = 0; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_create(smtx, FALSE); #endif #endif } void shared_group_shared_mutex_init_recursive(shared_group_shared_mutex_t* smtx) { mutex_init_recursive(&smtx->mutex); cond_init(&smtx->cond); smtx->rc = 0; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_create(smtx, TRUE); #endif #endif } void shared_group_shared_mutex_destroy(shared_group_shared_mutex_t* smtx) { yassert(smtx->rc == 0); cond_finalize(&smtx->cond); mutex_destroy(&smtx->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_destroy(smtx); #endif #endif } void shared_group_mutex_init(shared_group_mutex_t* mtx, shared_group_shared_mutex_t* smtx, const char *name) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("shared_group_mutex: init mutex@%p+%p '%s'", mtx, smtx, name); #endif #else (void)name; #endif mutex_lock(&smtx->mutex); smtx->rc++; mutex_unlock(&smtx->mutex); mtx->shared_mutex = smtx; mtx->count = 0; mtx->owner = GROUP_MUTEX_NOBODY; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_create(mtx, TRUE); #endif #endif } bool shared_group_mutex_islocked(shared_group_mutex_t *mtx) { mutex_lock(&mtx->shared_mutex->mutex); bool r = mtx->owner != 0; mutex_unlock(&mtx->shared_mutex->mutex); return r; } bool shared_group_mutex_islocked_by(shared_group_mutex_t *mtx, u8 owner) { mutex_lock(&mtx->shared_mutex->mutex); bool r = mtx->owner == (owner & GROUP_MUTEX_LOCKMASK_FLAG); mutex_unlock(&mtx->shared_mutex->mutex); return r; } void shared_group_mutex_lock(shared_group_mutex_t *mtx, u8 owner) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("shared_group_mutex: locking mutex@%p for %x", mtx, owner); #endif #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_t *mcm = mutex_contention_lock_begin(thread_self(), mtx, debug_stacktrace_get(), shared_group_mutex_type_name); #endif #endif mutex_lock(&mtx->shared_mutex->mutex); for(;;) { /* A simple way to ensure that a lock can be shared by similar entities or not. Sharable entities have their msb off. */ u8 co = mtx->owner & GROUP_MUTEX_LOCKMASK_FLAG; if(co == GROUP_MUTEX_NOBODY || co == owner) { yassert(mtx->count != MAX_S32); mtx->owner = owner & GROUP_MUTEX_LOCKMASK_FLAG; mtx->count++; break; } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_wait(mcm); #endif #endif cond_wait(&mtx->shared_mutex->cond, &mtx->shared_mutex->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_resume(mcm); #endif #endif } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif #endif mutex_unlock(&mtx->shared_mutex->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("shared_group_mutex: locked mutex@%p for %x", mtx, owner); #endif #endif } bool shared_group_mutex_trylock(shared_group_mutex_t *mtx, u8 owner) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("shared_group_mutex: trying to lock mutex@%p for %x", mtx, owner); #endif #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_t *mcm = mutex_contention_lock_begin(thread_self(), mtx, debug_stacktrace_get(), shared_group_mutex_type_name); #endif #endif mutex_lock(&mtx->shared_mutex->mutex); u8 co = mtx->owner & GROUP_MUTEX_LOCKMASK_FLAG; if(co == GROUP_MUTEX_NOBODY || co == owner) { yassert(mtx->count != MAX_S32); mtx->owner = owner & GROUP_MUTEX_LOCKMASK_FLAG; mtx->count++; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif #endif mutex_unlock(&mtx->shared_mutex->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("shared_group_mutex: locked mutex@%p for %x", mtx, owner); #endif #endif return TRUE; } else { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_fail(mcm); #endif #endif mutex_unlock(&mtx->shared_mutex->mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("shared_group_mutex: failed to lock mutex@%p for %x", mtx, owner); #endif #endif return FALSE; } } void shared_group_mutex_unlock(shared_group_mutex_t *mtx, u8 owner) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("shared_group_mutex: unlocking mutex@%p for %x (owned by %x)", mtx, owner, mtx->owner); #endif #endif mutex_lock(&mtx->shared_mutex->mutex); yassert(mtx->owner == (owner & GROUP_MUTEX_LOCKMASK_FLAG)); yassert(mtx->count != 0); (void)owner; mtx->count--; if(mtx->count == 0) { mtx->owner = GROUP_MUTEX_NOBODY; // wake up all the ones that were waiting for a clean ownership cond_notify(&mtx->shared_mutex->cond); } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_unlock(thread_self(), mtx); #endif #endif mutex_unlock(&mtx->shared_mutex->mutex); } bool shared_group_mutex_transferlock(shared_group_mutex_t *mtx, u8 owner, u8 newowner) { bool r; #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("shared_group_mutex: transferring ownership of mutex@%p from %x to %x (owned by %x)", mtx, owner, newowner, mtx->owner); #endif #endif mutex_lock(&mtx->shared_mutex->mutex); u8 co = mtx->owner & GROUP_MUTEX_LOCKMASK_FLAG; if((r = (co == owner))) { mtx->owner = newowner; } mutex_unlock(&mtx->shared_mutex->mutex); return r; } void shared_group_mutex_destroy(shared_group_mutex_t* mtx) { #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT > 1 #ifdef MODULE_MSG_HANDLE log_debug7("shared_group_mutex: destroy mutex@%p", mtx); #endif #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if MUTEX_CONTENTION_MONITOR mutex_contention_object_destroy(mtx); #endif #endif mutex_lock(&mtx->shared_mutex->mutex); mtx->shared_mutex->rc--; mutex_unlock(&mtx->shared_mutex->mutex); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/network.c0000644000000000000000000000013214505005532021165 xustar000000000000000030 mtime=1695812442.382981329 30 atime=1695812445.792030153 30 ctime=1695812494.638729736 yadifa-2.6.5-11201/lib/dnscore/src/network.c0000664000374500037450000002004314505005532021126 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include "dnscore/network.h" #include #include #include bool addr_info_is_any(struct addrinfo* addr) { bool is_any; if(addr->ai_family == AF_INET6) { static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; const struct sockaddr_in6 *addr_v6 = (const struct sockaddr_in6*)addr->ai_addr->sa_data; is_any = memcmp(&addr_v6->sin6_addr, &in6addr_any, 16) == 0; } else if(addr->ai_family == AF_INET) { const struct sockaddr_in *addr_v4 = (const struct sockaddr_in*)addr->ai_addr->sa_data; is_any = (addr_v4->sin_addr.s_addr == INADDR_ANY); } else { // no supported, so no is_any = FALSE; } return is_any; } ya_result network_interfaces_forall(network_interfaces_forall_callback cb, void *data) { ya_result ret = SUCCESS; struct ifaddrs *ia = NULL; if(getifaddrs(&ia) == 0) { socketaddress tmp; char tmp_name[128]; for(struct ifaddrs *a = ia; a != NULL; a = a->ifa_next) { if((a->ifa_flags & IFF_UP) == 0) { // interface is down continue; } if(a->ifa_addr == NULL) { // interface isn't usable continue; } socketaddress* sa = (socketaddress*)a->ifa_addr; switch(sa->sa.sa_family) { case AF_INET: { tmp = *sa; strncpy(tmp_name, a->ifa_name, sizeof(tmp_name)); tmp_name[sizeof(tmp_name) - 1] = '\0'; //formatln("v4: %s: %{sockaddr}", tmp_name, &tmp); ret = cb(tmp_name, &tmp, data); break; } case AF_INET6: { tmp = *sa; strncpy(tmp_name, a->ifa_name, sizeof(tmp_name)); tmp_name[sizeof(tmp_name) - 1] = '\0'; //formatln("v6: %s: %{sockaddr}", tmp_name, &tmp); ret = cb(tmp_name, &tmp, data); break; } default: { ret = SUCCESS; // ignore break; } } if(FAIL(ret)) { break; } } freeifaddrs(ia); } else { ret = ERRNO_ERROR; } return ret; } int sockaddr_compare_addr_port(const struct sockaddr *a, const struct sockaddr *b) { int ret; ret = a->sa_family; ret -= b->sa_family; if(ret == 0) { switch(a->sa_family) { case AF_INET: { const struct sockaddr_in *sa4 = (const struct sockaddr_in *)a; const struct sockaddr_in *sb4 = (const struct sockaddr_in *)b; ret = sa4->sin_port; ret -= sb4->sin_port; if(ret == 0) { ret = memcmp(&sa4->sin_addr.s_addr, &sb4->sin_addr.s_addr, 4); } break; } case AF_INET6: { const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *)a; const struct sockaddr_in6 *sb6 = (const struct sockaddr_in6 *)b; ret = sa6->sin6_port; ret -= sb6->sin6_port; if(ret == 0) { ret = memcmp(&sa6->sin6_addr, &sb6->sin6_addr, 16); } break; } } } return ret; } int socketaddress_compare_ip(const void *a, const void *b) { const socketaddress *sa = (const socketaddress*)a; const socketaddress *sb = (const socketaddress*)b; if(sa != sb) { int ret = (int)sa->sa.sa_family - (int)sb->sa.sa_family; if(ret == 0) { switch(sa->sa.sa_family) { case AF_INET: ret = memcmp(&sa->sa4.sin_addr, &sb->sa4.sin_addr, sizeof(sa->sa4.sin_addr)); break; case AF_INET6: ret = memcmp(&sa->sa6.sin6_addr, &sb->sa6.sin6_addr, sizeof(sa->sa6.sin6_addr)); break; default: ret = (int)(intptr)(sa - sb); break; } } return ret; } else { return 0; } } int sockaddr_storage_compare_ip(const void *key_a, const void *key_b) { const struct sockaddr_storage *ssap = (const struct sockaddr_storage *)key_a; const struct sockaddr_storage *ssbp = (const struct sockaddr_storage *)key_b; int d = ssap->ss_family - ssbp->ss_family; if(d == 0) { switch(ssap->ss_family) { case AF_INET: { struct sockaddr_in *ina = (struct sockaddr_in*)ssap; struct sockaddr_in *inb = (struct sockaddr_in*)ssbp; d = memcmp(&ina->sin_addr, &inb->sin_addr, sizeof(ina->sin_addr)); break; } case AF_INET6: { struct sockaddr_in6 *ina = (struct sockaddr_in6*)ssap; struct sockaddr_in6 *inb = (struct sockaddr_in6*)ssbp; d = memcmp(&ina->sin6_addr, &inb->sin6_addr, sizeof(ina->sin6_addr)); break; } default: { d = memcmp(ssap, ssbp, sizeof(struct sockaddr_storage)); break; } } } return d; } void sockaddr_storage_copy(struct sockaddr_storage *dest, const struct sockaddr_storage *src) { switch(src->ss_family) { case AF_INET: { memcpy(dest, src, sizeof(struct sockaddr_in)); break; } case AF_INET6: { memcpy(dest, src, sizeof(struct sockaddr_in6)); break; } default: { memcpy(dest, src, sizeof(struct sockaddr_storage)); break; } } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/nsec3-hash.c0000644000000000000000000000013214505005532021430 xustar000000000000000030 mtime=1695812442.452982331 30 atime=1695812445.794030182 30 ctime=1695812494.640729765 yadifa-2.6.5-11201/lib/dnscore/src/nsec3-hash.c0000664000374500037450000001114314505005532021372 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/dnssec_errors.h" #include "dnscore/nsec3-hash.h" #include "dnscore/digest.h" /****************************************************************************** * * Digest - related methods. * *****************************************************************************/ static u8 WILDCARD_PREFIX[2] = {1, '*'}; static ya_result nsec3_hash_unsupported_function(const u8* name, u32 name_len, const u8* salt, u32 salt_len, u32 iterations, u8* digest, bool wild) { (void)name; (void)name_len; (void)salt; (void)salt_len; (void)iterations; (void)digest; (void)wild; return DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM; } static ya_result nsec3_hash_sha1_function(const u8* name, u32 name_len, const u8* salt, u32 salt_len, u32 iterations, u8* digest, bool wild) { digest_s sha1; digest_sha1_init(&sha1); if(wild) { digest_update(&sha1, WILDCARD_PREFIX, 2); } digest_update(&sha1, name, name_len); digest_update(&sha1, salt, salt_len); digest_final_copy_bytes(&sha1, digest, SHA_DIGEST_LENGTH); // generates NSEC3 hash : safe use for(; iterations > 0; iterations--) { digest_sha1_init(&sha1); digest_update(&sha1, digest, SHA_DIGEST_LENGTH); digest_update(&sha1, salt, salt_len); digest_final_copy_bytes(&sha1, digest, SHA_DIGEST_LENGTH); // generates NSEC3 hash : safe use } return SUCCESS; } /** * * Returns the (NSEC3) hashing function for an algorithm * * If the algorithm is not supported, the returned function will * always return DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM. * * A typical usage for this is : * * get_nsec3_hash_function(NSEC3_ZONE_ALGORITHM(n3))(name, ...... ) * |_______________________________________________||_____________| * Get the digest function pointer Call the returned function * * @param algorithm the algorithm id * @return the hashing function * */ nsec3_hash_function* nsec3_hash_get_function(u8 algorithm) { switch(algorithm) { case 1: return &nsec3_hash_sha1_function; default: return &nsec3_hash_unsupported_function; } } /** * Returns the size in bytes of the hash computed by hashing function algorithm * * @param algorithm the algorithm id * @return size in bytes of the computed hash or 0 if the function is not supported */ u8 nsec3_hash_len(u8 algorithm) { switch(algorithm) { case 1: return SHA_DIGEST_LENGTH; default: return 0; } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/output_stream.c0000644000000000000000000000013214505005532022407 xustar000000000000000030 mtime=1695812442.369981142 30 atime=1695812445.791030139 30 ctime=1695812494.642729794 yadifa-2.6.5-11201/lib/dnscore/src/output_stream.c0000664000374500037450000003661014505005532022357 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * Implementation of routines for the resource_record struct * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #include #include #include "dnscore/dnscore.h" #include "dnscore/logger.h" #include "dnscore/dnsname.h" #include "dnscore/output_stream.h" #include "dnscore/base64.h" #include "dnscore/base32.h" #include "dnscore/base32hex.h" #include "dnscore/base16.h" #include "dnscore/zalloc.h" #define MODULE_MSG_HANDLE g_system_logger #define OSTREAM_TAG 0x4d41455254534f static const char ESCAPE_CHARS[] = {'@', '$', '\\', ';'}; ya_result output_stream_write_nu32(output_stream* os, u32 value) { u8 buffer[4]; /* ------------------------------------------------------------ */ buffer[0] = value >> 24; buffer[1] = value >> 16; buffer[2] = value >> 8; buffer[3] = value; return output_stream_write(os, buffer, 4); } ya_result output_stream_write_nu16(output_stream* os, u16 value) { u8 buffer[2]; /* ------------------------------------------------------------ */ buffer[0] = value >> 8; buffer[1] = value; return output_stream_write(os, buffer, 2); } ya_result output_stream_decode_base64(output_stream* os, const char * string, u32 length) { char buffer[64]; u8 buffer_bin[48]; u32 needle = 0; ya_result return_code = OK; /* ------------------------------------------------------------ */ while(length-- > 0) { char c = *string++; if(isspace(c)) { continue; } buffer[needle++] = c; if(needle == 64) { if(FAIL(return_code = base64_decode(buffer, needle, buffer_bin))) { return return_code; } if(FAIL(return_code = output_stream_write(os, buffer_bin, return_code))) { return return_code; } needle = 0; } } if(needle > 0) { if((needle & 3) != 0) { return PARSEB64_ERROR; } if(FAIL(return_code = base64_decode(buffer, needle, buffer_bin))) { return return_code; } if(FAIL(return_code = output_stream_write(os, buffer_bin, return_code))) { return return_code; } } return return_code; } ya_result output_stream_decode_base32(output_stream* os, const char * string, u32 length) { char buffer[64]; u8 buffer_bin[40]; u32 needle = 0; ya_result return_code = OK; /* ------------------------------------------------------------ */ while(length-- > 0) { char c = *string++; if(isspace(c)) { continue; } buffer[needle++] = c; if(needle == sizeof(buffer)) { if(FAIL(return_code = base32_decode(buffer, needle, buffer_bin))) { return return_code; } if(FAIL(return_code = output_stream_write(os, buffer_bin, return_code))) { return return_code; } needle = 0; } } if(needle > 0) { if((needle & 7) != 0) { return PARSEB32_ERROR; } if(FAIL(return_code = base32_decode(buffer, needle, buffer_bin))) { return return_code; } if(FAIL(return_code = output_stream_write(os, buffer_bin, return_code))) { return return_code; } } return return_code; } ya_result output_stream_decode_base32hex(output_stream* os, const char * string, u32 length) { char buffer[64]; u8 buffer_bin[40]; u32 needle = 0; ya_result return_code = OK; /* ------------------------------------------------------------ */ while(length-- > 0) { char c = *string++; if(isspace(c)) { continue; } buffer[needle++] = c; if(needle == sizeof(buffer)) { if(FAIL(return_code = base32hex_decode(buffer, needle, buffer_bin))) { return return_code; } if(FAIL(return_code = output_stream_write(os, buffer_bin, return_code))) { return return_code; } needle = 0; } } if(needle > 0) { if((needle & 7) != 0) { return PARSEB32H_ERROR; } if(FAIL(return_code = base32hex_decode(buffer, needle, buffer_bin))) { return return_code; } if(FAIL(return_code = output_stream_write(os, buffer_bin, return_code))) { return return_code; } } return return_code; } ya_result output_stream_decode_base16(output_stream* os, const char * string, u32 length) { const char *string_start = string; u32 needle = 0; ya_result return_code = OK; char buffer[64]; u8 buffer_bin[32]; /* ------------------------------------------------------------ */ while(length-- > 0) { char c = *string++; if(isspace(c)) { continue; } buffer[needle++] = c; if(needle == sizeof(buffer)) { if(FAIL(return_code = base16_decode(buffer, needle, buffer_bin))) { return return_code; } if(FAIL(return_code = output_stream_write(os, buffer_bin, return_code))) { return return_code; } needle = 0; } } if(needle > 0) { if((needle & 1) != 0) { return PARSEB16_ERROR; } if(FAIL(return_code = base16_decode(buffer, needle, buffer_bin))) { return return_code; } if(FAIL(return_code = output_stream_write(os, buffer_bin, return_code))) { return return_code; } } /* return the number of bytes read, instead of the last write size * this way something can be done about the input. * * alternatively we could just return "success" */ return (ya_result)(string - string_start); } ya_result output_stream_write_pu16(output_stream* os, u16 value) { u8 v; if(value > 127) { v = (u8)value; value >>= 7; v |= 0x80; /* I'll only check the error for the last byte */ output_stream_write(os, &v, 1); } v = (u8)value; return output_stream_write(os, &v, 1); } ya_result output_stream_write_pu32(output_stream* os, u32 value) { u8 v; while(value > 127) { v = (u8)value; value >>= 7; v |= 0x80; /* I'll only check the error for the last byte */ output_stream_write(os, &v, 1); } v = (u8)value; return output_stream_write(os, &v, 1); } ya_result output_stream_write_pu64(output_stream* os, u64 value) { u8 v; while(value > 127) { v = (u8)value; value >>= 7; v |= 0x80; /* I'll only check the error for the last byte */ output_stream_write(os, &v, 1); } v = (u8)value; return output_stream_write(os, &v, 1); } ya_result output_stream_write_dnsname(output_stream* os, const u8 *name) { u32 len = dnsname_len(name); return output_stream_write(os, name, len); } ya_result output_stream_write_dnsname_text(output_stream* os, const u8 *name) { static char dot[1] = {'.'}; const u8 *base = name; u8 label_len; label_len = *name; if(label_len > 0) { do { output_stream_write(os, ++name, label_len); output_stream_write(os, &dot, 1); name += label_len; label_len = *name; } while(label_len > 0); } else { output_stream_write(os, &dot, 1); } return (ya_result)(name - base + 1); } ya_result output_stream_write_dnslabel_text_escaped(output_stream* os, const u8 *label) { static const char escape[1] = {'\\'}; int len = *label++; u32 additional_len = 0; for(int i = 0; i < len; ++i) { switch(label[i]) { case '@': case '$': case ';': case '\\': ++additional_len; output_stream_write(os, escape, 1); FALLTHROUGH // fall through default: output_stream_write(os, &label[i], 1); } } return len + additional_len; } static bool output_stream_write_should_escape(const u8* name, size_t name_len) { for(size_t i = 0; i < name_len; ++i) { const char c = name[i]; for(u32 j = 0; j < sizeof(ESCAPE_CHARS); ++j) { if(c == ESCAPE_CHARS[j]) { return TRUE; } } } return FALSE; } ya_result output_stream_write_dnsname_text_escaped(output_stream* os, const u8 *name) { static const char dot[1] = {'.'}; u8 label_len; label_len = *name; ya_result ret; if(label_len > 0) { ret = 0; do { ++name; if(!output_stream_write_should_escape(name, label_len)) { output_stream_write(os, name, label_len); ret += label_len; } else { // write escaped ret += output_stream_write_dnslabel_text_escaped(os, name - 1); } output_stream_write(os, dot, 1); ++ret; name += label_len; label_len = *name; } while(label_len > 0); } else { output_stream_write(os, dot, 1); ret = 1; } return ret; } ya_result output_stream_write_dnslabel_vector(output_stream* os, dnslabel_vector_reference labels, s32 top) { ya_result n = 0; s32 i; for(i = 0; i <= top; i++) { ya_result err; u8 len = labels[i][0] + 1; if(FAIL(err = output_stream_write(os, labels[i], len))) { return err; } n += err; } output_stream_write_u8(os, 0); return n; } ya_result output_stream_write_dnslabel_stack(output_stream* os, dnslabel_stack_reference labels, s32 top) { ya_result n = 0; s32 i; for(i = top; i >= 0; i--) { ya_result err; u8 len = labels[i][0] + 1; if(FAIL(err = output_stream_write(os, labels[i], len))) { return err; } n += err; } output_stream_write_u8(os, 0); return n; } output_stream* output_stream_alloc() { output_stream* os; ZALLOC_OBJECT_OR_DIE(os, output_stream, OSTREAM_TAG); /* OSTREAM */ os->data = NULL; os->vtbl = NULL; return os; } static ya_result void_output_stream_write(output_stream* stream, const u8* buffer, u32 len) { (void)stream; (void)buffer; (void)len; log_err("tried to write a closed stream"); return INVALID_STATE_ERROR; } static ya_result void_output_stream_flush(output_stream* stream) { (void)stream; log_err("tried to flush a closed stream"); return INVALID_STATE_ERROR; } static void void_output_stream_close(output_stream* stream) { (void)stream; /* * WARNING */ log_err("tried to close a closed stream"); #if DEBUG abort(); #endif } static const output_stream_vtbl void_output_stream_vtbl ={ void_output_stream_write, void_output_stream_flush, void_output_stream_close, "void_output_stream", }; /** * This tools allows a safer misuse (and detection) of closed streams * It sets the stream to a sink that warns abouts its usage and for which every call that can fail fails. */ void output_stream_set_void(output_stream* stream) { stream->data = NULL; stream->vtbl = &void_output_stream_vtbl; } static ya_result sink_output_stream_write(output_stream* stream, const u8* buffer, u32 len) { (void)stream; (void)buffer; return len; } static ya_result sink_output_stream_flush(output_stream* stream) { (void)stream; return SUCCESS; } static void sink_output_stream_close(output_stream* stream) { (void)stream; } static const output_stream_vtbl sink_output_stream_vtbl ={ sink_output_stream_write, sink_output_stream_flush, sink_output_stream_close, "sink_output_stream", }; /** * Used to temporarily initialise a stream with a sink that can be closed safely. * Typically used as pre-init so the stream can be closed even if the function * setup failed before reaching stream initialisation. * * @param os */ void output_stream_set_sink(output_stream* os) { os->data = NULL; os->vtbl = &sink_output_stream_vtbl; } ya_result output_stream_write_fully(output_stream* stream, const void* buffer_start, u32 len_start) { output_stream_write_method* writefunc = stream->vtbl->write; u32 len = len_start; u8* buffer = (u8*)buffer_start; ya_result ret; while(len > 0) { if(FAIL(ret = writefunc(stream, buffer, len))) { return ret; } if(ret == 0) /* eof */ { break; } buffer += ret; len -= ret; // cppcheck: false positive } /* If we only read a partial it's wrong. * If we were asked to read nothing it's ok. * If we read nothing at all we were on EOF and its still ok */ if(len > 0) { return UNABLE_TO_COMPLETE_FULL_WRITE; } return (ya_result)(buffer - (u8*)buffer_start); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/pace.c0000644000000000000000000000013114505005532020403 xustar000000000000000030 mtime=1695812442.482982761 29 atime=1695812445.79603021 30 ctime=1695812494.644729822 yadifa-2.6.5-11201/lib/dnscore/src/pace.c0000664000374500037450000001111514505005532020345 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include #include "dnscore/logger.h" #include "dnscore/pace.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define PACE_DUMP 0 #define PACE_MODE_SMOOTH 0 #define PACE_MODE_HARD 1 #define PACE_MODE PACE_MODE_HARD void pace_init(pace_s *pace, u64 min_us, u64 max_us, const char *name) { if(min_us > max_us) { u64 tmp = max_us; max_us = min_us; min_us = tmp; } pace->min_us = min_us; pace->max_us = max_us; #if PACE_MODE == PACE_MODE_SMOOTH pace->current_us = (max_us + min_us) >> 1; #else pace->current_us = min_us; #endif pace->counter = 0; pace->name = name; } /** * Will pause for a while */ void pace_wait(pace_s *pace) { u64 start = timeus(); if((pace->counter > 0) && ((pace->counter & 3) != 0)) { #if defined(PACE_DUMP) && (PACE_DUMP > 0) u64 current = pace->current_us; #endif pace->current_us <<= 1; if(pace->current_us == 0) { pace->current_us = 1; } if(pace->current_us > pace->max_us) { pace->current_us = pace->max_us; } #if defined(PACE_DUMP) && (PACE_DUMP > 0) if(current != pace->current_us) { log_debug("pace: '%s' waiting for %lluµs (#%llu)", pace->name, pace->current_us, pace->counter); } #endif } else { pace->wait_start = start; #if defined(PACE_DUMP) && (PACE_DUMP > 0) log_debug("pace: '%s' waiting for %lluµs (#%llu)", pace->name, pace->current_us, pace->counter); #endif } pace->counter++; u64 elapsed = 0; u64 current = pace->current_us; do { if(elapsed > current) { log_err("pace_wait: impossible! elapsed = %llu > %llu", elapsed, current); break; } usleep(current - elapsed); u64 now = timeus(); if(now < start) { log_err("pace_wait: now=%llu < start=%llu (%llu)", now, start, start-now); break; } elapsed = now - start; } while(elapsed < current); } /** * Will update the pace taking the fact that now we have work to do */ void pace_work(pace_s *pace) { pace->wait_end = timeus(); #if defined(PACE_DUMP) && (PACE_DUMP > 0) log_debug("pace: '%s' working after %lluµs (%lluµs #%llu)", pace->name, pace->wait_end - pace->wait_start, pace->current_us, pace->counter); #endif pace->counter = 0; #if PACE_MODE == PACE_MODE_SMOOTH pace->current_us >>= 1; if(pace->current_us < pace->min_us) { pace->current_us = pace->min_us; } #else pace->current_us = pace->min_us; #endif } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/packet_reader.c0000644000000000000000000000013214505005532022265 xustar000000000000000030 mtime=1695812442.384981358 30 atime=1695812445.792030153 30 ctime=1695812494.647729865 yadifa-2.6.5-11201/lib/dnscore/src/packet_reader.c0000664000374500037450000010316414505005532022234 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnspacket DNS Messages * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include #include "dnscore/dnscore-config.h" #include "dnscore/packet_reader.h" //#include "dnscore/rfc.h" #include "dnscore/tsig.h" #if DNSCORE_HAS_CTRL #include "dnscore/ctrl-rfc.h" #endif #define TMP00003_TAG 0x3330303030504d54 ya_result packet_reader_read_fqdn(packet_unpack_reader_data* reader, u8 *output_buffer, u32 len_) { const u8 *p_limit = &reader->packet[reader->packet_size]; u8 *buffer = output_buffer; u8 *buffer_limit = &buffer[len_]; const u8 *p = &reader->packet[reader->offset]; /* ------------------------------------------------------------ */ if(p >= p_limit) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; /* EOF */ } for(;;) { u8 len = *p++; if((len & 0xc0) == 0xc0) { if(p >= p_limit) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; /* EOF */ } reader->offset = p - reader->packet; /* reposition the pointer */ u32 new_offset = len & 0x3f; new_offset <<= 8; new_offset |= *p; const u8* q = &reader->packet[new_offset]; if(q >= p) { return RCODE_ERROR_CODE(RCODE_FORMERR); } p = q; reader->offset++; break; } *buffer++ = len; if(len == 0) { reader->offset = p - reader->packet; return buffer - output_buffer; } if(p + len >= p_limit) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } if(buffer + len >= buffer_limit) { return BUFFER_WOULD_OVERFLOW; } /* MEMCOPY(buffer, p, len); buffer += len; p += len; */ u8* buffer_limit = &buffer[len]; do { *buffer++ = tolower(*p++); } while(buffer < buffer_limit); } for(;;) { u8 len = *p; if((len & 0xc0) == 0xc0) /* EDF: better yet: cmp len, 192; jge */ { /* reposition the pointer */ u32 new_offset = len & 0x3f; new_offset <<= 8; new_offset |= p[1]; const u8* q = &reader->packet[new_offset]; if(q < p) { p = q; continue; } return RCODE_ERROR_CODE(RCODE_FORMERR); } *buffer++ = len; if(len == 0) { return buffer - output_buffer; } ++p; if(p + len >= p_limit) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } if(buffer + len >= buffer_limit) { return BUFFER_WOULD_OVERFLOW; } u8* buffer_limit = &buffer[len]; do { *buffer++ = tolower(*p++); } while(buffer < buffer_limit); } // never reached } ya_result packet_reader_read(packet_unpack_reader_data* reader, void *output_buffer, u32 len) { u32 remaining = reader->packet_size - reader->offset; if(remaining >= len) { MEMCOPY(output_buffer, &reader->packet[reader->offset], len); reader->offset += len; return len; } else { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } } ya_result packet_reader_read_u16(packet_unpack_reader_data* reader, u16 *val) { yassert(val != NULL); u32 remaining = reader->packet_size - reader->offset; if(remaining >= 2) { *val = GET_U16_AT(reader->packet[reader->offset]); reader->offset += 2; return 2; } else { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } } ya_result packet_reader_skip_bytes(packet_unpack_reader_data* reader, u16 count) { u32 remaining = reader->packet_size - reader->offset; if(remaining >= count) { reader->offset += count; return count; } else { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } } ya_result packet_reader_read_dnstype(packet_unpack_reader_data* reader) { u32 remaining = reader->packet_size - reader->offset; if(remaining >= 2) { u16 dnstype = GET_U16_AT(reader->packet[reader->offset]); reader->offset += 2; return dnstype; } else { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } } ya_result packet_reader_read_dnsclass(packet_unpack_reader_data* reader) { u32 remaining = reader->packet_size - reader->offset; if(remaining >= 2) { u16 dnsclass = GET_U16_AT(reader->packet[reader->offset]); reader->offset += 2; return dnsclass; } else { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } } ya_result packet_reader_skip_query(packet_unpack_reader_data* reader, const u8 *domain, u16 dnstype, u16 dnsclass) { ya_result ret; u8 fqdn[MAX_DOMAIN_LENGTH]; if(ISOK(ret = packet_reader_read_fqdn(reader, fqdn, sizeof(fqdn)))) { if(dnsname_equals_ignorecase(domain, fqdn)) { if(FAIL(ret = packet_reader_read_dnstype(reader))) { return ret; } if(ret != dnstype) { return MESSAGE_UNEXPECTED_ANSWER_TYPE_CLASS; } if(FAIL(ret = packet_reader_read_dnsclass(reader))) { return ret; } if(ret != dnsclass) { return MESSAGE_UNEXPECTED_ANSWER_TYPE_CLASS; } } else { return MESSAGE_UNEXPECTED_ANSWER_DOMAIN; } } return ret; } ya_result packet_reader_read_u32(packet_unpack_reader_data* reader, u32 *val) { yassert(val != NULL); u32 remaining = reader->packet_size - reader->offset; if(remaining >= 4) { *val = GET_U32_AT(reader->packet[reader->offset]); reader->offset += 4; return 4; } else { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } } ya_result packet_reader_read_zone_record(packet_unpack_reader_data* reader, u8* output_buffer, u32 buffer_size) { ya_result ret; u8* buffer = output_buffer; /* Read the name */ if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, buffer_size))) { return ret; } buffer += ret; buffer_size -= ret; if(buffer_size >= 4) { /* read the TYPE CLASS (4 bytes) */ if(FAIL(ret = packet_reader_read(reader, buffer, 4))) // exact { return ret; } yassert(ret == 4); buffer += 4; return buffer - output_buffer; } else { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } } ya_result packet_reader_skip_zone_record(packet_unpack_reader_data* reader) { u32 from = reader->offset; ya_result ret; /* Read the name */ if(FAIL(ret = packet_reader_skip_fqdn(reader))) { return ret; } /* read the TYPE CLASS TTL RDATASIZE (4 bytes) */ if(FAIL(ret = packet_reader_skip(reader, 4))) { return ret; } return reader->offset - from; } ya_result packet_reader_skip_query_section(packet_unpack_reader_data* reader) { u32 from = reader->offset; u16 records = ntohs(MESSAGE_SECTION_COUNT(reader->packet, 0)); while(records > 0) { ya_result ret = packet_reader_skip_zone_record(reader); if(FAIL(ret)) { return ret; } --records; } return reader->offset - from; } ya_result packet_reader_skip_section(packet_unpack_reader_data* reader, int section) { switch(section) { case 0: { ya_result ret = packet_reader_skip_query_section(reader); return ret; } case 1: case 2: case 3: { s32 from = reader->offset; u16 records = MESSAGE_SECTION_COUNT(reader->packet, section); while(records > 0) { ya_result ret = packet_reader_skip_record(reader); if(FAIL(ret)) { return ret; } --records; } return reader->offset - from; } default: return INVALID_ARGUMENT_ERROR; } } ya_result packet_reader_read_rdata(packet_unpack_reader_data* reader, u16 type, s32 rdata_size, u8 *buffer, s32 buffer_size) { u8* rdata_start = buffer; const u32 rdata_limit = reader->offset + rdata_size; // without compression, this is where the rdata ends + 1 byte ya_result ret; if(packet_reader_available(reader) < rdata_size) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } switch(type) { /****************************************************************************** * The types that requires special handling (dname compression) ******************************************************************************/ case TYPE_MX: case TYPE_AFSDB: { u8 *p = buffer; buffer += 2; buffer_size -= 2; rdata_size -= 2; if(buffer_size == 0 || rdata_size > MAX_DOMAIN_LENGTH) { return INVALID_RECORD; /* wrong size */ } packet_reader_read_unchecked(reader, p, 2); // exact if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, buffer_size))) /* err = error code or bytes filled, not bytes read (compression) */ { return ret; } buffer += ret; break; } case TYPE_NS: case TYPE_CNAME: case TYPE_DNAME: case TYPE_PTR: case TYPE_MB: case TYPE_MD: case TYPE_MF: case TYPE_MG: case TYPE_MR: { /* ONE NAME record */ if(rdata_size == 0 || rdata_size > MAX_DOMAIN_LENGTH) { return INVALID_RECORD; /* wrong size */ } if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, buffer_size))) { return ret; } buffer += ret; break; } case TYPE_SOA: { /* NOTE: NO NEED TO SORT (There is only one) */ if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, buffer_size))) { return ret; } buffer += ret; buffer_size -= ret; if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, buffer_size))) { return ret; } if(rdata_limit - reader->offset != 20) { return INVALID_RECORD; } buffer_size -= ret; if(buffer_size < 20) { return BUFFER_WOULD_OVERFLOW; } buffer += ret; //len -= err; packet_reader_read_unchecked(reader, buffer, 20); // exact buffer += 20; break; } case TYPE_RRSIG: /* not supposed to be compressed */ { if(rdata_size > 2+1+1+4+4+4+2+256+1024+4) { return UNSUPPORTED_RECORD; /* too big */ } if(rdata_size < RRSIG_RDATA_HEADER_LEN) { return INVALID_RECORD; } packet_reader_read_unchecked(reader, buffer, RRSIG_RDATA_HEADER_LEN); // exact buffer += RRSIG_RDATA_HEADER_LEN; buffer_size -= RRSIG_RDATA_HEADER_LEN; if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, buffer_size))) { return ret; } buffer += ret; if(FAIL(ret = packet_reader_read(reader, buffer, rdata_limit - reader->offset))) // exact { return ret; } buffer += ret; break; } case TYPE_NSEC: /* not supposed to be compressed */ { if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, buffer_size))) { return ret; } buffer += ret; //len -= err; if(rdata_limit - reader->offset == 0) { return INVALID_RECORD; // record is broken } if(FAIL(ret = packet_reader_read(reader, buffer, rdata_limit - reader->offset))) // exact { return ret; } buffer += ret; break; } /****************************************************************************** * The types we reject ******************************************************************************/ case TYPE_SIG: { if(rdata_size > 1024) { return UNSUPPORTED_RECORD; /* key is too big */ } packet_reader_skip_unchecked(reader, rdata_size); // checked return UNSUPPORTED_TYPE; } case TYPE_A6: { if(rdata_size > 1+16+256) { return UNSUPPORTED_RECORD; /* key is too big */ } packet_reader_skip_unchecked(reader, rdata_size); // checked return UNSUPPORTED_TYPE; } /****************************************************************************** * The other types ******************************************************************************/ case TYPE_A: { if(rdata_size != 4) { return INCORRECT_IPADDRESS; } packet_reader_read_unchecked(reader, buffer, 4); // exact buffer += 4; break; } case TYPE_AAAA: { if(rdata_size != 16) { return INCORRECT_IPADDRESS; } packet_reader_read_unchecked(reader, buffer, 16); // exact buffer += 16; break; } /* case TYPE_HINFO: case TYPE_MINFO: case TYPE_DS: case TYPE_TXT: case TYPE_WKS: case TYPE_DNSKEY: case TYPE_NSEC3: case TYPE_NSEC3PARAM: case TYPE_LOC: */ default: { packet_reader_read_unchecked(reader, buffer, rdata_size); // exact // rdata_size has been checked for overflow already buffer += rdata_size; break; } } if(rdata_limit != reader->offset) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } return buffer - rdata_start; } /** * @note DOES NOT AND SHOULD NOT WORK FOR CTRL TYPES ! */ ya_result packet_reader_read_record(packet_unpack_reader_data* reader, u8* output_buffer, u32 len) { ya_result ret; u8* buffer = output_buffer; /* Read the name */ if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, len))) { return ret; } buffer += ret; len -= ret; if(len < 10) { return BUFFER_WOULD_OVERFLOW; } /* read the TYPE CLASS TTL RDATASIZE (10 bytes) */ ret = packet_reader_read(reader, buffer, 10); // exact if(FAIL(ret)) { return ret; } /* * ret always return either what was asked, either unexpected eof * if(ret != 10) * { * reader->offset = reader->packet_size; * return UNEXPECTED_EOF; * } */ u16 rdata_size = ntohs(GET_U16_AT(buffer[8])); if(rdata_size == 0) /* Can occur for dynupdate record set delete */ { return (buffer - output_buffer) + 10; } if(len < rdata_size) { return BUFFER_WOULD_OVERFLOW; } if(packet_reader_available(reader) < rdata_size) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } u16 rtype = (GET_U16_AT(buffer[0])); /** @note : NATIVETYPE */ buffer += 10; /* * EDF: No need to cut the len short, especially since what is returned * by the fqdn readers is the output side, not the input one (unpack) */ u8* rdata_start = buffer; u32 rdata_limit = reader->offset + rdata_size; switch(rtype) { /****************************************************************************** * The types that requires special handling (dname compression) ******************************************************************************/ case TYPE_MX: case TYPE_AFSDB: { u8 *p = buffer; buffer += 2; len -= 2; rdata_size -= 2; if(len == 0 || rdata_size > MAX_DOMAIN_LENGTH) { return INVALID_RECORD; /* wrong rdata_size */ } packet_reader_read_unchecked(reader, p, 2); // exact if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, len))) /* err = error code or bytes filled, not bytes read (compression) */ { return ret; } buffer += ret; break; } case TYPE_NS: case TYPE_CNAME: case TYPE_DNAME: case TYPE_PTR: case TYPE_MB: case TYPE_MD: case TYPE_MF: case TYPE_MG: case TYPE_MR: { /* ONE NAME record */ if((rdata_size == 0) || (rdata_size > MAX_DOMAIN_LENGTH)) { return INVALID_RECORD; /* wrong rdata_size */ } if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, len))) { return ret; } buffer += ret; break; } case TYPE_SOA: { /* NOTE: NO NEED TO SORT (There is only one) */ if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, len))) { return ret; } buffer += ret; len -= ret; if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, len))) { return ret; } if(rdata_limit - reader->offset != 20) { return INVALID_RECORD; } len -= ret; if(len < 20) { return BUFFER_WOULD_OVERFLOW; } buffer += ret; //len -= err; packet_reader_read_unchecked(reader, buffer, 20); // exact buffer += 20; break; } case TYPE_RRSIG: /* not supposed to be compressed */ { if(rdata_size > 2+1+1+4+4+4+2+256+1024+4) { return UNSUPPORTED_RECORD; /* too big */ } if(rdata_size < RRSIG_RDATA_HEADER_LEN) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } packet_reader_read_unchecked(reader, buffer, RRSIG_RDATA_HEADER_LEN); // exact buffer += RRSIG_RDATA_HEADER_LEN; len -= RRSIG_RDATA_HEADER_LEN; if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, len))) { return ret; } buffer += ret; if(FAIL(ret = packet_reader_read(reader, buffer, rdata_limit - reader->offset))) // exact { return ret; } buffer += ret; break; } case TYPE_NSEC: /* not supposed to be compressed */ { if(FAIL(ret = packet_reader_read_fqdn(reader, buffer, len))) { return ret; } buffer += ret; //len -= err; if(rdata_limit - reader->offset == 0) { return INVALID_RECORD; // record is broken } if(FAIL(ret = packet_reader_read(reader, buffer, rdata_limit - reader->offset))) // exact { return ret; } buffer += ret; break; } /****************************************************************************** * The types we reject ******************************************************************************/ case TYPE_SIG: { if(rdata_size > 1024) { return UNSUPPORTED_RECORD; /* key is too big */ } packet_reader_skip_unchecked(reader, rdata_size); // checked //buffer += err; return UNSUPPORTED_TYPE; } case TYPE_A6: { if(rdata_size > 1+16+256) { return UNSUPPORTED_RECORD; /* key is too big */ } packet_reader_skip_unchecked(reader, rdata_size); // checked return UNSUPPORTED_TYPE; } /****************************************************************************** * The other types ******************************************************************************/ case TYPE_A: { if(rdata_size != 4) { return INCORRECT_IPADDRESS; } packet_reader_read_unchecked(reader, buffer, 4); // exact buffer += 4; break; } case TYPE_AAAA: { if(rdata_size != 16) { return INCORRECT_IPADDRESS; } packet_reader_read_unchecked(reader, buffer, 16); // exact buffer += 16; break; } /* case TYPE_HINFO: case TYPE_MINFO: case TYPE_DS: case TYPE_TXT: case TYPE_WKS: case TYPE_DNSKEY: case TYPE_NSEC3: case TYPE_NSEC3PARAM: case TYPE_LOC: */ default: { packet_reader_read_unchecked(reader, buffer, rdata_size); // exact buffer += rdata_size; break; } } if(rdata_limit != reader->offset) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } SET_U16_AT(rdata_start[-2], htons(buffer - rdata_start)); /* rdata rdata_size */ /* * This len was the rdata_size but this was the packed rdata_size. * So I cannot compare without a relatively expensive test * yassert(len == 0); * */ return buffer - output_buffer; } ya_result packet_reader_read_dns_resource_record(packet_unpack_reader_data* reader, dns_resource_record *rr) { ya_result ret; if(ISOK(ret = packet_reader_read_fqdn(reader, rr->name, sizeof(rr->name)))) { rr->name_len = ret; if(ISOK(ret = packet_reader_read(reader, &rr->tctr, 10))) { u16 rdata_size = ntohs(rr->tctr.rdlen); dns_resource_record_ensure_size(rr, rdata_size); rr->rdata_size = rdata_size; u32 offset = reader->offset; while((ret = packet_reader_read_rdata(reader, rr->tctr.qtype, rdata_size, rr->rdata, rr->rdata_buffer_size)) == BUFFER_WOULD_OVERFLOW) { dns_resource_record_ensure_size(rr, MIN((MAX_DOMAIN_LENGTH + 7) & ~7, MAX(rr->rdata_buffer_size * 2, 65535))); reader->offset = offset; } } } return ret; } void packet_reader_rewind(packet_unpack_reader_data* reader) { reader->offset = 0; } /* * Skip a compressed fqdn */ ya_result packet_reader_skip_fqdn(packet_unpack_reader_data* reader) { /* Testing for a minimum len size is pointless */ u32 from = reader->offset; const u8* p_limit = &reader->packet[reader->packet_size]; const u8* p = &reader->packet[reader->offset]; if(p >= p_limit) { return UNEXPECTED_EOF; /* EOF */ } for(;;) { u8 len = *p++; if((len & 0xc0) == 0xc0) { p++; reader->offset = p - reader->packet; return reader->offset - from; } if(len == 0) { reader->offset = p - reader->packet; return reader->offset - from; } if(p + len >= p_limit) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } p += len; } } /* * Skip a record */ ya_result packet_reader_skip_record(packet_unpack_reader_data* reader) { ya_result err; ya_result from = reader->offset; /* Read the name */ if(FAIL(err = packet_reader_skip_fqdn(reader))) { return err; } /* read the TYPE CLASS TTL RDATASIZE (10 bytes) */ u16 size = ntohs(GET_U16_AT(reader->packet[reader->offset + 8])); u32 next_offset = reader->offset + 10 + size; if(next_offset > reader->packet_size) { reader->offset = reader->packet_size; return UNEXPECTED_EOF; } reader->offset = next_offset; /* * This len was the rdata_size but this was the packed size. * So I cannot compare without a relatively expensive test * yassert(len == 0); * */ return reader->offset - from; } #if DNSCORE_HAS_CTRL /** * * Returns true iff the string txt is utf-8 * The current implementation checks it's ASCII7 (which is a valid subset of utf-8) * * @param txt * @param len * @return */ static bool is_utf8(const char *txt, u16 len) { for(u16 i = 0; i < len; i++) { if((txt[i] & 0x80) != 0) { return FALSE; } } return TRUE; } /** * * @note Yes, this COULD go in the message.* files, once they are finalised * * @param reader * @param rdatasize * @param rclass * @param txt * @param dryrun * @return */ ya_result packet_reader_read_utf8(packet_unpack_reader_data *reader, u16 rdatasize, u16 rclass, char **txt, bool dryrun) { char *tmp = NULL; ya_result return_value; if(rclass == CLASS_ANY) { if(rdatasize != 0) { return RCODE_ERROR_CODE(RCODE_FORMERR); /* formerr */ } if(!dryrun) { free(*txt); *txt = NULL; } return_value = SUCCESS; } else { MALLOC_OR_DIE(char *, tmp, rdatasize + 1, TMP00003_TAG); if(ISOK(packet_reader_read(reader, (u8*)tmp, rdatasize))) { tmp[rdatasize] = '\0'; if(is_utf8(tmp, rdatasize)) { return_value = SUCCESS; if(!dryrun) { if(rclass != CLASS_NONE) { if(*txt != NULL) { free(*txt); } *txt = tmp; tmp = NULL; } else { if(*txt != NULL) { if(strcmp(*txt, tmp) == 0) { free(*txt); *txt = NULL; } } } } } else { return_value = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } else { return_value = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(tmp != NULL) { free(tmp); } } return return_value; } /** * * @note Yes, this COULD go in the message.* files, once they are finalised * * @param reader * @param rdatasize * @param rclass * @param ha * @param dryrun * @return */ ya_result packet_reader_read_remote_server(packet_unpack_reader_data *reader, u16 rdatasize, u16 rclass, host_address **ha, bool dryrun) { u16 ip_port = 0; u8 ipver; u8 flags; u8 ip_buffer[16]; u8 tsig_name[MAX_DOMAIN_LENGTH]; if(rclass == CLASS_ANY) { if(rdatasize != 0) { return RCODE_ERROR_CODE(RCODE_FORMERR); /* formerr */ } if(!dryrun) { if(*ha != NULL) { host_address_delete_list(*ha); *ha = NULL; } } return SUCCESS; } ya_result return_value; if(ISOK(return_value = packet_reader_read(reader, &flags, 1))) { return_value = INVALID_STATE_ERROR; ipver = flags & REMOTE_SERVER_FLAGS_IP_MASK; if((ipver == HOST_ADDRESS_IPV4) || (ipver == HOST_ADDRESS_IPV6)) { tsig_item *tsig = NULL; if(ipver == HOST_ADDRESS_IPV4) { return_value = packet_reader_read(reader, ip_buffer, 4); } else { return_value = packet_reader_read(reader, ip_buffer, 16); } if(FAIL(return_value)) { return return_value; } if((flags & REMOTE_SERVER_FLAGS_PORT_MASK) != 0) { if(FAIL(return_value = packet_reader_read_u16(reader, &ip_port))) { return return_value; } } if((flags & REMOTE_SERVER_FLAGS_KEY_MASK) != 0) { if(FAIL(return_value = packet_reader_read_fqdn(reader, tsig_name, sizeof(tsig_name)))) { return return_value; } if((tsig = tsig_get(tsig_name)) == NULL) { return RCODE_ERROR_CODE(RCODE_BADKEY); } } if(!dryrun) { host_address *address; MALLOC_OBJECT_OR_DIE(address, host_address, HOSTADDR_TAG); address->next = NULL; address->tsig = tsig; if(ipver == HOST_ADDRESS_IPV4) { memcpy(address->ip.v4.bytes, ip_buffer, 4); address->port = ip_port; address->version = HOST_ADDRESS_IPV4; } else // HOST_ADDRESS_IPV6: { memcpy(address->ip.v6.bytes, ip_buffer, 16); address->port = ip_port; address->version = HOST_ADDRESS_IPV6; } /* * Here the rclass changes the behaviour */ if(rclass != CLASS_NONE) { if(*ha == NULL) { *ha = address; } else { host_address_append_host_address(*ha, address); // copy made, or may fail is address is not supported free(address); } } else { host_address_remove_host_address(ha, address); /* not freed */ free(address); } return_value = SUCCESS; } } } return return_value; } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/packet_writer.c0000644000000000000000000000013214505005532022337 xustar000000000000000030 mtime=1695812442.424981931 30 atime=1695812445.793030168 30 ctime=1695812494.649729894 yadifa-2.6.5-11201/lib/dnscore/src/packet_writer.c0000664000374500037450000003201414505005532022301 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnspacket DNS Messages * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/packet_writer.h" #include "dnscore/dnsname.h" #include "dnscore/logger.h" #include "dnscore/message.h" #include "dnscore/rfc.h" #include "dnscore/dns_resource_record.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define PACKET_COMPRESSION_DEBUG 0 /* * */ ya_result packet_writer_init(packet_writer* pc, u8* packet, u32 packet_offset, u32 size_limit) { pc->pool_head = pc->pool; pc->head = NULL; packet_dictionary_node* child_node = NULL; u32 offset = DNS_HEADER_LENGTH; u8* fqdn = &packet[offset]; while(*fqdn != 0) { packet_dictionary_node* node = pc->pool_head++; node->next = NULL; node->child = child_node; node->label = fqdn; node->offset = offset; u8 len = fqdn[0] + 1; fqdn += len; offset += len; child_node = node; } #if DEBUG fqdn += 1 + 2 + 2; if(packet_offset < fqdn - packet) { log_err("packet_writer_init expected %u = %u", packet_offset, fqdn - packet); } #endif pc->head = child_node; pc->packet = packet; pc->packet_offset = packet_offset; pc->packet_limit = size_limit; return SUCCESS; } void packet_writer_create(packet_writer* pc, u8* packet, u32 limit) { pc->pool_head = pc->pool; pc->head = NULL; pc->packet = packet; pc->packet_offset = DNS_HEADER_LENGTH; pc->packet_limit = limit; } ya_result packet_writer_add_fqdn_uncompressed(packet_writer* pc, const u8* fqdn) { pc->packet_offset += dnsname_copy(&pc->packet[pc->packet_offset], fqdn); return pc->packet_offset; } #if PACKET_COMPRESSION_DEBUG static char packet_writer_dictionary_node_log_spaces[129] = { '>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ', '>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ', '>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ', '>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ', '>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ', '>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ', '>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ', '>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ','>',' ',' ',' ', 0 }; static void packet_writer_dictionary_node_log(packet_dictionary_node* node, int spaces, dnsname_stack *fqdnp) { while(node != NULL) { dnsname_stack_push_label(fqdnp, node->label); log_debug2("%p [%4i] %04x %s %{dnslabel} : %{dnsnamestack}", node, spaces, node->offset, &packet_writer_dictionary_node_log_spaces[sizeof(packet_writer_dictionary_node_log_spaces) - 1 - 4 * spaces], node->label, fqdnp); packet_dictionary_node* child = node->child; if(child != NULL) { do { packet_writer_dictionary_node_log(child, spaces + 1, fqdnp); child = child->child; } while(child != NULL); } dnsname_stack_pop_label(fqdnp); node = node->next; } } static void packet_writer_dictionary_log(packet_writer* pc) { dnsname_stack fqdn; fqdn.size = -1; packet_dictionary_node* node = pc->head; log_debug2("packet_writer_dictionary_log(%p)", pc); packet_writer_dictionary_node_log(node, 0, &fqdn); } #endif // PACKET_COMPRESSION_DEBUG ya_result packet_writer_add_fqdn(packet_writer* pc, const u8* fqdn) { #if PACKET_COMPRESSION_DEBUG log_debug2("packet_writer_add_fqdn(%p, %{dnsname} @ %04x)", pc, fqdn, pc->packet_offset); #endif dnslabel_vector name; s32 top = dnsname_to_dnslabel_vector(fqdn, name); s32 best_top = top + 1; packet_dictionary_node* best = NULL; packet_dictionary_node* node = pc->head; u8 *packet_base = pc->packet; u32 offset = pc->packet_offset; u32 limit = pc->packet_limit; /* Look for the name in the compression dictionary */ if((node != NULL) && (top >= 0)) { for(;;) { if(dnslabel_equals_ignorecase_left(name[top], node->label)) { /* we got a match on this level */ best = node; best_top = top; node = node->child; if(node == NULL) { break; } if(--top < 0) { break; } } else if((node = node->next) == NULL) { break; } } } /* Every label in the interval [0;best_top is new */ /* Create a compression dictionary entry for each of them * along with their writing. */ packet_dictionary_node* child_node = NULL; u8* packet = &packet_base[offset]; if(best_top > 0) { top = 0; if(offset < 0x3ffe) { do { u8 len = name[top][0] + 1; if(offset + len >= limit) { return BUFFER_WOULD_OVERFLOW; } MEMCOPY(packet, name[top], len); node = pc->pool_head++; node->next = NULL; node->child = child_node; node->label = packet; node->offset = offset; child_node = node; packet += len; offset += len; } while(++top < best_top); if(offset >= 0x4000) { child_node = NULL; } } else { do { u8 len = name[top][0] + 1; if(offset + len >= limit) { return BUFFER_WOULD_OVERFLOW; } MEMCOPY(packet, name[top], len); packet += len; offset += len; } while(++top < best_top); } } if(best != NULL) { /* found a (partial) match */ /* Add the new chain to the parent */ if(offset + 2 >= limit) { return BUFFER_WOULD_OVERFLOW; } if(child_node != NULL) { child_node->next = best->child; best->child = child_node; } *packet++ = (best->offset >> 8) | 0xc0; *packet = (best->offset & 0xff); offset += 2; } else { /* create a new entry */ /* child_node can be null if we tried to write something beyond the * 16KB limit * */ if(offset + 1 >= limit) { return BUFFER_WOULD_OVERFLOW; } if(child_node != NULL) { child_node->next = pc->head; pc->head = child_node; } *packet = 0; offset++; } pc->packet_offset = offset; #if PACKET_COMPRESSION_DEBUG packet_writer_dictionary_log(pc); log_debug2("packet_writer_add_fqdn(%p, %{dnsname}) = %i", pc, fqdn, offset); #endif return offset; } ya_result packet_writer_add_rdata(packet_writer* pc, u16 rr_type, const u8* rdata, u16 rdata_size) { yassert(pc->packet_offset + rdata_size < pc->packet_limit); u32 offset = pc->packet_offset; pc->packet_offset += 2; switch(rr_type) { case TYPE_MX: packet_writer_add_bytes(pc, rdata, 2); rdata += 2; /* Fallthrough */ case TYPE_NS: case TYPE_CNAME: case TYPE_DNAME: case TYPE_PTR: case TYPE_MB: case TYPE_MD: case TYPE_MF: case TYPE_MG: case TYPE_MR: /* ONE NAME record */ { packet_writer_add_fqdn(pc, rdata); packet_writer_set_u16(pc, htons(pc->packet_offset - offset - 2), offset); break; } case TYPE_SOA: { u32 len1 = dnsname_len(rdata); packet_writer_add_fqdn(pc, rdata); rdata += len1; u32 len2 = dnsname_len(rdata); packet_writer_add_fqdn(pc, rdata); rdata += len2; packet_writer_add_bytes(pc, rdata, 20); packet_writer_set_u16(pc, htons(pc->packet_offset - offset - 2), offset); break; } default: { packet_writer_set_u16(pc, htons(rdata_size), offset); packet_writer_add_bytes(pc, rdata, rdata_size); break; } } /* switch(type) */ return pc->packet_offset; } ya_result packet_writer_encode_base32hex_digest(packet_writer *pw, const u8 *digest) { pw->packet[pw->packet_offset++] = BASE32HEX_ENCODED_LEN(SHA_DIGEST_LENGTH); /*u32 b32_len =*/ base32hex_lc_encode(digest, SHA_DIGEST_LENGTH, (char*)&pw->packet[pw->packet_offset]); pw->packet_offset += BASE32HEX_ENCODED_LEN(SHA_DIGEST_LENGTH); return BASE32HEX_ENCODED_LEN(SHA_DIGEST_LENGTH) + 1; } /** * Writes the content of the buffer of a packet writer to a TCP output stream, * that is: first the size of the buffer in network endiant 16 bits followed * by the actual content of the buffer * * @param pw the packet writer whose content needs to be written * @param tcpos the TCP output stream * * @return an error code or the size of the buffer */ ya_result write_tcp_packet(packet_writer *pw, output_stream *tcpos) { int n; if(FAIL(n = output_stream_write_nu16(tcpos, pw->packet_offset))) { return n; } if(FAIL(n = output_stream_write(tcpos, pw->packet, pw->packet_offset))) { return n; } return n; } ya_result packet_writer_add_record(packet_writer* pw, const u8* fqdn, u16 rr_type, u16 rr_class, u32 rr_ttl, const u8* rdata, u16 rdata_size) { ya_result return_code; u32 offset = pw->packet_offset; if(ISOK(return_code = packet_writer_add_fqdn(pw, fqdn))) { if(pw->packet_limit - pw->packet_offset >= 10) { packet_writer_add_u16(pw, rr_type); packet_writer_add_u16(pw, rr_class); packet_writer_add_u32(pw, rr_ttl); if(ISOK(return_code = packet_writer_add_rdata(pw, rr_type, rdata, rdata_size))) { return pw->packet_offset; } } } pw->packet_offset = offset; return return_code; } ya_result packet_writer_add_dnsrr(packet_writer *pw, dns_resource_record* dns_rr) { ya_result return_code; u32 offset = pw->packet_offset; if(ISOK(return_code = packet_writer_add_fqdn(pw, dns_rr->name))) { if(pw->packet_limit - pw->packet_offset >= 10) { packet_writer_add_u16(pw, dns_rr->tctr.qtype); packet_writer_add_u16(pw, dns_rr->tctr.qclass); packet_writer_add_u32(pw, dns_rr->tctr.ttl); if(ISOK(return_code = packet_writer_add_rdata(pw, dns_rr->tctr.qtype, dns_rr->rdata, dns_rr->rdata_size))) { return pw->packet_offset; } } } pw->packet_offset = offset; return return_code; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/parser.c0000644000000000000000000000013214505005532020770 xustar000000000000000030 mtime=1695812442.473982632 30 atime=1695812445.795030196 30 ctime=1695812494.651729922 yadifa-2.6.5-11201/lib/dnscore/src/parser.c0000664000374500037450000012122214505005532020732 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include //#include #include #include #include "dnscore/timems.h" #include "dnscore/logger.h" #include "dnscore/file_output_stream.h" #include "dnscore/file_input_stream.h" #include "dnscore/logger_channel_stream.h" #include "dnscore/buffer_input_stream.h" #include "dnscore/base16.h" #include "dnscore/base32hex.h" #include "dnscore/base64.h" #include "dnscore/parser.h" #include "dnscore/ptr_set.h" #include "dnscore/mutex.h" #define DO_PRINT 0 #define DO_BUFFERIZE 1 #define PARSER_STREAM_BUFFER_SIZE 4096 static const char eol_park_needle[2] = {' ', '\0'}; static bool parser_init_error_codes_done = FALSE; static inline ya_result parser_set_couples(parser_s *parser, const char* input, u8 kind, u8 closer_kind) { u32 n = strlen(input); if((n & 1) != 0) { return PARSER_ODD_CHAR_NUMBER; } for(u32 i = 0; i < n; i+= 2) { parser->char_type[(u8)input[i]] = kind; if(closer_kind != PARSER_CHAR_TYPE_IGNORE) { parser->char_type[(u8)input[i + 1]] = closer_kind; } parser->delimiter_close[(u8)input[i]] = input[i + 1]; } return n>>1; } static inline u32 parser_set_singleton(parser_s *parser, const char* input, u8 kind) { u32 n = strlen(input); for(u32 i = 0; i < n; i++) { parser->char_type[(u8)input[i]] = kind; } return n; } void parser_init_error_codes() { if(parser_init_error_codes_done) { return; } parser_init_error_codes_done = TRUE; error_register(PARSER_SYNTAX_ERROR_MULTILINE,"PARSER_SYNTAX_ERROR_MULTILINE"); error_register(PARSER_SYNTAX_ERROR_EXPECTED_EOL,"PARSER_SYNTAX_ERROR_EXPECTED_EOL"); error_register(PARSER_SYNTAX_ERROR_LINE_TOO_BIG,"PARSER_SYNTAX_ERROR_LINE_TOO_BIG"); error_register(PARSER_BUFFER_TOO_SMALL,"PARSER_BUFFER_TOO_SMALL"); error_register(PARSER_NO_INPUT,"PARSER_NO_INPUT"); error_register(PARSER_ODD_CHAR_NUMBER,"PARSER_ODD_CHAR_NUMBER"); error_register(PARSER_LINE_ENDED_WITH_ESCAPE,"PARSER_LINE_ENDED_WITH_ESCAPE"); error_register(PARSER_UNEXPECTED_STRING_DELIMITER,"PARSER_UNEXPECTED_STRING_DELIMITER"); error_register(PARSER_EXPECTED_STRING_END_DELIMITER,"PARSER_EXPECTED_STRING_END_DELIMITER"); error_register(PARSER_INCLUDE_DEPTH_TOO_BIG,"PARSER_INCLUDE_DEPTH_TOO_BIG"); error_register(PARSER_UNKNOWN_TIME_UNIT,"PARSER_UNKNOWN_TIME_UNIT"); error_register(PARSER_NO_MARK_SET,"PARSER_NO_MARK_SET"); error_register(PARSER_REACHED_END_OF_LINE,"PARSER_REACHED_END_OF_LINE"); error_register(PARSER_FOUND_WORD,"PARSER_FOUND_WORD"); error_register(PARSER_REACHED_END_OF_FILE, "PARSER_REACHED_END_OF_FILE"); error_register(PARSER_INVALID_ESCAPED_FORMAT, "PARSER_INVALID_ESCAPED_FORMAT"); } ya_result parser_init(parser_s *parser, const char *string_delimiters, // by 2 const char *multiline_delimiters, // by 2 const char *comment_markers, // by 1 const char *blank_makers, // by 1 const char *escape_characters // by 1 ) { ya_result return_code = SUCCESS; /// @note may be improved if we spawn parser a lot ZEROMEMORY(parser, sizeof(parser_s)); // if(ISOK(return_code = parser_set_couples(parser, string_delimiters, PARSER_CHAR_TYPE_STRING_DELIMITER, PARSER_CHAR_TYPE_IGNORE))) { parser->string_delimiters_count = return_code; if(ISOK(return_code = parser_set_couples(parser, multiline_delimiters, PARSER_CHAR_TYPE_MULTILINE_DELIMITER, PARSER_CHAR_TYPE_MULTILINE_DELIMITER_END))) { parser->multiline_delimiters_count = return_code; parser->comment_marker_count = parser_set_singleton(parser, comment_markers, PARSER_CHAR_TYPE_COMMENT_MARKER); parser->comment_marker = comment_markers; parser->blank_marker_count = parser_set_singleton(parser, blank_makers, PARSER_CHAR_TYPE_BLANK_MARKER); parser->blank_marker = blank_makers; parser->escape_characters_count =parser_set_singleton(parser, escape_characters, PARSER_CHAR_TYPE_ESCAPE_CHARACTER); parser->escape_characters = escape_characters; parser->close_last_stream = TRUE; parser_set_singleton(parser, "\n", PARSER_CHAR_TYPE_EOL); } } return return_code; } ya_result parser_finalize(parser_s *parser) { for(;;) { input_stream *is = parser_pop_stream(parser); if(is == NULL) { break; } if((parser->input_stream_stack_size == 0) && !parser->close_last_stream) { break; } input_stream_close(is); input_stream_set_void(is); } return SUCCESS; } static inline u32 parser_line_size(parser_s *parser) { return (u32)(parser->limit - parser->needle); } static inline ya_result parser_clear_escape_codes(char **startp, int *lenp, char escape_char, char *new_start) { char *start = *startp; char *escape_char_ptr; int len = *lenp; if((escape_char_ptr = memchr(start, escape_char, len)) != NULL) { char *op = new_start; for(;;) { size_t n = escape_char_ptr - start; // is the escape code is at the last position ? if(n + 1 == (size_t)len) { // oops return PARSER_LINE_ENDED_WITH_ESCAPE; } memcpy(op, start, n); char c = escape_char_ptr[1]; if((c >= '0') && (c <= '2')) { if(n + 3 < (size_t)len) { u32 decimal_char = (c - '0') * 100; c = escape_char_ptr[2]; if((c >= '0') && (c <= '9')) { decimal_char += (c - '0') * 10; c = escape_char_ptr[3]; if((c >= '0') && (c <= '9')) { decimal_char += (c - '0'); if(decimal_char <= 255) { op[n] = (u8)decimal_char; op += n + 1; start = escape_char_ptr + 4; len -= n + 4; } else { return PARSER_INVALID_ESCAPED_FORMAT; } } else { return PARSER_INVALID_ESCAPED_FORMAT; } } else { return PARSER_INVALID_ESCAPED_FORMAT; } } else { return PARSER_INVALID_ESCAPED_FORMAT; } } else { op[n] = c; op += n + 1; start = escape_char_ptr + 2; len -= n + 2; } yassert(len >= 0); if(len == 0) { break; } if((escape_char_ptr = memchr(start, escape_char, len)) == NULL) { // copy the remaining bytes memcpy(op, start, len); op += len; break; } } *startp = new_start; *lenp = op - new_start; } // else we have nothing more to do return len; } /** * * returns the token type * * @param parser * @return */ static inline ya_result parser_read_line(parser_s *parser) { ya_result return_code; if(parser_line_size(parser) == 0) { // read next line if(parser->input_stream_stack_size == 0) { return_code = PARSER_NO_INPUT; // no input file/stream return return_code; } char *buffer = parser->line_buffer; char *limit = &parser->line_buffer[sizeof(parser->line_buffer)]; for(;;) { if(limit - buffer == 0) { return PARSER_SYNTAX_ERROR_LINE_TOO_BIG; } #if DO_BUFFERIZE return_code = buffer_input_stream_read_line(parser->input_stream_stack[parser->input_stream_stack_size - 1], buffer, limit - buffer); #else return_code = input_stream_read_line(parser->input_stream_stack[parser->input_stream_stack_size - 1], buffer, limit - buffer); #endif if(return_code > 0) { // one line has been read (maybe) buffer += return_code; if(return_code > 1) { if(buffer[-2] == parser->escape_characters[0]) { // the EOL was escaped, concat the next line ... // do NOT remove the escape code now continue; } } parser->limit = buffer; parser->needle = parser->line_buffer; parser->line_number++; } else { // error or end of stream parser->limit = parser->line_buffer; parser->needle = parser->line_buffer; if(return_code == 0) { if(parser->multiline != 0) { return_code = PARSER_SYNTAX_ERROR_MULTILINE; } } } return return_code; } } return PARSER_EOF; } ya_result parser_next_token(parser_s *parser) { ya_result return_code; for(;;) { if((return_code = parser_read_line(parser)) <= 0) { if(return_code == 0) { return PARSER_EOF; } return return_code; } // there are bytes return_code = 0; for(char *needle = parser->needle; needle < parser->limit; needle++) { u8 b = (u8)*needle; // test for multiline close bool has_escapes = FALSE; switch(parser->char_type[b]) { #if DNSCORE_HAS_FULL_ASCII7 case PARSER_CHAR_TYPE_TO_TRANSLATE: *needle = parser->translation_table[b]; --needle; FALLTHROUGH // fall through #endif case PARSER_CHAR_TYPE_ESCAPE_CHARACTER: // the text starts after the next char, whatever it is if(++needle < parser->limit) { if((*needle >= '0') && (*needle <= '2')) { // octal byte if(needle + 2 < parser->limit) { //u8 octal_char = ((*needle) - '0') * 100; ++needle; if((*needle >= '0') && (*needle <= '9')) { //octal_char |= ((*needle) - '0') * 10; ++needle; if((*needle >= '0') && (*needle <= '9')) { //octal_char |= ((*needle) - '0'); needle -= 3; has_escapes = TRUE; // the buffer needs to be copied } else { // octal parse error return PARSER_INVALID_ESCAPED_FORMAT; } } else { // octal parse error return PARSER_INVALID_ESCAPED_FORMAT; } } else { // octal parse error return PARSER_INVALID_ESCAPED_FORMAT; } } } FALLTHROUGH // fall through case PARSER_CHAR_TYPE_NORMAL: { // BLANK or MULTI => done // STRING => error // COMMENT => CUT parser->text = needle++; for(; needle < parser->limit; needle++) { b = (u8)*needle; switch(parser->char_type[b]) { case PARSER_CHAR_TYPE_MULTILINE_DELIMITER_END: { if((parser->multiline) != 0 && (b == parser->multiline)) { b = ' '; *needle = b; parser->multiline = 0; } else { return PARSER_SYNTAX_ERROR_MULTILINE; } // we got the whole word parser->text_length = needle - parser->text; parser->needle = needle + 1; goto parser_next_token_end_of_token_found; /********* GOTO G O T O GOTO **********/ } case PARSER_CHAR_TYPE_MULTILINE_DELIMITER: { if(parser->multiline == 0) { parser->multiline = parser->delimiter_close[b]; } else { return PARSER_SYNTAX_ERROR_MULTILINE; } *needle = ' '; // we got the whole word parser->text_length = needle - parser->text; parser->needle = needle + 1; goto parser_next_token_end_of_token_found; /********* GOTO G O T O GOTO **********/ } case PARSER_CHAR_TYPE_EOL: { // only tell we got an EOL if we are not on "multiline" if(parser->multiline != 0) { *needle = ' '; } // we got the whole word parser->text_length = needle - parser->text; parser->needle = needle; goto parser_next_token_end_of_token_found; /********* GOTO G O T O GOTO **********/ } case PARSER_CHAR_TYPE_BLANK_MARKER: { // we got the whole word parser->text_length = needle - parser->text; parser->needle = needle + 1; goto parser_next_token_end_of_token_found; /********* GOTO G O T O GOTO **********/ } case PARSER_CHAR_TYPE_ESCAPE_CHARACTER: { needle++; has_escapes = TRUE; break; } case PARSER_CHAR_TYPE_COMMENT_MARKER: { // we got the whole word parser->text_length = needle - parser->text; parser->needle = needle; goto parser_next_token_end_of_token_found; /********* GOTO G O T O GOTO **********/ } case PARSER_CHAR_TYPE_STRING_DELIMITER: { // parse error if(!parser->tokenize_on_string) { return PARSER_UNEXPECTED_STRING_DELIMITER; } parser->text_length = needle - parser->text; parser->needle = needle; goto parser_next_token_end_of_token_found; /********* GOTO G O T O GOTO **********/ } #if DNSCORE_HAS_FULL_ASCII7 case PARSER_CHAR_TYPE_TO_TRANSLATE: { *needle = parser->translation_table[b]; break; } #endif //case PARSER_CHAR_TYPE_NORMAL: default: { break; } } // end switch char type } // end for needle parser_next_token_end_of_token_found: ; // at this point we have a full token (maybe still escaped) int token_len = needle - parser->text; if(has_escapes) { yassert(parser->escape_characters_count <= 1); if(parser->escape_characters_count == 1) { ya_result err; char escape_char = parser->escape_characters[0]; if(FAIL(err = parser_clear_escape_codes(&parser->text, &token_len, escape_char, parser->extra_buffer))) { return err; } } } parser->text_length = token_len; parser->needle = needle; return return_code | PARSER_WORD; } case PARSER_CHAR_TYPE_COMMENT_MARKER: { // cut line parser->text = needle; parser->text_length = parser->limit - needle; parser->needle = parser->limit; if(parser->multiline == 0) { parser->needle_mark = NULL; return return_code | PARSER_COMMENT | PARSER_EOL; } else { return return_code | PARSER_COMMENT; } } case PARSER_CHAR_TYPE_MULTILINE_DELIMITER_END: { if((parser->multiline) != 0 && (b == parser->multiline)) { /*b = ' '; *needle = b;*/ parser->multiline = 0; } else { return PARSER_SYNTAX_ERROR_MULTILINE; } break; } case PARSER_CHAR_TYPE_STRING_DELIMITER: { // find the end char ... // note: see strpbrk char end_char = parser->delimiter_close[b]; char *string_start = ++needle; char *string_end; for(;;) { string_end = memchr(needle, end_char, parser->limit - needle); if(string_end != NULL) { // this one may have been escaped /// @note 20190917 edf -- Patch submitted trough github by JZerf /// This fixes the case of escaped escapes as well as an incorrect limit test /// The patch has been slightly adapted in 2.4.x but may be kept as it is in 2.3.x /* Check if the string delimiter that was found was escaped. Keep in * mind that if there was an escape character in front of the string * delimiter, the escape character itself could have also been escaped * (and the one before that and the one before that...). What we can do * is check to see how many consecutive preceding escape characters * there are (by finding the first preceding nonescape character or the * opening string delimiter if there isn't one) and if it's an even * number then the string delimiter we found is unescaped but if it's an * odd number then it is escaped. Note that this will need to be revised * if YADIDA later adds support for using \DDD type escape sequences * between string delimiters. */ /// @note 20190917 edf -- while => do-while : I've kept the first if out of the loop to avoid needlessly /// testing for the needle. (Which should be the most common case) const char *prior_nonescape_character = string_end - 1; do { if(parser->char_type[(u8)*prior_nonescape_character] != PARSER_CHAR_TYPE_ESCAPE_CHARACTER) { break; } } while(--prior_nonescape_character >= needle); // this one was escaped ... if(((string_end - prior_nonescape_character) & 1) == 1) { break; /* String delimiter was not escaped if we got here. */ } string_end++; // needle = string_end + 1 and try again ? if(string_end >= parser->limit) { return PARSER_EXPECTED_STRING_END_DELIMITER; } needle = string_end; } else { // syntax error return PARSER_EXPECTED_STRING_END_DELIMITER; } } int token_len = string_end - string_start; yassert(parser->escape_characters_count <= 1); for(u32 escape_index = 0; escape_index < parser->escape_characters_count; escape_index++) { ya_result err; char escape_char = parser->escape_characters[escape_index]; if(FAIL(err = parser_clear_escape_codes(&string_start, &token_len, escape_char, parser->extra_buffer))) { return err; } } parser->text = string_start; parser->text_length = token_len; parser->needle = string_end + 1; // end of token ... return ? return return_code | PARSER_WORD; } case PARSER_CHAR_TYPE_MULTILINE_DELIMITER: { if(parser->multiline == 0) { parser->multiline = parser->delimiter_close[b]; } else { return PARSER_SYNTAX_ERROR_MULTILINE; } *needle = ' '; break; } case PARSER_CHAR_TYPE_EOL: { // only tell we got an EOL if we are not on "multiline" if(parser->multiline == 0) { parser->needle = parser->limit; parser->text_length = 0; parser->needle_mark = NULL; return PARSER_EOL; } *needle = ' '; } FALLTHROUGH // fall through case PARSER_CHAR_TYPE_BLANK_MARKER: { return_code |= PARSER_BLANK_START; break; } } } // reached the end of line without a token : EOL // if we are not on a multiline: return EOL parser->needle = parser->limit; parser->text_length = 0; if(parser->multiline == 0) { return PARSER_EOL; } // else read the next line (loop) } // never reached // return 0; } void parser_set_eol(parser_s *parser) { parser->needle = (char*)&eol_park_needle[0]; parser->limit = (char*)&eol_park_needle[1]; } #if DNSCORE_HAS_FULL_ASCII7 void parser_add_translation(parser_s *parser, u8 character, u8 translates_into) { parser->translation_table[character] = translates_into; parser->char_type[character] = PARSER_CHAR_TYPE_TO_TRANSLATE; } void parser_del_translation(parser_s *parser, u8 character) { parser->char_type[character] = PARSER_CHAR_TYPE_NORMAL; } #endif ya_result parser_next_characters(parser_s *parser) { parser->text = parser->needle; parser->text_length = parser->limit - parser->needle; if(parser->multiline != 0) { u32 offset = parser->text_length; memcpy(parser->additional_buffer, parser->text, offset); parser->additional_buffer[offset++] = ' '; ya_result ret; do { ret = parser_next_token(parser); const char *text = parser_text(parser); size_t text_length = parser_text_length(parser); size_t new_length = offset + text_length + 1; if(new_length > sizeof(parser->additional_buffer)) { return PARSER_SYNTAX_ERROR_LINE_TOO_BIG; } memcpy(&parser->additional_buffer[offset], text, text_length); offset = new_length; parser->additional_buffer[offset - 1] = ' '; } while((ret & (PARSER_EOF|PARSER_EOL)) == 0); parser->text = parser->additional_buffer; parser->text_length = offset - 1; } parser->needle = (char*)&eol_park_needle[0]; parser->limit = (char*)&eol_park_needle[1]; return parser->text_length; } ya_result parser_next_characters_nospace(parser_s *parser) { parser->text = parser->needle; parser->text_length = parser->limit - parser->needle; if(parser->multiline != 0) { u32 offset = parser->text_length; memcpy(parser->additional_buffer, parser->text, offset); ya_result ret; do { ret = parser_next_token(parser); const char *text = parser_text(parser); size_t text_length = parser_text_length(parser); size_t new_length = offset + text_length; if(new_length > sizeof(parser->additional_buffer)) { return PARSER_SYNTAX_ERROR_LINE_TOO_BIG; } memcpy(&parser->additional_buffer[offset], text, text_length); offset = new_length; } while((ret & (PARSER_EOF|PARSER_EOL)) == 0); parser->text = parser->additional_buffer; parser->text_length = offset; } char* text = parser->text; while(parser->char_type[(u8)*text] == PARSER_CHAR_TYPE_BLANK_MARKER) { text++; } parser->text_length -= text - parser->text; parser->text = text; parser->needle = (char*)&eol_park_needle[0]; parser->limit = (char*)&eol_park_needle[1]; return parser->text_length; } ya_result parser_concat_next_tokens(parser_s *parser) { ya_result ret; size_t offset = 0; // char space = parser->blank_marker[0]; const char space = ' '; do { ret = parser_next_token(parser); if(ret & PARSER_WORD) { const char *text = parser_text(parser); size_t text_length = parser_text_length(parser); size_t new_length = offset + text_length; if(new_length > sizeof(parser->additional_buffer)) { return PARSER_SYNTAX_ERROR_LINE_TOO_BIG; } memcpy(&parser->additional_buffer[offset], text, text_length); // VS false positive: overflow is chercked right before offset = new_length; parser->additional_buffer[offset] = space; offset++; } } while((ret & (PARSER_EOF|PARSER_EOL)) == 0); // remove the last space, because we always add a space offset--; char *text = parser->additional_buffer; parser->text_length = offset - (text - parser->additional_buffer); parser->text = text; parser->needle = (char*)&eol_park_needle[0]; parser->limit = (char*)&eol_park_needle[1]; return parser->text_length; } ya_result parser_concat_current_and_next_tokens_nospace(parser_s *parser) { ya_result ret; size_t offset; if(parser->text_length > sizeof(parser->additional_buffer)) { return PARSER_SYNTAX_ERROR_LINE_TOO_BIG; } memcpy(&parser->additional_buffer[0], parser->text, parser->text_length); offset = parser->text_length; do { ret = parser_next_token(parser); if((ret & PARSER_COMMENT) != 0) { continue; } const char *text = parser_text(parser); size_t text_length = parser_text_length(parser); size_t new_length = offset + text_length; if(new_length > sizeof(parser->additional_buffer)) { return PARSER_SYNTAX_ERROR_LINE_TOO_BIG; } memcpy(&parser->additional_buffer[offset], text, text_length); offset = new_length; } while((ret & (PARSER_EOF|PARSER_EOL)) == 0); char* text = parser->additional_buffer; while(parser->char_type[(u8)*text] == PARSER_CHAR_TYPE_BLANK_MARKER) { text++; } parser->text_length = offset - (text - parser->additional_buffer); parser->text = text; parser->needle = (char*)&eol_park_needle[0]; parser->limit = (char*)&eol_park_needle[1]; return parser->text_length; } ya_result parser_concat_next_tokens_nospace(parser_s *parser) { ya_result ret; size_t offset = 0; do { ret = parser_next_token(parser); if((ret & PARSER_COMMENT) != 0) { continue; } if((ret & PARSER_WORD) != 0) { const char *text = parser_text(parser); size_t text_length = parser_text_length(parser); size_t new_length = offset + text_length; if(new_length > sizeof(parser->additional_buffer)) { return PARSER_SYNTAX_ERROR_LINE_TOO_BIG; } memcpy(&parser->additional_buffer[offset], text, text_length); offset = new_length; } } while((ret & (PARSER_EOF|PARSER_EOL)) == 0); char* text = parser->additional_buffer; while(parser->char_type[(u8)*text] == PARSER_CHAR_TYPE_BLANK_MARKER) { text++; } parser->text_length = offset - (text - parser->additional_buffer); parser->text = text; parser->needle = (char*)&eol_park_needle[0]; parser->limit = (char*)&eol_park_needle[1]; return parser->text_length; } ya_result parser_push_stream(parser_s *p, input_stream *is) { if(p->input_stream_stack_size < PARSER_INCLUDE_DEPTH_MAX ) { #if DO_BUFFERIZE buffer_input_stream_init(is, is, PARSER_STREAM_BUFFER_SIZE); #endif p->input_stream_stack[p->input_stream_stack_size] = is; p->line_number_stack[p->input_stream_stack_size] = p->line_number; ++p->input_stream_stack_size; return p->input_stream_stack_size; } return PARSER_INCLUDE_DEPTH_TOO_BIG; } /** * @param p * @return the popped stream or NULL if the stack is empty */ input_stream * parser_pop_stream(parser_s *p) { input_stream *is = NULL; if(p->input_stream_stack_size > 0) { is = p->input_stream_stack[--p->input_stream_stack_size]; #if DEBUG p->input_stream_stack[p->input_stream_stack_size] = NULL; #endif p->line_number = p->line_number_stack[p->input_stream_stack_size]; } return is; } /////////////////////////////////////////////////////////////////////////////// ya_result parser_copy_next_ttl(parser_s *p, s32 *out_value) { ya_result return_code = parser_next_word(p); if(ISOK(return_code)) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); char lc = text[text_len - 1]; if(isdigit(lc)) { return_code = parse_s32_check_range_len_base10(text, text_len, out_value, 0, MAX_S32); } else { s64 mult = 1; text_len--; switch(lc) { case 'w': case 'W': mult = 60 * 60 * 24 * 7; break; case 'd': case 'D': mult = 60 * 60 * 24; break; case 'h': case 'H': mult = 60 * 60; break; case 'm': case 'M': mult = 60; break; case 's': case 'S': break; default: { return PARSER_UNKNOWN_TIME_UNIT; } } s32 ttl32; if(ISOK(return_code = parse_s32_check_range_len_base10(text, text_len, &ttl32, 0, MAX_S32))) { mult *= ttl32; if(mult <= MAX_S32) { *out_value = (s32)mult; } else { return_code = PARSEINT_ERROR; } } } } return return_code; } ya_result parser_type_bit_maps_initialise(parser_s *p, type_bit_maps_context* context) { u16 type; u8 *type_bitmap_field = context->type_bitmap_field; u8 *window_size = context->window_size; u32 type_bit_maps_size = 0; u8 ws; /* ------------------------------------------------------------ */ //ZEROMEMORY(window_size, sizeof(context->window_size)); s32 last_type_window = -1; //ZEROMEMORY(type_bitmap_field, sizeof(context->type_bitmap_field)); ya_result return_code; do { if(FAIL(return_code = parser_next_token(p))) { return return_code; } if((return_code & PARSER_WORD) != 0) { const char *text = parser_text(p); u32 text_len = parser_text_length(p); ya_result ret; // MUST use another return variable than return_code if(FAIL(ret = dns_type_from_case_name_length(text, text_len, &type))) { return ret; } type = ntohs(type); /* types are now stored in NETWORK order */ s32 type_window = type >> 8; if(type_window > last_type_window) { s32 length = type_window - last_type_window; ZEROMEMORY(&window_size[last_type_window + 1], length); ZEROMEMORY(&type_bitmap_field[(last_type_window + 1) << 5], length << 5); last_type_window = type_window; } /* Network bit order */ type_bitmap_field[type >> 3] |= 1 << (7 - (type & 7)); window_size[type_window] = ((type & 0xf8) >> 3) + 1; } } while((return_code & (PARSER_EOF|PARSER_EOL)) == 0); for(s32 i = 0; i <= last_type_window; i++) { ws = window_size[i]; if(ws > 0) { type_bit_maps_size += 1 + 1 + ws; } } context->type_bit_maps_size = type_bit_maps_size; context->last_type_window = last_type_window; return type_bit_maps_size; } ya_result parser_get_network_protocol_from_next_word(parser_s *p, int *out_value) { char protocol_token[64]; ya_result ret = parser_copy_next_word(p, protocol_token, sizeof(protocol_token)); if(ISOK(ret)) { ret = protocol_name_to_id(protocol_token, out_value); } return ret; } ya_result parser_get_network_service_port_from_next_word(parser_s *p, int *out_value) { char service_token[64]; ya_result ret = parser_copy_next_word(p, service_token, sizeof(service_token)); if(ISOK(ret)) { ret = server_name_to_port(service_token, out_value); } return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/parsing.c0000644000000000000000000000013014505005532021135 xustar000000000000000028 mtime=1695812442.3669811 30 atime=1695812445.791030139 30 ctime=1695812494.653729951 yadifa-2.6.5-11201/lib/dnscore/src/parsing.c0000664000374500037450000004563014505005532021111 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoretools Generic Tools * @ingroup dnscore * @brief * * @{ */ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #include #include "dnscore/parsing.h" #if !HAVE_TIMEGM && !HAS_TIMEGM static inline time_t timegm(struct tm *tv) { return timegm_internal(tv); } #endif /** \brief A string will be checked * * The number will be extracted from the string if present. This number can * be 10-based, or hex-based, or...\n * The base must be between 2 and 36 and the number must be be between the min * values and max value * * @param[in] src string with number part in it * @param[out] dst number found * @param[in] min * @param[in] max * @param[in] base * * @retval OK * @retval NOK, if no digits found, or number not in the range */ ya_result parse_u32_check_range(const char *src, u32 *dst, u32 min, u32 max, u8 base) { long long int val; char *endptr; int err; /** @note sizeof(long long int) > sizeof(u32) */ /* ------------------------------------------------------------ */ errno = 0; /** @note strtol returns a 64 bits integer on 64 bits architectures * strtoll should be 64 bits on both 32 and 64 bits architectures * so for portability 64 bits has to be handled */ val = strtoll(src, &endptr, base); /* stroll = 64 bits : dst is 32 */ err = errno; /* in case errno is a macro */ if((endptr == src) || (err == EINVAL) || (err == ERANGE) || (val < (long long int)min) || (val > (long long int)max)) { return PARSEINT_ERROR; } *dst = (u32)val; return OK; } ya_result parse_u32_check_range_len_base10(const char *src, u32 src_len, u32 *dst, u32 min, u32 max) { // 0......N // 67612321 if(src_len > 10) { return PARSEINT_ERROR; // out of range } --src_len; u64 output_value = ((u64)src[src_len]) - '0'; if((u64)output_value > 9) { return PARSEINT_ERROR; } u32 base_multiplier = 10; while(src_len > 0) { --src_len; u64 value = ((u64)src[src_len]) - '0'; if(value > 9) { return PARSEINT_ERROR; } value *= base_multiplier; output_value += value; base_multiplier *= 10; } if((output_value < min) || (output_value > max)) { return PARSEINT_ERROR; } *dst = (u32)output_value; return SUCCESS; } ya_result parse_s32_check_range_len_base10(const char *src, u32 src_len, s32 *dst, s32 min, s32 max) { // 0......N // 67612321 --src_len; if(src_len > 10) { return PARSEINT_ERROR; // out of range } bool minus; if((minus = (src[0] == '-'))) { src++; --src_len; } u32 base_multiplier = 10; s64 output_value = ((s64)src[src_len]) - '0'; if((u64)output_value > 9) { return PARSEINT_ERROR; } while(src_len > 0) { --src_len; s64 value = ((s64)src[src_len]) - '0'; if((u64)value > 9) { return PARSEINT_ERROR; } value *= base_multiplier; output_value += value; base_multiplier *= 10; } if(minus) { output_value = -output_value; } if((output_value < min) || (output_value > max)) { return PARSEINT_ERROR; } *dst = (s32)output_value; return SUCCESS; } ya_result parse_u64_check_range_len_base10(const char *src, u32 src_len, u64 *dst, u64 min, u64 max) { // 0......N // 18446744073709551615 if(src_len > 20) { return PARSEINT_ERROR; // out of range } --src_len; // 19 u64 output_value = ((u64)src[src_len]) - '0'; if((u64)output_value > 9) { return PARSEINT_ERROR; } if(src_len < 19) // if no risk of overflow { u64 base_multiplier = 10; while(src_len > 0) { --src_len; u64 value = ((u64)src[src_len]) - '0'; if(value > 9) { return PARSEINT_ERROR; } output_value += value * base_multiplier; base_multiplier *= 10; } } else // the only case with possible overflow at the last iteration of the loop { u64 base_multiplier = 10; while(src_len-- > 1) { u64 value = ((u64)src[src_len]) - '0'; if(value > 9) { return PARSEINT_ERROR; } output_value += value * base_multiplier; base_multiplier *= 10; } if(src_len == 0) { u64 max_div_10 = max / 10; if(output_value > max_div_10) // check before multiplication there will be no 64 bits overflow { // this only should be tested for the last iteration of the loop return PARSEINT_ERROR; // => the last pass should happen out of this loop } u64 value = ((u64)src[0]) - '0'; if(value > 9) { return PARSEINT_ERROR; } value *= base_multiplier; if(output_value > max - value) // check before addition there will be no 64 bits overflow { return PARSEINT_ERROR; } output_value += value; } } if((output_value < min) || (output_value > max)) // the second half of the test could probably get rid of, with a slight modification { return PARSEINT_ERROR; } *dst = output_value; return SUCCESS; } /** \brief Converts a string to an epoch * * Converts a string to an epoch * * @param[in] src string in the form YYYYMMDDhhmmss * @param[out] dst value of the source converted into GMT epoch * * @retval OK * @retval NOK, if no digits found, or number not in the range */ ya_result parse_yyyymmddhhmmss_check_range_len(const char *src, u32 src_len, time_t *dst) { struct tm thetime; if(src_len != 14) { return PARSEDATE_ERROR; } #if DEBUG memset(&thetime, 0xff, sizeof(thetime)); #endif u32 tmp_u32; if(FAIL(parse_u32_check_range_len_base10(src, 4, &tmp_u32, 1970, 2106/*2038*/))) { return PARSEDATE_ERROR; } thetime.tm_year = tmp_u32; src += 4; if(FAIL(parse_u32_check_range_len_base10(src, 2, &tmp_u32, 1, 12))) { return PARSEDATE_ERROR; } thetime.tm_mon = tmp_u32; src += 2; if(FAIL(parse_u32_check_range_len_base10(src, 2, &tmp_u32, 1, 31))) { return PARSEDATE_ERROR; } thetime.tm_mday = tmp_u32; src += 2; if(FAIL(parse_u32_check_range_len_base10(src, 2, &tmp_u32, 0, 23))) { return PARSEDATE_ERROR; } thetime.tm_hour = tmp_u32; src += 2; if(FAIL(parse_u32_check_range_len_base10(src, 2, &tmp_u32, 0, 59))) { return PARSEDATE_ERROR; } thetime.tm_min = tmp_u32; src += 2; if(FAIL(parse_u32_check_range_len_base10(src, 2, &tmp_u32, 0, 61))) { return PARSEDATE_ERROR; } thetime.tm_sec = tmp_u32; thetime.tm_year -= 1900; thetime.tm_mon--; time_t t = timegm(&thetime); if(t < 0) { return PARSEDATE_ERROR; } *dst = (u32)t; return OK; } ya_result parse_yyyymmddhhmmss_check_range(const char *src, time_t *dst) { ya_result return_code; return_code = parse_yyyymmddhhmmss_check_range_len(src, strlen(src), dst); return return_code; } /** \brief Converts a chain of pascal strings to a string * * Converts a chain of pascal strings to a string * * @param[in] src string in the form [len+chars]* * @param[out] dst string * * @retval OK * @retval NOK, if something is broken */ ya_result parse_pstring(char **srcp, size_t src_len, u8 *dst, size_t dst_len) { char *s = *srcp; const char * const limit = &s[src_len]; u8 *p; const u8 *dst_limit; bool quoted; if(src_len == 0 || dst_len < 256) { return PARSESTRING_ERROR; } p = &dst[1]; dst_limit = &dst[dst_len]; quoted = FALSE; if(s[0] == '"') { quoted = TRUE; s++; } for(; s < limit; s++) { char c = *s; if((c < 32)) { return PARSE_INVALID_CHARACTER; } // If unescaped '\' go on otherwise set escape = 1 if(c == '\\') { // grab next char IF there is one s++; if(s < limit) { if((c < 32)) { return PARSE_INVALID_CHARACTER; } if(p == dst_limit) { return PARSE_BUFFER_TOO_SMALL_ERROR; } *p++ = *s; } else { return PARSESTRING_ERROR; } continue; } // only " if(c == '"') { if(!quoted) { return PARSESTRING_ERROR; } quoted = FALSE; break; } if(!quoted) { if(isspace(c)) { break; } } if(p == dst_limit) { return PARSE_BUFFER_TOO_SMALL_ERROR; } /* add character to temporary variable */ *p++ = c; } /* if unbalanaced qoutes --> stop */ if(quoted) { return PARSESTRING_ERROR; } ya_result len = p - dst; dst[0] = len - 1; /* Now it is really done the parsing */ *srcp = s + 1; return len; } /** \brief Copies and trim a string * * Copies a string while remove head & tail spaces and reducing any blank run to a single space * The source does not need to be asciiz * The destination will be asciiz * * @param[in] src string * @param[in] src_len size of the string (the zero sentinel is not checked) * @param[in] dst buffer that will receive the output string * @param[in] dst_len size of the buffer * * @retval >= 0, the length of the dst string * @retval ERROR, dst_len was too small */ ya_result parse_copy_trim_spaces(const char *src, u32 src_len, char *dst, u32 dst_len) { yassert(src != NULL && dst != NULL && dst_len > 0); const char *src_limit = src + src_len; const char *dst_limit = dst + dst_len - 1; const char *dst_org = dst; bool has_space = FALSE; *dst = '\0'; while(src < src_limit && isspace(*src)) { src++; } while(src < src_limit) { char c = *src++; if(isspace(c)) { has_space = TRUE; continue; } if(has_space) { *dst++ = ' '; if(dst == dst_limit) { return PARSE_BUFFER_TOO_SMALL_ERROR; /* buffer too small */ } } has_space = FALSE; *dst++ = c; if(dst == dst_limit) { return PARSE_BUFFER_TOO_SMALL_ERROR; /* buffer too small */ } } *dst++ = '\0'; return dst - dst_org; } ya_result parse_remove_spaces(char *inout_txt) { char *p = inout_txt; char c; while((c = *inout_txt++) != '\0') { if(isspace(c)) { continue; } *p++ = c; } *p = '\0'; return p - inout_txt; } /** \brief Skips a specific keyword from a string, case insensitive * * Skips a specific keyword from a string, case insensitive, skips white spaces before and after the match * * @param[in] src string * @param[in] src_len size of the string (the zero sentinel is not checked) * @param[in] words array of strings that will be looked for * @param[in] word_count the size of the array * @param[in] matched_word a pointer to an integer that will hold the matched word index or -1 (can be NULL) * * @retval >= 0, the number of bytes until the next word * @retval ERROR, dst_len was too small */ ya_result parse_skip_word_specific(const char *src, u32 src_len, const char **words, u32 word_count, s32 *matched_word) { const char *src_org = src; const char *src_limit = src + src_len; // skip spaces src = parse_skip_spaces(src); // get the non-space const char *p = src; while(p < src_limit && !isspace(*p)) { p++; } // p == src_limit OR p is at the first blank after the word src_limit = p; src_len = src_limit - src; for(u32 i = 0; i < word_count; i++) { const char *ptr = src; const char *word = words[i]; u32 word_len = strlen(word); if(word_len != src_len) { continue; } const char *word_limit = word + word_len; // lengths are the same while(word < word_limit) { if(tolower(*ptr++) != tolower(*word++)) { break; } } if(word == word_limit) { /* match */ if(matched_word != NULL) { *matched_word = i; } return src_limit - src_org; } } if(matched_word != NULL) { *matched_word = -1; } return PARSEWORD_NOMATCH_ERROR; /* no match */ } const char * parse_skip_until_chars(const char *src, const char *chars, u32 chars_len) { for(;;) { char c = *src; if(c == '\0') { return src; } for(u32 i = 0; i < chars_len; i++) { if(c == chars[i]) { return src; } } src++; } } /** \brief Skips a specific keyword from a string, case insensitive * * Skips a specific keyword from a string, case insensitive, skips white spaces before and after the match * * @param[in] src string * @param[in] src_len size of the string (the zero sentinel is not checked) * @param[in] dst buffer that will receive the binary version of the ip * @param[in] dst_len the size of the buffer, minimum 4 for ipv4 and minimum 16 for ipv6 * * @retval >= 0, the number of bytes written (4 for ipv4 and 16 for ipv6) * @retval ERROR, dst_len was too small or the src was not a valid ip */ ya_result parse_ip_address(const char *src, u32 src_len_, u8 *dst, u32 dst_len) { const char *new_src = parse_skip_spaces(src); s32 src_len = (s32)src_len_; src_len -= new_src - src; bool expect_v6_or_more = FALSE; if(src_len <= 0) { return PARSEIP_ERROR; } if(*new_src == '[') /// @note handle RFC 3986, section 3.2.2 { expect_v6_or_more = TRUE; new_src++; // IPv6+ delimiter char *end = strchr(new_src, ']'); if(end == NULL) { return PARSEIP_ERROR; } src_len = end - new_src; } char tmp[64]; src_len = MIN((size_t)src_len, sizeof(tmp)-1); memcpy(tmp, src, src_len); tmp[src_len] = '\0'; if(dst_len < 4) { return PARSE_BUFFER_TOO_SMALL_ERROR; /* dst too small */ } if(inet_pton(AF_INET, tmp, dst) == 1) { if(expect_v6_or_more) { return PARSEIP_ERROR; } return 4; } if(dst_len < 16) { return PARSE_BUFFER_TOO_SMALL_ERROR; /* dst too small */ } if(inet_pton(AF_INET6, tmp, dst) == 1) { return 16; } return PARSEIP_ERROR; } s32 parse_next_token(char *dest, size_t dest_size, const char *from, const char *delim) { const char *to = from; for(;;) { char c = *to; if(c == '\0') { size_t len = to - from; if(len > dest_size) { return PARSE_BUFFER_TOO_SMALL_ERROR; } memcpy(dest, from, len); dest[len] = '\0'; return len; } // for every delimiter, test if c if such a delimiter // if it is, then for(const char *d = delim; *d != 0; d++) { if(*d == c) { // end of word size_t len = to - from; if(len > dest_size) { return PARSE_BUFFER_TOO_SMALL_ERROR; } memcpy(dest, from, len); dest[len] = '\0'; return len; } } ++to; } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/process.c0000644000000000000000000000013114505005532021151 xustar000000000000000030 mtime=1695812442.446982246 30 atime=1695812445.794030182 29 ctime=1695812494.65572998 yadifa-2.6.5-11201/lib/dnscore/src/process.c0000664000374500037450000000734514505005532021125 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/process.h" #include "dnscore/thread_pool.h" /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT void debug_malloc_mutex_lock(); // Internal use only void debug_malloc_mutex_unlock(); // Internal use only #endif /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ pid_t g_pid = -1; pid_t fork_ex() { #if __unix__ logger_flush(); dnscore_stop_timer(); service_stop_all(); thread_pool_stop_all(); #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_stop(); #endif #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT // ensure this mutex isn't locked while we are forking debug_malloc_mutex_lock(); #endif pid_t pid = fork(); #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT debug_malloc_mutex_unlock(); #endif if(pid == 0) { g_pid = getpid(); } #if MUTEX_CONTENTION_MONITOR mutex_contention_monitor_start(); #endif thread_pool_start_all(); service_start_all(); dnscore_reset_timer(); return pid; #else return -1; #endif } int waitpid_ex(pid_t pid, int *wstatus, int options) { int ret; #if __unix__ while((ret = waitpid(pid, wstatus, options)) < 0) { int err = errno; if(err == EINTR) { continue; } else { return -1; } } return ret; #else WaitForSingleObject(pid, INFINITE); #endif } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/pid.c0000644000000000000000000000013114505005532020247 xustar000000000000000030 mtime=1695812442.502983047 29 atime=1695812445.79603021 30 ctime=1695812494.657730008 yadifa-2.6.5-11201/lib/dnscore/src/pid.c0000664000374500037450000002252314505005532020216 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include #include "dnscore/pid.h" #include "dnscore/sys_types.h" #include "dnscore/logger.h" #include "dnscore/parser.h" #include "dnscore/fdtools.h" #include "dnscore/process.h" /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ /** \brief Read \b pid \b file, program quits on log_quit * * @param[in] path * @param[in] file_name * * @retval pid * @retval NOK (negative number), * @return otherwise log_quit will stop the program with correct exit code */ pid_t pid_file_read(const char *pid_file_path) { ssize_t received; int fd; char *p; u32 pid; ya_result ret; char buffer[8 + 1]; /* ------------------------------------------------------------ */ yassert(pid_file_path != NULL); if(strlen(pid_file_path) > PATH_MAX) { log_err("pid file '%s': path is bigger than %i", pid_file_path, PATH_MAX); return INVALID_PATH; } if(FAIL(fd = open_ex(pid_file_path, O_RDONLY|O_CLOEXEC))) { ret = ERRNO_ERROR; log_debug("pid file '%s': cannot open: %r", pid_file_path, ret); return ret; /* no file found : not running assumed */ } received = readfully(fd, buffer, sizeof(buffer) - 1); if(received <= 0) { if(received < 0) { ret = received; log_err("pid file '%s': cannot read pid: %r", pid_file_path, ret); } else { ret = UNEXPECTED_EOF; } close_ex(fd); /* close the pid file */ return ret; } buffer[received] = '\0'; /* Append a terminator for strlen */ p = buffer; while(isdigit(*p)!=0) p++; /* Cut after the first character that is not a digit (ie: CR LF ...) */ *p = '\0'; if(FAIL(ret = parse_u32_check_range(buffer, &pid, 0, MAX_S32, BASE_10))) { log_err("pid file '%s': invalid pid number: %r", pid_file_path, ret); return ret; } close_ex(fd); /* close the pid file */ return (pid_t)pid; } /** \brief Create or overwrite the \b pid \b file with its new process id * * @param[in] config is a config_data structure * * @retval OK * @retval YDF_ERROR_CHOWN if can not "chown" * @return otherwise log_quit will stop the program with correct exit code */ ya_result pid_file_create(pid_t *pid, const char *pid_file_path, uid_t new_uid, gid_t new_gid) { ya_result ret; int fd; mode_t permissions = 0644; #if __unix__ uid_t uid = getuid(); #endif char buffer[16]; pid_t pid_tmp; if(pid == NULL) { pid = &pid_tmp; } /* ------------------------------------------------------------ */ yassert(pid_file_path != NULL); if(strlen(pid_file_path) > PATH_MAX) { log_err("pid file '%s': path is bigger than %i", pid_file_path, PATH_MAX); return INVALID_PATH; } *pid = getpid_ex(); int buffer_len = snprintf(buffer, sizeof(buffer), "%d\n", *pid); // VS complains for something that's Windows specific and wrong at the moment anyhow. yassert(buffer_len > 0); fd = open_create_ex(pid_file_path, O_WRONLY | O_CREAT | O_TRUNC, permissions); if(fd >= 0) { for(;;) { #if __unix__ if(flock(fd, LOCK_EX|LOCK_NB) < 0) { ret = errno; if(ret == EINTR) { continue; } if(ret == EWOULDBLOCK) { // already locked close_ex(fd); return PID_LOCKED; } abort(); } #endif break; } if(ISOK(ret = pid_check_running_program(pid_file_path, NULL))) { // got the lock if(writefully(fd, buffer, buffer_len) > 0) { ret = SUCCESS; #if __unix__ if(uid == 0) // only applicable if you are root { if(fchown(fd, new_uid, new_gid) >= 0) // avoid race condition (Flawfinder) { log_debug("pid file '%s': created", pid_file_path); } else { ret = ERRNO_ERROR; log_err("pid file '%s': cannot change owner.group to %i.%i: %r", pid_file_path, new_uid, new_gid, ret); pid_file_destroy(pid_file_path); } } #endif } else { ret = ERRNO_ERROR; log_err("pid file '%s': cannot write pid: %r", pid_file_path, ret); pid_file_destroy(pid_file_path); } } } else { ret = ERRNO_ERROR; log_err("pid file '%s': cannot create: %r", pid_file_path, ret); } close_ex(fd); return ret; } /** \brief Check if program is already running * * @param[in] config is a config_data structure * * @return NONE * @return otherwise log_quit will stop the program with correct exit code */ ya_result pid_check_running_program(const char *pid_file_path, pid_t *out_pid) { #if __unix__ yassert(pid_file_path != NULL); pid_t pid; /* ------------------------------------------------------------ */ yassert(pid_file_path != NULL); if(strlen(pid_file_path) > PATH_MAX) { log_err("pid file '%s': path is bigger than %i", pid_file_path, PATH_MAX); return INVALID_PATH; } if(ISOK(pid = pid_file_read(pid_file_path))) { if((pid != getpid_ex()) && ((kill(pid, 0) == 0) || (errno == EPERM))) { if(out_pid != NULL) { *out_pid = pid; } return PID_LOCKED; } } #endif return SUCCESS; } void pid_file_destroy(const char *pid_file_path) { yassert(pid_file_path != NULL); if(strlen(pid_file_path) > PATH_MAX) { log_err("pid file '%s': path is bigger than %i", pid_file_path, PATH_MAX); return; } if(FAIL(unlink(pid_file_path))) { int ret = ERRNO_ERROR; // don't complain if the file has already been destroyed if(ret != ENOENT) { log_err("pid file '%s': cannot delete: %r", pid_file_path, ret); } } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/pipe_stream.c0000644000000000000000000000013114505005532022003 xustar000000000000000030 mtime=1695812442.499983004 29 atime=1695812445.79603021 30 ctime=1695812494.659730037 yadifa-2.6.5-11201/lib/dnscore/src/pipe_stream.c0000664000374500037450000002027314505005532021752 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include #include "dnscore/pipe_stream.h" #include "dnscore/logger.h" /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #define MODULE_MSG_HANDLE g_system_logger #define DEBUG_PIPE_OUTPUT_STREAM 0 #define OUTPUT_OPENED 1 #define INPUT_OPENED 2 typedef struct pipe_stream_data pipe_stream_data; #define PIPESDTA_TAG 0x4154445345504950 #define PIPESBFR_TAG 0x5246425345504950 struct pipe_stream_data { u8* buffer; u32 buffer_size; u32 write_offset; u32 write_avail; u32 read_offset; u32 read_avail; u8 flags; }; /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ static ya_result pipe_stream_output_write(output_stream* stream, const u8* buffer, u32 len) { if(len == 0) { return 0; } pipe_stream_data *data = (pipe_stream_data*)stream->data; u32 remaining = len; while((remaining > 0) && (data->write_avail > 0)) { u32 chunk_len = MIN(data->buffer_size - data->write_offset, data->write_avail); chunk_len = MIN(remaining, chunk_len); #if DEBUG_PIPE_OUTPUT_STREAM log_debug("pipe: w: %d bytes", len); log_memdump_ex(g_system_logger, LOG_DEBUG, buffer, chunk_len, 16, OSPRINT_DUMP_ALL); #endif MEMCOPY(&data->buffer[data->write_offset], buffer, chunk_len); buffer += chunk_len; data->write_offset += chunk_len; data->write_avail -= chunk_len; data->read_avail += chunk_len; if(data->write_offset == data->buffer_size) { data->write_offset = 0; } remaining -= chunk_len; //usleep(1000); } len -= remaining; if((len == 0) && ( (data->flags & (INPUT_OPENED|OUTPUT_OPENED)) != (INPUT_OPENED|OUTPUT_OPENED))) { return UNEXPECTED_EOF; // if one of the sides is closed ... } return len; } static ya_result pipe_stream_output_flush(output_stream* stream) { (void)stream; return SUCCESS; } static void pipe_stream_output_close(output_stream* stream) { pipe_stream_data* data = (pipe_stream_data*)stream->data; data->flags &= ~OUTPUT_OPENED; if((data->flags & INPUT_OPENED) == 0) { free(data->buffer); free(data); } output_stream_set_void(stream); } static const output_stream_vtbl pipe_stream_output_vtbl = { pipe_stream_output_write, pipe_stream_output_flush, pipe_stream_output_close, "pipe_stream_output", }; static ya_result pipe_stream_input_read(input_stream* stream, void *buffer_, u32 len) { if(len == 0) { return 0; } u8 *buffer = (u8*)buffer_; #if DEBUG memset(buffer, 0xff, len); #endif pipe_stream_data* data = (pipe_stream_data*)stream->data; u32 remaining = len; while((remaining > 0) && (data->read_avail > 0)) { u32 chunk_len = MIN(data->buffer_size - data->read_offset, data->read_avail); chunk_len = MIN(remaining, chunk_len); MEMCOPY(buffer, &data->buffer[data->read_offset], chunk_len); buffer += chunk_len; data->read_offset += chunk_len; data->read_avail -= chunk_len; data->write_avail += chunk_len; if(data->read_offset == data->buffer_size) { data->read_offset = 0; } remaining -= chunk_len; } return len - remaining; } static ya_result pipe_stream_input_skip(input_stream* stream, u32 len) { if(len == 0) { return 0; } pipe_stream_data* data = (pipe_stream_data*)stream->data; u32 remaining = len; for(;;) { while((remaining > 0) && (data->read_avail > 0)) { u32 chunk_len = MIN(data->buffer_size - data->read_offset, data->read_avail); chunk_len = MIN(remaining, chunk_len); data->read_offset += chunk_len; data->read_avail -= chunk_len; data->write_avail += chunk_len; if(data->read_offset == data->buffer_size) { data->read_offset = 0; } remaining -= chunk_len; } if((len != remaining) || ((data->flags & OUTPUT_OPENED) == 0)) { break; } usleep(1000); } return len - remaining; } static void pipe_stream_input_close(input_stream* stream) { pipe_stream_data* data = (pipe_stream_data*)stream->data; data->flags &= ~INPUT_OPENED; if((data->flags & OUTPUT_OPENED) == 0) { free(data->buffer); free(data); } input_stream_set_void(stream); } static const input_stream_vtbl pipe_stream_input_vtbl = { pipe_stream_input_read, pipe_stream_input_skip, pipe_stream_input_close, "pipe_stream_input_stream", }; /** * Creates both output and input stream * Writing in the output stream makes it available for the input stream * This is not currently threadable. * * @param output * @param input */ void pipe_stream_init(output_stream *output, input_stream *input, u32 buffer_size) { pipe_stream_data *data; MALLOC_OBJECT_OR_DIE(data, pipe_stream_data, PIPESDTA_TAG); ZEROMEMORY(data, sizeof(pipe_stream_data)); MALLOC_OR_DIE(u8*, data->buffer, buffer_size, PIPESBFR_TAG); #if DEBUG memset(data->buffer, 0xff, buffer_size); #endif data->buffer_size = buffer_size; data->write_avail = buffer_size; data->flags = OUTPUT_OPENED|INPUT_OPENED; output->data = data; output->vtbl = &pipe_stream_output_vtbl; input->data = data; input->vtbl = &pipe_stream_input_vtbl; } /** * * Number of available bytes in the input stream * * @param input * @return */ ya_result pipe_stream_read_available(input_stream *input) { pipe_stream_data *data = (pipe_stream_data*)input->data; return data->read_avail; } /** * * Room for bytes in the output stream * * @param input * @return */ ya_result pipe_stream_write_available(output_stream *input) { pipe_stream_data *data = (pipe_stream_data*)input->data; return data->write_avail; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/pool.c0000644000000000000000000000013214505005532020445 xustar000000000000000030 mtime=1695812442.395981515 30 atime=1695812445.792030153 30 ctime=1695812494.661730066 yadifa-2.6.5-11201/lib/dnscore/src/pool.c0000664000374500037450000001564414505005532020421 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include "dnscore/pool.h" #include "dnscore/logger.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger static mutex_t pool_chain_mtx = MUTEX_INITIALIZER; static pool_s *pool_chain = NULL; static void pool_reset_nop(void *ptr, void *args) { (void)ptr; (void)args; } void pool_init_ex(pool_s *pool, pool_allocate_callback *allocate_, pool_free_callback *free_, pool_reset_callback *reset_, void *allocate_args, const char* name) { #if DEBUG // ensure there are no double initialisations pool_s *first = pool_chain; while(first != NULL) { if(first == pool) { abort(); } first = first->next; } #endif ptr_vector_init(&pool->pool); pool->allocate_method = allocate_; pool->free_method = free_; pool->reset_method = reset_; pool->allocate_args = allocate_args; mutex_init(&pool->mtx); pool->allocated_count = 0; pool->released_count = 0; pool->name = name; pool->max_size = 0; pool->current_count = 0; pool->peak_count = 0; pool->hard_limit = FALSE; pool->maxed = FALSE; pool_set_size(pool, 0x10000); mutex_lock(&pool_chain_mtx); pool->next = pool_chain; pool_chain = pool; mutex_unlock(&pool_chain_mtx); } void pool_init(pool_s *pool, pool_allocate_callback *allocate_, pool_free_callback *free_, void *allocate_args, const char *name) { pool_init_ex(pool, allocate_, free_, pool_reset_nop, allocate_args, name); } void pool_log_stats_ex(pool_s *pool, logger_handle* handle, u32 level) { if(pool != NULL) { logger_handle_msg(handle, level, "pool '%s' handled %llu allocations and %llu releases; pooled %i maxed at %i; using %u peaked at %u", pool->name, pool->allocated_count, pool->released_count, pool->pool.offset + 1, pool->max_size, pool->current_count, pool->peak_count); } else { logger_handle_msg(handle, MSG_ERR, "pool is NULL"); } } void pool_log_stats(pool_s *pool) { pool_log_stats_ex(pool, MODULE_MSG_HANDLE, MSG_DEBUG); } void pool_log_all_stats_ex(logger_handle* handle, u32 level) { mutex_lock(&pool_chain_mtx); pool_s *p = pool_chain; while(p != NULL) { pool_log_stats_ex(p, handle, level); p = p->next; } mutex_unlock(&pool_chain_mtx); } void pool_log_all_stats() { pool_log_all_stats_ex(MODULE_MSG_HANDLE, MSG_DEBUG); } void pool_finalize(pool_s *pool) { #if DEBUG pool_log_stats(pool); #endif mutex_lock(&pool_chain_mtx); pool_s **pp = &pool_chain; while(*pp != NULL) { if(*pp == pool) { *pp = pool->next; break; } pp = &(*pp)->next; } mutex_unlock(&pool_chain_mtx); u64 delta; mutex_lock(&pool->mtx); delta = pool->allocated_count - pool->released_count; for(s32 i = 0; i <= pool->pool.offset; i++) { pool->free_method(pool->pool.data[i], pool->allocate_args); pool->pool.data[i] = NULL; } ptr_vector_destroy(&pool->pool); mutex_unlock(&pool->mtx); mutex_destroy(&pool->mtx); pool_log_stats(pool); if(delta != 0) { log_warn("pool '%s' leaked: %d items", pool->name, delta); } #if DEBUG memset(pool, 0xe0, sizeof(pool_s)); #endif } void* pool_alloc(pool_s *pool) { void *p; mutex_lock(&pool->mtx); if(pool->hard_limit) { if(pool->current_count >= pool->max_size + 1) { if(!pool->maxed) // the maxed flag helps to only complain once the limit is reached { log_warn("pool '%s' : pool usage reached maximum %i > %i", pool->name, pool->peak_count, pool->max_size); pool->maxed = TRUE; } mutex_unlock(&pool->mtx); return NULL; } pool->maxed = FALSE; } pool->allocated_count++; if(++pool->current_count > pool->peak_count) { pool->peak_count = pool->current_count; } if(pool->pool.offset >= 0) { p = ptr_vector_pop(&pool->pool); mutex_unlock(&pool->mtx); pool->reset_method(p, pool->allocate_args); } else { mutex_unlock(&pool->mtx); p = pool->allocate_method(pool->allocate_args); } log_debug7("pool '%s': alloc %p", pool->name, p); return p; } void pool_release(pool_s *pool, void *p) { log_debug7("pool '%s': release %p", pool->name, p); mutex_lock(&pool->mtx); if((--pool->current_count) < 0) { log_err("pool '%s': <0: %d", pool->name, pool->current_count); } if(pool->pool.offset < pool->max_size) { ptr_vector_append(&pool->pool, p); } else { pool->free_method(p, pool->allocate_args); } pool->released_count++; mutex_unlock(&pool->mtx); } void pool_set_size(pool_s *pool, s32 max_size) { yassert(ptr_vector_size(&pool->pool) <= max_size); ptr_vector_resize(&pool->pool, max_size); pool->max_size = max_size - 1; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/popen-output-stream.c0000644000000000000000000000013114505005532023443 xustar000000000000000030 mtime=1695812442.483982775 29 atime=1695812445.79603021 30 ctime=1695812494.663730094 yadifa-2.6.5-11201/lib/dnscore/src/popen-output-stream.c0000664000374500037450000001562014505005532023412 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore * @ingroup dnscore * @brief popen is not enough * * * @{ */ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #include #define _ZALLOC_C #include "dnscore/sys_types.h" #include "dnscore/popen-output-stream.h" #include "dnscore/fdtools.h" #include "dnscore/zalloc.h" #include "dnscore/identity.h" #if DEBUG #include "dnscore/format.h" #endif #define POPENOSD_TAG 0x44534f4e45504f50 struct popen_output_stream_data { int fd; pid_t child; }; typedef struct popen_output_stream_data popen_output_stream_data; static ya_result popen_output_stream_write(output_stream* stream, const u8* buffer, u32 len) { int fd = ((popen_output_stream_data*)stream->data)->fd; const u8* start = buffer; while(len > 0) { ssize_t ret = write(fd, buffer, len); if(ret <= 0) { int err = errno; if(err == EINTR) { continue; } if(err == EAGAIN) { #if __FreeBSD__ || __OpenBSD__ || __APPLE__ int oldflags = fcntl (fd, F_GETFL, 0); if(oldflags < 0) { return MAKE_ERRNO_ERROR(err); } #endif continue; } /* error */ return MAKE_ERRNO_ERROR(err); } buffer += ret; len -= ret; } return buffer - start; } static ya_result popen_output_stream_flush(output_stream* stream) { int fd = ((popen_output_stream_data*)stream->data)->fd; if(fsync_ex(fd) == 0) /* or fdatasync ... maybe it would be slightly better */ { return SUCCESS; } return ERRNO_ERROR; } static void popen_output_stream_close(output_stream* stream) { struct popen_output_stream_data *data = (struct popen_output_stream_data*)stream->data; #if DEBUG int fd = data->fd; #endif close_ex(data->fd); data->fd = -1; int status; #if DEBUG formatln("popen_output_stream_close(%i, %i) (wait)", data->child, fd); #endif while(waitpid(data->child, &status, 0) < 0) { int err = errno; if(err != EINTR) { break; } } #if DEBUG formatln("popen_output_stream_close(%i, %i) (done)", data->child, fd); #endif data->child = -1; ZFREE_OBJECT(data); } static const output_stream_vtbl popen_output_stream_vtbl = { popen_output_stream_write, popen_output_stream_flush, popen_output_stream_close, "popen_output_stream", }; int popen_output_stream_ex(output_stream* os, const char* command, popen_output_stream_parameters* parms) { #if __unix__ int write_pipe[2]; ya_result ret; /// @note 20210104 edf -- The null file is opened at this moment so we can return with an error right now if it fails. /// It is way better than forking and failing. #if DEBUG formatln("popen_output_stream_ex(%s) (open null)", command); #endif int fdnull = open_ex("/dev/null", O_WRONLY); if(fdnull < 0) { return ERRNO_ERROR; } #if DEBUG formatln("popen_output_stream_ex(%s) (pipe)", command); #endif if(pipe(write_pipe) < 0) { ret = ERRNO_ERROR; close_ex(fdnull); return ret; } #if DEBUG formatln("popen_output_stream_ex(%s) (fork)", command); #endif pid_t child; if((child = fork()) > 0) { // child + write_pipe[1] close_ex(write_pipe[0]); fd_setcloseonexec(write_pipe[1]); close_ex(fdnull); popen_output_stream_data* data; ZALLOC_OBJECT_OR_DIE(data, popen_output_stream_data, POPENOSD_TAG); data->fd = write_pipe[1]; data->child = child; os->data = data; os->vtbl = &popen_output_stream_vtbl; #if DEBUG formatln("popen_output_stream_ex(%s) = (%i, %i)", command, data->child, data->fd); #endif return SUCCESS; } else if(child == 0) { close_ex(write_pipe[1]); #if __unix__ signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGABRT, SIG_DFL); signal(SIGSEGV, SIG_DFL); signal(SIGPIPE, SIG_DFL); signal(SIGALRM, SIG_DFL); signal(SIGTERM, SIG_DFL); identity_change(parms->uid, parms->gid); #endif dup2_ex(write_pipe[0], 0); // write to its standard input dup2_ex(fdnull, 1); // ignore its standard output dup2_ex(fdnull, 2); // ignore its standard error close_ex(write_pipe[0]); close_ex(fdnull); execl("/bin/sh", "sh", "-c", command, NULL); /// @note 20210104 edf -- this would obviously fail if /bin/sh isn't present. // never reached abort(); } else // fork failed { ret = ERRNO_ERROR; close_ex(write_pipe[0]); close_ex(write_pipe[1]); close_ex(fdnull); return ret; } #else return -1; #endif } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/ptr_set.c0000644000000000000000000000013214505005532021154 xustar000000000000000030 mtime=1695812442.374981214 30 atime=1695812445.791030139 30 ctime=1695812494.665730123 yadifa-2.6.5-11201/lib/dnscore/src/ptr_set.c0000664000374500037450000002043414505005532021121 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #include #define _PTR_SET_COLLECTION_C #define DEBUG_LEVEL 0 #include "dnscore/ptr_set.h" #include "dnscore/zalloc.h" /* * The following macros are defining relevant fields in the node */ /* * Access to the field that points to the left child */ #define AVL_LEFT_CHILD(node) ((node)->children.lr.left) /* * Access to the field that points to the right child */ #define AVL_RIGHT_CHILD(node) ((node)->children.lr.right) /* * Access to the field that points to one of the children (0: left, 1: right) */ #define AVL_CHILD(node,id) ((node)->children.child[(id)]) /* * OPTIONAL : Access to the field that points the parent of the node. * * This field is optional but is mandatory if AVL_HAS_PARENT_POINTER is not 0 */ #define AVL_PARENT(node) ((node)->parent) /* * Access to the field that keeps the balance (a signed byte) */ #define AVL_BALANCE(node) ((node)->balance) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE void* /* * */ #define AVL_REFERENCE_FORMAT_STRING "%p" #define AVL_REFERENCE_FORMAT(reference) ((void*)reference) /* * A macro to initialize a node and setting the reference */ #define AVL_INIT_NODE(node,reference) node->key = reference /* * A macro to allocate a new node */ #define AVL_ALLOC_NODE(node,reference) \ ZALLOC_OBJECT_OR_DIE( node, AVL_NODE_TYPE, PTR_NODE_TAG); \ ZEROMEMORY(node,sizeof(AVL_NODE_TYPE)); /* * A macro to free a node */ #define AVL_FREE_NODE(node) ZFREE(node, AVL_NODE_TYPE) /* * A macro to print the node */ #define AVL_DUMP_NODE(node) format("node@%p",(node)); /* * A macro that returns the reference field of the node. * It must be of type REFERENCE_TYPE */ #define AVL_REFERENCE(node) (node)->key #define AVL_REFERENCE_IS_POINTER TRUE #define AVL_REFERENCE_IS_CONST FALSE #define AVL_TERNARYCMP 1 #if !AVL_TERNARYCMP /* * A macro to compare two references * Returns TRUE if and only if the references are equal. */ #define AVL_ISEQUAL(reference_a,reference_b) (tree->compare((reference_a),(reference_b)) == 0) /* * A macro to compare two references * Returns TRUE if and only if the first one is bigger than the second one. */ #define AVL_ISBIGGER(reference_a,reference_b) (tree->compare((reference_a),(reference_b)) > 0) #else #define AVL_COMPARE(reference_a,reference_b) (tree->compare((reference_a),(reference_b))) #endif /* * Copies the payload of a node * It MUST NOT copy the "proprietary" node fields : children, parent, balance */ //#define AVL_COPY_PAYLOAD(node_trg,node_src) {(node_trg)->data = (node_src)->data;(node_trg)->key = (node_src)->key;} #define AVL_COPY_PAYLOAD(node_trg,node_src) {(node_trg)->data = (node_src)->data;(node_trg)->key = (node_src)->key;} /* * A macro to preprocess a node before it is preprocessed for a delete (detach) * If there was anything to do BEFORE deleting a node, we would do it here * After this macro is exectuted, the node * _ is detached, then deleted with FREE_NODE * _ has got its content overwritten by the one of another node, then the other * node is deleted with FREE_NODE */ #define AVL_NODE_DELETE_CALLBACK(node) #include "dnscore/avl.c.inc" int ptr_set_ptr_node_compare(const void *key_a, const void *key_b) { #if __SIZEOF_POINTER__ == 8 s64 a = (s64)key_a; s64 b = (s64)key_b; s64 d = b - a; return (d < 0)?-1:((d > 0)?1:0); #elif __SIZEOF_POINTER__ == 4 s32 a = (s32)key_a; s32 b = (s32)key_b; s32 d = b - a; return d; #else #error "__SIZEOF_POINTER__ not defined" #endif } int ptr_set_asciizp_node_compare(const void *key_a, const void *key_b) { return strcmp((const char*)key_a, (const char*)key_b); } int ptr_set_asciizcasep_node_compare(const void *key_a, const void *key_b) { //formatln("'%s' ? '%s'", node_a, node_b);flushout(); return strcasecmp((const char*)key_a, (const char*)key_b); } /** * Top Down, lexicographically */ int ptr_set_fqdn_node_compare(const void *key_a, const void *key_b) { dnslabel_stack a; dnslabel_stack b; s32 a_top = dnsname_to_dnslabel_stack((const u8*)key_a, a); s32 b_top = dnsname_to_dnslabel_stack((const u8*)key_b, b); s32 d; s32 top = MIN(a_top, b_top); for(s32 i = 0; i <= top; ++i) { d = dnslabel_compare(a[i], b[i]); if(d != 0) { return d; } } d = a_top - b_top; return d; } int ptr_set_dnsname_node_compare(const void *key_a, const void *key_b) { return dnsname_compare((const u8*)key_a, (const u8*)key_b); } // key = fqdn (cannot be NULL) int ptr_set_dnslabel_node_compare(const void *key_a, const void *key_b) { const u8 *a = (const u8*)key_a; // length of label key_a const u8 *b = (const u8*)key_b; // length of label key_b int n = MIN(*a, *b) + 1; // length of the smallest label with its length return memcmp(a, b, n); // smaller strings first, then lexicographical order } int ptr_set_nullable_asciizp_node_compare(const void *key_a, const void *key_b) { if(key_a != NULL) { if(key_b != NULL) { return strcmp((const char*)key_a, (const char*)key_b); } else { return -1; } } else { return (key_b == NULL)?0:1; } } int ptr_set_nullable_dnsname_node_compare(const void *key_a, const void *key_b) { if(key_a != NULL) { if(key_b != NULL) { return dnsname_compare((const u8*)key_a, (const u8*)key_b); } else { return -1; } } else { return (key_b == NULL)?0:1; } } int ptr_set_host_address_node_compare(const void *key_a, const void *key_b) { if(key_a != NULL) { if(key_b != NULL) { return host_address_compare((const host_address*)key_a, (const host_address*)key_b); } else { return -1; } } else { return (key_b == NULL)?0:1; } } void* ptr_set_iterator_hasnext_next_value(ptr_set_iterator *iterp) { if(ptr_set_iterator_hasnext(iterp)) { ptr_node *node = ptr_set_iterator_next_node(iterp); void *ptr = node->value; return ptr; } else { return NULL; } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/ptr_set_debug.c0000644000000000000000000000013214505005532022322 xustar000000000000000030 mtime=1695812442.381981315 30 atime=1695812445.791030139 30 ctime=1695812494.667730152 yadifa-2.6.5-11201/lib/dnscore/src/ptr_set_debug.c0000664000374500037450000001676714505005532022305 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #define _PTR_SET_COLLECTION_C #define DEBUG_LEVEL 0 #include "dnscore/ptr_set_debug.h" #include "dnscore/zalloc.h" #undef malloc #undef free #undef realloc #undef calloc #undef debug_mtest #undef debug_stat #undef debug_mallocated /* * The following macros are defining relevant fields in the node */ /* * Access to the field that points to the left child */ #define AVL_LEFT_CHILD(node) ((node)->children.lr.left) /* * Access to the field that points to the right child */ #define AVL_RIGHT_CHILD(node) ((node)->children.lr.right) /* * Access to the field that points to one of the children (0: left, 1: right) */ #define AVL_CHILD(node,id) ((node)->children.child[(id)]) /* * OPTIONAL : Access to the field that points the parent of the node. * * This field is optional but is mandatory if AVL_HAS_PARENT_POINTER is not 0 */ #define AVL_PARENT(node) ((node)->parent) /* * Access to the field that keeps the balance (a signed byte) */ #define AVL_BALANCE(node) ((node)->balance) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE void* /* * */ #define AVL_REFERENCE_FORMAT_STRING "%p" #define AVL_REFERENCE_FORMAT(reference) ((void*)reference) /* * A macro to initialize a node and setting the reference */ #define AVL_INIT_NODE(node,reference) node->key = reference /* * A macro to allocate a new node */ #define AVL_ALLOC_NODE(node,reference) node=((AVL_NODE_TYPE*)debug_malloc_unmonitored(sizeof(AVL_NODE_TYPE)));memset(node, 0, sizeof(AVL_NODE_TYPE)) /* * A macro to free a node */ #define AVL_FREE_NODE(node) debug_free_unmonitored(node) /* * A macro to print the node */ #define AVL_DUMP_NODE(node) format("node@%p",(node)); /* * A macro that returns the reference field of the node. * It must be of type REFERENCE_TYPE */ #define AVL_REFERENCE(node) (node)->key #define AVL_REFERENCE_IS_POINTER TRUE #define AVL_REFERENCE_IS_CONST FALSE #define AVL_TERNARYCMP 1 #if !AVL_TERNARYCMP /* * A macro to compare two references * Returns TRUE if and only if the references are equal. */ #define AVL_ISEQUAL(reference_a,reference_b) (tree->compare((reference_a),(reference_b)) == 0) /* * A macro to compare two references * Returns TRUE if and only if the first one is bigger than the second one. */ #define AVL_ISBIGGER(reference_a,reference_b) (tree->compare((reference_a),(reference_b)) > 0) #else #define AVL_COMPARE(reference_a,reference_b) (tree->compare((reference_a),(reference_b))) #endif /* * Copies the payload of a node * It MUST NOT copy the "proprietary" node fields : children, parent, balance */ //#define AVL_COPY_PAYLOAD(node_trg,node_src) {(node_trg)->data = (node_src)->data;(node_trg)->key = (node_src)->key;} #define AVL_COPY_PAYLOAD(node_trg,node_src) {(node_trg)->data = (node_src)->data;(node_trg)->key = (node_src)->key;} /* * A macro to preprocess a node before it is preprocessed for a delete (detach) * If there was anything to do BEFORE deleting a node, we would do it here * After this macro is exectuted, the node * _ is detached, then deleted with FREE_NODE * _ has got its content overwritten by the one of another node, then the other * node is deleted with FREE_NODE */ #define AVL_NODE_DELETE_CALLBACK(node) #include "dnscore/avl.c.inc" int ptr_set_debug_ptr_node_compare(const void *node_a, const void *node_b) { ssize_t a = (ssize_t)node_a; ssize_t b = (ssize_t)node_b; ssize_t d = b - a; #if __SIZEOF_POINTER__ == 8 if((d & 0xffffffffULL) == 0) { d >>= 32; } #endif return (int)d; } int ptr_set_debug_asciizp_node_compare(const void *node_a, const void *node_b) { return strcmp((const char*)node_a, (const char*)node_b); } int ptr_set_debug_dnsname_node_compare(const void *node_a, const void *node_b) { return dnsname_compare((const u8*)node_a, (const u8*)node_b); } // key = fqdn (cannot be NULL) int ptr_set_debug_dnslabel_node_compare(const void *node_a, const void *node_b) { const u8 *a = (const u8*)node_a; const u8 *b = (const u8*)node_b; int n = MIN(*a, *b) + 1; return memcmp(a, b, n); } int ptr_set_debug_nullable_asciizp_node_compare(const void *node_a, const void *node_b) { if(node_a != NULL) { if(node_b != NULL) { return strcmp((const char*)node_a, (const char*)node_b); } else { return -1; } } else { return (node_b == NULL)?0:1; } } int ptr_set_debug_nullable_dnsname_node_compare(const void *node_a, const void *node_b) { if(node_a != NULL) { if(node_b != NULL) { return dnsname_compare((const u8*)node_a, (const u8*)node_b); } else { return -1; } } else { return (node_b == NULL)?0:1; } } int ptr_set_debug_host_address_node_compare(const void *node_a, const void *node_b) { if(node_a != NULL) { if(node_b != NULL) { return host_address_compare((const host_address*)node_a, (const host_address*)node_b); } else { return -1; } } else { return (node_b == NULL)?0:1; } } void* ptr_set_debug_iterator_hasnext_next_value(ptr_set_debug_iterator *iterp) { if(ptr_set_debug_iterator_hasnext(iterp)) { ptr_node_debug *node = ptr_set_debug_iterator_next_node(iterp); void *ptr = node->value; return ptr; } else { return NULL; } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/ptr_vector.c0000644000000000000000000000013014505005532021661 xustar000000000000000030 mtime=1695812442.488982847 29 atime=1695812445.79603021 29 ctime=1695812494.66973018 yadifa-2.6.5-11201/lib/dnscore/src/ptr_vector.c0000664000374500037450000010037214505005532021630 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A dynamic-sized array of pointers * * A dynamic-sized array of pointers * * Used for resource record canonization and such. * * @{ */ #include "dnscore/dnscore-config.h" #include "dnscore/ptr_vector.h" #define PTR_QSORT_SMALL 50 #define PTR_QSORT_PIVOT_CHOSE 1 #define PTR_QSORT_DERECURSE 1 #define PTR_QSORT_DERECURSE_DEPTH 64 #define PTR_VECTOR_RESTRICTED_SIZE_INCREASE 16 #if PTR_VECTOR_RESTRICTED_SIZE_INCREASE <= 0 #error "PTR_VECTOR_RESTRICTED_SIZE_INCREASE must be > 0" #endif /** * Initialises a vector structure with a size of PTR_VECTOR_DEFAULT_SIZE entries * * @param v a pointer to the ptr_vector structure to initialise */ void ptr_vector_init(ptr_vector* v) { v->size = PTR_VECTOR_DEFAULT_SIZE; MALLOC_OR_DIE(void**, v->data, v->size * sizeof(void*), PTR_VECTOR_TAG); v->offset = -1; } /** * Initialises a vector structure with a size of PTR_VECTOR_DEFAULT_SIZE entries * * @param v a pointer to the ptr_vector structure to initialise * @param initial_capacity the size to allocate to start with */ void ptr_vector_init_ex(ptr_vector* v, u32 initial_capacity) { v->size = initial_capacity; if(initial_capacity > 0) { MALLOC_OR_DIE(void**, v->data, v->size * sizeof(void*), PTR_VECTOR_TAG); } else { v->data = NULL; } v->offset = -1; } /** * Initialises a vector as a copy as another vector. * The reserved size is the size of the original plus the extra size. * * @param v a pointer to the ptr_vector structure to initialise * @param original the vector to copy * @param extra_size the amount of reserved slots to allocate */ void ptr_vector_init_copy(ptr_vector* v, const ptr_vector* original, u32 extra_size) { assert(ptr_vector_size(original) >= 0); ptr_vector_init_ex(v, ptr_vector_size(original) + extra_size); if(ptr_vector_last_index(original) >= 0) // => size > 0 => v->data != NULL { assert(original->data != NULL && v->data != NULL); memcpy(v->data, original->data, ptr_vector_size(original) * sizeof(void*)); // scan-build false positive } v->offset = original->offset; } /** * Initialises a vector as a copy as another vector plus onz item added * The reserved size is the size of the original plus one * * @param v a pointer to the ptr_vector structure to initialise * @param original the vector to copy * @param data an item to add */ void ptr_vector_init_copy_append(ptr_vector* v, const ptr_vector* original, void *data) { assert(ptr_vector_size(original) >= 0); ptr_vector_init_ex(v, ptr_vector_size(original) + 1); if(ptr_vector_last_index(original) >= 0) { assert(original->data != NULL && v->data != NULL); memcpy(v->data, original->data, ptr_vector_size(original) * sizeof(void*)); } v->offset = original->offset; ptr_vector_append(v, data); } /** * Initialises a vector as a copy as another vector plus a few items added * The reserved size is the size of the original plus the data size. * * @param v a pointer to the ptr_vector structure to initialise * @param original the vector to copy * @param data an array of pointers * @param data_size the size of the data array */ void ptr_vector_init_copy_append_array(ptr_vector* v, const ptr_vector* original, void *data, u32 data_size) { ptr_vector_init_ex(v, ptr_vector_size(original) + data_size); if(ptr_vector_last_index(original) >= 0) // A faster way to test if size > 0 => v->data != NULL { assert(original->data != NULL && v->data != NULL); memcpy(v->data, original->data, ptr_vector_size(original) * sizeof(void*)); // scan-build false positive: v->data is not NULL } v->offset = original->offset; ptr_vector_append_array(v, data, data_size); } /** * Calls the callback on every pointer stored in the vector. * Frees the memory used by a vector structure * * @param v a pointer to the ptr_vector structure */ void ptr_vector_callback_and_destroy(ptr_vector *v, callback_function free_memory) { ptr_vector_callback_and_clear(v, free_memory); v->size = -1; free(v->data); v->data = NULL; } /** * Frees the memory used by a vector structure (not the vector structure itself) * * @param v a pointer to the ptr_vector structure */ void ptr_vector_destroy(ptr_vector* v) { v->size = -1; v->offset = -1; free(v->data); v->data = NULL; } /** * Empties the vector (does not release memory) * * @param v a pointer to the ptr_vector structure */ void ptr_vector_clear(ptr_vector* v) { v->offset = -1; } /** * Changes the capacity of a vector to the specified size * The new size SHOULD be enough to keep the current content * of the vector. Failing to do so will most likely result * into a crash or a leak of the pointers lost in the operation. * * Note that when shrinking, the capacity is not really changed. * * * @param v a pointer to the ptr_vector structure * @param newsize */ void ptr_vector_resize(ptr_vector*v, s32 newsize) { void** data; assert(newsize >= 0); assert(v->offset >= -1); assert(v->size >= 0); if(v->offset >= 0) { if(newsize > v->offset + 1) { MALLOC_OR_DIE(void**, data, newsize * sizeof(void*), PTR_VECTOR_TAG); /* Only the data up to v->offset (included) is relevant */ MEMCOPY(data, v->data, (v->offset + 1) * sizeof(void*)); #if DEBUG if(v->data != NULL) { memset(v->data, 0xff, v->size * sizeof(void*)); } #endif free(v->data); v->data = data; v->size = newsize; } else { v->offset = newsize - 1; } } else { if(newsize != v->size) { free(v->data); if(newsize > 0) { MALLOC_OR_DIE(void**, data, newsize * sizeof(void*), PTR_VECTOR_TAG); } else { #if DEBUG #pragma message ("Should set data to NULL and keep newsize to 0 but scan-build couldn't handle it. DEBUG builds only.") MALLOC_OR_DIE(void**, data, sizeof(void*), PTR_VECTOR_TAG); newsize = 1; #else data = NULL; newsize = 0; #endif } v->data = data; v->size = newsize; } } } /** * Ensures the vector has enough capacity to accommodate a * specified number of items * * @param v a pointer to the ptr_vector structure * @param reqsize the minimum size of the vector */ void ptr_vector_ensures(ptr_vector*v, s32 reqsize) { if(v->size >= 0) { if(v->size < reqsize) { ptr_vector_resize(v, reqsize); } } else { if(reqsize > 0) { ptr_vector_init_ex(v, reqsize); } } } void ptr_vector_remove_from(ptr_vector *v, s32 first_bad_index) { assert((first_bad_index >= 0) && (first_bad_index <= v->offset)); v->offset = first_bad_index - 1; } void ptr_vector_remove_after(ptr_vector *v, s32 last_good_index) { assert((last_good_index >= -1) && (last_good_index <= v->offset)); v->offset = last_good_index; } /** * Resizes the capacity so it can at most contain its * current size. * * @param v a pointer to the ptr_vector structure */ void ptr_vector_shrink(ptr_vector*v) { if(v->size != (v->offset + 1)) { ptr_vector_resize(v, v->offset + 1); } } /** * Appends the item (pointer) to the vector * * @param v a pointer to the ptr_vector structure * @param data a pointer to the item */ void ptr_vector_append(ptr_vector* v, void* data) { if(v->offset + 1 >= v->size) { if(v->size == 0) { v->size = PTR_VECTOR_DEFAULT_SIZE; } ptr_vector_resize(v, v->size * 2); } assert(v->data != NULL); v->data[++v->offset] = data; } /** * Appends the item (pointer) to the vector * * @param v a pointer to the ptr_vector structure * @param datap a pointer to the items * @param data_size the number of items to append */ void ptr_vector_append_array(ptr_vector* v, void** datap, u32 data_size) { if(data_size > 0) { while((u32)(v->offset + data_size) >= (u32)v->size) { if(v->size == 0) { v->size = PTR_VECTOR_DEFAULT_SIZE; } ptr_vector_resize(v, v->size * 2); } assert(v->data != NULL); assert(datap != NULL); memcpy(&v->data[++v->offset], datap, data_size * sizeof(void*)); // scan-build false positive: v->data can only be null if data_size is 0, which is not possible } } void ptr_vector_append_vector(ptr_vector *v, ptr_vector *toappend) { ptr_vector_append_array(v, toappend->data, toappend->offset + 1); } /** * Appends the item (pointer) to the vector and try to keep the buffer size at at most * restrictedlimit. * The goal is to avoid a growth of *2 that would go far beyond the restrictedlimit. * The performance is extremely poor when the number of items in the buffer is restrictedlimit or more. * * @param v a pointer to the ptr_vector structure * @param data a pointer to the item * @param restrictedlimit a guideline limit on the size of the vector */ void ptr_vector_append_restrict_size(ptr_vector* v, void* data, u32 restrictedlimit) { assert((v->size >= 0) && (v->offset < v->size) && (v->offset >= -1)); u32 next_offset = (u32)(v->offset + 1); // >= 0 if(next_offset >= (u32)v->size) // size has to be > next_offset { u32 size = (u32)v->size; // unsigned // if the size is not 0 prepare to double it, else set it to a reasonable minimum if(size != 0) // size > 0 { size <<= 1; // if the size is bigger than the restriction, set it to the maximum between the restriction and what we actually need if(size > restrictedlimit) { size = MAX(MIN(restrictedlimit, PTR_VECTOR_DEFAULT_SIZE), next_offset + PTR_VECTOR_RESTRICTED_SIZE_INCREASE); // worst case size = MAX(>0, 0) } } else { size = PTR_VECTOR_DEFAULT_SIZE; // size > 0 } ptr_vector_resize(v, size); } v->data[++v->offset] = data; // scan-build false positive, can only happen if resize called with size = 0, which is impossible } /** * Appends the item (pointer) to the vector * * @param v a pointer to the ptr_vector structure * @param data a pointer to the item */ void* ptr_vector_pop(ptr_vector* v) { if(v->offset >= 0) { return v->data[v->offset--]; } else { return NULL; } } static int ptr_sort_heap_parent(int index) { assert(index > 0); return (index - 1) / 2; } static int ptr_sort_heap_leftchild(int index) { return (index * 2) + 1; } static void ptr_sort_siftdown(void** base, int from, size_t n, ptr_vector_qsort_r_callback *cmp, void *data) { int root = from; int child; while((child = ptr_sort_heap_leftchild(root)) <= (int)n) { int swp = root; if(cmp(base[swp], base[child], data) < 0) { swp = child; } if((child + 1 <= (int)n) && (cmp(base[swp], base[child + 1], data) < 0)) { swp = child + 1; } if(swp == root) { break; } void **tmp = base[swp]; base[swp] = base[root]; base[root] = tmp; root = swp; } } static void ptr_sort_heapify(void **base, size_t n, ptr_vector_qsort_r_callback *cmp, void *data) { int start = ptr_sort_heap_parent(n - 1); while(start >= 0) { ptr_sort_siftdown(base, start, n - 1, cmp, data); --start; } } void ptr_sort_heapsort(void **base, size_t n, ptr_vector_qsort_r_callback *cmp, void *data) { if(n > 2) { ptr_sort_heapify(base, n, cmp, data); size_t end = n - 1; while(end > 0) { void **tmp = base[0]; base[0] = base[end]; base[end] = tmp; --end; ptr_sort_siftdown(base, 0, end, cmp, data); } } else if(n == 2) { if(cmp(base[0], base[1], data) > 0) { void **tmp = base[0]; base[0] = base[1]; base[1] = tmp; } } } void ptr_sort_insertion(void **base, size_t n, ptr_vector_qsort_r_callback *cmp, void *data) { for(ssize_t i = 1; i < (ssize_t)n; ++i) { void **tmp = base[i]; ssize_t j = i - 1; for(; (j >= 0) && (cmp(base[j], tmp, data) > 0); --j) { base[j + 1] = base[j]; } base[j + 1] = tmp; } } void ptr_sort3_bubble(void **base, size_t n, ptr_vector_qsort_r_callback *cmp, void *data) { for(size_t i = 0; i < n; ++i) { for(size_t j = i + 1; j < n; ++j) { if(cmp(base[i], base[j], data) > 0) { void **tmp = base[j]; base[j] = base[i]; base[i] = tmp; } } } } struct ptr_sort3_quicksort2_stack_cell { void **base; void **limit; }; static void ptr_sort_quicksort(void **base, size_t n, ptr_vector_qsort_callback *cmp) { void **limit = &base[n]; ssize_t sp = -1; struct ptr_sort3_quicksort2_stack_cell stack[PTR_QSORT_DERECURSE_DEPTH]; //ssize_t msp = -1; for(;;) { if(limit - base <= PTR_QSORT_SMALL) { //ptr_sort_insertion(base, limit - base, cmp); for(void **ip = base + 1; ip < limit; ++ip) //for(ssize_t i = 1; i < (ssize_t)n; ++i) { void *tmp = *ip; void **jp = ip - 1; for(; (jp >= base) && (cmp(*jp, tmp) > 0); --jp) { jp[1] = *jp; // base[j + 1] = base[j]; } jp[1] = tmp; //base[j + 1] = tmp; } if(sp >= 0) { //if(sp > msp) msp = sp; base = stack[sp].base; limit = stack[sp--].limit; continue; } return; } // choose a good enough pivot // doing this, start sorting void **hip = limit - 1; void **lop = base; void *pivot; { void **middlep = &base[(limit - base) >> 1]; // A B C // A > B ? if(cmp(*lop, *middlep) > 0) { // A > C ? if(cmp(*lop, *hip) > 0) { // A is the highest: ? ? A if(cmp(*middlep, *hip) > 0) { // C is the smallest: C B A register void *tmp = *lop; // t = A *lop = *hip; // A = C *hip = tmp; // C = t } else { // B is the smallest: B C A register void *tmp = *lop; // t = A *lop = *middlep; // A = B *middlep = *hip; // B = C *hip = tmp; // C = t } } else // A <= C { // B A C register void *tmp = *lop; // t = A *lop = *middlep; // A = B *middlep = tmp; // B = t } } // A <= B else { // B > C ? if(cmp(*middlep, *hip) > 0) { // B is the highest: ? ? B if(cmp(*lop, *hip) > 0) { // C is the smallest: C A B register void *tmp = *lop; // t = A *lop = *hip; // A = C *hip = *middlep; // C = B *middlep = tmp; // B = t } else { // A is the smallest: A C B register void *tmp = *middlep; // t = B *middlep = *hip; // B = C *hip = tmp; // C = t } } else // B <= C { // A B C } } pivot = *middlep; } // 0 is already < pivot // last is already > pivot // continue from there ++lop; --hip; for(;;) { while(cmp(*lop, pivot) < 0) // while smaller than pivot { ++lop; } while(cmp(*hip, pivot) > 0) // while bigger than pivot { --hip; } ssize_t d = hip - lop; if(d <= 1) { if(d > 0) { register void *tmp = *lop; *lop = *hip; *hip = tmp; } else { hip = lop; } break; } // exchange two values (<= pivot with >= pivot) register void *tmp = *lop; *lop = *hip; *hip = tmp; ++lop; --hip; } size_t first = hip - base; size_t second = limit - hip; assert(sp < PTR_QSORT_DERECURSE_DEPTH); if(first > second) { stack[++sp].base = base; stack[sp].limit = hip; base = hip; } else { stack[++sp].base = hip; stack[sp].limit = limit; limit = hip; } } } /** * Sort the content of the vector using the compare callback * * @param v a pointer to the ptr_vector structure * @param compare comparison callback */ void ptr_vector_qsort(ptr_vector* v, ptr_vector_qsort_callback compare) { if(v->offset > 0) /* at least 2 items */ { ptr_sort_quicksort(v->data, v->offset + 1, compare); } } static void ptr_sort_quicksort_r(void **base, size_t n, ptr_vector_qsort_r_callback *cmp, void *data) { void **limit = &base[n]; ssize_t sp = -1; struct ptr_sort3_quicksort2_stack_cell stack[PTR_QSORT_DERECURSE_DEPTH]; //ssize_t msp = -1; for(;;) { if(limit - base <= PTR_QSORT_SMALL) { //ptr_sort_insertion(base, limit - base, cmp, data); for(void **ip = base + 1; ip < limit; ++ip) //for(ssize_t i = 1; i < (ssize_t)n; ++i) { void *tmp = *ip; void **jp = ip - 1; for(; (jp >= base) && (cmp(*jp, tmp, data) > 0); --jp) { jp[1] = *jp; // base[j + 1] = base[j]; } jp[1] = tmp; //base[j + 1] = tmp; } if(sp >= 0) { //if(sp > msp) msp = sp; base = stack[sp].base; limit = stack[sp--].limit; continue; } return; } // choose a good enough pivot // doing this, start sorting void **hip = limit - 1; void **lop = base; void *pivot; { void **middlep = &base[(limit - base) >> 1]; // A B C // A > B ? if(cmp(*lop, *middlep, data) > 0) { // A > C ? if(cmp(*lop, *hip, data) > 0) { // A is the highest: ? ? A if(cmp(*middlep, *hip, data) > 0) { // C is the smallest: C B A register void *tmp = *lop; // t = A *lop = *hip; // A = C *hip = tmp; // C = t } else { // B is the smallest: B C A register void *tmp = *lop; // t = A *lop = *middlep; // A = B *middlep = *hip; // B = C *hip = tmp; // C = t } } else // A <= C { // B A C register void *tmp = *lop; // t = A *lop = *middlep; // A = B *middlep = tmp; // B = t } } // A <= B else { // B > C ? if(cmp(*middlep, *hip, data) > 0) { // B is the highest: ? ? B if(cmp(*lop, *hip, data) > 0) { // C is the smallest: C A B register void *tmp = *lop; // t = A *lop = *hip; // A = C *hip = *middlep; // C = B *middlep = tmp; // B = t } else { // A is the smallest: A C B register void *tmp = *middlep; // t = B *middlep = *hip; // B = C *hip = tmp; // C = t } } else // B <= C { // A B C } } pivot = *middlep; } // 0 is already < pivot // last is already > pivot // continue from there ++lop; --hip; for(;;) { while(cmp(*lop, pivot, data) < 0) // while smaller than pivot { ++lop; } while(cmp(*hip, pivot, data) > 0) // while bigger than pivot { --hip; } ssize_t d = hip - lop; if(d <= 1) { if(d > 0) { register void *tmp = *lop; *lop = *hip; *hip = tmp; } else { hip = lop; } break; } // exchange two values (<= pivot with >= pivot) register void *tmp = *lop; *lop = *hip; *hip = tmp; ++lop; --hip; } size_t first = hip - base; size_t second = limit - hip; assert(sp < PTR_QSORT_DERECURSE_DEPTH); if(first > second) { stack[++sp].base = base; stack[sp].limit = hip; base = hip; } else { stack[++sp].base = hip; stack[sp].limit = limit; limit = hip; } } } void ptr_vector_qsort_r(ptr_vector *v, ptr_vector_qsort_r_callback compare, void *compare_context) { if(v->offset > 0) /* at least 2 items */ { ptr_sort_quicksort_r(v->data, v->offset + 1, compare, compare_context); } } void ptr_vector_insertionsort_r(ptr_vector *v, ptr_vector_qsort_r_callback compare, void *compare_context) { if(v->offset > 0) /* at least 2 items */ { ptr_sort_insertion(v->data, v->offset + 1, compare, compare_context); } } /** * Empties the vector releasing the item memory first * * @param v a pointer to the ptr_vector structure * @param free_memory item free callback */ void ptr_vector_callback_and_clear(ptr_vector* v, callback_function free_memory) { int n = v->offset; int i; for(i = 0; i <= n; i++) { free_memory(v->data[i]); #if DEBUG v->data[i] = NULL; #endif } v->offset = -1; } /** * Look sequentially in the vector for an item using a key and a comparison function * * @param v a pointer to the ptr_vector structure * @param what the key * @param compare the comparison function * * @return the first matching item or NULL if none has been found */ void* ptr_vector_linear_search(const ptr_vector* v, const void* what, ptr_vector_search_callback compare) { int last = v->offset; int i; for(i = 0; i <= last; i++) { void* data = v->data[i]; if(compare(what, data) == 0) { return data; } } return NULL; } s32 ptr_vector_search_ptr_index(const ptr_vector* v, const void* what) { int last = v->offset; int i; for(i = 0; i <= last; i++) { void* data = v->data[i]; if(what == data) { return i; } } return -1; } /** * Look sequentially in the vector for an item using a key and a comparison function, returns the index of the first matching item * * @param v a pointer to the ptr_vector structure * @param what the key * @param compare the comparison function * * @return the first matching item index or -1 if none has been found */ s32 ptr_vector_index_of(const ptr_vector* v, const void* what, ptr_vector_search_callback compare) { s32 last = v->offset; s32 i; for(i = 0; i <= last; i++) { void* data = v->data[i]; if(compare(what, data) == 0) { return i; } } return -1; } /** * Look in the SORTED vector for an item using a key and a comparison function * The callback needs to tell equal (0) smaller (<0) or bigger (>0) * * @param v a pointer to the ptr_vector structure * @param what the key * @param compare the comparison function * * @return the first matching item or NULL if none has been found */ void* ptr_vector_search(const ptr_vector* v, const void* what, ptr_vector_search_callback compare) { int first = 0; int last = v->offset; /* * NOTE: for small intervals, a linear search may be faster * */ while(first < last) { int pivot = (last + first) >> 1; void *item = v->data[pivot]; int cmp = compare(what, item); if(cmp == 0) { return item; } if(cmp < 0) { last = pivot - 1; } else { first = pivot + 1; } } if(first == last) { void *item = v->data[first]; if(compare(what, item) == 0) { return item; } } return NULL; } /** * Look in the SORTED vector for an item using a key and a comparison function * The callback needs to tell equal (0) smaller (<0) or bigger (>0) * * @param v a pointer to the ptr_vector structure * @param what the key * @param compare the comparison function * * @return the first matching item or NULL if none has been found */ s32 ptr_vector_search_index(const ptr_vector* v, const void* what, ptr_vector_search_callback compare) { int first = 0; int last = v->offset; /* * NOTE: for small intervals, a linear search may be faster * */ while(first < last) { int pivot = (last + first) >> 1; void *item = v->data[pivot]; int cmp = compare(what, item); if(cmp == 0) { return pivot; } if(cmp < 0) { last = pivot - 1; } else { first = pivot + 1; } } if(first == last) { void *item = v->data[first]; if(compare(what, item) == 0) { return first; } } return -1; } /** * Inserts a value at position, pushing items from this position up * Potentially very slow. * * @param pv * @param idx */ void ptr_vector_insert_at(ptr_vector *pv, s32 idx, void *val) { assert(idx >= 0); if(idx <= pv->offset) { ptr_vector_ensures(pv, pv->offset + 1); memmove(&pv->data[idx + 1], &pv->data[idx], (pv->offset - idx) * sizeof(void*)); // scan-build false positive as ensures is called with size > 0 and thus data cannot be NULL pv->data[idx] = val; } else { ptr_vector_ensures(pv, idx + 1); memset(&pv->data[pv->offset + 1], 0, &pv->data[idx] - &pv->data[pv->offset + 1]); // scan-build false positive as ensures is called with size > 0 and thus data cannot be NULL pv->data[idx] = val; pv->offset = idx; } } /** * Inserts multiple values at position, pushing items from this position up * Potentially very slow. * * @param pv * @param idx * @param valp an array of pointers that will be inserted * @param n the size of the array of pointers */ void ptr_vector_insert_array_at(ptr_vector *pv, s32 idx, void **valp, u32 n) { assert(idx >= 0); assert(pv->offset >= -1); if(n > 0) { if(idx <= pv->offset) { ptr_vector_ensures(pv, pv->offset + n); memmove(&pv->data[idx + n], &pv->data[idx], (pv->offset - idx + n) * sizeof(void*)); // scan-build false positive as ensures is called with size > 0 and thus data cannot be NULL memcpy(&pv->data[idx], valp, n); } else { ptr_vector_ensures(pv, idx + n); memset(&pv->data[pv->offset + n], 0, &pv->data[idx] - &pv->data[pv->offset + n]); // scan-build false positive as ensures is called with size > 0 and thus data cannot be NULL memcpy(&pv->data[idx], valp, n); pv->offset = idx + n - 1; } } } /** * * Removes a value at position, pulling items above this position down * Potentially very slow * * @param pv * @param idx * @return the removed value */ void* ptr_vector_remove_at(ptr_vector *pv, s32 idx) { void *data = pv->data[idx]; if(idx <= pv->offset) { memmove(&pv->data[idx], &pv->data[idx + 1], (pv->offset - idx) * sizeof(void*)); --pv->offset; } return data; } int ptr_vector_compare_pointers_callback(const void *a, const void *b) { intptr va = (intptr)a; intptr vb = (intptr)b; return va - vb; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/queue-sl.c0000644000000000000000000000013214505005532021234 xustar000000000000000030 mtime=1695812442.437982116 30 atime=1695812445.794030182 30 ctime=1695812494.671730209 yadifa-2.6.5-11201/lib/dnscore/src/queue-sl.c0000664000374500037450000000436714505005532021210 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A node-based single linked list * * A node-based single linked list * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include "dnscore/queue-sl.h" /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/random.c0000644000000000000000000000013214505005532020754 xustar000000000000000030 mtime=1695812442.502983047 30 atime=1695812445.797030225 30 ctime=1695812494.673730237 yadifa-2.6.5-11201/lib/dnscore/src/random.c0000664000374500037450000001606614505005532020727 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoretools Generic Tools * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/random.h" // #define restrict #define RNDCTX_TAG 0x585443444e52 /* * I've written two optimizations over the algorithm (both are avoiding modulos) * */ #define IFJUMP_OVER_MODULO 2 /* 6M -> 7M */ #define SPLITTEDLOOP_OVER_MODULO 2 /* 7M -> 10M : The v2 is slightly faster than the v1 */ /** * * Mersene Twister random generator. * */ /* Create a length 624 array to store the state of the generator */ #define MERSERNE_TWISTER_STATE_SIZE 624 /* used by the auto init to randomise the seed further */ static smp_int random_serial = SMP_INT_INITIALIZER_AT(0x7565edf1); typedef struct random_context random_context; struct random_context { u32 MT[MERSERNE_TWISTER_STATE_SIZE]; #if IFJUMP_OVER_MODULO < 2 u32 MT_index /*= 0*/; #else u32* MT_offset /*= MT*/; #endif }; random_ctx random_init(u32 seed) { random_context *ctx; u32 i; MALLOC_OBJECT_OR_DIE(ctx, random_context, RNDCTX_TAG); u32 *MT = &ctx->MT[0]; MT[0] = seed; for(i = 1; i < MERSERNE_TWISTER_STATE_SIZE; i++) { u32 MT_im1 = MT[i - 1]; MT[i] = (0x6c078965L * (MT_im1 ^ ((MT_im1) >> 30))) + i; } #if IFJUMP_OVER_MODULO < 2 ctx->MT_index = 0; #else ctx->MT_offset = &ctx->MT[0]; #endif return (random_ctx)ctx; } random_ctx random_init_auto() { u64 now = timeus(); now ^= (now >> 32); now ^= (u32)(intptr)thread_self(); now ^= smp_int_get(&random_serial); smp_int_add(&random_serial, 0xc18e2a1d); return random_init((u32)now); } void random_finalize(random_ctx ctx) { free(ctx); } // Generate an array of 624 untempered numbers static void random_generate(random_context *ctx) { #if SPLITTEDLOOP_OVER_MODULO == 2 u32 *MT = &ctx->MT[0]; u32 * restrict MT_i = &MT[0]; u32 * restrict MT_limit_1 = &MT[MERSERNE_TWISTER_STATE_SIZE - 397]; u32 * restrict MT_limit_2 = &MT[MERSERNE_TWISTER_STATE_SIZE - 1 ]; do { u32 y = (MT_i[0] & 0x80000000L) | (MT_i[1] & 0x7fffffffL); MT_i[0] = MT_i[397] ^ (y >> 1); if((y & 1) == 1) { MT_i[0] ^= 0x9908b0dfL; } } while(++MT_i < MT_limit_1); /* i = MERSERNE_TWISTER_STATE_SIZE - 397 */ do { u32 y = (MT_i[0] & 0x80000000L) | (MT_i[1] & 0x7fffffffL); MT_i[0] = MT_i[-(MERSERNE_TWISTER_STATE_SIZE - 397)] ^ (y >> 1); if((y & 1) == 1) { MT_i[0] ^= 0x9908b0dfL; } } while(++MT_i < MT_limit_2); /* i = MERSERNE_TWISTER_STATE_SIZE - 1 */ { u32 y = (MT[MERSERNE_TWISTER_STATE_SIZE - 1]&0x80000000L) | (MT[ 0 ] & 0x7fffffffL); MT[MERSERNE_TWISTER_STATE_SIZE - 1] = MT[ 396 ] ^ (y >> 1); if((y & 1) == 1) { MT[MERSERNE_TWISTER_STATE_SIZE - 1] ^= 0x9908b0dfL; } } #elif SPLITTEDLOOP_OVER_MODULO == 1 u32 *MT = &ctx->MT[0]; u32 i; for(i = 0; i < MERSERNE_TWISTER_STATE_SIZE - 397; i++) { u32 y = (MT[i]&0x80000000L) | (MT[ i + 1 ] & 0x7fffffffL); MT[i] = MT[ i + 397 ] ^ (y >> 1); if((y & 1) == 1) { MT[i] ^= 0x9908b0dfL; } } /* i = MERSERNE_TWISTER_STATE_SIZE - 397 */ for(; i < MERSERNE_TWISTER_STATE_SIZE - 1; i++) { u32 y = (MT[i]&0x80000000L) | (MT[ i + 1 ] & 0x7fffffffL); MT[i] = MT[i - (MERSERNE_TWISTER_STATE_SIZE - 397) ] ^ (y >> 1); if((y & 1) == 1) { MT[i] ^= 0x9908b0dfL; } } /* i = MERSERNE_TWISTER_STATE_SIZE - 1 */ { u32 y = (MT[MERSERNE_TWISTER_STATE_SIZE - 1]&0x80000000L) | (MT[ 0 ] & 0x7fffffffL); MT[MERSERNE_TWISTER_STATE_SIZE - 1] = MT[ 396 ] ^ (y >> 1); if((y & 1) == 1) { MT[MERSERNE_TWISTER_STATE_SIZE - 1] ^= 0x9908b0dfL; } } #else u32 *MT = &ctx->MT[0]; u32 i; for(i = 0; i < MERSERNE_TWISTER_STATE_SIZE; i++) { u32 y = (MT[i]&0x80000000L) | (MT[(i + 1) % MERSERNE_TWISTER_STATE_SIZE] & 0x7fffffffL); MT[i] = MT[(i + 397) % MERSERNE_TWISTER_STATE_SIZE] ^ (y >> 1); if((y & 1) == 1) { MT[i] ^= 0x9908b0dfL; } } #endif } u32 random_next(random_ctx ctx_) { random_context *ctx = (random_context*)ctx_; #if IFJUMP_OVER_MODULO < 2 if(ctx->MT_index == 0) { random_generate(ctx); } #else if(ctx->MT_offset == ctx->MT) { random_generate(ctx); } #endif #if IFJUMP_OVER_MODULO == 0 u32 y = ctx->MT[ctx->MT_index++]; ctx->MT_index %= MERSERNE_TWISTER_STATE_SIZE; #elif IFJUMP_OVER_MODULO == 1 u32 y = ctx->MT[ctx->MT_index++]; if(ctx->MT_index == MERSERNE_TWISTER_STATE_SIZE) { ctx->MT_index = 0; } #elif IFJUMP_OVER_MODULO == 2 u32 y = *ctx->MT_offset++; if(ctx->MT_offset == &ctx->MT[MERSERNE_TWISTER_STATE_SIZE]) { ctx->MT_offset = ctx->MT; } #endif y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680L; y ^= (y << 15) & 0xefc60000L; y ^= (y >> 18); return y; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/rc.c0000644000000000000000000000013214505005532020100 xustar000000000000000030 mtime=1695812442.457982403 30 atime=1695812445.794030182 30 ctime=1695812494.675730266 yadifa-2.6.5-11201/lib/dnscore/src/rc.c0000664000374500037450000000606714505005532020053 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading mutexes, ... * @ingroup dnscore * @brief * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/logger.h" #include "dnscore/rc.h" #define MODULE_MSG_HANDLE g_system_logger void rc_init_vtbl(rc_vtbl *vtbl, rc_free_method *free_callback, mutex_t *mtx) { vtbl->free_callback = free_callback; vtbl->mtx = mtx; } void rc_finalize_vtbl(rc_vtbl *vtbl) { vtbl->free_callback = NULL; vtbl->mtx = NULL; } void rc_set_internal(rc_s *rc, rc_vtbl *vtbl) { rc->vtbl = vtbl; rc->count = 0; } void rc_aquire_internal(rc_s *rc) { mutex_lock(rc->vtbl->mtx); ++rc->count; mutex_unlock(rc->vtbl->mtx); } void rc_release_internal(rc_s *rc, void *data) { mutex_lock(rc->vtbl->mtx); if(--rc->count > 0) { mutex_unlock(rc->vtbl->mtx); } else { if(rc->count < 0) { // oopsie log_err("negative RC count: %i rc=%p data=%p", rc->count, rc, data); logger_flush(); // then abort() abort(); } mutex_unlock(rc->vtbl->mtx); rc->vtbl->free_callback(data); } } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/rewind-input-stream.c0000644000000000000000000000013214505005532023412 xustar000000000000000030 mtime=1695812442.411981744 30 atime=1695812445.793030168 30 ctime=1695812494.677730295 yadifa-2.6.5-11201/lib/dnscore/src/rewind-input-stream.c0000664000374500037450000002537214505005532023365 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include #include #if DEBUG #include "dnscore/logger.h" #define MODULE_MSG_HANDLE g_system_logger extern logger_handle* g_system_logger; #endif #include "dnscore/rewind-input-stream.h" #define REWIND_INPUT_STREAM_TAG 0x53495246465542 /* BUFFERIS */ /* *buffer buffer size *| | *v v *[0123456... ] * ^ ^ * |<->| * | buffer offset * | * read position * * <-> is rewind relative * */ typedef struct rewind_input_stream_data rewind_input_stream_data; struct rewind_input_stream_data { input_stream filtered; #if DEBUG u64 offset; #endif s32 buffer_size; // amount of the rewind that's filled s32 buffer_offset; // position in the rewind s32 rewind_relative;// bool marked; bool marked; u8 buffer[]; }; static ya_result rewind_input_stream_read(input_stream *stream, void *buffer, u32 len); static void rewind_input_stream_close(input_stream *stream); static ya_result rewind_input_stream_skip(input_stream *stream, u32 len); static const input_stream_vtbl rewind_input_stream_vtbl = { rewind_input_stream_read, rewind_input_stream_skip, rewind_input_stream_close, "rewind_input_stream" }; /** *Marks the stream as the new earliest beginning for a rewind. * *@param stream *@return */ void rewind_input_stream_mark(input_stream *stream) { rewind_input_stream_data *data = (rewind_input_stream_data*)stream->data; yassert(stream->vtbl == &rewind_input_stream_vtbl); #if DEBUG log_debug1("rewind_input_stream_mark(%p) (%llu, %u, %u, %u)", stream, data->offset, data->buffer_offset, data->rewind_relative, data->buffer_offset-data->rewind_relative); #endif if(!data->marked) { data->buffer_offset = 0; data->rewind_relative = 0; data->marked = TRUE; #if DEBUG memset(data->buffer, 0xff, data->buffer_size); #endif } else { // If rewind relative is not 0, then memory will have to be moved // else it means that we are at the buffer_offset and thus we don't care // about the past. s32 src_len = data->rewind_relative; if(src_len != 0 && data->buffer_offset != src_len) { memmove(&data->buffer[0], &data->buffer[data->buffer_offset - src_len], src_len); } data->buffer_offset = src_len; data->rewind_relative = src_len; #if DEBUG memset(&data->buffer[data->buffer_offset], 0xff, data->buffer_size - data->buffer_offset); #endif } } void rewind_input_stream_rewind(input_stream *stream, s32 how_much) { rewind_input_stream_data *data = (rewind_input_stream_data*)stream->data; yassert(stream->vtbl == &rewind_input_stream_vtbl); s32 relative = data->rewind_relative + how_much; if(relative <= data->buffer_offset) { data->rewind_relative = how_much; } else { data->rewind_relative = relative; } } void rewind_input_stream_rewind_to_mark(input_stream *stream) { rewind_input_stream_data *data = (rewind_input_stream_data*)stream->data; yassert(stream->vtbl == &rewind_input_stream_vtbl); #if DEBUG log_debug1("rewind_input_stream_rewind_to_mark(%p) (%llu, %u, %u, %u)", stream, data->offset, data->buffer_offset, data->rewind_relative, data->buffer_offset-data->rewind_relative); #endif data->rewind_relative = data->buffer_offset; } static ya_result rewind_input_stream_read(input_stream *stream, void *buffer_, u32 len) { rewind_input_stream_data *data = (rewind_input_stream_data*)stream->data; ya_result ret; u8 *buffer = (u8*)buffer_; #if DEBUG log_debug1("rewind_input_stream_read(%p, %p, %u) (%llu, %u, %u, %u)", stream, buffer, len, data->offset, data->buffer_offset, data->rewind_relative, data->buffer_offset-data->rewind_relative); #endif if(!data->marked) { ret = data->filtered.vtbl->read(&data->filtered, buffer, len); #if DEBUG if(ISOK(ret)) data->offset += len; #endif return ret; } s32 rewind_len = 0; if(data->rewind_relative > 0) { rewind_len = MIN(data->rewind_relative, (s32)len); memcpy(buffer, &data->buffer[data->buffer_offset - data->rewind_relative], rewind_len); data->rewind_relative -= rewind_len; len -= rewind_len; if(len == 0) { return rewind_len; } // still some bytes to read buffer += rewind_len; } // marked ... add to the rewind buffer s32 remaining_space_in_buffer = data->buffer_size - data->buffer_offset; if(remaining_space_in_buffer >= (s32)len) { if(ISOK(ret = data->filtered.vtbl->read(&data->filtered, &data->buffer[data->buffer_offset], len))) { memcpy(buffer, &data->buffer[data->buffer_offset], ret); data->buffer_offset += ret; #if DEBUG data->offset += ret; #endif return ret + rewind_len; } return ret; } else { // we are about to overflow the buffer // two implementation choices: // _ remove the mark and continue // _ cut the read to fill the buffer and return the short read data->marked = FALSE; if(ISOK(ret = data->filtered.vtbl->read(&data->filtered, buffer, len))) { #if DEBUG data->offset += ret; #endif return ret + rewind_len; } return ret; } } static void rewind_input_stream_close(input_stream *stream) { rewind_input_stream_data *data = (rewind_input_stream_data*)stream->data; input_stream_close(&data->filtered); free(data); input_stream_set_void(stream); } static ya_result rewind_input_stream_skip(input_stream *stream, u32 len) { rewind_input_stream_data *data = (rewind_input_stream_data*)stream->data; ya_result ret; #if DEBUG log_debug1("rewind_input_stream_skip(%p, %u) (%llu, %u, %u, %u)", stream, len, data->offset, data->buffer_offset, data->rewind_relative, data->buffer_offset-data->rewind_relative); #endif if(!data->marked) { ret = data->filtered.vtbl->skip(&data->filtered, len); #if DEBUG if(ISOK(ret)) data->offset += ret; #endif return ret; } // marked ... add to the rewind buffer s32 rewind_len = 0; if(data->rewind_relative > 0) { rewind_len = MIN(data->rewind_relative, (s32)len); data->rewind_relative -= rewind_len; len -= rewind_len; if(len == 0) { return rewind_len; } // still some bytes to read } s32 remaining_space_in_buffer = data->buffer_size - data->buffer_offset; if(remaining_space_in_buffer >= (s32)len) { if(ISOK(ret = data->filtered.vtbl->read(&data->filtered, &data->buffer[data->buffer_offset], len))) { data->buffer_offset += ret; #if DEBUG data->offset += ret; #endif return ret + rewind_len; } return ret; } else { // we are about to overflow the buffer // two implementation choices: // _ remove the mark and continue // _ cut the read to fill the buffer and return the short read data->marked = FALSE; if(ISOK(ret = data->filtered.vtbl->skip(&data->filtered, len))) { #if DEBUG data->offset += ret; #endif return ret + rewind_len; } return ret; } } void rewind_input_stream_init(input_stream *filtered, input_stream *stream, int rewind_size) { rewind_input_stream_data *data; yassert(rewind_size > 0); yassert(filtered->vtbl != NULL); MALLOC_OR_DIE(rewind_input_stream_data*, data, sizeof(rewind_input_stream_data) + rewind_size, REWIND_INPUT_STREAM_TAG); data->filtered.data = filtered->data; data->filtered.vtbl = filtered->vtbl; #if DEBUG data->offset = 0; memset(data->buffer, 0xff, rewind_size); #endif filtered->data = NULL; filtered->vtbl = NULL; data->buffer_size = rewind_size; data->marked = FALSE; stream->data = data; stream->vtbl = &rewind_input_stream_vtbl; } input_stream* rewind_input_stream_get_filtered(input_stream *bos) { rewind_input_stream_data *data = (rewind_input_stream_data*)bos->data; return &data->filtered; } /** *Returns true iff the input stream is a rewind input stream * *@param bos *@return */ bool is_rewind_input_stream(input_stream *bos) { return bos->vtbl == &rewind_input_stream_vtbl; } /* *@} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/rfc.c0000644000000000000000000000013214505005532020246 xustar000000000000000030 mtime=1695812442.443982203 30 atime=1695812445.794030182 30 ctime=1695812494.679730324 yadifa-2.6.5-11201/lib/dnscore/src/rfc.c0000664000374500037450000010300214505005532020204 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include "dnscore/rfc.h" #include "dnscore/ctrl-rfc.h" #include "dnscore/string_set.h" #include "dnscore/ptr_set.h" #include "dnscore/u32_set.h" #include "dnscore/format.h" #include "dnscore/mutex.h" #define DNSCORE_RFC_C /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ static mutex_t rfc_init_mtx = MUTEX_INITIALIZER; static string_node* class_set = NULL; static string_node* type_set = NULL; static string_node* dnssec_algo_set = NULL; static string_set word_set = NULL; static bool rfc_init_done = FALSE; const class_table qclass[] = { { CLASS_IN, CLASS_IN_NAME }, { CLASS_CS, CLASS_CS_NAME }, { CLASS_CH, CLASS_CH_NAME }, { CLASS_HS, CLASS_HS_NAME }, { CLASS_CTRL, CLASS_CTRL_NAME }, { CLASS_NONE, CLASS_NONE_NAME }, { CLASS_ANY, CLASS_ANY_NAME }, { 0, NULL } }; const type_table qtype[] = { { TYPE_A, TYPE_A_NAME }, // 1 { TYPE_NS, TYPE_NS_NAME }, // 2 { TYPE_MD, TYPE_MD_NAME }, // 3 { TYPE_MF, TYPE_MF_NAME }, // 4 { TYPE_CNAME, TYPE_CNAME_NAME }, // 5 { TYPE_SOA, TYPE_SOA_NAME }, // 6 { TYPE_MB, TYPE_MB_NAME }, // 7 { TYPE_MG, TYPE_MG_NAME }, // 8 { TYPE_MR, TYPE_MR_NAME }, // 9 { TYPE_NULL, TYPE_NULL_NAME }, // 10 { TYPE_WKS, TYPE_WKS_NAME }, // 11 { TYPE_PTR, TYPE_PTR_NAME }, // 12 { TYPE_HINFO, TYPE_HINFO_NAME }, // 13 { TYPE_MINFO, TYPE_MINFO_NAME }, // 14 { TYPE_MX, TYPE_MX_NAME }, // 15 { TYPE_TXT, TYPE_TXT_NAME }, // 16 { TYPE_RP, TYPE_RP_NAME }, // 17 { TYPE_AFSDB, TYPE_AFSDB_NAME }, // 18 { TYPE_X25, TYPE_X25_NAME }, // 19 { TYPE_ISDN, TYPE_ISDN_NAME }, // 20 { TYPE_RT, TYPE_RT_NAME }, // 21 { TYPE_NSAP, TYPE_NSAP_NAME }, // 22 { TYPE_NSAP_PTR, TYPE_NSAP_PTR_NAME }, // 23 { TYPE_SIG, TYPE_SIG_NAME }, // 24 { TYPE_KEY, TYPE_KEY_NAME }, // 25 { TYPE_PX, TYPE_PX_NAME }, // 26 { TYPE_GPOS, TYPE_GPOS_NAME }, // 27 { TYPE_AAAA, TYPE_AAAA_NAME }, // 28 { TYPE_LOC, TYPE_LOC_NAME }, // 29 { TYPE_NXT, TYPE_NXT_NAME }, // 30 { TYPE_EID, TYPE_EID_NAME }, // 31 { TYPE_NIMLOC, TYPE_NIMLOC_NAME }, // 32 { TYPE_SRV, TYPE_SRV_NAME }, // 33 { TYPE_ATMA, TYPE_ATMA_NAME }, // 34 { TYPE_NAPTR, TYPE_NAPTR_NAME }, // 35 { TYPE_KX, TYPE_KX_NAME }, // 36 { TYPE_CERT, TYPE_CERT_NAME }, // 37 { TYPE_A6, TYPE_A6_NAME }, // 38 { TYPE_DNAME, TYPE_DNAME_NAME }, // 39 { TYPE_SINK, TYPE_SINK_NAME }, // 40 { TYPE_OPT, TYPE_OPT_NAME }, // 41 { TYPE_APL, TYPE_APL_NAME }, // 42 { TYPE_DS, TYPE_DS_NAME }, // 43 { TYPE_SSHFP, TYPE_SSHFP_NAME }, // 44 { TYPE_IPSECKEY, TYPE_IPSECKEY_NAME }, // 45 { TYPE_RRSIG, TYPE_RRSIG_NAME }, // 46 { TYPE_NSEC, TYPE_NSEC_NAME }, // 47 { TYPE_DNSKEY, TYPE_DNSKEY_NAME }, // 48 { TYPE_DHCID, TYPE_DHCID_NAME }, // 49 { TYPE_NSEC3, TYPE_NSEC3_NAME }, // 50 { TYPE_NSEC3PARAM, TYPE_NSEC3PARAM_NAME }, // 51 { TYPE_TLSA, TYPE_TLSA_NAME }, // 52 { TYPE_HIP, TYPE_HIP_NAME }, // 55 { TYPE_NINFO, TYPE_NINFO_NAME }, // 56 { TYPE_RKEY, TYPE_RKEY_NAME }, // 57 { TYPE_TALINK, TYPE_TALINK_NAME }, // 58 { TYPE_CDS, TYPE_CDS_NAME }, // 59 { TYPE_CDNSKEY, TYPE_CDNSKEY_NAME }, // 60 { TYPE_OPENPGPKEY, TYPE_OPENPGPKEY_NAME }, // 61 { TYPE_CSYNC, TYPE_CSYNC_NAME }, // 62 { TYPE_SPF, TYPE_SPF_NAME }, // 99 { TYPE_UINFO, TYPE_UINFO_NAME }, // 100 { TYPE_UID, TYPE_UID_NAME }, // 101 { TYPE_GID, TYPE_GID_NAME }, // 102 { TYPE_UNSPEC, TYPE_UNSPEC_NAME }, // 103 { TYPE_NID, TYPE_NID_NAME }, // 104 { TYPE_L32, TYPE_L32_NAME }, // 105 { TYPE_L64, TYPE_L64_NAME }, // 106 { TYPE_LP, TYPE_LP_NAME }, // 107 { TYPE_EUI48, TYPE_EUI48_NAME }, // 108 { TYPE_EUI64, TYPE_EUI64_NAME }, // 109 { TYPE_TKEY, TYPE_TKEY_NAME }, // 249 { TYPE_TSIG, TYPE_TSIG_NAME }, // 250 { TYPE_IXFR, TYPE_IXFR_NAME }, // 251 { TYPE_AXFR, TYPE_AXFR_NAME }, // 252 { TYPE_MAILB, TYPE_MAILB_NAME }, // 253 { TYPE_MAILA, TYPE_MAILA_NAME }, // 254 { TYPE_ANY, TYPE_ANY_NAME }, // 255 { TYPE_URI, TYPE_URI_NAME }, // 256 { TYPE_CAA, TYPE_CAA_NAME }, // 257 { TYPE_AVC, TYPE_AVC_NAME }, // 258 { TYPE_TA, TYPE_TA_NAME }, // 32768 { TYPE_DLV, TYPE_DLV_NAME }, // 32769 #if 1//HAS_CTRL { TYPE_CTRL_SRVCFGRELOAD, TYPE_CTRL_SRVCFGRELOAD_NAME }, { TYPE_CTRL_SRVQUERYLOG, TYPE_CTRL_SRVQUERYLOG_NAME }, { TYPE_CTRL_SRVLOGREOPEN, TYPE_CTRL_SRVLOGREOPEN_NAME }, { TYPE_CTRL_SRVLOGLEVEL, TYPE_CTRL_SRVLOGLEVEL_NAME }, { TYPE_CTRL_SRVSHUTDOWN, TYPE_CTRL_SHUTDOWN_NAME }, { TYPE_CTRL_ZONECFGRELOAD, TYPE_CTRL_ZONECFGRELOAD_NAME }, { TYPE_CTRL_ZONECFGRELOADALL, TYPE_CTRL_ZONECFGRELOADALL_NAME }, { TYPE_CTRL_ZONEFREEZE, TYPE_CTRL_ZONEFREEZE_NAME }, { TYPE_CTRL_ZONEFREEZEALL, TYPE_CTRL_ZONEFREEZEALL_NAME }, { TYPE_CTRL_ZONERELOAD, TYPE_CTRL_ZONERELOAD_NAME }, { TYPE_CTRL_ZONEUNFREEZE, TYPE_CTRL_ZONEUNFREEZE_NAME }, { TYPE_CTRL_ZONEUNFREEZEALL, TYPE_CTRL_ZONEUNFREEZEALL_NAME }, { TYPE_CTRL_ZONESYNC, TYPE_CTRL_ZONESYNC_NAME }, { TYPE_CTRL_ZONENOTIFY, TYPE_CTRL_ZONENOTIFY_NAME }, #endif { 0, NULL } }; const dnssec_algo_table dnssec_algo[] = { /// @note 20160512 gve -- 3 algorithms are not used ( deprecated or not implemented ) // { DNSKEY_ALGORITHM_RSAMD5, DNSKEY_ALGORITHM_RSAMD5_NAME }, // 1 // { DNSKEY_ALGORITHM_DIFFIE_HELLMAN, DNSKEY_ALGORITHM_DIFFIE_HELLMAN_NAME }, // 2 { DNSKEY_ALGORITHM_DSASHA1, DNSKEY_ALGORITHM_DSASHA1_NAME }, // 3 { DNSKEY_ALGORITHM_RSASHA1, DNSKEY_ALGORITHM_RSASHA1_NAME }, // 5 { DNSKEY_ALGORITHM_DSASHA1_NSEC3, DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME }, // 6 { DNSKEY_ALGORITHM_RSASHA1_NSEC3, DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME }, // 7 { DNSKEY_ALGORITHM_RSASHA256_NSEC3, DNSKEY_ALGORITHM_RSASHA256_NSEC3_NAME }, // 8 { DNSKEY_ALGORITHM_RSASHA512_NSEC3, DNSKEY_ALGORITHM_RSASHA512_NSEC3_NAME }, // 10 // { DNSKEY_ALGORITHM_GOST, DNSKEY_ALGORITHM_GOST_NAME }, // 12 { DNSKEY_ALGORITHM_ECDSAP256SHA256, DNSKEY_ALGORITHM_ECDSAP256SHA256_NAME }, // 13 { DNSKEY_ALGORITHM_ECDSAP384SHA384, DNSKEY_ALGORITHM_ECDSAP384SHA384_NAME }, // 14 { DNSKEY_ALGORITHM_ED25519, DNSKEY_ALGORITHM_ED25519_NAME }, // 15 { DNSKEY_ALGORITHM_ED448, DNSKEY_ALGORITHM_ED448_NAME }, // 16 #ifdef DNSKEY_ALGORITHM_DUMMY { DNSKEY_ALGORITHM_DUMMY, DNSKEY_ALGORITHM_DUMMY_NAME }, // 254 #endif { 0, NULL } }; static char *opcode[16] = { "QUERY", // 0 "IQUERY", // 1 obsolete "STATUS", "OPCODE3", "NOTIFY", "UPDATE", "OPCODE6", "OPCODE7", "OPCODE8", // 8 "CTRL", /* special for yadifa client for view the result in verbose mode */ "OPCODE10", "OPCODE11", "OPCODE12", "OPCODE13", "OPCODE14", "OPCODE15" }; static char *rcode[32] = { "NOERROR", // 0 /* No error rfc 1035 */ "FORMERR", // 1 /* Format error rfc 1035 */ "SERVFAIL", // 2 /* Server failure rfc 1035 */ "NXDOMAIN", // 3 /* Name error rfc 1035 */ "NOTIMP", // 4 /* Not implemented rfc 1035 */ "REFUSED", // 5 /* Refused rfc 1035 */ "YXDOMAIN", // 6 /* Name exists when it should not rfc 2136 */ "YXRRSET", // 7 /* RR Set exists when it should not rfc 2136 */ "NXRRSET", // 8 /* RR set that should exist doesn't rfc 2136 */ "NOTAUTH", // 9 /* Server not Authortative for zone rfc 2136 */ // 9 /* Not Authorized rfc 2845 */ "NOTZONE", // 10 /* Name not contained in zone rfc 2136 */ "RCODE11", "RCODE12", "RCODE13", "RCODE14", "RCODE15", "BADVERS", // or BADSIG // 16 /* Bad OPT Version rfc 2671 / rfc 6891 */ "BADKEY", "BADTIME", "BADMODE", "BADNAME", "BADALG", "BADTRUNC", "RCODE23", "RCODE24", "RCODE25", "RCODE26", "RCODE27", "RCODE28", "RCODE29", "RCODE30", "RCODE31" }; static char* rfc_word_get(const char *w) { string_node *node = string_set_insert(&word_set, w); // assumes new value set to 0 if(node->value == 0) { node->key = strdup(w); } if(node->value < 0xffff) { ++node->value; } return (char*)node->key; } static void rfc_word_destroy_cb(string_node *node) { free((char*)node->key);node->key = NULL; } static void rfc_word_destroy() { string_set_callback_and_destroy(&word_set, rfc_word_destroy_cb); } const char* dns_message_opcode_get_name(u16 o) { return opcode[o & 0x0f]; } const char* dns_message_rcode_get_name(u16 r) { return rcode[r & 0x1f]; } const char* dns_class_get_name(u16 c) { switch(c) { case CLASS_IN: return CLASS_IN_NAME; case CLASS_CH: return CLASS_CH_NAME; case CLASS_HS: return CLASS_HS_NAME; case CLASS_CTRL: return CLASS_CTRL_NAME; case CLASS_NONE: return CLASS_NONE_NAME; case CLASS_ANY: return CLASS_ANY_NAME; default: return NULL; } } const char* dns_type_get_name(u16 t) { switch(t) { case TYPE_A: return TYPE_A_NAME; case TYPE_NS: return TYPE_NS_NAME; case TYPE_MD: return TYPE_MD_NAME; case TYPE_MF: return TYPE_MF_NAME; case TYPE_CNAME: return TYPE_CNAME_NAME; case TYPE_SOA: return TYPE_SOA_NAME; case TYPE_MB: return TYPE_MB_NAME; case TYPE_MG: return TYPE_MG_NAME; case TYPE_MR: return TYPE_MR_NAME; case TYPE_NULL: return TYPE_NULL_NAME; case TYPE_WKS: return TYPE_WKS_NAME; case TYPE_PTR: return TYPE_PTR_NAME; case TYPE_HINFO: return TYPE_HINFO_NAME; case TYPE_MINFO: return TYPE_MINFO_NAME; case TYPE_MX: return TYPE_MX_NAME; case TYPE_TXT: return TYPE_TXT_NAME; case TYPE_RP: return TYPE_RP_NAME; case TYPE_AFSDB: return TYPE_AFSDB_NAME; case TYPE_X25: return TYPE_X25_NAME; case TYPE_ISDN: return TYPE_ISDN_NAME; case TYPE_RT: return TYPE_RT_NAME; case TYPE_NSAP: return TYPE_NSAP_NAME; case TYPE_NSAP_PTR: return TYPE_NSAP_PTR_NAME; case TYPE_SIG: return TYPE_SIG_NAME; case TYPE_KEY: return TYPE_KEY_NAME; case TYPE_PX: return TYPE_PX_NAME; case TYPE_GPOS: return TYPE_GPOS_NAME; case TYPE_AAAA: return TYPE_AAAA_NAME; case TYPE_LOC: return TYPE_LOC_NAME; case TYPE_NXT: return TYPE_NXT_NAME; case TYPE_EID: return TYPE_EID_NAME; case TYPE_NIMLOC: return TYPE_NIMLOC_NAME; case TYPE_SRV: return TYPE_SRV_NAME; case TYPE_ATMA: return TYPE_ATMA_NAME; case TYPE_NAPTR: return TYPE_NAPTR_NAME; case TYPE_KX: return TYPE_KX_NAME; case TYPE_CERT: return TYPE_CERT_NAME; case TYPE_A6: return TYPE_A6_NAME; case TYPE_DNAME: return TYPE_DNAME_NAME; case TYPE_SINK: return TYPE_SINK_NAME; case TYPE_OPT: return TYPE_OPT_NAME; case TYPE_APL: return TYPE_APL_NAME; case TYPE_DS: return TYPE_DS_NAME; case TYPE_SSHFP: return TYPE_SSHFP_NAME; case TYPE_IPSECKEY: return TYPE_IPSECKEY_NAME; case TYPE_RRSIG: return TYPE_RRSIG_NAME; case TYPE_NSEC: return TYPE_NSEC_NAME; case TYPE_DNSKEY: return TYPE_DNSKEY_NAME; case TYPE_DHCID: return TYPE_DHCID_NAME; case TYPE_NSEC3: return TYPE_NSEC3_NAME; case TYPE_NSEC3PARAM: return TYPE_NSEC3PARAM_NAME; case TYPE_TLSA: return TYPE_TLSA_NAME; case TYPE_HIP: return TYPE_HIP_NAME; case TYPE_NINFO: return TYPE_NINFO_NAME; case TYPE_RKEY: return TYPE_RKEY_NAME; case TYPE_TALINK: return TYPE_TALINK_NAME; case TYPE_CDS: return TYPE_CDS_NAME; case TYPE_CDNSKEY: return TYPE_CDNSKEY_NAME; case TYPE_OPENPGPKEY: return TYPE_OPENPGPKEY_NAME; case TYPE_SPF: return TYPE_SPF_NAME; case TYPE_UINFO: return TYPE_UINFO_NAME; case TYPE_NID: return TYPE_NID_NAME; case TYPE_L32: return TYPE_L32_NAME; case TYPE_L64: return TYPE_L64_NAME; case TYPE_LP: return TYPE_LP_NAME; case TYPE_EUI48: return TYPE_EUI48_NAME; case TYPE_EUI64: return TYPE_EUI64_NAME; case TYPE_TKEY: return TYPE_TKEY_NAME; case TYPE_TSIG: return TYPE_TSIG_NAME; case TYPE_IXFR: return TYPE_IXFR_NAME; case TYPE_AXFR: return TYPE_AXFR_NAME; case TYPE_MAILB: return TYPE_MAILB_NAME; case TYPE_MAILA: return TYPE_MAILA_NAME; case TYPE_ANY: return TYPE_ANY_NAME; case TYPE_URI: return TYPE_URI_NAME; case TYPE_CAA: return TYPE_CAA_NAME; case TYPE_TA: return TYPE_TA_NAME; case TYPE_DLV: return TYPE_DLV_NAME; #if DNSCORE_HAS_CTRL case TYPE_CTRL_SRVSHUTDOWN: return TYPE_CTRL_SHUTDOWN_NAME; case TYPE_CTRL_ZONEFREEZE: return TYPE_CTRL_ZONEFREEZE_NAME; case TYPE_CTRL_ZONEUNFREEZE: return TYPE_CTRL_ZONEUNFREEZE_NAME; case TYPE_CTRL_ZONERELOAD: return TYPE_CTRL_ZONERELOAD_NAME; case TYPE_CTRL_SRVLOGREOPEN: return TYPE_CTRL_LOGREOPEN_NAME; case TYPE_CTRL_SRVCFGRELOAD: return TYPE_CTRL_SRVCFGRELOAD_NAME; case TYPE_CTRL_ZONECFGRELOAD: return TYPE_CTRL_ZONECFGRELOAD_NAME; case TYPE_CTRL_ZONESYNC: return TYPE_CTRL_ZONESYNC_NAME; case TYPE_CTRL_SRVQUERYLOG: return TYPE_CTRL_SRVQUERYLOG_NAME; case TYPE_CTRL_SRVLOGLEVEL: return TYPE_CTRL_SRVLOGLEVEL_NAME; case TYPE_CTRL_ZONENOTIFY: return TYPE_CTRL_ZONENOTIFY_NAME; //case TYPE_CTRL_%: // return TYPE_CTRL_SCFGMERGE_NAME; //case TYPE_CTRL_CFGSAVE: // return TYPE_CTRL_CFGSAVE_NAME; //case TYPE_CTRL_CFGLOAD: // return TYPE_CTRL_CFGLOAD_NAME; #endif default: return NULL; } } const char* dns_encryption_algorithm_get_name(u16 d) { switch(d) { case DNSKEY_ALGORITHM_RSAMD5: return DNSKEY_ALGORITHM_RSAMD5_NAME; case DNSKEY_ALGORITHM_DIFFIE_HELLMAN: return DNSKEY_ALGORITHM_DIFFIE_HELLMAN_NAME; case DNSKEY_ALGORITHM_DSASHA1: return DNSKEY_ALGORITHM_DSASHA1_NAME; case DNSKEY_ALGORITHM_RSASHA1: return DNSKEY_ALGORITHM_RSASHA1_NAME; case DNSKEY_ALGORITHM_DSASHA1_NSEC3: return DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME; case DNSKEY_ALGORITHM_RSASHA1_NSEC3: return DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME; case DNSKEY_ALGORITHM_RSASHA256_NSEC3: return DNSKEY_ALGORITHM_RSASHA256_NSEC3_NAME; case DNSKEY_ALGORITHM_RSASHA512_NSEC3: return DNSKEY_ALGORITHM_RSASHA512_NSEC3_NAME; case DNSKEY_ALGORITHM_GOST: return DNSKEY_ALGORITHM_GOST_NAME; case DNSKEY_ALGORITHM_ECDSAP256SHA256: return DNSKEY_ALGORITHM_ECDSAP256SHA256_NAME; case DNSKEY_ALGORITHM_ECDSAP384SHA384: return DNSKEY_ALGORITHM_ECDSAP384SHA384_NAME; case DNSKEY_ALGORITHM_ED25519: return DNSKEY_ALGORITHM_ED25519_NAME; case DNSKEY_ALGORITHM_ED448: return DNSKEY_ALGORITHM_ED448_NAME; #ifdef DNSKEY_ALGORITHM_DUMMY case DNSKEY_ALGORITHM_DUMMY: return DNSKEY_ALGORITHM_DUMMY_NAME; #endif default: return NULL; } } /** \brief Check in search table of class for the value * * @param[in] src data to be found in table * @param[out] dst value found in table * * @retval OK * @retval NOK */ int dns_class_from_name(const char *src, u16 *dst) { const string_node *node = string_set_find(&class_set, (const char *)src); if(node != NULL) { u16 c = node->value; *dst = c; return c; } else { /** @note supports CLASS# syntax (rfc 3597) */ if(strncasecmp(src, "CLASS", 5) == 0) { char *endptr; long long int val; src += 5; val = strtoll(src, &endptr, 10); int err = errno; if(!((endptr == src) || (err == EINVAL) || (err == ERANGE) || ((val & 0xffffLL) != val))) { u16 c = htons((u16)val); *dst = c; return c; } } return UNKNOWN_DNS_CLASS; } } /** \brief Check in global table qtype for the value * * @param[in] src data to be found in table * @param[oet] dst value found in table * * @retval OK * @retval NOK */ int dns_type_from_name(const char *src, u16 *dst) { string_node *node = string_set_find(&type_set, (const char *)src); if(node != NULL) { u16 t = node->value; *dst = t; return 0; } else { /** @note supports TYPE# syntax (rfc 3597) */ if(strncasecmp(src, "TYPE", 4) == 0) { char *endptr; long long int val; src += 4; errno = 0; val = strtoll(src, &endptr, 10); int err = errno; if(!((endptr == src) || (err == EINVAL) || (err == ERANGE) || ((val & 0xffffLL) != val))) { u16 t = htons((u16)val); *dst = t; return 1; } } return UNKNOWN_DNS_TYPE; } } /** \brief Check in search table of class for the value * * @param[in] src data to be found in table * @param[out] dst value found in table * * @retval OK * @retval NOK */ int dns_encryption_algorithm_from_name(const char *src, u8 *dst) { const string_node *node = string_set_find(&dnssec_algo_set, (const char *)src); if(node != NULL) { u8 c = node->value; *dst = c; return c; } return DNSSEC_ALGORITHM_UNKOWN; } int dns_class_from_case_name(const char *src, u16 *dst) { char txt[16]; size_t n = strlen(src); if(n >= sizeof(txt)) { return UNKNOWN_DNS_CLASS; } for(size_t i = 0; i < n; i++) { txt[i] = toupper(src[i]); } txt[n] = '\0'; return dns_class_from_name(txt, dst); } int dns_type_from_case_name(const char *src, u16 *dst) { char txt[16]; size_t n = strlen(src); if(n >= sizeof(txt)) { return UNKNOWN_DNS_TYPE; } for(size_t i = 0; i < n; i++) { txt[i] = toupper(src[i]); } txt[n] = '\0'; ya_result ret = dns_type_from_name(txt, dst); return ret; } int dns_encryption_algorithm_from_case_name(const char *src, u8 *dst) { char txt[32]; size_t n = strlen(src); if(n >= sizeof(txt)) { return DNSSEC_ALGORITHM_UNKOWN; } for(size_t i = 0; i < n; i++) { txt[i] = toupper(src[i]); } txt[n] = '\0'; return dns_encryption_algorithm_from_name(txt, dst); } int dns_type_from_case_name_length(const char *src, int src_len, u16 *dst) { char txt[16]; if(src_len >= (int)sizeof(txt)) { return UNKNOWN_DNS_TYPE; } for(int i = 0; i < src_len; i++) { txt[i] = toupper(src[i]); } txt[src_len] = '\0'; ya_result ret = dns_type_from_name(txt, dst); return ret; } static ptr_set protocol_name_to_id_set = PTR_SET_ASCIIZCASE_EMPTY; static u32_set protocol_id_to_name_set = U32_SET_EMPTY; static ptr_set server_name_to_port_set = PTR_SET_ASCIIZCASE_EMPTY; static u32_set server_port_to_name_set = U32_SET_EMPTY; static void protocol_name_to_id_init() { #if __unix__ if(ptr_set_isempty(&protocol_name_to_id_set)) { struct protoent *ent; for(;;) { if((ent = getprotoent()) == NULL) { break; } ptr_node *node = ptr_set_insert(&protocol_name_to_id_set, ent->p_name); node->key = rfc_word_get(ent->p_name); if(node->value != NULL) { continue; } node->value = (void*)(intptr)ent->p_proto; u32_node *id_node = u32_set_insert(&protocol_id_to_name_set, ent->p_proto); id_node->value = node->key; char **a = ent->p_aliases; if(a != NULL) { while(*a != NULL) { node = ptr_set_insert(&protocol_name_to_id_set, *a); if(node->value == NULL) { node->key = rfc_word_get(*a); node->value = (void*)(intptr)ent->p_proto; } ++a; } } } endprotoent(); } #endif } static void protocol_name_to_id_finalize() { ptr_set_destroy(&protocol_name_to_id_set); u32_set_destroy(&protocol_id_to_name_set); } ya_result protocol_name_to_id(const char* name, int *out_proto) { ya_result ret = PARSEINT_ERROR; if(sscanf(name, "%d", &ret) <= 0) { ptr_node *node = ptr_set_find(&protocol_name_to_id_set, name); if(node != NULL) { ret = (int)(intptr)node->value; } } else { if(ret > 255) { ret = INVALID_STATE_ERROR; } } if(ISOK(ret) && (out_proto != NULL)) { *out_proto = ret; } return ret; } ya_result protocol_id_to_name(int proto, char *name, size_t name_len) { u32_node *proto_node = u32_set_find(&protocol_id_to_name_set, proto); if(proto_node != NULL) { return snformat(name, name_len, "%s", (const char*)proto_node->value); } else { return snformat(name, name_len, "%i", proto); } } static void server_name_to_port_init() { #if __unix__ if(ptr_set_isempty(&server_name_to_port_set)) { struct servent *ent; for(;;) { if((ent = getservent()) == NULL) { break; } ptr_node *node = ptr_set_insert(&server_name_to_port_set, ent->s_name); if(node->value != NULL) { continue; } node->key = rfc_word_get(ent->s_name); u16 hport = ntohs(ent->s_port); node->value = (void*)(intptr)hport; u32_node *port_node = u32_set_insert(&server_port_to_name_set, hport); port_node->value = node->key; char **a = ent->s_aliases; if(a != NULL) { while(*a != NULL) { node = ptr_set_insert(&server_name_to_port_set, *a); if(node->value == NULL) { node->key = rfc_word_get(*a); node->value = (void*)(intptr)ntohs(ent->s_port); } ++a; } } } endservent(); } #endif } static void server_name_to_port_finalize() { if(!ptr_set_isempty(&server_name_to_port_set)) { ptr_set_destroy(&server_name_to_port_set); u32_set_destroy(&server_port_to_name_set); } } ya_result server_name_to_port(const char* name, int *out_port) { ya_result ret = PARSEINT_ERROR; if(sscanf(name, "%d", &ret) <= 0) { ptr_node *node = ptr_set_find(&server_name_to_port_set, name); if(node != NULL) { ret = (int)(intptr)node->value; } } else { if(ret > 65535) { ret = INVALID_STATE_ERROR; } } if(ISOK(ret) && (out_port != NULL)) { *out_port = ret; } return ret; } ya_result server_port_to_name(int port, char *name, size_t name_len) { u32_node *port_node = u32_set_find(&server_port_to_name_set, port); if(port_node != NULL) { return snformat(name, name_len, "%s", (const char*)port_node->value); } else { return snformat(name, name_len, "%i", port); } } static void rfc_dnssec_algo_init() { int i; string_set_init(&dnssec_algo_set); for(i = 0; dnssec_algo[i].id != 0; i++) { string_node* node = string_set_insert(&dnssec_algo_set, dnssec_algo[i].data); node->value = dnssec_algo[i].id; } // alias { string_node* node = string_set_insert(&dnssec_algo_set, DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME2); node->value = DNSKEY_ALGORITHM_DSASHA1_NSEC3; } // alias { string_node* node = string_set_insert(&dnssec_algo_set, DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME2); node->value = DNSKEY_ALGORITHM_RSASHA1_NSEC3; } } static void rfc_dnssec_algo_finalize() { string_set_destroy(&dnssec_algo_set); } void rfc_init() { mutex_lock(&rfc_init_mtx); if(rfc_init_done) { mutex_unlock(&rfc_init_mtx); return; } rfc_init_done = TRUE; int i; string_set_init(&class_set); for(i = 0; qclass[i].id != 0; i++) { string_node* node = string_set_insert(&class_set, qclass[i].data); node->value = qclass[i].id; } string_set_init(&type_set); for(i = 0; qtype[i].id != 0; i++) { string_node* node = string_set_insert(&type_set, qtype[i].data); node->value = qtype[i].id; } protocol_name_to_id_init(); server_name_to_port_init(); rfc_dnssec_algo_init(); mutex_unlock(&rfc_init_mtx); } void rfc_finalize() { mutex_lock(&rfc_init_mtx); if(!rfc_init_done) { mutex_unlock(&rfc_init_mtx); return; } rfc_init_done = FALSE; rfc_dnssec_algo_finalize(); server_name_to_port_finalize(); protocol_name_to_id_finalize(); string_set_destroy(&type_set); string_set_destroy(&class_set); rfc_word_destroy(); mutex_unlock(&rfc_init_mtx); } ya_result value_name_table_get_value_from_casename(const value_name_table *table, const char *name, u32 *out_value) { while(table->data != NULL) { if(strcasecmp(table->data, name) == 0) { *out_value = table->id; return SUCCESS; } table++; } return UNKNOWN_NAME; } ya_result value_name_table_get_name_from_value(const value_name_table *table, u32 value, const char** out_name) { while(table->data != NULL) { if(table->id == value) { *out_name = table->data; return SUCCESS; } table++; } return INVALID_ARGUMENT_ERROR; } /* * SOA */ ya_result rr_soa_get_serial(const u8* rdata, u16 rdata_size, u32* out_serial) { s32 soa_size = rdata_size; const u8* soa_start = rdata; u32 len = dnsname_len(soa_start); soa_size -= len; if(soa_size <= 0) { return INCORRECT_RDATA; } soa_start += len; len = dnsname_len(soa_start); soa_size -= len; if(soa_size != 5 * 4) /* Only the 5 32 bits (should) remain */ { return INCORRECT_RDATA; } soa_start += len; if(out_serial != NULL) { *out_serial = ntohl(GET_U32_AT(*soa_start)); } return SUCCESS; } ya_result rr_soa_increase_serial(u8* rdata, u16 rdata_size, u32 increment) { s32 soa_size = rdata_size; u8* soa_start = rdata; u32 len = dnsname_len(soa_start); soa_size -= len; if(soa_size <= 0) { return INCORRECT_RDATA; } soa_start += len; len = dnsname_len(soa_start); soa_size -= len; if(soa_size != 5 * 4) /* Only the 5 32 bits (should) remain */ { return INCORRECT_RDATA; } soa_start += len; SET_U32_AT(*soa_start, htonl(ntohl(GET_U32_AT(*soa_start)) + increment)); return SUCCESS; } ya_result rr_soa_set_serial(u8* rdata, u16 rdata_size, u32 serial) { s32 soa_size = rdata_size; u8* soa_start = rdata; u32 len = dnsname_len(soa_start); soa_size -= len; if(soa_size <= 0) { return INCORRECT_RDATA; } soa_start += len; len = dnsname_len(soa_start); soa_size -= len; if(soa_size != 5 * 4) /* Only the 5 32 bits (should) remain */ { return INCORRECT_RDATA; } soa_start += len; SET_U32_AT(*soa_start, htonl(serial)); return SUCCESS; } ya_result rr_soa_get_minimumttl(const u8* rdata, u16 rdata_size, s32 *out_minimum_ttl) { s32 soa_size = rdata_size; const u8* soa_start = rdata; u32 len = dnsname_len(soa_start); soa_size -= len; if(soa_size <= 0) { return INCORRECT_RDATA; } soa_start += len; len = dnsname_len(soa_start); soa_size -= len; if(soa_size != 5 * 4) /* Only the 5 32 bits (should) remain */ { return INCORRECT_RDATA; } soa_start += len + 16; *out_minimum_ttl = ntohl(GET_U32_AT(*soa_start)); return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/serial.c0000644000000000000000000000013214505005532020753 xustar000000000000000030 mtime=1695812442.412981759 30 atime=1695812445.793030168 30 ctime=1695812494.681730352 yadifa-2.6.5-11201/lib/dnscore/src/serial.c0000664000374500037450000000610514505005532020717 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscore * @ingroup dnscore * @brief serial arithmetic * * @{ * *----------------------------------------------------------------------------*/ //#include "dnscore/dnscore-config.h" #include "dnscore/dnscore-config.h" #include "dnscore/serial.h" /* * SERIAL */ /** * * Returns TRUE iff a > b in serial arithmetic, else FALSE * * @param a * @param b * @return a > b */ bool serial_gt(u32 a, u32 b) { return ( (a < b) && ((b - a) > 0x7fffffff)) || ((a > b) && ((a - b) < 0x7fffffff)); } /** * * Returns TRUE iff a < b in serial arithmetic, else FALSE * * @param a * @param b * @return a < b */ bool serial_lt(u32 a, u32 b) { return ( (a < b) && ((b - a) < 0x7fffffff)) || ((a > b) && ((a - b) > 0x7fffffff)); } /** * * Returns TRUE iff a >= b in serial arithmetic, else FALSE * * @param a * @param b * @return a >= b */ bool serial_ge(u32 a, u32 b) { return (a == b) || ((a < b) && ((b - a) > 0x7fffffff)) || ((a > b) && ((a - b) < 0x7fffffff)); } /** * * Returns TRUE iff a <= b in serial arithmetic, else FALSE * * @param a * @param b * @return a <= b */ bool serial_le(u32 a, u32 b) { return (a == b) || ((a < b) && ((b - a) < 0x7fffffff)) || ((a > b) && ((a - b) > 0x7fffffff)); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/server-setup.c0000644000000000000000000000013214505005532022140 xustar000000000000000030 mtime=1695812442.393981486 30 atime=1695812445.792030153 30 ctime=1695812494.684730395 yadifa-2.6.5-11201/lib/dnscore/src/server-setup.c0000664000374500037450000002643614505005532022115 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include "dnscore/logger.h" #include "dnscore/service.h" #include "dnscore/config_settings.h" #include "dnscore/fdtools.h" #include "dnscore/thread_pool.h" #include "dnscore/logger-output-stream.h" #include "dnscore/chroot.h" #include "dnscore/pid.h" #include "dnscore/identity.h" #include "dnscore/server-setup.h" #include "dnscore/mt_output_stream.h" #include "dnscore/process.h" #include "dnscore/signals.h" #include #if __unix__ #include #endif #include #include #include #if DNSCORE_HAS_LOG_THREAD_TAG void thread_tag_log_tags(); #endif /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger /*------------------------------------------------------------------------------ * FUNCTIONS */ static inline void ttylog_err(const char *format, ...) { va_list args; if(logger_is_running()) { va_start(args, format); logger_handle_vmsg(MODULE_MSG_HANDLE, MSG_ERR, format, args); va_end(args); logger_flush(); } // else { flushout(); osprint(termerr, "error: "); va_start(args, format); vosformat(termerr, format, args); va_end(args); osprintln(termerr, ""); flusherr(); } } /** \brief Damonize the program and set the correct system limitations * * @param[in] config is a config_data structure needed for \b "pid file" * * @return OK * @return Otherwise log_quit will stop the program */ int server_setup_daemon_go_ex(bool parent_exit, bool child_logger_ownership) { #if __unix__ mode_t mask = 0; pid_t pid; struct sigaction sa; /* ------------------------------------------------------------ */ log_info("daemonizing"); if(!config_logger_isconfigured()) { osformatln(termerr, "warning: daemonize enabled with default logging on tty output, no output will be available."); flusherr(); } log_debug("daemonize: stop timer"); logger_flush(); dnscore_stop_timer(); log_debug("daemonize: stop services"); logger_flush(); service_stop_all(); log_debug("daemonize: stop thread pools"); logger_flush(); ya_result error_code; if(FAIL(error_code = thread_pool_stop_all())) { osformatln(termerr, "daemonize: unable to stop all thread pools: %r", error_code); flusherr(); exit(EXIT_FAILURE); } #if DNSCORE_HAS_LOG_THREAD_TAG thread_tag_log_tags(); #endif logger_flush(); logger_stop(); /* Clear file creation mask */ umask(mask); #if DEBUG debug_println("releasing ownership of the logger"); flushout(); #endif logger_release_ownership(); /* Become a session leader to lose controlling TTYs */ if((pid = fork()) < 0) { osformatln(termerr, "[%i] cannot fork: %r", getpid(), ERRNO_ERROR); flusherr(); exit(EXIT_FAILURE); } // if the logger was running, disconnect ownership from the parent and give it to the child if(pid != 0) /* parent */ { #if DEBUG formatln("[%i] first level parent done", getpid()); flushout(); #endif if(parent_exit) { exit(EXIT_SUCCESS); } // else re-enable everything and return logger_start(); #if DNSCORE_HAS_LOG_THREAD_TAG thread_tag_log_tags(); #endif dnscore_reset_timer(); thread_pool_start_all(); service_start_all(); logger_flush(); return pid; } /* Set program in new session */ setsid(); #if __unix__ /* Ensure future opens won't allocate controlling TTYs */ sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if(sigaction(SIGHUP, &sa, NULL) < 0) { osformatln(termerr, "sigaction error: %r", ERRNO_ERROR); flusherr(); exit(EXIT_FAILURE); } #endif /* Stevens way of detaching the program from the parent process, * forking twice */ if((pid = fork()) < 0) { osformatln(termerr, "cannot fork (2nd level): %r", ERRNO_ERROR); flusherr(); exit(EXIT_FAILURE); } if(pid != 0) /* parent */ { #if DEBUG formatln("[%i] second level parent done", getpid()); flushout(); #endif exit(EXIT_SUCCESS); } #if DEBUG debug_osformatln(termout, "taking ownership of the logger (%i)", getpid()); flushout(); #endif g_pid = getpid(); if(child_logger_ownership) { logger_take_ownership(getpid()); } logger_start(); #if DNSCORE_HAS_LOG_THREAD_TAG thread_tag_log_tags(); #endif log_debug("daemonize: start timer"); dnscore_reset_timer(); #if DEBUG // It has been asked to fix the "tmpfile vulnerability" on DEBUG builds. // Although this mode is meant for us (Gery & I), we can imagine that // someone else could have some interest in it too. // So the output file name now includes high-precision time and PID and // will break if the file exists already. // Later, the "server" part will also be modifiable by the caller. char output_file[PATH_MAX]; snformat(output_file, sizeof(output_file), "/tmp/server-%013llx-%05x.std.txt", timeus(), getpid()); debug_osformatln(termout,"redirecting all to '%s'\n", output_file); int file_flags = O_RDWR|O_CREAT|O_EXCL; // ensure no overwrite #else const char *output_file = "/dev/null"; int file_flags = O_RDWR; #endif /* Attach file descriptors 0, 1, and 2 to /dev/null */ flushout(); flusherr(); int tmpfd; if((tmpfd = open_create_ex(output_file, file_flags, 0660)) < 0) { fprintf(stderr, "couldn't get file for redirection: %s '%s'\n", strerror(errno), output_file); fflush(NULL); exit(EXIT_FAILURE); } int tmpfdin; #if DEBUG if((tmpfdin = open_create_ex("/dev/null", O_WRONLY, 0440)) < 0) { fprintf(stderr, "couldn't get file for redirection: %s '%s'\n", strerror(errno), output_file); fflush(NULL); exit(EXIT_FAILURE); } #else tmpfdin = tmpfd; #endif { int fd; if((fd = dup2_ex(tmpfdin, 0)) < 0) { log_err("dup2 failed from %i to %i: %s", tmpfdin, 0, strerror(errno)); exit(EXIT_FAILURE); } if(fd != 0) { log_err("expected fd %d instead of %d", 0, fd); exit(EXIT_FAILURE); } } for(int i = 1; i <= 2; i++) { int fd; if((fd = dup2_ex(tmpfd, i)) < 0) { log_err("dup2 failed from %i to %i: %s", tmpfd, i, strerror(errno)); exit(EXIT_FAILURE); } if(fd != i) { log_err("expected fd %d instead of %d", i, fd); exit(EXIT_FAILURE); } } #if DEBUG debug_osformatln(termout, "detaching from console"); flushout(); #endif log_debug("daemonize: start thread pools"); thread_pool_start_all(); log_debug("daemonize: start services"); service_start_all(); /* Change the current working directory to the root so * we won't prevent file systems from being unmounted. */ #if DEBUG debug_println("daemonized"); flushout(); #endif log_info("daemonized"); logger_flush(); return pid; #else return 0; #endif } void server_setup_daemon_go() { server_setup_daemon_go_ex(TRUE, TRUE); } /// @NOTE 20201105 edf -- pid_file_pathp must be a char** because of managed paths, it cannot be a const char** either ya_result server_setup_env(pid_t *pid, char ** pid_file_pathp, uid_t uid, gid_t gid, u32 setup_flags) { ya_result return_code; if((pid_file_pathp == NULL) || (*pid_file_pathp == NULL)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } #if __unix__ if(setup_flags & SETUP_CORE_LIMITS) { struct rlimit core_limits = {RLIM_INFINITY, RLIM_INFINITY}; if(setrlimit(RLIMIT_CORE, &core_limits) < 0) { ttylog_err("unable to set core dump limit: %r", ERRNO_ERROR); } #if DEBUG else { log_debug("core no-limit set"); } #endif } if(setup_flags & SETUP_ROOT_CHANGE) { log_info("going to jail"); if(FAIL(return_code = chroot_jail())) /* Chroot to new path */ { log_err("failed to jail: %r", return_code); return return_code; } } if(setup_flags & SETUP_ID_CHANGE) { /* Change uid and gid */ if(FAIL(return_code = identity_change(uid, gid))) { ttylog_err("unable to change identity: %r", return_code); return return_code; } } if(setup_flags & SETUP_CREATE_PID_FILE) { /* Setup environment */ if(FAIL(return_code = pid_file_create(pid, *pid_file_pathp, uid, gid))) { ttylog_err("unable to create pid file '%s': %r", *pid_file_pathp, return_code); return return_code; } } #endif return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/service.c0000644000000000000000000000013214505005532021134 xustar000000000000000030 mtime=1695812442.477982689 30 atime=1695812445.795030196 30 ctime=1695812494.686730424 yadifa-2.6.5-11201/lib/dnscore/src/service.c0000664000374500037450000007614514505005532021113 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #if HAS_PTHREAD_SETNAME_NP #if DEBUG #define _GNU_SOURCE 1 #endif #endif #include #include #include "dnscore/ptr_set.h" #include "dnscore/logger.h" #include "dnscore/thread_pool.h" #include "dnscore/service.h" #include "dnscore/thread.h" #include "dnscore/signals.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define SERVICE_WAKE_USING_SIGUSR2 0 // don't use signals static int service_ptr_set_compare(const void *node_a, const void *node_b) { struct service_s *a = (struct service_s *)node_a; struct service_s *b = (struct service_s *)node_b; return strcmp(a->name, b->name); } static ptr_set service_set = {NULL, service_ptr_set_compare}; static mutex_t service_set_mutex = MUTEX_INITIALIZER; static noreturn void* service_thread(void *args) { struct service_worker_s *worker = (struct service_worker_s *)args; yassert(worker != NULL); sigset_t set; sigemptyset(&set); sigaddset(&set, SIGQUIT); sigaddset(&set, SIGTERM); sigaddset(&set, SIGINT); sigaddset(&set, SIGSTOP); sigaddset(&set, SIGCONT); pthread_sigmask(SIG_BLOCK, &set, NULL); struct service_s *desc = (struct service_s *)worker->service; thread_pool_setup_random_ctx(); thread_set_name(desc->name, worker->worker_index, worker->service->worker_count); if(worker->service->worker_count == 1) { #if DNSCORE_HAS_LOG_THREAD_TAG char service_tag[9]; service_tag[8] = '\0'; thread_make_tag(desc->name, worker->worker_index, desc->worker_count, service_tag); logger_handle_set_thread_tag(service_tag); log_debug("service: %s tagged '%s' (pid=%i, thread=%p)", desc->name, service_tag, getpid(), thread_self()); #endif log_debug("service: %s starting", desc->name); } else { #if DNSCORE_HAS_LOG_THREAD_TAG char service_tag[9]; service_tag[8] = '\0'; thread_make_tag(desc->name, worker->worker_index, desc->worker_count, service_tag); logger_handle_set_thread_tag(service_tag); log_debug("service: %s tagged '%s' (pid=%i, thread=%p) (%i/%i)", desc->name, service_tag, getpid(), thread_self(), worker->worker_index + 1, worker->service->worker_count); #endif log_debug("service: %s starting (%i/%i)", desc->name, worker->worker_index + 1, worker->service->worker_count); } if(desc->entry_point != NULL) { worker->return_code = desc->entry_point(worker); log_debug("service: %s terminated with: %r", desc->name, worker->return_code); mutex_lock(&worker->lock); worker->flags = SERVICE_OFF; mutex_unlock(&worker->lock); } else { worker->return_code = SERVICE_WITHOUT_ENTRY_POINT; log_debug("service: NULL entry point", worker->return_code); } thread_pool_destroy_random_ctx(); mutex_lock(&worker->service->wait_lock); cond_notify(&worker->service->wait_cond); mutex_unlock(&worker->service->wait_lock); #if DNSCORE_HAS_LOG_THREAD_TAG logger_handle_clear_thread_tag(); #endif thread_exit(NULL); // unreachable // return NULL; } static void* service_on_main_thread(void *args) { struct service_worker_s *worker = (struct service_worker_s *)args; if(worker == NULL) { log_err("service: with NULL worker"); return NULL; } if(worker->service == NULL) { log_err("service: worker not linked to a service"); return NULL; } if(worker->service->entry_point == NULL) { log_err("service: with NULL entry point"); mutex_lock(&worker->service->wait_lock); cond_notify(&worker->service->wait_cond); mutex_unlock(&worker->service->wait_lock); return NULL; } sigset_t set; sigemptyset(&set); sigaddset(&set, SIGQUIT); sigaddset(&set, SIGTERM); sigaddset(&set, SIGINT); sigaddset(&set, SIGSTOP); sigaddset(&set, SIGCONT); pthread_sigmask(SIG_BLOCK, &set, NULL); struct service_s *desc = (struct service_s *)worker->service; thread_pool_setup_random_ctx(); yassert(worker->service->worker_count == 1); log_debug("service: %s starting", desc->name); thread_set_name(desc->name, 0, 0); #if DNSCORE_HAS_LOG_THREAD_TAG logger_handle_set_thread_tag(desc->name); #endif if(desc->entry_point != NULL) { worker->return_code = desc->entry_point(worker); log_debug("service: %s terminated with: %r", desc->name, worker->return_code); mutex_lock(&worker->lock); worker->flags = SERVICE_OFF; mutex_unlock(&worker->lock); } else { worker->return_code = SERVICE_WITHOUT_ENTRY_POINT; log_debug("service: NULL entry point", worker->return_code); } thread_pool_destroy_random_ctx(); mutex_lock(&worker->service->wait_lock); cond_notify(&worker->service->wait_cond); mutex_unlock(&worker->service->wait_lock); #if DNSCORE_HAS_LOG_THREAD_TAG logger_handle_clear_thread_tag(); #endif return NULL; } static void service_wakeup_no_operation(struct service_s *desc) { (void)desc; } /** * Initialises service with an entry point, a name, and a number of workers * Each worker will know its index (from 0 to count-1). * No threads are started yet after this call. * * @param desc the service * @param entry_point the function of the service, it must be of the type service_main * @param wakeup_function a function that will wakup-up all the workers of the service (e.g. so they can notice a reconfiguration or shutdown) * @param name the name of the service * @param count the number of workers for the service * @return an error code */ int service_init_ex2(struct service_s *desc, service_main *entry_point, service_wakeup *wakeup_function, const char* name, u32 count) { if(count == 0) { return INVALID_ARGUMENT_ERROR; } mutex_lock(&service_set_mutex); bool already_initialised = !desc->_not_initialised; mutex_unlock(&service_set_mutex); if(already_initialised) { log_debug("service: %s instance %p already initialized", name, desc); return SERVICE_ALREADY_INITIALISED; } mutex_init(&desc->wait_lock); cond_init(&desc->wait_cond); desc->name = (char*)name; mutex_lock(&service_set_mutex); ptr_node *node = ptr_set_find(&service_set, desc); mutex_unlock(&service_set_mutex); if(node == NULL) { log_debug("service: %s init %i workers", name, count); desc->entry_point = entry_point; desc->wakeup_all_workers = wakeup_function; desc->name = strdup(name); MALLOC_OR_DIE(struct service_worker_s*, desc->worker, sizeof(struct service_worker_s) * count, SRVCWRKR_TAG); // DON'T POOL desc->worker_count = count; for(u32 i = 0; i < count; i++) { mutex_init(&desc->worker[i].lock); desc->worker[i].service = desc; desc->worker[i].tid = 0; desc->worker[i].worker_index = i; desc->worker[i].return_code = 0; desc->worker[i].flags = 0; } desc->args = NULL; mutex_lock(&service_set_mutex); desc->_not_initialised = FALSE; ptr_set_insert(&service_set, desc); mutex_unlock(&service_set_mutex); return SUCCESS; } else { log_err("service: %s instance %p already initialized, but marked as if not", name, desc); return SERVICE_ALREADY_INITIALISED; } } /** * Initialises service with an entry point, a name, and a number of workers * Each worker will know its index (from 0 to count-1). * No threads are started yet after this call. * * @param desc the service * @param entry_point the function of the service, it must be of the type service_main * @param wakeup_function a function that will wakup-up all the workers of the service (e.g. so they can notice a reconfiguration or shutdown) * @param name the name of the service * @param count the number of workers for the service * @return an error code */ int service_init_ex(struct service_s *desc, service_main *entry_point, const char* name, u32 count) { int ret = service_init_ex2(desc, entry_point, service_wakeup_no_operation, name, count); return ret; } /** * Initialises service with an entry point, a name, and one worker * No threads are started yet after this call. * * This is basically calling service_init_ex(desc, entry_point, name, 1); * * @param desc the service * @param entry_point the function of the service, it must be of the type service_main * @param name the name of the service * @return an error code */ int service_init(struct service_s *desc, service_main *entry_point, const char* name) { int ret = service_init_ex(desc, entry_point, name, 1); return ret; } bool service_initialised(struct service_s *desc) { return !desc->_not_initialised; } /** * Set service args. * * @param desc a pointer to the service * @param args a pointer to the args */ void service_args_set(struct service_s *desc, void *args) { mutex_lock(&desc->wait_lock); desc->args = args; mutex_unlock(&desc->wait_lock); } /** * Get service args. * * @param desc a pointer to the service * * @return a pointer to the args */ void* service_args_get(struct service_s *desc) { mutex_lock(&desc->wait_lock); void *ret = desc->args; mutex_unlock(&desc->wait_lock); return ret; } /** * Stops then waits for all workers of the service. * Then destroy the service and release its content. * * @param desc the service * @return an error code */ int service_finalize(struct service_s *desc) { log_debug("service: %s finalize", STRNULL(desc->name)); if(desc->name == NULL) { return INVALID_STATE_ERROR; } service_stop(desc); service_wait(desc); mutex_lock(&service_set_mutex); ptr_set_delete(&service_set, desc); mutex_unlock(&service_set_mutex); mutex_lock(&desc->wait_lock); for(u32 i = 0; i < desc->worker_count; i++) { mutex_destroy(&desc->worker[i].lock); } ZEROMEMORY(desc->worker, sizeof(struct service_worker_s) * desc->worker_count); free(desc->worker); desc->worker = NULL; desc->worker_count = 0; desc->entry_point = NULL; cond_finalize(&desc->wait_cond); free(desc->name); desc->name = NULL; mutex_lock(&service_set_mutex); desc->_not_initialised = TRUE; mutex_unlock(&service_set_mutex); mutex_unlock(&desc->wait_lock); mutex_destroy(&desc->wait_lock); static const struct service_s dummy_uninitialised_service = UNINITIALIZED_SERVICE; *desc = dummy_uninitialised_service; return SUCCESS; } /** * Starts all workers of the service * If a worker is already running, it is left alone with undefined results. * A service should be fully stopped and waited on before being started again. * * @param desc the service * @return an error code */ int service_start(struct service_s *desc) { log_debug("service: %s start", desc->name); u32 success = 0; u32 failure = 0; #if SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT u32 now = time(NULL); desc->last_seen_alive = now; #endif for(u32 i = 0; i < desc->worker_count; i++) { struct service_worker_s *worker = &desc->worker[i]; mutex_lock(&worker->lock); if(worker->flags == SERVICE_OFF) { worker->flags = SERVICE_START; mutex_unlock(&worker->lock); } else { worker->return_code = SERVICE_ALREADY_RUNNING; mutex_unlock(&worker->lock); log_warn("service_start: %s worker #%u already up and running", desc->name, i); // service worker already up, ignore continue; } if(thread_create(&worker->tid, service_thread, worker) == 0) { log_debug("service_start: worker %i created with id %p", i, worker->tid); success++; } else { int err = ERRNO_ERROR; mutex_lock(&worker->lock); #if SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT worker->last_seen_alive = now; #endif worker->tid = 0; worker->return_code = err; worker->flags = SERVICE_OFF; mutex_unlock(&worker->lock); log_err("service_start: failed with: %r", err); failure++; } } if(failure > 0) { log_err("service_start: service workers did not initialise properly (%u failures over %u workers)", failure, desc->worker_count); if(success > 0) { log_err("service_start: but %u of the workers have been properly initialised", success); } return INVALID_STATE_ERROR; } return success; } /** * Starts a service and waits for its end. * This is meant for services with only one thread. * If used with such a service, no new thread will be started and the service * will be run on the current thread. * It is useful when you have a model where the main thread of the program * could change behaviour with an option. * ie: the server service (nudge nudge, wink wink ...) * * @param desc * @return */ int service_start_and_wait(struct service_s *desc) { int ret; if(desc->worker_count != 1) { ret = service_start(desc); if(ISOK(ret)) { ret = service_wait(desc); } } else { log_debug("service: %s start", desc->name); #if SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT u32 now = time(NULL); desc->last_seen_alive = now; #endif struct service_worker_s *worker = &desc->worker[0]; mutex_lock(&worker->lock); if(worker->flags == SERVICE_OFF) { worker->flags = SERVICE_START; mutex_unlock(&worker->lock); service_on_main_thread(worker); ret = SUCCESS; } else { worker->return_code = SERVICE_ALREADY_RUNNING; mutex_unlock(&worker->lock); log_warn("service_start: %s worker #%u already up and running", desc->name, 0); // service worker already up : cannot main-thread run it ret = service_wait(desc); } } return ret; } /** * Set the status of all workers of the service to "STOP" and sends SIGUSR2 to * each of them. * * The signal is meant to interrupt blocking IOs and the worker should notice * it 'in time' and finish. * * @param desc the service * * @return an error code */ int service_stop(struct service_s *desc) { log_debug("service: %s stop", desc->name); int err = SERVICE_NOT_RUNNING; for(u32 i = 0; i < desc->worker_count; i++) { struct service_worker_s *worker = &desc->worker[i]; mutex_lock(&worker->lock); u8 f = worker->flags; if((f & (SERVICE_START|SERVICE_STOP)) == SERVICE_START) { worker->flags |= SERVICE_STOP; err = SUCCESS; } mutex_unlock(&worker->lock); #if SERVICE_WAKE_USING_SIGUSR2 if((f != 0) && (worker->tid != 0)) { thread_kill(worker->tid, SIGUSR2); } #endif } desc->wakeup_all_workers(desc); return err; } /** * Set the status of all workers of the service to "RECONFIGURE" and sends SIGUSR2 to * each of them. * * The signal is meant to interrupt blocking IOs and the worker should notice * it 'in time' and finish. * * @param desc the service * * @return an error code */ int service_reconfigure(struct service_s *desc) { log_debug("service: %s stop", desc->name); int err = SERVICE_NOT_RUNNING; for(u32 i = 0; i < desc->worker_count; i++) { struct service_worker_s *worker = &desc->worker[i]; mutex_lock(&worker->lock); u8 f = worker->flags; if((f & SERVICE_RECONFIGURE) != SERVICE_RECONFIGURE) { worker->flags |= SERVICE_RECONFIGURE; err = SUCCESS; } mutex_unlock(&worker->lock); #if SERVICE_WAKE_USING_SIGUSR2 if((f != 0) && (worker->tid != 0)) { thread_kill(worker->tid, SIGUSR2); } #endif } desc->wakeup_all_workers(desc); return err; } /** * Waits for all threads of the service to be stopped. * * @param desc the service descriptor * @return */ int service_wait(struct service_s *desc) { log_debug("service: %s wait", desc->name); mutex_lock(&desc->wait_lock); for(int tries = 0;;++tries) { u32 running = desc->worker_count; for(u32 i = 0; i < desc->worker_count; i++) { struct service_worker_s *worker = &desc->worker[i]; mutex_lock(&worker->lock); u8 f = worker->flags; thread_t tid = worker->tid; mutex_unlock(&worker->lock); if(f == SERVICE_OFF) { running--; } else { if(tid != 0) { #if __unix__ if(thread_kill(tid, 0) != 0) { log_err("service: %s thread %p died on us", desc->name, tid); running--; mutex_lock(&worker->lock); worker->flags = SERVICE_OFF; mutex_unlock(&worker->lock); } else #endif { // if the worker is meant to stop but is not stopping yet, then signal it if((worker->flags & (SERVICE_STOP|SERVICE_STOPPING)) == SERVICE_STOP) { if(tries > 0) { if(tries <= 2) { log_info("service: %s thread %p hasn't stopped yet ...", desc->name, tid); #if DEBUG logger_flush(); #endif usleep_ex(500000); // 0.5 seconds } else { log_warn("service: %s thread %p is not stopping ...", desc->name, tid); #if DEBUG logger_flush(); #endif #if __unix__ thread_kill(tid, SIGINT); #endif } } } } } } } if(running == 0) { break; } cond_wait(&desc->wait_cond, &desc->wait_lock); log_debug("service: %s wait ... (%u/%u running)", desc->name, running, desc->worker_count); } mutex_unlock(&desc->wait_lock); for(u32 i = 0; i < desc->worker_count; i++) { struct service_worker_s *worker = &desc->worker[i]; if(worker->tid == 0) { continue; } log_debug("service: %s join ... (%u/%u)", desc->name, i, desc->worker_count); int err = thread_join(worker->tid, NULL); switch(err) { case 0: { // success break; } case EINVAL: { log_err("service: %s thread %p is not joinable", desc->name, worker->tid); break; } case ESRCH: { log_debug("service: %s thread %p does not exist", desc->name, worker->tid); break; } case EDEADLK: { log_err("service: %s thread %p is deadlocked", desc->name, worker->tid); break; } default: { log_warn("service: %s thread %p joining returned an unexpected error code %i", desc->name, worker->tid, err); break; } } mutex_lock(&worker->lock); worker->flags = SERVICE_OFF; worker->tid = 0; mutex_unlock(&worker->lock); } log_debug("service: %s all %u workers are stopped", desc->name, desc->worker_count); return 0; } /** * Returns TRUE if all the workers of the service have notified they had started * * @param desc the service * @return TRUE iff all the workers of the service have notified they started */ bool service_servicing(struct service_s *desc) { for(u32 i = 0; i < desc->worker_count; i++) { struct service_worker_s *worker = &desc->worker[i]; mutex_lock(&worker->lock); u8 f = worker->flags; mutex_unlock(&worker->lock); if((f & (SERVICE_START|SERVICE_STOP|SERVICE_SERVICING|SERVICE_STOPPING)) != (SERVICE_START|SERVICE_SERVICING)) { return FALSE; } } return TRUE; } /** * Only to be called by the worker of the service itself when it has started. * Calling it is not mandatory but give more accuracy to the status of the service. * * @param worker the worker calling this function */ int service_set_servicing(struct service_worker_s *worker) { int err = SERVICE_NOT_RUNNING; log_debug("service: %s running", worker->service->name); mutex_lock(&worker->lock); if((worker->flags & (SERVICE_START|SERVICE_STOP)) == SERVICE_START) { worker->flags |= SERVICE_SERVICING; err = SUCCESS; } mutex_unlock(&worker->lock); return err; } /** * Returns TRUE if none of the workers of the service are running * * @param desc the service * @return TRUE iff none of the workers of the service are running */ bool service_stopped(struct service_s *desc) { for(u32 i = 0; i < desc->worker_count; i++) { struct service_worker_s *worker = &desc->worker[i]; mutex_lock(&worker->lock); u8 f = worker->flags; mutex_unlock(&worker->lock); if(f != SERVICE_OFF) { return FALSE; } } return TRUE; } /** * Only to be called by the worker of the service itself when it is stopping. * Calling it is not mandatory but give more accuracy to the status of the service. * * @param worker the worker calling this function */ int service_set_stopping(struct service_worker_s *worker) { int err = SERVICE_NOT_RUNNING; log_debug("service: %s stopping", worker->service->name); mutex_lock(&worker->lock); if((worker->flags & SERVICE_STOP) != 0) { worker->flags |= SERVICE_STOPPING; worker->flags &= ~SERVICE_SERVICING; err = SUCCESS; } mutex_unlock(&worker->lock); return err; } /** * Only to be called by the worker of the service itself when it has reconfigured. * Calling it is not mandatory but give more accuracy to the status of the service. * * @param worker the worker calling this function */ int service_clear_reconfigure(struct service_worker_s *worker) { int err = SERVICE_NOT_RUNNING; log_debug("service: %s reconfigured", worker->service->name); mutex_lock(&worker->lock); if((worker->flags & SERVICE_RECONFIGURE) != 0) { worker->flags &= ~SERVICE_RECONFIGURE; err = SUCCESS; } mutex_unlock(&worker->lock); return err; } /** * Waits until all workers have notified they were servicing. * Calling this on a service that does not call service_set_servicing will * potentially wait forever (or until the program is shutting down). * * @param desc the service * @return an error code */ ya_result service_wait_servicing(struct service_s *desc) { while(service_started(desc)) { if(service_servicing(desc)) { return SUCCESS; } else { if(dnscore_shuttingdown()) { return STOPPED_BY_APPLICATION_SHUTDOWN; } sleep(1); } } return SERVICE_NOT_RUNNING; } int service_should_run(struct service_worker_s *worker) { mutex_lock(&worker->lock); u8 f = worker->flags; mutex_unlock(&worker->lock); #if SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT time_t now = time(NULL); mutex_lock(&worker->lock); worker->last_seen_alive = now; worker->service->last_seen_alive = now; mutex_unlock(&worker->lock); #endif return (f & (SERVICE_START | SERVICE_STOP)) == SERVICE_START; } int service_should_reconfigure(struct service_worker_s *worker) { mutex_lock(&worker->lock); u8 f = worker->flags; mutex_unlock(&worker->lock); #if SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT time_t now = time(NULL); worker->last_seen_alive = now; worker->service->last_seen_alive = now; #endif return (f & (SERVICE_START | SERVICE_STOP | SERVICE_STOPPING | SERVICE_RECONFIGURE)) == (SERVICE_START | SERVICE_RECONFIGURE); } int service_should_reconfigure_or_stop(struct service_worker_s *worker) { mutex_lock(&worker->lock); u8 f = worker->flags; mutex_unlock(&worker->lock); #if SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT time_t now = time(NULL); worker->last_seen_alive = now; worker->service->last_seen_alive = now; #endif return f & (SERVICE_STOP | SERVICE_STOPPING | SERVICE_RECONFIGURE); } #if SERVICE_HAS_LAST_SEEN_ALIVE_SUPPORT int service_check_all_alive() { time_t now = time(NULL); mutex_lock(&service_set_mutex); ptr_set_iterator iter; ptr_set_iterator_init(&service_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); struct service_s *desc = (struct service_s *)node->key; if(desc->last_seen_alive > 0) { s32 adt = now - desc->last_seen_alive; if(adt > 5) { log_warn("service '%s' has not been seen alive for %u seconds", desc->name, adt); for(u32 i = 0; i < desc->worker_count; i++) { adt = now - desc->worker[i].last_seen_alive; if(adt > 5) { log_warn("service '%s' worker #%u has not been seen alive for %u seconds", desc->name, i, adt); } } } } else { // not started yet // ignore it } } mutex_unlock(&service_set_mutex); return SUCCESS; } #else int service_check_all_alive() { // not available in release return SUCCESS; } #endif /** * Appends all services references to the array. * * Services are supposed to be defined statically. * Their reference will never point to an unmapped space. * * @param services a pointer to the ptr_vector to append the services to * @return the number of services added to the vector */ int service_get_all(ptr_vector *services) { int ret = 0; mutex_lock(&service_set_mutex); ptr_set_iterator iter; ptr_set_iterator_init(&service_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); struct service_s *desc = (struct service_s *)node->key; ptr_vector_append(services, desc); ++ret; } return ret; } struct service_worker_s* service_worker_get_sibling(const struct service_worker_s* worker, u32 idx) { if(worker != NULL) { if(worker->service != NULL) { if(worker->service->worker_count > idx) { return &worker->service->worker[idx]; } } } return NULL; } struct service_worker_s* service_get_worker(const struct service_s *service, u32 idx) { if(service != NULL) { if(service->worker_count > idx) { return &service->worker[idx]; } } return NULL; } void service_stop_all() { mutex_lock(&service_set_mutex); ptr_set_iterator iter; ptr_set_iterator_init(&service_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); struct service_s *desc = (struct service_s *)node->key; log_debug("service_stop_all: stop '%s'", STRNULL(desc->name)); service_stop(desc); } ptr_set_iterator_init(&service_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); struct service_s *desc = (struct service_s *)node->key; log_debug("service_stop_all: wait '%s'", STRNULL(desc->name)); service_wait(desc); } mutex_unlock(&service_set_mutex); } void service_start_all() { mutex_lock(&service_set_mutex); ptr_set_iterator iter; ptr_set_iterator_init(&service_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); struct service_s *desc = (struct service_s *)node->key; log_debug("service_start_all: start '%s'", STRNULL(desc->name)); service_start(desc); } mutex_unlock(&service_set_mutex); } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/shared-heap.c0000644000000000000000000000013214505005532021655 xustar000000000000000030 mtime=1695812442.463982489 30 atime=1695812445.795030196 30 ctime=1695812494.688730452 yadifa-2.6.5-11201/lib/dnscore/src/shared-heap.c0000664000374500037450000010710514505005532021623 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/dnscore.h" #include "dnscore/fdtools.h" #include "dnscore/shared-heap.h" /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include #include #include #define L1_DATA_LINE_SIZE 0x40 #define L1_DATA_LINE_MASK (L1_DATA_LINE_SIZE - 1) #define MUTEX_PROCESS_SHARED_SUPPORTED 1 //#define MUTEX_PROCESS_SHARED_SUPPORTED 0 // experimental, not enough resources to make this work #define SHARED_HEAP_ALLOC_DEBUG 0 #define SHARED_HEAP_ALLOC_PRINT 0 struct shared_heap_bloc { s32 prev_size; s32 real_size; u8 heap_index; u8 allocated; u16 _reserved0; s32 size; }; struct shared_heap_free_bloc { s32 prev_size; s32 real_size; u8 heap_index; u8 allocated; u16 _reserved0; s32 size; struct shared_heap_free_bloc *next; struct shared_heap_free_bloc *prev; }; #define SHARED_HEAP_BLOC_SIZE ((sizeof(struct shared_heap_bloc) + 7) & ~7) struct shared_heap_ctx { #if MUTEX_PROCESS_SHARED_SUPPORTED mutex_t mtx; cond_t cond; #else semaphore_t sem; #endif #if DEBUG #if SHARED_HEAP_ALLOC_DEBUG debug_memory_by_tag_context_t *mem_ctx; #endif #endif struct shared_heap_bloc *base; struct shared_heap_free_bloc free; struct shared_heap_bloc *limit; size_t size; }; static struct shared_heap_ctx *shared_heaps = NULL; static int shared_heap_next = -1; #if MUTEX_PROCESS_SHARED_SUPPORTED static inline int shared_heap_lock_init(shared_heap_ctx *ctx) { int ret; if((ret = mutex_init_process_shared(&ctx->mtx)) == 0) { if((ret = cond_init_process_shared(&ctx->cond)) != 0) { mutex_destroy(&ctx->mtx); ret = MAKE_ERRNO_ERROR(ret); } } else { ret = MAKE_ERRNO_ERROR(ret); } return ret; } static inline void shared_heap_lock_finalize(shared_heap_ctx *ctx) { cond_finalize(&ctx->cond); mutex_destroy(&ctx->mtx); } static inline void shared_heap_lock(shared_heap_ctx *ctx) { mutex_lock(&ctx->mtx); } static inline bool shared_heap_try_lock(shared_heap_ctx *ctx) { bool ret = mutex_trylock(&ctx->mtx); return ret; } static inline void shared_heap_unlock(shared_heap_ctx *ctx) { mutex_unlock(&ctx->mtx); } static inline void shared_heap_wait(shared_heap_ctx *ctx) { // cond_wait(&ctx->cond, &ctx->mtx); cond_wait_auto_time_out(&ctx->cond, &ctx->mtx); } static inline void shared_heap_notify_unlock(shared_heap_ctx *ctx) { cond_notify(&ctx->cond); // @NOTE https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=884776 mutex_unlock(&ctx->mtx); } #else static inline void shared_heap_lock_init(shared_heap_ctx *ctx) { semaphone_init_process_shared(&ctx->sem); } static inline void shared_heap_lock_finalize(shared_heap_ctx *ctx) { semaphore_finalize(&ctx->sem); } static inline void shared_heap_lock(shared_heap_ctx *ctx) { semaphore_lock(&ctx->sem); } static inline void shared_heap_unlock(shared_heap_ctx *ctx) { semaphore_unlock(&ctx->sem); } static inline void shared_heap_wait(shared_heap_ctx *ctx) { semaphore_unlock(&ctx->sem); semaphore_lock(&ctx->sem); } static inline void shared_heap_notify_unlock(shared_heap_ctx *ctx) { semaphore_unlock(&ctx->sem); } #endif void shared_heap_check_bloc(u8 id, void *bloc_, u8 allocated) { #if DEBUG struct shared_heap_bloc *bloc = (struct shared_heap_bloc*)bloc_; assert(bloc->heap_index == id); assert((size_t)bloc->prev_size < shared_heaps[id].size); assert((size_t)bloc->real_size < shared_heaps[id].size); assert((bloc >= shared_heaps[id].base) && (bloc < shared_heaps[id].limit)); if(allocated <= 1) { assert(bloc->allocated == allocated); if(bloc->allocated != allocated) { if(allocated == 1) { osformatln(termerr, "%i: shared-heap[%i] : double free at %p", getpid(), id, bloc_);flusherr(); } else { osformatln(termerr, "%i: shared-heap[%i] : corruption at %p", id, bloc_);flusherr(); } osprint_dump(termerr, bloc, bloc->size, 16, OSPRINT_DUMP_ADDRESS|OSPRINT_DUMP_HEX|OSPRINT_DUMP_TEXT); flusherr(); } } if(bloc->allocated == 1) { #ifndef NDEBUG size_t real_size = (bloc->size + SHARED_HEAP_BLOC_SIZE + L1_DATA_LINE_MASK) & ~L1_DATA_LINE_MASK; assert((size_t)bloc->real_size == real_size); #endif } #endif (void)id; (void)bloc_; (void)allocated; } void shared_heap_check_ptr(u8 id, void *ptr) { #if DEBUG struct shared_heap_bloc *bloc = (struct shared_heap_bloc *)&(((u8*)ptr)[-SHARED_HEAP_BLOC_SIZE]); shared_heap_check_bloc(id, bloc, 1); #endif (void)id; (void)ptr; } ya_result shared_heap_init() { if(shared_heaps == NULL) { const size_t ctx_size = (sizeof(struct shared_heap_ctx) + L1_DATA_LINE_MASK) & ~L1_DATA_LINE_MASK; const size_t ctx_array_size = ((ctx_size * 256) + 4095) & ~4095; shared_heaps = (struct shared_heap_ctx*)mmap(NULL, ctx_array_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if(shared_heaps != ((struct shared_heap_ctx*)MAP_FAILED)) { memset(shared_heaps, 0, ctx_array_size); shared_heap_next = 0; return SUCCESS; } else { return ERRNO_ERROR; } } return SUCCESS; } void shared_heap_finalize() { if(shared_heaps != NULL) { const size_t ctx_size = (sizeof(struct shared_heap_ctx) + L1_DATA_LINE_MASK) & ~L1_DATA_LINE_MASK; const size_t ctx_array_size = ((ctx_size * 256) + 4095) & ~4095; munmap(shared_heaps, ctx_array_size); shared_heaps = NULL; } } ya_result shared_heap_create(size_t size) { if(shared_heap_next < 0) { return OBJECT_NOT_INITIALIZED; } size = (size + 4093) & ~4093; void *ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if(ptr == MAP_FAILED) { return ERRNO_ERROR; } struct shared_heap_ctx *ctx = &shared_heaps[shared_heap_next]; ya_result ret; if(FAIL(ret = shared_heap_lock_init(ctx))) { munmap(ptr, size); return ret; } ctx->base = (struct shared_heap_bloc*)ptr; ctx->limit = (struct shared_heap_bloc*)&((u8*)ptr)[size]; ctx->free.prev_size = 0; ctx->free.real_size = 0; ctx->free.heap_index = (u8)shared_heap_next; ctx->free.allocated = 1; ctx->free.next = (struct shared_heap_free_bloc*)&((u8*)ptr)[L1_DATA_LINE_SIZE]; ctx->free.prev = ctx->free.next; ctx->size = size; ctx->free.next->prev_size = L1_DATA_LINE_SIZE; ctx->free.next->real_size = size - L1_DATA_LINE_SIZE * 2; ctx->free.next->heap_index = (u8)shared_heap_next; ctx->free.next->allocated = 0; ctx->free.next->size = 0; ctx->free.next->next = &ctx->free; ctx->free.next->prev = &ctx->free; #if DEBUG #if SHARED_HEAP_ALLOC_DEBUG ctx->mem_ctx = debug_memory_by_tag_new_instance("shared-heap"); #endif #endif struct shared_heap_bloc *header = (struct shared_heap_bloc *)&(((u8*)ptr)[0]); header->real_size = L1_DATA_LINE_SIZE; header->prev_size = 0; header->heap_index = (u8)shared_heap_next; header->allocated = 1; #if DEBUG header->_reserved0 = 0x4848; #endif header->size = 0; memset((struct shared_heap_bloc *)&(((u8*)ptr)[SHARED_HEAP_BLOC_SIZE]), 'H', L1_DATA_LINE_SIZE - SHARED_HEAP_BLOC_SIZE); struct shared_heap_bloc *footer = (struct shared_heap_bloc *)&(((u8*)ptr)[size - L1_DATA_LINE_SIZE]); footer->real_size = L1_DATA_LINE_SIZE; footer->prev_size = size - L1_DATA_LINE_SIZE * 2; footer->heap_index = (u8)shared_heap_next; footer->allocated = 1; #if DEBUG footer->_reserved0 = 0x4646; #endif footer->size = 0; memset((struct shared_heap_bloc *)&(((u8*)ptr)[size - L1_DATA_LINE_SIZE + SHARED_HEAP_BLOC_SIZE]), 'F', L1_DATA_LINE_SIZE - SHARED_HEAP_BLOC_SIZE); ret = shared_heap_next; while(shared_heap_next < 256) { ++shared_heap_next; if(shared_heaps[shared_heap_next].base == NULL) { return ret; } } shared_heap_next = 0; while(shared_heap_next < ret) { if(shared_heaps[shared_heap_next].base == NULL) { return ret; } shared_heap_next++; } shared_heap_next = -1; return ret; } void shared_heap_destroy(u8 id) { if(shared_heaps[id].base != NULL) { shared_heap_lock_finalize(&shared_heaps[id]); #if DEBUG memset(shared_heaps[id].base, 0xfe, shared_heaps[id].size); #endif munmap(shared_heaps[id].base, shared_heaps[id].size); shared_heaps[id].base = NULL; shared_heaps[id].free.next = NULL; shared_heaps[id].free.prev = NULL; shared_heaps[id].size = 0; #if DEBUG #if SHARED_HEAP_ALLOC_DEBUG debug_memory_by_tag_delete(shared_heaps[id].mem_ctx); shared_heaps[id].mem_ctx = NULL; #endif #endif } if(shared_heap_next < 0) { shared_heap_next = id; } } void* shared_heap_alloc_from_ctx(struct shared_heap_ctx *ctx, size_t size) { size_t real_size = (SHARED_HEAP_BLOC_SIZE + size + L1_DATA_LINE_MASK) & ~L1_DATA_LINE_MASK; shared_heap_lock(ctx); struct shared_heap_free_bloc *bloc = ctx->free.next; while(bloc != &ctx->free) { assert(bloc->allocated == 0); // will be wrong: assert(bloc->real_size >= bloc->size); if((size_t)bloc->real_size >= real_size) { // take from this bloc if((size_t)bloc->real_size == real_size) { // perfect match bloc->next->prev = bloc->prev; bloc->prev->next = bloc->next; // bloc prev & next are now irrelevant bloc->allocated = 1; #if DEBUG if(bloc->_reserved0 == 0) { bloc->_reserved0 = 0x4141; } #if SHARED_HEAP_ALLOC_DEBUG debug_memory_by_tag_alloc_notify(ctx->mem_ctx, GENERIC_TAG, size); #endif #endif bloc->size = size; shared_heap_unlock(ctx); return &((u8*)bloc)[SHARED_HEAP_BLOC_SIZE]; } else { // cut the bloc struct shared_heap_free_bloc *next_bloc = (struct shared_heap_free_bloc*)&(((u8*)bloc)[real_size]); next_bloc->real_size = bloc->real_size - real_size; next_bloc->prev_size = real_size; next_bloc->next = bloc->next; next_bloc->prev = bloc->prev; bloc->next->prev = next_bloc; bloc->prev->next = next_bloc; // bloc prev & next are now irrelevant next_bloc->heap_index = bloc->heap_index; next_bloc->allocated = 0; #if DEBUG next_bloc->_reserved0 = 0x4343; #endif struct shared_heap_free_bloc *next_next_bloc = (struct shared_heap_free_bloc*)&((u8*)next_bloc)[next_bloc->real_size]; next_next_bloc->prev_size = next_bloc->real_size; bloc->real_size = real_size; bloc->allocated = 1; bloc->size = size; #if DEBUG shared_heap_check_bloc(bloc->heap_index, bloc, 1); shared_heap_check_bloc(bloc->heap_index, next_bloc, 0); shared_heap_check_bloc(bloc->heap_index, next_next_bloc, 2); #if SHARED_HEAP_ALLOC_DEBUG debug_memory_by_tag_alloc_notify(ctx->mem_ctx, GENERIC_TAG, size); #endif #endif shared_heap_unlock(ctx); return &((u8*)bloc)[SHARED_HEAP_BLOC_SIZE]; } } else { bloc = bloc->next; } } shared_heap_unlock(ctx); return NULL; } void* shared_heap_try_alloc_from_ctx(struct shared_heap_ctx *ctx, size_t size) { size_t real_size = (SHARED_HEAP_BLOC_SIZE + size + L1_DATA_LINE_MASK) & ~L1_DATA_LINE_MASK; if(shared_heap_try_lock(ctx)) { struct shared_heap_free_bloc *bloc = ctx->free.next; while(bloc != &ctx->free) { assert(bloc->allocated == 0); // will be wrong: assert(bloc->real_size >= bloc->size); if((size_t)bloc->real_size >= real_size) { // take from this bloc if((size_t)bloc->real_size == real_size) { // perfect match bloc->next->prev = bloc->prev; bloc->prev->next = bloc->next; // bloc prev & next are now irrelevant bloc->allocated = 1; #if DEBUG if(bloc->_reserved0 == 0) { bloc->_reserved0 = 0x4141; } #if SHARED_HEAP_ALLOC_DEBUG debug_memory_by_tag_alloc_notify(ctx->mem_ctx, GENERIC_TAG, size); #endif #endif bloc->size = size; shared_heap_unlock(ctx); return &((u8*)bloc)[SHARED_HEAP_BLOC_SIZE]; } else { // cut the bloc struct shared_heap_free_bloc *next_bloc = (struct shared_heap_free_bloc*)&(((u8*)bloc)[real_size]); next_bloc->real_size = bloc->real_size - real_size; next_bloc->prev_size = real_size; next_bloc->next = bloc->next; next_bloc->prev = bloc->prev; bloc->next->prev = next_bloc; bloc->prev->next = next_bloc; // bloc prev & next are now irrelevant next_bloc->heap_index = bloc->heap_index; next_bloc->allocated = 0; #if DEBUG next_bloc->_reserved0 = 0x4343; #endif struct shared_heap_free_bloc *next_next_bloc = (struct shared_heap_free_bloc*)&((u8*)next_bloc)[next_bloc->real_size]; next_next_bloc->prev_size = next_bloc->real_size; bloc->real_size = real_size; bloc->allocated = 1; bloc->size = size; #if DEBUG shared_heap_check_bloc(bloc->heap_index, bloc, 1); shared_heap_check_bloc(bloc->heap_index, next_bloc, 0); shared_heap_check_bloc(bloc->heap_index, next_next_bloc, 2); #if SHARED_HEAP_ALLOC_DEBUG debug_memory_by_tag_alloc_notify(ctx->mem_ctx, GENERIC_TAG, size); #endif #endif shared_heap_unlock(ctx); return &((u8*)bloc)[SHARED_HEAP_BLOC_SIZE]; } } else { bloc = bloc->next; } } shared_heap_unlock(ctx); } return NULL; } void* shared_heap_wait_alloc_from_ctx(struct shared_heap_ctx *ctx, size_t size) { size_t real_size = (SHARED_HEAP_BLOC_SIZE + size + L1_DATA_LINE_MASK) & ~L1_DATA_LINE_MASK; shared_heap_lock(ctx); for(;;) { struct shared_heap_free_bloc *bloc = ctx->free.next; while(bloc != &ctx->free) { assert(bloc->allocated == 0); // will be wrong: assert(bloc->real_size >= bloc->size); #if DEBUG shared_heap_check_bloc(bloc->heap_index, bloc, 0); #endif if((size_t)bloc->real_size >= real_size) { // take from this bloc if((size_t)bloc->real_size == real_size) { // perfect match bloc->next->prev = bloc->prev; bloc->prev->next = bloc->next; // bloc prev & next are now irrelevant bloc->allocated = 1; #if DEBUG if(bloc->_reserved0 == 0) { bloc->_reserved0 = 0x4141; } #if SHARED_HEAP_ALLOC_DEBUG debug_memory_by_tag_alloc_notify(ctx->mem_ctx, GENERIC_TAG, size); #endif #endif bloc->size = size; #if DEBUG shared_heap_check_bloc(bloc->heap_index, bloc, 1); #endif shared_heap_unlock(ctx); #if DEBUG memset(&((u8*)bloc)[SHARED_HEAP_BLOC_SIZE], 'A', bloc->real_size - SHARED_HEAP_BLOC_SIZE); #endif return &((u8*)bloc)[SHARED_HEAP_BLOC_SIZE]; } else { // cut the bloc struct shared_heap_free_bloc *next_bloc = (struct shared_heap_free_bloc*)&(((u8*)bloc)[real_size]); next_bloc->real_size = bloc->real_size - real_size; next_bloc->prev_size = real_size; next_bloc->next = bloc->next; next_bloc->prev = bloc->prev; bloc->next->prev = next_bloc; bloc->prev->next = next_bloc; // bloc prev & next are now irrelevant next_bloc->heap_index = bloc->heap_index; next_bloc->allocated = 0; #if DEBUG next_bloc->_reserved0 = 0x4343; #endif struct shared_heap_free_bloc *next_next_bloc = (struct shared_heap_free_bloc*)&((u8*)next_bloc)[next_bloc->real_size]; next_next_bloc->prev_size = next_bloc->real_size; bloc->allocated = 1; bloc->real_size = real_size; bloc->size = size; #if DEBUG shared_heap_check_bloc(bloc->heap_index, bloc, 1); shared_heap_check_bloc(bloc->heap_index, next_bloc, 0); shared_heap_check_bloc(bloc->heap_index, next_next_bloc, 2); #if SHARED_HEAP_ALLOC_DEBUG debug_memory_by_tag_alloc_notify(ctx->mem_ctx, GENERIC_TAG, size); #endif #endif shared_heap_unlock(ctx); #if DEBUG memset(&((u8*)bloc)[SHARED_HEAP_BLOC_SIZE], 'a', bloc->real_size - SHARED_HEAP_BLOC_SIZE); #endif return &((u8*)bloc)[SHARED_HEAP_BLOC_SIZE]; } } else { bloc = bloc->next; } } // while bloc != ctx->free shared_heap_wait(ctx); } } static void shared_heap_grow_allocated_with_following_free_bloc(struct shared_heap_free_bloc *bloc, struct shared_heap_free_bloc *next_bloc) { #if DEBUG shared_heap_check_bloc(bloc->heap_index, bloc, 1); shared_heap_check_bloc(next_bloc->heap_index, next_bloc, 0); #endif next_bloc->next->prev = next_bloc->prev; next_bloc->prev->next = next_bloc->next; bloc->real_size += next_bloc->real_size; #if DEBUG bloc->size = bloc->real_size - SHARED_HEAP_BLOC_SIZE; #endif struct shared_heap_free_bloc *next_next_bloc = (struct shared_heap_free_bloc*)&((u8*)next_bloc)[next_bloc->real_size]; next_next_bloc->prev_size = bloc->real_size; } /** * Merge two blocks in specific states. * After the call, the allocated block will nolonger be (obviously). */ static void shared_heap_merge_allocated_with_following_free_bloc(struct shared_heap_free_bloc *bloc, struct shared_heap_free_bloc *next_bloc) { #if DEBUG shared_heap_check_bloc(bloc->heap_index, bloc, 1); shared_heap_check_bloc(next_bloc->heap_index, next_bloc, 0); #endif bloc->real_size += next_bloc->real_size; #if DEBUG bloc->size = bloc->real_size - SHARED_HEAP_BLOC_SIZE; #endif bloc->next = next_bloc->next; bloc->next->prev = bloc; bloc->prev = next_bloc->prev; bloc->prev->next = bloc; bloc->allocated = 0; struct shared_heap_free_bloc *next_next_bloc = (struct shared_heap_free_bloc*)&((u8*)next_bloc)[next_bloc->real_size]; next_next_bloc->prev_size = bloc->real_size; #if DEBUG memset(next_bloc, 'T', L1_DATA_LINE_SIZE); #endif } /** * Merge two blocks in specific states. * After the call, the allocated block will nolonger be (obviously). */ static void shared_heap_merge_free_with_following_allocated_bloc(struct shared_heap_free_bloc *bloc, struct shared_heap_free_bloc *next_bloc) { #if DEBUG shared_heap_check_bloc(bloc->heap_index, bloc, 0); shared_heap_check_bloc(next_bloc->heap_index, next_bloc, 1); #endif bloc->real_size += next_bloc->real_size; #if DEBUG bloc->size = bloc->real_size - SHARED_HEAP_BLOC_SIZE; #endif struct shared_heap_free_bloc *next_next_bloc = (struct shared_heap_free_bloc*)&((u8*)next_bloc)[next_bloc->real_size]; next_next_bloc->prev_size = bloc->real_size; #if DEBUG memset(next_bloc, 'U', L1_DATA_LINE_SIZE); #endif } /** * Merge three blocks in specific states. * After the call, the allocated block will nolonger be (obviously). */ static void shared_heap_merge_allocated_with_surrounding_free_blocs(struct shared_heap_free_bloc *prev_bloc, struct shared_heap_free_bloc *bloc, struct shared_heap_free_bloc *next_bloc) { #if DEBUG shared_heap_check_bloc(prev_bloc->heap_index, prev_bloc, 0); shared_heap_check_bloc(bloc->heap_index, bloc, 1); shared_heap_check_bloc(next_bloc->heap_index, next_bloc, 0); #endif // detach the next bloc from the chain // merge the 3 next_bloc->next->prev = next_bloc->prev; next_bloc->prev->next = next_bloc->next; prev_bloc->real_size += bloc->real_size + next_bloc->real_size; #if DEBUG prev_bloc->size = bloc->real_size - SHARED_HEAP_BLOC_SIZE; #endif struct shared_heap_free_bloc *next_next_bloc = (struct shared_heap_free_bloc*)&((u8*)next_bloc)[next_bloc->real_size]; next_next_bloc->prev_size = prev_bloc->real_size; #if DEBUG memset(bloc, 'V', L1_DATA_LINE_SIZE); memset(next_bloc, 'W', L1_DATA_LINE_SIZE); #endif } void shared_heap_free_from_ctx(struct shared_heap_ctx *ctx, void *ptr) { struct shared_heap_free_bloc *bloc = (struct shared_heap_free_bloc *)&(((u8*)ptr)[-SHARED_HEAP_BLOC_SIZE]); shared_heap_lock(ctx); #if DEBUG shared_heap_check_bloc(bloc->heap_index, bloc, 1); #if SHARED_HEAP_ALLOC_DEBUG debug_memory_by_tag_free_notify(ctx->mem_ctx, GENERIC_TAG, bloc->size); #endif #endif struct shared_heap_free_bloc *next_bloc = (struct shared_heap_free_bloc*)&(((u8*)bloc)[bloc->real_size]); #if DEBUG shared_heap_check_bloc(bloc->heap_index, next_bloc, 2); #endif if(next_bloc->allocated == 0) { struct shared_heap_free_bloc *prev_bloc = (struct shared_heap_free_bloc*)&(((u8*)bloc)[-bloc->prev_size]); #if DEBUG shared_heap_check_bloc(bloc->heap_index, prev_bloc, 2); #endif if(prev_bloc->allocated == 0) { // merge 3 #if DEBUG prev_bloc->_reserved0 = 0xfe03; bloc->_reserved0 = 0xfe13; next_bloc->_reserved0 = 0xfe23; #endif shared_heap_merge_allocated_with_surrounding_free_blocs(prev_bloc, bloc, next_bloc); bloc = prev_bloc; } else { // merge 2 #if DEBUG bloc->_reserved0 = 0xfe02; next_bloc->_reserved0 = 0xfe12; #endif shared_heap_merge_allocated_with_following_free_bloc(bloc, next_bloc); } } else { struct shared_heap_free_bloc *prev_bloc = (struct shared_heap_free_bloc*)&(((u8*)bloc)[-bloc->prev_size]); #if DEBUG shared_heap_check_bloc(bloc->heap_index, prev_bloc, 2); #endif if(prev_bloc->allocated == 0) { // merge 2 #if DEBUG prev_bloc->_reserved0 = 0xfe01; bloc->_reserved0 = 0xfe11; #endif shared_heap_merge_free_with_following_allocated_bloc(prev_bloc, bloc); bloc = prev_bloc; } else { #if DEBUG bloc->_reserved0 = 0xfe00; #endif bloc->next = &ctx->free; bloc->prev = ctx->free.prev; ctx->free.prev = bloc; bloc->prev->next = bloc; bloc->allocated = 0; } } #if DEBUG assert(bloc->_reserved0 != 0); #endif shared_heap_notify_unlock(ctx); } void* shared_heap_realloc_from_ctx(struct shared_heap_ctx *ctx, void *ptr, size_t new_size) { struct shared_heap_free_bloc *bloc = (struct shared_heap_free_bloc *)&(((u8*)ptr)[-SHARED_HEAP_BLOC_SIZE]); assert(bloc->allocated == 1); if(new_size <= (size_t)bloc->real_size) { return ptr; } shared_heap_lock(ctx); struct shared_heap_free_bloc *next_bloc = (struct shared_heap_free_bloc*)&(((u8*)bloc)[bloc->real_size]); if(next_bloc->allocated == 0) { // maybe the next bloc can be stolen from size_t real_size = (SHARED_HEAP_BLOC_SIZE + new_size + L1_DATA_LINE_MASK) & ~L1_DATA_LINE_MASK; size_t needed_size = real_size - bloc->real_size; if((size_t)next_bloc->real_size >= needed_size) { // steal some memory from the next bloc // create a new bloc in the next bloc // update pointers if((size_t)next_bloc->real_size == needed_size) { // remove the bloc from the free chain // add its space to the current bloc shared_heap_grow_allocated_with_following_free_bloc(bloc, next_bloc); shared_heap_unlock(ctx); } else { // split the bloc struct shared_heap_free_bloc *split_bloc = (struct shared_heap_free_bloc*)&(((u8*)next_bloc)[needed_size]); split_bloc->real_size -= needed_size; split_bloc->prev_size = real_size; split_bloc->next = next_bloc->next; split_bloc->prev = next_bloc->prev; split_bloc->next->prev = split_bloc; split_bloc->prev->next = split_bloc; // bloc prev & next are now irrelevant split_bloc->heap_index = next_bloc->heap_index; split_bloc->allocated = 0; bloc->real_size = real_size; shared_heap_unlock(ctx); } return ptr; } } // cannot grow : allocate a new bloc and free the current one shared_heap_unlock(ctx); void *new_ptr = shared_heap_alloc_from_ctx(ctx, new_size); memcpy(new_ptr, ptr, bloc->size); shared_heap_free_from_ctx(ctx, ptr); return new_ptr; } void* shared_heap_alloc(u8 id, size_t size) { void *ptr = shared_heap_alloc_from_ctx(&shared_heaps[id], size); #if DEBUG && SHARED_HEAP_ALLOC_DEBUG #if SHARED_HEAP_ALLOC_PRINT osformatln(termout, "%i : shared_heap_alloc(%i, %lli) = %p", getpid(), id, size, ptr); #endif if(ptr != NULL) { shared_heap_ctx *ctx = &shared_heaps[id]; debug_memory_by_tag_alloc_notify(ctx->mem_ctx, 0, size); } #endif return ptr; } void* shared_heap_wait_alloc(u8 id, size_t size) { void *ptr = shared_heap_wait_alloc_from_ctx(&shared_heaps[id], size); #if DEBUG && SHARED_HEAP_ALLOC_DEBUG #if SHARED_HEAP_ALLOC_PRINT osformatln(termout, "%i : shared_heap_wait_alloc(%i, %lli) = %p", getpid(), id, size, ptr); #endif if(ptr != NULL) { shared_heap_ctx *ctx = &shared_heaps[id]; debug_memory_by_tag_alloc_notify(ctx->mem_ctx, 0, size); } #endif return ptr; } void* shared_heap_try_alloc(u8 id, size_t size) { void *ptr = shared_heap_try_alloc_from_ctx(&shared_heaps[id], size); #if DEBUG && SHARED_HEAP_ALLOC_DEBUG #if SHARED_HEAP_ALLOC_PRINT osformatln(termout, "%i : shared_heap_try_alloc(%i, %lli) = %p", getpid(), id, size, ptr); #endif if(ptr != NULL) { shared_heap_ctx *ctx = &shared_heaps[id]; debug_memory_by_tag_alloc_notify(ctx->mem_ctx, 0, size); } #endif return ptr; } void shared_heap_free(void *ptr) { assert(ptr != NULL); struct shared_heap_free_bloc *bloc = (struct shared_heap_free_bloc *)&(((u8*)ptr)[-SHARED_HEAP_BLOC_SIZE]); #if DEBUG && SHARED_HEAP_ALLOC_DEBUG shared_heap_ctx *ctx = &shared_heaps[bloc->heap_index]; #if SHARED_HEAP_ALLOC_PRINT osformatln(termout, "%i : shared_heap_free(%p) of size=%i", getpid(), ptr, bloc->size); #endif debug_memory_by_tag_free_notify(ctx->mem_ctx, 0, bloc->size); #endif shared_heap_free_from_ctx(&shared_heaps[bloc->heap_index], ptr); } void* shared_heap_realloc(u8 id, void *ptr, size_t new_size) { return shared_heap_realloc_from_ctx(&shared_heaps[id], ptr, new_size); } struct shared_heap_ctx * shared_heap_context_from_id(u8 id) { return &shared_heaps[id]; } void shared_heap_check(u8 id) { struct shared_heap_ctx *ctx = &shared_heaps[id]; shared_heap_lock(ctx); void *ptr = ctx->base; size_t size = ctx->size; const struct shared_heap_bloc *header = (const struct shared_heap_bloc *)&(((u8*)ptr)[0]); assert(header->real_size == L1_DATA_LINE_SIZE); assert(header->prev_size == 0); assert(header->heap_index == id); assert(header->allocated == 1); assert(header->size == 0); //memset((struct shared_heap_bloc *)&(((u8*)ptr)[SHARED_HEAP_BLOC_SIZE]), 'H', L1_DATA_LINE_SIZE - SHARED_HEAP_BLOC_SIZE); const struct shared_heap_bloc *footer = (const struct shared_heap_bloc *)&(((u8*)ptr)[size - L1_DATA_LINE_SIZE]); assert(footer->real_size == L1_DATA_LINE_SIZE); //assert(footer->prev_size == size - L1_DATA_LINE_SIZE * 2); assert(footer->heap_index == id); assert(footer->allocated == 1); assert(footer->size == 0); //memset((struct shared_heap_bloc *)&(((u8*)ptr)[size - L1_DATA_LINE_SIZE + SHARED_HEAP_BLOC_SIZE]), 'F', L1_DATA_LINE_SIZE - SHARED_HEAP_BLOC_SIZE); const struct shared_heap_bloc *prev_bloc = header; for(;;) { const struct shared_heap_bloc *bloc = (const struct shared_heap_bloc *)&(((u8*)prev_bloc)[prev_bloc->real_size]); if(bloc >= footer) { assert(bloc == footer); break; } assert(bloc->prev_size == prev_bloc->real_size); assert(bloc->heap_index == id); prev_bloc = bloc; } const struct shared_heap_free_bloc *pf = &ctx->free; for(;;) { const struct shared_heap_free_bloc *f = pf->next; assert(f->heap_index == id); assert(f->prev == pf); if(f == &ctx->free) { break; } assert(f->allocated == 0); pf = f; } //assert(footer->prev_size == prev_bloc->real_size); shared_heap_unlock(ctx); } void shared_heap_count_allocated(u8 id, size_t* totalp, size_t* countp) { struct shared_heap_ctx *ctx = &shared_heaps[id]; shared_heap_lock(ctx); const void *ptr = ctx->base; size_t size = ctx->size; const struct shared_heap_bloc *header = (const struct shared_heap_bloc *)&(((u8*)ptr)[L1_DATA_LINE_SIZE]); const struct shared_heap_bloc *footer = (const struct shared_heap_bloc *)&(((u8*)ptr)[size - L1_DATA_LINE_SIZE]); const struct shared_heap_bloc *prev_bloc = header; size_t total = 0; size_t count = 0; for(;;) { const struct shared_heap_bloc *bloc = (const struct shared_heap_bloc *)&(((u8*)prev_bloc)[prev_bloc->real_size]); if(bloc >= footer) { break; } if(bloc->allocated == 1) { total += bloc->real_size; ++count; } prev_bloc = bloc; } shared_heap_unlock(ctx); if(totalp != NULL) { *totalp = total; } if(countp != NULL) { *countp = count; } } void shared_heap_print_map(u8 id, size_t* totalp, size_t* countp) { #if DEBUG struct shared_heap_ctx *ctx = &shared_heaps[id]; shared_heap_lock(ctx); const void *ptr = ctx->base; size_t size = ctx->size; const struct shared_heap_bloc *header = (const struct shared_heap_bloc *)&(((u8*)ptr)[L1_DATA_LINE_SIZE]); const struct shared_heap_bloc *footer = (const struct shared_heap_bloc *)&(((u8*)ptr)[size - L1_DATA_LINE_SIZE]); size_t total = 0; size_t count = 0; u8 allocated = 255; const u8 *range_start = NULL; const struct shared_heap_bloc *bloc = header; for(;;) { if(bloc >= footer) { if(range_start != NULL) { formatln("shared-heap[%i] [%p ; %p] %8x allocated=%i", id, range_start, ((u8*)bloc) - 1, (u8*)bloc - range_start, allocated); } break; } if(bloc->allocated != allocated) { if(range_start != NULL) { formatln("shared-heap[%i] [%p ; %p] %8x allocated=%i", id, range_start, ((u8*)bloc) - 1, (u8*)bloc - range_start, allocated); } range_start = (const u8*)bloc; allocated = bloc->allocated; } if(bloc->allocated == 1) { total += bloc->real_size; ++count; } const struct shared_heap_bloc *next_bloc = (const struct shared_heap_bloc*)&(((u8*)bloc)[bloc->real_size]); bloc = next_bloc; } shared_heap_unlock(ctx); if(totalp != NULL) { *totalp = total; } if(countp != NULL) { *countp = count; } formatln("shared-heap[%i] total=%llu count=%llu", id, total, count); #else (void)id; (void)totalp; (void)countp; #endif } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/shared-circular-buffer.c0000644000000000000000000000013214505005532024013 xustar000000000000000030 mtime=1695812442.374981214 30 atime=1695812445.791030139 30 ctime=1695812494.690730481 yadifa-2.6.5-11201/lib/dnscore/src/shared-circular-buffer.c0000664000374500037450000003272214505005532023763 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include "dnscore/dnscore.h" #include "dnscore/fdtools.h" #include "dnscore/mutex.h" #include "dnscore/shared-circular-buffer.h" #define L1_DATA_LINE_SIZE 0x40 #define L1_DATA_LINE_MASK (L1_DATA_LINE_SIZE - 1) #define DEBUG_SHARED_CIRCULAR_BUFFER_MEM_USAGE 0 #define DEBUG_SHARED_CIRCULAR_BUFFER_SELF_REPORT 0 struct shared_circular_buffer { mutex_t mtx; cond_t cond_r; cond_t cond_w; size_t mask; size_t total_size; size_t additional_buffer_size; u8 *additional_buffer_ptr; #if DEBUG_SHARED_CIRCULAR_BUFFER_MEM_USAGE && DNSCORE_DEBUG_HAS_BLOCK_TAG debug_memory_by_tag_context_t *memctx; #endif #if DEBUG_SHARED_CIRCULAR_BUFFER_SELF_REPORT s64 last_report_time; s64 peak_usage; #endif #if __unix__ volatile s64 enqueue_index __attribute__ ((aligned (L1_DATA_LINE_SIZE))); volatile s64 dequeue_index __attribute__ ((aligned (L1_DATA_LINE_SIZE))); struct shared_circular_buffer_slot base[] __attribute__ ((aligned (L1_DATA_LINE_SIZE))); #else volatile s64 enqueue_index; volatile s64 dequeue_index; struct shared_circular_buffer_slot base[]; #endif }; #if DEBUG_SHARED_CIRCULAR_BUFFER_SELF_REPORT static void shared_circular_buffer_stats(struct shared_circular_buffer* buffer) { s64 now = timeus(); if(now - buffer->last_report_time > 60 * ONE_SECOND_US) { buffer->last_report_time = now; s64 size = buffer->mask + 1; s64 used = buffer->enqueue_index - buffer->dequeue_index; if(used < 0) { used = size - used; } if(buffer->peak_usage < used) { buffer->peak_usage = used; } formatln("shared_circular_buffer@%p: free=%lli, used=%lli, peak=%lli, enqueue=%lli, dequeue=%lli", buffer, size - used, used, buffer->peak_usage, buffer->enqueue_index, buffer->dequeue_index); } } #endif u8 *shared_circular_buffer_additional_space_ptr(struct shared_circular_buffer* buffer) { return buffer->additional_buffer_ptr; } size_t shared_circular_buffer_additional_space_size(struct shared_circular_buffer* buffer) { return buffer->additional_buffer_size; } struct shared_circular_buffer* shared_circular_buffer_create_ex(u8 log_2_buffer_size, u32 additional_space_bytes) { struct shared_circular_buffer *buffer; const size_t header_size = (sizeof(struct shared_circular_buffer) + L1_DATA_LINE_MASK) & ~L1_DATA_LINE_MASK; size_t buffer_size = sizeof(struct shared_circular_buffer_slot) << log_2_buffer_size; size_t additional_space_real_bytes = (additional_space_bytes + 4095) & ~4095; const size_t total_buffer_size = ((header_size + buffer_size + 4095) & ~4095) + additional_space_real_bytes; buffer = (struct shared_circular_buffer*)mmap(NULL, total_buffer_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if(buffer != ((struct shared_circular_buffer*)MAP_FAILED)) { memset(buffer, 0, header_size); if(mutex_init_process_shared(&buffer->mtx) != 0) { munmap(buffer, total_buffer_size); return NULL; } if(cond_init_process_shared(&buffer->cond_r) != 0) { mutex_destroy(&buffer->mtx); munmap(buffer, total_buffer_size); return NULL; } if(cond_init_process_shared(&buffer->cond_w) != 0) { cond_finalize(&buffer->cond_r); mutex_destroy(&buffer->mtx); munmap(buffer, total_buffer_size); return NULL; } buffer->enqueue_index = 0; buffer->dequeue_index = 0; buffer->mask = (1 << log_2_buffer_size) - 1; buffer->total_size = total_buffer_size; buffer->additional_buffer_size = additional_space_real_bytes; buffer->additional_buffer_ptr = &((u8*)buffer)[total_buffer_size - additional_space_real_bytes]; #if DEBUG_SHARED_CIRCULAR_BUFFER_MEM_USAGE && DNSCORE_DEBUG_HAS_BLOCK_TAG buffer->memctx = debug_memory_by_tag_new_instance("shrqueue"); #endif #if DEBUG_SHARED_CIRCULAR_BUFFER_SELF_REPORT buffer->last_report_time = 0; buffer->peak_usage = 0; #endif return buffer; } else { return NULL; } } struct shared_circular_buffer* shared_circular_buffer_create(u8 log_2_buffer_size) { struct shared_circular_buffer* ret = shared_circular_buffer_create_ex(log_2_buffer_size, 0); return ret; } void shared_circular_buffer_destroy(struct shared_circular_buffer* buffer) { if(buffer != NULL) { #if DEBUG_SHARED_CIRCULAR_BUFFER_MEM_USAGE && DNSCORE_DEBUG_HAS_BLOCK_TAG debug_memory_by_tag_delete(buffer->memctx); #endif cond_finalize(&buffer->cond_w); cond_finalize(&buffer->cond_r); mutex_destroy(&buffer->mtx); munmap(buffer, buffer->total_size); } } struct shared_circular_buffer_slot* shared_circular_buffer_prepare_enqueue(struct shared_circular_buffer* buffer) { struct shared_circular_buffer_slot *ret; mutex_lock(&buffer->mtx); for(;;) { s64 di = buffer->dequeue_index; s64 ei = buffer->enqueue_index; if((ei >= di) && ((ei - di) <= (s64)buffer->mask)) { ret = (struct shared_circular_buffer_slot*)&buffer->base[ei & buffer->mask]; ret->state = 0; #if DEBUG memset(ret->data, 'E', sizeof(ret->data)); #endif buffer->enqueue_index = ei + 1; #if DEBUG_SHARED_CIRCULAR_BUFFER_SELF_REPORT shared_circular_buffer_stats(buffer); #endif break; } cond_wait(&buffer->cond_w, &buffer->mtx); // wait to write } // cond_notify(&buffer->cond_r); // notify reader mutex_unlock(&buffer->mtx); return ret; } struct shared_circular_buffer_slot* shared_circular_buffer_try_prepare_enqueue(struct shared_circular_buffer* buffer) { struct shared_circular_buffer_slot *ret; if(mutex_trylock(&buffer->mtx)) { s64 di = buffer->dequeue_index; s64 ei = buffer->enqueue_index; if((ei >= di) && ((ei - di) <= (s64)buffer->mask)) { ret = (struct shared_circular_buffer_slot*)&buffer->base[ei & buffer->mask]; ret->state = 0; #if DEBUG memset(ret->data, 'e', sizeof(ret->data)); #endif buffer->enqueue_index = ei + 1; #if DEBUG_SHARED_CIRCULAR_BUFFER_SELF_REPORT shared_circular_buffer_stats(buffer); #endif } else { ret = NULL; } mutex_unlock(&buffer->mtx); return ret; } return NULL; } void shared_circular_buffer_commit_enqueue(struct shared_circular_buffer* buffer, struct shared_circular_buffer_slot* slot) { mutex_lock(&buffer->mtx); slot->state = 1; #if DEBUG #if DEBUG_SHARED_CIRCULAR_BUFFER_MEM_USAGE && DNSCORE_DEBUG_HAS_BLOCK_TAG debug_memory_by_tag_alloc_notify(buffer->memctx, GENERIC_TAG, sizeof(*slot)); #endif #endif #if DEBUG_SHARED_CIRCULAR_BUFFER_SELF_REPORT shared_circular_buffer_stats(buffer); #endif cond_notify(&buffer->cond_r); mutex_unlock(&buffer->mtx); } size_t shared_circular_buffer_get_index(struct shared_circular_buffer* buffer, struct shared_circular_buffer_slot* slot) { return slot - buffer->base; } bool shared_circular_buffer_empty(struct shared_circular_buffer* buffer) { bool ret; mutex_lock(&buffer->mtx); ret = buffer->dequeue_index == buffer->enqueue_index; mutex_unlock(&buffer->mtx); return ret; } size_t shared_circular_buffer_size(struct shared_circular_buffer* buffer) { size_t ret; mutex_lock(&buffer->mtx); ret = buffer->enqueue_index - buffer->dequeue_index; mutex_unlock(&buffer->mtx); return ret; } size_t shared_circular_buffer_avail(struct shared_circular_buffer* buffer) { return buffer->mask - shared_circular_buffer_size(buffer); } void shared_circular_buffer_lock(struct shared_circular_buffer* buffer) { mutex_lock(&buffer->mtx); } void shared_circular_buffer_unlock(struct shared_circular_buffer* buffer) { mutex_unlock(&buffer->mtx); } struct shared_circular_buffer_slot* shared_circular_buffer_prepare_dequeue(struct shared_circular_buffer* buffer) { struct shared_circular_buffer_slot *ret; mutex_lock(&buffer->mtx); for(;;) { s64 di = buffer->dequeue_index; s64 ei = buffer->enqueue_index; if(di < ei) { ret = (struct shared_circular_buffer_slot*)&buffer->base[di & buffer->mask]; u8 * volatile state = &ret->state; while(*state != 1) { cond_wait(&buffer->cond_r, &buffer->mtx); // wait to read // there is only one dequeuer so there is no need to reload this slot } #if DEBUG *state = 2; #endif #if DEBUG_SHARED_CIRCULAR_BUFFER_SELF_REPORT shared_circular_buffer_stats(buffer); #endif break; } cond_wait(&buffer->cond_r, &buffer->mtx); // wait to read } mutex_unlock(&buffer->mtx); return ret; } struct shared_circular_buffer_slot* shared_circular_buffer_prepare_dequeue_with_timeout(struct shared_circular_buffer* buffer, s64 timeoutus) { struct shared_circular_buffer_slot *ret; mutex_lock(&buffer->mtx); for(;;) { s64 di = buffer->dequeue_index; s64 ei = buffer->enqueue_index; if(di < ei) { ret = (struct shared_circular_buffer_slot*)&buffer->base[di & buffer->mask]; u8 * volatile state = &ret->state; while(*state != 1) { if(cond_timedwait(&buffer->cond_r, &buffer->mtx, timeoutus) != 0) // wait to read // there is only one dequeuer so there is no need to reload this slot { ret = NULL; break; } } #if DEBUG *state = 2; #endif #if DEBUG_SHARED_CIRCULAR_BUFFER_SELF_REPORT shared_circular_buffer_stats(buffer); #endif break; } if(cond_timedwait(&buffer->cond_r, &buffer->mtx, timeoutus) != 0) // wait to read { ret = NULL; break; } } mutex_unlock(&buffer->mtx); return ret; } void shared_circular_buffer_commit_dequeue(struct shared_circular_buffer* buffer) { mutex_lock(&buffer->mtx); #if DEBUG struct shared_circular_buffer_slot *ret; ret = (struct shared_circular_buffer_slot*)&buffer->base[buffer->dequeue_index & buffer->mask]; memset(ret->data, 'D', sizeof(ret->data)); #if DEBUG_SHARED_CIRCULAR_BUFFER_MEM_USAGE && DNSCORE_DEBUG_HAS_BLOCK_TAG debug_memory_by_tag_free_notify(buffer->memctx, GENERIC_TAG, sizeof(*ret)); #endif #endif if(++buffer->dequeue_index == buffer->enqueue_index) { if(buffer->enqueue_index > 65535) // don't advise for less than a few pages { intptr ptr = (intptr)&buffer->base[0]; ptr += 4095; ptr &=~4095; size_t size = buffer->total_size - buffer->additional_buffer_size; if(size > 8192) { size -= 8192; madvise((void*)ptr, size, MADV_DONTNEED); } } buffer->enqueue_index = 0; buffer->dequeue_index = 0; #if DEBUG_SHARED_CIRCULAR_BUFFER_SELF_REPORT shared_circular_buffer_stats(buffer); #endif } cond_notify(&buffer->cond_w); // notify writers mutex_unlock(&buffer->mtx); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/shared-heap-bytearray-output-stream.c0000644000000000000000000000013114505005532026503 xustar000000000000000030 mtime=1695812442.409981716 30 atime=1695812445.793030168 29 ctime=1695812494.69273051 yadifa-2.6.5-11201/lib/dnscore/src/shared-heap-bytearray-output-stream.c0000664000374500037450000001730514505005532026454 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/shared-heap.h" #include "dnscore/shared-heap-bytearray-output-stream.h" #include "dnscore/zalloc.h" #define BYTE_ARRAY_OUTPUT_STREAM_DATA_TAG 0x41544144534f4853 /* SHOSDATA */ #define SHARED_HEAP_STARTSIZE 48 typedef struct shared_heap_output_stream_data shared_heap_output_stream_data; /** * @NOTE: if this changes, take care that shared_heap_output_stream_context in the header file has at least the SAME SIZE */ struct shared_heap_output_stream_data { u8* buffer; u32 buffer_size; u32 buffer_offset; u8 flags; u8 id; }; static ya_result shared_heap_output_stream_write(output_stream* stream, const u8* buffer, u32 len) { if(len == 0) { return 0; } shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data; u32 remaining = data->buffer_size - data->buffer_offset; /* 1;48 -> 48 49;112 -> 112 */ if(len > remaining) { /* Either we can resize, either we have to trunk */ if((data->flags & SHARED_HEAP_DYNAMIC) != 0) { u8* newbuffer; u32 newsize = (((data->buffer_offset + len) + 16 + 63) & ~63) - 16; newbuffer = (u8*)shared_heap_wait_alloc(data->id, newsize); MEMCOPY(newbuffer, data->buffer, data->buffer_offset); if((data->flags & SHARED_HEAP_OWNED) != 0) { shared_heap_free(data->buffer); } data->buffer = newbuffer; data->buffer_size = newsize; data->flags |= SHARED_HEAP_OWNED; } else { len = remaining; } } MEMCOPY(&data->buffer[data->buffer_offset], buffer, len); data->buffer_offset += len; return len; } static ya_result shared_heap_output_stream_flush(output_stream* stream) { (void)stream; return SUCCESS; } static void shared_heap_output_stream_close(output_stream* stream) { shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data; if((data->flags & SHARED_HEAP_OWNED) != 0) { #if DEBUG memset(data->buffer, 0xe5, data->buffer_size); #endif shared_heap_free(data->buffer); } if((data->flags & SHARED_HEAP_ZALLOC_CONTEXT) != 0) { ZFREE_OBJECT(data); } output_stream_set_void(stream); } static const output_stream_vtbl shared_heap_output_stream_vtbl = { shared_heap_output_stream_write, shared_heap_output_stream_flush, shared_heap_output_stream_close, "shared_heap_output_stream", }; void shared_heap_output_stream_init_ex_static(output_stream* out_stream, u8 id, u8* array,u32 size, u8 flags, shared_heap_output_stream_context *ctx) { shared_heap_output_stream_data *data = (shared_heap_output_stream_data*)ctx; if(array == NULL) { flags |= SHARED_HEAP_OWNED; if(size == 0) { flags |= SHARED_HEAP_DYNAMIC; size = SHARED_HEAP_STARTSIZE; } else { // size = ((size + 63) & ~63) - 16; } array = (u8*)shared_heap_wait_alloc(id, size); } data->buffer = array; data->buffer_size = size; data->buffer_offset = 0; data->flags = flags; data->id = id; out_stream->data = data; out_stream->vtbl = &shared_heap_output_stream_vtbl; } void shared_heap_output_stream_try_init_ex_static(output_stream* out_stream, u8 id, u8* array,u32 size, u8 flags, shared_heap_output_stream_context *ctx) { shared_heap_output_stream_data *data = (shared_heap_output_stream_data*)ctx; if(array == NULL) { flags |= SHARED_HEAP_OWNED; if(size == 0) { flags |= SHARED_HEAP_DYNAMIC; size = SHARED_HEAP_STARTSIZE; } else { // size = ((size + 63) & ~63) - 16; } array = (u8*)shared_heap_try_alloc(id, size); } data->buffer = array; data->buffer_size = size; data->buffer_offset = 0; data->flags = flags; data->id = id; out_stream->data = data; out_stream->vtbl = &shared_heap_output_stream_vtbl; } void shared_heap_output_stream_init_ex(output_stream* out_stream, u8 id, u8* array, u32 size, u8 flags) { shared_heap_output_stream_data* data; ZALLOC_OBJECT_OR_DIE( data, shared_heap_output_stream_data, BYTE_ARRAY_OUTPUT_STREAM_DATA_TAG); array = (u8*)shared_heap_wait_alloc(id, size); flags |= SHARED_HEAP_ZALLOC_CONTEXT; shared_heap_output_stream_init_ex_static(out_stream, id, array, size, flags, (shared_heap_output_stream_context*)data); } void shared_heap_output_stream_init(output_stream* out_stream, u8 id, u8* array, u32 size) { shared_heap_output_stream_init_ex(out_stream, id, array, size, 0); } void shared_heap_output_stream_reset(output_stream* stream) { shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data; data->buffer_offset = 0; } u32 shared_heap_output_stream_size(output_stream* stream) { shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data; return data->buffer_offset; } u32 shared_heap_output_stream_buffer_size(output_stream* stream) { shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data; return data->buffer_size; } u8* shared_heap_output_stream_buffer(output_stream* stream) { shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data; return data->buffer; } u8* shared_heap_output_stream_detach(output_stream* stream) { shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data; data->flags &= ~SHARED_HEAP_OWNED; return data->buffer; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/signals.c0000644000000000000000000000013114505005532021133 xustar000000000000000030 mtime=1695812442.493982919 29 atime=1695812445.79603021 30 ctime=1695812494.694730538 yadifa-2.6.5-11201/lib/dnscore/src/signals.c0000664000374500037450000011771014505005532021105 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #if __unix__ #define _GNU_SOURCE 1 #include #include #include #include #include #if defined(__linux__) || defined(__gnu_hurd__) #define _GNU_SOURCE 1 #include #include #include #elif defined(__sun) #include #endif #include "dnscore/logger.h" #include "dnscore/format.h" #include "dnscore/fdtools.h" #include "dnscore/timems.h" #include "dnscore/thread.h" #include "dnscore/thread_pool.h" #include "dnscore/process.h" #include "dnscore/signals.h" #define SIGNAL_MAX 32 #define SIGNAL_HANDLER_CHAIN 0 #define SIGNAL_DONT_QUEUE_TWICE 1 // avoids hammering the signal handling thread #if SIGNAL_DONT_QUEUE_TWICE #if HAVE_STDATOMIC_H #include #else #include "dnscore/thirdparty/stdatomic.h" #endif // HAS_STDATOMIC_H #endif // SIGNAL_DONT_QUEUE_TWICE #if DEBUG #if defined(__linux__) #include // testing for !((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 30))) is irrelevant as there is no name collision. #include static inline long int signal_gettid() { return (long int)syscall(__NR_gettid); } #else static inline long int signal_gettid() { return (long int)~0; } #endif #endif #define MODULE_MSG_HANDLE g_system_logger #define MAXTRACE 128 // Let this to 0 // This prevents the coredump from occurring. // Let's configure this using runtime flags. #define SIGNAL_HOOK_COREDUMP 1 static const char* signal_dump_path = "/tmp"; static thread_t signal_thread = 0; static mutex_t signal_mutex = MUTEX_INITIALIZER; static volatile int signal_handler_read_fd = -1; static volatile int signal_handler_write_fd = -1; static bool sigsegv_trytrace = TRUE; static bool sigsegv_tryloggerflush = TRUE; #if DEBUG static void signal_handler_cb_debug(u8 signum) { log_info("signal: %i received", (int)signum); } #define SIGNAL_HANDLER_NULL signal_handler_cb_debug #else #define SIGNAL_HANDLER_NULL NULL #endif // signal can be lost, a full pipe will not block and lose even more. // shutdown is thus given an override so that it cannot be lost after // the signal handler gets it. static volatile bool signal_shutdown_received = FALSE; struct signal_handler_entry { signal_handler_cb handler; #if SIGNAL_HANDLER_CHAIN struct signal_handler_entry *next; #endif #if SIGNAL_DONT_QUEUE_TWICE atomic_flag queued; #endif }; typedef struct signal_handler_entry signal_handler_entry; #if SIGNAL_HANDLER_CHAIN #if SIGNAL_DONT_QUEUE_TWICE #define SIGNAL_HANDLER_ENTRY {SIGNAL_HANDLER_NULL, NULL, ATOMIC_FLAG_INIT} #else #define SIGNAL_HANDLER_ENTRY {SIGNAL_HANDLER_NULL, NULL} #endif #else #if SIGNAL_DONT_QUEUE_TWICE #define SIGNAL_HANDLER_ENTRY {SIGNAL_HANDLER_NULL, ATOMIC_FLAG_INIT} #else #define SIGNAL_HANDLER_ENTRY {SIGNAL_HANDLER_NULL} #endif #endif static signal_handler_entry signal_handlers[SIGNAL_MAX] = { SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY, SIGNAL_HANDLER_ENTRY }; static u8 signal_ignored_at_shutdown[SIGNAL_MAX] = { SIGHUP, SIGUSR1, SIGINT, SIGTERM, SIGPIPE,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }; static void signal_ignore_for_shutdown() { int errno_value = errno; for(int i = 0; i < SIGNAL_MAX; ++i) { int s; if((s = signal_ignored_at_shutdown[i]) == 0) break; signal(s, SIG_IGN); } errno = errno_value; } static void signal_send_to_thread(int signo) { #if SIGNAL_DONT_QUEUE_TWICE assert(((signo >= 0) && (signo < SIGNAL_MAX)) || (signo == MAX_U8)); #if !defined(GCC_VERSION) || (GCC_VERSION > 40700) bool old_flag = (signo < SIGNAL_MAX)?atomic_flag_test_and_set(&signal_handlers[signo].queued):FALSE; #else bool old_flag; if(signo < SIGNAL_MAX) { atomic_flag* flag = &signal_handlers[signo].queued; old_flag = atomic_flag_test_and_set(flag); } else { old_flag = FALSE; } #endif if(!old_flag) { #endif int errno_value = errno; int ret; u8 signum = (u8)signo; // MUST be one byte long while((ret = write(signal_handler_write_fd, &signum, sizeof(signum))) != sizeof(signum)) { if(ret < 0) { ret = errno; #if EAGAIN != EWOULDBLOCK if((ret == EINTR) || (ret == EAGAIN) || (ret == EWOULDBLOCK)) { continue; } #else if((ret == EINTR) || (ret == EAGAIN)) { continue; } #endif } else if(ret == 0) { continue; } // failed unexpectedly if(signo < SIGNAL_MAX) { atomic_flag_clear(&signal_handlers[signo].queued); } break; } errno = errno_value; #if SIGNAL_DONT_QUEUE_TWICE } #endif } /* * signals are not supposed to be interrupted by other signals * still, it happened once, the pthread_create of another signal : deadlock * so, here is another check (mutexes are of course forbidden) */ // tool to avoid external function calls during the signal static int signal_strcat(char *dest, const char* src) { char *p = dest; while(*p != '\0') { p++; } while(*src != '\0') { *p++ = *src++; } *p = '\0'; return p - dest; } // tool to avoid external function calls during the signal static int signal_int2str(char *dest, int src) { char *p = dest; int tmp = src; do { p++; tmp /= 10; } while(tmp > 0); *p = '\0'; do { char c = '0' + (char)(src % 10); src /= 10; --p; *p = c; } while(src > 0); while(p > dest) { --p; *p = ' '; } return p - dest; } #if defined(__GLIBC__) || defined(__gnu_hurd__) static const char __HEXA__[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; static int signal_longlong2hexstr(char *dest, u64 src) { int shift = 60; do { *dest++ = __HEXA__[(src >> shift) & 15]; shift -= 4; } while(shift >= 0); *dest = '\0'; return 16; } static int signal_int2hexstr(char *dest, u32 src) { int shift = 28; do { *dest++ = __HEXA__[(src >> shift) & 15]; shift -= 4; } while(shift >= 0); *dest = '\0'; return 8; } static int signal_char2hexstr(char *dest, u8 src) { int shift = 4; do { *dest++ = __HEXA__[(src >> shift) & 15]; shift -= 4; } while(shift >= 0); *dest = '\0'; return 2; } // tool to avoid external function calls during the signal static int signal_ptr2str(char *dest, const void* srcp) { #if __SIZEOF_POINTER__ == 8 return signal_longlong2hexstr(dest,(u64)srcp); #elif __SIZEOF_POINTER__ == 4 return signal_int2hexstr(dest,(u32)srcp); #else #error "unsupported pointer size" #endif } #endif // static void signal_handler_thread_stop() { log_info("signal: thread stopping"); mutex_lock(&signal_mutex); if(signal_handler_read_fd >= 0) { signal_send_to_thread(MAX_U8); } mutex_unlock(&signal_mutex); } static noreturn void* signal_handler_thread(void* parms) { (void)parms; #if DEBUG log_debug7("thread started: self=%p, tid=%i", thread_self(), signal_gettid()); #endif thread_set_name("signal", 0, 0); #if DNSCORE_HAS_LOG_THREAD_TAG static char signal_thread_tag[9] = "signal"; logger_handle_set_thread_tag(signal_thread_tag); #endif log_info("signal: thread started"); while(signal_handler_read_fd >= 0) { u8 signum; ya_result return_code; #if DEBUG log_debug7("signal: waiting for next signal"); #endif if(FAIL(return_code = readfully(signal_handler_read_fd, &signum, sizeof(signum)))) { log_err("signal: error reading the next signal: %r", return_code); break; } #if DEBUG log_debug7("signal: handling signal %i", signum); #endif if(signum < SIGNAL_MAX) { #if SIGNAL_DONT_QUEUE_TWICE atomic_flag_clear(&signal_handlers[signum].queued); #endif if(signal_shutdown_received) { #if DEBUG if(signum != SIGINT && signum != SIGTERM) { log_debug7("signal: check that, handling a SIGINT instead"); } #endif signum = SIGINT; } #if SIGNAL_HANDLER_CHAIN signal_handler_entry* = &signal_handlers[signum]; if(signal_handler_entry->handler != NULL) { do { signal_handler_entry->handler(signum); signal_handler_entry = signal_handler_entry->next; } while(signal_handler_entry != NULL); } #else switch(signum) { case SIGABRT: case SIGBUS: case SIGFPE: case SIGILL: case SIGSEGV: break; case SIGINT: case SIGTERM: logger_sink_noblock(); break; default: logger_sink_noblock(); break; } if(signal_handlers[signum].handler != NULL) // NULL is right { signal_handlers[signum].handler(signum); } #endif } else if(signum == MAX_U8) { //signal_handler_thread_stop(); break; } } log_info("signal: thread stopping"); /* mutex_lock(&signal_mutex); signal_thread = 0; mutex_unlock(&signal_mutex); */ #if DNSCORE_HAS_LOG_THREAD_TAG logger_flush(); logger_handle_clear_thread_tag(); #endif log_info("signal: thread stopped"); logger_flush(); thread_exit(NULL); // unreachable #if GCC_VERSION < 40600 return NULL; #endif } void signal_handler_stop() { signal_handler_thread_stop(); /** * The signal thread CANNOT be joined here, * as if a signal handler callback calls it then it will ovbiously be a deadlock. */ } /** \brief handle the signals received * * @param[in] signo * * @note The signal handler CANNOT use the loggers or it has to use its own channels + handle. (ie: not the ones of the logger) * The reason being mutexes are not reentrant. So if a signal occurs while the log mutex is on * the signal will deadlock as soon as it tries to log. * * return NONE */ static void signal_handler(int signo, siginfo_t* info, void* context) { // formatln("signal_handler, pid=%i, tid=%p, signal=%i", getpid(), thread_self(), signo); switch(signo) { case SIGINT: // special cases case SIGTERM: { /* * We are shutting down : ignore other "command" signals * Also, in order to avoid handling an hammering of signals, * (and risking missing the shutdown if the pipe is already full) * we set a volatile that will be sync "soon" (no mutexes here please) */ signal_ignore_for_shutdown(); signal_shutdown_received = TRUE; signal_send_to_thread(signo); break; } #if SIGNAL_HOOK_COREDUMP case SIGABRT: case SIGBUS: case SIGFPE: case SIGILL: case SIGSEGV: { // reactivate the default handler int errno_value = errno; signal(signo, SIG_DFL); if(sigsegv_trytrace) { char filepath[PATH_MAX]; char number[32]; sigsegv_trytrace = FALSE; for(int source = 0; source <= 1; source++) { char *eol = (source == 0)?"\n":""; int fd = -1; /// @note edf: set to -1 to shut-up false positive "uninitialised" int len; filepath[0] = '\0'; signal_strcat(filepath, signal_dump_path); signal_strcat(filepath, "/"); signal_strcat(filepath, "sig-"); signal_int2str(number, signo); signal_strcat(filepath, number); signal_strcat(filepath, "-"); signal_int2str(number, getpid_ex()); signal_strcat(filepath, number); if(source == 0) { fd = open_create_ex(filepath, O_WRONLY|O_CREAT|O_APPEND|O_CLOEXEC, 0644); if(fd < 0) { continue; } } else { if(!logger_is_running()) { continue; } } len = signal_strcat(filepath, eol); if(source == 0) { writefully(fd, filepath, len); fsync(fd); } else { log_err(filepath); } #if defined(__GLIBC__) || defined(__gnu_hurd__) void* buffer[MAXTRACE]; char** strings; int n = backtrace(buffer, MAXTRACE); int i; time_t now = time(NULL); filepath[0] = '\0'; signal_strcat(filepath, "got signal "); signal_int2str(number, signo); signal_strcat(filepath, number); signal_strcat(filepath, " at time="); signal_int2str(number, now); signal_strcat(filepath, number); signal_strcat(filepath, " for address "); signal_ptr2str(number, info->si_addr); signal_strcat(filepath, number); len = signal_strcat(filepath, eol); if(source == 0) { writefully(fd, filepath, len); fsync(fd); } else { log_err(filepath); } #if __linux__ ucontext_t* ucontext = (ucontext_t*)context; /* * cpu registers dump, if supported * this helps a lot if there is no core dump available */ #ifdef __x86_64__ // specific x86_64 information struct text_idx { const char* name; int index; }; static struct text_idx text_idx[18] = { {"rax", REG_RAX}, {"rcx", REG_RCX}, {"rdx", REG_RDX}, {"rbx", REG_RBX}, {"rsi", REG_RSI}, {"rdi", REG_RDI}, {"rsp", REG_RSP}, {"rbp", REG_RBP}, {"r8 ", REG_R8}, {"r9 ", REG_R9}, {"r10", REG_R10}, {"r11", REG_R11}, {"r12", REG_R12}, {"r13", REG_R13}, {"r14", REG_R14}, {"r15", REG_R15}, {"rip", REG_RIP}, {"efl", REG_EFL} }; for(int i = 0; i < 18; ++i) { filepath[0] = '\0'; signal_strcat(filepath, text_idx[i].name); signal_strcat(filepath, "="); signal_longlong2hexstr(number, ucontext->uc_mcontext.gregs[text_idx[i].index]); signal_strcat(filepath, number); len = signal_strcat(filepath, eol); if(source == 0) { writefully(fd, filepath, len); fsync(fd); } else { log_err(filepath); } } #elif defined(__i386__) struct text_idx { const char* name; int index; }; static struct text_idx text_idx[10] = { {"eax", REG_EAX}, {"ecx", REG_ECX}, {"edx", REG_EDX}, {"ebx", REG_EBX}, {"esi", REG_ESI}, {"edi", REG_EDI}, {"esp", REG_ESP}, {"ebp", REG_EBP}, {"rip", REG_EIP}, {"efl", REG_EFL} }; for(int i = 0; i < 10; ++i) { filepath[0] = '\0'; signal_strcat(filepath, text_idx[i].name); signal_strcat(filepath, "="); signal_int2hexstr(number, ucontext->uc_mcontext.gregs[text_idx[i].index]); signal_strcat(filepath, number); len = signal_strcat(filepath, eol); if(source == 0) { writefully(fd, filepath, len); fsync(fd); } else { log_err(filepath); } } #else // not x86_64 nor i386 // cpu registers dump not supported (void)ucontext; #endif #endif // linux strings = backtrace_symbols(buffer, n); if(strings != NULL) { for(i = 0; i < n; i++) { filepath[0] = '\0'; signal_strcat(filepath, "\t["); signal_int2str(number, i); signal_strcat(filepath, number); signal_strcat(filepath, "]: "); signal_strcat(filepath, strings[i]); len = signal_strcat(filepath, eol); if(source == 0) { writefully(fd, filepath, len); fsync(fd); } else { log_err(filepath); } } } else { filepath[0] = '\0'; signal_strcat(filepath, "no backtrace available: "); signal_int2str(number, errno); signal_strcat(filepath, number); len = signal_strcat(filepath, eol); if(source == 0) { writefully(fd, filepath, len); fsync(fd); } else { log_err(filepath); } } filepath[0] = '\0'; signal_strcat(filepath, "pid: "); signal_int2str(number, getpid_ex()); signal_strcat(filepath, number); signal_strcat(filepath, " "); signal_strcat(filepath, "thread id: "); thread_t self = thread_self(); if(sizeof(self) >= sizeof(u64)) { signal_longlong2hexstr(number,(u64)self); } else { signal_int2hexstr(number,(u32)self); } signal_strcat(filepath, number); len = signal_strcat(filepath, eol); if(source == 0) { writefully(fd, filepath, len); fsync(fd); // fd IS initialised : (source == 0) => fd set } else { log_err(filepath); } #if __linux__ && (defined(__x86_64__) || defined(__i386__)) && (_BSD_SOURCE || _SVID_SOURCE || _DEFAULT_SOURCE) // dump more information about the memory address of the error #define PAGESIZE 4096 #define LINESIZE 32 const u8 *addr = (u8*)info->si_addr; for(;;) { u8 *page_addr = (u8*)(((intptr)addr) & ~(PAGESIZE - 1)); unsigned char vec[1]; if(mincore(page_addr, PAGESIZE, vec) == 0) { // memory is resident for(const u8* p = page_addr; p < &page_addr[PAGESIZE]; p += 32) { filepath[0] = '\0'; signal_ptr2str(number, p); signal_strcat(filepath, number); signal_strcat(filepath, " | "); for(int i = 0; i < LINESIZE; ++i) { signal_char2hexstr(number, p[i]); signal_strcat(filepath, number); signal_strcat(filepath, " "); } len = signal_strcat(filepath, "| "); for(int i = 0; i < LINESIZE; ++i) { u8 c = p[i]; if(c < 32 || c >= 127) { c = '.'; } filepath[len + i] = c; } len += LINESIZE; if(source == 0) { writefully(fd, filepath, len); fsync(fd); // fd IS initialised : (source == 0) => fd set } else { log_err(filepath); } } // dump enough memory to make sense if(&page_addr[PAGESIZE] >= &addr[32]) { break; } } else { int err = errno; if(err == ENOMEM) { // memory is not mapped filepath[0] = '\0'; signal_strcat(filepath, "page at "); signal_ptr2str(number, page_addr); signal_strcat(filepath, number); len = signal_strcat(filepath, " is not mapped."); } else { // filepath[0] = '\0'; signal_strcat(filepath, "could not get information for page at "); signal_ptr2str(number, page_addr); signal_strcat(filepath, number); signal_strcat(filepath, " : errno = "); signal_int2str(number, err); len = signal_strcat(filepath, number); } if(source == 0) { writefully(fd, filepath, len); fsync(fd); // fd IS initialised : (source == 0) => fd set } else { log_err(filepath); } break; } } #endif // linux && mincore supported #elif defined(__sun) filepath[0] = '\0'; signal_strcat(filepath, "got signal "); signal_int2str(number, signo); signal_strcat(filepath, number); signal_strcat(filepath, eol); if(source == 0) // 0 -> output to file, else to the logger if it's on { writefully(fd, filepath, len); printstack(fd); fsync(fd); } else { signal_strcat(filepath, "stack trace dumped in "); signal_strcat(filepath, signal_dump_path); signal_strcat(filepath, "/"); signal_strcat(filepath, "sig-"); signal_int2str(number, signo); signal_strcat(filepath, number); signal_strcat(filepath, "-"); signal_int2str(number, getpid_ex()); signal_strcat(filepath, number); log_err(filepath); } #else (void)info; (void)context; filepath[0] = '\0'; signal_strcat(filepath, "got signal "); signal_int2str(number, signo); signal_strcat(filepath, number); len = signal_strcat(filepath, "\nno backtrace available\n"); if(source == 0) { writefully(fd, filepath, len); fsync(fd); } else { log_err(filepath); } #endif if(source == 0) { close_ex(fd); } } // for both sources /** * Do NOT free(strings) : * If the memory is corrupted, this is one more chance to crash * */ } // if sigsegv_trytrace /* There COULD be some relevant information in the logger */ /* try to flush it */ if(sigsegv_tryloggerflush) { sigsegv_tryloggerflush = FALSE; logger_flush(); log_err("CRITICAL ERROR"); logger_flush(); } debug_malloc_hook_tracked_dump(); flushout(); errno = errno_value; break; } #endif default: { if(signal_handlers[signo].handler != NULL) // NULL is right, don't use SIGNAL_HANDLER_NULL { signal_send_to_thread(signo); } break; } } } /** \brief initialize the signals * * @param NONE * * @return NONE * */ int signal_handler_init() { int fds[2]; log_debug("signal_handler_init()"); if((signal_handler_read_fd >= 0) || (signal_handler_write_fd >= 0)) { log_debug("signal_handler_init() : already initialised"); return INVALID_STATE_ERROR; // invalid status } if(pipe(fds) < 0) { int pipe_err = ERRNO_ERROR; log_debug("signal_handler_init(): %r", pipe_err); return pipe_err; } signal_handler_read_fd = fds[0]; signal_handler_write_fd = fds[1]; int write_fd_flags = fcntl(signal_handler_write_fd, F_GETFL, 0); write_fd_flags |= O_NONBLOCK; if(fcntl(signal_handler_write_fd, F_SETFL, write_fd_flags) < 0) { int fcntl_err = ERRNO_ERROR; log_debug("signal_handler_init(): %r", fcntl_err); return fcntl_err; } int thread_errcode; if((thread_errcode = thread_create(&signal_thread, signal_handler_thread, NULL)) != 0) { close_ex(signal_handler_read_fd); close_ex(signal_handler_write_fd); signal_handler_read_fd = -1; signal_handler_write_fd = -1; log_debug("signal_handler_init(): %r", thread_errcode); return thread_errcode; } static const u8 handled_signals[] = { SIGHUP, /* Hangup (POSIX). */ SIGINT, /* Interrupt (ANSI). */ SIGQUIT, /* Quit (POSIX). */ SIGIOT, /* IOT trap (4.2 BSD). */ SIGUSR1, /* User-defined signal 1 (POSIX). */ #if SIGNAL_HOOK_COREDUMP SIGABRT, /* Abort (ANSI). */ SIGILL, /* Illegal instruction (ANSI). */ /* ERROR/EXIT */ SIGBUS, /* BUS error (4.2 BSD). */ SIGFPE, /* Floating-point exception (ANSI). */ /* ERROR/EXIT */ SIGSEGV, /* Segmentation violation (ANSI). */ /* ERROR/EXIT */ #endif SIGUSR2, /* User-defined signal 2 (POSIX). */ SIGALRM, /* Alarm clock (POSIX). */ SIGTERM, /* Termination (ANSI). */ /* SIGSTKFLT,*/ /* Stack fault. */ SIGCHLD, /* Child status has changed (POSIX). */ SIGCONT, /* Continue (POSIX). */ SIGTSTP, /* Keyboard stop (POSIX). */ SIGTTIN, /* Background read from tty (POSIX). */ SIGTTOU, /* Background write to tty (POSIX). */ SIGURG, /* Urgent condition on socket (4.2 BSD). */ SIGXCPU, /* CPU limit exceeded (4.2 BSD). */ SIGXFSZ, /* File size limit exceeded (4.2 BSD). */ 0 }; static const u8 ignored_signals[] = { SIGPIPE, /* Broken pipe (POSIX). */ 0 }; struct sigaction action; struct sigaction error_action; int signal_idx; ZEROMEMORY(&action, sizeof(action)); action.sa_sigaction = signal_handler; #ifdef SA_NOCLDWAIT action.sa_flags = SA_SIGINFO | SA_NOCLDSTOP | SA_NOCLDWAIT; #else /// @note 20151119 edf -- quick fix for Debian Hurd i386, and any other system missing SA_NOCLDWAIT action.sa_flags = SA_SIGINFO | SA_NOCLDSTOP; #endif ZEROMEMORY(&error_action, sizeof(error_action)); error_action.sa_sigaction = signal_handler; #ifdef SA_NOCLDWAIT error_action.sa_flags = SA_SIGINFO | SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESETHAND; #else /// @note 20151119 edf -- quick fix for Debian Hurd i386, and any other system missing SA_NOCLDWAIT error_action.sa_flags = SA_SIGINFO | SA_NOCLDSTOP | SA_RESETHAND; #endif for(signal_idx = 0; handled_signals[signal_idx] != 0; signal_idx++) { switch(signal_idx) { case SIGBUS: case SIGFPE: case SIGILL: case SIGSEGV: case SIGABRT: { sigemptyset(&error_action.sa_mask); /* can interrupt the interrupt */ break; } default: { sigfillset(&action.sa_mask); /* don't interrupt the interrupt */ break; } } sigaction(handled_signals[signal_idx], &action, NULL); } action.sa_handler = SIG_IGN; for(signal_idx = 0; ignored_signals[signal_idx] != 0; ++signal_idx) { sigaction(ignored_signals[signal_idx], &action, NULL); } log_debug("signal_handler_init() done"); return SUCCESS; } signal_handler_cb signal_handler_get(u8 signum) { if(signum < SIGNAL_MAX) { return signal_handlers[signum].handler; } else { return NULL; } } void signal_handler_set(u8 signum, signal_handler_cb handler) { if(handler != NULL) { struct sigaction action; struct sigaction error_action; ZEROMEMORY(&action, sizeof(action)); action.sa_sigaction = signal_handler; #ifdef SA_NOCLDWAIT action.sa_flags = SA_SIGINFO | SA_NOCLDSTOP | SA_NOCLDWAIT; #else /// @note 20151119 edf -- quick fix for Debian Hurd i386, and any other system missing SA_NOCLDWAIT action.sa_flags = SA_SIGINFO | SA_NOCLDSTOP; #endif ZEROMEMORY(&error_action, sizeof(error_action)); error_action.sa_sigaction = signal_handler; #ifdef SA_NOCLDWAIT error_action.sa_flags = SA_SIGINFO | SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESETHAND; #else /// @note 20151119 edf -- quick fix for Debian Hurd i386, and any other system missing SA_NOCLDWAIT error_action.sa_flags = SA_SIGINFO | SA_NOCLDSTOP | SA_RESETHAND; #endif sigfillset(&action.sa_mask); /* don't interrupt the interrupt */ signal_handlers[signum].handler = handler; sigaction(signum, &action, NULL); } else { signal(signum, SIG_DFL); signal_handlers[signum].handler = NULL; } } void signal_handler_finalize() { log_debug("signal_handler_finalize()"); if(signal_handler_write_fd >= 0) { for(int signum = 0; signum < SIGNAL_MAX; ++signum) { if(signal_handlers[signum].handler != NULL) // NULL is right { signal_handler_set(signum, NULL); } } log_debug1("signal: pipe not closed yet"); mutex_lock(&signal_mutex); thread_t signal_thread_local = signal_thread; mutex_unlock(&signal_mutex); if(signal_handler_read_fd >= 0) { u8 stop_value = MAX_U8; if(signal_thread_local != 0) { log_debug1("signal: handler is still running"); writefully(signal_handler_write_fd, &stop_value, sizeof(stop_value)); thread_join(signal_thread_local, NULL); mutex_lock(&signal_mutex); signal_thread = 0; mutex_unlock(&signal_mutex); log_debug1("signal: handler has stopped"); } else { log_debug1("signal: handler is not running anymore"); } int signal_handler_read_fd_local = signal_handler_read_fd; if(signal_handler_read_fd_local >= 0) { close_ex(signal_handler_read_fd_local); mutex_lock(&signal_mutex); signal_handler_read_fd = -1; mutex_unlock(&signal_mutex); } } else { if(signal_thread_local != 0) { log_debug1("signal: waiting for the handler to stop"); thread_join(signal_thread_local, NULL); mutex_lock(&signal_mutex); signal_thread = 0; mutex_unlock(&signal_mutex); } log_debug1("signal: handler has stopped"); } close_ex(signal_handler_write_fd); signal_handler_write_fd = -1; } else { if(signal_handler_read_fd >= 0) { log_err("signal: invalid pipe status r:%i>=0 && w:%i>=0", signal_handler_read_fd, signal_handler_write_fd); } if(signal_thread != 0) { log_err("signal: handler is unexpectedly still running"); } } log_debug("signal_handler_finalize() done"); } #else // WIN32 #include "dnscore/signals.h" int signal_handler_init() { return 0; } signal_handler_cb signal_handler_get(u8 signum) { return NULL; } void signal_handler_set(u8 signum, signal_handler_cb handler) { } void signal_handler_stop() { } void signal_handler_finalize() { } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/simple-http-server.c0000644000000000000000000000013214505005532023246 xustar000000000000000030 mtime=1695812442.425981945 30 atime=1695812445.793030168 30 ctime=1695812494.696730567 yadifa-2.6.5-11201/lib/dnscore/src/simple-http-server.c0000664000374500037450000006454514505005532023226 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnspacket DNS Messages * @ingroup dnscore * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include #include #if HAS_HTTPS #include #include #include #include #include #endif #include "dnscore/fdtools.h" #include "dnscore/ptr_vector.h" #include "dnscore/logger.h" #include "dnscore/config-cmdline.h" #include "dnscore/config_settings.h" #include "dnscore/pid.h" #include "dnscore/service.h" #include "dnscore/thread_pool.h" #include "dnscore/cmdline.h" #include "dnscore/tcp_io_stream.h" #include "dnscore/ptr_set.h" #include "dnscore/socket-server.h" #include "dnscore/zalloc.h" #include "dnscore/network.h" #include "dnscore/bytearray_output_stream.h" #include "dnscore/parsing.h" #include "dnscore/simple-http-server.h" #define SIMPLE_REST_SERVER_CLIENT_LINE_SIZE 4096 #define SIMPLE_REST_SERVER_CLIENT_LISTEN_BACKLOG 30 #define SRSTCLNT_TAG 0x544e4c4354535253 #define SRSTPAGE_TAG 0x4547415054535253 /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger ya_result uri_decode(const char *text_, const char *text_limit_, uri_decode_callback *uri_callback, void *args) { // un-escape output_stream baos; bytearray_output_stream_init_ex(&baos, NULL, text_limit_ - text_, BYTEARRAY_DYNAMIC); while(text_ < text_limit_) { if(*text_ != '%') { output_stream_write_u8(&baos, *text_); ++text_; } else { u32 v; ++text_; // for the percent if(sscanf(text_, "%2x", &v) == 1) { output_stream_write_u8(&baos, v); text_ += 2; // for the two ASCII chars } else { // log_err("uri decoding of '%s' failed", text_); output_stream_close(&baos); return ERROR; } } } output_stream_write_u8(&baos, 0); // parse char *text = (char*)bytearray_output_stream_buffer(&baos); //const char *text_limit = &text_[bytearray_output_stream_size(&baos) - 1]; char *param0; param0 = strchr(text, '?'); if(param0 == NULL) { // no parameters uri_callback(NULL, text, args); output_stream_close(&baos); return SUCCESS; } *param0++ = '\0'; uri_callback(NULL, text, args); char *name = param0; for(;;) { char *value = strchr(name, '='); if(value == NULL) { break; } size_t name_len = value - name; ++value; size_t value_len; char *name_next = strchr(value, '&'); if(name_next == NULL) { value_len = text_limit_ - value; } else { value_len = name_next - value; } name[name_len] = '\0'; value[value_len] = '\0'; // log_info("'%s' = '%s'", name, value); uri_callback(name, value, args); if(name_next == NULL) { break; } name = name_next + 1; } output_stream_close(&baos); return SUCCESS; } /** * Sends the "HTTP/1.1 [code]" header. * Where [code] is * 200 -- success * or anything else from https://en.wikipedia.org/wiki/List_of_HTTP_status_codes * @param os * @param code the * @return */ ya_result http_header_code(output_stream *os, int code) { ya_result ret; if(ISOK(ret = output_stream_write_fully(os, "HTTP/1.1 ", 9))) { if(ISOK(ret = osformat(os, "%i", code))) { ret = output_stream_write_fully(os, "\r\n", 2); } } return ret; } /** * Sends a header field. * * name: value\r\n * * @param os * @param name * @param name_len * @param value * @param value_len * @return */ ya_result http_header_field(output_stream *os, const char *name, size_t name_len, const char *value, size_t value_len) { ya_result ret; if(ISOK(ret = output_stream_write_fully(os, name, name_len))) { if(ISOK(ret = output_stream_write_fully(os, ": ", 2))) { if(ISOK(ret = output_stream_write_fully(os, value, value_len))) { ret = output_stream_write_fully(os, "\r\n", 2); } } } return ret; } /** * Sends the host header field. * * @param os * @param host * @param host_len * @return */ ya_result http_header_host(output_stream *os, const char *host, size_t host_len) { ya_result ret = http_header_field(os, "Host", 4, host, host_len); return ret; } /** * Sends the Content-Type header field. * * @param os * @param content_type * @param content_type_len * @return */ ya_result http_header_content_type(output_stream *os, const char *content_type, size_t content_type_len) { ya_result ret = http_header_field(os, "Content-Type", 12, content_type, content_type_len); return ret; } /** * Sends the application/octet-stream Content-Type header field. * * @param os * @return */ ya_result http_header_content_type_application_octet_stream(output_stream *os) { ya_result ret = http_header_content_type(os, "application/octet-stream", 24); return ret; } /** * Sends the application/json Content-Type header field. * * @param os * @return */ ya_result http_header_content_type_application_json(output_stream *os) { ya_result ret = http_header_content_type(os, "application/json", 16); return ret; } /** * Sends the text/html;charset=UTF-8 Content-Type header field. * * @param os * @return */ ya_result http_header_content_type_text_html_utf8(output_stream *os) { ya_result ret = http_header_content_type(os, "text/html;charset=UTF-8", 23); return ret; } /** * Sends the Transfer-Encoding header field. * * @param os * @param transfer_encoding * @param transfer_encoding_len * @return */ ya_result http_header_transfer_encoding(output_stream *os, const char *transfer_encoding, size_t transfer_encoding_len) { ya_result ret = http_header_field(os, "Transfer-Encoding", 17, transfer_encoding, transfer_encoding_len); return ret; } /** * Sends Transfer-Encoding as "chunked". * * @param os * @return */ ya_result http_header_transfer_encoding_chunked(output_stream *os) { ya_result ret = http_header_transfer_encoding(os, "chunked", 7); return ret; } /** * Sends the Content-Length field. * * @param os * @param length * @return */ ya_result http_header_content_length(output_stream *os, size_t length) { char length_as_text[16]; ya_result n = snformat(length_as_text, sizeof(length_as_text), "%llu", length); ya_result ret = http_header_field(os, "Content-Length", 14, length_as_text, n); return ret; } /** * Sends the Date header field. * * @param os * @param date * @param date_len * @return */ ya_result http_header_date(output_stream *os, const char *date, size_t date_len) { ya_result ret = http_header_field(os, "Date", 4, date, date_len); return ret; } /** * Sends the current date in RFC5322 format. * * @param os * @return */ ya_result http_header_date_now(output_stream *os) { char date_buffer[32]; ya_result date_buffer_len = time_epoch_as_rfc5322(time(NULL), date_buffer, sizeof(date_buffer)); // only fails if the buffer is < 29 bytes long ya_result ret = http_header_date(os, date_buffer, date_buffer_len); return ret; } /** * Closes the header. * * @param os * @return */ ya_result http_header_close(output_stream *os) { ya_result ret = output_stream_write_fully(os, "\r\n", 2); return ret; } /** * Sends a chunk lenght (Transfer-Encoding: chunked) * * MUST be followed by the announced amount of bytes, then * http_write_chunk_end(os) must be called * * @param os * @param data * @param size * @return */ ya_result http_write_chunk_begin(output_stream *os, size_t size) { ya_result ret; ret = osformat(os, "%llx\r\n", size); return ret; } /** * Sends a chunk (Transfer-Encoding: chunked) * * Ends a block started with the http_write_chunk_begin() call * Note that the last chunk is sent using http_write_chunk_close(os) * * @param os * @param data * @param size * @return */ ya_result http_write_chunk_end(output_stream *os) { ya_result ret; ret = output_stream_write_fully(os, "\r\n", 2); return ret; } /** * Sends a chunk (Transfer-Encoding: chunked) * * Note that the last chunk is sent using http_write_chunk_close(os) * * @param os * @param data * @param size * @return */ ya_result http_write_chunk(output_stream *os, const void *data, size_t size) { ya_result ret; if(ISOK(ret = osformat(os, "%llx\r\n", size))) { if(size > 0) { if(ISOK(ret = output_stream_write_fully(os, data, size))) { ret = output_stream_write_fully(os, "\r\n", 2); } } } return ret; } /** * Sends a chunk terminator * * @param os * @return */ ya_result http_write_chunk_close(output_stream *os) { ya_result ret = output_stream_write_fully(os, "0\r\n\r\n", 5); return ret; } /** * Sends content. * * The size must match Content-Length * * @param os * @param data * @param size * @return */ ya_result http_write_content(output_stream *os, const void *data, size_t size) { ya_result ret = output_stream_write_fully(os, data, size); return ret; } struct simple_rest_server_client { simple_rest_server *srs; socketaddress sa; socklen_t sa_len; int sockfd; }; typedef struct simple_rest_server_client simple_rest_server_client; static simple_rest_server_client* simple_rest_server_client_new_instance(simple_rest_server *srs) { simple_rest_server_client *client; ZALLOC_OBJECT_OR_DIE(client, simple_rest_server_client, SRSTCLNT_TAG); client->srs = srs; client->sa_len = sizeof(client->sa); client->sockfd = -1; mutex_lock(&srs->mtx); ++srs->client_current_count; mutex_unlock(&srs->mtx); return client; } static void simple_rest_server_client_reset(simple_rest_server_client* client) { client->sa_len = sizeof(client->sa); client->sockfd = -1; } static void simple_rest_server_client_delete(simple_rest_server_client *client) { if(client != NULL) { mutex_lock(&client->srs->mtx); --client->srs->client_current_count; cond_notify(&client->srs->cond); mutex_unlock(&client->srs->mtx); close_ex(client->sockfd); ZFREE_OBJECT(client); } } static int simple_rest_server_main(struct service_worker_s *worker); ya_result simple_rest_server_init(simple_rest_server *srs, struct addrinfo *addr) { static const int on = 1; socket_server_opensocket_s socket; ya_result ret; if(FAIL(ret = socket_server_opensocket_init(&socket, addr, SOCK_STREAM))) { return ret; } socket_server_opensocket_setopt(&socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); #if defined(SO_REUSEPORT) socket_server_opensocket_setopt(&socket, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)); #endif int sockfd = socket_server_opensocket_open(&socket); if(FAIL(sockfd)) { return sockfd; } mutex_init(&srs->mtx); cond_init(&srs->cond); ptr_set_init(&srs->path_page_set); srs->path_page_set.compare = ptr_set_asciizp_node_compare; srs->thread_pool = NULL; service_init(&srs->service, simple_rest_server_main, "rest"); service_args_set(&srs->service, srs); srs->client_current_count = 0; srs->sockfd = sockfd; return SUCCESS; } static simple_rest_server_page* simple_rest_server_page_new_instance(const char *path, simple_rest_server_page_writer *page_writer, void *page_private) { simple_rest_server_page *page; ZALLOC_OBJECT_OR_DIE(page, simple_rest_server_page, SRSTPAGE_TAG); page->path = strdup(path); page->writer = page_writer; page->private = page_private; page->rc = 1; return page; } static void simple_rest_server_page_delete(simple_rest_server_page *page) { if(page != NULL) { free(page->path); ZFREE_OBJECT(page); } } static void simple_rest_server_page_acquire_nolock(simple_rest_server *srs, simple_rest_server_page *page) { (void)srs; ++page->rc; } #if UNUSED_DONT_REMOVE_YET static void simple_rest_server_page_acquire(simple_rest_server *srs, simple_rest_server_page *page) { mutex_lock(&srs->mtx); simple_rest_server_page_acquire_nolock(srs, page); mutex_unlock(&srs->mtx); } #endif static void simple_rest_server_page_release(simple_rest_server *srs, simple_rest_server_page *page) { mutex_lock(&srs->mtx); if(--page->rc == 0) { ptr_set_delete(&srs->path_page_set, page->path); mutex_unlock(&srs->mtx); simple_rest_server_page_delete(page); } else { mutex_unlock(&srs->mtx); } } static ya_result simple_rest_server_page_release_with_path(simple_rest_server *srs, const char *path) { simple_rest_server_page *page; mutex_lock(&srs->mtx); ptr_node *node = ptr_set_find(&srs->path_page_set, path); if((node != NULL) && (node->value != NULL)) { page = (simple_rest_server_page*)node->value; if(--page->rc == 0) { ptr_set_delete(&srs->path_page_set, path); mutex_unlock(&srs->mtx); simple_rest_server_page_delete(page); } else { mutex_unlock(&srs->mtx); } return SUCCESS; } else { return ERROR; } } ya_result simple_rest_server_page_register(simple_rest_server *srs, const char *path, simple_rest_server_page_writer *page_writer, void *page_private) { simple_rest_server_page *page = simple_rest_server_page_new_instance(path, page_writer, page_private); bool inserted = FALSE; mutex_lock(&srs->mtx); ptr_node *node = ptr_set_insert(&srs->path_page_set, page->path); if(node->value == NULL) { node->value = page; inserted = TRUE; } mutex_unlock(&srs->mtx); if(inserted) { return SUCCESS; } else { simple_rest_server_page_delete(page); return ERROR; } } ya_result simple_rest_server_page_unregister(simple_rest_server *srs, const char *path) { ya_result ret = simple_rest_server_page_release_with_path(srs, path); return ret; } static void simple_rest_server_destroy_callback(ptr_node *node) { if(node->value != NULL) { simple_rest_server_page *page = (simple_rest_server_page*)node->value; simple_rest_server_page_delete(page); } } void simple_rest_server_finalize(simple_rest_server *srs) { mutex_lock(&srs->mtx); ptr_set_callback_and_destroy(&srs->path_page_set, simple_rest_server_destroy_callback); mutex_unlock(&srs->mtx); cond_finalize(&srs->cond); mutex_destroy(&srs->mtx); close_ex(srs->sockfd); srs->sockfd = -1; } void simple_rest_server_threadpool_set(simple_rest_server *srs, struct thread_pool_s* tp) { mutex_lock(&srs->mtx); srs->thread_pool = tp; mutex_unlock(&srs->mtx); } struct thread_pool_s* simple_rest_server_threadpool_get(simple_rest_server *srs) { mutex_lock(&srs->mtx); struct thread_pool_s* tp = srs->thread_pool; mutex_unlock(&srs->mtx); return tp; } ya_result simple_rest_server_start(simple_rest_server *srs) { ya_result ret = service_start(&srs->service); return ret; } ya_result simple_rest_server_stop(simple_rest_server *srs) { ya_result ret = service_stop(&srs->service); return ret; } /** * * Gets the HTTP header field of the query * * @param args * @param host * @return */ const char * simple_rest_server_page_writer_args_get_header_field(const simple_rest_server_page_writer_args *args, const char *host) { ptr_node *node = ptr_set_find(&args->query_name_value_set, host); if(node != NULL && node->value != NULL) { return (const char*)node->value; } else { return NULL; } } /** * * Gets the HTTP header field of the query * * @param args * @param host * @return */ const char * simple_rest_server_page_writer_args_get_uri_arg(const simple_rest_server_page_writer_args *args, const char *host) { ptr_node *node = ptr_set_find(&args->uri_name_value_set, host); if(node != NULL && node->value != NULL) { return (const char*)node->value; } else { return NULL; } } static void simple_rest_server_client_answer_uri(const char *name, const char *value, void *args) { simple_rest_server_page_writer_args *srspwa = (simple_rest_server_page_writer_args*)args; if(name != NULL) { ptr_set *uri_parameters_set = (ptr_set*)&srspwa->uri_name_value_set; ptr_node *node = ptr_set_insert(uri_parameters_set, (void*)name); if(node->value == NULL) { node->key = strdup(name); node->value = strdup(value); } } else { srspwa->path = strdup(value); } } static void simple_rest_server_client_answer_destroy_callback(ptr_node *node) { if(node->value != NULL) { free(node->key); free(node->value); } } static void simple_rest_server_client_answer(simple_rest_server_client *client) { input_stream is; output_stream os; simple_rest_server_page *page = NULL; simple_rest_server_page_writer_args args; ya_result ret; int line_index; char line[SIMPLE_REST_SERVER_CLIENT_LINE_SIZE]; // read the input fd_input_stream_attach(&is, client->sockfd); fd_output_stream_attach_noclose(&os, client->sockfd); // we don't want to close the file descriptor twice ptr_set_init(&args.uri_name_value_set); args.uri_name_value_set.compare = ptr_set_asciizp_node_compare; ptr_set_init(&args.query_name_value_set); args.query_name_value_set.compare = ptr_set_asciizp_node_compare; for(line_index = 0; ; ++line_index) { if((ret = input_stream_read_line(&is, line, sizeof(line))) <= 0) { // unexpected eof log_err("http: unexpected eof"); break; } --ret; while((ret >= 0) && (line[ret] <= ' ')) { --ret; } ++ret; if(ret == 0) { // details have been gathered, now answer if(page != NULL) { page->writer(page, &os, &args); break; } } line[ret] = '\0'; log_debug("http: parsing [%i] '%s'", line_index, line); // begins with 'GET ' ? // ends with ' HTTP/1.1' ? if(line_index == 0) { if((ret >= 9) && (memcmp(line, "GET ", 4) == 0) && (memcmp(&line[ret - 9], " HTTP/1.1", 9) == 0)) { ya_result uri_err = uri_decode(&line[4], &line[ret - 9], simple_rest_server_client_answer_uri, &args); if(FAIL(uri_err)) { line[ret - 9] = '\0'; log_err("http: could not parse uri '%s'", &line[4]); break; } // early cut: check if the page is registered mutex_lock(&client->srs->mtx); const char *path = args.path; while(*path == '/') ++path; // get the page ptr_node *node = ptr_set_find(&client->srs->path_page_set, path); if((node != NULL) && (node->value != NULL)) { page = (simple_rest_server_page*)node->value; simple_rest_server_page_acquire_nolock(client->srs, page); mutex_unlock(&client->srs->mtx); } else { static const char error_404[] = "404 not found."; mutex_unlock(&client->srs->mtx); http_header_code(&os, 404); http_header_host(&os, "localhost", 9); http_header_date_now(&os); http_header_content_length(&os, sizeof(error_404) - 1); http_header_close(&os); http_write_content(&os, error_404, sizeof(error_404) - 1); log_err("http: '%s': path not found", args.path); break; } } else { log_err("http: query '%s' not supported", line); break; } } else { char *name_end = strchr(line, ':'); if(name_end == NULL) { log_err("http: cannot parse '%s'", line); break; } *name_end++ = '\0'; const char *name = line; const char *value = parse_skip_spaces(name_end); ptr_node *node = ptr_set_insert(&args.query_name_value_set, (void*)name); if(node->value != NULL) { node->key = strdup(name); node->value = strdup(value); } } } ptr_set_callback_and_destroy(&args.uri_name_value_set, simple_rest_server_client_answer_destroy_callback); ptr_set_callback_and_destroy(&args.query_name_value_set, simple_rest_server_client_answer_destroy_callback); if(page != NULL) { simple_rest_server_page_release(client->srs, page); } output_stream_close(&os); input_stream_close(&is); } static void* simple_rest_server_client_answer_thread(void *client_parm) { simple_rest_server_client *client = (simple_rest_server_client*)client_parm; simple_rest_server_client_answer(client); simple_rest_server_client_delete(client); return NULL; } static int simple_rest_server_main(struct service_worker_s *worker) { simple_rest_server *srs = (simple_rest_server*)service_args_get(worker->service); if(FAIL(listen(srs->sockfd, SIMPLE_REST_SERVER_CLIENT_LISTEN_BACKLOG))) { return ERRNO_ERROR; } simple_rest_server_client *client = simple_rest_server_client_new_instance(srs); service_set_servicing(worker); while(service_should_run(worker)) { int client_sockfd = accept(srs->sockfd, &client->sa.sa, &client->sa_len); if(client_sockfd < 0) { int err = errno; #if EAGAIN != EWOULDBLOCK if(!((err == EINTR) || (err == EAGAIN) || (err == EWOULDBLOCK))) { log_err("failure to accept: %r", MAKE_ERRNO_ERROR(err)); } #else if(!((err == EINTR) || (err == EAGAIN))) { log_err("failure to accept: %r", MAKE_ERRNO_ERROR(err)); } #endif continue; } client->sockfd = client_sockfd; if(srs->thread_pool != NULL) { if(ISOK(thread_pool_try_enqueue_call(srs->thread_pool, simple_rest_server_client_answer_thread, client, NULL, "rest-client"))) { client = simple_rest_server_client_new_instance(srs); } else { simple_rest_server_client_answer(client); simple_rest_server_client_reset(client); } } else { simple_rest_server_client_answer(client); simple_rest_server_client_reset(client); } } service_set_stopping(worker); simple_rest_server_client_delete(client); // do this first mutex_lock(&srs->mtx); while(srs->client_current_count > 0) { cond_timedwait(&srs->cond, &srs->mtx, ONE_SECOND_US); // 1 sec } mutex_unlock(&srs->mtx); return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/socket-server.c0000644000000000000000000000013214505005532022270 xustar000000000000000030 mtime=1695812442.453982345 30 atime=1695812445.794030182 30 ctime=1695812494.698730596 yadifa-2.6.5-11201/lib/dnscore/src/socket-server.c0000664000374500037450000010725714505005532022246 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup network * @ingroup dnscore * @brief * * @{ */ #include #include "dnscore/dnscore-config-features.h" #if DNSCORE_HAVE_SYS_PRCTL_H #if 0 /* fix */ #else #define HAS_PR_SET_PDEATHSIG 0 #endif #endif #if HAS_PR_SET_PDEATHSIG #include #endif #define SHUTDOWN_DETECT_BY_POLLING 0 #include "dnscore/socket-server.h" #include "dnscore/format.h" #include "dnscore/fdtools.h" #include "dnscore/host_address.h" #include "dnscore/mutex.h" #include "dnscore/logger.h" #include "dnscore/process.h" #include "dnscore/thread.h" /* #if sizeof(socket_server_opensocket_s) < sizeof(struct socket_server_opensocket_noserver_s) #error "socket_server_opensocket_s is smaller than socket_server_opensocket_noserver_s" #endif */ extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_MASK 3 #define SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_IGNORE 0 #define SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_WARNING 1 #define SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_ERROR 2 // will stop the socket creation #if __unix__ static pid_t socket_server_pid = 0; static pid_t socket_server_parent_pid = 0; static uid_t socket_server_parent_uid = 65535; static int socket_server_pipe[2] = {-1, -1}; static int socket_server_sock[2] = {-1, -1}; static int socket_server_wire[2] = {-1, -1}; static group_mutex_t socket_server_mtx = GROUP_MUTEX_INITIALIZER; static void socket_server_get_level_name(int level, char *out_buffer, size_t out_buffer_size) { const char *text; switch(level) { #ifdef IPPROTO_IP case IPPROTO_IP: { text = "IPPROTO_IP"; break; } #endif #ifdef IPPROTO_IPV6 case IPPROTO_IPV6: { text = "IPPROTO_IPV6"; break; } #endif #ifdef SOL_SOCKET case SOL_SOCKET: { text = "SOL_SOCKET"; break; } #endif default: text = NULL; break; } if(text != NULL) { strncpy(out_buffer, text, out_buffer_size); out_buffer[out_buffer_size - 1] = '\0'; } else { snformat(out_buffer, out_buffer_size, "%i", text); } } static void socket_server_get_optname_name(int level, int optname, char *out_buffer, size_t out_buffer_size) { (void)level; const char *text; switch(optname) { #ifdef IPV6_V6ONLY case IPV6_V6ONLY: { text = "IPV6_V6ONLY"; break; } #endif #ifdef IP_RECVDSTADDR case IP_RECVDSTADDR: { text = "IP_RECVDSTADDR"; break; } #endif #ifdef IPV6_PKTINFO case IPV6_PKTINFO: { text = "IPV6_PKTINFO"; break; } #endif #ifdef IPV6_RECVPKTINFO case IPV6_RECVPKTINFO: { text = "IPV6_RECVPKTINFO"; break; } #endif #ifdef SO_REUSEADDR case SO_REUSEADDR: { text = "SO_REUSEADDR"; break; } #endif #ifdef SO_REUSEPORT case SO_REUSEPORT: { text = "SO_REUSEPORT"; break; } #endif default: text = NULL; break; } if(text != NULL) { strncpy(out_buffer, text, out_buffer_size); out_buffer[out_buffer_size - 1] = '\0'; } else { snformat(out_buffer, out_buffer_size, "%i", text); } } static void socket_server_close_fd(int* fd) { if((fd != NULL) && (*fd >= 0)) { log_info("socket-server: closing fd %i", *fd); close_ex(*fd); *fd = -1; } } uid_t socket_server_uid() { return socket_server_parent_uid; } static void socket_server_close_fds() { // close socket_server_close_fd(&socket_server_pipe[0]); // R socket_server_close_fd(&socket_server_pipe[1]); // W socket_server_close_fd(&socket_server_sock[0]); // R socket_server_close_fd(&socket_server_sock[1]); // W socket_server_close_fd(&socket_server_wire[0]); // R socket_server_close_fd(&socket_server_wire[1]); // W } static ya_result socket_server_send_error(int fd, ya_result value) { struct msghdr msg; struct iovec iov[1]; log_warn("socket-server: answering with an error: socket %i: %r", fd, value); msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = &value; iov[0].iov_len = sizeof(value); msg.msg_iov = iov; msg.msg_iovlen = 1; ssize_t n; while((n = sendmsg(fd, &msg, 0)) < 0) { ya_result ret = errno; if(ret != EINTR) { ret = MAKE_ERRNO_ERROR(ret); log_err("socket-server: failed to answer with an error: socket %i: %r", fd, ret); return ret; } } return (ya_result)n; } static ya_result socket_server_send(int fd, int sockfd) { struct msghdr msg; struct iovec iov[1]; log_info("socket-server: answering: socket %i: %i", fd, sockfd); ya_result ret = 0; union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; /// @note 20170518 edf -- this OSX warning is said to be harmless } control_un; struct cmsghdr *cmptr; ZEROMEMORY(&msg, sizeof(msg)); ZEROMEMORY(iov, sizeof(iov)); ZEROMEMORY(&control_un, sizeof(control_un)); msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); cmptr = CMSG_FIRSTHDR(&msg); cmptr->cmsg_len = CMSG_LEN(sizeof(int)); cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; int * const cmptr_sockfd_ptr = (int*)CMSG_DATA(cmptr); *cmptr_sockfd_ptr = sockfd; msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = &ret; iov[0].iov_len = sizeof(ret); msg.msg_iov = iov; msg.msg_iovlen = 1; ssize_t n; while((n = sendmsg(fd, &msg, 0)) < 0) { ya_result ret = errno; if(ret != EINTR) { ret = MAKE_ERRNO_ERROR(ret); log_err("socket-server: failed to answer: socket %i: %i: %r", fd, sockfd, ret); return ret; } } return (ya_result)n; } static ssize_t socket_server_recv(int fd, int *sockfdp) { struct msghdr msg; struct iovec iov[1]; ya_result ret = /**/ ERROR; // valid use of ERROR union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; log_info("socket-server: receiving: socket %i", fd); msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); cmptr = CMSG_FIRSTHDR(&msg); cmptr->cmsg_len = CMSG_LEN(sizeof(int)); cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; int *data_to_set_to_zero = (int*)CMSG_DATA(cmptr); *data_to_set_to_zero = 0; msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = &ret; iov[0].iov_len = sizeof(ret); msg.msg_iov = iov; msg.msg_iovlen = 1; while(recvmsg(fd, &msg, 0) <= 0) { ya_result err = errno; if(err != EINTR) { err = MAKE_ERRNO_ERROR(err); log_err("socket-server: failed to receive: socket %i: %r", fd, ret); return err; } } if( ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL) && (cmptr->cmsg_len == CMSG_LEN(sizeof(int))) ) { if(cmptr->cmsg_level != SOL_SOCKET) { log_err("socket-server: receiving: socket %i: !SOL_SOCKET", fd); return ERROR; } if(cmptr->cmsg_type != SCM_RIGHTS) { log_err("socket-server: receiving: socket %i: !SCM_RIGHTS", fd); return ERROR; } int* cmsg_data = (int*)CMSG_DATA(cmptr); *sockfdp = *cmsg_data; if(*sockfdp < 0) { ret = MAKE_ERRNO_ERROR(ENFILE); } log_info("socket-server: received: socket %i: %i", fd, *sockfdp); return ret; } else if((msg.msg_iovlen == 1) && (msg.msg_iov != NULL) && (msg.msg_iov->iov_len == sizeof(u32)) && (msg.msg_iov->iov_base != NULL)) { ret = (s32)GET_U32_AT_P(msg.msg_iov->iov_base); if(ISOK(ret)) { ret = MAKE_ERRNO_ERROR(ENFILE); } *sockfdp = -1; return ret; } else { log_err("socket-server: receiving: socket %i: invalid message", fd); if(ISOK(ret)) { ret = INVALID_STATE_ERROR; } *sockfdp = -1; return ret; } } #if !SHUTDOWN_DETECT_BY_POLLING static void* socket_server_wire_thread(void* args) { (void)args; static const char name[] = "wire"; thread_set_name("wire", 0, 0); #if DNSCORE_HAS_LOG_THREAD_TAG static char wire_thread_tag[9] = "wire"; logger_handle_set_thread_tag(wire_thread_tag); #endif // will block when the pipe is full (4KB) // will trigger a SIGPIPE when every other parent is dead for(;;) { int n = write(socket_server_wire[1], name, sizeof(name)); if(n < 0) { int err = errno; if(err == EPIPE) { #if DNSCORE_HAS_LOG_THREAD_TAG logger_handle_clear_thread_tag(); #endif exit(0); } } } } #endif static void socket_server_server() { #if SHUTDOWN_DETECT_BY_POLLING struct timeval timeout; fd_set rdset; #endif u8 buffer_in[SERVER_CONTEXT_API_BUFFER_SIZE]; thread_set_name("ynetsrv", 0, 0); // should NOT be named with "yadifa(d)*" #if SHUTDOWN_DETECT_BY_POLLING timeout.tv_sec = 5; timeout.tv_usec = 0; #endif #if DNSCORE_HAS_LOG_THREAD_TAG static char socksvr_thread_tag[9] = "socksvr"; logger_handle_set_thread_tag(socksvr_thread_tag); #endif log_info("socket-server: started"); #if DEBUG formatln("socket-server: started"); flushout(); #endif #if !SHUTDOWN_DETECT_BY_POLLING thread_t wire_thread = 0; if(thread_create(&wire_thread, socket_server_wire_thread, NULL) == 0) { log_info("socket-server: trip wire started"); #if DEBUG formatln("socket-server: trip wire started"); flushout(); #endif } else { log_warn("socket-server: trip wire did not start: server may not stop without some help"); #if DEBUG formatln("socket-server: trip wire did not start: server may not stop without some help"); flushout(); #endif } #endif bool parent_ready = FALSE; for(;;) { ya_result ret = SUCCESS; // ai_family ai_addr ai_addrlen // count * (data_len, data) #if SHUTDOWN_DETECT_BY_POLLING FD_ZERO(&rdset); FD_SET(socket_server_pipe[0], &rdset); int avail = select(socket_server_pipe[0] + 1, &rdset, NULL, NULL, &timeout); if(avail < 0) { log_err("socket-server: select failed with: %r", ERRNO_ERROR); #if DEBUG formatln("socket-server: select failed with: %r", ERRNO_ERROR); flushout(); #endif break; } if(avail == 0) { if(getppid() == socket_server_parent_pid) { continue; } else { break; } } #endif if(parent_ready) { log_info("socket-server: waiting for command"); } #if DEBUG formatln("socket-server: waiting for command"); flushout(); #endif int n = read(socket_server_pipe[0], buffer_in, 1); if(!parent_ready) { #if DEBUG formatln("socket-server: parent is not ready yet"); flushout(); #endif logger_start(); #if DEBUG formatln("socket-server: logger started"); flushout(); #endif logger_flush(); #if DEBUG formatln("socket-server: logger flushed"); flushout(); #endif parent_ready = TRUE; } if(n < 0) { ret = ERRNO_ERROR; #if DEBUG formatln("socket-server: read: header: %r", ret); flushout(); #endif log_err("socket-server: read: header: %r", ret); break; } if(n == 0) { #if DEBUG formatln("socket-server: read: header: empty"); flushout(); #endif log_err("socket-server: read: header: empty"); break; } log_debug("socket-server: reading command message (%i bytes)", buffer_in[0]); #if DEBUG formatln("socket-server: reading command message (%i bytes)", buffer_in[0]); flushout(); #endif if(FAIL(ret = readfully(socket_server_pipe[0], &buffer_in[1], buffer_in[0]))) { ret = ERRNO_ERROR; #if DEBUG formatln("socket-server: read: data: %r", ret); flushout(); #endif log_err("socket-server: read: data: %r", ret); break; } char level_buffer[32]; char optname_buffer[32]; // ai_family ai_addr ai_addrlen // count * (field1, field2, data_len, data[]) u8 *p = &buffer_in[1]; int sockopt_count = *p; ++p; int ai_family = GET_U32_AT_P(p); p += 4; int so_type = GET_U32_AT_P(p); p += 4; int so_proto = GET_U32_AT_P(p); p += 4; int ai_addrlen = GET_U32_AT_P(p); p += 4; socketaddress ai_addr; memcpy(&ai_addr, p, ai_addrlen); p += ai_addrlen; #if DEBUG formatln("socket-server: sockaddr family %i %{sockaddr} (%i) ai_addr.ss_family=%i", ai_family, &ai_addr, ai_addrlen, ai_addr.sa.sa_family); flushout(); #endif #if DEBUG switch(ai_addr.sa.sa_family) { case AF_INET: { #if DEBUG formatln("socket-server: sockaddr family %i %{sockaddr} (%i) ai_addr.ss_family=%i v4 port=%i", ai_family, &ai_addr, ai_addrlen, ai_addr.sa.sa_family, ai_addr.sa4.sin_port); flushout(); #endif if(ai_addr.sa4.sin_port == 0) { ai_addr.sa.sa_family = AF_UNSPEC; } break; } case AF_INET6: { #if DEBUG formatln("socket-server: sockaddr family %i %{sockaddr} (%i) ai_addr.ss_family=%i v6 port=%i", ai_family, &ai_addr, ai_addrlen, ai_addr.sa.sa_family, ai_addr.sa6.sin6_port); flushout(); #endif if(ai_addr.sa6.sin6_port == 0) { ai_addr.sa.sa_family = AF_UNSPEC; } break; } default: { ai_addr.sa.sa_family = AF_UNSPEC; break; } } #endif int sockfd; #if DEBUG formatln("socket-server: socket(%i, %i, %i)", ai_family, so_type, so_proto); flushout(); #endif if(FAIL(sockfd = socket(ai_family, so_type, so_proto))) { ret = ERRNO_ERROR; #if DEBUG formatln("socket-server: failed to socket(%i, %i, %i) for %{sockaddr}: %r", ai_family, so_type, so_proto, &ai_addr, ret); flushout(); #endif log_err("socket-server: socket: failed to socket(%i, %i, %i) for %{sockaddr}: %r", ai_family, so_type, so_proto, &ai_addr, ret); continue; } fd_setcloseonexec(sockfd); //HAVE_MSGHDR_MSG_CONTROL for(int i = 0; i < sockopt_count; ++i) { int operation = GET_U32_AT_P(p); p += sizeof(u32); int level = GET_U32_AT_P(p); p += sizeof(u32); int optname = GET_U32_AT_P(p); p += sizeof(u32); socklen_t optlen = GET_U32_AT_P(p); p += sizeof(u32); void *opt_val = p; p += optlen; socket_server_get_level_name(level, level_buffer, sizeof(level_buffer)); socket_server_get_optname_name(level, optname, optname_buffer, sizeof(optname_buffer)); #if DEBUG formatln("socket-server: setsockopt(%i, %s, %s, %p, %i)", sockfd, level_buffer, optname_buffer, opt_val, optlen); flushout(); #endif if(FAIL(setsockopt(sockfd, level, optname, opt_val, optlen))) { ya_result setsockopt_ret = ERRNO_ERROR; if((operation & SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_MASK) == SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_WARNING) { #if DEBUG formatln("socket-server: setsockopt: failed to setsockopt(%i, %s, %s, %p, %i) for %{sockaddr}: %r", sockfd, level_buffer, optname_buffer, opt_val, optlen, &ai_addr, setsockopt_ret); flushout(); #endif log_warn("socket-server: setsockopt: failed to setsockopt(%i, %s, %s, %p, %i) for %{sockaddr}: %r", sockfd, level_buffer, optname_buffer, opt_val, optlen, &ai_addr, setsockopt_ret); } else if((operation & SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_MASK) == SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_ERROR) { #if DEBUG formatln("socket-server: setsockopt: failed to setsockopt(%i, %s, %s, %p, %i) for %{sockaddr}: %r", sockfd, level_buffer, optname_buffer, opt_val, optlen, &ai_addr, setsockopt_ret); flushout(); #endif log_err("socket-server: setsockopt: failed to setsockopt(%i, %s, %s, %p, %i) for %{sockaddr}: %r", sockfd, level_buffer, optname_buffer, opt_val, optlen, &ai_addr, setsockopt_ret); socket_server_close_fd(&sockfd); ret = setsockopt_ret; break; } } #if DEBUG formatln("socket-server: setsockopt(%i, %i, %i, %p, %i) success", sockfd, level, optname, opt_val, optlen); #endif } if(ISOK(ret)) { #if DEBUG formatln("socket-server: bind(%i, %{sockadd}, %i)", sockfd, &ai_addr.sa, ai_addrlen); flushout(); #endif if(ISOK(bind(sockfd, &ai_addr.sa, ai_addrlen))) { // send the socket on its channel #if DEBUG formatln("socket-server: sending %{sockaddr} on bound socked %i to the caller", &ai_addr, sockfd); flushout(); #endif log_info("socket-server: sending %{sockaddr} on bound socked %i to the caller", &ai_addr, sockfd); if(FAIL(ret = socket_server_send(socket_server_sock[1], sockfd))) { #if DEBUG formatln("socket-server: failed to send %{sockaddr} on bound socked %i to the caller: %r", &ai_addr, sockfd, ret); flushout(); #endif log_err("socket-server: failed to send %{sockaddr} on bound socked %i to the caller: %r", &ai_addr, sockfd, ret); } socket_server_close_fd(&sockfd); } else { ret = ERRNO_ERROR; #if DEBUG formatln("bind: failed to bind(%i, %{sockaddr}, %i) for %{sockaddr}: %r", sockfd, &ai_addr.sa, ai_addrlen, &ai_addr, ret); flushout(); #endif // log_warn("socket-server: socket server can only serve privileged ports if the uid is 0"); log_err("socket-server: bind: failed to bind(%i, %{sockaddr}, %i) for %{sockaddr}: %r", sockfd, &ai_addr.sa, ai_addrlen, &ai_addr, ret); socket_server_close_fd(&sockfd); socket_server_send_error(socket_server_sock[1], ret); } } else { #if DEBUG formatln("socket-server: setsockopt(%i, ...) failed: %r", sockfd, ret); #endif } } #if DEBUG formatln("socket-server: stopped"); flushout(); #endif log_info("socket-server: stopped"); socket_server_close_fd(&socket_server_pipe[0]); #if DNSCORE_HAS_LOG_THREAD_TAG logger_handle_clear_thread_tag(); #endif dnscore_finalize(); exit(0); } #else // WIN32 // #endif /** * * * @param ctx the struct to initialise * @param addr the address * @param sock_type e.g.: SOCK_STREAM, SOCK_DGRAM, ... */ ya_result socket_server_opensocket_init(socket_server_opensocket_s *ctx, struct addrinfo *addr, int sock_type) { switch(addr->ai_family) { case AF_INET: { struct sockaddr_in* sa4 = (struct sockaddr_in*)addr->ai_addr; if(sa4->sin_port == 0) { return INVALID_ARGUMENT_ERROR; } break; } case AF_INET6: { struct sockaddr_in6* sa6 = (struct sockaddr_in6*)addr->ai_addr; if(sa6->sin6_port == 0) { return INVALID_ARGUMENT_ERROR;; } break; } default: { return INVALID_ARGUMENT_ERROR;; } } #if __unix__ if(socket_server_pid != 0) { u8 *p = ctx->buffer_out; #if DEBUG memset(p, 0x5a, sizeof(ctx->buffer_out)); #endif *p = 0xff; // reserved for message size ++p; *p = 0; // reserved for message size ++p; SET_U32_AT_P(p, addr->ai_family); p += sizeof(u32); SET_U32_AT_P(p, sock_type); p += sizeof(u32); SET_U32_AT_P(p, 0); p += sizeof(u32); SET_U32_AT_P(p, addr->ai_addrlen); p += sizeof(u32); memcpy(p, addr->ai_addr, addr->ai_addrlen); p += addr->ai_addrlen; ctx->p = p; } else #endif // WIN32 { struct socket_server_opensocket_noserver_s* alt = (struct socket_server_opensocket_noserver_s*)ctx; alt->sockfd = socket(addr->ai_family, sock_type, 0); // fcntl(alt->sockfd, F_SETFD, FD_CLOEXEC); alt->error = (alt->sockfd >= 0)?0:ERRNO_ERROR; alt->family = sock_type; alt->addr = *addr; memcpy(&alt->ss, addr->ai_addr, addr->ai_addrlen); alt->addr.ai_addr = &alt->ss.sa; } return SUCCESS; } void socket_server_opensocket_setopt(socket_server_opensocket_s *ctx, int level, int optname, const void* opt, socklen_t optlen) { #if __unix__ if(socket_server_pid != 0) { u8 *p = ctx->p; assert((size_t)(&ctx->buffer_out[sizeof(ctx->buffer_out)] - p) >= (sizeof(u32) + sizeof(u32) + sizeof(u32) + optlen)); ++ctx->buffer_out[1]; SET_U32_AT_P(p, SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_ERROR); // operation is mandatory p += sizeof(u32); SET_U32_AT_P(p, level); p += sizeof(u32); SET_U32_AT_P(p, optname); p += sizeof(u32); SET_U32_AT_P(p, optlen); p += sizeof(u32); memcpy(p, opt, optlen); p += optlen; ctx->p = p; } else #endif { struct socket_server_opensocket_noserver_s* alt = (struct socket_server_opensocket_noserver_s*)ctx; if(ISOK(alt->error)) { if(setsockopt(alt->sockfd, level, optname, opt, optlen) < 0) { alt->error = ERRNO_ERROR; char level_buffer[32]; char optname_buffer[32]; socket_server_get_level_name(level, level_buffer, sizeof(level_buffer)); socket_server_get_optname_name(level, optname, optname_buffer, sizeof(optname_buffer)); log_err("socket-server: setsockopt: failed to setsockopt(%i, %s, %s, %p, %i): %r", alt->sockfd, level_buffer, optname_buffer, opt, optlen, alt->error); close_ex(alt->sockfd); alt->sockfd = -1; } } } } void socket_server_opensocket_setopt_ignore_result(socket_server_opensocket_s *ctx, int level, int optname, const void* opt, socklen_t optlen) { #if __unix__ if(socket_server_pid != 0) { u8 *p = ctx->p; assert((size_t)(&ctx->buffer_out[sizeof(ctx->buffer_out)] - p) >= (sizeof(u32) + sizeof(u32) + sizeof(u32) + optlen)); ++ctx->buffer_out[1]; SET_U32_AT_P(p, SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_IGNORE); // operation failure will only log a warning p += sizeof(u32); SET_U32_AT_P(p, level); p += sizeof(u32); SET_U32_AT_P(p, optname); p += sizeof(u32); SET_U32_AT_P(p, optlen); p += sizeof(u32); memcpy(p, opt, optlen); p += optlen; ctx->p = p; } else #endif { struct socket_server_opensocket_noserver_s* alt = (struct socket_server_opensocket_noserver_s*)ctx; if(ISOK(alt->error)) { if(setsockopt(alt->sockfd, level, optname, opt, optlen) < 0) { alt->error = ERRNO_ERROR; char level_buffer[32]; char optname_buffer[32]; socket_server_get_level_name(level, level_buffer, sizeof(level_buffer)); socket_server_get_optname_name(level, optname, optname_buffer, sizeof(optname_buffer)); log_warn("socket-server: setsockopt: failed to setsockopt(%i, %s, %s, %p, %i): %r", alt->sockfd, level_buffer, optname_buffer, opt, optlen, alt->error); } } } } void socket_server_opensocket_setopt_ignore_error(socket_server_opensocket_s *ctx, int level, int optname, const void* opt, socklen_t optlen) { #if __unix__ if(socket_server_pid != 0) { u8 *p = ctx->p; assert((size_t)(&ctx->buffer_out[sizeof(ctx->buffer_out)] - p) >= (sizeof(u32) + sizeof(u32) + sizeof(u32) + optlen)); ++ctx->buffer_out[1]; SET_U32_AT_P(p, SOCKET_SERVER_OPERATION_ERROR_BEHAVIOUR_WARNING); // operation failure will only log a warning p += sizeof(u32); SET_U32_AT_P(p, level); p += sizeof(u32); SET_U32_AT_P(p, optname); p += sizeof(u32); SET_U32_AT_P(p, optlen); p += sizeof(u32); memcpy(p, opt, optlen); p += optlen; ctx->p = p; } else #endif { struct socket_server_opensocket_noserver_s* alt = (struct socket_server_opensocket_noserver_s*)ctx; if(ISOK(alt->error)) { if(setsockopt(alt->sockfd, level, optname, opt, optlen) < 0) { alt->error = ERRNO_ERROR; char level_buffer[32]; char optname_buffer[32]; socket_server_get_level_name(level, level_buffer, sizeof(level_buffer)); socket_server_get_optname_name(level, optname, optname_buffer, sizeof(optname_buffer)); log_warn("socket-server: setsockopt: failed to setsockopt(%i, %s, %s, %p, %i): %r", alt->sockfd, level_buffer, optname_buffer, opt, optlen, alt->error); } } } } /** * Opens the socket and returns its file descriptor or an error code. * * @param ctx * * @return the file descriptor or an error code */ int socket_server_opensocket_open(socket_server_opensocket_s *ctx) { #if __unix__ if(socket_server_pid != 0) // the socket server is up { group_mutex_lock(&socket_server_mtx, GROUP_MUTEX_WRITE); ctx->buffer_out[0] = ctx->p - &ctx->buffer_out[1]; ssize_t written = writefully(socket_server_pipe[1], ctx->buffer_out, ctx->p - ctx->buffer_out); if(ISOK(written)) { #if DEBUG log_info("socket_server_opensocket_open(%i) = %lli", socket_server_pipe[1], written); #endif } else { ya_result ret = (ya_result)written; group_mutex_unlock(&socket_server_mtx, GROUP_MUTEX_WRITE); log_err("socket_server_opensocket_open(%i) = %r", socket_server_pipe[1], ret); return ret; } int sockfd = -2; ya_result ret = socket_server_recv(socket_server_sock[0], &sockfd); group_mutex_unlock(&socket_server_mtx, GROUP_MUTEX_WRITE); if(ISOK(ret)) { #if DEBUG log_info("socket_server_opensocket_open(%i, *%p = %i) = %i", socket_server_sock[0], &sockfd, sockfd, ret); #endif ret = sockfd; } else { log_err("socket_server_opensocket_open(%i, *%p = %i) = %r", socket_server_sock[0], &sockfd, sockfd, ret); } return ret; } else #endif // WIN32 { struct socket_server_opensocket_noserver_s* alt = (struct socket_server_opensocket_noserver_s*)ctx; ya_result ret = alt->error; if(ISOK(ret)) { if(bind(alt->sockfd, alt->addr.ai_addr, alt->addr.ai_addrlen) >= 0) { ret = alt->sockfd; #if DEBUG log_info("socket_server_opensocket_open(*%p = %i) = %i", &alt->sockfd, alt->sockfd, ret); #endif } else { alt->error = ERRNO_ERROR; close_ex(alt->sockfd); alt->sockfd = -1; ret = alt->error; log_err("socket_server_opensocket_open(*%p = %i) = %i", &alt->sockfd, alt->sockfd, alt->error); } } return ret; } } ya_result socket_server_finalize() { #if __unix__ if(socket_server_pid != 0) { // send stop command socket_server_close_fds(); // kill(socket_server_pid, SIGTERM); // forget socket_server_pid = 0; return SUCCESS; } return ERROR; #else // WIN32 return SUCCESS; #endif } ya_result socket_server_init(int argc, char **argv) { log_info("socket-server: init"); #if __unix__ if(socket_server_parent_pid != 0) { log_err("socket-server: already initialised"); return ERROR; } if(getuid() != 0) { #if DEBUG printf("warning: socket server can only serve privileged ports if the uid is 0\n"); #endif } if(socket_server_pid != 0) { log_warn("socket-server: socket server appears to be already running"); return ERROR; // black magic already running } if(pipe(socket_server_pipe) < 0) { ya_result ret = ERRNO_ERROR; log_err("socket-server: could not create pipe: %r", ret); return ret; // could not create ipc } fd_setcloseonexec(socket_server_pipe[0]); fd_setcloseonexec(socket_server_pipe[1]); if(socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_server_sock) < 0) { ya_result ret = ERRNO_ERROR; log_err("socket-server: failed to create socketpair: %r", ret); socket_server_close_fds(); return ret; } fd_setcloseonexec(socket_server_sock[0]); fd_setcloseonexec(socket_server_sock[1]); if(pipe(socket_server_wire) < 0) { ya_result ret = ERRNO_ERROR; log_err("socket-server: could not create pipe: %r", ret); socket_server_close_fds(); return ret; // could not create wire pipe } socket_server_parent_pid = getpid(); socket_server_parent_uid = getuid(); pid_t pid = fork_ex(); if(pid < 0) { ya_result ret = ERRNO_ERROR; log_err("socket-server: could not fork: %r", ret); socket_server_close_fds(); socket_server_parent_pid = 0; return ret; // could not fork } if(pid == 0) { FILE *f; //MODULE_MSG_HANDLE = LOGGER_HANDLE_SINK; socket_server_pipe[1] = -1; f = freopen("/dev/null", "r", stdin); if(f == NULL) { exit(EXIT_FAILURE); } #if !DEBUG f = freopen("/dev/null", "a", stdout); if(f == NULL) { exit(EXIT_FAILURE); } f = freopen("/dev/null", "a", stderr); if(f == NULL) { exit(EXIT_FAILURE); } #else f = freopen("/tmp/yadifa-socket-server.out", "a", stdout); if(f == NULL) { if((/*f = */freopen("/dev/null", "a", stdout)) == NULL) { exit(EXIT_FAILURE); } } f = freopen("/tmp/yadifa-socket-server.err", "a", stderr); if(f == NULL) { if((/*f = */freopen("/dev/null", "a", stderr)) == NULL) { exit(EXIT_FAILURE); } } #if __FreeBSD__ fprintf(stdout, "FreeBSD: stdout reopened (%i)\n", getpid_ex()); fprintf(stderr, "FreeBSD: stderr reopened (%i)\n", getpid_ex()); fflush(NULL); #endif #endif socket_server_close_fd(&socket_server_pipe[1]); socket_server_close_fd(&socket_server_sock[0]); socket_server_close_fd(&socket_server_wire[0]); signal(SIGPIPE, SIG_DFL); #if HAS_PR_SET_PDEATHSIG // linux-only code that avoids the need for polling prctl(PR_SET_PDEATHSIG, SIGINT); #endif if((argc > 0) && (argv != NULL)) { // replace the program name size_t argv0_len = strlen(argv[0]); // returns the size of the storage of the string, minus 1. strncpy(argv[0], "network", argv0_len); // not strncpy in this case // erase all parameters for(int i = 1; i < argc; ++i) { memset(argv[i], 0, strlen(argv[i])); } } socket_server_server(); // NEVER REACHED abort(); // should never be called } else { socket_server_close_fd(&socket_server_pipe[0]); socket_server_close_fd(&socket_server_sock[1]); socket_server_close_fd(&socket_server_wire[1]); socket_server_pid = pid; socket_server_pipe[0] = -1; } #else // WIN32 #endif return 1; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/string_set.c0000644000000000000000000000013214505005532021655 xustar000000000000000030 mtime=1695812442.399981572 30 atime=1695812445.792030153 30 ctime=1695812494.700730624 yadifa-2.6.5-11201/lib/dnscore/src/string_set.c0000664000374500037450000001216114505005532021620 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A dictionary C-string => u16 based on the AVL code. * * A dictionary C-string => u16 based on the AVL code. * Mostly used for name => dns type or name => dns class * * @{ *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #define _STRING_SET_C #define DEBUG_LEVEL 0 #include "dnscore/dnscore.h" #include "dnscore/string_set.h" #include "dnscore/zalloc.h" #define STRNGSET_TAG 0x544553474e525453 /* * The following macros are defining relevant fields in the node */ static int strcompare(const char *a, const char *b) { return strcmp(a, b); } /* * Access to the field that points to the left child */ #define AVL_LEFT_CHILD(node) ((node)->children.lr.left) /* * Access to the field that points to the right child */ #define AVL_RIGHT_CHILD(node) ((node)->children.lr.right) /* * Access to the field that points to one of the children (0: left, 1: right) */ #define AVL_CHILD(node,id) ((node)->children.child[(id)]) /* * Access to the field that keeps the balance (a signed byte) */ #define AVL_BALANCE(node) ((node)->balance) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE const char* #define AVL_REFERENCE_IS_CONST TRUE /* * */ #define AVL_REFERENCE_FORMAT_STRING '%s' #define AVL_REFERENCE_FORMAT(reference) reference /* * A macro to initialize a node and setting the reference */ #define AVL_INIT_NODE(node__,reference__) (node__)->key = (reference__);(node__)->value = 0; #if 0 /* fix */ #else /* * A macro to allocate a new node */ #define AVL_ALLOC_NODE(node__,reference__) ZALLOC_OBJECT_OR_DIE(node__,AVL_NODE_TYPE, STRNGSET_TAG); /* * A macro to free a node allocated by ALLOC_NODE */ #define AVL_FREE_NODE(node__) ZFREE(node__,AVL_NODE_TYPE) #endif /* * A macro to print the node */ #define AVL_DUMP_NODE(node__) format("node@%p",(node__)); /* * A macro that returns the reference field of the node. * It must be of type REFERENCE_TYPE */ #define AVL_REFERENCE(node__) (node__)->key #define AVL_TERNARYCMP 1 #if !AVL_TERNARYCMP /* * A macro to compare two references * Returns TRUE if and only if the references are equal. */ #define AVL_ISEQUAL(reference_a,reference_b) (strcompare(reference_a,reference_b)==0) /* * A macro to compare two references * Returns TRUE if and only if the first one is bigger than the second one. */ #define AVL_ISBIGGER(reference_a,reference_b) (strcompare(reference_a,reference_b)>0) #else #define AVL_COMPARE(reference_a,reference_b) (strcompare(reference_a,reference_b)) #endif /* * Copies the payload of a node * It MUST NOT copy the "proprietary" node fields : children, parent, balance */ #define AVL_COPY_PAYLOAD(node_trg,node_src) (node_trg)->key=(node_src)->key;(node_trg)->value=(node_src)->value; /* * A macro to preprocess a node before it is preprocessed for a delete (detach) * If there was anything to do BEFORE deleting a node, we would do it here * After this macro is exectuted, the node * _ is detached, then deleted with FREE_NODE * _ has got its content overwritten by the one of another node, then the other * node is deleted with FREE_NODE */ #define AVL_NODE_DELETE_CALLBACK(node__) #include "dnscore/avl.c.inc" /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/sys_error.c0000644000000000000000000000013214505005532021523 xustar000000000000000030 mtime=1695812442.416981816 30 atime=1695812445.793030168 30 ctime=1695812494.702730653 yadifa-2.6.5-11201/lib/dnscore/src/sys_error.c0000664000374500037450000005020614505005532021470 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoreerror Error * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include #include #include "dnscore/dnscore-config.h" #include "dnscore/sys_types.h" #include "dnscore/sys_error.h" #include "dnscore/rfc.h" #include "dnscore/u32_set.h" #include "dnscore/output_stream.h" #include "dnscore/format.h" #include "dnscore/dnssec_errors.h" #include "dnscore/parser.h" #include "dnscore/config_settings.h" #include "dnscore/cmdline.h" #include "dnscore/zone_reader.h" #include "dnscore/zone_reader_text.h" extern logger_handle *g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #define ERRORTBL_TAG 0x4c4254524f525245 #define ERROR_TEXT_COPIED 0 /*----------------------------------------------------------------------------*/ void dief(ya_result error_code, const char* format, ...) { /** * @note Cannot use format here. The output call HAS to be from the standard library/system. */ fflush(NULL); fprintf(stderr, "critical error : %i %x '%s'\n", error_code, error_code, error_gettext(error_code)); fflush(NULL); va_list args; va_start(args, format); vfprintf(stderr, format, args); /* Keep native */ va_end(args); fflush(NULL); abort(); } static u32_node *error_set = NULL; void error_register(ya_result code, const char* const text) { if(text == NULL) { fprintf(stderr, "error_register(%08x, NULL): text cannot be NULL", code); fflush(stderr); } if(YA_ERROR_BASE(code) == ERRNO_ERROR_BASE) { fprintf(stderr, "error_register(%08x,%s): the errno space is reserved (0x8000xxxx), ignoring code", code, text); fflush(stderr); return; } u32_node *error_node; if((error_node = u32_set_find(&error_set, code)) == NULL) { error_node = u32_set_insert(&error_set, code); if(error_node->value == 0) { #if ERROR_TEXT_COPIED error_node->value = strdup(text); #else error_node->value = (void*)text; /// @note 20210427 edf -- it used to be strdup(text), but the parameter is supposed to be a constant string. #endif } } else { fprintf(stderr, "\nerror_register(%08x,%s): duplicate key, previous value = '%s'\n", code, text, (const char*)error_node->value); fflush(stderr); } } #if ERROR_TEXT_COPIED static void error_unregister_all_cb(u32_node *node) { free(node->value); } #endif void error_unregister_all() { #if ERROR_TEXT_COPIED u32_set_callback_and_destroy(&error_set, error_unregister_all_cb); #else u32_set_destroy(&error_set); #endif } static char error_gettext_tmp[64]; /** * * DEPRECATED * * @param code * @return */ const char* error_gettext(ya_result code) { /* errno handling */ if(code > 0) { snprintf(error_gettext_tmp, sizeof(error_gettext_tmp), "success (%08x)", code); return error_gettext_tmp; } if(YA_ERROR_BASE(code) == ERRNO_ERROR_BASE) { return strerror(YA_ERROR_CODE(code)); } /**/ u32_node *error_node; error_node = u32_set_find(&error_set, code); if(error_node != NULL) { return (const char*)error_node->value; } u32 error_base = YA_ERROR_BASE(code); error_node = u32_set_find(&error_set, error_base); if(error_node != NULL) { return (const char*)error_node->value; } snprintf(error_gettext_tmp, sizeof(error_gettext_tmp), "undefined error code %08x", code); return error_gettext_tmp; } /** * * Text representation of the error code * * @param os * @param code */ void error_writetext(output_stream *os, ya_result code) { /* errno handling */ if(code > 0) { osformat(os, "success (%08x)", code); return; } if(YA_ERROR_BASE(code) == ERRNO_ERROR_BASE) { code &= 0xffff; #if DEBUG if(code == EINTR) { osprint(os, " "); // whoopsie } #endif osprint(os, strerror(code)); return; } else if(YA_ERROR_BASE(code) == SSL_ERROR_BASE) { code &= 0xffff; char buffer[256]; ERR_error_string_n(code, buffer, sizeof(buffer)); osformat(os, "SSL error %i '%s'", code, buffer); return; } /**/ u32_node *error_node; error_node = u32_set_find(&error_set, code); if(error_node != NULL) { osprint(os, (const char*)error_node->value); return; } u32 error_base = YA_ERROR_BASE(code); error_node = u32_set_find(&error_set, error_base); if(error_node != NULL) { osformatln(os, "%s(%08x)", (const char*)error_node->value, code); return; } osformat(os, "undefined error code %08x", code); } static bool dnscore_register_errors_done = FALSE; void dnscore_register_errors() { if(dnscore_register_errors_done) { return; } dnscore_register_errors_done = TRUE; error_register(SUCCESS, "SUCCESS"); error_register(PARSEB16_ERROR, "PARSEB16_ERROR"); error_register(PARSEB32_ERROR, "PARSEB32_ERROR"); error_register(PARSEB32H_ERROR, "PARSEB32H_ERROR"); error_register(PARSEB64_ERROR, "PARSEB64_ERROR"); error_register(PARSEINT_ERROR, "PARSEINT_ERROR"); error_register(PARSEDATE_ERROR, "PARSEDATE_ERROR"); error_register(PARSEIP_ERROR, "PARSEIP_ERROR"); error_register(CIRCULAR_FILE_FULL, "CIRCULAR_FILE_FULL"); error_register(CIRCULAR_FILE_SHORT, "CIRCULAR_FILE_SHORT"); error_register(CIRCULAR_FILE_END, "CIRCULAR_FILE_FULL"); error_register(CIRCULAR_FILE_LIMIT_EXCEEDED, "CIRCULAR_FILE_LIMIT_EXCEEDED"); error_register(DATA_FORMAT_ERROR, "DATA_FORMAT_ERROR"); error_register(LOCK_FAILED, "LOCK_FAILED"); error_register(TCP_RATE_TOO_SLOW, "TCP_RATE_TOO_SLOW"); error_register(PARSEWORD_NOMATCH_ERROR, "PARSEWORD_NOMATCH_ERROR"); error_register(PARSESTRING_ERROR, "PARSESTRING_ERROR"); error_register(PARSE_BUFFER_TOO_SMALL_ERROR, "PARSE_BUFFER_TOO_SMALL_ERROR"); error_register(PARSE_INVALID_CHARACTER, "PARSE_INVALID_CHARACTER"); error_register(PARSE_INVALID_ARGUMENT, "PARSE_INVALID_ARGUMENT"); error_register(PARSE_EMPTY_ARGUMENT, "PARSE_EMPTY_ARGUMENT"); error_register(CONFIG_SECTION_CALLBACK_ALREADY_SET, "CONFIG_SECTION_CALLBACK_ALREADY_SET"); error_register(CONFIG_SECTION_CALLBACK_NOT_SET, "CONFIG_SECTION_CALLBACK_NOT_SET"); error_register(CONFIG_SECTION_CALLBACK_NOT_FOUND, "CONFIG_SECTION_CALLBACK_NOT_FOUND"); error_register(CONFIG_NOT_A_REGULAR_FILE, "CONFIG_NOT_A_REGULAR_FILE"); error_register(CONFIG_TOO_MANY_HOSTS, "CONFIG_TOO_MANY_HOSTS"); error_register(CONFIG_FQDN_NOT_ALLOWED, "CONFIG_FQDN_NOT_ALLOWED"); error_register(CONFIG_PORT_NOT_ALLOWED, "CONFIG_PORT_NOT_ALLOWED"); error_register(CONFIG_EXPECTED_VALID_PORT_VALUE, "CONFIG_EXPECTED_VALID_PORT_VALUE"); error_register(CONFIG_TSIG_NOT_ALLOWED, "CONFIG_TSIG_NOT_ALLOWED"); error_register(CONFIG_INTERNAL_ERROR, "CONFIG_INTERNAL_ERROR"); error_register(CONFIG_IPV4_NOT_ALLOWED, "CONFIG_IPV4_NOT_ALLOWED"); error_register(CONFIG_IPV6_NOT_ALLOWED, "CONFIG_IPV6_NOT_ALLOWED"); error_register(CONFIG_KEY_UNKNOWN, "CONFIG_KEY_UNKNOWN"); error_register(CONFIG_KEY_PARSE_ERROR, "CONFIG_KEY_PARSE_ERROR"); error_register(CONFIG_SECTION_ERROR, "CONFIG_SECTION_ERROR"); error_register(CONFIG_IS_BUSY, "CONFIG_IS_BUSY"); error_register(CONFIG_FILE_NOT_FOUND, "CONFIG_FILE_NOT_FOUND"); error_register(LOGGER_INITIALISATION_ERROR, "LOGGER_INITIALISATION_ERROR"); error_register(COMMAND_ARGUMENT_EXPECTED, "COMMAND_ARGUMENT_EXPECTED"); error_register(OBJECT_NOT_INITIALIZED, "OBJECT_NOT_INITIALIZED"); error_register(FORMAT_ALREADY_REGISTERED, "FORMAT_ALREADY_REGISTERED"); error_register(STOPPED_BY_APPLICATION_SHUTDOWN, "STOPPED_BY_APPLICATION_SHUTDOWN"); error_register(INVALID_STATE_ERROR, "INVALID_STATE_ERROR"); error_register(FEATURE_NOT_IMPLEMENTED_ERROR, "FEATURE_NOT_IMPLEMENTED_ERROR"); error_register(UNEXPECTED_NULL_ARGUMENT_ERROR, "UNEXPECTED_NULL_ARGUMENT_ERROR"); error_register(INVALID_ARGUMENT_ERROR, "INVALID_ARGUMENT_ERROR"); error_register(INVALID_PATH, "INVALID_PATH"); error_register(PID_LOCKED, "PID_LOCKED"); error_register(UNABLE_TO_COMPLETE_FULL_READ, "UNABLE_TO_COMPLETE_FULL_READ"); error_register(UNEXPECTED_EOF, "UNEXPECTED_EOF"); error_register(UNSUPPORTED_TYPE, "UNSUPPORTED_TYPE"); error_register(UNSUPPORTED_CLASS, "UNSUPPORTED_CLASS"); error_register(CANNOT_OPEN_FILE, "CANNOT_OPEN_FILE"); error_register(UNKNOWN_NAME, "UNKNOWN_NAME"); error_register(BIGGER_THAN_PATH_MAX, "BIGGER_THAN_PATH_MAX"); error_register(UNABLE_TO_COMPLETE_FULL_WRITE, "UNABLE_TO_COMPLETE_FULL_WRITE"); error_register(BUFFER_WOULD_OVERFLOW, "BUFFER_WOULD_OVERFLOW"); error_register(CHROOT_NOT_A_DIRECTORY, "CHROOT_NOT_A_DIRECTORY"); error_register(CHROOT_ALREADY_JAILED, "CHROOT_ALREADY_JAILED"); error_register(IP_VERSION_NOT_SUPPORTED, "IP_VERSION_NOT_SUPPORTED"); error_register(THREAD_CREATION_ERROR, "THREAD_CREATION_ERROR"); error_register(THREAD_DOUBLEDESTRUCTION_ERROR, "THREAD_DOUBLEDESTRUCTION_ERROR"); error_register(SERVICE_ID_ERROR, "SERVICE_ID_ERROR"); error_register(SERVICE_WITHOUT_ENTRY_POINT, "SERVICE_WITHOUT_ENTRY_POINT"); error_register(SERVICE_ALREADY_INITIALISED, "SERVICE_ALREADY_INITIALISED"); error_register(SERVICE_ALREADY_RUNNING, "SERVICE_ALREADY_RUNNING"); error_register(SERVICE_NOT_RUNNING, "SERVICE_NOT_RUNNING"); error_register(SERVICE_NOT_INITIALISED, "SERVICE_NOT_INITIALISED"); error_register(SERVICE_HAS_RUNNING_THREADS, "SERVICE_HAS_RUNNING_THREADS"); error_register(TSIG_DUPLICATE_REGISTRATION, "TSIG_DUPLICATE_REGISTRATION"); error_register(TSIG_UNABLE_TO_SIGN, "TSIG_UNABLE_TO_SIGN"); error_register(NET_UNABLE_TO_RESOLVE_HOST, "NET_UNABLE_TO_RESOLVE_HOST"); error_register(CHARON_ERROR_FILE_LOCKED, "CHARON_ERROR_FILE_LOCKED"); error_register(CHARON_ERROR_NOT_AUTHORISED, "CHARON_ERROR_NOT_AUTHORISED"); error_register(CHARON_ERROR_UNKNOWN_ID, "CHARON_ERROR_UNKNOWN_ID"); error_register(CHARON_ERROR_EXPECTED_MAGIC_HEAD, "CHARON_ERROR_EXPECTED_MAGIC_HEAD"); error_register(CHARON_ERROR_INVALID_HEAD, "CHARON_ERROR_INVALID_HEAD"); error_register(CHARON_ERROR_INVALID_TAIL, "CHARON_ERROR_INVALID_TAIL"); error_register(CHARON_ERROR_INVALID_COMMAND, "CHARON_ERROR_INVALID_COMMAND"); error_register(CHARON_ERROR_COMMAND_SEQ_MISMATCHED, "CHARON_ERROR_COMMAND_SEQ_MISMATCHED"); error_register(CHARON_ERROR_UNKNOWN_MAGIC, "CHARON_ERROR_UNKNOWN_MAGIC"); error_register(CHARON_ERROR_ALREADY_RUNNING, "CHARON_ERROR_ALREADY_RUNNING"); error_register(CHARON_ERROR_ALREADY_STOPPED, "CHARON_ERROR_ALREADY_STOPPED"); error_register(LOGGER_CHANNEL_ALREADY_REGISTERED, "LOGGER_CHANNEL_ALREADY_REGISTERED"); error_register(LOGGER_CHANNEL_NOT_REGISTERED, "LOGGER_CHANNEL_NOT_REGISTERED"); error_register(LOGGER_CHANNEL_HAS_LINKS, "LOGGER_CHANNEL_HAS_LINKS"); error_register(ALARM_REARM, "ALARM_REARM"); error_register(DNS_ERROR_BASE, "DNS_ERROR_BASE"); error_register(DOMAIN_TOO_LONG, "DOMAIN_TOO_LONG"); error_register(INCORRECT_IPADDRESS, "INCORRECT_IPADDRESS"); error_register(INCORRECT_RDATA, "INCORRECT_RDATA"); error_register(LABEL_TOO_LONG, "LABEL_TOO_LONG"); error_register(INVALID_CHARSET, "INVALID_CHARSET"); error_register(ZONEFILE_INVALID_TYPE, "ZONEFILE_INVALID_TYPE"); error_register(DOMAINNAME_INVALID, "DOMAINNAME_INVALID"); error_register(TSIG_FORMERR, "TSIG_FORMERR"); error_register(TSIG_SIZE_LIMIT_ERROR, "TSIG_SIZE_LIMIT_ERROR"); error_register(UNPROCESSABLE_MESSAGE, "UNPROCESSABLE_MESSAGE"); error_register(INVALID_PROTOCOL, "INVALID_PROTOCOL"); error_register(INVALID_RECORD, "INVALID_RECORD"); error_register(UNSUPPORTED_RECORD, "UNSUPPORTED_RECORD"); error_register(ZONE_ALREADY_UP_TO_DATE, "ZONE_ALREADY_UP_TO_DATE"); error_register(UNKNOWN_DNS_TYPE, "UNKNOWN_DNS_TYPE"); error_register(UNKNOWN_DNS_CLASS, "UNKNOWN_DNS_CLASS"); error_register(MESSAGE_HAS_WRONG_ID, "MESSAGE_HAS_WRONG_ID"); error_register(MESSAGE_IS_NOT_AN_ANSWER, "MESSAGE_IS_NOT_AN_ANSWER"); error_register(MESSAGE_UNEXPECTED_ANSWER_DOMAIN, "MESSAGE_UNEXPECTED_ANSWER_DOMAIN"); error_register(MESSAGE_UNEXPECTED_ANSWER_TYPE_CLASS, "MESSAGE_UNEXPECTED_ANSWER_TYPE_CLASS"); error_register(MESSAGE_CONTENT_OVERFLOW, "MESSAGE_CONTENT_OVERFLOW"); error_register(MESSAGE_TRUNCATED, "MESSAGE_TRUNCATED"); error_register(RRSIG_COVERED_TYPE_DIFFERS, "RRSIG_COVERED_TYPE_DIFFERS"); error_register(RRSIG_OUTPUT_DIGEST_SIZE_TOO_BIG, "RRSIG_OUTPUT_DIGEST_SIZE_TOO_BIG"); error_register(RRSIG_UNSUPPORTED_COVERED_TYPE, "RRSIG_UNSUPPORTED_COVERED_TYPE"); error_register(RRSIG_VERIFICATION_FAILED, "RRSIG_VERIFICATION_FAILED"); error_register(DNSSEC_ALGORITHM_UNKOWN, "DNSSEC_ALGORITHM_UNKOWN"); /* DNS */ error_register(RCODE_ERROR_CODE(RCODE_NOERROR), "NOERROR"); error_register(RCODE_ERROR_CODE(RCODE_FORMERR), "FORMERR"); error_register(RCODE_ERROR_CODE(RCODE_SERVFAIL), "SERVFAIL"); error_register(RCODE_ERROR_CODE(RCODE_NXDOMAIN), "NXDOMAIN"); error_register(RCODE_ERROR_CODE(RCODE_NOTIMP), "NOTIMP"); error_register(RCODE_ERROR_CODE(RCODE_REFUSED), "REFUSED"); error_register(RCODE_ERROR_CODE(RCODE_YXDOMAIN), "YXDOMAIN"); error_register(RCODE_ERROR_CODE(RCODE_YXRRSET), "YXRRSET"); error_register(RCODE_ERROR_CODE(RCODE_NXRRSET), "NXRRSET"); error_register(RCODE_ERROR_CODE(RCODE_NOTAUTH), "NOTAUTH"); error_register(RCODE_ERROR_CODE(RCODE_NOTZONE), "NOTZONE"); // error_register(RCODE_ERROR_CODE(RCODE_BADVERS), "BADVERS"); // collides with ... error_register(RCODE_ERROR_CODE(RCODE_BADSIG), "BADSIG"); error_register(RCODE_ERROR_CODE(RCODE_BADKEY), "BADKEY"); error_register(RCODE_ERROR_CODE(RCODE_BADTIME), "BADTIME"); error_register(RCODE_ERROR_CODE(RCODE_BADMODE), "BADMODE"); error_register(RCODE_ERROR_CODE(RCODE_BADNAME), "BADNAME"); error_register(RCODE_ERROR_CODE(RCODE_BADALG), "BADALG"); error_register(RCODE_ERROR_CODE(RCODE_BADTRUNC), "BADTRUNC"); error_register(DNSSEC_ERROR_BASE, "DNSSEC_ERROR_BASE"); error_register(DNSSEC_ERROR_NOENGINE, "DNSSEC_ERROR_NOENGINE"); error_register(DNSSEC_ERROR_INVALIDENGINE, "DNSSEC_ERROR_INVALIDENGINE"); error_register(DNSSEC_ERROR_CANTPOOLTHREAD, "DNSSEC_ERROR_CANTPOOLTHREAD"); error_register(DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM, "DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM"); error_register(DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM, "DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM"); error_register(DNSSEC_ERROR_FILE_FORMAT_VERSION, "DNSSEC_ERROR_FILE_FORMAT_VERSION"); error_register(DNSSEC_ERROR_EXPECTED_CLASS_IN, "DNSSEC_ERROR_EXPECTED_CLASS_IN"); error_register(DNSSEC_ERROR_EXPECTED_TYPE_DNSKEY, "DNSSEC_ERROR_EXPECTED_TYPE_DNSKEY"); error_register(DNSSEC_ERROR_DUPLICATEKEY, "DNSSEC_ERROR_DUPLICATEKEY"); error_register(DNSSEC_ERROR_INCOMPLETEKEY, "DNSSEC_ERROR_INCOMPLETEKEY"); error_register(DNSSEC_ERROR_KEYSTOREPATHISTOOLONG, "DNSSEC_ERROR_KEYSTOREPATHISTOOLONG"); error_register(DNSSEC_ERROR_UNABLETOCREATEKEYFILES, "DNSSEC_ERROR_UNABLETOCREATEKEYFILES"); error_register(DNSSEC_ERROR_KEYWRITEERROR, "DNSSEC_ERROR_KEYWRITEERROR"); error_register(DNSSEC_ERROR_BNISNULL, "DNSSEC_ERROR_BNISNULL"); error_register(DNSSEC_ERROR_BNISBIGGERTHANBUFFER, "DNSSEC_ERROR_BNISBIGGERTHANBUFFER"); error_register(DNSSEC_ERROR_UNEXPECTEDKEYSIZE, "DNSSEC_ERROR_UNEXPECTEDKEYSIZE"); error_register(DNSSEC_ERROR_KEYISTOOBIG, "DNSSEC_ERROR_KEYISTOOBIG"); error_register(DNSSEC_ERROR_KEYRING_ALGOTAG_COLLISION, "DNSSEC_ERROR_KEYRING_ALGOTAG_COLLISION"); error_register(DNSSEC_ERROR_KEYRING_KEY_IS_NOT_PRIVATE,"DNSSEC_ERROR_KEYRING_KEY_IS_NOT_PRIVATE"); error_register(DNSSEC_ERROR_KEY_GENERATION_FAILED, "DNSSEC_ERROR_KEY_GENERATION_FAILED"); error_register(DNSSEC_ERROR_NO_KEY_FOR_DOMAIN, "DNSSEC_ERROR_NO_KEY_FOR_DOMAIN"); error_register(DNSSEC_ERROR_CANNOT_WRITE_NEW_FILE, "DNSSEC_ERROR_CANNOT_WRITE_NEW_FILE"); error_register(DNSSEC_ERROR_FIELD_NOT_HANDLED, "DNSSEC_ERROR_FIELD_NOT_HANDLED"); error_register(DNSSEC_ERROR_CANNOT_READ_KEY_FROM_RDATA, "DNSSEC_ERROR_CANNOT_READ_KEY_FROM_RDATA"); error_register(DNSSEC_ERROR_RSASIGNATUREFAILED, "DNSSEC_ERROR_RSASIGNATUREFAILED"); error_register(DNSSEC_ERROR_DSASIGNATUREFAILED, "DNSSEC_ERROR_DSASIGNATUREFAILED"); error_register(DNSSEC_ERROR_NSEC3_INVALIDZONESTATE, "DNSSEC_ERROR_NSEC3_INVALIDZONESTATE"); error_register(DNSSEC_ERROR_NSEC3_LABELTODIGESTFAILED, "DNSSEC_ERROR_NSEC3_LABELTODIGESTFAILED"); error_register(DNSSEC_ERROR_NSEC3_DIGESTORIGINOVERFLOW, "DNSSEC_ERROR_NSEC3_DIGESTORIGINOVERFLOW"); error_register(DNSSEC_ERROR_NSEC3_LABELNOTFOUND, "DNSSEC_ERROR_NSEC3_LABELNOTFOUND"); error_register(DNSSEC_ERROR_NSEC_INVALIDZONESTATE, "DNSSEC_ERROR_NSEC_INVALIDZONESTATE"); error_register(DNSSEC_ERROR_RRSIG_NOENGINE, "DNSSEC_ERROR_RRSIG_NOENGINE"); error_register(DNSSEC_ERROR_RRSIG_NOZONEKEYS, "DNSSEC_ERROR_RRSIG_NOZONEKEYS"); error_register(DNSSEC_ERROR_RRSIG_NOUSABLEKEYS, "DNSSEC_ERROR_RRSIG_NOUSABLEKEYS"); error_register(DNSSEC_ERROR_RRSIG_NOSOA, "DNSSEC_ERROR_RRSIG_NOSOA"); error_register(DNSSEC_ERROR_RRSIG_NOSIGNINGKEY, "DNSSEC_ERROR_RRSIG_NOSIGNINGKEY"); error_register(DNSSEC_ERROR_RRSIG_UNSUPPORTEDRECORD, "DNSSEC_ERROR_RRSIG_UNSUPPORTEDRECORD"); error_register(ZALLOC_ERROR_MMAPFAILED, "ZALLOC_ERROR_MMAPFAILED"); error_register(ZALLOC_ERROR_OUTOFMEMORY, "ZALLOC_ERROR_OUTOFMEMORY"); zone_reader_text_init_error_codes(); parser_init_error_codes(); config_init_error_codes(); cmdline_init_error_codes(); } ya_result ya_ssl_error() { unsigned long ssl_err = ERR_get_error(); if(ssl_err != 0) { LOGGER_EARLY_CULL_PREFIX(MSG_ERR) { char buffer[256]; ERR_error_string_n(ssl_err, buffer, sizeof(buffer)); log_err("ssl: %i, %s", ssl_err, buffer); unsigned long next_ssl_err; while((next_ssl_err = ERR_get_error()) != 0) { ERR_error_string_n(next_ssl_err, buffer, sizeof(buffer)); log_err("ssl: %i, %s", next_ssl_err, buffer); } ERR_clear_error(); } } return SSL_ERROR_CODE(ssl_err); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/sys_get_cpu_count.c0000644000000000000000000000013214505005532023230 xustar000000000000000030 mtime=1695812442.474982646 30 atime=1695812445.795030196 30 ctime=1695812494.704730682 yadifa-2.6.5-11201/lib/dnscore/src/sys_get_cpu_count.c0000664000374500037450000000646514505005532023205 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup cpu CPU * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include "dnscore/dnscore-config-features.h" #include #include #include #if defined(__linux__) && HAVE_CPUID_H #include #endif #include "dnscore/sys_types.h" /* * */ static u32 cpu_count_override = 0; void sys_set_cpu_count(int override) { if(override < 0) { override = 0; } cpu_count_override = (u32)override; } u32 sys_get_cpu_count() { if(cpu_count_override == 0) { #if __unix__ int cc = sysconf(_SC_NPROCESSORS_ONLN); if( cc <= 0 ) { /* * This fix has been made for FreeBSD that returns -1 for the above call */ cc = 1; } return (u32)cc; #else SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); DWORD cc = sysinfo.dwNumberOfProcessors; if(cc <= 0) { /* * This fix has been made for FreeBSD that returns -1 for the above call */ cc = 1; } return (u32)cc; #endif } return cpu_count_override; } bool sys_has_hyperthreading() { #if defined(__linux__) && HAVE_CPUID_H unsigned int a,c,d,b; int ret = __get_cpuid(1,&a,&b,&c,&d); if(ret == 1) { return (d & (1<<28)) != 0; } #endif return FALSE; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/tcp_io_stream.c0000644000000000000000000000013114505005532022323 xustar000000000000000030 mtime=1695812442.418981844 30 atime=1695812445.793030168 29 ctime=1695812494.70673071 yadifa-2.6.5-11201/lib/dnscore/src/tcp_io_stream.c0000664000374500037450000003114714505005532022274 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup streaming Streams * @ingroup dnscore * @brief * * @{ */ #include "dnscore/dnscore-config.h" #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #include #include "dnscore/tcp_io_stream.h" #include "dnscore/fdtools.h" #include "dnscore/parsing.h" #include "dnscore/format.h" #include "dnscore/timems.h" #define DNSCORE_TCP_FLAGS "DNSCORE_TCP_FLAGS" // nodelay,delay,cork,nocork static bool tcp_nodelay = TRUE; static bool tcp_cork = FALSE; /* * AF_INET * AF_INET6 * AF_UNSPEC ( = 0) */ /** * * Resolves the host address * * @param host * @param port * @param sa * @param familly * @return */ ya_result gethostaddr(const char* host, u16 port, struct sockaddr *sa, int familly) { /* ------------------------------------------------------------ */ /* Create a network address structure * from the dotted-quad format ddd.ddd.ddd.ddd into a in_addr_t */ /* If not forced in ipv6 then ... */ struct addrinfo hints; struct addrinfo *info; struct addrinfo *next; int eai_err; ZEROMEMORY(&hints, sizeof(struct addrinfo)); hints.ai_family = familly; ZEROMEMORY(sa, sizeof(struct sockaddr)); // valid use of sizeof(struct sockaddr) /* ------------------------------------------------------------ */ if((eai_err = getaddrinfo(host, NULL, &hints, &info)) != 0) { return EAI_ERROR_CODE(eai_err); // NET_UNABLE_TO_RESOLVE_HOST } next = info; while(next != NULL) { if((familly != AF_INET6) && (next->ai_family == AF_INET)) /* Only process IPv4 addresses */ { struct sockaddr_in *sai = (struct sockaddr_in *)sa; memcpy(sai, next->ai_addr, next->ai_addrlen); sai->sin_port = htons(port); #if HAS_SOCKADDR_IN_SIN_LEN sai->sin_len = sizeof(struct sockaddr_in); #endif break; } if((familly != AF_INET) && (next->ai_family == AF_INET6)) /* Only process IPv4 addresses */ { struct sockaddr_in6 *sai6 = (struct sockaddr_in6 *)sa; memcpy(sai6, next->ai_addr, next->ai_addrlen); sai6->sin6_port = htons(port); #if HAS_SOCKADDR_IN6_SIN6_LEN sai6->sin6_len = sizeof(struct sockaddr_in6); #endif break; } next = next->ai_next; } freeaddrinfo(info); if(next == NULL) /* nothing found for AF_INET */ { return NET_UNABLE_TO_RESOLVE_HOST; } return SUCCESS; } ya_result tcp_input_output_stream_connect_sockaddr(const struct sockaddr *sa, input_stream *istream_, output_stream *ostream_, struct sockaddr *bind_from, u8 to_sec) { int fd; while((fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) { int err = errno; if(err != EINTR) { return MAKE_ERRNO_ERROR(err); // scan-build does not understand this make the value signed } } fd_setcloseonexec(fd); /* * Bind the socket if required. */ if(bind_from != NULL) { s64 try_until = (to_sec > 0)?timeus() + (ONE_SECOND_US * to_sec):MAX_S64; while((bind(fd, bind_from, sizeof(socketaddress))) < 0) { int err = errno; if(err == EINTR) { continue; } if(err == EADDRNOTAVAIL) { if(try_until >= timeus()) { close_ex(fd); return MAKE_ERRNO_ERROR(err); } else { continue; } } close_ex(fd); return MAKE_ERRNO_ERROR(err); } } int ssec, susec, rsec, rusec; tcp_get_sendtimeout(fd, &ssec, &susec); tcp_get_recvtimeout(fd, &rsec, &rusec); tcp_set_sendtimeout(fd, to_sec, 0); tcp_set_recvtimeout(fd, to_sec, 0); tcp_set_nodelay(fd, tcp_nodelay); tcp_set_cork(fd, tcp_cork); #if HAS_SOCKADDR_SA_LEN while(connect(fd, sa, sa->sa_len) < 0) #else while(connect(fd, sa, sizeof(socketaddress)) < 0) #endif { int err = errno; if(err != EINTR) { close_ex(fd); // note: EADDRNOTAVAIL here basically means the network is overloaded // Linux quirk if(err == EINPROGRESS) { err = ETIMEDOUT; } return MAKE_ERRNO_ERROR(err); } } /* can only fail if fd < 0, which is never the case here */ fd_input_stream_attach(istream_, fd); fd_output_stream_attach_noclose(ostream_, fd); tcp_set_sendtimeout(fd, ssec, susec); tcp_set_recvtimeout(fd, rsec, rusec); return fd; } ya_result tcp_input_output_stream_connect_ex(const char *server, u16 port, input_stream *istream_, output_stream *ostream_, struct sockaddr *bind_from, u8 to_sec) { ya_result return_code; socketaddress sa; /* * If the client interface is specified, then use its family. * Else use the unspecified familly to let the algorithm choose the first available one. */ int family = (bind_from != NULL) ? bind_from->sa_family : AF_UNSPEC; if(ISOK(return_code = gethostaddr(server, port, &sa.sa, family))) { return_code = tcp_input_output_stream_connect_sockaddr(&sa.sa, istream_, ostream_, bind_from, to_sec); } return return_code; } ya_result tcp_input_output_stream_connect(const char *server, u16 port, input_stream *istream, output_stream *ostream) { return tcp_input_output_stream_connect_ex(server, port, istream, ostream, NULL, 0); } ya_result tcp_input_output_stream_connect_host_address(const host_address *ha, input_stream *istream_, output_stream *ostream_, u8 to_sec) { socketaddress sa; ya_result return_code; if(ISOK(return_code = host_address2sockaddr(ha, &sa))) { return_code = tcp_input_output_stream_connect_sockaddr(&sa.sa, istream_, ostream_, NULL, to_sec); } return return_code; } ya_result tcp_input_output_stream_connect_host_address_ex(const host_address *ha, input_stream *istream_, output_stream *ostream_, const host_address *bind_to, u8 to_sec) { socketaddress sa; socketaddress bind_sa; ya_result return_code; if(ISOK(return_code = host_address2sockaddr(ha, &sa))) { if(ISOK(return_code = host_address2sockaddr(bind_to, &bind_sa))) { return_code = tcp_input_output_stream_connect_sockaddr(&sa.sa, istream_, ostream_, &bind_sa.sa, to_sec); } } return return_code; } ya_result tcp_io_stream_connect_ex(const char *server, u16 port, io_stream *ios, struct sockaddr *bind_from) { input_stream istream; output_stream ostream; #if DEBUG input_stream_set_void(&istream); // this should shut-up a false-positive from scan-build output_stream_set_void(&ostream); #endif ya_result return_code; if(ISOK(return_code = tcp_input_output_stream_connect_ex(server, port, &istream, &ostream, bind_from, 0))) { io_stream_link(ios, &istream, &ostream); } return return_code; } ya_result tcp_io_stream_connect(const char *server, u16 port, io_stream *ios) { return tcp_io_stream_connect_ex(server, port, ios, NULL); } void tcp_set_linger(int fd, bool enable, int seconds) { struct linger l; l.l_onoff = (enable)?1:0; l.l_linger = seconds; setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); } /** * Nagle * * @param fd * @param enable */ void tcp_set_nodelay(int fd, bool enable) { int flag = (enable)?1:0; setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag) ); } #if defined(__linux__) /** * @param fd * @param enable */ void tcp_set_cork(int fd, bool enable) { int flag = (enable)?1:0; setsockopt(fd, IPPROTO_TCP, TCP_CORK, &flag, sizeof(flag) ); } #elif defined(__FreeBSD__) /** * @param fd * @param enable */ //#error THIS NEEDS TO BE TESTED ON BSD (This error message is to remind you that) void tcp_set_cork(int fd, bool enable) { int flag = (enable)?1:0; setsockopt(fd, IPPROTO_TCP, TCP_NOPUSH, &flag, sizeof(flag) ); } #else void tcp_set_cork(int fd, bool enable) { /** * Cork/NoPush have been documented as Linux/FreeBSD specifics */ } #endif void tcp_set_sendtimeout(int fd, int seconds, int useconds) { struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = useconds; setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); } void tcp_set_recvtimeout(int fd, int seconds, int useconds) { struct timeval tv; tv.tv_sec = seconds; tv.tv_usec = useconds; setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); } void tcp_get_sendtimeout(int fd, int *seconds, int *useconds) { struct timeval tv; socklen_t tv_len = sizeof(tv); getsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, &tv_len); *seconds = tv.tv_sec; *useconds = tv.tv_usec; } void tcp_get_recvtimeout(int fd, int *seconds, int *useconds) { struct timeval tv; socklen_t tv_len = sizeof(tv); getsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &tv_len); *seconds = tv.tv_sec; *useconds = tv.tv_usec; } static const char* tcp_env_keywords[4] = { "nodelay", "delay", "cork", "nocork" }; void tcp_init_with_env() { char tmp[256]; const char* tcp_flags_cfg = getenv(DNSCORE_TCP_FLAGS); if(tcp_flags_cfg != NULL) { strcpy_ex(tmp, tcp_flags_cfg, sizeof(tmp)-1); tmp[sizeof(tmp) - 1] = '\0'; size_t tmp_len = strlen(tmp); for(size_t i = 0; i < tmp_len; i++) { if(tmp[i] == ',') { tmp[i] = ' '; } } const char *p = parse_skip_spaces(tmp); while(*p != '\0') { s32 keyword = -1; s32 word_len = parse_skip_word_specific(p, strlen(p), tcp_env_keywords, 4, &keyword); if(FAIL(word_len)) { break; } switch(keyword) { case 0: // nodelay tcp_nodelay = TRUE; break; case 1: // delay tcp_nodelay = FALSE; break; case 2: // cork tcp_cork = TRUE; break; case 3: // nocork tcp_cork = FALSE; break; default: osformatln(termerr, "syntax error in env %s", DNSCORE_TCP_FLAGS); flusherr(); break; } p += word_len; p = parse_skip_spaces(p); } } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/thread.c0000644000000000000000000000013214505005532020743 xustar000000000000000030 mtime=1695812442.424981931 30 atime=1695812445.793030168 30 ctime=1695812494.708730739 yadifa-2.6.5-11201/lib/dnscore/src/thread.c0000664000374500037450000001323314505005532020707 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #if HAS_PTHREAD_SETNAME_NP #define _GNU_SOURCE 1 #endif #include #include #include #include "dnscore/logger.h" #define MODULE_MSG_HANDLE g_system_logger #define PTHCWRAP_TAG 0x5041525743485450 #if HAS_PTHREAD_SETNAME_NP static int thread_count_get_nibbles(u32 count) { int ret = 0; do { ++ret; count >>= 4; } while(count > 0); return ret; } void thread_set_name(const char *name, int index, int count) { // 16 is the size limit for this, cfr man page char tmp[16 + 1]; char fmt[11]; // :%010x/%010x if(--count <= 0) { strcpy_ex(tmp, name, sizeof(tmp)); } else { int count_digits = thread_count_get_nibbles((u32) count); if(count_digits < 5) { // name:xx/xx int suffix_len = count_digits * 2 + 2; int avail = sizeof(tmp) - 1 - suffix_len; strcpy_ex(tmp, name, avail); int size = strlen(tmp); snformat(fmt, sizeof(fmt), ":%%0%ix/%%0%ix", count_digits, count_digits); // 11 bytes long as count_digits is at most 4 so 1 byte long snprintf(&tmp[size], sizeof(tmp) - size, fmt, index, count); } else { //name:xx assert(count_digits <= 8); int suffix_len = count_digits + 1; int avail = sizeof(tmp) - 1 - suffix_len; strcpy_ex(tmp, name, avail); int size = strlen(tmp); snformat(fmt, sizeof(fmt), ":%%0%ix", count_digits); // 6 bytes as count_digits is at most 8 so 1 byte long snprintf(&tmp[size], sizeof(tmp) - size, fmt, index, count); } } #if __APPLE__ pthread_setname_np(tmp); #elif __NetBSD__ pthread_setname_np(thread_self(), tmp, strlen(tmp)); #else pthread_setname_np(thread_self(), tmp); #endif // __APPLE__ } #else void thread_set_name(const char *name, int index, int count) { (void)name; (void)index; (void)count; } #endif #if DEBUG struct pthead_create_wrapper_s { void *(*function_thread)(void*); void *function_args; }; static void* pthead_create_wrapper(void* args_) { char name_buffer[32]; strcpy(name_buffer, "unnamed"); #if __linux__ pthread_getname_np(thread_self(), name_buffer, sizeof(name_buffer)); #endif struct pthead_create_wrapper_s *args = (struct pthead_create_wrapper_s*)args_; log_debug1("thread: %p (%i) started (%s)", (void*)pthread_self(), gettid(), name_buffer); struct pthead_create_wrapper_s targs = *args; free(args); void *thread_ret = targs.function_thread(targs.function_args); log_debug1("thread: %p (%i) stopped (%s) with %p", (void*)pthread_self(), gettid(), name_buffer, thread_ret); return thread_ret; } #endif ya_result thread_create(thread_t *t, void* (*function_thread)(void*), void *function_args) { int ret; #if !DEBUG ret = pthread_create(t, NULL, function_thread, function_args); #else // DEBUG struct pthead_create_wrapper_s *pthead_create_wrapper_args; MALLOC_OBJECT_OR_DIE(pthead_create_wrapper_args, struct pthead_create_wrapper_s, PTHCWRAP_TAG); pthead_create_wrapper_args->function_thread = function_thread; pthead_create_wrapper_args->function_args = function_args; ret = pthread_create(t, NULL, pthead_create_wrapper, pthead_create_wrapper_args); #endif if(ret != 0) { ret = MAKE_ERRNO_ERROR(ret); } return ret; } ya_result thread_kill(thread_t t, int signo) { #if __unix__ int ret = pthread_kill(t, signo); if(ret != 0) { ret = MAKE_ERRNO_ERROR(ret); } return ret; #else return ERROR; #endif } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/thread_pool.c0000644000000000000000000000013114505005532021773 xustar000000000000000030 mtime=1695812442.494982933 29 atime=1695812445.79603021 30 ctime=1695812494.711730782 yadifa-2.6.5-11201/lib/dnscore/src/thread_pool.c0000664000374500037450000011277014505005532021746 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #if HAS_PTHREAD_SETNAME_NP #if DEBUG #define _GNU_SOURCE 1 #endif #endif #include #include #include #include #define THREADED_QUEUE_MODE 6 #include "dnscore/threaded_queue.h" #include "dnscore/thread_pool.h" #include "dnscore/logger.h" #include "dnscore/format.h" #include "dnscore/u32_set.h" #include "dnscore/zalloc.h" #include "dnscore/process.h" #include "dnscore/mutex.h" // 0 = nothing, 1 = warns and worse, 2 = info and worse, 3 = debug and worse #define VERBOSE_THREAD_LOG 3 // Enabling this will slow down the starting and stopping parts of the threads, testing only #define THREADPOOL_DEBUG_SLOW_ARCH 0 // Disable when in release mode #if !DEBUG #undef VERBOSE_THREAD_LOG #define VERBOSE_THREAD_LOG 0 #endif #define MODULE_MSG_HANDLE g_system_logger #define THREADPOOL_TAG 0x4c4f4f5044524854 /* THRDPOOL */ #define THREADPOOL_QUEUE_SIZE_FACTOR 4096 /* 2 */ #define THREADPOOL_FLAG_PAUSED 1 typedef struct threaded_queue_task threaded_queue_task; struct threaded_queue_task { thread_pool_function* function; void* parm; thread_pool_task_counter *counter; const char* categoryname; /* so it's easy to know what thread is running*/ }; struct thread_descriptor_s { struct thread_pool_s *pool; // 8 thread_t id; // 8 u32 index; // 4 volatile u8 status; // 1 u8 reserved1; // 1 u16 reserved2; // 2 char info[16]; // 16 }; typedef struct thread_descriptor_s thread_descriptor_s; /* The array of thread descriptors*/ static thread_key_t thread_pool_random_key = ~0; static thread_once_t thread_pool_random_key_once = PTHREAD_ONCE_INIT; static thread_key_t thread_pool_thread_index_key = ~0; static thread_once_t thread_pool_thread_index_key_once = PTHREAD_ONCE_INIT; static mutex_t thread_pool_set_mutex = MUTEX_INITIALIZER; static u32_set thread_pool_set = U32_SET_EMPTY; static u32 thread_pool_id_next = 0; #if DEBUG static smp_int thread_pool_waiting = SMP_INT_INITIALIZER; static smp_int thread_pool_running = SMP_INT_INITIALIZER; #endif #define THRDPOOL_TAG 0x4c4f4f5044524854 struct thread_pool_s { mutex_t mtx; struct thread_descriptor_s **descriptors; threaded_queue queue; u32 thread_pool_size; u8 flags; #if DEBUG volatile u8 created; volatile u8 destroying; volatile u8 destroyed; #endif char *pool_name; u32 id; }; typedef struct thread_pool_s thread_pool_s; u32 g_max_thread_per_pool_limit = THREAD_POOL_SIZE_LIMIT_DEFAULT; #if THREADPOOL_DEBUG_SLOW_ARCH static void thread_pool_debug_slow_arch_wait() { s64 now = timeus(); s64 stop = now + 1000000 + (rand() & 0xfffff); // between about 1 to 2 seconds. do { s64 delta = stop - now; usleep(delta); now = timeus(); } while(now < stop); } #endif u32 thread_pool_get_max_thread_per_pool_limit() { return g_max_thread_per_pool_limit; } u32 thread_pool_set_max_thread_per_pool_limit(u32 max_thread_per_pool_limit) { if((max_thread_per_pool_limit >= THREAD_POOL_SIZE_LIMIT_MIN) && (max_thread_per_pool_limit <= THREAD_POOL_SIZE_LIMIT_MAX)) { g_max_thread_per_pool_limit = max_thread_per_pool_limit; } return g_max_thread_per_pool_limit; } void thread_pool_counter_init(thread_pool_task_counter *counter, s32 value) { mutex_init(&counter->mutex); cond_init(&counter->cond); counter->value = value; } void thread_pool_counter_destroy(thread_pool_task_counter *counter) { cond_finalize(&counter->cond); mutex_destroy(&counter->mutex); } s32 thread_pool_counter_get_value(thread_pool_task_counter *counter) { s32 ret; mutex_lock(&counter->mutex); ret = counter->value; mutex_unlock(&counter->mutex); return ret; } s32 thread_pool_counter_add_value(thread_pool_task_counter *counter, s32 value) { s32 ret; mutex_lock(&counter->mutex); counter->value += value; ret = counter->value; cond_notify(&counter->cond); mutex_unlock(&counter->mutex); return ret; } s32 thread_pool_counter_wait_below_or_equal(thread_pool_task_counter *counter, s32 value) { s32 ret; mutex_lock(&counter->mutex); for(;;) { ret = counter->value; if(ret <= value) { break; } cond_wait(&counter->cond, &counter->mutex); } mutex_unlock(&counter->mutex); return ret; } ya_result thread_pool_counter_wait_equal(thread_pool_task_counter *counter, s32 value) { mutex_lock(&counter->mutex); for(;;) { if(counter->value == value) { break; } cond_wait(&counter->cond, &counter->mutex); } mutex_unlock(&counter->mutex); return SUCCESS; } ya_result thread_pool_counter_wait_equal_with_timeout(thread_pool_task_counter *counter, s32 value, u64 usec) { s32 ret; s64 until = timeus() + usec; mutex_lock(&counter->mutex); for(;;) { if(counter->value == value) { ret = SUCCESS; break; } cond_timedwait(&counter->cond, &counter->mutex, usec); if(timeus() >= until) { ret = MAKE_ERRNO_ERROR(ETIMEDOUT); break; } } mutex_unlock(&counter->mutex); return ret; } static void thread_pool_random_key_finalize(void *unused) { #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: random thread-local key finalize"); #endif (void)unused; } static void thread_pool_random_key_init(void) { #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: random thread-local key init"); #endif ya_result ret; if((ret = thread_key_create(&thread_pool_random_key, thread_pool_random_key_finalize)) < 0) { log_quit("thread_key_create = %r", ret); } } static void thread_pool_thread_index_init(void) { #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: random thread-local key init"); #endif ya_result ret; if((ret = thread_key_create(&thread_pool_thread_index_key, NULL)) < 0) { log_quit("thread_key_create = %r", ret); } } int thread_pool_queue_size(thread_pool_s *tp) { int size = threaded_queue_size(&tp->queue); return size; } void thread_pool_wait_queue_empty(struct thread_pool_s *tp) { threaded_queue_wait_empty(&tp->queue); } u32 thread_pool_thread_index_get() { u32 *idp = (u32*)thread_key_get(thread_pool_thread_index_key); if(idp != NULL) { return *idp; } else { return MAX_U32; } } static noreturn void* thread_pool_thread(void *args) { /* * Dequeue from the task queue * If what we got is NULL then it's time to stop * Else we run it */ thread_descriptor_s* desc = (thread_descriptor_s*)args; threaded_queue *queue = &desc->pool->queue; #if VERBOSE_THREAD_LOG >= 1 thread_t id = desc->id; #endif #if THREADPOOL_DEBUG_SLOW_ARCH thread_pool_debug_slow_arch_wait(); #endif ya_result ret; #if DNSCORE_HAS_LOG_THREAD_TAG char service_tag[9]; memset(service_tag,'=', sizeof(service_tag) - 1); service_tag[sizeof(service_tag) - 1] = '\0'; thread_make_tag(STRNULL(desc->pool->pool_name), desc->index, desc->pool->thread_pool_size, service_tag); logger_handle_set_thread_tag(service_tag); #endif #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: %p (%i) %x started (pool '%s')", (void*)thread_self(), gettid(), desc->id, STRNULL(desc->pool->pool_name)); #endif if(thread_key_get(thread_pool_random_key) == NULL) { random_ctx rndctx = random_init_auto(); if(FAIL(ret = thread_key_set(thread_pool_random_key, rndctx))) { log_quit("thread_key_set(thread_pool_random_key) = %r", ret); } } if(thread_key_get(thread_pool_thread_index_key) == NULL) { if(FAIL(ret = thread_key_set(thread_pool_thread_index_key, &desc->index))) { log_quit("thread_key_set(thread_pool_thread_index_key) = %r", ret); } } #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: %x random thread-local variable ready", desc->id); #endif for(;;) { #if HAS_PTHREAD_SETNAME_NP thread_set_name(desc->pool->pool_name, desc->index, desc->pool->thread_pool_size); #endif #if DEBUG smp_int_inc(&thread_pool_waiting); #endif desc->status = THREAD_STATUS_WAITING; void* data = threaded_queue_dequeue(queue); #if DEBUG smp_int_dec(&thread_pool_waiting); #endif if(data == NULL) { #if VERBOSE_THREAD_LOG >= 1 log_debug("thread: %x got terminate", id); #endif desc->status = THREAD_STATUS_TERMINATING; break; } desc->status = THREAD_STATUS_WORKING; threaded_queue_task* task = (threaded_queue_task*)data; thread_pool_task_counter *counter = task->counter; thread_pool_function* function = task->function; void *parm = task->parm; const char *categoryname = task->categoryname; ZFREE_OBJECT(task); strcpy_ex(desc->info, categoryname, sizeof(desc->info)); if(counter != NULL) { thread_pool_counter_add_value(counter, +1); } #if VERBOSE_THREAD_LOG >= 3 log_debug("thread: %x %s::%p(%p) begin", id, categoryname, function, parm); #endif thread_set_name(desc->info, 0, 0); #if DEBUG smp_int_inc(&thread_pool_running); #endif function(parm); #if DEBUG smp_int_dec(&thread_pool_running); #endif #if VERBOSE_THREAD_LOG >= 3 log_debug("thread: %x %s::%p(%p) end", id, categoryname, function, parm); #endif if(counter != NULL) { thread_pool_counter_add_value(counter, -1); } memcpy(desc->info, "IDLE", 5); } #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: %x finalising random thread-local variable", desc->id); #endif random_ctx rndctx = (random_ctx)thread_key_get(thread_pool_random_key); if(rndctx != NULL) { random_finalize(rndctx); thread_key_set(thread_pool_random_key, NULL); } #if VERBOSE_THREAD_LOG >= 1 log_debug("thread: %p (%i) %x stopped", (void*)thread_self(), gettid(), id); #endif #if THREADPOOL_DEBUG_SLOW_ARCH thread_pool_debug_slow_arch_wait(); #endif #if DNSCORE_HAS_LOG_THREAD_TAG logger_handle_clear_thread_tag(); #endif #if THREADPOOL_DEBUG_SLOW_ARCH thread_pool_debug_slow_arch_wait(); #endif thread_exit(NULL); // end of the thread from the pool // unreachable // return NULL; } random_ctx thread_pool_get_random_ctx() { random_ctx rndctx = (random_ctx)thread_key_get(thread_pool_random_key); return rndctx; } /** * This MUST be called at the start or a thread that will, one way or another, use * the random function. In doubt, do it. So just do it. * * @note: It's automatically done for all threads from the pool. * @note: It's made on the core alarm function (the one also responsible for * flushing & cie) */ void thread_pool_setup_random_ctx() { #if DEBUG log_debug7("thread_pool_setup_random_ctx()", ERRNO_ERROR); #endif ya_result ret; thread_once(&thread_pool_random_key_once, thread_pool_random_key_init); if(thread_key_get(thread_pool_random_key) == NULL) { random_ctx rndctx = random_init_auto(); if(FAIL(ret = thread_key_set(thread_pool_random_key, rndctx))) { log_quit("thread_key_set = %r", ERRNO_ERROR); } } } void thread_pool_destroy_random_ctx() { random_ctx rndctx; ya_result ret; #if DEBUG log_debug7("thread_pool_destroy_random_ctx()", ERRNO_ERROR); #endif thread_once(&thread_pool_random_key_once, thread_pool_random_key_init); if((rndctx = thread_key_get(thread_pool_random_key)) != NULL) { random_finalize(rndctx); if(FAIL(ret = thread_key_set(thread_pool_random_key, NULL))) { log_quit("thread_key_set = %r", ret); } } else { log_warn("no random context for thread"); } } static thread_descriptor_s* thread_pool_create_thread(thread_pool_s *tp, int index) { thread_descriptor_s *td = NULL; MALLOC_OBJECT_OR_DIE(td, thread_descriptor_s, THREADPOOL_TAG); ZEROMEMORY(td, sizeof(thread_descriptor_s)); td->pool = tp; td->status = THREAD_STATUS_STARTING; td->index = index; int ret; if((ret = thread_create(&td->id, thread_pool_thread, td)) != 0) { OSDEBUG(termerr, "thread_pool_set_pool_size: thread_create : oops: (%r) %s\n", ret, strerror(ret&0xffff)); free(td); return NULL; } return td; } struct thread_pool_s* thread_pool_init_ex(u32 thread_count, u32 queue_size, const char *pool_name) { #if VERBOSE_THREAD_LOG >= 1 log_debug("thread_pool_init(%d, %d, %s)", thread_count, queue_size, STRNULL(pool_name)); #endif if((thread_count > g_max_thread_per_pool_limit) || (thread_count < THREAD_POOL_SIZE_LIMIT_MIN)) { return NULL; } thread_once(&thread_pool_thread_index_key_once, thread_pool_thread_index_init); if(queue_size == 0) { queue_size = thread_count; } if(pool_name == NULL) { pool_name = "thread-pool"; } thread_pool_setup_random_ctx(); thread_pool_s *tp; MALLOC_OBJECT_OR_DIE(tp, thread_pool_s, THRDPOOL_TAG); ZEROMEMORY(tp, sizeof(thread_pool_s)); tp->pool_name = strdup(pool_name); log_debug("thread-pool: '%s' init", pool_name); thread_descriptor_s** thread_descriptors; mutex_init(&tp->mtx); tp->thread_pool_size = thread_count; u16 i; /* thread creation loop counter */ threaded_queue_init(&tp->queue, queue_size); MALLOC_OR_DIE(thread_descriptor_s**, thread_descriptors, thread_count * sizeof(thread_descriptor_s*), THREADPOOL_TAG); for(i = 0; i < thread_count; i++) { thread_descriptor_s *td; if((td = thread_pool_create_thread(tp, i)) == NULL) { log_err("thread-pool: '%s' failed to create thread #%i/%i", pool_name, i, thread_count); free(thread_descriptors); threaded_queue_finalize(&tp->queue); return NULL; } thread_descriptors[i] = td; } tp->descriptors = thread_descriptors; for(;;) { mutex_lock(&thread_pool_set_mutex); u32 id = thread_pool_id_next++; u32_node *node = u32_set_insert(&thread_pool_set, id); mutex_unlock(&thread_pool_set_mutex); if(node->value == NULL) { tp->id = id; node->value = tp; break; } } #if DEBUG tp->created = (u8)rand() | 0x40; tp->destroying = 0; tp->destroyed = 0; #endif log_debug("thread-pool: '%s' ready", pool_name); return tp; } struct thread_pool_s* thread_pool_init(u32 thread_count, u32 queue_size) { struct thread_pool_s* tp = thread_pool_init_ex(thread_count, queue_size, NULL); return tp; } u32 thread_pool_get_size(struct thread_pool_s *tp) { return tp->thread_pool_size; } #if DEBUG static void thread_pool_debug_dump(struct thread_pool_s* tp) { struct thread_descriptor_s **d = tp->descriptors; u32 n = tp->thread_pool_size; u32 i = 0; while(n-- > 0) { log_debug("thread_pool_debug_dump %d, %x, %x, %s", i, d[i]->id, d[i]->status, d[i]->info); i++; } } #endif /** * Enqueues a function to be executed by a thread pool * Do NOT use this function for concurrent producer-consumer spawning on the same pool as * you will end up with a situation where no slots are available for consumers and everybody is waiting. * Instead, when spawning a group, use thread_pool_enqueue_calls * * @param tp the thread pool * @param func the function * @param parm the parameter for the function * @param counter an optional counter that will be incremented just before the function is called, and decremented just after * @param categoryname an optional string that will be along the thread, mostly for debugging * * @return SUCCESS */ ya_result thread_pool_enqueue_call(struct thread_pool_s* tp, thread_pool_function func, void* parm, thread_pool_task_counter *counter, const char* categoryname) { if(tp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } #if DEBUG if(tp->destroying == tp->created) { abort(); } if(tp->destroyed == tp->created) { abort(); } #endif #if DEBUG int running = smp_int_get(&thread_pool_running); int waiting = smp_int_get(&thread_pool_waiting); log_debug("thread_pool_enqueue_call(%p,%p,%p,%s), queue size = %d+1, wait=%d, run=%d",func,parm,counter,(categoryname!=NULL)?categoryname:"NULL",threaded_queue_size(&tp->queue), waiting, running); static u32 last_dump_time = 0; u32 now = time(NULL); if(now - last_dump_time > 30) { thread_pool_debug_dump(tp); last_dump_time = now; } #endif threaded_queue_task* task; ZALLOC_OBJECT_OR_DIE( task, threaded_queue_task, THREADPOOL_TAG); task->function = func; task->parm = parm; task->counter = counter; if(categoryname == NULL) { categoryname = "anonymous"; } task->categoryname = categoryname; threaded_queue_enqueue(&tp->queue, task); return SUCCESS; } /** * Tries to enqueue a function to be executed by a thread pool * If the queue is not available (high concurrency or full), the function will give up and return ERROR. * * @param tp the thread pool * @param func the function * @param parm the parameter for the function * @param counter an optional counter that will be incremented just before the function is called, and decremented just after * @param categoryname an optional string that will be along the thread, mostly for debugging * * @return SUCCESS if the call has been queued, ERROR if the queue was not available for pushing */ ya_result thread_pool_try_enqueue_call(struct thread_pool_s* tp, thread_pool_function func, void* parm, thread_pool_task_counter *counter, const char* categoryname) { if(tp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } #if DEBUG if(tp->destroying == tp->created) { abort(); } if(tp->destroyed == tp->created) { abort(); } #endif threaded_queue_task* task; ZALLOC_OBJECT_OR_DIE(task, threaded_queue_task, THREADPOOL_TAG); task->function = func; task->parm = parm; task->counter = counter; if(categoryname == NULL) { categoryname = "anonymous"; } task->categoryname = categoryname; if(threaded_queue_try_enqueue(&tp->queue, task)) { return SUCCESS; } else { ZFREE_OBJECT(task); return LOCK_TIMEOUT; // full } } ya_result thread_pool_stop(struct thread_pool_s* tp) { if(tp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } #if DEBUG if(tp->destroying == tp->created) { abort(); } if(tp->destroyed == tp->created) { abort(); } #endif thread_descriptor_s** td; u32 tps = tp->thread_pool_size; u32 i; mutex_lock(&tp->mtx); td = tp->descriptors; mutex_unlock(&tp->mtx); if(td == NULL) { #if VERBOSE_THREAD_LOG >= 1 log_debug("thread_pool_stop called on a NULL set"); #endif return SERVICE_NOT_RUNNING; } if((tp->flags & THREADPOOL_FLAG_PAUSED) != 0) { #if VERBOSE_THREAD_LOG >= 1 log_debug("thread_pool_stop called on a NULL set"); #endif return SERVICE_ALREADY_PAUSED; } /* * Sending a node with data == NULL will kill one thread * * I have to launch one for each thread. */ s64 thread_pool_stop_report_time = timeus(); for(i = 0; i < tps; i++) { s64 now = timeus(); if(now - thread_pool_stop_report_time > ONE_SECOND_US) { log_info("thread-pool: %s, busy stopping thread %i/%i", STRNULL(tp->pool_name), i + 1, tps); thread_pool_stop_report_time = now; } switch(td[i]->status) /* Unimportant W -> R race */ { case THREAD_STATUS_TERMINATING: #if VERBOSE_THREAD_LOG >= 1 log_debug("thread: #%i [%x]: already terminating", i, td[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; case THREAD_STATUS_TERMINATED: #if VERBOSE_THREAD_LOG >= 1 log_debug("thread: #%i [%x]: already terminated", i, td[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; case THREAD_STATUS_WORKING: #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: working: sending stop", i, td[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; case THREAD_STATUS_WAITING: #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: waiting: sending stop", i, td[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; default: #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: sending stop on %i status", i, td[i]->id, td[i]->status); #endif threaded_queue_enqueue(&tp->queue, NULL); break; } } /* * I need to wait for each thread */ for(i = 0; i < tps; i++) { int err; /* * @NOTE: helgrind will complain here about a r/w race condition * This is not a problem. The thread keeps its working status (in a volatile) * And this loop only tries to wait if the status is not "done" yet. * * @note by default, threads are PTHREAD_CREATE_JOINABLE */ if(td[i]->status != THREAD_STATUS_TERMINATING && td[i]->status != THREAD_STATUS_TERMINATED) { #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: waiting termination", i, td[i]->id); #endif if((err = thread_join(td[i]->id, NULL)) != 0) { #if VERBOSE_THREAD_LOG >= 3 log_debug("thread: error joining #%i [%x] %r (%x)", i, td[i]->id, err, err); #endif } } td[i]->status = THREAD_STATUS_TERMINATED; #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i: stopped", i); #endif // keep the descriptor for the resume } tp->flags |= THREADPOOL_FLAG_PAUSED; return SUCCESS; } static ya_result thread_pool_start(struct thread_pool_s* tp) { if(tp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } #if DEBUG if(tp->destroying == tp->created) { abort(); } if(tp->destroyed == tp->created) { abort(); } #endif if((tp->flags & THREADPOOL_FLAG_PAUSED) == 0) { return INVALID_STATE_ERROR; } thread_descriptor_s** thread_descriptors = tp->descriptors; u32 tps = tp->thread_pool_size; u32 i; if(thread_descriptors == NULL) { #if VERBOSE_THREAD_LOG >= 1 log_debug("thread_pool_stop called on a NULL set"); #endif return SERVICE_NOT_RUNNING; } s64 thread_pool_start_report_time = timeus(); for(i = 0; i < tps; i++) { /* * @NOTE: helgrind will complain here about a r/w race condition * This is not a problem. The thread keeps its working status (in a volatile) * And this loop only tries to wait if the status is not "done" yet. * * @note by default, threads are PTHREAD_CREATE_JOINABLE */ s64 now = timeus(); if(now - thread_pool_start_report_time > ONE_SECOND_US) { log_info("thread-pool: %s, busy starting thread %i/%i", STRNULL(tp->pool_name), i + 1, tps); thread_pool_start_report_time = now; } u8 status = thread_descriptors[i]->status; switch(status) { case THREAD_STATUS_TERMINATING: case THREAD_STATUS_TERMINATED: // all good break; default: log_err("thread_pool_stop: '%s' has status %hhu", STRNULL(tp->pool_name), status); return SERVICE_HAS_RUNNING_THREADS; } } for(i = 0; i < tps; i++) { int ret; thread_descriptors[i]->status = THREAD_STATUS_STARTING; thread_descriptors[i]->index = tps; if((ret = thread_create(&thread_descriptors[i]->id, thread_pool_thread, thread_descriptors[i])) != 0) { return ret; } #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i: started again", i); #endif // keep the descriptor for the resume } tp->flags &= ~THREADPOOL_FLAG_PAUSED; return SUCCESS; } ya_result thread_pool_resize(struct thread_pool_s* tp, u32 new_size) { if(tp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } #if DEBUG if(tp->destroying == tp->created) { abort(); } if(tp->destroyed == tp->created) { abort(); } #endif if((new_size > g_max_thread_per_pool_limit) || (new_size < THREAD_POOL_SIZE_LIMIT_MIN)) { return INVALID_ARGUMENT_ERROR; } mutex_lock(&tp->mtx); thread_descriptor_s** tds; u32 tps = tp->thread_pool_size; u32 i; if(tps == new_size) { // nothing to do mutex_unlock(&tp->mtx); return tps; } tds = tp->descriptors; tp->descriptors = NULL; // allocate a new struct, reuse thestructs thread_descriptor_s** thread_descriptors; MALLOC_OR_DIE(thread_descriptor_s**, thread_descriptors, sizeof(thread_descriptor_s*) * new_size, THREADPOOL_TAG); // if grow if(new_size > tps) { // copy the current ones memcpy(thread_descriptors, tds, sizeof(thread_descriptor_s*) * tps); // create new threads [tps;new_size[ for(i = tps; i < new_size; i++) { thread_descriptor_s *td; if((td = thread_pool_create_thread(tp, i)) == NULL) { // failed to allocate one thread ... // it's bad. keep what we have. log_err("thread_pool: could not resize from %u to %u, cutting at %u", tps, new_size, i - 1); logger_flush(); if(i == tps) { free(thread_descriptors); thread_descriptors = tds; new_size = tps; } else { free(tds); new_size = i - 1; } tp->descriptors = thread_descriptors; tp->thread_pool_size = new_size; mutex_unlock(&tp->mtx); return new_size; } thread_descriptors[i] = td; // VS false positive (nonsense) } } else { // copy what we can memcpy(thread_descriptors, tds, sizeof(thread_descriptor_s*) * new_size); // stop threads [new_size;tps[ for(i = new_size; i < tps; i++) { switch(tds[i]->status) /* Unimportant W -> R race */ { case THREAD_STATUS_TERMINATING: #if VERBOSE_THREAD_LOG >= 1 log_debug("thread: #%i [%x]: already terminating", i, tds[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; case THREAD_STATUS_TERMINATED: #if VERBOSE_THREAD_LOG >= 1 log_debug("thread: #%i [%x]: already terminated", i, tds[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; case THREAD_STATUS_WORKING: #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: working: sending stop", i, tds[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; case THREAD_STATUS_WAITING: #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: waiting: sending stop", i, tds[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; default: #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: sending stop on %i status", i, tds[i]->id, tds[i]->status); #endif threaded_queue_enqueue(&tp->queue, NULL); break; } } /* * I need to wait for each thread */ for(i = new_size; i < tps; i++) { int err; /* * @NOTE: helgrind will complain here about a r/w race condition * This is not a problem. The thread keeps its working status (in a volatile) * And this loop only tries to wait if the status is not "done" yet. * * @note by default, threads are PTHREAD_CREATE_JOINABLE */ if(tds[i]->status != THREAD_STATUS_TERMINATING && tds[i]->status != THREAD_STATUS_TERMINATED) { #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: waiting termination", i, tds[i]->id); #endif if((err = thread_join(tds[i]->id, NULL)) != 0) { #if VERBOSE_THREAD_LOG >= 3 log_debug("thread: error joining #%i [%x] %r %x", i, tds[i]->id, err, err); #endif } } tds[i]->status = THREAD_STATUS_TERMINATED; #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i: terminated", i); #endif free(tds[i]); tds[i] = NULL; } } free(tds); tp->descriptors = thread_descriptors; tp->thread_pool_size = new_size; mutex_unlock(&tp->mtx); return new_size; } ya_result thread_pool_destroy(struct thread_pool_s* tp) { if(tp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } #if DEBUG if(tp->destroying == tp->created) { abort(); } if(tp->destroyed == tp->created) { abort(); } tp->destroying = tp->created; #endif thread_descriptor_s** td; u32 tps = tp->thread_pool_size; u32 i; mutex_lock(&tp->mtx); td = tp->descriptors; tp->descriptors = NULL; mutex_unlock(&tp->mtx); if(td == NULL) { #if VERBOSE_THREAD_LOG >= 1 log_debug("thread_pool_destroy called on a NULL set (already done)"); #endif return THREAD_DOUBLEDESTRUCTION_ERROR; /* double call */ } mutex_lock(&thread_pool_set_mutex); u32_set_delete(&thread_pool_set, tp->id); mutex_unlock(&thread_pool_set_mutex); tp->thread_pool_size = 0; s64 thread_pool_destroy_report_time = timeus(); /* * Sending a node with data == NULL will kill one thread-pool thread * * I have to launch one for each thread. */ for(i = 0; i < tps; i++) { s64 now = timeus(); if(now - thread_pool_destroy_report_time > ONE_SECOND_US) { log_info("thread-pool: %s, busy destroying thread %i/%i", STRNULL(tp->pool_name), i + 1, tps); thread_pool_destroy_report_time = now; } threaded_queue_wait_empty(&tp->queue); // the queue needs to be empty before it's cleared switch(td[i]->status) /* Unimportant W -> R race */ { case THREAD_STATUS_TERMINATING: #if VERBOSE_THREAD_LOG >= 1 log_debug("thread: #%i [%x]: already terminating", i, td[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; case THREAD_STATUS_TERMINATED: #if VERBOSE_THREAD_LOG >= 1 log_debug("thread: #%i [%x]: already terminated", i, td[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; case THREAD_STATUS_WORKING: #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: working: sending stop", i, td[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; case THREAD_STATUS_WAITING: #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: waiting: sending stop", i, td[i]->id); #endif threaded_queue_enqueue(&tp->queue, NULL); break; default: #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: sending stop on %i status", i, td[i]->id, td[i]->status); #endif threaded_queue_enqueue(&tp->queue, NULL); break; } } /* * I need to wait for each thread */ for(i = 0; i < tps; i++) { int err; /* * @NOTE: helgrind will complain here about a r/w race condition * This is not a problem. The thread keeps its working status (in a volatile) * And this loop only tries to wait if the status is not "done" yet. * * @note by default, threads are PTHREAD_CREATE_JOINABLE */ //if(td[i]->status != THREAD_STATUS_TERMINATING && td[i]->status != THREAD_STATUS_TERMINATED) { #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i [%x]: waiting termination", i, td[i]->id); #endif if((err = thread_join(td[i]->id, NULL)) != 0) { log_err("thread: error joining #%i [%x] %r %x", i, td[i]->id, err, err); logger_flush(); } } td[i]->status = THREAD_STATUS_TERMINATED; #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: #%i: terminated", i); #endif free(td[i]); td[i] = NULL; } free(td); #if VERBOSE_THREAD_LOG >= 2 log_debug("thread: thread_pool_destroy: finalize"); #endif threaded_queue_finalize(&tp->queue); if(tp->pool_name != NULL) { free(tp->pool_name); } #if DEBUG tp->destroyed = tp->created; #endif free(tp); return SUCCESS; } ya_result thread_pool_stop_all() { ya_result err = SUCCESS; mutex_lock(&thread_pool_set_mutex); u32_set_iterator iter; u32_set_iterator_init(&thread_pool_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); if(node->value != NULL) { thread_pool_s *tp = (thread_pool_s*)node->value; log_debug("stopping thread pool '%s'", STRNULL(tp->pool_name)); if(FAIL(err = thread_pool_stop(tp))) { log_err("thread_pool_stop_all failed on '%s' with %r", STRNULL(tp->pool_name), err); break; } } } mutex_unlock(&thread_pool_set_mutex); return err; } ya_result thread_pool_start_all() { ya_result err = SUCCESS; mutex_lock(&thread_pool_set_mutex); u32_set_iterator iter; u32_set_iterator_init(&thread_pool_set, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); if(node->value != NULL) { thread_pool_s *tp = (thread_pool_s*)node->value; log_debug("starting thread pool '%s'", STRNULL(tp->pool_name)); if(FAIL(err = thread_pool_start(tp))) { log_err("thread_pool_start_all failed on '%s' with %r", STRNULL(tp->pool_name), err); break; } } } mutex_unlock(&thread_pool_set_mutex); return err; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/thread-tag.c0000644000000000000000000000013114505005532021513 xustar000000000000000030 mtime=1695812442.375981228 30 atime=1695812445.791030139 29 ctime=1695812494.71373081 yadifa-2.6.5-11201/lib/dnscore/src/thread-tag.c0000664000374500037450000002664414505005532021472 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #if HAS_PTHREAD_SETNAME_NP #if DEBUG #define _GNU_SOURCE 1 #endif #endif #include #include #include #include #include "dnscore/threaded_queue.h" #include "dnscore/thread_pool.h" #include "dnscore/logger.h" #include "dnscore/format.h" #include "dnscore/u32_set.h" #include "dnscore/zalloc.h" #include "dnscore/process.h" #include "dnscore/mutex.h" #include "dnscore/thread-tag.h" /* 0 = nothing, 1 = warns and worse, 2 = info and worse, 3 = debug and worse */ #define VERBOSE_THREAD_LOG 0 #define DEBUG_THREAD_TAG_COLLISIONS 0 /* Disable when in release mode */ #if !DEBUG #undef VERBOSE_THREAD_LOG #define VERBOSE_THREAD_LOG 0 #endif #define MODULE_MSG_HANDLE g_system_logger #if DNSCORE_HAS_LOG_THREAD_TAG #define THREAD_TAG_HASH_PRIME 8191 #define THREAD_TAG_HASH_SIZE (THREAD_TAG_HASH_PRIME + 1) #if __SIZEOF_POINTER__ == 8 struct thread_tag_entry_s { thread_t id; char tag[8]; thread_t thread_id; intptr reserved; }; #else struct thread_tag_entry_s { thread_t id; char tag[8]; thread_t thread_id; }; #endif typedef struct thread_tag_entry_s thread_tag_entry_s; static const char thread_tag_unknown[THREAD_TAG_SIZE] = {'-','-','-','-','-','-','-',' '}; #if __SIZEOF_POINTER__ == 8 static thread_tag_entry_s thread_tag_entry[THREAD_TAG_HASH_SIZE] = {{0,{0,0,0,0,0,0,0,0},0,0}}; #else static thread_tag_entry_s thread_tag_entry[THREAD_TAG_HASH_SIZE] = {{0,{0,0,0,0,0,0,0,0},0}}; #endif static mutex_t thread_tag_mtx = MUTEX_INITIALIZER; static int thread_id_key(thread_t id_) { intptr id = (intptr)id_; unsigned int key = (u32)id; #if __SIZEOF_POINTER__ == 8 key ^= (u32)(id >> 32); #endif return key % THREAD_TAG_HASH_PRIME; } const char * thread_get_tag_with_pid_and_tid(pid_t pid_, thread_t tid_) { intptr pid = (intptr)pid_; intptr tid = (intptr)tid_; thread_t id = (thread_t)(tid ^ pid); int key = thread_id_key(id); for(int c = THREAD_TAG_HASH_SIZE;;) // no need to mtx this { if(thread_tag_entry[key].id == id) { #if VERBOSE_THREAD_LOG const char *tag = thread_tag_entry[key].tag; osformatln(termout, "[%i] thread_get_tag_with_pid_and_tid(%i,%p) => %p = %c%c%c%c%c%c%c%c (%i)", getpid(), pid, tid, id, tag[0],tag[1],tag[2],tag[3], tag[4],tag[5],tag[6],tag[7], key); #endif return thread_tag_entry[key].tag; } if(--c == 0) { #if VERBOSE_THREAD_LOG osformatln(termout, "[%i] thread_get_tag_with_pid_and_tid(%i,%p) => %p = unknown (%i)", getpid(), pid, tid, id, thread_id_key(id)); #endif return thread_tag_unknown; } key = (key + 1) & THREAD_TAG_HASH_PRIME; } // should never be reached // return thread_tag_unknown; } char * thread_copy_tag_with_pid_and_tid(pid_t pid, thread_t tid, char *out_9_bytes) { memcpy(out_9_bytes, thread_get_tag_with_pid_and_tid(pid, tid), 9); out_9_bytes[8] = '\0'; return out_9_bytes; } #if DEBUG_THREAD_TAG_COLLISIONS static int thread_set_tag_with_pid_and_tid_collisions = 0; #endif void thread_set_tag_with_pid_and_tid(pid_t pid_, thread_t tid_, const char *tag8chars) { intptr pid = (intptr)pid_; intptr tid = (intptr)tid_; thread_t id = (thread_t)(tid ^ pid); int key = thread_id_key(id); #if VERBOSE_THREAD_LOG const char *tag = tag8chars; osformatln(termout, "[%i] thread_set_tag_with_pid_and_tid(%i,%p, %c%c%c%c%c%c%c%c) => %p (%i)", getpid(), pid, tid, tag[0],tag[1],tag[2],tag[3], tag[4],tag[5],tag[6],tag[7], id, key); flushout(); #endif #if VERBOSE_THREAD_LOG >= 3 log_info("thread-tag: %i::%p: base key is %i '%c%c%c%c%c%c%c%c'", pid, tid, key, tag8chars[0],tag8chars[1],tag8chars[2],tag8chars[3],tag8chars[4],tag8chars[5],tag8chars[6],tag8chars[7]); #endif mutex_lock(&thread_tag_mtx); for(int c = THREAD_TAG_HASH_SIZE;;) { if((thread_tag_entry[key].id == 0) || (thread_tag_entry[key].id == id)) { thread_tag_entry[key].id = id; int i; for(i = 0; i < THREAD_TAG_SIZE; ++i) { if(tag8chars[i] == '\0') { break; } thread_tag_entry[key].tag[i] = tag8chars[i]; } for(; i < THREAD_TAG_SIZE; ++i) { thread_tag_entry[key].tag[i] = ' '; } thread_tag_entry[key].thread_id = (thread_t)tid; mutex_unlock(&thread_tag_mtx); #if VERBOSE_THREAD_LOG >= 3 log_warn("[%i] thread-tag: %i::%p: last key is %i, %i collisions", getpid(), pid, tid, key, THREAD_TAG_HASH_SIZE - c); #endif return; } if(--c == 0) { mutex_unlock(&thread_tag_mtx); return; // ignore } key = (key + 1) & THREAD_TAG_HASH_PRIME; #if DEBUG_THREAD_TAG_COLLISIONS ++thread_set_tag_with_pid_and_tid_collisions; formatln("thread_set_tag_with_pid_and_tid_collisions = %i", thread_set_tag_with_pid_and_tid_collisions); #endif } } void thread_clear_tag_with_pid_and_tid(pid_t pid_, thread_t tid_) { intptr pid = (intptr)pid_; intptr tid = (intptr)tid_; thread_t id = (thread_t)(tid ^ pid); int key = thread_id_key(id); #if VERBOSE_THREAD_LOG osformatln(termout, "[%i] thread_clear_tag_with_pid_and_tid(%i,%p) => %p (%i)", getpid(), pid, tid, id, key); flushout(); #endif mutex_lock(&thread_tag_mtx); for(int c = THREAD_TAG_HASH_SIZE;;) { if(thread_tag_entry[key].id == id) { thread_tag_entry[key].id = 0; thread_tag_entry[key].tag[0] = 0; mutex_unlock(&thread_tag_mtx); return; } if(--c == 0) { mutex_unlock(&thread_tag_mtx); return; // ignore } key = (key + 1) & THREAD_TAG_HASH_PRIME; } } void thread_tag_log_tags() { for(int key = 0; key < THREAD_TAG_HASH_SIZE; ++key) { if(thread_tag_entry[key].id != 0) { log_info("thread-tag: id=%08i tag=%c%c%c%c%c%c%c%c", thread_tag_entry[key].id, thread_tag_entry[key].tag[0],thread_tag_entry[key].tag[1],thread_tag_entry[key].tag[2],thread_tag_entry[key].tag[3], thread_tag_entry[key].tag[4],thread_tag_entry[key].tag[5],thread_tag_entry[key].tag[6],thread_tag_entry[key].tag[7]); } } } void thread_tag_push_tags() { for(int key = 0; key < THREAD_TAG_HASH_SIZE; ++key) { if(thread_tag_entry[key].id != 0) { #if DEBUG debug_osformatln(termout, "thread-tag: pushing id=%p tag=%c%c%c%c%c%c%c%c", thread_tag_entry[key].thread_id, thread_tag_entry[key].tag[0],thread_tag_entry[key].tag[1],thread_tag_entry[key].tag[2],thread_tag_entry[key].tag[3], thread_tag_entry[key].tag[4],thread_tag_entry[key].tag[5],thread_tag_entry[key].tag[6],thread_tag_entry[key].tag[7]); /* log_debug("thread-tag: pushing id=%p tag=%c%c%c%c%c%c%c%c", thread_tag_entry[key].thread_id, thread_tag_entry[key].tag[0],thread_tag_entry[key].tag[1],thread_tag_entry[key].tag[2],thread_tag_entry[key].tag[3], thread_tag_entry[key].tag[4],thread_tag_entry[key].tag[5],thread_tag_entry[key].tag[6],thread_tag_entry[key].tag[7]); */ #endif logger_handle_set_thread_tag_with_pid_and_tid(getpid(), thread_tag_entry[key].thread_id, thread_tag_entry[key].tag); } } } void thread_make_tag(const char *prefix, u32 index, u32 count, char *out_service_tag) { char service_tag[THREAD_TAG_SIZE + 1]; if(prefix == NULL) { prefix = "X"; } memset(out_service_tag, '-', THREAD_TAG_SIZE); size_t prefix_len = strlen(prefix); if(prefix_len > THREAD_TAG_SIZE) { prefix_len = THREAD_TAG_SIZE; } memcpy(service_tag, prefix, prefix_len); for(size_t i = prefix_len; i < THREAD_TAG_SIZE; ++i) { service_tag[i] = ' '; } service_tag[THREAD_TAG_SIZE] = '\0'; if(count <= 1) { // good as it is } else if(count <= 0x10) // [ 0 ; 0x10 [ => 1 byte { snformat(&service_tag[7], 2, "%x", index); } else if(count <= 0x100) { snformat(&service_tag[6], 3, "%02x", index); } else if(count <= 0x1000) { snformat(&service_tag[5], 4, "%03x", index); } else if(count <= 0x10000) { snformat(&service_tag[4], 5, "%04x", index); } else if(count <= 0x100000) { snformat(&service_tag[3], 6, "%05x", index); } else { snformat(&service_tag[1], THREAD_TAG_SIZE, "%x", index); } memcpy(out_service_tag, service_tag, THREAD_TAG_SIZE); #if VERBOSE_THREAD_LOG > 1 osformatln(termout, "[%i] thread_make_tag(%s,%i,%i,&): %i (%i) %p) = %c%c%c%c%c%c%c%c", getpid(), prefix, index, count, getpid_ex(), getpid(), thread_self(), service_tag[0], service_tag[1], service_tag[2], service_tag[3], service_tag[4], service_tag[5], service_tag[6], service_tag[7]); #endif } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/threaded-qsl-cw.c0000644000000000000000000000013214505005532022460 xustar000000000000000030 mtime=1695812442.428981988 30 atime=1695812445.793030168 30 ctime=1695812494.715730839 yadifa-2.6.5-11201/lib/dnscore/src/threaded-qsl-cw.c0000664000374500037450000002133414505005532022425 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/threaded-qsl-cw.h" #define MODULE_MSG_HANDLE g_system_logger #define DLL_POOL 1 /* * Note: * * If a mutex_init fails, it's because of a resource, memory or rights issue. * So the application will fail soon enough. * I still should check this and exit. * * mutex_lock will fail only if the current thread aleady owns the mutex * * mutex_unlock will fail only if the current thread does not owns the mutex * */ void threaded_qsl_cw_init(threaded_qsl_cw *queue, int max_size) { #if DEBUG memset(queue, 0xff, sizeof(threaded_qsl_cw)); #endif queue_sl_init(&queue->queue); #if DLL_POOL queue->pool = NULL; #endif mutex_init(&queue->mutex); cond_init(&queue->cond_read); cond_init(&queue->cond_write); queue->max_size = max_size; } void threaded_qsl_cw_finalize(threaded_qsl_cw *queue) { /** * If the queue is not empty : too bad ! * * It's the responsibility of the caller to ensure the queue and set of listeners is empty. */ mutex_lock(&queue->mutex); while(queue_sl_size(&queue->queue) > 0) { void *leaked_data = queue_sl_dequeue(&queue->queue); log_err("threaded_qsl_cw_finalize: leaked data @%p", leaked_data); } #if DLL_POOL queue_sl_node_s *node = queue->pool; while(node != NULL) { queue_sl_node_s *node_next = node->next; queue_sl_node_free(node); node = node_next; } #endif mutex_unlock(&queue->mutex); cond_finalize(&queue->cond_write); cond_finalize(&queue->cond_read); mutex_destroy(&queue->mutex); #if DEBUG memset(queue, 0xde, sizeof(threaded_qsl_cw)); #endif } void threaded_qsl_cw_enqueue(threaded_qsl_cw *queue, void *constant_pointer) { /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while(queue_sl_size(&queue->queue) >= queue->max_size) { cond_wait(&queue->cond_write, &queue->mutex); } #if DLL_POOL queue_sl_node_s *node; if(queue->pool != NULL) { node = queue->pool; queue->pool = node->next; } else { node = queue_sl_node_alloc(); } node->data = constant_pointer; queue_sl_enqueue_node(&queue->queue, node); #else queue_sl_enqueue(&queue->queue, constant_pointer); #endif /* * We are done here, we can always signal the readers */ cond_notify(&queue->cond_read); mutex_unlock(&queue->mutex); } bool threaded_qsl_cw_try_enqueue(threaded_qsl_cw* queue, void* constant_pointer) { /* * Ensure I'm allowed to work on queue (only one working on it) */ if(!mutex_trylock(&queue->mutex)) { return FALSE; } if( queue_sl_size(&queue->queue) >= queue->max_size ) { mutex_unlock(&queue->mutex); return FALSE; } /* * Set the data to the write position, * and move the write position to the next slot * */ #if DLL_POOL queue_sl_node_s *node; if(queue->pool != NULL) { node = queue->pool; queue->pool = node->next; } else { node = queue_sl_node_alloc(); } node->data = constant_pointer; queue_sl_enqueue_node(&queue->queue, node); #else queue_sl_enqueue(&queue->queue, constant_pointer); #endif cond_notify(&queue->cond_read); mutex_unlock(&queue->mutex); return TRUE; } void* threaded_qsl_cw_dequeue(threaded_qsl_cw *queue) { /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while(queue_sl_size(&queue->queue) == 0) { cond_wait(&queue->cond_read, &queue->mutex); } bool write_blocked = (queue_sl_size(&queue->queue) == queue->max_size); #if DLL_POOL queue_sl_node_s *node = queue_sl_dequeue_node(&queue->queue); void *data = node->data; node->next = queue->pool; queue->pool = node; #else void *data = queue_sl_dequeue(&queue->queue); #endif if(write_blocked) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we can free (one of) them. * (They will however still be locked until the queue mutex is released) */ cond_notify(&queue->cond_write); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void* threaded_qsl_cw_try_dequeue(threaded_qsl_cw *queue) { mutex_lock(&queue->mutex); if(queue_sl_size(&queue->queue) == 0) { mutex_unlock(&queue->mutex); return NULL; } /* * Get the data from the read position, * and move the read position to the next slot * */ bool write_blocked = (queue_sl_size(&queue->queue) == queue->max_size); #if DLL_POOL queue_sl_node_s *node = queue_sl_dequeue_node(&queue->queue); void *data = node->data; node->next = queue->pool; queue->pool = node; #else void *data = queue_sl_dequeue(&queue->queue); #endif if(write_blocked) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ cond_notify(&queue->cond_write); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void threaded_qsl_cw_wait_empty(threaded_qsl_cw *queue) { int size; for(;;) { mutex_lock(&queue->mutex); size = queue_sl_size(&queue->queue); mutex_unlock(&queue->mutex); if(size == 0) { break; } usleep(1000); } } int threaded_qsl_cw_size(threaded_qsl_cw *queue) { int size; mutex_lock(&queue->mutex); size = queue_sl_size(&queue->queue); mutex_unlock(&queue->mutex); return size; } int threaded_qsl_cw_room(threaded_qsl_cw *queue) { int room; mutex_lock(&queue->mutex); room = queue->max_size - queue_sl_size(&queue->queue); mutex_unlock(&queue->mutex); return room; } ya_result threaded_qsl_cw_set_maxsize(threaded_qsl_cw *queue, int max_size) { ya_result ret; mutex_lock(&queue->mutex); if(max_size >= (int)queue_sl_size(&queue->queue)) { queue->max_size = max_size; } ret = queue->max_size; // can only grow : wake up the writers that may be blocked because there was no room left in the queue cond_notify(&queue->cond_write); mutex_unlock(&queue->mutex); return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/threaded_dll_cw.c0000644000000000000000000000013214505005532022600 xustar000000000000000030 mtime=1695812442.391981457 30 atime=1695812445.792030153 30 ctime=1695812494.717730868 yadifa-2.6.5-11201/lib/dnscore/src/threaded_dll_cw.c0000664000374500037450000002371614505005532022553 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/threaded_dll_cw.h" #define MODULE_MSG_HANDLE g_system_logger #define DLL_POOL 1 /* * Note: * * If a mutex_init fails, it's because of a resource, memory or rights issue. * So the application will fail soon enough. * I still should check this and exit. * * mutex_lock will fail only if the current thread aleady owns the mutex * * mutex_unlock will fail only if the current thread does not owns the mutex * */ void threaded_dll_cw_init(threaded_dll_cw *queue, int max_size) { #if DEBUG memset(queue, 0xff, sizeof(threaded_dll_cw)); #endif list_dl_init(&queue->queue); #if DLL_POOL queue->pool = NULL; #endif mutex_init(&queue->mutex); cond_init(&queue->cond_read); cond_init(&queue->cond_write); queue->max_size = max_size; } void threaded_dll_cw_finalize(threaded_dll_cw *queue) { /** * If the queue is not empty : too bad ! * * It's the responsibility of the caller to ensure the queue and set of listeners is empty. */ mutex_lock(&queue->mutex); while(list_dl_size(&queue->queue) > 0) { void *leaked_data = list_dl_dequeue(&queue->queue); log_err("threaded_dll_cw_finalize: leaked data @%p", leaked_data); } #if DLL_POOL list_dl_node_s *node = queue->pool; while(node != NULL) { list_dl_node_s *node_next = node->next; list_dl_node_free(node); node = node_next; } #endif mutex_unlock(&queue->mutex); cond_finalize(&queue->cond_write); cond_finalize(&queue->cond_read); mutex_destroy(&queue->mutex); #if DEBUG memset(queue, 0xde, sizeof(threaded_dll_cw)); #endif } void threaded_dll_cw_enqueue(threaded_dll_cw *queue, void *constant_pointer) { /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while(list_dl_size(&queue->queue) >= queue->max_size) { cond_wait(&queue->cond_write, &queue->mutex); } #if DLL_POOL list_dl_node_s *node; if(queue->pool != NULL) { node = queue->pool; queue->pool = node->next; } else { node = list_dl_node_alloc(); } node->data = constant_pointer; list_dl_insert_node(&queue->queue, node); #else list_dl_enqueue(&queue->queue, constant_pointer); #endif /* * We are done here, we can always signal the readers */ cond_notify(&queue->cond_read); mutex_unlock(&queue->mutex); } bool threaded_dll_cw_try_enqueue(threaded_dll_cw* queue, void* constant_pointer) { /* * Ensure I'm allowed to work on queue (only one working on it) */ if(!mutex_trylock(&queue->mutex)) { return FALSE; } if( list_dl_size(&queue->queue) >= queue->max_size ) { mutex_unlock(&queue->mutex); return FALSE; } /* * Set the data to the write position, * and move the write position to the next slot * */ #if DLL_POOL list_dl_node_s *node; if(queue->pool != NULL) { node = queue->pool; queue->pool = node->next; } else { node = list_dl_node_alloc(); } node->data = constant_pointer; list_dl_insert_node(&queue->queue, node); #else list_dl_enqueue(&queue->queue, constant_pointer); #endif cond_notify(&queue->cond_read); mutex_unlock(&queue->mutex); return TRUE; } void* threaded_dll_cw_dequeue(threaded_dll_cw *queue) { /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while(list_dl_size(&queue->queue) == 0) { cond_wait(&queue->cond_read, &queue->mutex); } bool write_blocked = (list_dl_size(&queue->queue) == queue->max_size); #if DLL_POOL list_dl_node_s *node = list_dl_remove_last_node(&queue->queue); void *data = node->data; node->next = queue->pool; queue->pool = node; #else void *data = list_dl_dequeue(&queue->queue); #endif if(write_blocked) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we can free (one of) them. * (They will however still be locked until the queue mutex is released) */ cond_notify(&queue->cond_write); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void* threaded_dll_cw_try_dequeue(threaded_dll_cw *queue) { mutex_lock(&queue->mutex); if(list_dl_size(&queue->queue) == 0) { mutex_unlock(&queue->mutex); return NULL; } /* * Get the data from the read position, * and move the read position to the next slot * */ bool write_blocked = (list_dl_size(&queue->queue) == queue->max_size); #if DLL_POOL list_dl_node_s *node = list_dl_remove_last_node(&queue->queue); void *data = node->data; node->next = queue->pool; queue->pool = node; #else void *data = list_dl_dequeue(&queue->queue); #endif if(write_blocked) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ cond_notify(&queue->cond_write); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void* threaded_dll_cw_dequeue_with_timeout(threaded_dll_cw *queue, s64 timeout_us) { /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while(list_dl_size(&queue->queue) == 0) { if(cond_timedwait(&queue->cond_read, &queue->mutex, timeout_us) != 0) { // timed-out mutex_unlock(&queue->mutex); return NULL; } } bool write_blocked = (list_dl_size(&queue->queue) == queue->max_size); #if DLL_POOL list_dl_node_s *node = list_dl_remove_last_node(&queue->queue); void *data = node->data; node->next = queue->pool; queue->pool = node; #else void *data = list_dl_dequeue(&queue->queue); #endif if(write_blocked) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we can free (one of) them. * (They will however still be locked until the queue mutex is released) */ cond_notify(&queue->cond_write); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void threaded_dll_cw_wait_empty(threaded_dll_cw *queue) { int size; for(;;) { mutex_lock(&queue->mutex); size = list_dl_size(&queue->queue); mutex_unlock(&queue->mutex); if(size == 0) { break; } usleep(1000); } } int threaded_dll_cw_size(threaded_dll_cw *queue) { int size; mutex_lock(&queue->mutex); size = list_dl_size(&queue->queue); mutex_unlock(&queue->mutex); return size; } int threaded_dll_cw_room(threaded_dll_cw *queue) { int room; mutex_lock(&queue->mutex); room = queue->max_size - list_dl_size(&queue->queue); mutex_unlock(&queue->mutex); return room; } ya_result threaded_dll_cw_set_maxsize(threaded_dll_cw *queue, int max_size) { ya_result ret; mutex_lock(&queue->mutex); if(max_size >= (int)list_dl_size(&queue->queue)) { queue->max_size = max_size; } ret = queue->max_size; // can only grow : wake up the writers that may be blocked because there was no room left in the queue cond_notify(&queue->cond_write); mutex_unlock(&queue->mutex); return ret; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/threaded_nb_mm.c0000644000000000000000000000013214505005532022424 xustar000000000000000030 mtime=1695812442.469982575 30 atime=1695812445.795030196 30 ctime=1695812494.719730896 yadifa-2.6.5-11201/lib/dnscore/src/threaded_nb_mm.c0000664000374500037450000000777114505005532022402 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief "no-wait" stack allocator * meant to be used with the "no-wait" queue * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/threaded_nb_mm.h" #define THRDNBMM_TAG 0x4d4d424e44524854 void threaded_nb_mm_init(threaded_nb_mm *mm, u32 count, u32 size) { assert(count > 1); size = (size + sizeof(void*) - 1) & ~(sizeof(void*)-1); u32 n = count * size; MALLOC_OR_DIE(u8*,mm->items, n, THRDNBMM_TAG); mm->item_count = count; mm->item_size = size; if(n == 0) { mm->item_head = NULL; return; } const u8 * const limit = &mm->items[n]; // n > 0, (n is unsigned) => limit > &mm->items[0] assert(&mm->items[0] < limit); // silents a false positive u8** pp; for(u8* p = &mm->items[0]; p < limit; p += size) // the loop runs at least once (see line 86) { pp = (u8**)p; *pp = &p[size]; } *pp = NULL; // false "maybe-uninitialized" positive : the loop always runs AT LEAST once (n > 0 => and limit > p) mm->item_head = (volatile void**)&mm->items[0]; } void* threaded_nb_mm_alloc(threaded_nb_mm *mm) { void *first; for(;;) { first = __sync_fetch_and_add(&mm->item_head, 0); if(first != NULL) { void **firstp = (void**)first; void *next = *firstp; if(__sync_bool_compare_and_swap(&mm->item_head, first, next)) { break; } usleep(5); } else { return NULL; } } return first; } void threaded_nb_mm_free(threaded_nb_mm *mm, void *p) { void **pp = (void**)p; for(;;) { void *first = __sync_fetch_and_add(&mm->item_head, 0); *pp = first; if(__sync_bool_compare_and_swap(&mm->item_head, first, p)) { break; } usleep(5); } } void threaded_nb_mm_finalize(threaded_nb_mm *mm) { free(mm->item_head); mm->item_head = NULL; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/threaded_nbrb.c0000644000000000000000000000013214505005532022257 xustar000000000000000030 mtime=1695812442.505983091 30 atime=1695812445.797030225 30 ctime=1695812494.721730925 yadifa-2.6.5-11201/lib/dnscore/src/threaded_nbrb.c0000664000374500037450000002216514505005532022227 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/threaded_nbrb.h" #define HAS_ATOMIC_FEATURES 0 #if HAS_ATOMIC_FEATURES #define THREADED_QUEUE_NBRB_TAG 0x4252424e5154 /* TQUEUE */ #define BASE_WAIT 5 // us #define BASE_WAIT_MAX 500000 // so about 0.5 secs max /* * The maximum number of nodes I should ever require is the queue size + 1 * * A good way to handle this is : * * Node allocator, node destroyer * * But the node allocator only allocates a node if none are free * And the node destroyer does not release a node but queue it instead. * * If I enforce the requirement that the allocation/destruction is done * by a single thread I could gain some cpu cycles. * * This reasoning is also valid for the thread_pool_task * */ /* * Note: * * If a mutex_init fails, it's because of a resource, memory or rights issue. * So the application will fail soon enough. * I still should check this and exit. * * mutex_lock will fail only if the current thread aleady owns the mutex * * mutex_unlock will fail only if the current thread does not owns the mutex * */ #define SENTINEL ((void*)~0) #define DO_YIELD 0 #define LOOP_WAIT(t) \ if(t == BASE_WAIT) \ { \ sched_yield(); \ t += BASE_WAIT; \ continue; \ } \ \ usleep(t); \ \ t += BASE_WAIT; \ if(t > BASE_WAIT_MAX) \ { \ t = BASE_WAIT_MAX; \ } void threaded_nbrb_init(threaded_nbrb *queue, int max_size) { u32 real_size = 1; while(real_size <= max_size) { real_size <<= 1; } real_size >>= 1; if(real_size < 4) { real_size = 4; } else if(real_size > 0x1000000) { real_size = 0x1000000; } MALLOC_OR_DIE(void**, queue->buffer, sizeof(void*)* real_size, THREADED_QUEUE_NBRB_TAG); queue->empty_slots = real_size; queue->filled_slots = 0; queue->write_offset = 0; queue->read_offset = 0; queue->size_mask = real_size - 1; for(u32 i = 0; i < real_size; i++) { queue->buffer[i] = SENTINEL; } } void threaded_nbrb_finalize(threaded_nbrb *queue) { /** * If the queue is not empty : too bad ! * * It's the responsibility of the caller to ensure the queue and set of listeners is empty. */ free(queue->buffer); queue->buffer = NULL; } void threaded_nbrb_enqueue(threaded_nbrb* queue, void* constant_pointer) { const u32 one = 1; int t = BASE_WAIT; s32 e; for(;;) { e = __sync_fetch_and_sub(&queue->empty_slots, one); if(e > 0) { break; } __sync_fetch_and_add(&queue->empty_slots, one); LOOP_WAIT(t) } s32 wo = __sync_fetch_and_add(&queue->write_offset, one); #if 0 /* fix */ #elif 1 //__sync_synchronize(); queue->buffer[wo & queue->size_mask] = constant_pointer; //__sync_synchronize(); #else //while(!__sync_bool_compare_and_swap(&queue->buffer[wo & queue->size_mask],queue->buffer[wo & queue->size_mask],constant_pointer)); while(!__sync_bool_compare_and_swap(&queue->buffer[wo & queue->size_mask], SENTINEL, constant_pointer)); #endif __sync_fetch_and_add(&queue->filled_slots, one); } bool threaded_nbrb_try_enqueue(threaded_nbrb* queue, void* constant_pointer) { const u32 one = 1; s32 e = __sync_fetch_and_sub(&queue->empty_slots, one); if(e <= 0) { __sync_fetch_and_add(&queue->empty_slots, one); return FALSE; } s32 wo = __sync_fetch_and_add(&queue->write_offset, one); //queue->buffer[wo & queue->size_mask] = constant_pointer; queue->buffer[wo & queue->size_mask] = constant_pointer; __sync_fetch_and_add(&queue->filled_slots, one); return TRUE; } void* threaded_nbrb_try_peek(threaded_nbrb *queue) { const s32 zero = 0; const s32 one = 1; s32 e = __sync_fetch_and_sub(&queue->filled_slots, one); if(e <= 0) { __sync_fetch_and_add(&queue->filled_slots, one); return NULL; } s32 ro = __sync_fetch_and_add(&queue->read_offset, zero); void* p = queue->buffer[ro & queue->size_mask]; __sync_fetch_and_add(&queue->filled_slots, one); return p; } void* threaded_nbrb_peek(threaded_nbrb *queue) { const s32 zero = 0; const s32 one = 1; int t = BASE_WAIT; s32 e; for(;;) { e = __sync_fetch_and_sub(&queue->filled_slots, one); if(e > 0) { break; } __sync_fetch_and_add(&queue->filled_slots, one); LOOP_WAIT(t) } s32 ro = __sync_fetch_and_add(&queue->read_offset, zero); void* p = queue->buffer[ro & queue->size_mask]; __sync_fetch_and_add(&queue->filled_slots, one); return p; } void* threaded_nbrb_dequeue(threaded_nbrb *queue) { const s32 one = 1; int t = BASE_WAIT; s32 e; for(;;) { e = __sync_fetch_and_sub(&queue->filled_slots, one); if(e > 0) { break; } __sync_fetch_and_add(&queue->filled_slots, one); LOOP_WAIT(t) } s32 ro = __sync_fetch_and_add(&queue->read_offset, one); #if 0 /* fix */ #elif 1 void * volatile *pp = (void* volatile *)&queue->buffer[ro & queue->size_mask]; void* p; for(;;) { //__sync_synchronize(); p = *pp; if(p != SENTINEL) { queue->buffer[ro & queue->size_mask] = SENTINEL; break; } //sched_yield(); __sync_synchronize(); } //__sync_synchronize(); #else //while(!__sync_val_compare_and_swap(&queue->buffer[ro & queue->size_mask], SENTINEL, #endif __sync_fetch_and_add(&queue->empty_slots, one); return p; } void* threaded_nbrb_try_dequeue(threaded_nbrb *queue) { const u32 one = 1; s32 e = __sync_fetch_and_sub(&queue->filled_slots, one); if(e <= 0) { __sync_fetch_and_add(&queue->filled_slots, one); return NULL; } s32 ro = __sync_fetch_and_add(&queue->read_offset, one); void* p = queue->buffer[ro & queue->size_mask]; __sync_fetch_and_add(&queue->empty_slots, one); return p; } u32 threaded_nbrb_dequeue_set(threaded_nbrb* queue, void** array, u32 array_size) { u32 loops = 0; return loops; /* Return the amount we got from the queue */ } void threaded_nbrb_wait_empty(threaded_nbrb *queue) { const u32 zero = 0; //u32 m = queue->size_mask; int t = BASE_WAIT; for(;;) { s32 f = __sync_fetch_and_add(&queue->filled_slots, zero); if(f == 0) { break; } LOOP_WAIT(t) } } int threaded_nbrb_size(threaded_nbrb *queue) { const u32 zero = 0; s32 f = __sync_fetch_and_add(&queue->filled_slots, zero); return f; } ya_result threaded_nbrb_set_maxsize(threaded_nbrb *queue, int max_size) { ya_result ret = FEATURE_NOT_IMPLEMENTED_ERROR; return ret; } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/threaded_queue_slg.c0000644000000000000000000000013214505005532023325 xustar000000000000000030 mtime=1695812442.404981644 30 atime=1695812445.792030153 30 ctime=1695812494.723730954 yadifa-2.6.5-11201/lib/dnscore/src/threaded_queue_slg.c0000664000374500037450000001573414505005532023301 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include "dnscore/threaded_queue_slg.h" #define MODULE_MSG_HANDLE g_system_logger #define THRDQSPG_TAG 0x4750535144524854 void threaded_queue_slg_init(threaded_queue_slg_t *q, int ignored_size) { (void)ignored_size; threaded_queue_slg_page_t *page = NULL; ZALLOC_OBJECT_OR_DIE(page, threaded_queue_slg_page_t, THRDQSPG_TAG); page->size = 0; page->next = NULL; mutex_init(&q->mtx); q->page_pool = NULL; q->read_page = page; cond_init(&q->read_cond); q->read_index = 0; q->write_page = page; } void threaded_queue_slg_finalize(threaded_queue_slg_t *q) { mutex_lock(&q->mtx); int pool_released_count = 0; int read_released_count = 0; bool write_auto_cleared = (q->write_page == NULL); threaded_queue_slg_page_t *page = q->page_pool; while(page != NULL) { threaded_queue_slg_page_t *tmp = page; page = page->next; ZFREE_OBJECT(tmp); ++pool_released_count; } q->page_pool = NULL; page = q->read_page; while(page != NULL) { threaded_queue_slg_page_t *tmp = page; page = page->next; ZFREE_OBJECT(tmp); ++read_released_count; if(q->write_page == tmp) { q->write_page = NULL; write_auto_cleared = TRUE; } } q->read_page = NULL; q->read_index = 0; mutex_unlock(&q->mtx); log_debug("threaded_queue_slg_finalize: %i pooled, %i released, write %s", pool_released_count, read_released_count, ((write_auto_cleared)?"auto-cleared":"not cleared")); cond_finalize(&q->read_cond); mutex_destroy(&q->mtx); } int threaded_queue_slg_room(threaded_queue_slg_t *q) { (void)q; return MAX_S32; } ya_result threaded_queue_slg_set_maxsize(threaded_queue_slg_t *q, int max_size) { (void)q; (void)max_size; return SUCCESS; } void threaded_queue_slg_enqueue(threaded_queue_slg_t *q, void *data) { mutex_lock(&q->mtx); threaded_queue_slg_page_t *page = q->write_page; if(page->size < THREADED_QUEUE_SQL_SLOTS) { page->data[page->size++] = data; } else { threaded_queue_slg_page_t *next_page; if(q->page_pool != NULL) { next_page = q->page_pool; q->page_pool = next_page->next; } else { ZALLOC_OBJECT_OR_DIE(next_page, threaded_queue_slg_page_t, THRDQSPG_TAG); } next_page->data[0] = data; next_page->size = 1; next_page->next = NULL; page->next = next_page; q->write_page = next_page; } cond_notify(&q->read_cond); mutex_unlock(&q->mtx); } void* threaded_queue_slg_dequeue(threaded_queue_slg_t *q) { void *data; mutex_lock(&q->mtx); for(;;) { volatile threaded_queue_slg_page_t *page = (volatile threaded_queue_slg_page_t*)q->read_page; intptr d = (intptr)page->size - (intptr)q->read_index; if(d > 0) { data = page->data[q->read_index++]; if(d == 1) { cond_notify(&q->read_cond); } mutex_unlock(&q->mtx); return data; } else { #if 1 if(page->size == THREADED_QUEUE_SQL_SLOTS) { if(page->next == NULL) { // buffer can be reset page->size = 0; q->read_index = 0; // wait cond_wait(&q->read_cond, &q->mtx); } else { threaded_queue_slg_page_t *tmp = (threaded_queue_slg_page_t*)page; page = page->next; tmp->next = q->page_pool; q->page_pool = tmp; q->read_page = (threaded_queue_slg_page_t*)page; q->read_index = 0; } } else { // buffer can be reset page->size = 0; q->read_index = 0; cond_wait(&q->read_cond, &q->mtx); } #else cond_wait(&q->read_cond, &q->mtx); #endif } } } void threaded_queue_slg_wait_empty(threaded_queue_slg_t *q) { mutex_lock(&q->mtx); while(!((q->read_page->next == NULL) && ((q->read_page->size - q->read_index) == 0))) { cond_wait(&q->read_cond, &q->mtx); } cond_notify_one(&q->read_cond); mutex_unlock(&q->mtx); } int threaded_queue_slg_size(threaded_queue_slg_t *q) { intptr ret = q->read_page->size; mutex_lock(&q->mtx); threaded_queue_slg_page_t *page = q->read_page->next; while(page != NULL) { ret += page->size; page = page->next; } ret -= q->read_index; mutex_unlock(&q->mtx); return (int)ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/threaded_ringbuffer.c0000644000000000000000000000013114505005532023464 xustar000000000000000030 mtime=1695812442.489982861 29 atime=1695812445.79603021 30 ctime=1695812494.725730982 yadifa-2.6.5-11201/lib/dnscore/src/threaded_ringbuffer.c0000664000374500037450000003541114505005532023433 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/threaded_ringbuffer.h" #define THREADED_QUEUE_RINGBUFFFER_TAG 0x4646554247525154 /* TQRGBUFF */ /* * The maximum number of nodes I should ever require is the queue size + 1 * * A good way to handle this is : * * Node allocator, node destroyer * * But the node allocator only allocates a node if none are free * And the node destroyer does not release a node but queue it instead. * * If I enforce the requirement that the allocation/destruction is done * by a single thread I could gain some cpu cycles. * * This reasoning is also valid for the thread_pool_task * */ typedef struct threaded_ringbuffer_node threaded_ringbuffer_node; struct threaded_ringbuffer_node { threaded_ringbuffer_node *next; threaded_ringbuffer_node *prev; void* data; }; /* * Note: * * If a mutex_init fails, it's because of a resource, memory or rights issue. * So the application will fail soon enough. * I still should check this and exit. * * mutex_lock will fail only if the current thread aleady owns the mutex * * mutex_unlock will fail only if the current thread does not owns the mutex * */ void threaded_ringbuffer_init(threaded_ringbuffer *queue, int max_size) { MALLOC_OR_DIE(void**, queue->buffer, sizeof(void*)* max_size, THREADED_QUEUE_RINGBUFFFER_TAG); queue->buffer_limit = &queue->buffer[max_size]; queue->write_slot = queue->buffer; queue->read_slot = queue->buffer; mutex_init(&queue->mutex); mutex_init(&queue->mutex_enqueue); mutex_init(&queue->mutex_dequeue); queue->max_size = max_size; queue->size = 0; mutex_lock(&queue->mutex_dequeue); } void threaded_ringbuffer_finalize(threaded_ringbuffer *queue) { /** * If the queue is not empty : too bad ! * * It's the responsibility of the caller to ensure the queue and set of listeners is empty. */ free(queue->buffer); queue->buffer = NULL; mutex_destroy(&queue->mutex); mutex_destroy(&queue->mutex_enqueue); mutex_destroy(&queue->mutex_dequeue); } void threaded_ringbuffer_enqueue(threaded_ringbuffer* queue, void* constant_pointer) { /* * Ensure I'm allowed to enqueue (only one enqueuer and queue not full) */ mutex_lock(&queue->mutex_enqueue); /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); /* * Set the data to the write position, * and move the write position to the next slot * */ /** * @note: From the random benchmark : "if(overflow) reset" is (much) faster than MOD(limit) */ *queue->write_slot++ = constant_pointer; if(queue->write_slot == queue->buffer_limit) { queue->write_slot = queue->buffer; } if(queue->size == 0) { /* * The queue is empty : the dequeuers are waiting. * Since we will add something for them, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ mutex_unlock(&queue->mutex_dequeue); } queue->size++; if(queue->size < queue->max_size) /* Too much -> lock the pushes, will be unlocked by a pop */ { /* * This new addition made the queue full. So we will not unlock the enqueuers. * The dequeuers will do that when they see fit. (ie: queue not full anymore) */ mutex_unlock(&queue->mutex_enqueue); } /* * We are done here. */ mutex_unlock(&queue->mutex); } bool threaded_ringbuffer_try_enqueue(threaded_ringbuffer* queue, void* constant_pointer) { /* * Ensure I'm allowed to enqueue (only one enqueuer and queue not full) */ if(!mutex_trylock(&queue->mutex_enqueue)) { return FALSE; } /* * Ensure I'm allowed to work on queue (only one working on it) */ if(!mutex_trylock(&queue->mutex)) { mutex_unlock(&queue->mutex_enqueue); return FALSE; } /* * Set the data to the write position, * and move the write position to the next slot * */ /** * @note: From the random benchmark : "if(overflow) reset" is (much) faster than MOD(limit) */ *queue->write_slot++ = constant_pointer; if(queue->write_slot == queue->buffer_limit) { queue->write_slot = queue->buffer; } if(queue->size == 0) { /* * The queue is empty : the dequeuers are waiting. * Since we will add something for them, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ mutex_unlock(&queue->mutex_dequeue); } queue->size++; if(queue->size < queue->max_size) /* Too much -> lock the pushes, will be unlocked by a pop */ { /* * This new addition made the queue full. So we will not unlock the enqueuers. * The dequeuers will do that when they see fit. (ie: queue not full anymore) */ mutex_unlock(&queue->mutex_enqueue); } /* * We are done here. */ mutex_unlock(&queue->mutex); return TRUE; } void* threaded_ringbuffer_try_peek(threaded_ringbuffer *queue) { /* * Ensure I'm allowed to dequeue (not empty and only one on it) */ if(!mutex_trylock(&queue->mutex_dequeue)) { return (void*)~0; } /* * Ensure I'm allowed to work on queue (only one working on it) */ if(!mutex_trylock(&queue->mutex)) { mutex_unlock(&queue->mutex_dequeue); return (void*)~0; } /* * Get the data from the read position, * and move the read position to the next slot * */ void* data = *queue->read_slot; mutex_unlock(&queue->mutex); mutex_unlock(&queue->mutex_dequeue); return data; } void* threaded_ringbuffer_peek(threaded_ringbuffer *queue) { /* * Ensure I'm allowed to dequeue (not empty and only one on it) */ mutex_lock(&queue->mutex_dequeue); /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); /* * Get the data from the read position, * and move the read position to the next slot * */ void* data = *queue->read_slot; mutex_unlock(&queue->mutex); mutex_unlock(&queue->mutex_dequeue); return data; } void* threaded_ringbuffer_dequeue(threaded_ringbuffer *queue) { /* * Ensure I'm allowed to dequeue (not empty and only one on it) */ mutex_lock(&queue->mutex_dequeue); /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); /* * Get the data from the read position, * and move the read position to the next slot * */ void* data = *queue->read_slot++; if(queue->read_slot == queue->buffer_limit) { queue->read_slot = queue->buffer; } if(queue->size == queue->max_size) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ mutex_unlock(&queue->mutex_enqueue); } queue->size--; if(queue->size > 0) /* at 0, locks the next dequeue */ { /* * This removal made the queue empty. So we will not unlock the dequeuers. * The enqueuers will do that when they see fit. (ie: queue not full anymore) */ mutex_unlock(&queue->mutex_dequeue); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void* threaded_ringbuffer_try_dequeue(threaded_ringbuffer *queue) { /* * Ensure I'm allowed to dequeue (not empty and only one on it) */ if(!mutex_trylock(&queue->mutex_dequeue)) { return (void*)~0; } /* * Ensure I'm allowed to work on queue (only one working on it) */ if(!mutex_trylock(&queue->mutex)) { mutex_unlock(&queue->mutex_dequeue); return (void*)~0; } /* * Get the data from the read position, * and move the read position to the next slot * */ void* data = *queue->read_slot++; if(queue->read_slot == queue->buffer_limit) { queue->read_slot = queue->buffer; } if(queue->size == queue->max_size) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ mutex_unlock(&queue->mutex_enqueue); } queue->size--; if(queue->size > 0) /* at 0, locks the next dequeue */ { /* * This removal made the queue empty. So we will not unlock the dequeuers. * The enqueuers will do that when they see fit. (ie: queue not full anymore) */ mutex_unlock(&queue->mutex_dequeue); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } u32 threaded_ringbuffer_dequeue_set(threaded_ringbuffer* queue, void** array, u32 array_size) { /* * Ensure I'm allowed to dequeue (not empty and only one on it) */ mutex_lock(&queue->mutex_dequeue); /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); /* * Get up to array_size times the data from the read position, * and move the read position to the next slot * */ bool unlock_enqueue = queue->size == queue->max_size; /* enqueue has just been locked -> schedule unlock */ u32 loops = MIN(queue->size, array_size); /* The amount we will be able to extract */ void ** const limit = &array[loops]; /* compute the limit so we only have one increment and one compare */ while(array < limit) { void* data = *queue->read_slot++; *array++ = data; if(queue->read_slot == queue->buffer_limit) { queue->read_slot = queue->buffer; } if(data == NULL) /* Break if a terminator is found*/ { loops -= limit - array; break; } } if(unlock_enqueue) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ mutex_unlock(&queue->mutex_enqueue); } queue->size -= loops; /* adjust the size */ if(queue->size > 0) /* at 0, locks the next dequeue */ { /* * This removal made the queue empty. So we will not unlock the dequeuers. * The enqueuers will do that when they see fit. (ie: queue not full anymore) */ mutex_unlock(&queue->mutex_dequeue); } /* * We are done here. */ mutex_unlock(&queue->mutex); return loops; /* Return the amount we got from the queue */ } void threaded_ringbuffer_wait_empty(threaded_ringbuffer *queue) { int size; for(;;) { mutex_lock(&queue->mutex); size = queue->size; mutex_unlock(&queue->mutex); if(size == 0) { break; } usleep(1); } } int threaded_ringbuffer_size(threaded_ringbuffer *queue) { int size; mutex_lock(&queue->mutex); size = queue->size; mutex_unlock(&queue->mutex); return size; } ya_result threaded_ringbuffer_set_maxsize(threaded_ringbuffer *queue, int max_size) { ya_result ret = SUCCESS; mutex_lock(&queue->mutex); if(max_size >= (int)queue->size) { void** tmp; MALLOC_OR_DIE(void**, tmp, sizeof(void*)* max_size, THREADED_QUEUE_RINGBUFFFER_TAG); /* * Copy from the read to the write position */ void** p = tmp; u32 count = queue->size; while(count-- > 0) { *p = *queue->read_slot++; if(queue->read_slot == queue->buffer_limit) { queue->read_slot = queue->buffer; } } /* * At this point ... * * tmp is the new "read" * p is the new "write", but it could be at the limit * */ free(queue->buffer); queue->buffer = tmp; queue->buffer_limit = &tmp[max_size]; queue->read_slot = tmp; if(p == queue->buffer_limit) { p = tmp; } queue->write_slot = p; queue->max_size = max_size; } mutex_unlock(&queue->mutex); return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/threaded_ringbuffer_cw.c0000644000000000000000000000013214505005532024156 xustar000000000000000030 mtime=1695812442.400981587 30 atime=1695812445.792030153 30 ctime=1695812494.727731011 yadifa-2.6.5-11201/lib/dnscore/src/threaded_ringbuffer_cw.c0000664000374500037450000003363514505005532024132 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/threaded_ringbuffer_cw.h" #define THREADED_QUEUE_RINGBUFFERCW_TAG 0x5743464247525154 /* TQRGBFCW */ /* * Note: * * If a mutex_init fails, it's because of a resource, memory or rights issue. * So the application will fail soon enough. * I still should check this and exit. * * mutex_lock will fail only if the current thread aleady owns the mutex * * mutex_unlock will fail only if the current thread does not owns the mutex * */ void threaded_ringbuffer_cw_init(threaded_ringbuffer_cw *queue, int max_size) { #if DEBUG memset(queue, 0xff, sizeof(threaded_ringbuffer_cw)); #endif MALLOC_OR_DIE(void**, queue->buffer, sizeof(void*) * max_size, THREADED_QUEUE_RINGBUFFERCW_TAG); queue->buffer_limit = &queue->buffer[max_size]; queue->write_slot = queue->buffer; queue->read_slot = queue->buffer; mutex_init(&queue->mutex); cond_init(&queue->cond_read); cond_init(&queue->cond_write); queue->max_size = max_size; queue->size = 0; } void threaded_ringbuffer_cw_finalize(threaded_ringbuffer_cw *queue) { /** * If the queue is not empty : too bad ! * * It's the responsibility of the caller to ensure the queue and set of listeners is empty. */ free(queue->buffer); queue->buffer = NULL; cond_finalize(&queue->cond_write); cond_finalize(&queue->cond_read); mutex_destroy(&queue->mutex); #if DEBUG memset(queue, 0xde, sizeof(threaded_ringbuffer_cw)); #endif } void threaded_ringbuffer_cw_enqueue(threaded_ringbuffer_cw *queue, void *constant_pointer) { assert(queue->max_size > 0); /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while( queue->size >= queue->max_size ) { cond_wait(&queue->cond_write, &queue->mutex); } /* * Set the data to the write position, * and move the write position to the next slot * */ /** * @note: "if(overflow) reset" is (much) faster than MOD(limit) */ *queue->write_slot++ = constant_pointer; if(queue->write_slot == queue->buffer_limit) { queue->write_slot = queue->buffer; } queue->size++; /* * We are done here, we can always signal the readers */ cond_notify(&queue->cond_read); mutex_unlock(&queue->mutex); } void threaded_ringbuffer_cw_enqueue_set(threaded_ringbuffer_cw *queue, void **constant_pointer_array, u32 count) { assert(queue->max_size > 0); assert(queue->max_size >= count); /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while( queue->size + count > queue->max_size ) { cond_wait(&queue->cond_write, &queue->mutex); } /* * Set the data to the write position, * and move the write position to the next slot * */ /** * @note: "if(overflow) reset" is (much) faster than MOD(limit) */ for(u32 i = 0; i < count; ++i) { *queue->write_slot++ = constant_pointer_array[i]; if(queue->write_slot == queue->buffer_limit) { queue->write_slot = queue->buffer; } } queue->size += count; /* * We are done here, we can always signal the readers */ cond_notify(&queue->cond_read); mutex_unlock(&queue->mutex); } bool threaded_ringbuffer_cw_try_enqueue(threaded_ringbuffer_cw* queue, void* constant_pointer) { /* * Ensure I'm allowed to work on queue (only one working on it) */ if(!mutex_trylock(&queue->mutex)) { return FALSE; } if( queue->size >= queue->max_size ) { mutex_unlock(&queue->mutex); return FALSE; } /* * Set the data to the write position, * and move the write position to the next slot * */ /** * @note: "if(overflow) reset" is (much) faster than MOD(limit) */ *queue->write_slot++ = constant_pointer; if(queue->write_slot == queue->buffer_limit) { queue->write_slot = queue->buffer; } queue->size++; /* * We are done here, we can always signal the readers */ cond_notify(&queue->cond_read); mutex_unlock(&queue->mutex); return TRUE; } void* threaded_ringbuffer_cw_peek(threaded_ringbuffer_cw *queue) { /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while( queue->size == 0 ) { cond_wait(&queue->cond_read,&queue->mutex); } /* * Get the data from the read position, * and move the read position to the next slot * */ void* data = *queue->read_slot; /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void* threaded_ringbuffer_cw_try_peek(threaded_ringbuffer_cw *queue) { mutex_lock(&queue->mutex); if( queue->size == 0 ) { mutex_unlock(&queue->mutex); return NULL; } /* * Get the data from the read position, * and move the read position to the next slot * */ void* data = *queue->read_slot; /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void* threaded_ringbuffer_cw_dequeue(threaded_ringbuffer_cw *queue) { /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while( queue->size == 0 ) { cond_wait(&queue->cond_read,&queue->mutex); } /* * Get the data from the read position, * and move the read position to the next slot * */ void* data = *queue->read_slot++; if(queue->read_slot == queue->buffer_limit) { queue->read_slot = queue->buffer; } if(queue->size-- == queue->max_size) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we can free (one of) them. * (They will however still be locked until the queue mutex is released) */ cond_notify(&queue->cond_write); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void* threaded_ringbuffer_cw_dequeue_with_timeout(threaded_ringbuffer_cw *queue, s64 timeout_us) { /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while( queue->size == 0 ) { if(cond_timedwait(&queue->cond_read,&queue->mutex, timeout_us) != 0) { mutex_unlock(&queue->mutex); return NULL; } } /* * Get the data from the read position, * and move the read position to the next slot * */ void* data = *queue->read_slot++; if(queue->read_slot == queue->buffer_limit) { queue->read_slot = queue->buffer; } if(queue->size-- == queue->max_size) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we can free (one of) them. * (They will however still be locked until the queue mutex is released) */ cond_notify(&queue->cond_write); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void* threaded_ringbuffer_cw_try_dequeue(threaded_ringbuffer_cw *queue) { mutex_lock(&queue->mutex); if( queue->size == 0 ) { mutex_unlock(&queue->mutex); return NULL; } /* * Get the data from the read position, * and move the read position to the next slot * */ void* data = *queue->read_slot++; if(queue->read_slot == queue->buffer_limit) { queue->read_slot = queue->buffer; } if(queue->size-- == queue->max_size) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ cond_notify(&queue->cond_write); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } u32 threaded_ringbuffer_cw_dequeue_set(threaded_ringbuffer_cw *queue, void **array, u32 array_size) { /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); while( queue->size == 0 ) { cond_wait(&queue->cond_read,&queue->mutex); } /* * Get up to array_size times the data from the read position, * and move the read position to the next slot * */ bool unlock_enqueue = queue->size == queue->max_size; /* enqueue has just been locked -> schedule unlock */ u32 loops = MIN(queue->size, array_size); /* The amount we will be able to extract */ void ** const limit = &array[loops]; /* compute the limit so we only have one increment and one compare */ while(array < limit) { void* data = *queue->read_slot++; *array++ = data; if(queue->read_slot == queue->buffer_limit) { queue->read_slot = queue->buffer; } if(data == NULL) /* Break if a terminator is found*/ { loops -= limit - array; break; } } queue->size -= loops; /* adjust the size */ if(unlock_enqueue) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ cond_notify(&queue->cond_write); } /* * We are done here. */ mutex_unlock(&queue->mutex); return loops; /* Return the amount we got from the queue */ } void threaded_ringbuffer_cw_wait_empty(threaded_ringbuffer_cw *queue) { int size; for(;;) { mutex_lock(&queue->mutex); size = queue->size; mutex_unlock(&queue->mutex); if(size == 0) { break; } usleep(1000); } } u32 threaded_ringbuffer_cw_size(threaded_ringbuffer_cw *queue) { u32 size; mutex_lock(&queue->mutex); size = queue->size; mutex_unlock(&queue->mutex); return size; } int threaded_ringbuffer_cw_room(threaded_ringbuffer_cw *queue) { int room; mutex_lock(&queue->mutex); room = queue->max_size - queue->size; mutex_unlock(&queue->mutex); return room; } ya_result threaded_ringbuffer_cw_set_maxsize(threaded_ringbuffer_cw *queue, int max_size) { ya_result ret = INVALID_ARGUMENT_ERROR; // can only grow mutex_lock(&queue->mutex); if(max_size >= (int)queue->size) { void** tmp; MALLOC_OR_DIE(void**, tmp, sizeof(void*) * max_size, THREADED_QUEUE_RINGBUFFERCW_TAG); /* * Copy from the read to the write position */ void** p = tmp; u32 count = queue->size; while(count-- > 0) { *p++ = *queue->read_slot++; // wrap when the end is reached if(queue->read_slot == queue->buffer_limit) { queue->read_slot = queue->buffer; } } /* * At this point ... * * tmp is the new "read" * p is the new "write", but it could be at the limit * */ free(queue->buffer); queue->buffer = tmp; queue->buffer_limit = &tmp[max_size]; queue->read_slot = tmp; if(p == queue->buffer_limit) { p = tmp; } queue->write_slot = p; queue->max_size = max_size; } ret = queue->max_size; mutex_unlock(&queue->mutex); return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/threaded_ringlist.c0000644000000000000000000000013114505005532023166 xustar000000000000000030 mtime=1695812442.449982289 30 atime=1695812445.794030182 29 ctime=1695812494.72973104 yadifa-2.6.5-11201/lib/dnscore/src/threaded_ringlist.c0000664000374500037450000003504014505005532023133 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup threading Threading, pools, queues, ... * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/threaded_ringlist.h" #ifndef DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #error "DNSCORE_HAS_MUTEX_DEBUG_SUPPORT not defined" #endif #define MUTEX_USE_SPINLOCK 0 #include "dnscore/mutex.h" #define THREADED_QUEUE_RINGLIST_TAG 0x54534c474e525154 /* TQRNGLST */ /* * The maximum number of nodes I should ever require is the queue size + 1 * * A good way to handle this is : * * Node allocator, node destroyer * * But the node allocator only allocates a node if none are free * And the node destroyer does not release a node but queue it instead. * * If I enforce the requirement that the allocation/destruction is done * by a single thread I could gain some cpu cycles. * * This reasoning is also valid for the thread_pool_task * */ typedef struct threaded_ringlist_node threaded_ringlist_node; struct threaded_ringlist_node { /* DO NOT MOVE THESE POINTERS */ threaded_ringlist_node *next; threaded_ringlist_node *prev; /* -------------------------- */ void* data; }; /* * Note: * * If a mutex_init fails, it's because of a resource, memory or rights issue. * So the application will fail soon enough. * I still should check this and exit. * * mutex_lock will fail only if the current thread aleady owns the mutex * * mutex_unlock will fail only if the current thread does not owns the mutex * */ void threaded_ringlist_init(threaded_ringlist *queue, int max_size) { queue->prev = (threaded_ringlist_node*)queue; queue->next = (threaded_ringlist_node*)queue; queue->pool = NULL; mutex_init(&queue->mutex); mutex_init(&queue->mutex_enqueue); mutex_init(&queue->mutex_dequeue); queue->max_size = max_size; queue->size = 0; mutex_lock(&queue->mutex_dequeue); } void threaded_ringlist_finalize(threaded_ringlist *queue) { threaded_ringlist_node* node; /** * If the queue is not empty : too bad ! * * It's the responsibility of the caller to ensure the queue and set of listeners is empty. */ mutex_lock(&queue->mutex); node = queue->next; queue->next = NULL; while(node != (threaded_ringlist_node*)queue) { threaded_ringlist_node* tmp; tmp = node; node = node->next; free(tmp); } node = queue->pool; queue->pool = NULL; while(node != NULL) { #if DEBUG assert(node->data == (void*)~0); #endif threaded_ringlist_node* tmp; tmp = node; node = node->next; free(tmp); } mutex_unlock(&queue->mutex); mutex_destroy(&queue->mutex); mutex_destroy(&queue->mutex_enqueue); mutex_destroy(&queue->mutex_dequeue); } void threaded_ringlist_enqueue(threaded_ringlist* queue, void* constant_pointer) { /* * Ensure I'm allowed to enqueue (only one enqueuer and queue not full) */ mutex_lock(&queue->mutex_enqueue); /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); threaded_ringlist_node* node = queue->pool; /* If there was a node in the pool : use it, else allocate a new one */ if(node != NULL) { queue->pool = node->next; } else { MALLOC_OBJECT_OR_DIE(node, threaded_ringlist_node, THREADED_QUEUE_RINGLIST_TAG); } node->prev = queue->prev; node->next = (threaded_ringlist_node*)queue; node->data = constant_pointer; queue->prev->next = node; queue->prev = node; if(queue->size == 0) { /* * The queue is empty : the dequeuers are waiting. * Since we will add something for them, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ mutex_unlock(&queue->mutex_dequeue); } queue->size++; if(queue->size < queue->max_size) /* Too much -> lock the pushes, will be unlocked by a pop */ { /* * This new addition made the queue full. So we will not unlock the enqueuers. * The dequeuers will do that when they see fit. (ie: queue not full anymore) */ mutex_unlock(&queue->mutex_enqueue); } /* * We are done here. */ mutex_unlock(&queue->mutex); } bool threaded_ringlist_try_enqueue(threaded_ringlist* queue, void* constant_pointer) { /* * Ensure I'm allowed to enqueue (only one enqueuer and queue not full) */ if(!mutex_trylock(&queue->mutex_enqueue)) { return FALSE; } /* * Ensure I'm allowed to work on queue (only one working on it) */ if(!mutex_trylock(&queue->mutex)) { mutex_unlock(&queue->mutex_enqueue); return FALSE; } threaded_ringlist_node* node = queue->pool; /* If there was a node in the pool : use it, else allocate a new one */ if(node != NULL) { queue->pool = node->next; } else { MALLOC_OBJECT_OR_DIE(node, threaded_ringlist_node, THREADED_QUEUE_RINGLIST_TAG); } node->prev = queue->prev; node->next = (threaded_ringlist_node*)queue; node->data = constant_pointer; queue->prev->next = node; queue->prev = node; if(queue->size == 0) { /* * The queue is empty : the dequeuers are waiting. * Since we will add something for them, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ mutex_unlock(&queue->mutex_dequeue); } queue->size++; if(queue->size < queue->max_size) /* Too much -> lock the pushes, will be unlocked by a pop */ { /* * This new addition made the queue full. So we will not unlock the enqueuers. * The dequeuers will do that when they see fit. (ie: queue not full anymore) */ mutex_unlock(&queue->mutex_enqueue); } /* * We are done here. */ mutex_unlock(&queue->mutex); return TRUE; } void* threaded_ringlist_peek(threaded_ringlist *queue) { threaded_ringlist_node* node; /* * Ensure I'm allowed to dequeue (not empty and only one on it) */ mutex_lock(&queue->mutex_dequeue); /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); node = queue->next; void* data = node->data; /* * We are done here. */ mutex_unlock(&queue->mutex); mutex_unlock(&queue->mutex_dequeue); return data; } void* threaded_ringlist_try_peek(threaded_ringlist *queue) { threaded_ringlist_node* node; /* * Ensure I'm allowed to dequeue (not empty and only one on it) */ if(!mutex_trylock(&queue->mutex_dequeue)) { return (void*)~0; } /* * Ensure I'm allowed to work on queue (only one working on it) */ if(!mutex_trylock(&queue->mutex)) { mutex_unlock(&queue->mutex_dequeue); return (void*)~0; } node = queue->next; void* data = node->data; /* * We are done here. */ mutex_unlock(&queue->mutex); mutex_unlock(&queue->mutex_dequeue); return data; } void* threaded_ringlist_dequeue(threaded_ringlist *queue) { threaded_ringlist_node* node; /* * Ensure I'm allowed to dequeue (not empty and only one on it) */ mutex_lock(&queue->mutex_dequeue); /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); node = queue->next; queue->next = node->next; node->next->prev = node->prev; void* data = node->data; #if DEBUG node->prev = (threaded_ringlist_node*)~0; node->data = (void*)~0; #endif /* Pool the node */ node->next = queue->pool; queue->pool = node; if(queue->size == queue->max_size) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ mutex_unlock(&queue->mutex_enqueue); } queue->size--; if(queue->size > 0) /* at 0, locks the next dequeue */ { /* * This removal made the queue empty. So we will not unlock the dequeuers. * The enqueuers will do that when they see fit. (ie: queue not full anymore) */ mutex_unlock(&queue->mutex_dequeue); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } void* threaded_ringlist_try_dequeue(threaded_ringlist *queue) { threaded_ringlist_node* node; /* * Ensure I'm allowed to dequeue (not empty and only one on it) */ if(!mutex_trylock(&queue->mutex_dequeue)) { return (void*)~0; } /* * Ensure I'm allowed to work on queue (only one working on it) */ if(!mutex_trylock(&queue->mutex)) { mutex_unlock(&queue->mutex_dequeue); return (void*)~0; } node = queue->next; queue->next = node->next; node->next->prev = node->prev; void* data = node->data; #if DEBUG node->prev = (threaded_ringlist_node*)~0; node->data = (void*)~0; #endif /* Pool the node */ node->next = queue->pool; queue->pool = node; if(queue->size == queue->max_size) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ mutex_unlock(&queue->mutex_enqueue); } queue->size--; if(queue->size > 0) /* at 0, locks the next dequeue */ { /* * This removal made the queue empty. So we will not unlock the dequeuers. * The enqueuers will do that when they see fit. (ie: queue not full anymore) */ mutex_unlock(&queue->mutex_dequeue); } /* * We are done here. */ mutex_unlock(&queue->mutex); return data; } u32 threaded_ringlist_dequeue_set(threaded_ringlist* queue, void** array, u32 array_size) { threaded_ringlist_node* node; /* * Ensure I'm allowed to dequeue (not empty and only one on it) */ mutex_lock(&queue->mutex_dequeue); /* * Ensure I'm allowed to work on queue (only one working on it) */ mutex_lock(&queue->mutex); bool unlock_enqueue = queue->size == queue->max_size; /* enqueue has just been locked -> schedule unlock */ u32 loops = MIN(queue->size, array_size); /* The amount we will be able to extract */ void ** const limit = &array[loops]; while(array < limit) { node = queue->next; queue->next = node->next; node->next->prev = node->prev; *array++ = node->data; /* Pool the node */ node->next = queue->pool; queue->pool = node; if(node->data == NULL) /* Break if a terminator is found*/ { loops -= limit - array; break; } } if(unlock_enqueue) /* enqueue has just been locked -> unlock */ { /* * The queue is full : the queuers are waiting. * Since we will are removing something, we car free (one of) them. * (They will however still be locked until the queue mutex is released) */ mutex_unlock(&queue->mutex_enqueue); } queue->size -= loops; if(queue->size > 0) /* at 0, locks the next dequeue */ { /* * This removal made the queue empty. So we will not unlock the dequeuers. * The enqueuers will do that when they see fit. (ie: queue not full anymore) */ mutex_unlock(&queue->mutex_dequeue); } /* * We are done here. */ mutex_unlock(&queue->mutex); return loops; } void threaded_ringlist_wait_empty(threaded_ringlist *queue) { int size; for(;;) { mutex_lock(&queue->mutex); size = queue->size; mutex_unlock(&queue->mutex); if(size == 0) { break; } usleep(1); } } int threaded_ringlist_size(threaded_ringlist *queue) { int size; mutex_lock(&queue->mutex); size = queue->size; mutex_unlock(&queue->mutex); return size; } ya_result threaded_ringlist_set_maxsize(threaded_ringlist *queue, int max_size) { mutex_lock(&queue->mutex); queue->max_size = max_size; mutex_unlock(&queue->mutex); return SUCCESS; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/timeformat.c0000644000000000000000000000013214505005532021643 xustar000000000000000030 mtime=1695812442.440982159 30 atime=1695812445.794030182 30 ctime=1695812494.731731068 yadifa-2.6.5-11201/lib/dnscore/src/timeformat.c0000664000374500037450000004104214505005532021606 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup format C-string formatting * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include /* Required for BSD */ #include #include #include #include //#include "dnscore/dnscore-config.h" #include "dnscore/rfc.h" #include "dnscore/ctrl-rfc.h" #include "dnscore/format.h" #include "dnscore/dnsname.h" #include "dnscore/base32hex.h" #include "dnscore/dnsformat.h" #include "dnscore/host_address.h" #define NULL_STRING_SUBSTITUTE (u8*)"(NULL)" #define NULL_STRING_SUBSTITUTE_LEN 6 /*(sizeof(NULL_STRING_SUBSTITUTE)-1)*/ #define PORT_SEPARATOR '#' #define PORT_SEPARATOR_V4 PORT_SEPARATOR #define PORT_SEPARATOR_V6 PORT_SEPARATOR static const char dateseparator[1] = {'-'}; static const char timeseparator[1] = {':'}; static const char fracseparator[1] = {'.'}; static const char datetimeseparator[1] = {' '}; static const char utcsuffix[1] = {'Z'}; /** * dtus * * @note 64 bits epoch written up to the us */ void datetimeus_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u64 epoch_us = (u64)(intptr)val; time_t epoch = (time_t)(epoch_us / 1000000); u32 us = (u32)(epoch_us % 1000000); struct tm t; gmtime_r(&epoch, &t); format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mon + 1 , stream, 2, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mday , stream, 2, '0', FALSE); output_stream_write(stream, datetimeseparator, 1); format_dec_u64(t.tm_hour , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_min , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_sec , stream, 2, '0', FALSE); output_stream_write(stream, fracseparator, 1); format_dec_u64(us , stream, 6, '0', FALSE); output_stream_write(stream, utcsuffix, 1); } void localdatetimeus_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u64 epoch_us = (u64)(intptr)val; time_t epoch = (time_t)(epoch_us / 1000000); u32 us = (u32)(epoch_us % 1000000); struct tm t; localtime_r(&epoch, &t); format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mon + 1 , stream, 2, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mday , stream, 2, '0', FALSE); output_stream_write(stream, datetimeseparator, 1); format_dec_u64(t.tm_hour , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_min , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_sec , stream, 2, '0', FALSE); output_stream_write(stream, fracseparator, 1); format_dec_u64(us , stream, 6, '0', FALSE); } static format_handler_descriptor datetimeus_format_handler_descriptor = { "dtus", 4, datetimeus_format_handler_method }; /** * dtms * * @note 64 bits epoch written up to the ms */ void datetimems_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u64 epoch_us = (u64)(intptr)val; time_t epoch = (time_t)(epoch_us / 1000000); u32 ms = (u32)(epoch_us % 1000000); ms /= 1000; struct tm t; gmtime_r(&epoch, &t); format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mon + 1 , stream, 2, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mday , stream, 2, '0', FALSE); output_stream_write(stream, datetimeseparator, 1); format_dec_u64(t.tm_hour , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_min , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_sec , stream, 2, '0', FALSE); output_stream_write(stream, fracseparator, 1); format_dec_u64(ms , stream, 3, '0', FALSE); } static format_handler_descriptor datetimems_format_handler_descriptor = { "dtms", 4, datetimems_format_handler_method }; /** * dts * * @note 64 bits epoch written up to the s */ void datetime_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u64 epoch_us = (u64)(intptr)val; time_t epoch = (time_t)(epoch_us / 1000000); struct tm t; gmtime_r(&epoch, &t); format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mon + 1 , stream, 2, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mday , stream, 2, '0', FALSE); output_stream_write(stream, datetimeseparator, 1); format_dec_u64(t.tm_hour , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_min , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_sec , stream, 2, '0', FALSE); } static format_handler_descriptor datetime_format_handler_descriptor = { "dts", 3, datetime_format_handler_method }; /** * dts * * @note 64 bits epoch written up to the s */ void localdatetime_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u64 epoch_us = (u64)(intptr)val; time_t epoch = (time_t)(epoch_us / 1000000); struct tm t; gmtime_r(&epoch, &t); format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mon + 1 , stream, 2, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mday , stream, 2, '0', FALSE); output_stream_write(stream, datetimeseparator, 1); format_dec_u64(t.tm_hour , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_min , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_sec , stream, 2, '0', FALSE); } static format_handler_descriptor localdatetime_format_handler_descriptor = { "ldts", 4, localdatetime_format_handler_method }; /** * date * * @note 64 bits epoch written up to the day */ void date_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u64 epoch_us = (u64)(intptr)val; time_t epoch = (time_t)(epoch_us / 1000000); struct tm t; gmtime_r(&epoch, &t); format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mon + 1 , stream, 2, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mday , stream, 2, '0', FALSE); } static format_handler_descriptor date_format_handler_descriptor = { "date", 4, date_format_handler_method }; /** * time * * @note 64 bits with only HH:MM:SS */ void time_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u64 epoch_us = (u64)(intptr)val; time_t epoch = (time_t)(epoch_us / 1000000); struct tm t; gmtime_r(&epoch, &t); format_dec_u64(t.tm_hour , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_min , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_sec , stream, 2, '0', FALSE); } static format_handler_descriptor time_format_handler_descriptor = { "time", 4, time_format_handler_method }; /** * epoch * * @note 32 bits epoch written up to the s */ void epoch_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; time_t epoch = (time_t)(intptr)val; struct tm t; gmtime_r(&epoch, &t); format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mon + 1 , stream, 2, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mday , stream, 2, '0', FALSE); output_stream_write(stream, datetimeseparator, 1); format_dec_u64(t.tm_hour , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_min , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_sec , stream, 2, '0', FALSE); output_stream_write(stream, utcsuffix, 1); } void localepoch_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; time_t epoch = (time_t)(intptr)val; struct tm t; localtime_r(&epoch, &t); format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mon + 1 , stream, 2, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mday , stream, 2, '0', FALSE); output_stream_write(stream, datetimeseparator, 1); format_dec_u64(t.tm_hour , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_min , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_sec , stream, 2, '0', FALSE); } static format_handler_descriptor epoch_format_handler_descriptor = { "epoch", 5, epoch_format_handler_method }; /** * epoch where value 0 prints nothing * * @note 32 bits epoch written up to the s */ void epochz_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; time_t epoch = (time_t)(intptr)val; if(epoch != 0) { struct tm t; gmtime_r(&epoch, &t); format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mon + 1 , stream, 2, '0', FALSE); output_stream_write(stream, dateseparator, 1); format_dec_u64(t.tm_mday , stream, 2, '0', FALSE); output_stream_write(stream, datetimeseparator, 1); format_dec_u64(t.tm_hour , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_min , stream, 2, '0', FALSE); output_stream_write(stream, timeseparator, 1); format_dec_u64(t.tm_sec , stream, 2, '0', FALSE); } else { while(padding > 0) { output_stream_write(stream, "-", 1); --padding; } } } static format_handler_descriptor epochz_format_handler_descriptor = { "epochz", 6, epochz_format_handler_method }; /** * epoch * * @note 32 bits epoch written up to the s */ void packedepoch_format_handler_method(const void *restrict val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; time_t epoch = (time_t)(intptr)val; struct tm t; gmtime_r(&epoch, &t); format_dec_u64(t.tm_year + 1900, stream, 4, '0', FALSE); format_dec_u64(t.tm_mon + 1 , stream, 2, '0', FALSE); format_dec_u64(t.tm_mday , stream, 2, '0', FALSE); format_dec_u64(t.tm_hour , stream, 2, '0', FALSE); format_dec_u64(t.tm_min , stream, 2, '0', FALSE); format_dec_u64(t.tm_sec , stream, 2, '0', FALSE); // DO NOT ADD A SUFFIX HERE } static format_handler_descriptor packedepoch_format_handler_descriptor = { "packedepoch", 11, packedepoch_format_handler_method }; static bool timeformat_class_init_done = FALSE; void timeformat_class_init() { if(timeformat_class_init_done) { return; } timeformat_class_init_done = TRUE; format_class_init(); // 64 bits format_registerclass(&datetimeus_format_handler_descriptor); format_registerclass(&datetimems_format_handler_descriptor); format_registerclass(&datetime_format_handler_descriptor); format_registerclass(&date_format_handler_descriptor); format_registerclass(&time_format_handler_descriptor); format_registerclass(&localdatetime_format_handler_descriptor); // 32 bits format_registerclass(&epoch_format_handler_descriptor); format_registerclass(&epochz_format_handler_descriptor); format_registerclass(&packedepoch_format_handler_descriptor); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/timems.c0000644000000000000000000000013214505005532020772 xustar000000000000000030 mtime=1695812442.422981902 30 atime=1695812445.793030168 30 ctime=1695812494.733731097 yadifa-2.6.5-11201/lib/dnscore/src/timems.c0000664000374500037450000005217514505005532020746 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnscoretools Generic Tools * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include "dnscore/timems.h" static int DAYS_IN_MONTH_NORM[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; static int DAYS_IN_MONTH_LEAP[12] = {31,29,31,30,31,30,31,31,30,31,30,31}; /// @note 20150326 edf -- timegm is not portable (Solaris) in the end, implementing one seemed the only choice /** * This implementation is based on the formula found in: * * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15 * 4.15 Seconds Since the Epoch * * It only cares on the Year, Month, Day, Hour, Minute and Second fields of struct tm (the one we are really caring about) * It's a constant-time implementation. * * I don't see an obvious way to make it faster expect having the year values pre-calculated for the next 30+ years * (This would spare a few divs and a mult.) * * If I improve it further, it may be a replacement on the timegm() dependency. * */ // J F M A M J J A S O N D // 31 28 31 30 31 30 31 31 30 31 30 31 #define MDAY_FIX(d_) ((d_)-1) static int timegm_mdays_norm[12] = {MDAY_FIX(0),MDAY_FIX( 31),MDAY_FIX( 59),MDAY_FIX( 90),MDAY_FIX( 120),MDAY_FIX( 151),MDAY_FIX( 181),MDAY_FIX( 212),MDAY_FIX( 243),MDAY_FIX( 273),MDAY_FIX( 304),MDAY_FIX( 334)}; // MDAY_FIX(365) static int timegm_mdays_leap[12] = {MDAY_FIX(0),MDAY_FIX( 31),MDAY_FIX( 60),MDAY_FIX( 91),MDAY_FIX( 121),MDAY_FIX( 152),MDAY_FIX( 182),MDAY_FIX( 213),MDAY_FIX( 244),MDAY_FIX( 274),MDAY_FIX( 305),MDAY_FIX( 335)}; // MDAY_FIX(366) static char time_day_of_week[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri","Sat"}; static char time_month_of_year[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; /** * Sun to Sat * * @param day * @return A 3 letters name followed by a zero */ const char * time_get_day_of_week_name(int day) { if(day >= 0 && day < 7) { return time_day_of_week[day]; } else { return NULL; } } /** * Jan to Dec * * @param month * @return A 3 letters name followed by a zero */ const char * time_get_month_of_year_name(int month) { if(month >= 0 && month < 12) { return time_month_of_year[month]; } else { return NULL; } } static char* time_write_day_time_number(char *buffer, int value) { yassert(value >= 0 && value <= 99); if(value >= 10) { *buffer++ = '0' + (value / 10); value %= 10; } *buffer++ = '0' + value; return buffer; } static char* time_write_year_time_number(char *buffer, int value) { yassert(value >= 0 && value <= 9999); if(value >= 1000) { *buffer++ = '0' + (value / 1000); value %= 1000; } if(value >= 100) { *buffer++ = '0' + (value / 100); value %= 100; } if(value >= 10) { *buffer++ = '0' + (value / 10); value %= 10; } *buffer++ = '0' + value; return buffer; } static char* time_write_zero_padded_time_number(char *buffer, int value) { yassert(value >= 0 && value <= 99); if(value >= 10) { *buffer++ = '0' + (value / 10); value %= 10; } else { *buffer++ = '0'; } *buffer++ = '0' + value; return buffer; } /** * Convert time structure into the text format defined by RFC5322 (GMT) * Does put a '\0' at the end of the buffer. * Requires a buffer of at least 29 bytes. * * @param epoch * @param buffer * @param buffer_size * * @return the number of chars written or an error */ ya_result time_tm_as_rfc5322(const struct tm *t, char *buffer, size_t buffer_size) { if(buffer_size >= 29) { const char * const day = time_get_day_of_week_name(t->tm_wday); if(day == NULL) { return INVALID_ARGUMENT_ERROR; } const char * const month = time_get_month_of_year_name(t->tm_mon); if(month == NULL) { return INVALID_ARGUMENT_ERROR; } memcpy(buffer, day, 3); memcpy(&buffer[3], ", ", 2); char *p = time_write_day_time_number(&buffer[5], t->tm_mday); *p++ = ' '; memcpy(buffer, month, 3); *p++ = ' '; p = time_write_year_time_number(p, t->tm_year + 1900); *p++ = ' '; p = time_write_zero_padded_time_number(p, t->tm_hour); *p++ = ':'; p = time_write_zero_padded_time_number(p, t->tm_min); *p++ = ':'; p = time_write_zero_padded_time_number(p, t->tm_sec); memcpy(p, " GMT" , 4); p += 4; return p - buffer; } else { return BUFFER_WOULD_OVERFLOW; } } /** * Convert epoch into the text format defined by RFC5322 (GMT) * Does put a '\0' at the end of the buffer. * Requires a buffer of at least 29 bytes. * * @param epoch * @param buffer * @param buffer_size * * @return the number of chars written or an error */ ya_result time_epoch_as_rfc5322(time_t epoch, char *buffer, size_t buffer_size) { struct tm t; gmtime_r(&epoch, &t); ya_result ret = time_tm_as_rfc5322(&t, buffer, buffer_size); return ret; } time_t timegm_internal(struct tm *tv) { time_t ret; if( (tv->tm_year < 0) || (((u32)tv->tm_mon) > 11) || (((u32)tv->tm_mday - 1) > 31 - 1) || (((u32)tv->tm_hour) > 60) || (((u32)tv->tm_min) > 59) || (((u32)tv->tm_sec) > 60) ) { return -1; } int yyyy = (tv->tm_year + 1900); int yday; if(((yyyy & 3) == 0) && (((yyyy % 100) != 0) || ((yyyy % 400) == 0))) { yday = timegm_mdays_leap[tv->tm_mon]; } else { yday = timegm_mdays_norm[tv->tm_mon]; } yday += tv->tm_mday; ret = tv->tm_sec + tv->tm_min * 60 + tv->tm_hour * 3600 + ( yday + ((tv->tm_year-69)/4) - ((tv->tm_year-1)/100) + ((tv->tm_year+299)/400) ) * 86400 + (tv->tm_year-70) * 31536000; return ret; } /* * Return the time in ms */ s64 timeus() { struct timeval tv; gettimeofday(&tv, NULL); s64 r = tv.tv_sec; r *= 1000000LL; r += tv.tv_usec; return r; } s64 timeus_and_s(s32 *seconds_ptr) { struct timeval tv; gettimeofday(&tv, NULL); *seconds_ptr = tv.tv_sec; s64 r = tv.tv_sec; r *= 1000000LL; r += tv.tv_usec; return r; } s64 timems() { struct timeval tv; gettimeofday(&tv, NULL); s64 r = tv.tv_sec; r *= 1000; r += tv.tv_usec / 1000; return r; } /* * Wait until the ms is incremented, then return the time in ms */ s64 timems_new() { s64 t; s64 tms; s64 ttr; t = timeus(); tms = t / 1000; do { usleep(MIN(1000 - (tms % 1000), 1)); ttr = timeus() / 1000; } while(ttr == tms); return ttr; } #define USLEEP_LIMIT 0xffffffff //#define USLEEP_LIMIT 1000000 /** * usleep only support a limited range of time (sometimes 2^32 us, sometimes < 1 s) * This wrapper ensures time supported is up to 4294967295.000000 seconds * * @param us the number of microseconds to wait for, can range from 0 to 4294967295000000 micro seconds */ void usleep_ex(u64 us_) { s64 us = (s64)us_; s64 now = timeus(); s64 limit = now + us; if(us >= USLEEP_LIMIT) { do { sleep(us / 1000000); now = timeus(); us = limit - now; } while(us >= USLEEP_LIMIT); } // us is the remaining us to wait for while(us > 0) { usleep(us); now = timeus(); us = limit - now; } } void usleep_until(s64 epoch_us) { s64 now = timeus(); while(now < epoch_us) { usleep_ex(epoch_us - now); now = timeus(); } } #if __unix__ time_t mkgmtime(const struct tm *tm_) { #if defined __FreeBSD__ || defined __OpenBSD__ || _BSD_SOURCE || _SVID_SOURCE struct tm tm_copy = *tm_; time_t ret = timegm(&tm_copy); #else struct tm tm; memcpy(&tm, tm_, sizeof(struct tm)); #if __unix__ tm.tm_zone = NULL; tm.tm_gmtoff = 0; #endif time_t ret = mktime(&tm); ret -= timezone; #endif // __FREEBSD__ return ret; } #else time_t mkgmtime(const struct tm* tm_) { return _mkgmtime(tm_); } #endif bool time_is_leap_year(int y) { return (((y & 3) == 0) && (((y % 100) != 0) || ((y % 400) == 0))); } int time_days_in_month(int y, int m) { yassert((m >= 0) &&( m < 12) && (y > 1900)); if(!time_is_leap_year(y)) { return DAYS_IN_MONTH_NORM[m]; } else { return DAYS_IN_MONTH_LEAP[m]; } } /** * Retrieves the first day of the month. * * 0 is Sunday * * @param year 0-based * @param month 0-based * @return the number of the day of the month or an error code */ int time_first_day_of_month(int year, int month) { yassert((month >= 0) &&( month < 12) && (year > 1900)); struct tm tm; ZEROMEMORY(&tm, sizeof(struct tm)); tm.tm_mday = 1; tm.tm_mon = month; tm.tm_year = year - 1900; time_t epoch = mkgmtime(&tm); gmtime_r(&epoch, &tm); return tm.tm_wday; } static s64 timeus_offset = 0; /** * Returns timeus() - offset * Used to fake the current time. */ s64 timeus_with_offset() { return timeus() + timeus_offset; } /** * Sets the offset of the time returned by timeus_with_offset() */ void timeus_set_offset(s64 us) { timeus_offset = us; } /** * Internal tool function for timeus_from_smarttime * Tells if a name starts by another. * * @param singular the name to match * @param name the matching name * @param name_limit points after the last letter of the matching name * * @return SUCCESS if it's a match, else PARSEDATE_ERROR * * e.g.: "seconds", "sec", ... => SUCCESS * e.g.: "seconds", "msec", ... => PARSEDATE_ERROR */ static ya_result timeus_tools_unit_name_check(const char* singular, const char* name, const char* name_limit) { int n = name_limit - name; for(int i = 1; i < n; ++i) { if(singular[i] != name[i]) { if(name[i] == '\0') { return SUCCESS; } else { return PARSEDATE_ERROR; } } } return SUCCESS; } /** * Parses a text as a date/time and converts it to an epoch in microseconds. * * yesterday * now * tomorrow * +1y +1year +1years (months,weeks,days,seconds) * -1y -1year -1years (months,weeks,days,seconds) * 2019-04-16 * 2019-04-16_12:00:00.123456 * 20190416 * 20190416120000123456 * */ s64 timeus_from_smarttime_ex(const char *text, s64 now) { s64 epoch = 0; s64 relative = 0; ya_result ret; text = parse_skip_spaces(text); if(*text == '+') { relative = 1; ++text; } else if(*text == '-') { relative = -1; ++text; } if(isalpha(*text)) { // keyword if(memcmp(text, "now", 3) == 0) { //relative = 0; epoch = now; return epoch; } else if(memcmp(text, "tomorrow", 8) == 0) { //relative = 0; epoch = now + ONE_SECOND_US * 86400; return epoch; } else if(memcmp(text, "yesterday", 9) == 0) { //relative = 0; epoch = now - ONE_SECOND_US * 86400; return epoch; } else { return CONFIG_PARSE_UNKNOWN_KEYWORD; } } if(isdigit(*text)) { if(relative) { // integer const char *limit = parse_skip_digits(text); size_t size = limit - text; s64 value; if(FAIL(ret = parse_u64_check_range_len_base10(text, size, (u64*)&value, 0, 504921600))) // 0 to 16 years expressed in seconds { return ret; } epoch = value * relative; // multiplier text = limit; if(*text != '\0') { limit += strlen(limit); switch(*text) { case 's': { if(FAIL(ret = timeus_tools_unit_name_check("seconds", text, limit))) { return ret; } epoch *= ONE_SECOND_US; break; } case 'h': { if(FAIL(ret = timeus_tools_unit_name_check("hours", text, limit))) { return ret; } epoch *= ONE_SECOND_US; break; } case 'd': // days { if(FAIL(ret = timeus_tools_unit_name_check("days", text, limit))) { return ret; } epoch *= 86400LL * ONE_SECOND_US; break; } case 'w': // weeks { if(FAIL(ret = timeus_tools_unit_name_check("weeks", text, limit))) { return ret; } epoch *= 7LL * 86400LL * ONE_SECOND_US; break; } case 'm': // months { if(FAIL(ret = timeus_tools_unit_name_check("months", text, limit))) { if(FAIL(ret = timeus_tools_unit_name_check("minutes", text, limit))) { return ret; } else { epoch *= 60LL * ONE_SECOND_US; } } else { epoch *= 31LL * 86400LL * ONE_SECOND_US; } break; } case 'y': // years { if(FAIL(ret = timeus_tools_unit_name_check("years", text, limit))) { return ret; } epoch *= 366LL * 86400LL * ONE_SECOND_US; break; } default: { return PARSEDATE_ERROR; } } } else { epoch *= ONE_SECOND_US; } epoch += now; return epoch; } else { // read 4 digits, skip non digits // read 2 digits, skip non digits // read 2 digits, skip non digits // this is an acceptable value, but if there is more // read 2 digits, skip non digits // read 2 digits, skip non digits // read 2 digits, skip non digits // this is an acceptable value, but if there is more // read up to 6 digits u32 year = 0, month = 0, day = 0; u32 hours = 0, minutes = 0, seconds = 0; u32 microseconds = 0; // parse year, month and day if(FAIL(ret = parse_u32_check_range_len_base10(text, 4, &year, 1970, 2034))) { return ret; } text += 4; text = parse_skip_nondigits(text); if(FAIL(ret = parse_u32_check_range_len_base10(text, 2, &month, 1, 12))) { return ret; } text += 2; text = parse_skip_nondigits(text); if(FAIL(ret = parse_u32_check_range_len_base10(text, 2, &day, 1, 31))) { return ret; } text += 2; // skip blanks // if the end of the text hasn't been reached then start parsing hours, minutes and seconds text = parse_skip_spaces(text); if(*text != 0) { text = parse_skip_nondigits(text); if(*text != '\0') { if(FAIL(ret = parse_u32_check_range_len_base10(text, 2, &hours, 0, 23))) { return ret; } text += 2; text = parse_skip_nondigits(text); } if(*text != '\0') { if(FAIL(ret = parse_u32_check_range_len_base10(text, 2, &minutes, 0, 59))) { return ret; } text += 2; text = parse_skip_nondigits(text); } if(*text != '\0') { if(FAIL(ret = parse_u32_check_range_len_base10(text, 2, &seconds, 0, 59))) { return ret; } text += 2; } // skip blanks // if the end of the text hasn't been reached then start parsing fractional time text = parse_skip_spaces(text); if(*text != 0) { text = parse_skip_nondigits(text); int digits = 6; while((digits > 0) && isdigit(*text)) { microseconds *= 10; microseconds += *text - '0'; ++text; --digits; } while(digits > 0) { microseconds *= 10; --digits; } } } struct tm tm; memset(&tm, 0, sizeof(struct tm)); tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day - 1; tm.tm_hour = hours; tm.tm_min = minutes; tm.tm_sec = seconds; time_t t = timegm(&tm); epoch = t; epoch *= ONE_SECOND_US; epoch += microseconds; return epoch; } } return PARSEDATE_ERROR; } /** * Parses a text as a date/time and converts it to an epoch in microseconds. * * yesterday * now * tomorrow * +1y +1year +1years (months,weeks,days,seconds) * -1y -1year -1years (months,weeks,days,seconds) * 2019-04-16 * 2019-04-16_12:00:00.123456 * 20190416 * 20190416120000123456 * */ s64 timeus_from_smarttime(const char *text) { s64 ret; ret = timeus_from_smarttime_ex(text, timeus()); return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/typebitmap.c0000644000000000000000000000013214505005532021652 xustar000000000000000030 mtime=1695812442.398981558 30 atime=1695812445.792030153 30 ctime=1695812494.735731125 yadifa-2.6.5-11201/lib/dnscore/src/typebitmap.c0000664000374500037450000002270514505005532021622 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include "dnscore/rfc.h" #include "dnscore/typebitmap.h" /* * Call this with the context->type_bitmap_field set */ void type_bit_maps_write(const type_bit_maps_context *context, u8 *output) { /* No types at all ? Should NOT have been called */ //yassert(context->type_bit_maps_size > 2); const u8* type_bitmap_field = context->type_bitmap_field; const u8* window_size = context->window_size; for(s32 i = 0; i <= context->last_type_window; i++) { u8 bytes = window_size[i]; if(bytes == 0) { continue; } *output++ = i; *output++ = bytes; u32 wo = i << 5; /* 256 bits = 32 bytes = 2^5 */ u32 wo_limit = wo + bytes; for(; wo < wo_limit; wo++) { *output++ = type_bitmap_field[wo]; } } } s32 type_bit_maps_expand(type_bit_maps_context* context, u8* type_bitmap, u32 size) { const u8 * const limit = type_bitmap + size; s32 last_type = -1; while(type_bitmap < limit) { u8 wn = *type_bitmap++; last_type = wn; u8 ws = *type_bitmap++; if(ws == 0) /* Blocks with no types present MUST NOT be included */ { continue; } u8* wp = &context->type_bitmap_field[wn << 8]; context->window_size[wn] = MAX(context->window_size[wn], ws); while(ws-- > 0) { *wp++ = *type_bitmap++; } } context->last_type_window = MAX(last_type >> 8, context->last_type_window); return last_type; } bool type_bit_maps_merge(type_bit_maps_context* context, u8* type_bitmap_a, u32 a_size, u8* type_bitmap_b, u32 b_size) { if(a_size == b_size) { if(memcmp(type_bitmap_a, type_bitmap_b, a_size) == 0) { return FALSE; /* Nothing to do. Both bitmaps are equals */ } } u8* type_bitmap_field = context->type_bitmap_field; u8* window_size = context->window_size; ZEROMEMORY(window_size, sizeof(context->window_size)); ZEROMEMORY(type_bitmap_field, sizeof(context->type_bitmap_field)); s32 last_type_a = type_bit_maps_expand(context, type_bitmap_a, a_size); s32 last_type_b = type_bit_maps_expand(context, type_bitmap_b, b_size); u32 type_bit_maps_size = 0; s32 last_type_window = MAX(last_type_a, last_type_b); for(s32 i = 0; i <= last_type_window; i++) { u8 ws = window_size[i]; if(ws > 0) { type_bit_maps_size += 1 + 1 + ws; } } return TRUE; } void type_bit_maps_output_stream_write(const type_bit_maps_context* context, output_stream* os) { /* No types at all */ if(context->type_bit_maps_size == 0) { return; } const u8* type_bitmap_field = context->type_bitmap_field; const u8* window_size = context->window_size; for(s32 i = 0; i <= context->last_type_window; i++) { u8 bytes = window_size[i]; if(bytes > 0) { output_stream_write_u8(os, i); output_stream_write_u8(os, bytes); output_stream_write(os, &type_bitmap_field[i << 5], bytes); } } } bool type_bit_maps_gettypestatus(u8* packed_type_bitmap, u32 size, u16 type) { u8 window_index = (type >> 8); /* Skip to the right window */ while(size > 2) { u8 current_index = *packed_type_bitmap++; u8 current_size = *packed_type_bitmap++; if(current_index >= window_index) { if(current_index == window_index) { u32 byte_offset = (type >> 3); if(byte_offset < current_size) { return (packed_type_bitmap[byte_offset] & (0x80 >> (type & 7))) != 0; } } break; } size -= 2; size -= current_size; packed_type_bitmap += current_size; } return FALSE; } /* * Force RRSIG: because the signatures could not be available yet. * Force NSEC: because the NSEC record is not available at first init. * */ void type_bit_maps_init(type_bit_maps_context *context) { //context->last_type_window = 0; context->type_bit_maps_size = 0; //ZEROMEMORY(context, sizeof(type_bit_maps_context)); context->last_type_window = -1; } void type_bit_maps_set_type(type_bit_maps_context *context, u16 rtype) { u8 *type_bitmap_field = context->type_bitmap_field; u8 *window_size = context->window_size; s32 last_type_window = context->last_type_window; // Network bit order rtype = (u16)ntohs(rtype); const s32 type_window = rtype >> 8; // clear additional bytes if needed if(type_window > last_type_window) { s32 length = type_window - last_type_window; ZEROMEMORY(&window_size[last_type_window + 1], length); ZEROMEMORY(&type_bitmap_field[(last_type_window + 1) << 5], length << 5); last_type_window = type_window; context->last_type_window = last_type_window; } const u8 mask = 1 << (7 - (rtype & 7)); type_bitmap_field[rtype >> 3] |= mask; u8 new_window_size = ((rtype & 0xf8) >> 3) + 1; if(new_window_size > window_size[type_window]) { window_size[type_window] = new_window_size; } // if the bit is cleared, increase the window size } void type_bit_maps_clear_type(type_bit_maps_context *context, u16 rtype) { u8 *type_bitmap_field = context->type_bitmap_field; u8 *window_size = context->window_size; /* Network bit order */ rtype = (u16)ntohs(rtype); const u8 mask = 1 << (7 - (rtype & 7)); int rtype_byte_offset = rtype >> 3; int rtype_window_offset = rtype >> 8; if((type_bitmap_field[rtype_byte_offset] & mask) == 0) { type_bitmap_field[rtype_byte_offset] &= ~mask; s8 ws = window_size[rtype_window_offset]; u8 *window_base = &type_bitmap_field[rtype_byte_offset & 0xf8]; while((ws > 0) && (window_base[ws] == 0)) { --ws; } window_size[rtype_window_offset] = ws; if(ws == 0) { while(rtype_window_offset >= 0) { if(window_size[rtype_window_offset] > 0) { break; } } } context->last_type_window = MAX(rtype_window_offset, context->last_type_window); } } u16 type_bit_maps_update_size(type_bit_maps_context *context) { const u8 *window_size = context->window_size; u32 type_bit_maps_size = 0; for(s32 i = 0; i <= context->last_type_window; i++) { u8 ws = window_size[i]; if(ws > 0) { type_bit_maps_size += 1 + 1 + ws; } } context->type_bit_maps_size = type_bit_maps_size; return type_bit_maps_size; } /** * Compares two types bit maps. * * type_bit_maps_update_size(a) must have been called before. * type_bit_maps_update_size(b) must have been called before. * * @param a * @param b * @return */ int type_bit_maps_compare(const type_bit_maps_context *a, const type_bit_maps_context *b) { int d = a->last_type_window; d -= b->last_type_window; if(d == 0) { d = a->type_bit_maps_size; d -= b->type_bit_maps_size; if(d == 0) { if(a->last_type_window > 0) { d = memcmp(a->type_bitmap_field, b->type_bitmap_field, a->last_type_window << 5); // VS complains: 32 bits is more than enough } } } return d; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/u32_set.c0000644000000000000000000000013214505005532020760 xustar000000000000000030 mtime=1695812442.464982503 30 atime=1695812445.795030196 30 ctime=1695812494.737731154 yadifa-2.6.5-11201/lib/dnscore/src/u32_set.c0000664000374500037450000001157514505005532020733 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A dictionary u32 => ptr based on the AVL code. * * A dictionary u32 => ptr based on the AVL code. * Mostly used for accessing hash => value * * @{ *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #define _U32_SET_C #define DEBUG_LEVEL 0 #include "dnscore/u32_set.h" #include "dnscore/zalloc.h" #define U32SET_TAG 0x544553323355 /* * The following macros are defining relevant fields in the node */ /* * Access to the field that points to the left child */ #define AVL_LEFT_CHILD(node) ((node)->children.lr.left) /* * Access to the field that points to the right child */ #define AVL_RIGHT_CHILD(node) ((node)->children.lr.right) /* * Access to the field that points to one of the children (0: left, 1: right) */ #define AVL_CHILD(node,id) ((node)->children.child[(id)]) /* * Access to the field that keeps the balance (a signed byte) */ #define AVL_BALANCE(node) ((node)->balance) /* * Self explanatory */ #define AVL_REFERENCE_IS_POINTER FALSE /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u32 /* * */ #define AVL_REFERENCE_FORMAT_STRING '%08x' #define AVL_REFERENCE_FORMAT(reference) reference /* * A macro to initialize a node and setting the reference */ #define AVL_INIT_NODE(node,reference) node->key = reference;node->value=NULL /* * A macro to allocate a new node */ #define AVL_ALLOC_NODE(node,reference) ZALLOC_OBJECT_OR_DIE(node,AVL_NODE_TYPE, U32SET_TAG); /* * A macro to free a node allocated by ALLOC_NODE */ #define AVL_FREE_NODE(node) ZFREE(node,AVL_NODE_TYPE) /* * A macro to print the node */ #define AVL_DUMP_NODE(node) format("node@%p",(node)); /* * A macro that returns the reference field of the node. * It must be of type REFERENCE_TYPE */ #define AVL_REFERENCE(node) (node)->key /* * A macro to compare two references * Returns TRUE if and only if the references are equal. */ #define AVL_ISEQUAL(reference_a,reference_b) ((u32)(reference_a) == (u32)(reference_b)) /* * A macro to compare two references * Returns TRUE if and only if the first one is bigger than the second one. */ #define AVL_ISBIGGER(reference_a,reference_b) ((u32)(reference_a) > (u32)(reference_b)) /* * Copies the payload of a node * It MUST NOT copy the "proprietary" node fields : children, parent, balance */ #define AVL_COPY_PAYLOAD(node_trg,node_src) (node_trg)->key=(node_src)->key;(node_trg)->value=(node_src)->value; /* * A macro to preprocess a node before it is preprocessed for a delete (detach) * If there was anything to do BEFORE deleting a node, we would do it here * After this macro is exectuted, the node * _ is detached, then deleted with FREE_NODE * _ has got its content overwritten by the one of another node, then the other * node is deleted with FREE_NODE */ #define AVL_NODE_DELETE_CALLBACK(node) #include "dnscore/avl.c.inc" /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/u64_set.c0000644000000000000000000000013114505005532020764 xustar000000000000000030 mtime=1695812442.489982861 29 atime=1695812445.79603021 30 ctime=1695812494.739731183 yadifa-2.6.5-11201/lib/dnscore/src/u64_set.c0000664000374500037450000001231714505005532020733 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief A dictionary u64 => ptr based on the AVL code. * * A dictionary u64 => ptr based on the AVL code. * Mostly used for accessing hash => value * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #define _U64_SET_C #define DEBUG_LEVEL 0 #include "dnscore/dnscore.h" #include "dnscore/u64_set.h" #include "dnscore/zalloc.h" #define U64SET_TAG 0x544553343655 /* * The following macros are defining relevant fields in the node */ /* * Access to the field that points to the left child */ #define AVL_LEFT_CHILD(node) ((node)->children.lr.left) /* * Access to the field that points to the right child */ #define AVL_RIGHT_CHILD(node) ((node)->children.lr.right) /* * Access to the field that points to one of the children (0: left, 1: right) */ #define AVL_CHILD(node,id) ((node)->children.child[(id)]) /* * Access to the field that keeps the balance (a signed byte) */ #define AVL_BALANCE(node) ((node)->balance) /* * Self explanatory */ #define AVL_REFERENCE_IS_POINTER FALSE /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u64 /* * */ #define AVL_REFERENCE_FORMAT_STRING '%08x' #define AVL_REFERENCE_FORMAT(reference) reference /* * A macro to initialize a node and setting the reference */ #define AVL_INIT_NODE(node,reference) node->key = reference;node->value=NULL #if 0 /* fix */ #else /* * A macro to allocate a new node */ #define AVL_ALLOC_NODE(node,reference) ZALLOC_OBJECT_OR_DIE(node,AVL_NODE_TYPE, U64SET_TAG); /* * A macro to free a node allocated by ALLOC_NODE */ #define AVL_FREE_NODE(node) ZFREE(node,AVL_NODE_TYPE) #endif /* * A macro to print the node */ #define AVL_DUMP_NODE(node) format("node@%p",(node)); /* * A macro that returns the reference field of the node. * It must be of type REFERENCE_TYPE */ #define AVL_REFERENCE(node) (node)->key /* * A macro to compare two references * Returns TRUE if and only if the references are equal. */ #define AVL_ISEQUAL(reference_a,reference_b) ((u64)(reference_a) == (u64)(reference_b)) /* * A macro to compare two references * Returns TRUE if and only if the first one is bigger than the second one. */ #define AVL_ISBIGGER(reference_a,reference_b) ((u64)(reference_a) > (u64)(reference_b)) /* * Copies the payload of a node * It MUST NOT copy the "proprietary" node fields : children, parent, balance */ #define AVL_COPY_PAYLOAD(node_trg,node_src) (node_trg)->key=(node_src)->key;(node_trg)->value=(node_src)->value; /* * A macro to preprocess a node before it is preprocessed for a delete (detach) * If there was anything to do BEFORE deleting a node, we would do it here * After this macro is exectuted, the node * _ is detached, then deleted with FREE_NODE * _ has got its content overwritten by the one of another node, then the other * node is deleted with FREE_NODE */ #define AVL_NODE_DELETE_CALLBACK(node) #include "dnscore/avl.c.inc" void *u64_set_iterator_hasnext_next_value(u64_set_iterator *iterp) { if(u64_set_iterator_hasnext(iterp)) { u64_node *node = u64_set_iterator_next_node(iterp); void *ptr = node->value; return ptr; } else { return NULL; } } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/u64_set_debug.c0000644000000000000000000000013114505005532022132 xustar000000000000000029 mtime=1695812442.45498236 30 atime=1695812445.794030182 30 ctime=1695812494.742731226 yadifa-2.6.5-11201/lib/dnscore/src/u64_set_debug.c0000664000374500037450000001254614505005532022105 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup collections Generic collections functions * @ingroup dnscore * @brief * * A collection of strings based on the AVL * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include #include #define _U64_SET_C #define DEBUG_LEVEL 0 #include "dnscore/dnscore.h" #include "dnscore/u64_set_debug.h" #include "dnscore/zalloc.h" #undef malloc #undef free #undef realloc #undef calloc #undef debug_mtest #undef debug_stat #undef debug_mallocated #define U64SET_TAG 0x544553343655 /* * The following macros are defining relevant fields in the node */ /* * Access to the field that points to the left child */ #define AVL_LEFT_CHILD(node) ((node)->children.lr.left) /* * Access to the field that points to the right child */ #define AVL_RIGHT_CHILD(node) ((node)->children.lr.right) /* * Access to the field that points to one of the children (0: left, 1: right) */ #define AVL_CHILD(node,id) ((node)->children.child[(id)]) /* * Access to the field that keeps the balance (a signed byte) */ #define AVL_BALANCE(node) ((node)->balance) /* * Self explanatory */ #define AVL_REFERENCE_IS_POINTER FALSE /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u64 /* * */ #define AVL_REFERENCE_FORMAT_STRING '%08x' #define AVL_REFERENCE_FORMAT(reference) reference /* * A macro to initialize a node and setting the reference */ #define AVL_INIT_NODE(node,reference) node->key = reference;node->value=NULL #if 0 /* fix */ #else /* * A macro to allocate a new node */ #define AVL_ALLOC_NODE(node,reference) node=((AVL_NODE_TYPE*)debug_malloc_unmonitored(sizeof(AVL_NODE_TYPE)));memset(node, 0, sizeof(AVL_NODE_TYPE)) /* * A macro to free a node allocated by ALLOC_NODE */ #define AVL_FREE_NODE(node) debug_free_unmonitored(node) #endif /* * A macro to print the node */ #define AVL_DUMP_NODE(node) format("node@%p",(node)); /* * A macro that returns the reference field of the node. * It must be of type REFERENCE_TYPE */ #define AVL_REFERENCE(node) (node)->key /* * A macro to compare two references * Returns TRUE if and only if the references are equal. */ #define AVL_ISEQUAL(reference_a,reference_b) ((u64)(reference_a) == (u64)(reference_b)) /* * A macro to compare two references * Returns TRUE if and only if the first one is bigger than the second one. */ #define AVL_ISBIGGER(reference_a,reference_b) ((u64)(reference_a) > (u64)(reference_b)) /* * Copies the payload of a node * It MUST NOT copy the "proprietary" node fields : children, parent, balance */ #define AVL_COPY_PAYLOAD(node_trg,node_src) (node_trg)->key=(node_src)->key;(node_trg)->value=(node_src)->value; /* * A macro to preprocess a node before it is preprocessed for a delete (detach) * If there was anything to do BEFORE deleting a node, we would do it here * After this macro is exectuted, the node * _ is detached, then deleted with FREE_NODE * _ has got its content overwritten by the one of another node, then the other * node is deleted with FREE_NODE */ #define AVL_NODE_DELETE_CALLBACK(node) #include "dnscore/avl.c.inc" #undef malloc #undef free #undef realloc #undef calloc #undef debug_mtest #undef debug_stat #undef debug_mallocated void *u64_set_debug_iterator_hasnext_next_value(u64_set_debug_iterator *iterp) { if(u64_set_debug_iterator_hasnext(iterp)) { u64_node_debug *node = u64_set_debug_iterator_next_node(iterp); void *ptr = node->value; return ptr; } else { return NULL; } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/xfr_input_stream.c0000644000000000000000000000013214505005532023065 xustar000000000000000030 mtime=1695812442.433982059 30 atime=1695812445.794030182 30 ctime=1695812494.744731255 yadifa-2.6.5-11201/lib/dnscore/src/xfr_input_stream.c0000664000374500037450000011355714505005532023043 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup dnscore * @brief * * @{ */ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include "dnscore/xfr_input_stream.h" #include "dnscore/zalloc.h" #include "dnscore/packet_reader.h" #include "dnscore/format.h" #include "dnscore/file_input_stream.h" #include "dnscore/file_output_stream.h" #include "dnscore/buffer_input_stream.h" #include "dnscore/buffer_output_stream.h" #include "dnscore/fdtools.h" #include "dnscore/pipe_stream.h" #include "dnscore/message.h" #include "dnscore/pool.h" #include "dnscore/random.h" #include "dnscore/thread_pool.h" #include "dnscore/tcp_io_stream.h" /* it depends if host is DARWIN or LINUX */ #ifdef HAVE_SYS_SYSLIMITS_H #ifndef __FreeBSD__ #include #endif #elif HAVE_LINUX_LIMITS_H #include #endif /* HAVE_SYS_SYSLIMITS_H */ #define MODULE_MSG_HANDLE g_system_logger #define DEBUG_XFR_INPUT_STREAM 0 typedef struct xfr_input_stream_data xfr_input_stream_data; #define XFRISDTA_TAG 0x4154445349524658 #define XFRISSOA_TAG 0x414f535349524658 #define XFRPOOL_TAG 0x4c4f4f50524658 struct xfr_input_stream_data { output_stream pipe_stream_output; input_stream pipe_stream_input; input_stream source_stream; output_stream source_output_stream; packet_unpack_reader_data reader; message_data *message; const u8 *origin; u8 *pool; // 64KB u8 *first_soa_record; u32 first_soa_record_size; u16 ancount; u16 xfr_mode; u32 record_index; // index of the record in the stream u32 last_serial; u32 last_refresh; u32 last_retry; u32 last_expire; u32 last_nttl; u64 mesg_hdr_mask; u64 mesg_hdr_result; u64 next_hdr_mask; u64 next_hdr_result; ya_result last_error; bool eos; bool ixfr_mark; bool owns_message; bool owns_input_stream; #if DNSCORE_HAS_TSIG_SUPPORT bool last_message_had_tsig; bool need_cleanup_tsig; #endif }; static pool_s xfr_pool; static mutex_t xfr_pool_init_mtx = MUTEX_INITIALIZER; static bool xfr_pool_initialised = FALSE; static void *xfr_pool_alloc(void *args) { (void)args; void *p; MALLOC_OBJECT_ARRAY(p, u8, 0x1010a, XFRPOOL_TAG); // void *p = malloc(0x1010a); return p; } static void xfr_pool_free(void *ptr, void* args) { (void)args; free(ptr); } /** * Reads from the (tcp) input stream for an xfr * Detects the xfr type * Copies into the right file * * @return error code */ //#if HAS_NON_AA_AXFR_SUPPORT /* * Non-RFC-compliant masks (allows AA bit not set) * * It seems (some?) Microsoft DNS answers to an AXFR query without setting the AA bit * * The RFC 5936 states that in the case of an AXFR answer with no error (RCODE set to 0), * the AA bit MUST be set. * */ #ifdef WORDS_BIGENDIAN #define AXFR_MESSAGE_LENIENT_HEADER_MASK (( (u64) 0 ) | \ (((u64) (QR_BITS | TC_BITS )) << 40 )| \ (((u64) ( RA_BITS | RCODE_BITS )) << 32 ) | \ ( (u64) 1LL << 16 )) #define AXFR_MESSAGE_LENIENT_HEADER_RESULT (( (u64) (QR_BITS ) << 40 ) | \ ( ((u64) 1LL) << 16 )) #define AXFR_NEXT_MESSAGE_LENIENT_HEADER_MASK (( (u64) 0LL ) | \ (((u64) ( QR_BITS | TC_BITS )) << 40 )| \ (((u64) ( RCODE_BITS )) << 32 )) #define AXFR_NEXT_MESSAGE_LENIENT_HEADER_RESULT (((u64) ( QR_BITS )) << 40 ) #else #define AXFR_MESSAGE_LENIENT_HEADER_MASK (( (u64) 0LL ) | \ (((u64) ( QR_BITS | TC_BITS )) << 16 )| \ (((u64) ( RCODE_BITS )) << 24 ) | \ (((u64) 1LL) << 40 )) #define AXFR_MESSAGE_LENIENT_HEADER_RESULT ((((u64) ( QR_BITS )) << 16 )| \ (((u64) 1LL) << 40 )) #define AXFR_NEXT_MESSAGE_LENIENT_HEADER_MASK (( (u64) 0LL ) | \ (((u64) ( QR_BITS | TC_BITS )) << 16 )| \ (((u64) ( RCODE_BITS )) << 24 )) #define AXFR_NEXT_MESSAGE_LENIENT_HEADER_RESULT (((u64) ( QR_BITS )) << 16 ) #endif //#else /* * RFC compliant masks (AA bit must be set) */ #ifdef WORDS_BIGENDIAN #define AXFR_MESSAGE_HEADER_MASK (( (u64) 0 ) | \ (((u64) (QR_BITS | AA_BITS | TC_BITS )) << 40 )| \ (((u64) ( RA_BITS | RCODE_BITS )) << 32 ) | \ ( (u64) 1LL << 16 )) #define AXFR_MESSAGE_HEADER_RESULT (( (u64) (QR_BITS | AA_BITS) << 40 ) | \ ( ((u64) 1LL) << 16 )) #define AXFR_NEXT_MESSAGE_HEADER_MASK (( (u64) 0LL ) | \ (((u64) ( QR_BITS | AA_BITS | TC_BITS )) << 40 )| \ (((u64) ( RCODE_BITS )) << 32 )) #define AXFR_NEXT_MESSAGE_HEADER_RESULT (((u64) ( QR_BITS | AA_BITS )) << 40 ) #else #define AXFR_MESSAGE_HEADER_MASK (( (u64) 0LL ) | \ (((u64) ( QR_BITS | AA_BITS | TC_BITS )) << 16 )| \ (((u64) ( RCODE_BITS )) << 24 ) | \ (((u64) 1LL) << 40 )) #define AXFR_MESSAGE_HEADER_RESULT ((((u64) ( QR_BITS | AA_BITS )) << 16 )| \ (((u64) 1LL) << 40 )) #define AXFR_NEXT_MESSAGE_HEADER_MASK (( (u64) 0LL ) | \ (((u64) ( QR_BITS | AA_BITS | TC_BITS )) << 16 )| \ (((u64) ( RCODE_BITS )) << 24 )) #define AXFR_NEXT_MESSAGE_HEADER_RESULT (((u64) ( QR_BITS | AA_BITS )) << 16 ) #endif //#endif /* * Reads the content of a message from the reader field in data (packet reader) * The ancount field in data contains the number of records to read * Every record read is written to the output pipe */ static ya_result xfr_input_stream_read_packet(xfr_input_stream_data *data) { //message_data *message = data->message; packet_unpack_reader_data *reader = &data->reader; u8 *record = data->pool; // no persistence of content needed s32 record_len; ya_result return_value = SUCCESS; #if DEBUG_XFR_INPUT_STREAM log_debug("xfr_input_stream_read_packet(%p) ancount=%hd record_index=%u", data, data->ancount, data->record_index); #endif while((data->ancount > 0) && (pipe_stream_write_available(&data->pipe_stream_output) > 2048 )) { --data->ancount; if(FAIL(record_len = packet_reader_read_record(reader, record, RDATA_MAX_LENGTH + 1))) { if(record_len != UNSUPPORTED_TYPE) { data->eos = TRUE; return_value = record_len; break; } log_err("xfr_input_stream: skipped unsupported record #%d %{recordwire}", data->record_index, record); data->record_index++; continue; } #if DEBUG_XFR_INPUT_STREAM log_debug("xfr_input_stream: <%u %{recordwire}", data->record_index, record); #endif const u8 *ptr = record + dnsname_len(record); u16 rtype = GET_U16_AT(*ptr); switch(rtype) { case TYPE_SOA: { /* handle SOA case */ if(!dnsname_equals(record, data->origin)) { data->eos = TRUE; return_value = MAKE_DNSMSG_ERROR(FP_XFR_QUERYERROR); // OWNER OF SOA RECORD SHOULD BE ORIGIN (protocol error) return return_value; } ptr += 10; /* type class ttl rdata_size */ ptr += dnsname_len(ptr); ptr += dnsname_len(ptr); u32 soa_serial = ntohl(GET_U32_AT(*ptr)); if(data->xfr_mode == TYPE_ANY) // the type of stream has not been decided yet { if(data->record_index == 1) { // second record is an SOA: this is an IXFR, the first record is not sent up #if DEBUG_XFR_INPUT_STREAM log_debug("xfr_input_stream: #%u %{recordwire} ; (IXFR START)", data->record_index, data->first_soa_record); #endif data->xfr_mode = TYPE_IXFR; } else { // second record is not an SOA: this is an AXFR, the first record is sent up #if DEBUG_XFR_INPUT_STREAM log_debug("xfr_input_stream: #%u %{recordwire} ; (AXFR START)", data->record_index, record); #endif output_stream_write(&data->pipe_stream_output, data->first_soa_record, data->first_soa_record_size); data->xfr_mode = TYPE_AXFR; } } if(soa_serial == data->last_serial) { // the SOA serial has the same value as the last record we expect // if it's an AXFR or this is the second time it happens on an IXFR, then it's then end of the stream if(data->xfr_mode == TYPE_AXFR || ((data->xfr_mode == TYPE_IXFR) && data->ixfr_mark)) { return_value = SUCCESS; /* * The last record of an AXFR must be written, * the last record of an IXFR must not. */ if(data->xfr_mode == TYPE_AXFR) { #if DEBUG_XFR_INPUT_STREAM log_debug("xfr_input_stream: #%u %{recordwire} ; (AXFR END)", data->record_index, record); #endif return_value = output_stream_write(&data->pipe_stream_output, record, record_len); } #if DEBUG_XFR_INPUT_STREAM else { log_debug("xfr_input_stream: #%u %{recordwire} ; (IXFR END)", data->record_index, record); } #endif // done data->eos = TRUE; return return_value; // reached the end } // IXFR needs to find the mark twice #if DEBUG_XFR_INPUT_STREAM log_debug("xfr_input_stream: #%u %{recordwire} ; (IXFR LAST)", data->record_index, record); #endif data->ixfr_mark = TRUE; } break; } case TYPE_IXFR: case TYPE_AXFR: case TYPE_OPT: case TYPE_ANY: return INVALID_PROTOCOL; default: { if(data->record_index == 1) { // special case to detect an AXFR returned by an IXFR query if(data->xfr_mode == TYPE_ANY) { data->xfr_mode = TYPE_AXFR; if(FAIL(return_value = output_stream_write(&data->pipe_stream_output, data->first_soa_record, data->first_soa_record_size))) { return return_value; } } else { return_value = INVALID_STATE_ERROR; // XFR mode should be "ANY" return return_value; // invalid status } } break; } } #if DEBUG_XFR_INPUT_STREAM log_debug("xfr_input_stream: >%u %{recordwire}", data->record_index, record); #endif if(FAIL(return_value = output_stream_write(&data->pipe_stream_output, record, record_len))) { data->eos = TRUE; break; } if(return_value != (s32)record_len) { return UNEXPECTED_EOF; } data->record_index++; } return return_value; } static ya_result xfr_input_stream_fill(input_stream *is, u32 len) { xfr_input_stream_data *data = (xfr_input_stream_data*)is->data; input_stream *source_stream = &data->source_stream; message_data *mesg = data->message; #if DNSCORE_HAS_TSIG_SUPPORT const tsig_item *tsig = message_tsig_get_key(mesg); #endif packet_unpack_reader_data *pr = &data->reader; if(FAIL(data->last_error)) { return data->last_error; } ya_result ret = SUCCESS; while(pipe_stream_read_available(&data->pipe_stream_input) < (s32)len) { /* read the packet and write on the output (so it can be read back on the input) */ if(FAIL(ret = xfr_input_stream_read_packet(data))) { break; } if(data->eos) { break; } if(data->ancount > 0) { break; } /* next TCP chunk */ #if DEBUG message_debug_trash_buffer(mesg); #endif u16 tcplen; ret = input_stream_read_nu16(source_stream, &tcplen); /* this is wrong ... */ if(ret != 2) { #if DEBUG log_debug("xfr_input_stream_read: next message is %ld bytes long", ret); #endif break; } if(tcplen == 0) { ret = UNEXPECTED_EOF; break; } if(FAIL(ret = input_stream_read_fully(source_stream, message_get_buffer(mesg), tcplen))) { break; } message_set_size(mesg, ret); #if DEBUG_XFR_INPUT_STREAM LOGGER_EARLY_CULL_PREFIX(MSG_INFO) message_log(MODULE_MSG_HANDLE, MSG_INFO, mesg); #endif #if DEBUG memset(&message_get_buffer(mesg)[tcplen], 0xdd, DNSPACKET_MAX_LENGTH + 1 - tcplen); #endif /* * Check the headers */ const u64 *h64 = (u64*)message_get_buffer(mesg); const u64 m64 = data->next_hdr_mask; // AXFR_NEXT_MESSAGE_HEADER_MASK; const u64 r64 = data->next_hdr_result; // AXFR_NEXT_MESSAGE_HEADER_RESULT; if(((*h64&m64) != r64) || (message_get_authority_count_ne(mesg) != 0)) { u8 code = message_get_rcode(mesg); if(code != 0) { ret = MAKE_DNSMSG_ERROR(code); } else { ret = UNPROCESSABLE_MESSAGE; } break; } #if DNSCORE_HAS_TSIG_SUPPORT if((data->last_message_had_tsig = (tsig != NULL))) { /* verify the TSIG * * AR > 0 * skip ALL the records until the last AR * it MUST be a TSIG * It's the first TSIG answering to our query * verify it * */ message_tsig_clear_key(mesg); if(FAIL(ret = tsig_message_extract(mesg))) { break; } if((ret == 1) && (message_tsig_get_key(mesg) != tsig)) { /* This is not the one we started with */ log_debug("xfr_input_stream: signature key does not match"); ret = TSIG_BADSIG; break; } if(FAIL(ret = tsig_verify_tcp_next_message(mesg))) { break; } } #endif message_header *header = message_get_header(mesg); data->ancount = ntohs(header->ancount); packet_reader_init_from_message_at(pr, mesg, DNS_HEADER_LENGTH); u16 n = ntohs(header->qdcount); while(n > 0) { if(FAIL(ret = packet_reader_skip_fqdn(pr))) // this is the domain already used for this query { break; } if(FAIL(ret = packet_reader_skip(pr, 4))) { break; } n--; } } // for(;;) /* process all TCP chunks */ return ret; } static ya_result xfr_input_stream_read(input_stream *is, void *buffer_, u32 len) { xfr_input_stream_data *data = (xfr_input_stream_data*)is->data; message_data *mesg = data->message; #if DNSCORE_HAS_TSIG_SUPPORT const tsig_item *tsig = message_tsig_get_key(mesg); #endif if(FAIL(data->last_error)) { return data->last_error; } u8 *buffer = (u8*)buffer_; ya_result return_value = xfr_input_stream_fill(is, len); /* while there is not enough bytes on the input */ if(ISOK(return_value)) { if((return_value = pipe_stream_read_available(&data->pipe_stream_input)) > 0) // never fails { if(FAIL(return_value = input_stream_read(&data->pipe_stream_input, buffer, len))) { #if DNSCORE_HAS_TSIG_SUPPORT if(data->need_cleanup_tsig) { tsig_verify_tcp_last_message(mesg); data->need_cleanup_tsig = FALSE; } #endif } } else { // here, return_value == 0 #if DNSCORE_HAS_TSIG_SUPPORT if(tsig != NULL) { tsig_verify_tcp_last_message(mesg); data->need_cleanup_tsig = FALSE; if(!data->last_message_had_tsig) { /* * The stream didn't end with a TSIG * It's bad. * */ log_err("xfr_input_stream: TSIG enabled answer didn't ended with a signed packet"); return_value = TSIG_BADSIG; } } #endif } } else { #if DNSCORE_HAS_TSIG_SUPPORT // cleanup tsig_verify_tcp_last_message(mesg); data->need_cleanup_tsig = FALSE; #endif } data->last_error = return_value; return return_value; } static ya_result xfr_input_stream_skip(input_stream *is, u32 len) { /* * The reader is too complicated to implement a skip, so skip is a wrapped read */ u32 remaining = len; ya_result return_value = SUCCESS; u8 buffer[512]; while(remaining > 0) { u32 n = MIN(remaining, sizeof(buffer)); return_value = xfr_input_stream_read(is, buffer, n); if(return_value <= 0) /* FAIL or EOF */ { break; } remaining -= return_value; } if(len != remaining) { return_value = len - remaining; } return return_value; } static void xfr_input_stream_close(input_stream *is) { xfr_input_stream_data *data = (xfr_input_stream_data*)is->data; #if DNSCORE_HAS_TSIG_SUPPORT if(data->need_cleanup_tsig) { message_clear_hmac(data->message); if(ISOK(data->last_error)) { #if DEBUG log_warn("xfr: %{dnsname}: TSIG has not been cleared (DEBUG)", data->origin); #else log_debug("xfr: %{dnsname}: TSIG has not been cleared (%r)", data->origin, data->last_error); #endif } data->need_cleanup_tsig = FALSE; } #endif #if DEBUG_XFR_INPUT_STREAM log_debug("xfr_input_stream: %{dnsname}: close, last serial is %i //////////////////////////////", data->origin, data->last_serial); #endif pool_release(&xfr_pool, data->pool); output_stream_close(&data->pipe_stream_output); input_stream_close(&data->pipe_stream_input); free(data->first_soa_record); if(data->owns_message) { message_free(data->message); } if(data->owns_input_stream) { input_stream_close(&data->source_stream); output_stream_close(&data->source_output_stream); } #if DEBUG memset(data, 0xfe, sizeof(xfr_input_stream_data)); #endif ZFREE(data, xfr_input_stream_data); // used to be leaked ? input_stream_set_void(is); } static const input_stream_vtbl xfr_input_stream_vtbl = { xfr_input_stream_read, xfr_input_stream_skip, xfr_input_stream_close, "xfr_input_stream", }; /** * * @param is the input stream with the AXFR or IXFR, wire format * @param flags mostly XFR_ALLOW_AXFR or XFR_ALLOW_IXFR * @param origin the domain of the zone * @param base_data_path the folder where to put the journal (or journal hash directories and journal) * @param current_serial the serial currently available * @param loaded_serial a pointer to get the serial available after loading * @param message the message that led to this download * * @return an error code, TYPE_AXFR, TYPE_IXFR, TYPE_NONE */ ya_result xfr_input_stream_init(input_stream* filtering_stream, const u8 *origin, input_stream *xfr_source_stream, message_data *mesg, u32 current_serial, xfr_copy_flags flags) { yassert(filtering_stream != NULL && origin != NULL && xfr_source_stream != NULL && mesg != NULL); mutex_lock(&xfr_pool_init_mtx); if(!xfr_pool_initialised) { xfr_pool_initialised = TRUE; pool_init(&xfr_pool, xfr_pool_alloc, xfr_pool_free, NULL, "xfr stream data pool"); } mutex_unlock(&xfr_pool_init_mtx); input_stream *is = xfr_source_stream; packet_unpack_reader_data pr; u8 *buffer; u8 *record; u8 *ptr; u8 *pool = NULL; // 128KB #if DNSCORE_HAS_TSIG_SUPPORT const tsig_item *tsig; #endif ya_result record_len; ya_result return_value; u32 origin_len; u32 last_serial = 0; u16 tcplen; u16 qtype; u16 qclass; u16 old_mac_size; bool last_message_had_tsig; bool need_cleanup_tsig = FALSE; #if DNSCORE_HAS_TSIG_SUPPORT u8 old_mac[64]; #endif #if DEBUG_XFR_INPUT_STREAM log_debug("xfr_input_stream: %{dnsname}: init, current serial is %i //////////////////////////////", origin, current_serial); #endif /* * ensure the stream will be unusable if the initialisation fails */ input_stream_set_sink(filtering_stream); /* * Start by reading the first packet, and determine if it's an AXFR or an IXFR (for the name) * note: it's read and converted to the host endianness */ if(!is_fd_input_stream(is)) { // expected file input stream return INVALID_ARGUMENT_ERROR; } //buffer_input_stream_init(is, is, 4096); /* TCP length */ if(FAIL(return_value = input_stream_read_nu16(is, &tcplen))) { return return_value; } if(return_value != 2) { return UNEXPECTED_EOF; } /* if the length is not enough, return the most appropriate error code */ origin_len = dnsname_len(origin); if(tcplen < DNS_HEADER_LENGTH + origin_len + 4) { return_value = UNEXPECTED_EOF; if(tcplen >= DNS_HEADER_LENGTH) { u8 tmp_hdr[DNS_HEADER_LENGTH]; if(ISOK(return_value = input_stream_read_fully(is, tmp_hdr, DNS_HEADER_LENGTH))) { return_value = MAKE_DNSMSG_ERROR(MESSAGE_RCODE(tmp_hdr)); } } return return_value; } pool = pool_alloc(&xfr_pool); /* read the whole message */ buffer = message_get_buffer(mesg); record = pool; // no persistence required if(FAIL(return_value = input_stream_read_fully(is, buffer, tcplen))) { pool_release(&xfr_pool, pool); return return_value; } message_set_size(mesg, return_value); #if DEBUG_XFR_INPUT_STREAM LOGGER_EARLY_CULL_PREFIX(MSG_INFO) message_log(MODULE_MSG_HANDLE, MSG_INFO, mesg); #endif /* check the message makes sense */ bool axfr_strict_authority = (flags & XFR_LOOSE_AUTHORITY) == 0; const u64 *h64 = (u64*)buffer; u64 m64 = axfr_strict_authority ? AXFR_MESSAGE_HEADER_MASK : AXFR_MESSAGE_LENIENT_HEADER_MASK; u64 r64 = axfr_strict_authority ? AXFR_MESSAGE_HEADER_RESULT : AXFR_MESSAGE_LENIENT_HEADER_RESULT; if(((*h64&m64) != r64) || (message_get_authority_count_ne(mesg) != 0)) { u8 code = message_get_rcode(mesg); if(code != 0) { return_value = MAKE_DNSMSG_ERROR(code); } else { return_value = UNPROCESSABLE_MESSAGE; } pool_release(&xfr_pool, pool); return return_value; } if(message_get_rcode(mesg) != RCODE_NOERROR) { pool_release(&xfr_pool, pool); return MAKE_DNSMSG_ERROR(message_get_rcode(mesg)); } packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_read_fqdn(&pr, record, RDATA_MAX_LENGTH + 1))) { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } if(!dnsname_equals(record, origin)) { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } if(FAIL(return_value = packet_reader_read_u16(&pr, &qtype))) { pool_release(&xfr_pool, pool); return return_value; } if(return_value != 2) { pool_release(&xfr_pool, pool); return UNEXPECTED_EOF; } /* * check that we are allowed to process this particular kind of transfer * note : this does not determine what is REALLY begin transferred */ switch(qtype) { case TYPE_AXFR: { if((flags & XFR_ALLOW_AXFR) == 0) { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } break; } case TYPE_IXFR: { if((flags & XFR_ALLOW_IXFR) == 0) { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } break; } default: { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } } if(FAIL(return_value = packet_reader_read_u16(&pr, &qclass))) { pool_release(&xfr_pool, pool); return return_value; } if(qclass != CLASS_IN) { // wrong answer pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } /* check for TSIG and verify */ u16 ancount = ntohs(MESSAGE_AN(buffer)); #if DNSCORE_HAS_TSIG_SUPPORT if((last_message_had_tsig = ((tsig = message_tsig_get_key(mesg)) != NULL))) { /* verify the TSIG * * AR > 0 * skip ALL the records until the last AR * it MUST be a TSIG * It's the first TSIG answering to our query * verify it * */ message_tsig_clear_key(mesg); old_mac_size = message_tsig_mac_get_size(mesg); message_tsig_mac_copy(mesg, old_mac); if(FAIL(return_value = tsig_message_extract(mesg))) { log_debug("xfr_input_stream: error extracting the signature"); pool_release(&xfr_pool, pool); return return_value; } if(return_value == 0) { log_debug("xfr_input_stream: no signature when one was requested"); pool_release(&xfr_pool, pool); return TSIG_BADSIG; /* no signature, when one was requested, is a bad signature */ } if(tsig != message_tsig_get_key(mesg)) { /* This is not the one we started with */ log_debug("xfr_input_stream: signature key does not match"); pool_release(&xfr_pool, pool); return TSIG_BADSIG; } /// check that the tsig in the message matches theh one that was sent if(FAIL(return_value = tsig_verify_tcp_first_message(mesg, old_mac, old_mac_size))) { pool_release(&xfr_pool, pool); return return_value; } pr.packet_size = message_get_size(mesg); need_cleanup_tsig = TRUE; } #endif log_debug("xfr_input_stream: expecting %5d answer records", ancount); /* * read the SOA (it MUST be an SOA) */ if(FAIL(record_len = packet_reader_read_record(&pr, record, RDATA_MAX_LENGTH + 1))) { pool_release(&xfr_pool, pool); return record_len; } if(!dnsname_equals(record, origin)) { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } ptr = &record[origin_len]; if(GET_U16_AT(*ptr) != TYPE_SOA) { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } ptr += 8; /* type class ttl */ u16 rdata_size = ntohs(GET_U16_AT(*ptr)); if(rdata_size < 22) { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } rdata_size -= 16; ptr += 2; /* rdata size */ s32 len = dnsname_len(ptr); if(len >= rdata_size) { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } rdata_size -= len; ptr += len; len = dnsname_len(ptr); if(len >= rdata_size) { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } rdata_size -= len; if(rdata_size != 4) { pool_release(&xfr_pool, pool); return INVALID_PROTOCOL; } ptr += len; // if the serial of the SOA is the same one as we know, then there is no // need to download the zone last_serial = ntohl(GET_U32_AT(ptr[0])); if(last_serial == current_serial) { pool_release(&xfr_pool, pool); return ZONE_ALREADY_UP_TO_DATE; } u32 last_refresh = ntohl(GET_U32_AT(ptr[4])); u32 last_retry = ntohl(GET_U32_AT(ptr[8])); u32 last_expire = ntohl(GET_U32_AT(ptr[12])); u32 last_nttl = ntohl(GET_U32_AT(ptr[16])); xfr_input_stream_data *data; ZALLOC_OBJECT_OR_DIE( data, xfr_input_stream_data, XFRISDTA_TAG); ZEROMEMORY(data, sizeof(xfr_input_stream_data)); /* * We have got the first SOA * Next time we find this SOA (second next time for IXFR) the stream, it will be the end of the stream */ /* * The stream can be AXFR or IXFR. * The only way to know this is to look at the records, maybe on many packets. * If there are two SOA (different serial numbers) for the start, then it's an IXFR, else it's an AXFR. * * OPEN A PIPE STREAM "XFRs" * * Save the first SOA */ MALLOC_OR_DIE(u8*, data->first_soa_record, record_len, XFRISSOA_TAG); MEMCOPY(data->first_soa_record, record, record_len); data->first_soa_record_size = record_len; filtering_stream->vtbl = &xfr_input_stream_vtbl; filtering_stream->data = data; u32 pipe_buffer_size = 0x10000; pipe_stream_init(&data->pipe_stream_output, &data->pipe_stream_input, pipe_buffer_size); MEMCOPY(&data->reader, &pr, sizeof(packet_unpack_reader_data)); data->origin = origin; data->message = mesg; data->pool = pool; data->ancount = ancount - 1; data->record_index++; data->last_serial = last_serial; data->last_refresh = last_refresh; data->last_retry = last_retry; data->last_expire = last_expire; data->last_nttl = last_nttl; if(axfr_strict_authority) { data->mesg_hdr_mask = AXFR_MESSAGE_HEADER_MASK; data->mesg_hdr_result = AXFR_MESSAGE_HEADER_RESULT; data->next_hdr_mask = AXFR_NEXT_MESSAGE_HEADER_MASK; data->next_hdr_result = AXFR_NEXT_MESSAGE_HEADER_RESULT; } else { data->mesg_hdr_mask = AXFR_MESSAGE_LENIENT_HEADER_MASK; data->mesg_hdr_result = AXFR_MESSAGE_LENIENT_HEADER_RESULT; data->next_hdr_mask = AXFR_NEXT_MESSAGE_LENIENT_HEADER_MASK; data->next_hdr_result = AXFR_NEXT_MESSAGE_LENIENT_HEADER_RESULT; } data->xfr_mode = TYPE_ANY; data->ixfr_mark = FALSE; data->last_message_had_tsig = last_message_had_tsig; data->source_stream = *is; data->need_cleanup_tsig = need_cleanup_tsig; data->owns_message = FALSE; data->owns_input_stream = FALSE; /* * Then we read all records for all packets * If we find an SOA ... * AXFR: it has to be the last serial and it is the end of the stream. * IXFR: if it's not the last serial it has to go from step to step * AND once we have reached the "last serial" once, the next hit is the end of the stream. */ data->eos = FALSE; /* * In order to know what the type is, read the first packet. */ if(ISOK(return_value = xfr_input_stream_fill(filtering_stream, pipe_buffer_size / 2))) { if(ISOK(return_value = xfr_input_stream_read_packet(data))) { return return_value; } } xfr_input_stream_close(filtering_stream); return return_value; } ya_result xfr_input_stream_init_with_query(input_stream* filtering_stream, const host_address *server, const u8 *origin, s32 ttl, const u8 *soa_rdata, int soa_rdata_size, xfr_copy_flags flags) { input_stream is; output_stream os; random_ctx rndctx = thread_pool_get_random_ctx(); message_data *mesg = message_new_instance(); ya_result ret; u32 serial; u16 id; if(FAIL(ret = rr_soa_get_serial(soa_rdata, soa_rdata_size, &serial))) { return ret; } id = (u16)random_next(rndctx); message_make_ixfr_query(mesg, id, origin, ttl, soa_rdata_size, soa_rdata); #if DNSCORE_HAS_TSIG_SUPPORT if(server->tsig != NULL) { if(FAIL(ret = message_sign_query(mesg, server->tsig))) { message_free(mesg); return ret; } } #endif /* * connect & send */ while(FAIL(ret = tcp_input_output_stream_connect_host_address(server, &is, &os, 3))) { if(ret != MAKE_ERRNO_ERROR(EINTR)) { message_free(mesg); return ret; } } if(FAIL(ret = message_write_tcp(mesg, &os))) { input_stream_close(&is); output_stream_close(&os); message_free(mesg); return ret; } output_stream_flush(&os); int fd = fd_input_stream_get_filedescriptor(&is); tcp_set_sendtimeout(fd, 10, 0); tcp_set_recvtimeout(fd, 10, 0); if(FAIL(xfr_input_stream_init(filtering_stream, origin, &is, mesg, serial, flags))) { input_stream_close(&is); output_stream_close(&os); message_free(mesg); return ret; } xfr_input_stream_data *data = (xfr_input_stream_data*)filtering_stream->data; data->owns_message = TRUE; data->owns_input_stream = TRUE; data->source_output_stream = os; return SUCCESS; } ya_result xfr_input_stream_get_type(input_stream *in_xfr_input_stream) { xfr_input_stream_data *data = (xfr_input_stream_data*)in_xfr_input_stream->data; return data->xfr_mode; } const u8* xfr_input_stream_get_origin(input_stream *in_xfr_input_stream) { xfr_input_stream_data *data = (xfr_input_stream_data*)in_xfr_input_stream->data; return data->origin; } u32 xfr_input_stream_get_serial(input_stream *in_xfr_input_stream) { xfr_input_stream_data *data = (xfr_input_stream_data*)in_xfr_input_stream->data; return data->last_serial; } u32 xfr_input_stream_get_refresh(input_stream *in_xfr_input_stream) { xfr_input_stream_data *data = (xfr_input_stream_data*)in_xfr_input_stream->data; return data->last_refresh; } void xfr_input_stream_finalize() { mutex_lock(&xfr_pool_init_mtx); if(xfr_pool_initialised) { pool_finalize(&xfr_pool); xfr_pool_initialised = FALSE; } mutex_unlock(&xfr_pool_init_mtx); } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/zalloc.c0000644000000000000000000000013214505005532020760 xustar000000000000000030 mtime=1695812442.402981615 30 atime=1695812445.792030153 30 ctime=1695812494.746731283 yadifa-2.6.5-11201/lib/dnscore/src/zalloc.c0000664000374500037450000005450114505005532020727 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup zalloc very fast, no-overhead specialised memory allocation functions * @ingroup dnscore * @brief no-overhead specialised allocation functions * * These memory allocations are using memory mapping to allocate blocks. * * One difficulty is that to free a block, its size has to be known first. * Which is not an issue for most of our uses. * * One drawback is that once allocated, the memory is never released to the system * (but is still available to be allocated again by the program) * * Much faster than malloc, and no overhead. * * Allocated memory is always aligned to at least 64 bits * * The granularity of the size of a block is 8 bytes * * The base alignment is always 4096 + real size of the block * * * @{ */ #include "dnscore/dnscore-config.h" #include "dnscore/dnscore-config-features.h" #include "dnscore/thread.h" #include #include #include #include #define _ZALLOC_C #include "dnscore/sys_types.h" #include "dnscore/logger.h" #include "dnscore/format.h" #include "dnscore/zalloc.h" #include "dnscore/mutex.h" extern logger_handle* g_system_logger; #define MODULE_MSG_HANDLE g_system_logger #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT #include "dnscore/ptr_set_debug.h" #define ZALLOC_DEBUG 1 #define DNSCORE_DEBUG_ZALLOC_TRASHMEMORY 1 #else #define ZALLOC_DEBUG 0 #define DNSCORE_DEBUG_ZALLOC_TRASHMEMORY 0 #endif #if DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT #define ZALLOC_STATISTICS 1 #else #define ZALLOC_STATISTICS 0 #endif /* * */ #if DNSCORE_HAS_ZALLOC_SUPPORT #define ZMALLOC_TAG 0x434f4c4c414d5a // ZMALLOC //#define ZALLOC_MMAP_BLOC_SIZE 0x20000 // 128K : for small usages //#define ZALLOC_MMAP_BLOC_SIZE 0x300000 // 3M : not enough to be in a 4M page, still a lot // This setting should stay as it is. // The one exception is for hardware #ifndef ZALLOC_MMAP_BLOC_SIZE #define ZALLOC_MMAP_BLOC_SIZE 0x1000000 // 16M : enough for lots of records, but too much for smaller setups // except if the LAZY define is set ... #endif #define ZALLOC_LAZY 1 /// @note edf -- do NOT disable this #if !ZALLOC_LAZY # pragma message("zalloc: there is no reason to disable the ZALLOC_LAZY variant beside for testing.") #endif #ifndef MAP_ANONYMOUS /* * MAP_ANON is the deprecated synonym of MAP_ANONYMOUS * Mac OS X has MAP_ANON but not MAP_ANONYMOUS */ #ifdef MAP_ANON #define MAP_ANONYMOUS MAP_ANON #else #error MMAP MAP_ANONYMOUS not supported. Please disable zalloc usage until an alternative way is implemented. #endif #endif typedef u8* page; // least common multiple static u32 lcm(u32 a, u32 b) { int i = a; int j = b; while(a != b) { if(a < b) { a += i; } else { b += j; } } return a; } /** * Page size by slot size, PLEASE do not edit this. * * page_size[n] / 4096 MUST be a positive integer. * * The values are calibrated for the database memory usage distribution. * */ #ifndef ZALLOC_DEBUG #define ADJUSTED_ALLOC_PG_SIZE_COUNT ZALLOC_PG_SIZE_COUNT #else #define ADJUSTED_ALLOC_PG_SIZE_COUNT (ZALLOC_PG_SIZE_COUNT + 1) #endif static u32 page_size[ADJUSTED_ALLOC_PG_SIZE_COUNT]; static void* line_sll[ADJUSTED_ALLOC_PG_SIZE_COUNT]; static s32 line_count[ADJUSTED_ALLOC_PG_SIZE_COUNT]; static s32 heap_total[ADJUSTED_ALLOC_PG_SIZE_COUNT]; #if ZALLOC_LAZY static u8* lazy_next[ADJUSTED_ALLOC_PG_SIZE_COUNT]; static u32 lazy_count[ADJUSTED_ALLOC_PG_SIZE_COUNT]; static u32 smallest_size[ADJUSTED_ALLOC_PG_SIZE_COUNT]; #endif static mutex_t line_mutex[ADJUSTED_ALLOC_PG_SIZE_COUNT]; #if ZALLOC_STATISTICS static volatile u64 zalloc_memory_allocated = 0; static volatile u32 mmap_count = 0; static mutex_t zalloc_statistics_mtx = MUTEX_INITIALIZER; #endif static int system_page_size = 0; static volatile bool zalloc_init_done = FALSE; static inline void* zalloc_line_head_get(u32 page_index) { void* ret = line_sll[page_index]; return ret; } static inline void zalloc_line_head_set(u32 page_index, void *ptr) { yassert(ptr != NULL); yassert((((intptr)ptr) & 7) == 0); line_sll[page_index] = ptr; } #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT struct zalloc_range_s { intptr from; intptr to; }; typedef struct zalloc_range_s zalloc_range_s; static int zalloc_ptr_set_debug_range_compare(const void *node_a, const void *node_b) { zalloc_range_s *ra = (zalloc_range_s*)node_a; zalloc_range_s *rb = (zalloc_range_s*)node_b; if(ra->to < rb->from) { return 1; } if(rb->to < ra->from) { return -1; } return 0; } ptr_set_debug zalloc_pages_set = { NULL, zalloc_ptr_set_debug_range_compare}; mutex_t zalloc_pages_set_mtx = MUTEX_INITIALIZER; #if DNSCORE_DEBUG_HAS_BLOCK_TAG debug_memory_by_tag_context_t *zalloc_memory_by_tag_ctx = NULL; #endif #endif int zalloc_init() { if(zalloc_init_done) { return SUCCESS; } #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT #if DNSCORE_DEBUG_HAS_BLOCK_TAG zalloc_memory_by_tag_ctx = debug_memory_by_tag_new_instance("zalloc"); #endif #endif zalloc_init_done = TRUE; // lcm is in this file #if __unix__ system_page_size = getpagesize(); #else system_page_size = 4096; #endif if(system_page_size > ZALLOC_MMAP_BLOC_SIZE) { fprintf(stderr, "System page size bigger than the internal allocation size (%d > %d)\n", system_page_size, ZALLOC_MMAP_BLOC_SIZE); fprintf(stderr, "Please reduce the page size to a smaller value or rebuild disabling the internal allocation using --disable-zalloc\n"); fflush(stderr); abort(); } yassert(system_page_size > 0); for(u32 i = 0; i < ADJUSTED_ALLOC_PG_SIZE_COUNT; i++) { u32 lcm_page_chunk = lcm(system_page_size, (i + 1) * 8); u32 chosen_size = ((ZALLOC_MMAP_BLOC_SIZE + lcm_page_chunk - 1) / lcm_page_chunk) * lcm_page_chunk; page_size[i] = chosen_size; line_sll[i] = NULL; line_count[i] = 0; heap_total[i] = 0; #if ZALLOC_LAZY lazy_next[i] = NULL; lazy_count[i] = 0; smallest_size[i] = lcm_page_chunk; #endif mutex_init(&line_mutex[i]); } return SUCCESS; } void zalloc_finalize() { #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT #if DNSCORE_DEBUG_HAS_BLOCK_TAG debug_memory_by_tag_delete(zalloc_memory_by_tag_ctx); zalloc_memory_by_tag_ctx = NULL; #endif #endif } /** * INTERNAL * * Allocates a bunch of memory for a page_index * * page2 has a lazy initialisation feature supposed to be enabled at compile time (can be off for testing & debugging) * * zalloc_lines is as nice with the memory than zalloc_lines with --enable-tiny-footprint set in ./configure but can handle * much more memory (the 3.8M test is not a problem) */ static void zalloc_lines(u32 page_index) { page map_pointer; u32 chunk_size = (page_index + 1) << 3; // size of one bloc #if ZALLOC_LAZY if(lazy_next[page_index] == NULL) { #endif u32 size = page_size[page_index]; map_pointer = (page)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT zalloc_range_s *range = malloc(sizeof(zalloc_range_s)); range->from = (intptr)map_pointer; range->to = range->from + size - 1; mutex_lock(&zalloc_pages_set_mtx); ptr_node_debug *node = ptr_set_debug_insert(&zalloc_pages_set, range); node->value = (void*)(intptr)page_index; mutex_unlock(&zalloc_pages_set_mtx); #endif #if ZALLOC_STATISTICS mutex_lock(&zalloc_statistics_mtx); mmap_count++; mutex_unlock(&zalloc_statistics_mtx); #endif if(map_pointer == MAP_FAILED) { osformatln(termerr, "zalloc_lines(%u,%u) mmap failed with %r", size, chunk_size, ERRNO_ERROR); DIE(ZALLOC_ERROR_MMAPFAILED); } #ifdef MADV_NOHUGEPAGE if(madvise(map_pointer, size, MADV_NOHUGEPAGE) < 0) { int err = errno; if(err != EINVAL) { printf("zalloc_lines(%u,%u) madvise(%p,%x,%i) failed with %x", size, chunk_size, map_pointer, size, MADV_NOHUGEPAGE, ERRNO_ERROR); } #if DEBUG else { printf("zalloc_lines(%u,%u) madvise(%p,%x,%i) failed with %x", size, chunk_size, map_pointer, size, MADV_NOHUGEPAGE, ERRNO_ERROR); } #endif } #endif /* * current issue: the new memory allocation does not take advantage of the lazy mechanism * I should only prepare one part = lcm(system_page_size,chunk_size) at a time. * when the page is filled, I fill another one. */ #if ZALLOC_LAZY // give the page to the (supposedly empty) lazy handling lazy_count[page_index] = size / smallest_size[page_index]; lazy_next[page_index] = map_pointer; } else { map_pointer = lazy_next[page_index]; } // lazy_next[i] is set, only prepare it if(--lazy_count[page_index] > 0) { lazy_next[page_index] += smallest_size[page_index]; } else { lazy_next[page_index] = NULL; } u32 count = (smallest_size[page_index] / chunk_size); #else // old mechanism : setup the whole mapped memory at once // next data // count u32 count = (size / chunk_size); #endif line_count[page_index] += count; heap_total[page_index] += count; /* Builds the block chain for the new page set */ u8* data = map_pointer; void** header = (void**)map_pointer; while(--count > 0) { data += chunk_size; *header = data; header = (void**)data; } *header = (void*)(~7); // the last header points to an impossible address zalloc_line_head_set(page_index, map_pointer); } /** * @brief Allocates one slot in a memory set * * Allocates one slot in a memory set. * * The size of a slot is page_index*8 * * @param[in] page_index the index of the memory set * * @return a pointer to the allocated memory */ void* zalloc_line(u32 page_index #if ZALLOC_DEBUG && DNSCORE_DEBUG_HAS_BLOCK_TAG , u64 tag #endif ) { #if ZALLOC_DEBUG #if DNSCORE_DEBUG_HAS_BLOCK_TAG yassert(page_index < ZALLOC_PG_SIZE_COUNT - 2); page_index += 2; // debug requires 16 more bytes #else yassert(page_index < ZALLOC_PG_SIZE_COUNT - 1); page_index++; // debug requires 8 more bytes #endif #else yassert(page_index < ZALLOC_PG_SIZE_COUNT); #endif mutex_lock(&line_mutex[page_index]); if(line_count[page_index] == 0) { zalloc_lines(page_index); } line_count[page_index]--; yassert(line_count[page_index] >= 0); // get the first free slot as a pointer to the next free slot void **ret = zalloc_line_head_get(page_index); yassert(ret != NULL); // it should not be NULL // the next free slot can be NULL iff page_index == 0 yassert((page_index == 0) || ((page_index > 0) && (*ret != NULL))); zalloc_line_head_set(page_index, *ret); *ret = NULL; /* erases ZALLOC pointer */ #if ZALLOC_DEBUG u64* hdr = (u64*)ret; // the allocated memory is at hdr #if DNSCORE_DEBUG_HAS_BLOCK_TAG hdr[0] = (page_index - 2) | 0x2a110c0000000000LL; // the allocated slot number (offset by DEBUG) hdr[1] = tag; // TAG debug_memory_by_tag_alloc_notify(zalloc_memory_by_tag_ctx, tag, (page_index - 2) << 3); ret = (void**)(hdr + 2); // the address returned (without the DEBUG header) #if DNSCORE_DEBUG_ZALLOC_TRASHMEMORY memset(ret, 0xac, ((page_index - 1) << 3)); #endif #else *hdr = (page_index - 1) | 0x2a110c0000000000LL; // the allocated slot number (offset by DEBUG) ret = (void**)(hdr + 1); // the address returned (without the DEBUG header) #if DNSCORE_DEBUG_ZALLOC_TRASHMEMORY memset(ret, 0xac, ((page_index) << 3)); #endif #endif // DNSCORE_DEBUG_HAS_BLOCK_TAG #else #if DNSCORE_DEBUG_ZALLOC_TRASHMEMORY memset(ret, 0xac, ((page_index + 1) << 3)); #endif #endif // ZALLOC_DEBUG #if ZALLOC_STATISTICS mutex_lock(&zalloc_statistics_mtx); zalloc_memory_allocated += (page_index + 1) << 3; mutex_unlock(&zalloc_statistics_mtx); #endif mutex_unlock(&line_mutex[page_index]); return ret; } /** * @brief Frees one slot in a memory set * * Frees one slot in a memory set * * The size of a slot is page_index*8 * * @param[in] ptr a pointer to the memory to free * @param[in] page_index the index of the memory set * */ static void zfree_line_report(int page_index) { log_err("zfree_line: page #%d count (%d) > total (%d)", page_index, line_count[page_index], heap_total[page_index]); logger_flush(); s32 count = line_count[page_index]; if(count > 0) { void** ret = zalloc_line_head_get(page_index); for(s32 i = 0; i < count; i++) { if(ret != NULL) { log_err("[%3x][%6x] %p", page_index, i, ret); void **old = ret; (void) old; ret = (void**)*ret; // do not: *old = NULL; } else { log_err("[%3x][%6x] NULL", page_index, i); break; } } logger_flush(); } #ifndef NDEBUG bool zalloc_memory_allocations_have_been_corrupted = FALSE; assert(zalloc_memory_allocations_have_been_corrupted); #endif } void zfree_line(void* ptr, u32 page_index) { if(ptr != NULL) { #if ZALLOC_DEBUG #if DNSCORE_DEBUG_HAS_BLOCK_TAG yassert(page_index < ZALLOC_PG_SIZE_COUNT - 2); page_index += 2; #else yassert(page_index < ZALLOC_PG_SIZE_COUNT - 1); page_index++; #endif #else yassert(page_index < ZALLOC_PG_SIZE_COUNT); #endif mutex_lock(&line_mutex[page_index]); #if DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT #if DNSCORE_DEBUG_HAS_BLOCK_TAG u64* hdr = (u64*)ptr; hdr -= 2; u64 tag = hdr[1]; debug_memory_by_tag_free_notify(zalloc_memory_by_tag_ctx, tag, (page_index - 2) << 3); #else u64* hdr = (u64*)ptr; hdr--; #endif zalloc_range_s range = {(intptr)hdr,(intptr)hdr}; ptr_node_debug *node; mutex_lock(&zalloc_pages_set_mtx); node = ptr_set_debug_find(&zalloc_pages_set, &range); mutex_unlock(&zalloc_pages_set_mtx); if(node == NULL) { fprintf(stderr, "address %p is not part of any of our allocated pages", ptr); fflush(stderr); abort(); // memory not part of the zalloc pages } if(node->value != (void*)(intptr)page_index) { int real_page_index = (int)(intptr)page_index; fprintf(stderr, "address %p is not part of pool %i (%i bytes) but of pool %i (%i bytes)", ptr, page_index - 1, (page_index - 1) << 3, real_page_index, real_page_index << 3 ); fflush(stderr); abort(); // memory not of the right size } u64 magic = *hdr; if((magic & 0xffffffff00000000LL) != 0x2a110c0000000000LL) { fprintf(stderr, "address %p has wrong magic (buffer overrun symptom)",ptr); fflush(stderr); abort(); } magic &= 0xffffffffLL; u32 expected_page_index; #if DNSCORE_DEBUG_HAS_BLOCK_TAG expected_page_index = page_index - 2; #else expected_page_index = page_index - 1; #endif if(magic != expected_page_index) { fprintf(stderr, "address %p was tagged with the wrong index %i != %i (buffer overrun symptom)",ptr, (u32)magic, expected_page_index); fflush(stderr); abort(); } ptr = hdr; #endif #if DNSCORE_DEBUG_ZALLOC_TRASHMEMORY memset(((u8*)ptr) + 8, 0xfe, page_index << 3); #endif #if ZALLOC_STATISTICS mutex_lock(&zalloc_statistics_mtx); zalloc_memory_allocated -= (page_index + 1) << 3; mutex_unlock(&zalloc_statistics_mtx); #endif void** ret = (void**)ptr; // get the pointer from the first free cell and put it in the newly freed block (thus making a new link in the chain) *ret = zalloc_line_head_get(page_index); // put the newly made link at the head of the line zalloc_line_head_set(page_index, ret); line_count[page_index]++; if(line_count[page_index] > heap_total[page_index]) { zfree_line_report(page_index); } mutex_unlock(&line_mutex[page_index]); } } /** * DEBUG */ u64 zheap_line_total(u32 page_index) { if(page_index < ADJUSTED_ALLOC_PG_SIZE_COUNT) { mutex_lock(&line_mutex[page_index]); u64 return_value = heap_total[page_index]; mutex_unlock(&line_mutex[page_index]); return return_value; } return 0; } u64 zheap_line_avail(u32 page_index) { if(page_index < ADJUSTED_ALLOC_PG_SIZE_COUNT) { mutex_lock(&line_mutex[page_index]); u64 return_value = line_count[page_index]; mutex_unlock(&line_mutex[page_index]); return return_value; } return 0; } s64 zallocatedtotal() { #if ZALLOC_STATISTICS u64 return_value = zalloc_memory_allocated; return return_value; #else return -1; #endif } /** * @brief Allocates unaligned memory of an arbitrary size using zalloc_line and malloc * * Allocates unaligned memory of an arbitrary size using zalloc_line and malloc * * @param[in] size the size to allocated * * @return a pointer to the allocated memory */ void* zalloc_unaligned(u32 size #if ZALLOC_DEBUG && DNSCORE_DEBUG_HAS_BLOCK_TAG , u64 tag #endif ) { yassert(size > 0); u8* p; size++; if(size <= 254) { u8 page_index = (size - 1) >> 3; p = (u8*) zalloc_line(page_index #if ZALLOC_DEBUG && DNSCORE_DEBUG_HAS_BLOCK_TAG , tag #endif ); *p = page_index; } else { #if !DNSCORE_HAS_MALLOC_DEBUG_SUPPORT p = (u8*)malloc(size); #else #if !DNSCORE_DEBUG_HAS_BLOCK_TAG p = (u8*)debug_malloc(size, __FILE__, __LINE__); #else p = (u8*)debug_malloc(size, __FILE__, __LINE__, ZMALLOC_TAG); #endif #endif // DNSCORE_HAS_MALLOC_DEBUG_SUPPORT if(p == NULL) { DIE(ZALLOC_ERROR_OUTOFMEMORY); } *p = 0xff; #if DNSCORE_DEBUG_ZALLOC_TRASHMEMORY memset(p + 1, 0xca, size); #endif } return ++p; } /** * @brief Frees unaligned memory of an arbitrary size using zfree_line and free * * Allocates unaligned memory of an arbitrary size using zalloc_line and malloc * * @param[in] ptr a pointer to the memory to free * */ void zfree_unaligned(void* ptr) { if(ptr != NULL) { u8* p = (u8*)ptr; u8 idx = *--p; if(idx <= 254) { zfree_line(p, idx); } else { free(p); } } } void zalloc_print_stats(output_stream *os) { #if ZALLOC_STATISTICS osformatln(os, "zdb alloc: page-sizes=%u (max %u bytes) allocated=%llu bytes mmap=%u", ADJUSTED_ALLOC_PG_SIZE_COUNT, (ADJUSTED_ALLOC_PG_SIZE_COUNT << 3), zalloc_memory_allocated, mmap_count); if(zalloc_init_done) { osprintln(os, "[ size ] blocsize -remain- -total-- -alloc-- --bytes--"); for(int i = 0; i < ADJUSTED_ALLOC_PG_SIZE_COUNT; i++) { osformatln(os, "[%6i] %-8u %-8u %-8u %-8u %-9u", (i + 1) << 3, page_size[i], line_count[i], heap_total[i], heap_total[i] - line_count[i], (heap_total[i] - line_count[i]) * (i + 1) << 3); } } #else osprintln(os, "zdb alloc: statistics not compiled in"); #endif } #else void* malloc_string_or_die(size_t len, u64 tag) { u8 *ret; MALLOC_OR_DIE(u8*,ret,len + 1,tag); *ret = (u8)MIN(255,len); ++ret; (void)tag; return ret; } void mfree_string(void *ptr_) { u8 *ptr = (u8*)ptr_; --ptr; yassert((((intptr)ptr)&1) == 0); free(ptr); } /** * ZALLOC NOT BUILT-IN : DOES NOTHING WORTH MENTIONNING */ int zalloc_init() { return FEATURE_NOT_IMPLEMENTED_ERROR; } /** * ZALLOC NOT BUILT-IN : DOES NOTHING WORTH MENTIONNING */ s64 zallocatedtotal() { return -1; } /** * ZALLOC NOT BUILT-IN : DOES NOTHING WORTH MENTIONNING */ void zalloc_print_stats(output_stream *os) { (void)os; } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/zone_reader_axfr.c0000644000000000000000000000013214505005532023011 xustar000000000000000030 mtime=1695812442.444982217 30 atime=1695812445.794030182 30 ctime=1695812494.748731312 yadifa-2.6.5-11201/lib/dnscore/src/zone_reader_axfr.c0000664000374500037450000001661514505005532022764 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup zoneaxfr AXFR file loader module * @ingroup dnscore * @brief zone functions * * Implementation of routines for the zone_data struct * - add * - adjust * - init * - parse * - print * - remove database * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnscore/dnscore-config.h" #include #include /* or netinet/in.h */ #include #include #include #include #include #include #include #include #define AXREADER_TAG 0x5245444145525841 extern logger_handle *g_zone_logger; #define MODULE_MSG_HANDLE g_zone_logger typedef struct zone_reader_axfr zone_reader_axfr; struct zone_reader_axfr { input_stream is; /* LOAD */ char* file_path; resource_record* unread_next; bool soa_found; /* LOAD */ }; static ya_result zone_reader_axfr_unread_record(zone_reader *zr, resource_record *entry) { zone_reader_axfr *zone = (zone_reader_axfr*)zr->data; resource_record *rr; u32 required = offsetof(resource_record,rdata) + entry->rdata_size; MALLOC_OR_DIE(resource_record*, rr, required, DNSRR_TAG); memcpy(rr, entry, required); rr->next = zone->unread_next; zone->unread_next = rr; return SUCCESS; } static ya_result zone_reader_axfr_read_record(zone_reader *zr, resource_record *entry) { yassert((zr != NULL) && (entry != NULL)); zone_reader_axfr *zone = (zone_reader_axfr*)zr->data; if(zone->unread_next != NULL) { resource_record *top = zone->unread_next; u32 required = offsetof(resource_record,rdata) + top->rdata_size; memcpy(entry, top, required); zone->unread_next = top->next; free(top); return 0; } ya_result return_value; u16 rdata_len; if(ISOK(return_value = input_stream_read_dnsname(&zone->is, entry->name))) { if(ISOK(return_value = input_stream_read_u16(&zone->is, &entry->type))) { if(ISOK(return_value = input_stream_read_u16(&zone->is, &entry->class))) { if(ISOK(return_value = input_stream_read_nu32(&zone->is, (u32*)&entry->ttl))) { if(ISOK(return_value = input_stream_read_nu16(&zone->is, &rdata_len))) { if(ISOK(return_value = input_stream_read_fully(&zone->is, entry->rdata, rdata_len))) { entry->rdata_size = return_value; if(entry->type == TYPE_SOA) { if(zone->soa_found) { return 1; /* done */ } zone->soa_found = TRUE; } return 0; } } } } } } return return_value; } static ya_result zone_reader_axfr_free_record(zone_reader *zone, resource_record *entry) { (void)zone; (void)entry; return OK; } static void zone_reader_axfr_close(zone_reader *zr) { yassert(zr != NULL); zone_reader_axfr *zone = (zone_reader_axfr*)zr->data; free(zone->file_path); input_stream_close(&zone->is); resource_record *rr = zone->unread_next; while(rr != NULL) { resource_record *tmp = rr; rr = rr->next; free(tmp); } free(zone); zr->data = NULL; zr->vtbl = NULL; } static bool zone_reader_axfr_canwriteback(zone_reader *zr) { yassert(zr != NULL); (void)zr; return TRUE; } static void zone_reader_axfr_handle_error(zone_reader *zr, ya_result error_code) { /* * If an error occurred loading the axfr : delete it * * More subtle tests on the error code could also be done. */ yassert(zr != NULL); if(FAIL(error_code)) { zone_reader_axfr *zone = (zone_reader_axfr*)zr->data; #if DEBUG log_debug("zone axfr: deleting broken AXFR file: %s", zone->file_path); #endif if(unlink(zone->file_path) < 0) { log_err("zone axfr: unlink(%s): %r", zone->file_path, ERRNO_ERROR); } } } static const char* zone_reader_axfr_get_last_error_message(zone_reader *zr) { // not supported yet (void)zr; return NULL; } static const zone_reader_vtbl zone_reader_axfr_vtbl = { zone_reader_axfr_read_record, zone_reader_axfr_unread_record, zone_reader_axfr_free_record, zone_reader_axfr_close, zone_reader_axfr_handle_error, zone_reader_axfr_canwriteback, zone_reader_axfr_get_last_error_message, "zone_reader_axfr" }; ya_result zone_reader_axfr_open(zone_reader *dst, const char *file_path) { zone_reader_axfr *zone; ya_result return_value; input_stream is; if(FAIL(return_value = file_input_stream_open(&is, file_path))) { return return_value; } /* ------------------------------------------------------------ */ MALLOC_OBJECT_OR_DIE(zone, zone_reader_axfr, AXREADER_TAG); ZEROMEMORY(zone, sizeof(zone_reader_axfr)); /* Initialize the new zone data */ buffer_input_stream_init(&zone->is, &is, 4096); zone->file_path = strdup(file_path); zone->soa_found = FALSE; dst->data = zone; dst->vtbl = &zone_reader_axfr_vtbl; return SUCCESS; } yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/zone_reader_text.c0000644000000000000000000000013114505005532023034 xustar000000000000000030 mtime=1695812442.406981673 30 atime=1695812445.792030153 29 ctime=1695812494.75073134 yadifa-2.6.5-11201/lib/dnscore/src/zone_reader_text.c0000664000374500037450000023173614505005532023013 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnscore/dnscore-config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dnscore/zone_reader_text.h" #define ZFREADER_TAG 0x524544414552465a #define ZFERRMSG_TAG 0x47534d525245465a #define ZONE_FILE_READER_INCLUDE_DEPTH_MAX 16 #define DOT_SYMBOL '.' #if !DNSCORE_HAS_FULL_ASCII7 #define AT_SYMBOL '@' #define VAR_SYMBOL '$' #else #define AT_SYMBOL ((char)0xff) #define VAR_SYMBOL ((char)0xfe) //#define DOT_SYMBOL ((char)0xfd) #endif logger_handle *g_zone_logger = LOGGER_HANDLE_SINK; #define MODULE_MSG_HANDLE g_zone_logger #define DEBUG_BENCH_TEXT_ZONE_PARSE 1 #if !DEBUG #undef DEBUG_BENCH_TEXT_ZONE_PARSE #define DEBUG_BENCH_TEXT_ZONE_PARSE 0 #endif static bool zone_reader_text_init_error_codes_done = FALSE; static const char * const zfr_string_delimiters = "\"\""; static const char * const zfr_multiline_delimiters = "()"; static const char * const zrf_comment_markers = ";"; static const char * const zrf_blank_makers = "\040\t\r"; static const char * const zfr_escape_characters = "\\"; #define ZONE_FILE_READER_MESSAGE_STATIC 0 #define ZONE_FILE_READER_MESSAGE_ALLOCATED 1 typedef struct zone_reader_text zone_reader_text; struct zone_reader_text { parser_s parser; resource_record* unread_next; s32 rttl_default; // $TTL s32 rttl_current; u32 dot_origin_size; // with the CHR0 sentinel s32 origin_stack_size; u16 rclass_current; u16 rdata_size; bool soa_found; bool template_source; bool rttl_default_defined; bool rttl_current_defined; u8 domain[MAX_DOMAIN_LENGTH + 1]; u8 origin[MAX_DOMAIN_LENGTH + 1]; char dot_origin[MAX_DOMAIN_LENGTH + 1]; u8 *origin_stack[PARSER_INCLUDE_DEPTH_MAX]; u8 rdata[RDATA_MAX_LENGTH]; input_stream includes[ZONE_FILE_READER_INCLUDE_DEPTH_MAX]; char *file_name[ZONE_FILE_READER_INCLUDE_DEPTH_MAX]; u8 includes_count; // ya_result error_message_code; u8 error_message_allocated; // 0: static 1: malloc char *error_message_buffer; // It's not aligned but this is an exception : // _ This is a rarely used structure (don't care too much about a hole) // _ This is an hopefully rarely used field (best case: "never" (besides setting it up to NULL)) // _ Putting it among the more popular fields will likely increase misses }; static void zone_reader_text_free_error_message(zone_reader_text *zfr) { if(zfr->error_message_allocated == ZONE_FILE_READER_MESSAGE_ALLOCATED) { free(zfr->error_message_buffer); } } /* static void zone_reader_text_clear_error_message(zone_reader_text *zfr) { zone_reader_text_free_error_message(zfr); zfr->error_message_buffer = NULL; } */ static ya_result zone_reader_text_cstr_to_locase_dnsname_with_check_len_with_origin(u8* name_parm, const char* text, u32 text_len, const u8 *origin, parser_s *p) { ya_result ret; if(FAIL(ret = cstr_to_locase_dnsname_with_check_len_with_origin(name_parm, text, text_len, origin))) { bool retry = FALSE; char retry_text[MAX_DOMAIN_LENGTH]; if(text_len <= MAX_DOMAIN_LENGTH) { for(u32 i = 0; i < text_len; ++i) { char c = text[i]; switch(c) { case VAR_SYMBOL: { retry_text[i] = '$'; retry = TRUE; break; } case AT_SYMBOL: { retry_text[i] = '@'; retry = TRUE; break; } default: { retry_text[i] = c; break; } } } } if(retry) { if(ISOK(ret = cstr_to_locase_dnsname_with_check_len_with_origin(name_parm, retry_text, text_len, origin))) { // an escape is probably missing /* char *file_name = "?"; if((p->includes_count > 0) && (p->includes_count < ZONE_FILE_READER_INCLUDE_DEPTH_MAX)) { if(p->file_name[p->includes_count - 1] != NULL) { file_name = p->file_name[p->includes_count - 1]; } } log_warn("zone parse: there is probably an escape missing in front of a '$' or a '@' in file '%s' at line %u for %{dnsname}", file_name, p->line_number, domain); */ log_warn("zone parse: there is probably an escape missing in front of a '$' or a '@' at line %u for %{dnsname}", p->line_number, name_parm); } } } return ret; } static inline ya_result zone_reader_text_copy_rdata_inline(parser_s *p, u16 rtype, u8 *rdata, u32 rdata_size, const u8 *origin) { const char *text; u32 text_len; ya_result return_code; char text_buffer[1024]; type_bit_maps_context tbmctx; if(FAIL(return_code = parser_copy_next_word(p, text_buffer, sizeof(text_buffer)))) { return return_code; } text = text_buffer; text_len = return_code; if(!((text_len >= 1) && (text[0] == '#'))) { switch(rtype) { case TYPE_A: { if(inet_pton(AF_INET, text, rdata)) { return_code = 4; } else { return_code = INCORRECT_IPADDRESS; } break; } case TYPE_AAAA: { if(inet_pton(AF_INET6, text, rdata)) { return_code = 16; } else { return_code = INCORRECT_IPADDRESS; } break; } case TYPE_SOA: { s32 total_size; if(FAIL(return_code = zone_reader_text_cstr_to_locase_dnsname_with_check_len_with_origin(rdata, text, text_len, origin, p))) { break; } total_size = return_code; rdata += return_code; if(FAIL(return_code = parser_copy_next_fqdn_locase_with_origin(p, rdata, origin))) { break; } total_size += return_code + 20; rdata += return_code; return_code = total_size; for(u8 i = 5; i > 0; i--) { s32 tmp_int32; ya_result err; if(FAIL(err = parser_copy_next_ttl(p, &tmp_int32))) { return_code = err; break; } tmp_int32 = htonl(tmp_int32); SET_U32_AT_P(rdata, tmp_int32); rdata += 4; } break; } case TYPE_NS: case TYPE_CNAME: case TYPE_PTR: #if !HAS_NOOBSOLETETYPES case TYPE_MD: /** @NOTE: obsolete */ case TYPE_MF: /** NOTE: obsolete */ case TYPE_MB: /** NOTE: obsolete */ case TYPE_MG: /** NOTE: obsolete */ case TYPE_MR: /** NOTE: obsolete */ #endif { return_code = zone_reader_text_cstr_to_locase_dnsname_with_check_len_with_origin(rdata, text, text_len, origin, p); break; } #if !HAS_NOOBSOLETETYPES case TYPE_WKS: { // ip address if(!inet_pton(AF_INET, text, rdata)) { return_code = INCORRECT_IPADDRESS; break; } rdata += 4; int protocol; if(FAIL(return_code = parser_get_network_protocol_from_next_word(p, &protocol))) { break; } rdata[0] = (u8) protocol; rdata++; ZEROMEMORY(rdata, rdata_size - 1); int port_limit = (rdata_size - 5) << 3; int max_index = -1; for(;;) { int service_port; if(FAIL(return_code = parser_get_network_service_port_from_next_word(p, &service_port))) { break; } if(service_port > port_limit) { return_code = MAKE_ERRNO_ERROR(ERANGE); break; } int index = service_port >> 3; rdata[index] |= 0x80 >> (service_port & 7); if(index > max_index) { max_index = index; } } if(FAIL(return_code)) { break; } if(max_index < 0) // @todo 20150608 timh -- is this the right way to do it? { // @note 20220805 edf -- this seems pointless. It seems max_index is only < 0 if there has been an error. return_code = INVALID_RECORD; break; } return_code = max_index + 6; // ipv4 + proto + index=>+1 parser_set_eol(p); // @todo 20150608 timh -- is this necessary? break; } #endif case TYPE_MX: case TYPE_KX: case TYPE_LP: case TYPE_AFSDB: { u16 preference; if(FAIL(return_code = parser_get_u16(text, text_len, &preference))) { break; } preference = htons(preference); SET_U16_AT_P(rdata, preference); rdata += 2; if(FAIL(return_code = parser_copy_next_fqdn_locase_with_origin(p, rdata, origin))) { break; } return_code += 2; break; } case TYPE_RRSIG: { u16 rtype; if(FAIL(return_code = dns_type_from_case_name_length(text, text_len, &rtype))) { break; } SET_U16_AT_P(rdata, rtype); rdata += 2; // algorithm (8 bits integer) if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { break; } rdata++; // labels (8 bits integer) if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { break; } rdata++; // original TTL (32 bits integer) s32 ttl; if(FAIL(return_code = parser_copy_next_ttl(p, &ttl))) { break; } ttl = htonl(ttl); SET_U32_AT_P(rdata, ttl); rdata += 4; // signature expiration (YYYYMMDDHHMMSS epoch -> 32 bits) u32 epoch; if(FAIL(return_code = parser_copy_next_yyyymmddhhmmss(p, &epoch))) { break; } epoch = htonl(epoch); SET_U32_AT_P(rdata, epoch); rdata += 4; // signature inception (YYYYMMDDHHMMSS epoch -> 32 bits) if(FAIL(return_code = parser_copy_next_yyyymmddhhmmss(p, &epoch))) { break; } epoch = htonl(epoch); SET_U32_AT_P(rdata, epoch); rdata += 4; // key tag (16 bits integer) u16 tag; if(FAIL(return_code = parser_copy_next_u16(p, &tag))) { break; } tag = htons(tag); SET_U16_AT_P(rdata, tag); rdata += 2; // signer's name (fqdn) if(FAIL(return_code = parser_copy_next_fqdn_with_origin(p, rdata, origin))) { break; } rdata += return_code; u32 signer_len = return_code; // signature (base64) if(FAIL(return_code = parser_concat_next_tokens_nospace(p))) { break; } if(FAIL(return_code = base64_decode(parser_text(p), parser_text_length(p), rdata))) { break; } return_code += 18 + signer_len; break; } case TYPE_DNSKEY: case TYPE_CDNSKEY: { // flags u16 flags; if(FAIL(return_code = parser_get_u16(text, text_len, &flags))) { break; } flags = htons(flags); SET_U16_AT_P(rdata, flags); rdata += 2; // protocol (8 bits integer) if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { break; } rdata++; // algorithm (8 bits integer) if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { if(ISOK(return_code = parser_copy_word(p, text_buffer, sizeof(text_buffer)))) { if(FAIL(return_code = dns_encryption_algorithm_from_name(text_buffer, rdata))) { break; } } else { break; } } rdata++; // key (base64) if(FAIL(return_code = parser_concat_next_tokens_nospace(p))) { break; } if(FAIL(return_code = base64_decode(parser_text(p), parser_text_length(p), rdata))) { break; } return_code += 4; break; } case TYPE_OPENPGPKEY: { if(FAIL(return_code = parser_concat_current_and_next_tokens_nospace(p))) { break; } return_code = base64_decode(parser_text(p), parser_text_length(p), rdata); break; } case TYPE_NSEC3PARAM: { // hash algorithm if(FAIL(return_code = parser_get_u8(text, text_len, rdata))) { break; } rdata++; // flags if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { break; } rdata++; // iterations u16 iterations; if(FAIL(return_code = parser_copy_next_u16(p, &iterations))) { break; } iterations = htons(iterations); SET_U16_AT_P(rdata, iterations); rdata += 2; // salt if(FAIL(return_code = parser_next_token(p))) { break; } if(! ((parser_text_length(p) == 1) && (parser_text(p)[0] == '-')) ) { if(FAIL(return_code = base16_decode(parser_text(p), parser_text_length(p), rdata + 1))) { break; } if(return_code > 255) { return_code = ZONEFILE_SALT_TOO_BIG; // parse error ... break; } } else { // no salt return_code = 0; } rdata[0] = (u8)return_code; return_code += 5; break; } case TYPE_NSEC3: { u8 *rdata_start = rdata; // hash algorithm if(FAIL(return_code = parser_get_u8(text, text_len, rdata))) { break; } rdata++; // flags if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { break; } rdata++; // iterations u16 iterations; if(FAIL(return_code = parser_copy_next_u16(p, &iterations))) { break; } iterations = htons(iterations); SET_U16_AT_P(rdata, iterations); rdata += 2; // salt if(FAIL(return_code = parser_next_token(p))) { break; } if(! ((parser_text_length(p) == 1) && (parser_text(p)[0] == '-')) ) { if(FAIL(return_code = base16_decode(parser_text(p), parser_text_length(p), rdata + 1))) { break; } if(return_code > 255) { return_code = ZONEFILE_SALT_TOO_BIG; // parse error ... break; } } else { return_code = 0; } rdata[0] = (u8)return_code; rdata += return_code + 1; // digest if(FAIL(return_code = parser_next_token(p))) { break; } if(FAIL(return_code = base32hex_decode(parser_text(p), parser_text_length(p), rdata + 1))) { break; } rdata[0] = (u8)return_code; rdata += return_code + 1; // type bitmap if(FAIL(return_code = parser_type_bit_maps_initialise(p, &tbmctx))) { break; } if(return_code > 0) { type_bit_maps_write(&tbmctx, rdata); rdata += return_code; } return_code = rdata - rdata_start; parser_set_eol(p); break; } case TYPE_NSEC: { u8 *rdata_start = rdata; if(FAIL(return_code = zone_reader_text_cstr_to_locase_dnsname_with_check_len_with_origin(rdata, text, text_len, origin, p))) { break; } rdata += return_code; // type bitmap if(FAIL(return_code = parser_type_bit_maps_initialise(p, &tbmctx))) { break; } type_bit_maps_write(&tbmctx, rdata); rdata += return_code; return_code = rdata - rdata_start; parser_set_eol(p); break; } case TYPE_DS: case TYPE_CDS: case TYPE_DLV: { // keytag u16 keytag; if(FAIL(return_code = parser_get_u16(text, text_len, &keytag))) { break; } keytag = htons(keytag); SET_U16_AT_P(rdata, keytag); rdata += 2; // algorithm if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { break; } rdata++; // digest type if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { break; } rdata++; // digest if(FAIL(return_code = parser_concat_next_tokens_nospace(p))) { break; } if(FAIL(return_code = base16_decode(parser_text(p), parser_text_length(p), rdata))) { break; } return_code += 4; break; } case TYPE_TXT: case TYPE_SPF: // discontinued { u8 *rdata_start = rdata; for(;;) { if(text_len > 255) { return_code = ZONEFILE_TEXT_TOO_BIG; break; } *rdata++ = (u8)text_len; memcpy(rdata, text, text_len); rdata += text_len; if(FAIL(return_code = parser_next_token(p))) { break; } if((return_code & (PARSER_COMMENT|PARSER_EOL|PARSER_EOF)) != 0) { // stop break; } text = parser_text(p); text_len = parser_text_length(p); } if(ISOK(return_code)) { return_code = rdata - rdata_start; parser_set_eol(p); } break; } case TYPE_SSHFP: { // algorithm if(FAIL(return_code = parser_get_u8(text, text_len, rdata))) { break; } rdata++; // fp type if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { break; } rdata++; // fingerprint if(FAIL(return_code = parser_concat_next_tokens_nospace(p))) { break; } if(FAIL(return_code = base16_decode(parser_text(p), parser_text_length(p), rdata))) { break; } return_code += 2; break; } case TYPE_TLSA: { // ? if(FAIL(return_code = parser_get_u8(text, text_len, rdata))) { break; } rdata++; // ? if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { break; } rdata++; // ? if(FAIL(return_code = parser_copy_next_u8(p, rdata))) { break; } rdata++; // ? if(FAIL(return_code = parser_concat_next_tokens_nospace(p))) { break; } if(FAIL(return_code = base16_decode(parser_text(p), parser_text_length(p), rdata))) { break; } return_code += 3; break; } case TYPE_SRV: { u16 tmp16; // ? if(FAIL(return_code = parser_get_u16(text, text_len, &tmp16))) { break; } tmp16 = htons(tmp16); SET_U16_AT_P(rdata, tmp16); rdata += 2; // ? if(FAIL(return_code = parser_copy_next_u16(p, &tmp16))) { break; } tmp16 = htons(tmp16); SET_U16_AT_P(rdata, tmp16); rdata += 2; // ? if(FAIL(return_code = parser_copy_next_u16(p, &tmp16))) { break; } tmp16 = htons(tmp16); SET_U16_AT_P(rdata, tmp16); rdata += 2; if(FAIL(return_code = parser_copy_next_fqdn_with_origin(p, rdata, origin))) { break; } return_code += 6; break; } case TYPE_NAPTR: { u8 *rdata_start = rdata; u16 tmp16; // order if(FAIL(return_code = parser_get_u16(text, text_len, &tmp16))) { break; } tmp16 = htons(tmp16); SET_U16_AT_P(rdata, tmp16); rdata += 2; // preference if(FAIL(return_code = parser_copy_next_u16(p, &tmp16))) { break; } tmp16 = htons(tmp16); SET_U16_AT_P(rdata, tmp16); rdata += 2; // flags if(FAIL(return_code = parser_next_token(p))) { break; } if((return_code & (PARSER_COMMENT|PARSER_EOL|PARSER_EOF)) != 0) { // stop break; } text = parser_text(p); text_len = parser_text_length(p); if(text_len > 255) { return_code = ZONEFILE_FLAGS_TOO_BIG; break; } *rdata++ = (u8)text_len; memcpy(rdata, text, text_len); rdata += text_len; // service if(FAIL(return_code = parser_next_token(p))) { break; } if((return_code & (PARSER_COMMENT|PARSER_EOL|PARSER_EOF)) != 0) { // stop break; } text = parser_text(p); text_len = parser_text_length(p); if(text_len > 255) { return_code = ZONEFILE_SERVICE_TOO_BIG; break; } *rdata++ = (u8)text_len; memcpy(rdata, text, text_len); rdata += text_len; // regex if(FAIL(return_code = parser_next_token(p))) { break; } if((return_code & (PARSER_COMMENT|PARSER_EOL|PARSER_EOF)) != 0) { // stop break; } text = parser_text(p); text_len = parser_text_length(p); if(text_len > 255) { return_code = ZONEFILE_REGEX_TOO_BIG; break; } *rdata++ = (u8)text_len; memcpy(rdata, text, text_len); rdata += text_len; if(FAIL(return_code = parser_copy_next_fqdn_with_origin(p, rdata, origin))) { break; } return_code += rdata - rdata_start; break; } // exist out of two parts // 1. mbox-dname // 2. txt-dname case TYPE_RP: { u8 *rdata_start = rdata; // 1.mbox-name1 //s32 total_size; // return_code = "length" or "error code" if(FAIL(return_code = zone_reader_text_cstr_to_locase_dnsname_with_check_len_with_origin(rdata, text, text_len, origin, p))) { break; } // set rdata to the next chunk rdata += return_code; if(FAIL(return_code = parser_copy_next_fqdn_locase_with_origin(p, rdata, origin))) { break; } return_code = rdata - rdata_start + return_code; break; } case TYPE_HINFO: // should not be supported anymore { u8 *rdata_start = rdata; if(text_len > 255) { return_code = ZONEFILE_TEXT_TOO_BIG; break; } *rdata++ = (u8)text_len; memcpy(rdata, text, text_len); rdata += text_len; if(FAIL(return_code = parser_next_token(p))) { break; } if((return_code & (PARSER_COMMENT|PARSER_EOL|PARSER_EOF)) != 0) { // stop break; } text = parser_text(p); text_len = parser_text_length(p); if(text_len > 255) { return_code = ZONEFILE_TEXT_TOO_BIG; break; } *rdata++ = (u8)text_len; memcpy(rdata, text, text_len); rdata += text_len; if(FAIL(return_code = parser_copy_next_fqdn_with_origin(p, rdata, origin))) { break; } return_code += rdata - rdata_start; break; } case TYPE_NID: case TYPE_L64: { u16 preference; if(FAIL(return_code = parser_get_u16(text, text_len, &preference))) { break; } preference = htons(preference); SET_U16_AT_P(rdata, preference); if(FAIL(return_code = parser_next_token(p))) { break; } memcpy(text_buffer, parser_text(p), parser_text_length(p)); text_buffer[parser_text_length(p)] = '\0'; // hex:hex:hex:hex unsigned int a,b,c,d; if(sscanf(text_buffer, "%x:%x:%x:%x", &a,&b,&c,&d) != 4) { return_code = PARSEB16_ERROR; break; } if((a|b|c|d) > 65535) { return_code = PARSEB16_ERROR; break; } SET_U16_AT(rdata[2], htons((u16)a)); SET_U16_AT(rdata[4], htons((u16)b)); SET_U16_AT(rdata[6], htons((u16)c)); SET_U16_AT(rdata[8], htons((u16)d)); return_code = 10; break; } case TYPE_L32: { u16 preference; if(FAIL(return_code = parser_get_u16(text, text_len, &preference))) { break; } preference = htons(preference); SET_U16_AT_P(rdata, preference); if(FAIL(return_code = parser_next_token(p))) { break; } memcpy(text_buffer, parser_text(p), parser_text_length(p)); text_buffer[parser_text_length(p)] = '\0'; // hex:hex:hex:hex unsigned int a,b,c,d; if(sscanf(text_buffer, "%u.%u.%u.%u", &a,&b,&c,&d) != 4) { return_code = PARSEB16_ERROR; break; } if((a|b|c|d) > 255) { return_code = PARSEB16_ERROR; break; } rdata[2] = (u8)a; rdata[3] = (u8)b; rdata[4] = (u8)c; rdata[5] = (u8)d; return_code = 6; break; } case TYPE_EUI48: { text_buffer[parser_text_length(p)] = '\0'; unsigned int a,b,c,d,e,f; if(sscanf(text_buffer, "%x-%x-%x-%x-%x-%x", &a,&b,&c,&d,&e,&f) != 6) { return_code = PARSEB16_ERROR; break; } if((a|b|c|d|e|f) > 255) { return_code = PARSEB16_ERROR; break; } rdata[0] = (u8)a; rdata[1] = (u8)b; rdata[2] = (u8)c; rdata[3] = (u8)d; rdata[4] = (u8)e; rdata[5] = (u8)f; return_code = 6; break; } case TYPE_EUI64: { text_buffer[parser_text_length(p)] = '\0'; unsigned int a,b,c,d,e,f,g,h; if(sscanf(text_buffer, "%x-%x-%x-%x-%x-%x-%x-%x", &a,&b,&c,&d,&e,&f,&g,&h) != 8) { return_code = PARSEB16_ERROR; break; } if((a|b|c|d|e|f|g|h) > 255) { return_code = PARSEB16_ERROR; break; } rdata[0] = (u8)a; rdata[1] = (u8)b; rdata[2] = (u8)c; rdata[3] = (u8)d; rdata[4] = (u8)e; rdata[5] = (u8)f; rdata[6] = (u8)g; rdata[7] = (u8)h; return_code = 8; break; } case TYPE_TSIG: for(;;) { return_code = parser_next_token(p); if((return_code == PARSER_CHAR_TYPE_EOL) || (return_code == PARSER_EOL) || (return_code == PARSER_EOF)) { break; } } case TYPE_OPT: case TYPE_IXFR: case TYPE_AXFR: case TYPE_ANY: { return_code = ZONEFILE_INVALID_TYPE; break; } default: { return_code = UNSUPPORTED_RECORD; log_err("zone file: %{dnsname}: %{dnstype}: %r", origin, &rtype, return_code); break; } } // end switch } else { // hex return_code = ZONEFILE_RDATA_PARSE_ERROR; /// parse error if((text_len == 1) && (text[0] == '#')) { u16 unknown_rdata_len; if(ISOK(return_code = parser_copy_next_u16(p, &unknown_rdata_len))) { return_code = ZONEFILE_RDATA_BUFFER_TOO_SMALL; /// buffer too small if(unknown_rdata_len <= rdata_size) { if(ISOK(return_code = parser_concat_next_tokens_nospace(p))) { if(((u32)return_code << 1) <= rdata_size) { if(ISOK(return_code = base16_decode(parser_text(p), parser_text_length(p), rdata))) { if(return_code != unknown_rdata_len) { return_code = ZONEFILE_RDATA_SIZE_MISMATCH; /// unexpected size } } } else { return_code = ZONEFILE_RDATA_BUFFER_TOO_SMALL; /// buffer too small } } } } } } // if(!((text_len >= 1) && (text[0] == '#'))) if(ISOK(return_code)) { // expect to find EOL ya_result got_eol = parser_expect_eol(p); if(FAIL(got_eol)) { return_code = got_eol; log_err("zone file: %{dnsname}: %{dnstype}: expected end of line: %r", origin, &rtype, return_code); } } return return_code; } static ya_result zone_reader_text_unread_record(zone_reader *zr, resource_record *entry) { zone_reader_text *zfr = (zone_reader_text*)zr->data; resource_record *rr; u32 required = offsetof(resource_record,rdata) + entry->rdata_size; MALLOC_OR_DIE(resource_record*, rr, required, DNSRR_TAG); memcpy(rr, entry, required); rr->next = zfr->unread_next; zfr->unread_next = rr; return SUCCESS; } static void zone_reader_text_escaped_string_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; #if !DNSCORE_HAS_FULL_ASCII7 output_stream_write(os, value, strlen((const char*)value)); #else const char *text = (const char*)value; for(;;) { char c = *text; switch(c) { case '\0': { return; } case VAR_SYMBOL: { output_stream_write_u8(os, '$'); break; } case AT_SYMBOL: { output_stream_write_u8(os, '@'); break; } case '$': { output_stream_write_u8(os, '\\'); output_stream_write_u8(os, '$'); break; } case '@': { output_stream_write_u8(os, '\\'); output_stream_write_u8(os, '@'); break; } default: { output_stream_write_u8(os, c); break; } } ++text; } #endif } static ya_result zone_reader_text_read_record(zone_reader *zr, resource_record *entry) { yassert((zr != NULL) && (entry != NULL)); zone_reader_text *zfr = (zone_reader_text*)zr->data; if(zfr->unread_next != NULL) { resource_record *top = zfr->unread_next; u32 required = offsetof(resource_record,rdata) + top->rdata_size; memcpy(entry, top, required); zfr->unread_next = top->next; free(top); return 0; } parser_s *p = &zfr->parser; ya_result return_code; for(;;) { if(ISOK(return_code = parser_next_token(p))) { if(!(return_code & PARSER_WORD)) { if(return_code & PARSER_COMMENT) { #if DO_PRINT print("[COMMENT]"); #endif continue; } if(return_code & PARSER_EOL) { #if DO_PRINT println("[EOL]"); #endif continue; } if(return_code & PARSER_EOF) { #if DO_PRINT println("[EOF]"); #endif if(zfr->origin_stack[--zfr->origin_stack_size] != NULL) { dnsname_copy(zfr->origin, zfr->origin_stack[zfr->origin_stack_size]); zfr->dot_origin_size = dnsname_to_cstr(&zfr->dot_origin[1], zfr->origin) + 1; dnsname_zfree(zfr->origin_stack[zfr->origin_stack_size]); } input_stream *completed_stream = parser_pop_stream(p); #if DEBUG if(zfr->includes_count <= 0) { abort(); } #endif --zfr->includes_count; #if DEBUG if(zfr->file_name[zfr->includes_count] == NULL) { abort(); } #endif free(zfr->file_name[zfr->includes_count]); input_stream_close(completed_stream); if(parser_stream_count(p) > 0) { continue; } else { break; } } continue; } p->needle_mark = p->text; // keywords or new domain u32 text_len = parser_text_length(p); const char *text = parser_text(p); if(text_len > 0) { if(text[0] == VAR_SYMBOL) { // keyword match if(parse_word_case_match(&text[1], text_len - 1, "ORIGIN", 6)) { if(FAIL(return_code = parser_next_word(p))) { entry->name[0] = '\0'; entry->type = TYPE_NONE; entry->class = CLASS_NONE; entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = return_code; format_writer escaped_text = {zone_reader_text_escaped_string_format, text}; if(ISOK(asformat(&zfr->error_message_buffer, "failed to parse $ORIGIN from line \"%w\"", &escaped_text))) { zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; } return return_code; } text_len = parser_text_length(p); text = parser_text(p); memcpy(&zfr->dot_origin[1], text, text_len); zfr->dot_origin_size = text_len + 1; // +1 for the dot if(FAIL(return_code = cstr_to_locase_dnsname_with_check_len(zfr->origin, &zfr->dot_origin[1], zfr->dot_origin_size - 1))) { entry->name[0] = '\0'; entry->type = TYPE_NONE; entry->class = CLASS_NONE; entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = return_code; format_writer escaped_text = {zone_reader_text_escaped_string_format, text}; if(ISOK(asformat(&zfr->error_message_buffer, "failed to parse $ORIGIN from line \"%w\"", &escaped_text))) { zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; } return return_code; } } else if(parse_word_case_match(&text[1], text_len - 1, "TTL", 3)) { if(FAIL(return_code = parser_copy_next_ttl(p, &zfr->rttl_default))) { entry->name[0] = '\0'; entry->type = TYPE_NONE; entry->class = CLASS_NONE; entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = return_code; format_writer escaped_text = {zone_reader_text_escaped_string_format, text}; if(ISOK(asformat(&zfr->error_message_buffer, "failed to parse $TTL from line \"%w\"", &escaped_text))) { zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; } return return_code; } zfr->rttl_current = zfr->rttl_default; zfr->rttl_default_defined = TRUE; } else if(parse_word_case_match(&text[1], text_len - 1, "INCLUDE", 7)) { char file_name[PATH_MAX]; if(FAIL(return_code = parser_copy_next_word(p, file_name, sizeof(file_name)))) { entry->name[0] = '\0'; entry->type = TYPE_NONE; entry->class = CLASS_NONE; entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = ZONEFILE_EXPECTED_FILE_PATH; format_writer escaped_text = {zone_reader_text_escaped_string_format, text}; if(ISOK(asformat(&zfr->error_message_buffer, "failed to parse $INCLUDE from line \"%w\"", &escaped_text))) { zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; } return return_code; } if(file_name[0] != '/') { // prepend the path of current file // path + current = zfr->file_name[zfr->includes_count - 1]; char *current = zfr->file_name[zfr->includes_count - 1]; char *path_end = strrchr(current, '/'); if(path_end != NULL) { size_t path_len = path_end - current + 1; size_t file_name_len = strlen(file_name) + 1; if(path_len + file_name_len < sizeof(file_name)) { memmove(&file_name[path_len], file_name, file_name_len); memcpy(file_name, current, path_len); } else { entry->name[0] = '\0'; entry->type = TYPE_NONE; entry->class = CLASS_NONE; entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = BUFFER_WOULD_OVERFLOW; format_writer escaped_text = {zone_reader_text_escaped_string_format, text}; if(ISOK(asformat(&zfr->error_message_buffer, "$INCLUDE absolute path of file is too big, from line \"%w\"", &escaped_text))) { zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; } return BUFFER_WOULD_OVERFLOW; } } } u8 new_origin[MAX_DOMAIN_LENGTH]; if(ISOK(return_code = parser_copy_next_fqdn(p, new_origin))) { if((return_code & PARSER_WORD) != 0) { // push current origin and replace zfr->origin_stack[zfr->origin_stack_size++] = dnsname_zdup(zfr->origin); dnsname_copy(zfr->origin, new_origin); zfr->dot_origin_size = dnsname_to_cstr(&zfr->dot_origin[1], new_origin) + 1; } else { zfr->origin_stack[zfr->origin_stack_size++] = NULL; } } else { zfr->origin_stack[zfr->origin_stack_size++] = NULL; } ya_result err; if(ISOK(err = file_input_stream_open(&zfr->includes[zfr->includes_count], file_name))) { zfr->file_name[zfr->includes_count] = strdup(file_name); parser_push_stream(&zfr->parser, &zfr->includes[zfr->includes_count++]); } else { entry->name[0] = '\0'; entry->type = TYPE_NONE; entry->class = CLASS_NONE; entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = err; if(ISOK(asformat(&zfr->error_message_buffer, "failed to open file %s", file_name))) { zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; } return err; } } else if(parse_word_match(&text[1], text_len - 1, "GENERATE", 8)) { entry->name[0] = '\0'; entry->type = TYPE_NONE; entry->class = CLASS_NONE; entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = ZONEFILE_FEATURE_NOT_SUPPORTED; zfr->error_message_buffer = "$GENERATE not supported"; return ZONEFILE_FEATURE_NOT_SUPPORTED; } else if(parse_word_match(&text[1], text_len - 1, "CLASS", 5)) { } else if(parse_word_match(&text[1], text_len - 1, "RETURN", 6)) { if(zfr->origin_stack[--zfr->origin_stack_size] != NULL) { dnsname_copy(zfr->origin, zfr->origin_stack[zfr->origin_stack_size]); zfr->dot_origin_size = dnsname_to_cstr(&zfr->dot_origin[1], zfr->origin) + 1; dnsname_zfree(zfr->origin_stack[zfr->origin_stack_size]); } input_stream *completed_stream = parser_pop_stream(p); free(zfr->file_name[zfr->includes_count]); input_stream_close(completed_stream); if(parser_stream_count(p) > 0) { continue; } else { break; } } else if(parse_word_match(&text[1], text_len - 1, "END", 3)) { break; } } else // parse record { // domain if((return_code & PARSER_BLANK_START) == 0) { // new domain u8 *domain = entry->name; if(!((text_len == 1) && (text[0] == AT_SYMBOL))) { if(text[text_len - 1] != DOT_SYMBOL) { if(FAIL(return_code = charp_to_locase_dnsname_with_check(domain, text, text_len))) { bool retry = FALSE; char retry_text[MAX_DOMAIN_LENGTH]; if(text_len <= MAX_DOMAIN_LENGTH) { for(u32 i = 0; i < text_len; ++i) { char c = text[i]; switch(c) { case VAR_SYMBOL: { retry_text[i] = '$'; retry = TRUE; break; } case AT_SYMBOL: { retry_text[i] = '@'; retry = TRUE; break; } default: { retry_text[i] = c; break; } } } } if(retry) { if(ISOK(return_code = charp_to_locase_dnsname_with_check(domain, retry_text, text_len))) { // an escape is probably missing char *file_name = "?"; if((zfr->includes_count > 0) && (zfr->includes_count < ZONE_FILE_READER_INCLUDE_DEPTH_MAX)) { if(zfr->file_name[zfr->includes_count - 1] != NULL) { file_name = zfr->file_name[zfr->includes_count - 1]; } } log_warn("zone parse: there is probably an escape missing in front of a '$' or a '@' in file '%s' at line %u for %{dnsname}", file_name, p->line_number, domain); } } if(FAIL(return_code)) { entry->type = TYPE_NONE; entry->class = CLASS_NONE; entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = return_code; MALLOC_OR_DIE(char*, zfr->error_message_buffer, text_len + 1, ZFERRMSG_TAG); memcpy(zfr->error_message_buffer, text, text_len); zfr->error_message_buffer[text_len] = '\0'; zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; return return_code; } } /*return_code =*/ dnsname_copy(&domain[return_code - 1], zfr->origin); /// @note: cannot fail } else { if(FAIL(return_code = charp_to_locase_dnsname(domain, text, text_len))) { entry->type = TYPE_NONE; entry->class = CLASS_NONE; entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = return_code; MALLOC_OR_DIE(char*, zfr->error_message_buffer, text_len + 1, ZFERRMSG_TAG); memcpy(zfr->error_message_buffer, text, text_len); zfr->error_message_buffer[text_len] = '\0'; zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; return return_code; } } } else // label is @ { dnsname_copy(domain, zfr->origin); /// @note: cannot fail dnsname_to_cstr(&zfr->dot_origin[1], zfr->origin); /// @note: cannot fail zfr->dot_origin_size = return_code + 1; zfr->template_source = TRUE; } } else { parser_rewind(p); } // TTL CLASS TYPE RDATA // CLASS TTL TYPE RDATA parser_mark(p); if(ISOK(parser_copy_next_ttl(p, &zfr->rttl_current))) // parses as an int ? { entry->ttl = zfr->rttl_current; zfr->rttl_current_defined = TRUE; parser_mark(p); if(FAIL(parser_copy_next_class(p, &zfr->rclass_current))) // TTL no CLASS { parser_rewind(p); } // else TTL + CLASS } else { parser_rewind(p); if(ISOK(parser_copy_next_class(p, &zfr->rclass_current))) { parser_mark(p); if(ISOK(parser_copy_next_ttl(p, &zfr->rttl_current))) // parses as an int ? // CLASS + TTL { entry->ttl = zfr->rttl_current; zfr->rttl_current_defined = TRUE; } else { if(!zfr->rttl_default_defined) // CLASS no TTL, no $TTL { if(zfr->rttl_current_defined) { entry->ttl = zfr->rttl_current; } else { // this will be handled with the SOA case } } parser_rewind(p); // CLASS no TTL, + $TTL entry->ttl = zfr->rttl_default; } } else // no CLASS, no TTL, $TTL ? { parser_rewind(p); if(zfr->rttl_default_defined) { entry->ttl = zfr->rttl_default; } else { entry->ttl = zfr->rttl_current; } } } entry->class = zfr->rclass_current; u16 rtype; if(FAIL(return_code = parser_copy_next_type(p, &rtype))) { entry->type = TYPE_NONE; entry->class = CLASS_NONE; entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = return_code; format_writer escaped_text = {zone_reader_text_escaped_string_format, text}; if(ISOK(asformat(&zfr->error_message_buffer, "could not parse type for %{dnsname} from line %i: \"%w\"", entry->name, parser_get_line_number(p), &escaped_text))) { zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; } return return_code; } entry->type = rtype; #if DNSCORE_HAS_FULL_ASCII7 parser_del_translation(&zfr->parser, '@'); parser_del_translation(&zfr->parser, '$'); #endif if(rtype != TYPE_SOA) { if(FAIL(return_code = zone_reader_text_copy_rdata_inline(p, rtype, entry->rdata, sizeof(entry->rdata), zfr->origin))) { entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = return_code; format_writer escaped_text = {zone_reader_text_escaped_string_format, text}; if(ISOK(asformat(&zfr->error_message_buffer, "could not parse rdata for %{dnsname} %{dnsclass} %{dnstype} from line \"%w\"", entry->name, &entry->class, &entry->type, &escaped_text))) { zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; } return return_code; } entry->rdata_size = return_code; } else // SOA { if(entry->class == CLASS_NONE) { entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = ZONEFILE_SOA_WITHOUT_CLASS; zfr->error_message_buffer = "no class set on the SOA record"; return ZONEFILE_SOA_WITHOUT_CLASS; } if(FAIL(return_code = zone_reader_text_copy_rdata_inline(p, rtype, entry->rdata, sizeof(entry->rdata), zfr->origin))) { entry->rdata_size = 0; // zone_reader_text_free_error_message(zfr); zfr->error_message_code = return_code; format_writer escaped_text = {zone_reader_text_escaped_string_format, text}; if(ISOK(asformat(&zfr->error_message_buffer, "could not parse rdata for %{dnsname} %{dnsclass} %{dnstype} from line \"%w\"", entry->name, &entry->class, &entry->type, &escaped_text))) { zfr->error_message_allocated = ZONE_FILE_READER_MESSAGE_ALLOCATED; } return return_code; } entry->rdata_size = return_code; // FULL RECORD READY if(!(zfr->rttl_default_defined || zfr->rttl_current_defined)) { u8 *p = entry->rdata; p += entry->rdata_size - 4; zfr->rttl_default = zfr->rttl_current = ntohl(GET_U32_AT_P(p)); zfr->rttl_default_defined = zfr->rttl_current_defined = TRUE; entry->ttl = zfr->rttl_default; } } #if DNSCORE_HAS_FULL_ASCII7 parser_add_translation(&zfr->parser, '@', AT_SYMBOL); parser_add_translation(&zfr->parser, '$', VAR_SYMBOL); #endif return SUCCESS; } } #if DO_PRINT flushout(); #endif } else { #if DO_PRINT formatln("[ERROR %r]", return_code); #endif break; } } if(ISOK(return_code)) { return_code = 1; } return return_code; } static ya_result zone_reader_text_free_record(zone_reader *zr, resource_record *entry) { (void)zr; (void)entry; return OK; } /** @brief Closes a zone file entry * * Closes a zone file entry. The function will do nothing if the zonefile has already been closed * * @param[in] zonefile a pointer to a valid (zone_file_open'ed) zone-file structure * */ static void zone_reader_text_close(zone_reader *zr) { yassert(zr != NULL); zone_reader_text *zfr = (zone_reader_text*)zr->data; parser_finalize(&zfr->parser); u8 n = zfr->includes_count; while(n-- > 0) { free(zfr->file_name[n]); /* Warning C6001 Using uninitialized memory '**zr[BYTE:268944]'. yadifa zone_reader_text.c 2411 */ } resource_record *rr = zfr->unread_next; while(rr != NULL) { resource_record *tmp = rr; rr = rr->next; free(tmp); } zone_reader_text_free_error_message(zfr); free(zfr); zr->data = NULL; zr->vtbl = NULL; } static bool zone_reader_text_canwriteback(zone_reader *zr) { yassert(zr != NULL); zone_reader_text *zfr = (zone_reader_text*)zr->data; return !zfr->template_source; } static void zone_reader_text_handle_error(zone_reader *zr, ya_result error_code) { /* nop */ (void)zr; (void)error_code; } static const char* zone_reader_text_get_last_error_message(zone_reader *zr) { zone_reader_text *zfr = (zone_reader_text*)zr->data; return zfr->error_message_buffer; } static const zone_reader_vtbl zone_reader_text_vtbl = { zone_reader_text_read_record, zone_reader_text_unread_record, zone_reader_text_free_record, zone_reader_text_close, zone_reader_text_handle_error, zone_reader_text_canwriteback, zone_reader_text_get_last_error_message, "zone_reader_text_v2" }; void zone_reader_text_init_error_codes() { if(zone_reader_text_init_error_codes_done) { return; } zone_reader_text_init_error_codes_done = TRUE; error_register(ZONEFILE_FEATURE_NOT_SUPPORTED, "ZONEFILE_FEATURE_NOT_SUPPORTED"); error_register(ZONEFILE_EXPECTED_FILE_PATH, "ZONEFILE_EXPECTED_FILE_PATH"); error_register(ZONEFILE_SOA_WITHOUT_CLASS, "ZONEFILE_SOA_WITHOUT_CLASS"); error_register(ZONEFILE_SALT_TOO_BIG, "ZONEFILE_SALT_TOO_BIG"); error_register(ZONEFILE_TEXT_TOO_BIG, "ZONEFILE_TEXT_TOO_BIG"); error_register(ZONEFILE_FLAGS_TOO_BIG, "ZONEFILE_FLAGS_TOO_BIG"); error_register(ZONEFILE_SERVICE_TOO_BIG, "ZONEFILE_SERVICE_TOO_BIG"); error_register(ZONEFILE_REGEX_TOO_BIG, "ZONEFILE_REGEX_TOO_BIG"); error_register(ZONEFILE_RDATA_PARSE_ERROR, "ZONEFILE_RDATA_PARSE_ERROR"); error_register(ZONEFILE_RDATA_BUFFER_TOO_SMALL, "ZONEFILE_RDATA_BUFFER_TOO_SMALL"); error_register(ZONEFILE_RDATA_SIZE_MISMATCH, "ZONEFILE_RDATA_SIZE_MISMATCH"); } static ya_result zone_reader_text_init(zone_reader *zr) { ya_result error_code; zone_reader_text *zfr; /* ------------------------------------------------------------ */ MALLOC_OBJECT_OR_DIE(zfr, zone_reader_text, ZFREADER_TAG); ZEROMEMORY(zfr, sizeof(zone_reader_text)); if(ISOK(error_code = parser_init(&zfr->parser, zfr_string_delimiters, // by 2 zfr_multiline_delimiters, // by 2 zrf_comment_markers, // by 1 zrf_blank_makers, // by 1 zfr_escape_characters))) // by 1 { zfr->rttl_default = 86400; zfr->rttl_current = 86400; zfr->dot_origin_size = 2; // with the CHR0 sentinel zfr->rclass_current = CLASS_IN; zfr->rdata_size = 0; zfr->soa_found = FALSE; zfr->domain[0] = (u8)'\0'; zfr->dot_origin[0] = '.'; zfr->dot_origin[1] = '\0'; } #if DNSCORE_HAS_FULL_ASCII7 parser_add_translation(&zfr->parser, '@', AT_SYMBOL); parser_add_translation(&zfr->parser, '$', VAR_SYMBOL); //parser_add_translation(&zfr->parser, '.', DOT_SYMBOL); #endif zr->data = zfr; zr->vtbl = &zone_reader_text_vtbl; return error_code; } #if DEBUG_BENCH_TEXT_ZONE_PARSE static debug_bench_s zone_reader_text_parse; static bool zone_reader_text_parse_done = FALSE; static inline void zone_reader_text_bench_register() { if(!zone_reader_text_parse_done) { zone_reader_text_parse_done = TRUE; debug_bench_register(&zone_reader_text_parse, "text parse"); } } #endif ya_result zone_reader_text_parse_stream(input_stream *ins, zone_reader *zr) { #if DEBUG_BENCH_TEXT_ZONE_PARSE zone_reader_text_bench_register(); u64 bench = debug_bench_start(&zone_reader_text_parse); #endif ya_result ret; if(ISOK(ret = zone_reader_text_init(zr))) { zone_reader_text *zfr = (zone_reader_text*)zr->data; // push the stream parser_push_stream(&zfr->parser, ins); } else { zone_reader_text_close(zr); } #if DEBUG_BENCH_TEXT_ZONE_PARSE zone_reader_text_bench_register(); debug_bench_stop(&zone_reader_text_parse, bench); #endif return ret; } /** @brief Opens a zone file * * Opens a zone file * * @param[in] fullpath the path and name of the file to open * @param[out] zone a pointer to a structure that will be used by the function * to hold the zone-file information * * @return A result code * @retval OK : the file has been opened successfully * @retval else : an error occurred */ ya_result zone_reader_text_open(const char* fullpath, zone_reader *zr) { ya_result return_value; #if DEBUG_BENCH_TEXT_ZONE_PARSE zone_reader_text_bench_register(); u64 bench = debug_bench_start(&zone_reader_text_parse); #endif if(ISOK(return_value = zone_reader_text_init(zr))) { // push the stream zone_reader_text *zfr = (zone_reader_text*)zr->data; if(ISOK(return_value = file_input_stream_open(&zfr->includes[0], fullpath))) { /* #if (DNSDB_USE_POSIX_ADVISE != 0) && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) int fd = fd_input_stream_get_filedescriptor(&zfr->includes[0]); fdatasync_ex(fd); posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); #endif */ zfr->file_name[zfr->includes_count] = strdup(fullpath); parser_push_stream(&zfr->parser, &zfr->includes[zfr->includes_count++]); } else { log_debug("zone file: cannot open: '%s': %r", fullpath, return_value); zone_reader_text_close(zr); return return_value; } #if DEBUG_BENCH_TEXT_ZONE_PARSE zone_reader_text_bench_register(); debug_bench_stop(&zone_reader_text_parse, bench); #endif } return return_value; } void zone_reader_text_ignore_missing_soa(zone_reader *zr) { zone_reader_text *zfr = (zone_reader_text*)zr->data; zfr->soa_found = TRUE; } ya_result zone_reader_text_set_origin(zone_reader *zr, const u8* origin) { zone_reader_text *zfr = (zone_reader_text*)zr->data; ya_result return_code = dnsname_copy(zfr->origin, origin); return return_code; } ya_result zone_reader_text_copy_rdata(const char *text, u16 rtype, u8 *rdata, u32 rdata_size, const u8 *origin) { parser_s parser; ya_result return_code; char buffer[4096]; int n = strlen(text); if(n > (int)(sizeof(buffer) - 2)) { return -1; } if(text[n - 1] != '\n') { memcpy(buffer, text, n); buffer[n] = '\n'; buffer[n + 1] = '\0'; n++; text = buffer; } if(ISOK(return_code = parser_init(&parser, zfr_string_delimiters, // by 2 zfr_multiline_delimiters, // by 2 zrf_comment_markers, // by 1 zrf_blank_makers, // by 1 zfr_escape_characters))) // by 1 { input_stream text_is; bytearray_input_stream_init_const(&text_is, (const u8*)text, n); if(ISOK(return_code = parser_push_stream(&parser, &text_is))) { return_code = zone_reader_text_copy_rdata_inline(&parser, rtype, rdata, rdata_size, origin); } // will be closed by the parser // input_stream_close(&text_is); parser_finalize(&parser); } return return_code; } ya_result zone_reader_text_len_copy_rdata(const char *text, u32 n, u16 rtype, u8 *rdata, u32 rdata_size, const u8 *origin) { parser_s parser; ya_result return_code; if(ISOK(return_code = parser_init(&parser, zfr_string_delimiters, // by 2 zfr_multiline_delimiters, // by 2 zrf_comment_markers, // by 1 zrf_blank_makers, // by 1 zfr_escape_characters))) // by 1 { input_stream text_is; bytearray_input_stream_init_const(&text_is, (const u8*)text, n); if(ISOK(return_code = parser_push_stream(&parser, &text_is))) { return_code = zone_reader_text_copy_rdata_inline(&parser, rtype, rdata, rdata_size, origin); } // will be closed by the parser // input_stream_close(&text_is); parser_finalize(&parser); } return return_code; } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/osx_clock_gettime.c0000644000000000000000000000013214505005532023176 xustar000000000000000030 mtime=1695812442.389981429 30 atime=1695812445.792030153 30 ctime=1695812494.752731369 yadifa-2.6.5-11201/lib/dnscore/src/osx_clock_gettime.c0000664000374500037450000000524514505005532023146 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup OSX portability * @ingroup dnscore * @brief * * @{ * *----------------------------------------------------------------------------*/ // CentOS 5.9 requires this to have PTHREAD_MUTEX_RECURSIVE #define _GNU_SOURCE 1 #include "dnscore/dnscore-config.h" #include #include #if !(defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)) && defined(__MACH__) #include #include typedef clock_id_t clockid_t; int clock_gettime(clockid_t clk_id, struct timespec *tp) { (void)clk_id; clock_serv_t cclock; mach_timespec_t mts; host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); clock_get_time(cclock, &mts); mach_port_deallocate(mach_task_self(), cclock); tp->tv_sec = mts.tv_sec; tp->tv_nsec = mts.tv_nsec; return 0; } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/tsig.c0000644000000000000000000000013014505005532020440 xustar000000000000000028 mtime=1695812442.3949815 30 atime=1695812445.792030153 30 ctime=1695812494.754731398 yadifa-2.6.5-11201/lib/dnscore/src/tsig.c0000664000374500037450000015306214505005532020413 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup dnscore * @brief * * @{ */ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/dnscore-config.h" #include "dnscore/zalloc.h" #include "dnscore/message.h" // DO NOT REMOVE ME #include "dnscore/tsig.h" #include "dnscore/packet_reader.h" #include "dnscore/logger.h" #if DNSCORE_HAS_TSIG_SUPPORT #define TSIGNODE_TAG 0x45444f4e47495354 #define TSIGPAYL_TAG 0x4c59415047495354 #define TSIGMAC_TAG 0x43414d47495354 #define MODULE_MSG_HANDLE g_system_logger #define LOG_DIGEST_INPUT 2 // set up to 2 for debugging #define TSIG_TCP_PERIOD 99 /* * AVL definition part begins here */ /* * The maximum depth of a tree. * 40 is enough for storing 433494436 items (worst case) * * Depth 0 is one node. * * Worst case : N is enough for sum[n = 0,N](Fn) where Fn is Fibonacci(n+1) * Best case : N is enough for (2^(N+1))-1 */ #define AVL_MAX_DEPTH 40 // no need for more /* * The previx that will be put in front of each function name */ #define AVL_PREFIX tsig_ /* * The type that hold the node */ #define AVL_NODE_TYPE tsig_node /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_TREE_TYPE AVL_NODE_TYPE* /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_CONST_TREE_TYPE AVL_NODE_TYPE * const /* * The way to get the root from the tree */ #define AVL_TREE_ROOT(__tree__) (*(__tree__)) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE const u8* #define AVL_REFERENCE_IS_CONST TRUE #define AVL_REFERENCE_IS_POINTER TRUE /* * The node has got a pointer to its parent * * 0 : disable * !=0 : enable */ #define AVL_HAS_PARENT_POINTER 0 #include "dnscore/avl.h.inc" /*********************************************************/ /* * The following macros are defining relevant fields in the node */ /* * Access to the field that points to the left child */ #define AVL_LEFT_CHILD(node) ((node)->children.lr.left) /* * Access to the field that points to the right child */ #define AVL_RIGHT_CHILD(node) ((node)->children.lr.right) /* * Access to the field that points to one of the children (0: left, 1: right) */ #define AVL_CHILD(node,id) ((node)->children.child[(id)]) /* * Access to the field that keeps the balance (a signed byte) */ #define AVL_BALANCE(node) ((node)->balance) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE const u8* #define AVL_REFERENCE_IS_CONST TRUE /* * */ #define AVL_REFERENCE_FORMAT_STRING "%{dnsname}" #define AVL_REFERENCE_FORMAT(reference) reference /* * A macro to initialize a node and setting the reference */ #define AVL_INIT_NODE(node,reference) ZEROMEMORY((node),sizeof(tsig_node));(node)->item.name = dnsname_dup(reference) /* * A macro to allocate a new node */ #define AVL_ALLOC_NODE(node,reference) MALLOC_OR_DIE(AVL_NODE_TYPE*,node,sizeof(AVL_NODE_TYPE), TSIGNODE_TAG) /* * A macro to free a node allocated by ALLOC_NODE */ #define AVL_FREE_NODE(node) free((u8*)(node)->item.name);free((u8*)(node)->item.mac);free(node) /* * A macro to print the node */ #define AVL_DUMP_NODE(node) format("node@%p",(node)); /* * A macro that returns the reference field of the node. * It must be of type REFERENCE_TYPE */ #define AVL_REFERENCE(node) (node)->item.name #define AVL_TERNARYCMP 1 #if !AVL_TERNARYCMP /* * A macro to compare two references * Returns TRUE if and only if the references are equal. */ #define AVL_ISEQUAL(reference_a,reference_b) dnsname_equals(reference_a,reference_b) /* * A macro to compare two references * Returns TRUE if and only if the first one is bigger than the second one. */ #define AVL_ISBIGGER(reference_a,reference_b) (dnsname_compare(reference_a,reference_b) > 0) #else #define AVL_COMPARE(reference_a,reference_b) (dnsname_compare(reference_a,reference_b)) #endif /* * Copies the payload of a node * It MUST NOT copy the "proprietary" node fields : children, parent, balance */ #define AVL_COPY_PAYLOAD(node_trg,node_src) (node_trg)->item.name = dnsname_dup((node_src)->item.name); \ MALLOC_OR_DIE(const u8*,(node_trg)->item.mac,(node_src)->item.mac_size, TSIGPAYL_TAG); \ MEMCOPY((u8*)(node_trg)->item.mac, (node_src)->item.mac, (node_src)->item.mac_size); \ (node_trg)->item.mac_size = (node_src)->item.mac_size; \ (node_trg)->item.mac_algorithm = (node_src)->item.mac_algorithm; /* * A macro to preprocess a node before it is preprocessed for a delete (detach) * If there was anything to do BEFORE deleting a node, we would do it here * After this macro is exectuted, the node * _ is detached, then deleted with FREE_NODE * _ has got its content overwritten by the one of another node, then the other * node is deleted with FREE_NODE */ #define AVL_NODE_DELETE_CALLBACK(node) #include "dnscore/avl.c.inc" #include "dnscore/message.h" // DO NOT REMOVE ME #undef AVL_MAX_DEPTH #undef AVL_PREFIX #undef AVL_NODE_TYPE #undef AVL_TREE_TYPE #undef AVL_CONST_TREE_TYPE #undef AVL_TREE_ROOT #undef AVL_REFERENCE_TYPE #undef _AVL_H_INC /* * */ static tsig_node *tsig_tree = NULL; static u32 tsig_tree_count = 0; static u8 tsig_serial = 0; /// @note load serial static const value_name_table hmac_digest_enum[]= { {HMAC_MD5 , "hmac-md5" }, {HMAC_SHA1 , "hmac-sha1" }, {HMAC_SHA224, "hmac-sha224" }, {HMAC_SHA256, "hmac-sha256" }, {HMAC_SHA384, "hmac-sha384" }, {HMAC_SHA512, "hmac-sha512" }, {0, NULL} }; static ya_result tsig_digest_answer(message_data *mesg); static ya_result tsig_add_tsig(message_data *mesg); ya_result tsig_get_hmac_algorithm_from_friendly_name(const char *hmacname) { ya_result ret; u32 integer_value; if(ISOK(ret = value_name_table_get_value_from_casename(hmac_digest_enum, hmacname, &integer_value))) { return (ya_result)integer_value; } else { return ret; } } const char * tsig_get_friendly_name_from_hmac_algorithm(u32 algorithm) { const char *name = "?"; value_name_table_get_name_from_value(hmac_digest_enum, algorithm, &name); return name; } /** * Call this before a config reload */ void tsig_serial_next() { tsig_serial++; } ya_result tsig_register(const u8 *name, const u8 *mac, u16 mac_size, u8 mac_algorithm) { ya_result return_code = SUCCESS; tsig_node *node = tsig_insert(&tsig_tree, name); if(node != NULL) { if(node->item.mac != NULL) { bool same = (node->item.mac_size == mac_size) && (node->item.mac_algorithm == mac_algorithm) && (memcmp((u8*)node->item.mac, mac, mac_size) == 0); if(same) { // don't complain if they are an exact match return SUCCESS; } if(node->item.load_serial != tsig_serial) { node->item.load_serial = tsig_serial; // else every 256 updates will see a duplicate // this is an old version of the key free((void*)node->item.mac); node->item.mac = NULL; } else { // it's a dup in the config file return TSIG_DUPLICATE_REGISTRATION; /* dup */ } } yassert(node->item.mac == NULL); MALLOC_OR_DIE(u8*, node->item.mac, mac_size, TSIGMAC_TAG); MEMCOPY((u8*)node->item.mac, mac, mac_size); node->item.mac_algorithm_name = tsig_get_algorithm_name(mac_algorithm); node->item.name_len = dnsname_len(name); node->item.mac_algorithm_name_len = dnsname_len(node->item.mac_algorithm_name); node->item.mac_size = mac_size; node->item.mac_algorithm = mac_algorithm; node->item.load_serial = tsig_serial; tsig_tree_count++; } else { return_code = INVALID_STATE_ERROR; /* internal error */ } return return_code; } tsig_item* tsig_get(const u8 *name) { tsig_node *node = tsig_find(&tsig_tree, name); if(node != NULL) { return &node->item; } return NULL; } u32 tsig_get_count() { return tsig_tree_count; } tsig_item* tsig_get_at_index(s32 index) { if(index < 0 || (u32)index >= tsig_tree_count) { return NULL; } tsig_iterator iter; tsig_iterator_init(&tsig_tree, &iter); while(tsig_iterator_hasnext(&iter)) { tsig_node *node = tsig_iterator_next_node(&iter); if(index == 0) { return &node->item; } index--; } // should never be reached return NULL; } void tsig_finalize_algorithms(); void tsig_finalize() { tsig_destroy(&tsig_tree); tsig_finalize_algorithms(); } static u8 tsig_typeclassttl[8] = {0x00, 0xfa, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00}; static u8 tsig_classttl[6] = {0x00, 0xff, 0x00, 0x00, 0x00, 0x00}; static u8 tsig_noerror_noother[4] = {0x00, 0x00, 0x00, 0x00}; static void tsig_update_time(message_data *mesg) { u64 now = time(NULL); mesg->_tsig.timehi = htons((u16)(now >> 32)); mesg->_tsig.timelo = htonl((u32)now); } static ya_result tsig_process_append_unsigned(message_data *mesg, packet_unpack_reader_data *purd, u32 tsig_offset) { u16* tsig_rdata_size_position_p; u16 tsig_rdata_size; message_set_status(mesg, FP_RCODE_NOTAUTH); // no fingerprint here, it's RFC message_update_answer_status(mesg); message_set_rcode(mesg, RCODE_NOTAUTH); packet_reader_set_position(purd, tsig_offset); if(FAIL(packet_reader_skip_zone_record(purd))) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(packet_reader_available(purd) <= 6) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } packet_reader_skip_bytes(purd, 4); // return value guaranteed : checked above tsig_rdata_size_position_p = (u16*)packet_reader_get_current_ptr_const(purd, 2); packet_reader_read_u16_unchecked(purd, &tsig_rdata_size); // checked above if(FAIL(packet_reader_skip_fqdn(purd))) // algorithm { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } u8 *p = (u8*)packet_reader_get_current_ptr_const(purd, 16); // ensures there is enough room if(p != NULL) { message_set_answer(mesg); // Make the message an answer // overwrite the TSIG without the MAC and with a BADKEY error code // keep the name and the algorithm u32 now = timeus() / ONE_SECOND_US; SET_U16_AT_P(p, 0); p += 2; SET_U32_AT_P(p, htonl(now)); p += 4; SET_U16_AT_P(p, NU16(300)); p += 2; SET_U16_AT_P(p, 0); p += 2; SET_U16_AT_P(p, message_get_id(mesg)); p += 2; SET_U16_AT_P(p, mesg->_tsig.error); // the error code is stored in network order p += 2; SET_U16_AT_P(p, 0); p += 2; // adjust the TSIG rdata size SET_U16_AT_P(tsig_rdata_size_position_p, htons((p - (u8*)tsig_rdata_size_position_p) - 2)); // adjust the message size packet_reader_skip_unchecked(purd, 16); // we know it's available message_set_size(mesg, packet_reader_position(purd)); return MAKE_DNSMSG_ERROR(ntohs(mesg->_tsig.error)); } else { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } static ya_result tsig_verify_query(message_data *mesg) { u32 md_len = 0; u8 md[EVP_MAX_MD_SIZE]; #if LOG_DIGEST_INPUT log_debug("tsig_verify_query(%p = %{dnsname} %{dnstype} %{dnsclass})", mesg, message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif u64 then = (u64)ntohs(mesg->_tsig.timehi); then <<= 32; then |= (u64)ntohl(mesg->_tsig.timelo); u64 now = time(NULL); s64 fudge = ntohs(mesg->_tsig.fudge); if(llabs((s64)((s64)then - now)) > fudge) // cast to signed in case now > then { message_set_status(mesg, FP_TSIG_ERROR); // MUST be NOTAUTH message_update_answer_status(mesg); message_set_rcode(mesg, RCODE_NOTAUTH); free(mesg->_tsig.other); mesg->_tsig.other_len = NU16(6); MALLOC_OR_DIE(u8*, mesg->_tsig.other, 6, TSIGOTHR_TAG); SET_U16_AT_P(mesg->_tsig.other, 0); SET_U32_AT_P(mesg->_tsig.other + 2, htonl(time(NULL))); mesg->_tsig.error = NU16(RCODE_BADTIME); tsig_digest_answer(mesg); tsig_add_tsig(mesg); return TSIG_BADTIME; } tsig_hmac_t hmac = tsig_hmac_allocate(); if(hmac == NULL) { return INVALID_STATE_ERROR; } if(FAIL(hmac_init(hmac, message_tsig_get_key_bytes(mesg), message_tsig_get_key_size(mesg), mesg->_tsig.tsig->mac_algorithm))) { hmac_free(hmac); return INVALID_STATE_ERROR; } /* DNS message */ hmac_update(hmac, message_get_buffer_const(mesg), message_get_size(mesg)); /* TSIG Variables */ hmac_update(hmac, mesg->_tsig.tsig->name, mesg->_tsig.tsig->name_len); hmac_update(hmac, tsig_classttl, sizeof(tsig_classttl)); hmac_update(hmac, mesg->_tsig.tsig->mac_algorithm_name, mesg->_tsig.tsig->mac_algorithm_name_len); hmac_update(hmac, (u8*) & mesg->_tsig.timehi, 2); hmac_update(hmac, (u8*) & mesg->_tsig.timelo, 4); hmac_update(hmac, (u8*) & mesg->_tsig.fudge, 2); hmac_update(hmac, (u8*) & mesg->_tsig.error, 2); hmac_update(hmac, (u8*) & mesg->_tsig.other_len, 2); if((mesg->_tsig.other != NULL) && (mesg->_tsig.other_len > 0)) { hmac_update(hmac, mesg->_tsig.other, ntohs(mesg->_tsig.other_len)); } hmac_final(hmac, md, &md_len); #if LOG_DIGEST_INPUT log_debug("tsig_verify_query: computed:"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, md, md_len, 32); log_debug("tsig_verify_query: expected:", mesg); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, (u8*) mesg->_tsig.mac, md_len, 32); #endif hmac_free(hmac); if((md_len != mesg->_tsig.mac_size) || (memcmp(mesg->_tsig.mac, md, md_len) != 0)) { packet_unpack_reader_data purd; purd.packet = message_get_buffer(mesg); purd.packet_size = message_get_buffer_size(mesg); u16 additionals = 1; // message_is_edns0(mesg)?2:1; message_set_additional_count(mesg, message_get_additional_count(mesg) + additionals); mesg->_tsig.error = NU16(RCODE_BADSIG); tsig_process_append_unsigned(mesg, &purd, mesg->_tsig.tsig_offset); return TSIG_BADSIG; } // no truncation supported at the moment return SUCCESS; } ya_result tsig_verify_answer(message_data *mesg, const u8 *mac, u16 mac_size) { u32 md_len = 0; u8 md[EVP_MAX_MD_SIZE]; u16 mac_size_network = htons(mac_size); #if LOG_DIGEST_INPUT log_debug("tsig_verify_answer(%p = %{dnsname} %{dnstype} %{dnsclass}, %p, %i)", mesg, message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), mac, mac_size ); #endif u64 then = (u64)ntohs(mesg->_tsig.timehi); then <<= 32; then |= (u64)ntohl(mesg->_tsig.timelo); u64 now = time(NULL); s64 fudge = ntohs(mesg->_tsig.fudge); if(llabs((s64)((s64)then - now)) > fudge) // cast to signed in case now > then { mesg->_tsig.error = NU16(RCODE_BADTIME); message_set_status(mesg, FP_TSIG_ERROR); // MUST be NOTAUTH return TSIG_BADTIME; } tsig_hmac_t hmac = tsig_hmac_allocate(); if(hmac == NULL) { return INVALID_STATE_ERROR; } if(FAIL(hmac_init(hmac, message_tsig_get_key_bytes(mesg), message_tsig_get_key_size(mesg), mesg->_tsig.tsig->mac_algorithm))) { hmac_free(hmac); return INVALID_STATE_ERROR; } hmac_update(hmac, (u8*) &mac_size_network, 2); hmac_update(hmac, mac, mac_size); /* DNS message */ hmac_update(hmac, message_get_buffer_const(mesg), message_get_size(mesg)); /* TSIG Variables */ hmac_update(hmac, mesg->_tsig.tsig->name, mesg->_tsig.tsig->name_len); hmac_update(hmac, tsig_classttl, sizeof(tsig_classttl)); hmac_update(hmac, mesg->_tsig.tsig->mac_algorithm_name, mesg->_tsig.tsig->mac_algorithm_name_len); hmac_update(hmac, (u8*) &mesg->_tsig.timehi, 2); hmac_update(hmac, (u8*) &mesg->_tsig.timelo, 4); hmac_update(hmac, (u8*) &mesg->_tsig.fudge, 2); hmac_update(hmac, (u8*) &mesg->_tsig.error, 2); hmac_update(hmac, (u8*) &mesg->_tsig.other_len, 2); if((mesg->_tsig.other != NULL) && (mesg->_tsig.other_len > 0)) { hmac_update(hmac, mesg->_tsig.other, ntohs(mesg->_tsig.other_len)); } hmac_final(hmac, md, &md_len); #if LOG_DIGEST_INPUT log_debug("tsig_verify_answer: computed"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, md, md_len, 32); log_debug("tsig_verify_answer: expected"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, mesg->_tsig.mac, md_len, 32); #endif hmac_free(hmac); if((md_len != mac_size) || (memcmp(mesg->_tsig.mac, md, md_len) != 0)) { message_set_status(mesg, FP_TSIG_ERROR); return TSIG_BADSIG; } return SUCCESS; } static ya_result tsig_digest_query(message_data *mesg) { /* Request MAC */ #if LOG_DIGEST_INPUT log_debug("tsig_digest_query(%p = %{dnsname} %{dnstype} %{dnsclass})", mesg, message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif tsig_hmac_t hmac = tsig_hmac_allocate(); if(hmac == NULL) { return INVALID_STATE_ERROR; } if(FAIL(hmac_init(hmac, message_tsig_get_key_bytes(mesg), message_tsig_get_key_size(mesg), mesg->_tsig.tsig->mac_algorithm))) { hmac_free(hmac); return ERROR; } /* DNS message */ hmac_update(hmac, message_get_buffer_const(mesg), message_get_size(mesg)); /* TSIG Variables */ hmac_update(hmac, mesg->_tsig.tsig->name, mesg->_tsig.tsig->name_len); hmac_update(hmac, tsig_classttl, sizeof(tsig_classttl)); hmac_update(hmac, mesg->_tsig.tsig->mac_algorithm_name, mesg->_tsig.tsig->mac_algorithm_name_len); hmac_update(hmac, (u8*) & mesg->_tsig.timehi, 2); hmac_update(hmac, (u8*) & mesg->_tsig.timelo, 4); hmac_update(hmac, (u8*) & mesg->_tsig.fudge, 2); // error is 0 // other len is 0 // no need to work on other data either (since other len is 0) hmac_update(hmac, tsig_noerror_noother, 4); // four zeros u32 tmp_mac_size; hmac_final(hmac, mesg->_tsig.mac, &tmp_mac_size); mesg->_tsig.mac_size = tmp_mac_size; #if LOG_DIGEST_INPUT log_debug("tsig_digest_query: computed"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, mesg->_tsig.mac, tmp_mac_size, 32); #endif hmac_free(hmac); return SUCCESS; } static ya_result tsig_digest_answer(message_data *mesg) { yassert(message_has_tsig(mesg)); tsig_hmac_t hmac = tsig_hmac_allocate(); if(hmac == NULL) { return INVALID_STATE_ERROR; } /* Request MAC */ #if LOG_DIGEST_INPUT log_debug("tsig_digest_answer(%p = %{dnsname} %{dnstype} %{dnsclass})", mesg, message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif if(mesg->_tsig.tsig != NULL && message_tsig_get_key_size(mesg) > 0) { if(FAIL(hmac_init(hmac, message_tsig_get_key_bytes(mesg), message_tsig_get_key_size(mesg), mesg->_tsig.tsig->mac_algorithm))) { hmac_free(hmac); return ERROR; } u16 mac_size_network = htons(mesg->_tsig.mac_size); hmac_update(hmac, (u8*) & mac_size_network, 2); hmac_update(hmac, mesg->_tsig.mac, mesg->_tsig.mac_size); /* DNS message */ hmac_update(hmac, message_get_buffer_const(mesg), message_get_size(mesg)); /* TSIG Variables */ hmac_update(hmac, mesg->_tsig.tsig->name, mesg->_tsig.tsig->name_len); hmac_update(hmac, tsig_classttl, sizeof(tsig_classttl)); hmac_update(hmac, mesg->_tsig.tsig->mac_algorithm_name, mesg->_tsig.tsig->mac_algorithm_name_len); hmac_update(hmac, (u8*) & mesg->_tsig.timehi, 2); hmac_update(hmac, (u8*) & mesg->_tsig.timelo, 4); hmac_update(hmac, (u8*) & mesg->_tsig.fudge, 2); hmac_update(hmac, (u8*) & mesg->_tsig.error, 2); hmac_update(hmac, (u8*) & mesg->_tsig.other_len, 2); if((mesg->_tsig.other != NULL) && (mesg->_tsig.other_len > 0)) { hmac_update(hmac, mesg->_tsig.other, ntohs(mesg->_tsig.other_len)); } u32 tmp_mac_size; hmac_final(hmac, mesg->_tsig.mac, &tmp_mac_size); mesg->_tsig.mac_size = tmp_mac_size; #if LOG_DIGEST_INPUT log_debug("tsig_digest_answer: computed"); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, mesg->_tsig.mac, tmp_mac_size, 32); #endif hmac_free(hmac); } else { } return SUCCESS; } /** * Extracts the TSIG from a message * * _ checks if the CLASS & TTL are right * _ checks if the TSIG name is known * _ loads the TSIG into the TSIG structure into the message * * Works fine for questions but for answer it needs to match a previous setup. * * @param mesg the message * @param purd a packet reader at the position of the TSIG record * @param tsig_offset * @param tsigname * @param tctr * @return */ ya_result tsig_process(message_data *mesg, packet_unpack_reader_data *purd, u32 tsig_offset, const tsig_item *tsig, struct type_class_ttl_rdlen *tctr) { u16 ar_count = message_get_additional_count(mesg); u8 algorithm[256]; mesg->_tsig.tsig_offset = (u16)tsig_offset; if((tctr->qclass == CLASS_ANY) && (tctr->ttl == 0)) { u32 tsig_rdata_len = ntohs(tctr->rdlen); ya_result return_code; /* * Read the algorithm name and see if it matches our TSIG key */ if(FAIL(return_code = packet_reader_read_fqdn(purd, algorithm, sizeof(algorithm)))) { /* oops */ mesg->_tsig.error = NU16(RCODE_BADKEY); message_set_status(mesg, FP_TSIG_BROKEN); return MAKE_DNSMSG_ERROR(FP_TSIG_BROKEN); // format error reading the algorithm name } tsig_rdata_len -= return_code; u8 alg = tsig_get_algorithm(algorithm); if((tsig == NULL) || (alg == HMAC_UNKNOWN) || ((tsig != NULL) && (tsig->mac_algorithm != alg))) { /** * If a non-forwarding server does not recognize the key used by the * client, the server MUST generate an error response with RCODE 9 * (NOTAUTH) and TSIG ERROR 17 (BADKEY). * * The server SHOULD log the error. * */ // The TSIG is modified here so we don't need to memorise the name of an unknown key. mesg->_tsig.error = NU16(RCODE_BADKEY); return_code = tsig_process_append_unsigned(mesg, purd, tsig_offset); return return_code; } tsig_rdata_len -= 10 + 6; message_set_size(mesg, tsig_offset); message_set_additional_count(mesg, ar_count - 1); /* * Save the TSIG. */ mesg->_tsig.other = NULL; mesg->_tsig.other_len = 0; mesg->_tsig.tsig = tsig; mesg->_tsig.mac_algorithm = alg; if(FAIL(return_code = packet_reader_read(purd, &mesg->_tsig.timehi, 10))) { /* oops */ message_set_status(mesg, FP_TSIG_BROKEN); return TSIG_FORMERR; } /* Check the time */ /** * * If the server time is outside the time interval specified by the * request (which is: Time Signed, plus/minus Fudge), the server MUST * generate an error response with RCODE 9 (NOTAUTH) and TSIG ERROR 18 (BADTIME). * * I cannot use time_t because on some systems time_t is 32 bits. I need more. * The next best thing is u64 */ u16 mac_size = ntohs(mesg->_tsig.mac_size); /* NETWORK => NATIVE */ if(mac_size > sizeof(mesg->_tsig.mac)) { /* oops */ message_set_status(mesg, FP_TSIG_BROKEN); return TSIG_FORMERR; } mesg->_tsig.mac_size = mac_size; if(FAIL(return_code = packet_reader_read(purd, mesg->_tsig.mac, mac_size))) { /* oops */ message_set_status(mesg, FP_TSIG_BROKEN); return TSIG_FORMERR; } tsig_rdata_len -= mac_size; if(FAIL(return_code = packet_reader_read(purd, &mesg->_tsig.original_id, 6))) // and error, and other len { /* oops */ message_set_status(mesg, FP_TSIG_BROKEN); return TSIG_FORMERR; } if(tsig_rdata_len != mesg->_tsig.other_len) { message_set_status(mesg, FP_TSIG_BROKEN); return TSIG_FORMERR; } if(mesg->_tsig.other_len != 0) { u16 other_len = ntohs(mesg->_tsig.other_len); MALLOC_OR_DIE(u8*, mesg->_tsig.other, other_len, TSIGOTHR_TAG); if(FAIL(return_code = packet_reader_read(purd, mesg->_tsig.other, other_len))) { /* oops */ free(mesg->_tsig.other); mesg->_tsig.other = NULL; mesg->_tsig.other_len = 0; message_set_status(mesg, FP_TSIG_BROKEN); return TSIG_FORMERR; } } if(!packet_reader_eof(purd)) { free(mesg->_tsig.other); mesg->_tsig.other = NULL; mesg->_tsig.other_len = 0; message_set_status(mesg, FP_TSIG_BROKEN); return TSIG_FORMERR; } return SUCCESS; } /* error : tsig but wrong tsig setup */ message_set_status(mesg, FP_TSIG_BROKEN); return TSIG_FORMERR; } ya_result tsig_process_query(message_data *mesg, packet_unpack_reader_data *purd, u32 tsig_offset, u8 tsigname[MAX_DOMAIN_LENGTH], struct type_class_ttl_rdlen *tctr) { ya_result return_value; tsig_item *tsig = tsig_get(tsigname); if(ISOK(return_value = tsig_process(mesg, purd, tsig_offset, tsig, tctr))) { if(ISOK(return_value = tsig_verify_query(mesg))) { return return_value; } // tsig process may have allocated tsig other free(mesg->_tsig.other); mesg->_tsig.other = NULL; mesg->_tsig.other_len = 0; } return return_value; } /** * Extracts and verifies the TSIG in an (answer) message. * * @param mesg the message * @param purd a packet reader set for the message * @param tsig_offset the position of the tsig * @param tsig * @param tctr * @return */ ya_result tsig_process_answer(message_data *mesg, packet_unpack_reader_data *purd, u32 tsig_offset, struct type_class_ttl_rdlen *tctr) { ya_result return_value; int mac_size = message_tsig_mac_get_size(mesg); u8 mac[64]; assert(mac_size <= (int)sizeof(mac)); message_tsig_mac_copy(mesg, mac); // extract the tsig if(ISOK(return_value = tsig_process(mesg, purd, tsig_offset, message_tsig_get_key(mesg), tctr))) { // verify the tsig in the answer if(mesg->_tsig.error == 0) /// @todo 20210825 edf -- should be more accurate { if(FAIL(return_value = tsig_verify_answer(mesg, mac, mac_size))) { /* oops */ free(mesg->_tsig.other); mesg->_tsig.other = NULL; mesg->_tsig.other_len = 0; mesg->_tsig.error = NU16(RCODE_BADSIG); tsig_append_error(mesg); } } } return return_value; } /** * Extracts the TSIG from the message * * Reads all the records but the last AR one */ ya_result tsig_extract_and_process(message_data *mesg) { /*yassert(message_is_additional_section_ptr_set(mesg));*/ /* * rfc2845 * * If there is a TSIG then * _ It must be put aside, safely * _ It must be removed from the query * _ It must be processed * * rfc2671 * * Handle OPT * */ /* * Read DNS name (decompression on) * Read type (TSIG = 250) * Read class (ANY) * Read TTL (0) * Read RDLEN * */ packet_unpack_reader_data purd; purd.packet = message_get_buffer_const(mesg); purd.packet_size = message_get_size(mesg); if(!message_is_additional_section_ptr_set(mesg)) { u32 tsig_index = message_get_answer_count(mesg) + message_get_authority_count(mesg) + message_get_additional_count(mesg) - 1; purd.offset = DNS_HEADER_LENGTH; /* Header */ packet_reader_skip_fqdn(&purd); // checked below if(FAIL(packet_reader_skip(&purd, 4))) // type class { return UNPROCESSABLE_MESSAGE; } while(tsig_index-- > 0) /* Skip all AR records but the last one */ { /* * It should be in this kind of processing that we read the EDNS0 flag */ if(FAIL(packet_reader_skip_record(&purd))) { return UNPROCESSABLE_MESSAGE; } } message_set_additional_section_ptr(mesg, (void*)packet_reader_get_next_u8_ptr_const(&purd)); } else { packet_reader_set_position(&purd, message_get_additional_section_ptr(mesg) - message_get_buffer(mesg)); } struct type_class_ttl_rdlen tctr; u32 record_offset = purd.offset; u8 tsigname[MAX_DOMAIN_LENGTH]; if(FAIL(packet_reader_read_fqdn(&purd, tsigname, sizeof(tsigname)))) { /* oops */ return TSIG_FORMERR; } /*yassert(((u8*)&tctr.rdlen) - ((u8*)&tctr.qtype) == 8);*/ if(ISOK(packet_reader_read(&purd, &tctr, 10))) // exact { if(tctr.qtype == TYPE_TSIG) /* && (tctr.qclass == TYPE_ANY) && (tctr.ttl == 0 )*/ { /* It must be the last AR record, class = ANY and TTL = 0 */ return tsig_process_query(mesg, &purd, record_offset, tsigname, &tctr); } /* if type is TSIG */ /* AR but not a TSIG : there is just no TSIG in this packet */ message_tsig_clear_key(mesg); } return TSIG_FORMERR; } /** * Adds the TSIG to the message * */ static ya_result tsig_add_tsig(message_data *mesg) { u16 ar_count = message_get_additional_count(mesg); /* Converted after network read ... so why do I do this ? */ u16 mac_size = mesg->_tsig.mac_size; u16 other_len = ntohs(mesg->_tsig.other_len); // if((mesg->_tsig.tsig != NULL) && (mac_size > 0)) if(message_get_buffer_size(mesg) < message_get_size(mesg) + // valid use of message_get_buffer_size() message_tsig_get_key(mesg)->name_len + /* DNS NAME of the TSIG (name of the key) */ mac_size + /* MAC */ other_len + /* OTHER DATA */ 12) /* time + fudge + mac size + original id + error + other len = 12 bytes */ { /* Cannot sign because of truncation */ message_set_truncated_answer(mesg); return TSIG_SIZE_LIMIT_ERROR; } u8 *tsig_ptr = message_get_buffer_limit(mesg); /* record */ memcpy(tsig_ptr, mesg->_tsig.tsig->name, mesg->_tsig.tsig->name_len); tsig_ptr += mesg->_tsig.tsig->name_len; memcpy(tsig_ptr, tsig_typeclassttl, sizeof(tsig_typeclassttl)); tsig_ptr += sizeof(tsig_typeclassttl); u16 *rdata_size_ptr = (u16*)tsig_ptr; tsig_ptr += 2; /* rdata */ memcpy(tsig_ptr, mesg->_tsig.tsig->mac_algorithm_name, mesg->_tsig.tsig->mac_algorithm_name_len); tsig_ptr += mesg->_tsig.tsig->mac_algorithm_name_len; SET_U16_AT(tsig_ptr[0], mesg->_tsig.timehi); SET_U32_AT(tsig_ptr[2], mesg->_tsig.timelo); SET_U16_AT(tsig_ptr[6], mesg->_tsig.fudge); SET_U16_AT(tsig_ptr[8], htons(mesg->_tsig.mac_size)); memcpy(&tsig_ptr[10], mesg->_tsig.mac, mac_size); tsig_ptr += mac_size + 10; SET_U16_AT(tsig_ptr[0], mesg->_tsig.original_id); SET_U16_AT(tsig_ptr[2], mesg->_tsig.error); SET_U16_AT(tsig_ptr[4], mesg->_tsig.other_len); tsig_ptr += 6; if(mesg->_tsig.other_len != 0) { yassert(mesg->_tsig.other != NULL); memcpy(tsig_ptr, mesg->_tsig.other, other_len); tsig_ptr += other_len; } u16 rdata_size = (tsig_ptr - (u8*)rdata_size_ptr) - 2; SET_U16_AT(*rdata_size_ptr, htons(rdata_size)); message_set_size(mesg, tsig_ptr - message_get_buffer(mesg)); message_set_additional_count(mesg, ar_count + 1); return SUCCESS; } /** * Signs the message answer with its TSIG */ ya_result tsig_sign_answer(message_data *mesg) { yassert(message_is_additional_section_ptr_set(mesg)); if(message_has_tsig(mesg)) { ya_result ret; tsig_update_time(mesg); if(ISOK(ret = tsig_digest_answer(mesg))) { ret = tsig_add_tsig(mesg); } return ret; } else { log_err("tsig_digest_answer() called on a message without TSIG"); return TSIG_BADKEY; } } /** * Signs the message query with its TSIG */ ya_result tsig_sign_query(message_data *mesg) { yassert(message_is_additional_section_ptr_set(mesg)); ya_result ret; // tsig_update_time(mesg); if(ISOK(ret = tsig_digest_query(mesg))) { ret = tsig_add_tsig(mesg); } return ret; } /** * On a RECEIVED message. * * Adds a TSIG error to the message * */ #if 0 ya_result tsig_append_unsigned_error(message_data *mesg) { yassert(message_is_additional_section_ptr_set(mesg)); u16 ar_count = message_get_additional_count(mesg); packet_unpack_reader_data purd; packet_reader_init_from_message(&purd, mesg); packet_reader_skip_fqdn(&purd); purd.offset += 4; message_set_size(mesg, purd.offset); message_set_query_answer_authority_additional_counts_ne(mesg, NU16(1), 0, 0, 0); if(!message_has_tsig(mesg) || message_get_buffer_size(mesg) < message_get_size(mesg) + // valid use of message_get_buffer_size() mesg->_tsig.tsig->name_len + /* DNS NAME of the TSIG (name of the key) */ 0 + /* MAC */ 0 + /* OTHER DATA */ 12 /*DO NOT REPLACE*/) /* = time + fudge + mac size + original id + error + other len */ { /* Cannot sign */ return TSIG_UNABLE_TO_SIGN; } u8 *tsig_ptr = message_get_buffer_limit(mesg); /* record */ memcpy(tsig_ptr, mesg->_tsig.tsig->name, mesg->_tsig.tsig->name_len); tsig_ptr += mesg->_tsig.tsig->name_len; memcpy(tsig_ptr, tsig_typeclassttl, sizeof(tsig_typeclassttl)); tsig_ptr += sizeof(tsig_typeclassttl); u16 *rdata_size_ptr = (u16*)tsig_ptr; tsig_ptr += 2; /* rdata */ memcpy(tsig_ptr, mesg->_tsig.tsig->mac_algorithm_name, mesg->_tsig.tsig->mac_algorithm_name_len); tsig_ptr += mesg->_tsig.tsig->mac_algorithm_name_len; SET_U16_AT(tsig_ptr[ 0], mesg->_tsig.timehi); SET_U32_AT(tsig_ptr[ 2], mesg->_tsig.timelo); SET_U16_AT(tsig_ptr[ 6], mesg->_tsig.fudge); SET_U16_AT(tsig_ptr[ 8], 0); /* MAC len */ SET_U16_AT(tsig_ptr[10], mesg->_tsig.original_id); SET_U16_AT(tsig_ptr[12], mesg->_tsig.error); SET_U16_AT(tsig_ptr[14], 0); /* Error len */ tsig_ptr += 16; u16 rdata_size = (tsig_ptr - (u8*)rdata_size_ptr) - 2; SET_U16_AT(*rdata_size_ptr, htons(rdata_size)); message_set_size(mesg, tsig_ptr - message_get_buffer(mesg)); message_set_additional_count(mesg, ar_count + 1); return SUCCESS; } #endif ya_result tsig_append_unsigned_error(message_data *mesg) { yassert(message_is_additional_section_ptr_set(mesg)); u16 ar_count = message_get_additional_count(mesg); packet_unpack_reader_data purd; packet_reader_init_from_message(&purd, mesg); packet_reader_skip_fqdn(&purd); // checked below if(FAIL(packet_reader_skip(&purd, 4))) // type class { return TSIG_UNABLE_TO_SIGN; } message_set_size(mesg, purd.offset); message_set_query_answer_authority_additional_counts_ne(mesg, NU16(1), 0, 0, 0); if(!message_has_tsig(mesg) || message_get_buffer_size(mesg) < message_get_size(mesg) + // valid use of message_get_buffer_size() mesg->_tsig.tsig->name_len + /* DNS NAME of the TSIG (name of the key) */ 0 + /* MAC */ 0 + /* OTHER DATA */ 12 /* DO NOT REPLACE THIS VALUE */) /* = time + fudge + mac size + original id + error + other len */ { /* Cannot sign */ return TSIG_UNABLE_TO_SIGN; } u8 *tsig_ptr = message_get_buffer_limit(mesg); /* record */ memcpy(tsig_ptr, mesg->_tsig.tsig->name, mesg->_tsig.tsig->name_len); tsig_ptr += mesg->_tsig.tsig->name_len; memcpy(tsig_ptr, tsig_typeclassttl, sizeof(tsig_typeclassttl)); tsig_ptr += sizeof(tsig_typeclassttl); u16 *rdata_size_ptr = (u16*)tsig_ptr; tsig_ptr += 2; /* rdata */ memcpy(tsig_ptr, mesg->_tsig.tsig->mac_algorithm_name, mesg->_tsig.tsig->mac_algorithm_name_len); tsig_ptr += mesg->_tsig.tsig->mac_algorithm_name_len; SET_U16_AT(tsig_ptr[ 0], mesg->_tsig.timehi); SET_U32_AT(tsig_ptr[ 2], mesg->_tsig.timelo); SET_U16_AT(tsig_ptr[ 6], mesg->_tsig.fudge); SET_U16_AT(tsig_ptr[ 8], 0); /* MAC len */ SET_U16_AT(tsig_ptr[10], mesg->_tsig.original_id); SET_U16_AT(tsig_ptr[12], mesg->_tsig.error); SET_U16_AT(tsig_ptr[14], 0); /* Error len */ tsig_ptr += 16; u16 rdata_size = (tsig_ptr - (u8*)rdata_size_ptr) - 2; SET_U16_AT(*rdata_size_ptr, htons(rdata_size)); message_set_size(mesg, tsig_ptr - message_get_buffer(mesg)); message_set_additional_count(mesg, ar_count + 1); return SUCCESS; } ya_result tsig_append_error(message_data *mesg) { yassert(message_is_additional_section_ptr_set(mesg)); message_update_answer_status(mesg); tsig_sign_answer(mesg); return SUCCESS; } ya_result tsig_sign_tcp_first_message(struct message_data *mesg) { ya_result ret = tsig_sign_answer(mesg); /* I must NOT clear the digest memory : it has already been done at the end of tsig_sign_answer */ if(FAIL(ret)) { return ret; } /* * Reset the digest * * Digest the digest (mesg->_tsig.mac, mesg->_tsig.mac_size (NETWORK ORDERED!)) */ yassert(mesg->_tsig.hmac == NULL); // ensure it's clean mesg->_tsig.hmac = tsig_hmac_allocate(); if(mesg->_tsig.hmac == NULL) { return INVALID_STATE_ERROR; } if(FAIL(hmac_init(mesg->_tsig.hmac, message_tsig_get_key_bytes(mesg), message_tsig_get_key_size(mesg), mesg->_tsig.tsig->mac_algorithm))) { hmac_free(mesg->_tsig.hmac); mesg->_tsig.hmac = NULL; return ERROR; } u16 mac_size_ne = htons(mesg->_tsig.mac_size); #if LOG_DIGEST_INPUT log_debug("tsig_sign_tcp_first_message(%p = %{dnsname} %{dnstype} %{dnsclass})", mesg, message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif #if LOG_DIGEST_INPUT log_debug("tsig_sign_tcp_first_message: previous digest: (%p)", mesg); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, (u8*) &mac_size_ne, 2, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, mesg->_tsig.mac, mesg->_tsig.mac_size, 32); #endif hmac_update(mesg->_tsig.hmac, (u8*) &mac_size_ne, 2); hmac_update(mesg->_tsig.hmac, mesg->_tsig.mac, mesg->_tsig.mac_size); mesg->_tsig.tcp_tsig_countdown = TSIG_TCP_PERIOD; return SUCCESS; } ya_result tsig_sign_tcp_next_message(struct message_data *mesg) { /* * Digest the message */ #if LOG_DIGEST_INPUT log_debug("tsig_sign_tcp_next_message(%p = %{dnsname} %{dnstype} %{dnsclass})", mesg, message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif hmac_update(mesg->_tsig.hmac, message_get_buffer_const(mesg), message_get_size(mesg)); /* * If it's the 100th since the last TSIG, then ... */ if(--mesg->_tsig.tcp_tsig_countdown == 0) { mesg->_tsig.tcp_tsig_countdown = TSIG_TCP_PERIOD; /* * Digest the time */ tsig_update_time(mesg); hmac_update(mesg->_tsig.hmac, (u8*) & mesg->_tsig.timehi, 2); hmac_update(mesg->_tsig.hmac, (u8*) & mesg->_tsig.timelo, 4); hmac_update(mesg->_tsig.hmac, (u8*) & mesg->_tsig.fudge, 2); u32 tmp_mac_size; hmac_final(mesg->_tsig.hmac, mesg->_tsig.mac, &tmp_mac_size); /* * Store the TSIG */ tsig_add_tsig(mesg); /* * Reset the digest * * Digest the digest */ hmac_reset(mesg->_tsig.hmac); if(FAIL(hmac_init(mesg->_tsig.hmac, message_tsig_get_key_bytes(mesg), message_tsig_get_key_size(mesg), mesg->_tsig.tsig->mac_algorithm))) { return ERROR; } u16 mac_size_ne = htons(mesg->_tsig.mac_size); #if LOG_DIGEST_INPUT log_debug("tsig_sign_tcp_first_message: previous digest: (%p)", mesg); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, (u8*) &mac_size_ne, 2, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, mesg->_tsig.mac, mesg->_tsig.mac_size, 32); #endif hmac_update(mesg->_tsig.hmac, (u8*) &mac_size_ne, 2); hmac_update(mesg->_tsig.hmac, mesg->_tsig.mac, mesg->_tsig.mac_size); } return SUCCESS; } ya_result tsig_sign_tcp_last_message(struct message_data *mesg) { /* * Digest the message */ #if LOG_DIGEST_INPUT log_debug("tsig_sign_tcp_last_message(%p = %{dnsname} %{dnstype} %{dnsclass})", mesg, message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif hmac_update(mesg->_tsig.hmac, message_get_buffer_const(mesg), message_get_size(mesg)); /* * If it's the 100th since the last TSIG, then ... */ mesg->_tsig.tcp_tsig_countdown = 0; /* * Digest the time */ tsig_update_time(mesg); hmac_update(mesg->_tsig.hmac, (u8*) & mesg->_tsig.timehi, 2); hmac_update(mesg->_tsig.hmac, (u8*) & mesg->_tsig.timelo, 4); hmac_update(mesg->_tsig.hmac, (u8*) & mesg->_tsig.fudge, 2); u32 tmp_mac_size; hmac_final(mesg->_tsig.hmac, mesg->_tsig.mac, &tmp_mac_size); /* * Store the TSIG */ tsig_add_tsig(mesg); hmac_free(mesg->_tsig.hmac); mesg->_tsig.hmac = NULL; return SUCCESS; } /** * If the message has no TSIG to do, it is considered to be successful. */ ya_result tsig_sign_tcp_message(struct message_data *mesg, tsig_tcp_message_position pos) { ya_result return_code = SUCCESS; if(message_has_tsig(mesg)) { switch(pos) { case TSIG_START: { return_code = tsig_sign_tcp_first_message(mesg); break; } case TSIG_MIDDLE: { return_code = tsig_sign_tcp_next_message(mesg); break; } case TSIG_END: { return_code = tsig_sign_tcp_last_message(mesg); break; } case TSIG_WHOLE: /* one packet message */ { return_code = tsig_sign_answer(mesg); break; } case TSIG_NOWHERE: { break; } } } return return_code; } ya_result tsig_verify_tcp_first_message(struct message_data *mesg, const u8 *mac, u16 mac_size) { #if LOG_DIGEST_INPUT log_debug("tsig_verify_tcp_first_message: first verify: (%p)", mesg); #endif ya_result ret = tsig_verify_answer(mesg, mac, mac_size); /* I must NOT clear the digest memory : it has already been done at the end of tsig_sign */ if(FAIL(ret)) { return ret; } /* * Reset the digest * * Digest the digest (mesg->_tsig.mac, mesg->_tsig.mac_size (NETWORK ORDERED!)) */ yassert(mesg->_tsig.hmac == NULL); // ensure it's clean mesg->_tsig.hmac = tsig_hmac_allocate(); if(mesg->_tsig.hmac == NULL) { return INVALID_STATE_ERROR; } if(FAIL(hmac_init(mesg->_tsig.hmac, message_tsig_get_key_bytes(mesg), message_tsig_get_key_size(mesg), mesg->_tsig.tsig->mac_algorithm))) { hmac_free(mesg->_tsig.hmac); mesg->_tsig.hmac = NULL; return ERROR; } u16 mac_size_network = htons(mesg->_tsig.mac_size); #if LOG_DIGEST_INPUT log_debug("tsig_verify_tcp_first_message: previous MAC: (%p)", mesg); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, (u8*) & mac_size_network, 2, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, mesg->_tsig.mac, mesg->_tsig.mac_size, 32); #endif hmac_update(mesg->_tsig.hmac, (u8*) & mac_size_network, 2); hmac_update(mesg->_tsig.hmac, mesg->_tsig.mac, mesg->_tsig.mac_size); mesg->_tsig.tcp_tsig_countdown = TSIG_TCP_PERIOD + 2; /* be a bit lenient */ return SUCCESS; } ya_result tsig_verify_tcp_next_message(struct message_data *mesg) { /* * Digest the message */ u8 mac[64]; #if LOG_DIGEST_INPUT log_debug("tsig_verify_tcp_next_message: message: (%p)", mesg); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, message_get_buffer_const(mesg), message_get_size(mesg), 32); #endif if(mesg->_tsig.tcp_tsig_countdown-- < 0) { return TSIG_BADSIG; } hmac_update(mesg->_tsig.hmac, message_get_buffer_const(mesg), message_get_size(mesg)); /* * If it has been signed ... */ if(mesg->_tsig.tsig != NULL) { mesg->_tsig.tcp_tsig_countdown = TSIG_TCP_PERIOD + 2; /* be a bit lenient */ /* * Digest the time */ #if LOG_DIGEST_INPUT log_debug("tsig_verify_tcp_next_message: timers: (%p)", mesg); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, (u8*) & mesg->_tsig.timehi, 2, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, (u8*) & mesg->_tsig.timelo, 4, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, (u8*) & mesg->_tsig.fudge, 2, 32); #endif hmac_update(mesg->_tsig.hmac, (u8*) & mesg->_tsig.timehi, 2); hmac_update(mesg->_tsig.hmac, (u8*) & mesg->_tsig.timelo, 4); hmac_update(mesg->_tsig.hmac, (u8*) & mesg->_tsig.fudge, 2); u32 tmp_mac_size; hmac_final(mesg->_tsig.hmac, mac, &tmp_mac_size); #if LOG_DIGEST_INPUT log_debug("tsig_verify_tcp_next_message: value:", mesg); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, (u8*) mac, tmp_mac_size, 32); log_debug("tsig_verify_tcp_next_message: expected:", mesg); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, (u8*) mesg->_tsig.mac, tmp_mac_size, 32); #endif if(memcmp(mesg->_tsig.mac, mac, tmp_mac_size) != 0) { log_debug("tsig_verify_tcp_next_message: BADSIG"); hmac_free(mesg->_tsig.hmac); mesg->_tsig.hmac = NULL; return TSIG_BADSIG; } /* * Reset the digest * * Digest the digest */ hmac_reset(mesg->_tsig.hmac); if(FAIL(hmac_init(mesg->_tsig.hmac, message_tsig_get_key_bytes(mesg), message_tsig_get_key_size(mesg), mesg->_tsig.tsig->mac_algorithm))) { return ERROR; } u16 mac_size_network = htons(mesg->_tsig.mac_size); #if LOG_DIGEST_INPUT log_debug("tsig_verify_tcp_next_message: previous MAC: (%p)", mesg); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, (u8*) & mac_size_network, 2, 32); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, mesg->_tsig.mac, mesg->_tsig.mac_size, 32); #endif hmac_update(mesg->_tsig.hmac, (u8*) & mac_size_network, 2); hmac_update(mesg->_tsig.hmac, mesg->_tsig.mac, mesg->_tsig.mac_size); } return SUCCESS; } /** * This only cleans-up after the verify * * @param mesg */ void tsig_verify_tcp_last_message(struct message_data *mesg) { /* * Clear the digest */ #if LOG_DIGEST_INPUT log_debug("tsig_verify_tcp_last_message: message: (%p)", mesg); log_memdump(MODULE_MSG_HANDLE, MSG_DEBUG, message_get_buffer_const(mesg), message_get_size(mesg), 32); #endif message_clear_hmac(mesg); } /** * Skips the header and all the records but the last AR. * * Does NOT care about errors but the ones preventing it to find the TSIG record * * Extract the TSIG * Decreases AR * Decreases the size of the message. * * Whole-message processing should avoid this as it does the job twice ... */ ya_result tsig_message_extract(struct message_data *mesg) { packet_unpack_reader_data reader; ya_result return_value; u16 ar_count = message_get_additional_count_ne(mesg); // will change endian after this if( ar_count == 0) { return 0; /* no TSIG */ } ar_count = ntohs(ar_count); u16 qd = message_get_query_count(mesg); u16 an = message_get_answer_count(mesg); u16 ns = message_get_authority_count(mesg); packet_reader_init(&reader, message_get_buffer_const(mesg), message_get_size(mesg)); reader.offset = DNS_HEADER_LENGTH; while(qd > 0) { if(FAIL(return_value = packet_reader_skip_fqdn(&reader))) { return return_value; } if(FAIL(return_value = packet_reader_skip(&reader, 4))) { return return_value; } qd--; } u16 n = an + ns + ar_count - 1; while(n > 0) { if(FAIL(return_value = packet_reader_skip_record(&reader))) { return return_value; } n--; } /* The following record is supposed to be a TSIG */ u32 tsig_offset = reader.offset; u8 fqdn[MAX_DOMAIN_LENGTH]; if(FAIL(return_value = packet_reader_read_fqdn(&reader, fqdn, sizeof(fqdn)))) { return return_value; } struct type_class_ttl_rdlen tctr; if(FAIL(return_value = packet_reader_read(&reader, &tctr, 10))) { return return_value; } if(tctr.qtype != TYPE_TSIG) { return 0; } if(tctr.qclass != CLASS_ANY) { return TSIG_FORMERR; } if(tctr.ttl != 0) { return TSIG_FORMERR; } tsig_item *tsig = tsig_get(fqdn); if(tsig == NULL) { return TSIG_BADKEY; } s32 len = ntohs(tctr.rdlen) - 16; if(len < 3 + 3) /* minimum for the fixed bytes + two relevant fqdn */ { return TSIG_FORMERR; } if(FAIL(return_value = packet_reader_read_fqdn(&reader, fqdn, sizeof(fqdn)))) { return return_value; } len -= return_value; if(packet_reader_available(&reader) < 2 + 4 + 2 + 2) { return TSIG_FORMERR; } packet_reader_read_u16_unchecked(&reader, &mesg->_tsig.timehi); // checked packet_reader_read_u32_unchecked(&reader, &mesg->_tsig.timelo); // checked packet_reader_read_u16_unchecked(&reader, &mesg->_tsig.fudge); // checked packet_reader_read_u16_unchecked(&reader, &mesg->_tsig.mac_size); // checked u16 mac_size = ntohs(mesg->_tsig.mac_size); mesg->_tsig.mac_size = mac_size; if(mac_size > sizeof(mesg->_tsig.mac)) { return TSIG_BADKEY; /* The key is bigger than anything supported */ } if(FAIL(return_value = packet_reader_read(&reader, mesg->_tsig.mac, mac_size))) { return return_value; } len -= return_value; if(packet_reader_available(&reader) < 2 + 2 + 2) { return TSIG_FORMERR; } packet_reader_read_u16_unchecked(&reader, &mesg->_tsig.original_id); // checked above packet_reader_read_u16_unchecked(&reader, &mesg->_tsig.error); // checked above packet_reader_read_u16_unchecked(&reader, &mesg->_tsig.other_len); // checked above u16 other_len = ntohs(mesg->_tsig.other_len); len -= other_len; if(len != 0) { return TSIG_FORMERR; } mesg->_tsig.other = NULL; mesg->_tsig.other_len = 0; mesg->_tsig.tsig = tsig; mesg->_tsig.mac_algorithm = tsig->mac_algorithm; message_set_size(mesg, tsig_offset); message_set_additional_count(mesg, ar_count - 1); return 1; /* got 1 signature */ } #endif /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/tsig_algorithms.c0000644000000000000000000000013214505005532022673 xustar000000000000000030 mtime=1695812442.475982661 30 atime=1695812445.795030196 30 ctime=1695812494.756731426 yadifa-2.6.5-11201/lib/dnscore/src/tsig_algorithms.c0000664000374500037450000000761514505005532022646 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup dnscore * @brief * * @{ */ #include "dnscore/dnscore-config.h" #include #include #include "dnscore/dnscore-config.h" #include "dnscore/sys_types.h" #include "dnscore/dnsname.h" #include "dnscore/rfc.h" #include "dnscore/string_set.h" #include "dnscore/tsig.h" /* * */ static string_node *hmac_algorithms = NULL; static void tsig_string_set_insert(const char *name, u32 value) { string_node *node; u8 fqdn[MAX_DOMAIN_LENGTH]; cstr_to_dnsname(fqdn, name); node = string_set_insert(&hmac_algorithms, (char*)dnsname_dup(fqdn)); node->value = value; } void tsig_register_algorithms() { tsig_string_set_insert("hmac-md5.sig-alg.reg.int", HMAC_MD5); tsig_string_set_insert("hmac-sha1", HMAC_SHA1); tsig_string_set_insert("hmac-sha224", HMAC_SHA224); tsig_string_set_insert("hmac-sha256", HMAC_SHA256); tsig_string_set_insert("hmac-sha384", HMAC_SHA384); tsig_string_set_insert("hmac-sha512", HMAC_SHA512); } void tsig_finalize_algorithms() { string_set_iterator iter; string_set_iterator_init(&hmac_algorithms, &iter); while(string_set_iterator_hasnext(&iter)) { string_node* node = string_set_iterator_next_node(&iter); free((void*)node->key); } string_set_destroy(&hmac_algorithms); } u8 tsig_get_algorithm(const u8 *name) { string_node *node = string_set_find(&hmac_algorithms, (char*)name); return (node != NULL) ? node->value : HMAC_UNKNOWN; } const u8* tsig_get_algorithm_name(u8 algorithm) { switch(algorithm) { case HMAC_MD5: return (u8*)"\010hmac-md5\007sig-alg\003reg\003int"; case HMAC_SHA1: return (u8*)"\011hmac-sha1"; case HMAC_SHA224: return (u8*)"\013hmac-sha224"; case HMAC_SHA256: return (u8*)"\013hmac-sha256"; case HMAC_SHA384: return (u8*)"\013hmac-sha384"; case HMAC_SHA512: return (u8*)"\013hmac-sha512"; default: return (u8*)"\004null"; /* UNKNOWN */ } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/src/PaxHeaders.1636/nsid.c0000644000000000000000000000013214505005532020431 xustar000000000000000030 mtime=1695812442.453982345 30 atime=1695812445.794030182 30 ctime=1695812494.758731455 yadifa-2.6.5-11201/lib/dnscore/src/nsid.c0000664000374500037450000000730314505005532020376 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnscore * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnscore/dnscore-config.h" #include //#include //#include //#include "dnscore/dnscore-config.h" #define DNSCORE_NSID_C #include "dnscore/nsid.h" #include "dnscore/rfc.h" static u8 edns0_rdatasize_nsid_option_wire_default[2] = {0,0}; u32 edns0_record_size = EDNS0_RECORD_SIZE; u8 *edns0_rdatasize_nsid_option_wire = edns0_rdatasize_nsid_option_wire_default; u32 edns0_rdatasize_nsid_option_wire_size = 2; void edns0_set_nsid(u8 *bytes, u16 size) { if(bytes != NULL) { if(size > EDNS0_NSID_SIZE_MAX) { return; } u8 *tmp = malloc(2 + 2 + 2 + size); if(tmp == NULL) { return; } tmp[0] = (size + 4) >> 8; tmp[1] = (size + 4) & 255; // VS false positive (nonsense) tmp[2] = 0; tmp[3] = EDNS0_OPT_3; tmp[4] = size >> 8; tmp[5] = size & 255; memcpy(&tmp[6], bytes, size); if(edns0_rdatasize_nsid_option_wire != edns0_rdatasize_nsid_option_wire_default) { free(edns0_rdatasize_nsid_option_wire); } edns0_rdatasize_nsid_option_wire = tmp; edns0_rdatasize_nsid_option_wire_size = 6 + size; edns0_record_size = EDNS0_RECORD_SIZE - 2 + edns0_rdatasize_nsid_option_wire_size; } else { if(edns0_rdatasize_nsid_option_wire != edns0_rdatasize_nsid_option_wire_default) { free(edns0_rdatasize_nsid_option_wire); edns0_rdatasize_nsid_option_wire = edns0_rdatasize_nsid_option_wire_default; edns0_rdatasize_nsid_option_wire_size = 2; edns0_record_size = EDNS0_RECORD_SIZE; } } } /** @} */ yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/Makefile.in0000644000000000000000000000013214505005546020613 xustar000000000000000030 mtime=1695812454.977161703 30 atime=1695812461.821259724 30 ctime=1695812494.119722303 yadifa-2.6.5-11201/lib/dnscore/Makefile.in0000664000374500037450000023210114505005546020554 0ustar00signersigner00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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@ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ # # ALL # ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ 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@ DIST_COMMON = $(srcdir)/../../mk/common-settings.mk \ $(srcdir)/../../mk/common-labels.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp \ $(dist_noinst_DATA) $(am__pkginclude_HEADERS_DIST) AUTHORS \ COPYING ChangeLog INSTALL NEWS README @USES_SUNC_TRUE@am__append_1 = @USES_SUNC_FALSE@am__append_2 = -O0 @IS_DARWIN_OS_TRUE@am__append_3 = -Wno-deprecated @HAS_CC_NO_IDENT_TRUE@am__append_4 = -fno-ident @HAS_CC_ANSI_TRUE@am__append_5 = -ansi @HAS_CC_PEDANTIC_TRUE@am__append_6 = -pedantic @HAS_CC_WALL_TRUE@am__append_7 = -Wall -Wno-unknown-pragmas @HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE@am__append_8 = -Werror=missing-field-initializers @HAS_CC_STD_GNU11_TRUE@am__append_9 = -std=gnu11 @HAS_CC_STD_C11_TRUE@@HAS_CC_STD_GNU11_FALSE@am__append_10 = -std=c11 -D_GNU_SOURCE @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_TRUE@am__append_11 = -std=gnu99 @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_C99_TRUE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_FALSE@am__append_12 = -std=c99 @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_C99_FALSE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_FALSE@@HAS_CC_XC99_TRUE@am__append_13 = -xc99 @HAS_CC_TUNE_NATIVE_TRUE@am__append_14 = -mtune=native @FORCE64BITS_TRUE@@HAS_CC_M64_TRUE@am__append_15 = -m64 @FORCE64BITS_TRUE@@HAS_CC_M64_TRUE@am__append_16 = -m64 @FORCE32BITS_TRUE@@FORCE64BITS_FALSE@@HAS_CC_M32_TRUE@am__append_17 = -m32 @FORCE32BITS_TRUE@@FORCE64BITS_FALSE@@HAS_CC_M32_TRUE@am__append_18 = -m32 # # DEBUG # @HAS_CC_G3_TRUE@am__append_19 = -g3 @HAS_CC_G3_FALSE@@HAS_CC_G_TRUE@am__append_20 = -g @HAS_CC_DWARF4_TRUE@am__append_21 = -gdwarf-4 @HAS_CC_DWARF3_TRUE@@HAS_CC_DWARF4_FALSE@am__append_22 = -gdwarf-3 # # Intel C Compiler # ############################################################################### #ICC #IPO= -ipo (need to use the intel xiar instead of ar) @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@am__append_23 = -DLTO -ipo @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@am__append_24 = -ipo @USES_ICC_TRUE@am__append_25 = -DUSES_ICC @HAS_CC_ANSI_ALIAS_TRUE@@USES_ICC_TRUE@am__append_26 = -ansi-alias -U__STRICT_ANSI__ @USES_ICC_TRUE@am__append_27 = -DMODE_DEBUG_ICC # # LLVM Clang # ############################################################################### # CLANG @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@am__append_28 = -DLTO -flto @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@am__append_29 = -flto @USES_CLANG_TRUE@am__append_30 = -DUSES_LLVM -Wno-gnu #-Wno-extended-offsetof @USES_CLANG_TRUE@am__append_31 = -DMODE_DEBUG_CLANG -fsanitize=address -fsanitize=bounds @IS_LINUX_FAMILY_TRUE@@USES_CLANG_TRUE@am__append_32 = -Wl,-z,stack-size=8388608 # Note: add a _d suffix for debug builds ? # # Gnu C # ############################################################################### #GCC @HAS_CPU_NIAGARA_TRUE@@USES_GCC_TRUE@am__append_33 = -mcpu=niagara @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_34 = -DLTO -flto -fwhole-program -fno-fat-lto-objects -fuse-linker-plugin @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_35 = -flto \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fwhole-program \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fno-fat-lto-objects \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fuse-linker-plugin \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -Wl,-Map=module.map \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -Wl,--cref @USES_GCC_TRUE@am__append_36 = -DUSES_GCC @USES_GCC_TRUE@am__append_37 = -DMODE_DEBUG_GCC -fstack-check -fstack-protector-strong @HAS_BFD_DEBUG_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_38 = -rdynamic @IS_LINUX_FAMILY_TRUE@@USES_GCC_TRUE@am__append_39 = -Wl,-z,stack-size=8388608 @USES_SUNC_TRUE@am__append_40 = -DUSES_SUNC @USES_SUNC_TRUE@am__append_41 = -DMODE_DEBUG_SUNC # Note: add a _d suffix for debug builds ? # # Unknown compiler # ############################################################################### # if an unknown compiler is used, it should have its own section @USES_UNKNOWN_TRUE@am__append_42 = -DUSES_UNKNOWN_COMPILER @USES_UNKNOWN_TRUE@am__append_43 = -DMODE_DEBUG_UNKNOWN # # Some BSD-based OSes need this # @IS_BSD_FAMILY_TRUE@am__append_44 = -I./include @IS_SOLARIS_FAMILY_TRUE@am__append_45 = -D_POSIX_PTHREAD_SEMANTICS # $(I)/ipc.h # $(I)/name.h @IS_DARWIN_OS_TRUE@am__append_46 = $(I)/osx_clock_gettime.h @IS_DARWIN_OS_TRUE@am__append_47 = src/osx_clock_gettime.c @HAS_NSID_SUPPORT_TRUE@am__append_48 = $(I)/nsid.h @HAS_NSID_SUPPORT_TRUE@am__append_49 = src/nsid.c subdir = lib/dnscore ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/eurid.m4 $(top_srcdir)/m4/yadifa.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = 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__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libdnscore_la_LIBADD = am__libdnscore_la_SOURCES_DIST = src/alarm.c src/acl.c \ src/acl-config.c src/allocator.c src/async.c src/base16.c \ src/base32.c src/base32hex.c src/base64.c \ src/basic-priority-queue.c src/buffer_input_stream.c \ src/buffer_output_stream.c src/buffered-file.c \ src/bytearray_input_stream.c src/bytearray_output_stream.c \ src/bytezarray_output_stream.c src/checked_output_stream.c \ src/chroot.c src/circular-file.c \ src/clone_input_output_stream.c src/cmdline.c \ src/concat_input_stream.c src/config-cmdline.c \ src/config_file_reader.c src/config_key.c src/config_logger.c \ src/config_settings.c src/config_struct.c \ src/counter_output_stream.c src/debug.c src/debug_bench.c \ src/debug_bfd.c src/debug_malloc.c src/debug_mmap.c \ src/debug_stacktrace.c src/digest_rawdata.c src/digest_sha1.c \ src/digest_sha256.c src/digest_sha384.c src/digest_sha512.c \ src/dns-udp.c src/dns_resource_record.c src/dnscore.c \ src/dnsformat.c src/dnskey.c src/dnskey-keyring.c \ src/dnskey_dsa.c src/dnskey_ecdsa.c src/dnskey_eddsa.c \ src/dnskey_rsa.c src/dnskey-signature.c src/dnsname.c \ src/empty-input-stream.c src/error_state.c src/fdtools.c \ src/file_input_stream.c src/file_output_stream.c \ src/file-pool.c src/filesystem-file.c src/format.c src/hash.c \ src/hash-table-values.c src/hmac-openssl.c src/host_address.c \ src/hsdllist.c src/identity.c src/input_stream.c src/json.c \ src/limited_input_stream.c src/limiter.c src/list-dl.c \ src/list-sl.c src/list-sl-debug.c src/logger-output-stream.c \ src/logger.c src/logger_channel_file.c \ src/logger_channel_pipe.c src/logger_channel_stream.c \ src/logger_channel_syslog.c src/logger_handle.c \ src/message-buffer.c src/message-viewer.c src/message.c \ src/message_print_format_dig.c src/message_verify_rrsig.c \ src/message_dnsupdate.c src/mapped-file.c \ src/mt_output_stream.c src/mutex.c src/network.c \ src/nsec3-hash.c src/output_stream.c src/pace.c \ src/packet_reader.c src/packet_writer.c src/parser.c \ src/parsing.c src/process.c src/pid.c src/pipe_stream.c \ src/pool.c src/popen-output-stream.c src/ptr_set.c \ src/ptr_set_debug.c src/ptr_vector.c src/queue-sl.c \ src/random.c src/rc.c src/rewind-input-stream.c src/rfc.c \ src/serial.c src/server-setup.c src/service.c \ src/shared-heap.c src/shared-circular-buffer.c \ src/shared-heap-bytearray-output-stream.c src/signals.c \ src/simple-http-server.c src/socket-server.c src/string_set.c \ src/sys_error.c src/sys_get_cpu_count.c src/tcp_io_stream.c \ src/thread.c src/thread_pool.c src/thread-tag.c \ src/threaded-qsl-cw.c src/threaded_dll_cw.c \ src/threaded_nb_mm.c src/threaded_nbrb.c \ src/threaded_queue_slg.c src/threaded_ringbuffer.c \ src/threaded_ringbuffer_cw.c src/threaded_ringlist.c \ src/timeformat.c src/timems.c src/typebitmap.c src/u32_set.c \ src/u64_set.c src/u64_set_debug.c src/xfr_input_stream.c \ src/zalloc.c src/zone_reader_axfr.c src/zone_reader_text.c \ src/osx_clock_gettime.c src/tsig.c src/tsig_algorithms.c \ src/nsid.c am__dirstamp = $(am__leading_dot)dirstamp @IS_DARWIN_OS_TRUE@am__objects_1 = src/osx_clock_gettime.lo @HAS_NSID_SUPPORT_TRUE@am__objects_2 = src/nsid.lo am_libdnscore_la_OBJECTS = src/alarm.lo src/acl.lo src/acl-config.lo \ src/allocator.lo src/async.lo src/base16.lo src/base32.lo \ src/base32hex.lo src/base64.lo src/basic-priority-queue.lo \ src/buffer_input_stream.lo src/buffer_output_stream.lo \ src/buffered-file.lo src/bytearray_input_stream.lo \ src/bytearray_output_stream.lo src/bytezarray_output_stream.lo \ src/checked_output_stream.lo src/chroot.lo \ src/circular-file.lo src/clone_input_output_stream.lo \ src/cmdline.lo src/concat_input_stream.lo \ src/config-cmdline.lo src/config_file_reader.lo \ src/config_key.lo src/config_logger.lo src/config_settings.lo \ src/config_struct.lo src/counter_output_stream.lo src/debug.lo \ src/debug_bench.lo src/debug_bfd.lo src/debug_malloc.lo \ src/debug_mmap.lo src/debug_stacktrace.lo \ src/digest_rawdata.lo src/digest_sha1.lo src/digest_sha256.lo \ src/digest_sha384.lo src/digest_sha512.lo src/dns-udp.lo \ src/dns_resource_record.lo src/dnscore.lo src/dnsformat.lo \ src/dnskey.lo src/dnskey-keyring.lo src/dnskey_dsa.lo \ src/dnskey_ecdsa.lo src/dnskey_eddsa.lo src/dnskey_rsa.lo \ src/dnskey-signature.lo src/dnsname.lo \ src/empty-input-stream.lo src/error_state.lo src/fdtools.lo \ src/file_input_stream.lo src/file_output_stream.lo \ src/file-pool.lo src/filesystem-file.lo src/format.lo \ src/hash.lo src/hash-table-values.lo src/hmac-openssl.lo \ src/host_address.lo src/hsdllist.lo src/identity.lo \ src/input_stream.lo src/json.lo src/limited_input_stream.lo \ src/limiter.lo src/list-dl.lo src/list-sl.lo \ src/list-sl-debug.lo src/logger-output-stream.lo src/logger.lo \ src/logger_channel_file.lo src/logger_channel_pipe.lo \ src/logger_channel_stream.lo src/logger_channel_syslog.lo \ src/logger_handle.lo src/message-buffer.lo \ src/message-viewer.lo src/message.lo \ src/message_print_format_dig.lo src/message_verify_rrsig.lo \ src/message_dnsupdate.lo src/mapped-file.lo \ src/mt_output_stream.lo src/mutex.lo src/network.lo \ src/nsec3-hash.lo src/output_stream.lo src/pace.lo \ src/packet_reader.lo src/packet_writer.lo src/parser.lo \ src/parsing.lo src/process.lo src/pid.lo src/pipe_stream.lo \ src/pool.lo src/popen-output-stream.lo src/ptr_set.lo \ src/ptr_set_debug.lo src/ptr_vector.lo src/queue-sl.lo \ src/random.lo src/rc.lo src/rewind-input-stream.lo src/rfc.lo \ src/serial.lo src/server-setup.lo src/service.lo \ src/shared-heap.lo src/shared-circular-buffer.lo \ src/shared-heap-bytearray-output-stream.lo src/signals.lo \ src/simple-http-server.lo src/socket-server.lo \ src/string_set.lo src/sys_error.lo src/sys_get_cpu_count.lo \ src/tcp_io_stream.lo src/thread.lo src/thread_pool.lo \ src/thread-tag.lo src/threaded-qsl-cw.lo \ src/threaded_dll_cw.lo src/threaded_nb_mm.lo \ src/threaded_nbrb.lo src/threaded_queue_slg.lo \ src/threaded_ringbuffer.lo src/threaded_ringbuffer_cw.lo \ src/threaded_ringlist.lo src/timeformat.lo src/timems.lo \ src/typebitmap.lo src/u32_set.lo src/u64_set.lo \ src/u64_set_debug.lo src/xfr_input_stream.lo src/zalloc.lo \ src/zone_reader_axfr.lo src/zone_reader_text.lo \ $(am__objects_1) src/tsig.lo src/tsig_algorithms.lo \ $(am__objects_2) libdnscore_la_OBJECTS = $(am_libdnscore_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 = libdnscore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libdnscore_la_LDFLAGS) $(LDFLAGS) -o $@ 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__depfiles_maybe = depfiles 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 = $(libdnscore_la_SOURCES) DIST_SOURCES = $(am__libdnscore_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_noinst_DATA) am__pkginclude_HEADERS_DIST = $(I)/alarm.h $(I)/acl.h \ $(I)/acl-config.h $(I)/allocator.h $(I)/async.h $(I)/avl.c.inc \ $(I)/avl.h.inc $(I)/base16.h $(I)/base32.h $(I)/base32hex.h \ $(I)/base64.h $(I)/basic-priority-queue.h \ $(I)/buffer_input_stream.h $(I)/buffer_output_stream.h \ $(I)/buffered-file.h $(I)/bytearray_input_stream.h \ $(I)/bytearray_output_stream.h $(I)/bytezarray_output_stream.h \ $(I)/checked_output_stream.h $(I)/chroot.h \ $(I)/circular-file.h $(I)/clone_input_output_stream.h \ $(I)/cmdline.h $(I)/concat_input_stream.h \ $(I)/config-cmdline.h $(I)/config_file_reader.h \ $(I)/config_settings.h $(I)/counter_output_stream.h \ $(I)/ctrl-rfc.h $(I)/debug.h $(I)/debug_config.h $(I)/digest.h \ $(I)/dns-udp.h $(I)/dns_resource_record.h $(I)/dnscore.h \ $(I)/dnscore-release-date.h $(I)/dnsformat.h $(I)/dnskey.h \ $(I)/dnskey-keyring.h $(I)/dnskey_dsa.h $(I)/dnskey_ecdsa.h \ $(I)/dnskey_eddsa.h $(I)/dnskey_rsa.h $(I)/dnskey-signature.h \ $(I)/dnsname.h $(I)/dnsname_set.h $(I)/dnssec_errors.h \ $(I)/empty-input-stream.h $(I)/error_state.h $(I)/fdtools.h \ $(I)/file.h $(I)/file_input_stream.h $(I)/file_output_stream.h \ $(I)/file-pool.h $(I)/filesystem-file.h $(I)/fingerprint.h \ $(I)/format.h $(I)/hash.h $(I)/hmac.h $(I)/host_address.h \ $(I)/hsdllist.h $(I)/identity.h $(I)/input_stream.h \ $(I)/io_stream.h $(I)/json.h $(I)/limited_input_stream.h \ $(I)/limiter.h $(I)/list-dl.h $(I)/list-sl.h \ $(I)/list-sl-debug.h $(I)/logger.h $(I)/logger_channel_file.h \ $(I)/logger_channel_pipe.h $(I)/logger_channel_stream.h \ $(I)/logger_channel_syslog.h $(I)/logger_handle.h \ $(I)/logger-output-stream.h $(I)/mapped-file.h \ $(I)/message-buffer.h $(I)/message-viewer.h $(I)/message.h \ $(I)/message_verify_rrsig.h $(I)/message_dnsupdate.h \ $(I)/mt_output_stream.h $(I)/mutex.h $(I)/network.h \ $(I)/nsec3-hash.h $(I)/openssl.h $(I)/output_stream.h \ $(I)/pace.h $(I)/packet_reader.h $(I)/packet_writer.h \ $(I)/parser.h $(I)/parsing.h $(I)/pid.h $(I)/pipe_stream.h \ $(I)/pool.h $(I)/popen-output-stream.h $(I)/print_stream.h \ $(I)/process.h $(I)/ptr_set.h $(I)/ptr_set_debug.h \ $(I)/ptr_vector.h $(I)/queue-sl.h $(I)/random.h $(I)/rc.h \ $(I)/rewind-input-stream.h $(I)/rfc.h $(I)/serial.h \ $(I)/server-setup.h $(I)/service.h $(I)/shared-heap.h \ $(I)/shared-circular-buffer.h \ $(I)/shared-heap-bytearray-output-stream.h $(I)/signals.h \ $(I)/simple-http-server.h $(I)/socket-server.h \ $(I)/string_set.h $(I)/sys_error.h $(I)/sys_get_cpu_count.h \ $(I)/sys_types.h $(I)/tcp_io_stream.h $(I)/tcp_manager.h \ $(I)/thread.h $(I)/thread_pool.h $(I)/thread-tag.h \ $(I)/threaded-qsl-cw.h $(I)/threaded_dll_cw.h \ $(I)/threaded_nb_mm.h $(I)/threaded_nbrb.h \ $(I)/threaded_queue.h $(I)/threaded_queue_slg.h \ $(I)/threaded_ringbuffer.h $(I)/threaded_ringbuffer_cw.h \ $(I)/threaded_ringlist.h $(I)/timeformat.h $(I)/timems.h \ $(I)/typebitmap.h $(I)/u32_set.h $(I)/u64_set.h \ $(I)/u64_set_debug.h $(I)/xfr_input_stream.h $(I)/zalloc.h \ $(I)/zone_reader.h $(I)/zone_reader_axfr.h \ $(I)/zone_reader_text.h $(I)/zonefile_reader.h \ $(I)/osx_clock_gettime.h $(I)/tsig.h $(I)/nsid.h HEADERS = $(pkginclude_HEADERS) 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)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) # libdnscore_ladir=. # alphabetically please pkgincludedir = $(includedir)/dnscore ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCOPTIMISATIONFLAGS = @CCOPTIMISATIONFLAGS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DNSCORE = @DNSCORE@ DNSDB = @DNSDB@ DNSLG = @DNSLG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAS_ACL_SUPPORT = @HAS_ACL_SUPPORT@ HAS_BFD_DEBUG_SUPPORT = @HAS_BFD_DEBUG_SUPPORT@ HAS_BIG_ENDIAN = @HAS_BIG_ENDIAN@ HAS_BUILD_TIMESTAMP = @HAS_BUILD_TIMESTAMP@ HAS_CC_ADDRESS_SANITIZER_CHECK = @HAS_CC_ADDRESS_SANITIZER_CHECK@ HAS_CC_ANSI = @HAS_CC_ANSI@ HAS_CC_ANSI_ALIAS = @HAS_CC_ANSI_ALIAS@ HAS_CC_CATCH_UNDEFINED_BEHAVIOR = @HAS_CC_CATCH_UNDEFINED_BEHAVIOR@ HAS_CC_DWARF2 = @HAS_CC_DWARF2@ HAS_CC_DWARF3 = @HAS_CC_DWARF3@ HAS_CC_DWARF4 = @HAS_CC_DWARF4@ HAS_CC_EXCEPTIONS = @HAS_CC_EXCEPTIONS@ HAS_CC_G = @HAS_CC_G@ HAS_CC_G3 = @HAS_CC_G3@ HAS_CC_M32 = @HAS_CC_M32@ HAS_CC_M64 = @HAS_CC_M64@ HAS_CC_MISSING_FIELD_INITIALIZERS = @HAS_CC_MISSING_FIELD_INITIALIZERS@ HAS_CC_NO_IDENT = @HAS_CC_NO_IDENT@ HAS_CC_NO_OMIT_FRAME_POINTER = @HAS_CC_NO_OMIT_FRAME_POINTER@ HAS_CC_PEDANTIC = @HAS_CC_PEDANTIC@ HAS_CC_RDYNAMIC = @HAS_CC_RDYNAMIC@ HAS_CC_SANITIZE_ADDRESS = @HAS_CC_SANITIZE_ADDRESS@ HAS_CC_STACK_PROTECTOR = @HAS_CC_STACK_PROTECTOR@ HAS_CC_STD_C11 = @HAS_CC_STD_C11@ HAS_CC_STD_C99 = @HAS_CC_STD_C99@ HAS_CC_STD_GNU11 = @HAS_CC_STD_GNU11@ HAS_CC_STD_GNU99 = @HAS_CC_STD_GNU99@ HAS_CC_TUNE_NATIVE = @HAS_CC_TUNE_NATIVE@ HAS_CC_WALL = @HAS_CC_WALL@ HAS_CC_XC99 = @HAS_CC_XC99@ HAS_CLOSE_EX_REF = @HAS_CLOSE_EX_REF@ HAS_CTRL = @HAS_CTRL@ HAS_DNSSEC_TOOLS = @HAS_DNSSEC_TOOLS@ HAS_DYNUPDATE_SUPPORT = @HAS_DYNUPDATE_SUPPORT@ HAS_ECDSA_SUPPORT = @HAS_ECDSA_SUPPORT@ HAS_EDDSA = @HAS_EDDSA@ HAS_EVENT_DYNAMIC_MODULE = @HAS_EVENT_DYNAMIC_MODULE@ HAS_FULL_ASCII7 = @HAS_FULL_ASCII7@ HAS_KEYGEN = @HAS_KEYGEN@ HAS_LIBC_MALLOC_DEBUG_SUPPORT = @HAS_LIBC_MALLOC_DEBUG_SUPPORT@ HAS_LITTLE_ENDIAN = @HAS_LITTLE_ENDIAN@ HAS_LOCK_DEBUG_SUPPORT = @HAS_LOCK_DEBUG_SUPPORT@ HAS_LOGDIR = @HAS_LOGDIR@ HAS_LOG_PID = @HAS_LOG_PID@ HAS_LOG_THREAD_ID = @HAS_LOG_THREAD_ID@ HAS_LOG_THREAD_TAG = @HAS_LOG_THREAD_TAG@ HAS_MALLOC_DEBUG_SUPPORT = @HAS_MALLOC_DEBUG_SUPPORT@ HAS_MASTER_SUPPORT = @HAS_MASTER_SUPPORT@ HAS_MEMALIGN_ISSUES = @HAS_MEMALIGN_ISSUES@ HAS_MUTEX_DEBUG_SUPPORT = @HAS_MUTEX_DEBUG_SUPPORT@ HAS_NON_AA_AXFR_SUPPORT = @HAS_NON_AA_AXFR_SUPPORT@ HAS_NSEC3_SUPPORT = @HAS_NSEC3_SUPPORT@ HAS_NSEC_SUPPORT = @HAS_NSEC_SUPPORT@ HAS_NSID_SUPPORT = @HAS_NSID_SUPPORT@ HAS_RRL_SUPPORT = @HAS_RRL_SUPPORT@ HAS_RRSIG_MANAGEMENT_SUPPORT = @HAS_RRSIG_MANAGEMENT_SUPPORT@ HAS_SYNC_BUILTINS = @HAS_SYNC_BUILTINS@ HAS_SYSTEMD_RESOLVED_AVOIDANCE = @HAS_SYSTEMD_RESOLVED_AVOIDANCE@ HAS_TESTS = @HAS_TESTS@ HAS_TOOLS = @HAS_TOOLS@ HAS_TRACK_ZONES_DEBUG_SUPPORT = @HAS_TRACK_ZONES_DEBUG_SUPPORT@ HAS_TSIG_SUPPORT = @HAS_TSIG_SUPPORT@ HAS_YADIFA = @HAS_YADIFA@ HAS_ZALLOC_DEBUG_SUPPORT = @HAS_ZALLOC_DEBUG_SUPPORT@ HAS_ZALLOC_STATISTICS_SUPPORT = @HAS_ZALLOC_STATISTICS_SUPPORT@ HAS_ZALLOC_SUPPORT = @HAS_ZALLOC_SUPPORT@ HAVE_RECVMMSG = @HAVE_RECVMMSG@ HAVE_SENDMMSG = @HAVE_SENDMMSG@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IS_BSD_FAMILY = @IS_BSD_FAMILY@ IS_DARWIN_GE14 = @IS_DARWIN_GE14@ IS_DARWIN_OS = @IS_DARWIN_OS@ IS_LINUX_FAMILY = @IS_LINUX_FAMILY@ IS_SOLARIS_FAMILY = @IS_SOLARIS_FAMILY@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL = @OPENSSL@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZDB_HAS_DNSSEC_SUPPORT = @ZDB_HAS_DNSSEC_SUPPORT@ 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_CXX = @ac_ct_CXX@ 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@ 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@ logdir = @logdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 # # # AM_CFLAGS = -D_THREAD_SAFE -D_REENTRANT -D_FILE_OFFSET_BITS=64 \ -I$(abs_builddir) -I$(abs_builddir)/include \ -I$(abs_srcdir)/include $(am__append_3) $(am__append_4) \ $(am__append_5) $(am__append_6) $(am__append_7) \ $(am__append_8) $(am__append_9) $(am__append_10) \ $(am__append_11) $(am__append_12) $(am__append_13) \ $(am__append_14) $(am__append_15) $(am__append_17) \ $(am__append_23) $(am__append_25) $(am__append_26) \ $(am__append_28) $(am__append_30) $(am__append_33) \ $(am__append_34) $(am__append_36) $(am__append_38) \ $(am__append_40) $(am__append_42) $(am__append_44) \ $(am__append_45) $(LOCALFLAGS) -DDNSCORE_BUILD=1 \ -I$(top_srcdir)/lib/dnscore/include \ -I$(top_builddir)/lib/dnscore/include AM_LDFLAGS = $(am__append_16) $(am__append_18) $(am__append_24) \ $(am__append_29) $(am__append_32) $(am__append_35) \ $(am__append_39) DEBUGFLAGS = $(am__append_1) $(am__append_2) $(am__append_19) \ $(am__append_20) $(am__append_21) $(am__append_22) \ $(am__append_27) $(am__append_31) $(am__append_37) \ $(am__append_41) $(am__append_43) LOCALFLAGS = -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)"' -DLOCALSTATEDIR='"$(localstatedir)"' -DDATAROOTDIR='"$(datarootdir)"' -DDATADIR='"$(datadir)"' -DLOCALEDIR='"$(localedir)"' -DLOGDIR='"$(logdir)"' -DTCLDIR='"$(tcldir)"' @HAS_LTO_SUPPORT_FALSE@@USES_CLANG_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_FALSE@@USES_GCC_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@AM_AR = llvm-ar @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@AM_AR = gcc-ar @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@AM_AR = xiar # # Sun C # ############################################################################### # SUNC @USES_SUNC_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_FALSE@@USES_CLANG_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_FALSE@@USES_GCC_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@AM_LD = ld.gold @USES_ICC_TRUE@AM_LD = ld @USES_SUNC_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@AM_RANLIB = gcc-ranlib #AM_CFLAGS += -I$(top_srcdir)/lib/dnsdb/include -I$(top_builddir)/lib/dnsdb/include #AM_CFLAGS += -I$(top_srcdir)/lib/dnslg/include -I$(top_builddir)/lib/dnslg/include #AM_CFLAGS += -I$(top_srcdir)/lib/dnstcl/include -I$(top_builddir)/lib/dnstcl/include dist_noinst_DATA = VERSION include/dnscore/thirdparty/stdatomic.h src/tcp_manager.c lib_LTLIBRARIES = libdnscore.la libdnscore_la_LDFLAGS = -version-info 7:5:0 #libdnscore_la_LIBADD=$(top_buildir)/lib/.../libsomething.la I = include/dnscore FEATURESFILE = dnscore-config-features.h FEATURES = $(I)/$(FEATURESFILE) FEATURESDIR = lib/dnscore/include/dnscore FEATURESSRC = $(top_builddir)/$(FEATURESDIR)/dnscore-config.h pkginclude_HEADERS = $(I)/alarm.h $(I)/acl.h $(I)/acl-config.h \ $(I)/allocator.h $(I)/async.h $(I)/avl.c.inc $(I)/avl.h.inc \ $(I)/base16.h $(I)/base32.h $(I)/base32hex.h $(I)/base64.h \ $(I)/basic-priority-queue.h $(I)/buffer_input_stream.h \ $(I)/buffer_output_stream.h $(I)/buffered-file.h \ $(I)/bytearray_input_stream.h $(I)/bytearray_output_stream.h \ $(I)/bytezarray_output_stream.h $(I)/checked_output_stream.h \ $(I)/chroot.h $(I)/circular-file.h \ $(I)/clone_input_output_stream.h $(I)/cmdline.h \ $(I)/concat_input_stream.h $(I)/config-cmdline.h \ $(I)/config_file_reader.h $(I)/config_settings.h \ $(I)/counter_output_stream.h $(I)/ctrl-rfc.h $(I)/debug.h \ $(I)/debug_config.h $(I)/digest.h $(I)/dns-udp.h \ $(I)/dns_resource_record.h $(I)/dnscore.h \ $(I)/dnscore-release-date.h $(I)/dnsformat.h $(I)/dnskey.h \ $(I)/dnskey-keyring.h $(I)/dnskey_dsa.h $(I)/dnskey_ecdsa.h \ $(I)/dnskey_eddsa.h $(I)/dnskey_rsa.h $(I)/dnskey-signature.h \ $(I)/dnsname.h $(I)/dnsname_set.h $(I)/dnssec_errors.h \ $(I)/empty-input-stream.h $(I)/error_state.h $(I)/fdtools.h \ $(I)/file.h $(I)/file_input_stream.h $(I)/file_output_stream.h \ $(I)/file-pool.h $(I)/filesystem-file.h $(I)/fingerprint.h \ $(I)/format.h $(I)/hash.h $(I)/hmac.h $(I)/host_address.h \ $(I)/hsdllist.h $(I)/identity.h $(I)/input_stream.h \ $(I)/io_stream.h $(I)/json.h $(I)/limited_input_stream.h \ $(I)/limiter.h $(I)/list-dl.h $(I)/list-sl.h \ $(I)/list-sl-debug.h $(I)/logger.h $(I)/logger_channel_file.h \ $(I)/logger_channel_pipe.h $(I)/logger_channel_stream.h \ $(I)/logger_channel_syslog.h $(I)/logger_handle.h \ $(I)/logger-output-stream.h $(I)/mapped-file.h \ $(I)/message-buffer.h $(I)/message-viewer.h $(I)/message.h \ $(I)/message_verify_rrsig.h $(I)/message_dnsupdate.h \ $(I)/mt_output_stream.h $(I)/mutex.h $(I)/network.h \ $(I)/nsec3-hash.h $(I)/openssl.h $(I)/output_stream.h \ $(I)/pace.h $(I)/packet_reader.h $(I)/packet_writer.h \ $(I)/parser.h $(I)/parsing.h $(I)/pid.h $(I)/pipe_stream.h \ $(I)/pool.h $(I)/popen-output-stream.h $(I)/print_stream.h \ $(I)/process.h $(I)/ptr_set.h $(I)/ptr_set_debug.h \ $(I)/ptr_vector.h $(I)/queue-sl.h $(I)/random.h $(I)/rc.h \ $(I)/rewind-input-stream.h $(I)/rfc.h $(I)/serial.h \ $(I)/server-setup.h $(I)/service.h $(I)/shared-heap.h \ $(I)/shared-circular-buffer.h \ $(I)/shared-heap-bytearray-output-stream.h $(I)/signals.h \ $(I)/simple-http-server.h $(I)/socket-server.h \ $(I)/string_set.h $(I)/sys_error.h $(I)/sys_get_cpu_count.h \ $(I)/sys_types.h $(I)/tcp_io_stream.h $(I)/tcp_manager.h \ $(I)/thread.h $(I)/thread_pool.h $(I)/thread-tag.h \ $(I)/threaded-qsl-cw.h $(I)/threaded_dll_cw.h \ $(I)/threaded_nb_mm.h $(I)/threaded_nbrb.h \ $(I)/threaded_queue.h $(I)/threaded_queue_slg.h \ $(I)/threaded_ringbuffer.h $(I)/threaded_ringbuffer_cw.h \ $(I)/threaded_ringlist.h $(I)/timeformat.h $(I)/timems.h \ $(I)/typebitmap.h $(I)/u32_set.h $(I)/u64_set.h \ $(I)/u64_set_debug.h $(I)/xfr_input_stream.h $(I)/zalloc.h \ $(I)/zone_reader.h $(I)/zone_reader_axfr.h \ $(I)/zone_reader_text.h $(I)/zonefile_reader.h \ $(am__append_46) $(I)/tsig.h $(am__append_48) libdnscore_la_SOURCES = src/alarm.c src/acl.c src/acl-config.c \ src/allocator.c src/async.c src/base16.c src/base32.c \ src/base32hex.c src/base64.c src/basic-priority-queue.c \ src/buffer_input_stream.c src/buffer_output_stream.c \ src/buffered-file.c src/bytearray_input_stream.c \ src/bytearray_output_stream.c src/bytezarray_output_stream.c \ src/checked_output_stream.c src/chroot.c src/circular-file.c \ src/clone_input_output_stream.c src/cmdline.c \ src/concat_input_stream.c src/config-cmdline.c \ src/config_file_reader.c src/config_key.c src/config_logger.c \ src/config_settings.c src/config_struct.c \ src/counter_output_stream.c src/debug.c src/debug_bench.c \ src/debug_bfd.c src/debug_malloc.c src/debug_mmap.c \ src/debug_stacktrace.c src/digest_rawdata.c src/digest_sha1.c \ src/digest_sha256.c src/digest_sha384.c src/digest_sha512.c \ src/dns-udp.c src/dns_resource_record.c src/dnscore.c \ src/dnsformat.c src/dnskey.c src/dnskey-keyring.c \ src/dnskey_dsa.c src/dnskey_ecdsa.c src/dnskey_eddsa.c \ src/dnskey_rsa.c src/dnskey-signature.c src/dnsname.c \ src/empty-input-stream.c src/error_state.c src/fdtools.c \ src/file_input_stream.c src/file_output_stream.c \ src/file-pool.c src/filesystem-file.c src/format.c src/hash.c \ src/hash-table-values.c src/hmac-openssl.c src/host_address.c \ src/hsdllist.c src/identity.c src/input_stream.c src/json.c \ src/limited_input_stream.c src/limiter.c src/list-dl.c \ src/list-sl.c src/list-sl-debug.c src/logger-output-stream.c \ src/logger.c src/logger_channel_file.c \ src/logger_channel_pipe.c src/logger_channel_stream.c \ src/logger_channel_syslog.c src/logger_handle.c \ src/message-buffer.c src/message-viewer.c src/message.c \ src/message_print_format_dig.c src/message_verify_rrsig.c \ src/message_dnsupdate.c src/mapped-file.c \ src/mt_output_stream.c src/mutex.c src/network.c \ src/nsec3-hash.c src/output_stream.c src/pace.c \ src/packet_reader.c src/packet_writer.c src/parser.c \ src/parsing.c src/process.c src/pid.c src/pipe_stream.c \ src/pool.c src/popen-output-stream.c src/ptr_set.c \ src/ptr_set_debug.c src/ptr_vector.c src/queue-sl.c \ src/random.c src/rc.c src/rewind-input-stream.c src/rfc.c \ src/serial.c src/server-setup.c src/service.c \ src/shared-heap.c src/shared-circular-buffer.c \ src/shared-heap-bytearray-output-stream.c src/signals.c \ src/simple-http-server.c src/socket-server.c src/string_set.c \ src/sys_error.c src/sys_get_cpu_count.c src/tcp_io_stream.c \ src/thread.c src/thread_pool.c src/thread-tag.c \ src/threaded-qsl-cw.c src/threaded_dll_cw.c \ src/threaded_nb_mm.c src/threaded_nbrb.c \ src/threaded_queue_slg.c src/threaded_ringbuffer.c \ src/threaded_ringbuffer_cw.c src/threaded_ringlist.c \ src/timeformat.c src/timems.c src/typebitmap.c src/u32_set.c \ src/u64_set.c src/u64_set_debug.c src/xfr_input_stream.c \ src/zalloc.c src/zone_reader_axfr.c src/zone_reader_text.c \ $(am__append_47) src/tsig.c src/tsig_algorithms.c \ $(am__append_49) # src/ipc.c # src/name.c BUILT_SOURCES = $(FEATURES) CLEANFILES = buildinfo.h $(FEATURESSRC) VP = DNSCORE all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../mk/common-settings.mk $(srcdir)/../../mk/common-labels.mk $(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) --gnu lib/dnscore/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/dnscore/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(srcdir)/../../mk/common-settings.mk $(srcdir)/../../mk/common-labels.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_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}; \ } src/$(am__dirstamp): @$(MKDIR_P) src @: > src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/$(DEPDIR) @: > src/$(DEPDIR)/$(am__dirstamp) src/alarm.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/acl.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/acl-config.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/allocator.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/async.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/base16.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/base32.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/base32hex.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/base64.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/basic-priority-queue.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/buffer_input_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/buffer_output_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/buffered-file.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/bytearray_input_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/bytearray_output_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/bytezarray_output_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/checked_output_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/chroot.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/circular-file.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/clone_input_output_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/cmdline.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/concat_input_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/config-cmdline.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/config_file_reader.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/config_key.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/config_logger.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/config_settings.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/config_struct.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/counter_output_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/debug.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/debug_bench.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/debug_bfd.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/debug_malloc.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/debug_mmap.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/debug_stacktrace.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/digest_rawdata.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/digest_sha1.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/digest_sha256.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/digest_sha384.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/digest_sha512.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dns-udp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dns_resource_record.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dnscore.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dnsformat.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dnskey.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dnskey-keyring.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dnskey_dsa.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dnskey_ecdsa.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dnskey_eddsa.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dnskey_rsa.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dnskey-signature.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dnsname.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/empty-input-stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/error_state.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/fdtools.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/file_input_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/file_output_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/file-pool.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/filesystem-file.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/format.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/hash.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/hash-table-values.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/hmac-openssl.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/host_address.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/hsdllist.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/identity.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/input_stream.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/json.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/limited_input_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/limiter.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/list-dl.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/list-sl.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/list-sl-debug.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/logger-output-stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/logger.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/logger_channel_file.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/logger_channel_pipe.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/logger_channel_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/logger_channel_syslog.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/logger_handle.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/message-buffer.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/message-viewer.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/message.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/message_print_format_dig.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/message_verify_rrsig.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/message_dnsupdate.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/mapped-file.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/mt_output_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/mutex.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/network.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/nsec3-hash.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/output_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/pace.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/packet_reader.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/packet_writer.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/parser.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/parsing.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/process.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/pid.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/pipe_stream.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/pool.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/popen-output-stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/ptr_set.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/ptr_set_debug.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/ptr_vector.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/queue-sl.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/random.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/rc.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/rewind-input-stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/rfc.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/serial.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/server-setup.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/service.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/shared-heap.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/shared-circular-buffer.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/shared-heap-bytearray-output-stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/signals.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/simple-http-server.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/socket-server.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/string_set.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/sys_error.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/sys_get_cpu_count.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/tcp_io_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/thread.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/thread_pool.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/thread-tag.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/threaded-qsl-cw.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/threaded_dll_cw.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/threaded_nb_mm.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/threaded_nbrb.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/threaded_queue_slg.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/threaded_ringbuffer.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/threaded_ringbuffer_cw.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/threaded_ringlist.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/timeformat.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/timems.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/typebitmap.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/u32_set.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/u64_set.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/u64_set_debug.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/xfr_input_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zalloc.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zone_reader_axfr.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zone_reader_text.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/osx_clock_gettime.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/tsig.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/tsig_algorithms.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/nsid.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) libdnscore.la: $(libdnscore_la_OBJECTS) $(libdnscore_la_DEPENDENCIES) $(EXTRA_libdnscore_la_DEPENDENCIES) $(AM_V_CCLD)$(libdnscore_la_LINK) -rpath $(libdir) $(libdnscore_la_OBJECTS) $(libdnscore_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f src/*.$(OBJEXT) -rm -f src/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/acl-config.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/acl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/alarm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/allocator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/async.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/base16.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/base32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/base32hex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/base64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/basic-priority-queue.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/buffer_input_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/buffer_output_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/buffered-file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bytearray_input_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bytearray_output_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bytezarray_output_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/checked_output_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/chroot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/circular-file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/clone_input_output_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/cmdline.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/concat_input_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/config-cmdline.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/config_file_reader.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/config_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/config_logger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/config_settings.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/config_struct.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/counter_output_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug_bench.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug_bfd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug_malloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug_mmap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug_stacktrace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/digest_rawdata.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/digest_sha1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/digest_sha256.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/digest_sha384.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/digest_sha512.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dns-udp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dns_resource_record.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnscore.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnsformat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnskey-keyring.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnskey-signature.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnskey.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnskey_dsa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnskey_ecdsa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnskey_eddsa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnskey_rsa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnsname.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/empty-input-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/error_state.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/fdtools.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/file-pool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/file_input_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/file_output_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/filesystem-file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/format.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/hash-table-values.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/hmac-openssl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/host_address.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/hsdllist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/identity.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/input_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/json.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/limited_input_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/limiter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/list-dl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/list-sl-debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/list-sl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/logger-output-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/logger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/logger_channel_file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/logger_channel_pipe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/logger_channel_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/logger_channel_syslog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/logger_handle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/mapped-file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/message-buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/message-viewer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/message.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/message_dnsupdate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/message_print_format_dig.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/message_verify_rrsig.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/mt_output_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/mutex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/network.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3-hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/osx_clock_gettime.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/output_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/packet_reader.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/packet_writer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/parser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/parsing.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pipe_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/popen-output-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/process.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ptr_set.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ptr_set_debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ptr_vector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/queue-sl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/random.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/rc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/rewind-input-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/rfc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/serial.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/server-setup.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/service.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/shared-circular-buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/shared-heap-bytearray-output-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/shared-heap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/signals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/simple-http-server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/socket-server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/string_set.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sys_error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sys_get_cpu_count.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tcp_io_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/thread-tag.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/thread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/thread_pool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/threaded-qsl-cw.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/threaded_dll_cw.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/threaded_nb_mm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/threaded_nbrb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/threaded_queue_slg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/threaded_ringbuffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/threaded_ringbuffer_cw.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/threaded_ringlist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/timeformat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/timems.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tsig.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/tsig_algorithms.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/typebitmap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/u32_set.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/u64_set.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/u64_set_debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/xfr_input_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zalloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zone_reader_axfr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zone_reader_text.Plo@am__quote@ .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 -rm -rf src/.libs src/_libs install-pkgincludeHEADERS: $(pkginclude_HEADERS) @$(NORMAL_INSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ done uninstall-pkgincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) 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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) 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: -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) -rm -f src/$(DEPDIR)/$(am__dirstamp) -rm -f src/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf src/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-pkgincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES 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 -rf src/$(DEPDIR) -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: uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-data-local install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am \ install-pkgincludeHEADERS 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 uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS ### YRCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -g -DCMR ### YPCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -pg -DCMP ### YDCFLAGS = -DDEBUG $(DEBUGFLAGS) -DCMD ### YSCFLAGS = $(YRCFLAGS) ### ### YRLDFLAGS = -g ### YPLDFLAGS = -pg ### YDLDFLAGS = -g ### ### if HAS_CC_RDYNAMIC ### YPLDFLAGS += -rdynamic ### YDLDFLAGS += -rdynamic ### endif ### ### if USES_CLANG ### # workaround a bug where clang does not handle properly profiling and optimizations ### YPCFLAGS += -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer ### endif ### ### YSLDFLAGS = $(YRLDFLAGS) ### ### AM_CFLAGS += $(YCFLAGS) ### AM_LDFLAGS += $(YLDFLAGS) ### ### AM_MAKEFLAGS=MODE_CFLAGS="$(AM_CFLAGS)" CC=$(CC) AR=$(AM_AR) LD=$(AM_LD) buildinfo.h: $(abs_top_builddir)/config.log echo \#pragma once > buildinfo.h 2> /dev/null echo // generated file, do not modify >> buildinfo.h 2> /dev/null echo \#define BUILD_OPTIONS \"$$(grep "/configure" $(abs_top_builddir)/config.log | head -1 | sed 's/.*\.\/configure *//')\" >> buildinfo.h 2> /dev/null all: REVISION $(FEATURESSRC) REVISION: (svn info 2>/dev/null;if [ $$? -ne 0 ];then echo "Revision: 0";fi)|grep Revision:|sed 's/^Revision: *//' > REVISION $(srcdir)/src/alarm.c: $(FEATURES) $(FEATURESSRC) $(FEATURESSRC): ../../config.h mkdir -p $(top_builddir)/$(FEATURESDIR) cp ../../config.h $(FEATURESSRC) features: $(FEATURES) $(FEATURES): ../../config.log REVISION VERSION $(FEATURESSRC) mkdir -p $(I) echo "#pragma once" > $(FEATURES) grep "^#define" $(FEATURESSRC) | sed -e 's/^#define /#define $(VP)_/' >> $(FEATURES) echo '#undef $(VP)_VERSION' >> $(FEATURES) which printf > /dev/null 2>&1 if [ $$? -eq 0 ];then \ printf '// version %i.%i.%i.%i-%i\n' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ printf '#define $(VP)_VERSION 0x%02x%02x%02x%02x%04xLL' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ else \ echo "#define $(VP)_VERSION_(vmain_,vsub_,vminor_,vpatch_,vrevision_) ((vmain_)<<40)|((vsub_)<<32)|((vminor_)<<24)|((vpatch_)<<16)|(vrevision_)" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMAIN_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VSUB_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\2')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMINOR_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\3')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VPATCH_ 0 >> $(FEATURES)" ; \ echo "#define $(VP)_VERSION_VREVISION_ $$(cat REVISION)" >> $(FEATURES) ; \ echo '#define $(VP)_VERSION $(VP)_VERSION_($(VP)_VERSION_VMAIN_,$(VP)_VERSION_VSUB_,$(VP)_VERSION_VMINOR_,$(VP)_VERSION_VPATCH_,$(VP)_VERSION_VREVISION_)' >> $(FEATURES) ; \ fi echo "// $(FEATURES)" >> $(FEATURES) echo >> $(FEATURES) install-data-local: $(FEATURES) mkdir -p $(DESTDIR)$(prefix)/include/dnscore /usr/bin/install -c -m 644 $(FEATURES) $(DESTDIR)$(prefix)/$(FEATURES) # 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: yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/Makefile.am0000644000000000000000000000013214505005532020575 xustar000000000000000030 mtime=1695812442.517983262 30 atime=1695812445.791030139 30 ctime=1695812494.121722332 yadifa-2.6.5-11201/lib/dnscore/Makefile.am0000664000374500037450000002730414505005532020545 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ACLOCAL_AMFLAGS = -I m4 include ../../mk/common-settings.mk AM_CFLAGS += -DDNSCORE_BUILD=1 AM_CFLAGS += -I$(top_srcdir)/lib/dnscore/include -I$(top_builddir)/lib/dnscore/include #AM_CFLAGS += -I$(top_srcdir)/lib/dnsdb/include -I$(top_builddir)/lib/dnsdb/include #AM_CFLAGS += -I$(top_srcdir)/lib/dnslg/include -I$(top_builddir)/lib/dnslg/include #AM_CFLAGS += -I$(top_srcdir)/lib/dnstcl/include -I$(top_builddir)/lib/dnstcl/include dist_noinst_DATA = VERSION include/dnscore/thirdparty/stdatomic.h src/tcp_manager.c lib_LTLIBRARIES= libdnscore.la libdnscore_la_LDFLAGS = -version-info 7:5:0 #libdnscore_la_LIBADD=$(top_buildir)/lib/.../libsomething.la I=include/dnscore FEATURESFILE=dnscore-config-features.h FEATURES=$(I)/$(FEATURESFILE) FEATURESDIR=lib/dnscore/include/dnscore FEATURESSRC=$(top_builddir)/$(FEATURESDIR)/dnscore-config.h # libdnscore_ladir=. # alphabetically please pkgincludedir = $(includedir)/dnscore pkginclude_HEADERS = \ $(I)/alarm.h \ $(I)/acl.h \ $(I)/acl-config.h \ $(I)/allocator.h \ $(I)/async.h \ $(I)/avl.c.inc \ $(I)/avl.h.inc \ $(I)/base16.h \ $(I)/base32.h \ $(I)/base32hex.h \ $(I)/base64.h \ $(I)/basic-priority-queue.h \ $(I)/buffer_input_stream.h \ $(I)/buffer_output_stream.h \ $(I)/buffered-file.h \ $(I)/bytearray_input_stream.h \ $(I)/bytearray_output_stream.h \ $(I)/bytezarray_output_stream.h \ $(I)/checked_output_stream.h \ $(I)/chroot.h \ $(I)/circular-file.h \ $(I)/clone_input_output_stream.h \ $(I)/cmdline.h \ $(I)/concat_input_stream.h \ $(I)/config-cmdline.h \ $(I)/config_file_reader.h \ $(I)/config_settings.h \ $(I)/counter_output_stream.h \ $(I)/ctrl-rfc.h \ $(I)/debug.h \ $(I)/debug_config.h \ $(I)/digest.h \ $(I)/dns-udp.h \ $(I)/dns_resource_record.h \ $(I)/dnscore.h \ $(I)/dnscore-release-date.h \ $(I)/dnsformat.h \ $(I)/dnskey.h \ $(I)/dnskey-keyring.h \ $(I)/dnskey_dsa.h \ $(I)/dnskey_ecdsa.h \ $(I)/dnskey_eddsa.h \ $(I)/dnskey_rsa.h \ $(I)/dnskey-signature.h \ $(I)/dnsname.h \ $(I)/dnsname_set.h \ $(I)/dnssec_errors.h \ $(I)/empty-input-stream.h \ $(I)/error_state.h \ $(I)/fdtools.h \ $(I)/file.h \ $(I)/file_input_stream.h \ $(I)/file_output_stream.h \ $(I)/file-pool.h \ $(I)/filesystem-file.h \ $(I)/fingerprint.h \ $(I)/format.h \ $(I)/hash.h \ $(I)/hmac.h \ $(I)/host_address.h \ $(I)/hsdllist.h \ $(I)/identity.h \ $(I)/input_stream.h \ $(I)/io_stream.h \ $(I)/json.h \ $(I)/limited_input_stream.h \ $(I)/limiter.h \ $(I)/list-dl.h \ $(I)/list-sl.h \ $(I)/list-sl-debug.h \ $(I)/logger.h \ $(I)/logger_channel_file.h \ $(I)/logger_channel_pipe.h \ $(I)/logger_channel_stream.h \ $(I)/logger_channel_syslog.h \ $(I)/logger_handle.h \ $(I)/logger-output-stream.h \ $(I)/mapped-file.h \ $(I)/message-buffer.h \ $(I)/message-viewer.h \ $(I)/message.h \ $(I)/message_verify_rrsig.h \ $(I)/message_dnsupdate.h \ $(I)/mt_output_stream.h \ $(I)/mutex.h \ $(I)/network.h \ $(I)/nsec3-hash.h \ $(I)/openssl.h \ $(I)/output_stream.h \ $(I)/pace.h \ $(I)/packet_reader.h \ $(I)/packet_writer.h \ $(I)/parser.h \ $(I)/parsing.h \ $(I)/pid.h \ $(I)/pipe_stream.h \ $(I)/pool.h \ $(I)/popen-output-stream.h \ $(I)/print_stream.h \ $(I)/process.h \ $(I)/ptr_set.h \ $(I)/ptr_set_debug.h \ $(I)/ptr_vector.h \ $(I)/queue-sl.h \ $(I)/random.h \ $(I)/rc.h \ $(I)/rewind-input-stream.h \ $(I)/rfc.h \ $(I)/serial.h \ $(I)/server-setup.h \ $(I)/service.h \ $(I)/shared-heap.h \ $(I)/shared-circular-buffer.h \ $(I)/shared-heap-bytearray-output-stream.h \ $(I)/signals.h \ $(I)/simple-http-server.h \ $(I)/socket-server.h \ $(I)/string_set.h \ $(I)/sys_error.h \ $(I)/sys_get_cpu_count.h \ $(I)/sys_types.h \ $(I)/tcp_io_stream.h \ $(I)/tcp_manager.h \ $(I)/thread.h \ $(I)/thread_pool.h \ $(I)/thread-tag.h \ $(I)/threaded-qsl-cw.h \ $(I)/threaded_dll_cw.h \ $(I)/threaded_nb_mm.h \ $(I)/threaded_nbrb.h \ $(I)/threaded_queue.h \ $(I)/threaded_queue_slg.h \ $(I)/threaded_ringbuffer.h \ $(I)/threaded_ringbuffer_cw.h \ $(I)/threaded_ringlist.h \ $(I)/timeformat.h \ $(I)/timems.h \ $(I)/typebitmap.h \ $(I)/u32_set.h \ $(I)/u64_set.h \ $(I)/u64_set_debug.h \ $(I)/xfr_input_stream.h \ $(I)/zalloc.h \ $(I)/zone_reader.h \ $(I)/zone_reader_axfr.h \ $(I)/zone_reader_text.h \ $(I)/zonefile_reader.h libdnscore_la_SOURCES = \ src/alarm.c \ src/acl.c \ src/acl-config.c \ src/allocator.c \ src/async.c \ src/base16.c \ src/base32.c \ src/base32hex.c \ src/base64.c \ src/basic-priority-queue.c \ src/buffer_input_stream.c \ src/buffer_output_stream.c \ src/buffered-file.c \ src/bytearray_input_stream.c \ src/bytearray_output_stream.c \ src/bytezarray_output_stream.c \ src/checked_output_stream.c \ src/chroot.c \ src/circular-file.c \ src/clone_input_output_stream.c \ src/cmdline.c \ src/concat_input_stream.c \ src/config-cmdline.c \ src/config_file_reader.c \ src/config_key.c \ src/config_logger.c \ src/config_settings.c \ src/config_struct.c \ src/counter_output_stream.c \ src/debug.c \ src/debug_bench.c \ src/debug_bfd.c \ src/debug_malloc.c \ src/debug_mmap.c \ src/debug_stacktrace.c \ src/digest_rawdata.c \ src/digest_sha1.c \ src/digest_sha256.c \ src/digest_sha384.c \ src/digest_sha512.c \ src/dns-udp.c \ src/dns_resource_record.c \ src/dnscore.c \ src/dnsformat.c \ src/dnskey.c \ src/dnskey-keyring.c \ src/dnskey_dsa.c \ src/dnskey_ecdsa.c \ src/dnskey_eddsa.c \ src/dnskey_rsa.c \ src/dnskey-signature.c \ src/dnsname.c \ src/empty-input-stream.c \ src/error_state.c \ src/fdtools.c \ src/file_input_stream.c \ src/file_output_stream.c \ src/file-pool.c \ src/filesystem-file.c \ src/format.c \ src/hash.c \ src/hash-table-values.c \ src/hmac-openssl.c \ src/host_address.c \ src/hsdllist.c \ src/identity.c \ src/input_stream.c \ src/json.c \ src/limited_input_stream.c \ src/limiter.c \ src/list-dl.c \ src/list-sl.c \ src/list-sl-debug.c \ src/logger-output-stream.c \ src/logger.c \ src/logger_channel_file.c \ src/logger_channel_pipe.c \ src/logger_channel_stream.c \ src/logger_channel_syslog.c \ src/logger_handle.c \ src/message-buffer.c \ src/message-viewer.c \ src/message.c \ src/message_print_format_dig.c \ src/message_verify_rrsig.c \ src/message_dnsupdate.c \ src/mapped-file.c \ src/mt_output_stream.c \ src/mutex.c \ src/network.c \ src/nsec3-hash.c \ src/output_stream.c \ src/pace.c \ src/packet_reader.c \ src/packet_writer.c \ src/parser.c \ src/parsing.c \ src/process.c \ src/pid.c \ src/pipe_stream.c \ src/pool.c \ src/popen-output-stream.c \ src/ptr_set.c \ src/ptr_set_debug.c \ src/ptr_vector.c \ src/queue-sl.c \ src/random.c \ src/rc.c \ src/rewind-input-stream.c \ src/rfc.c \ src/serial.c \ src/server-setup.c \ src/service.c \ src/shared-heap.c \ src/shared-circular-buffer.c \ src/shared-heap-bytearray-output-stream.c \ src/signals.c \ src/simple-http-server.c \ src/socket-server.c \ src/string_set.c \ src/sys_error.c \ src/sys_get_cpu_count.c \ src/tcp_io_stream.c \ src/thread.c \ src/thread_pool.c \ src/thread-tag.c \ src/threaded-qsl-cw.c \ src/threaded_dll_cw.c \ src/threaded_nb_mm.c \ src/threaded_nbrb.c \ src/threaded_queue_slg.c \ src/threaded_ringbuffer.c \ src/threaded_ringbuffer_cw.c \ src/threaded_ringlist.c \ src/timeformat.c \ src/timems.c \ src/typebitmap.c \ src/u32_set.c \ src/u64_set.c \ src/u64_set_debug.c \ src/xfr_input_stream.c \ src/zalloc.c \ src/zone_reader_axfr.c \ src/zone_reader_text.c # src/ipc.c # src/name.c BUILT_SOURCES = $(FEATURES) # $(I)/ipc.h # $(I)/name.h if IS_DARWIN_OS pkginclude_HEADERS += $(I)/osx_clock_gettime.h libdnscore_la_SOURCES += src/osx_clock_gettime.c endif pkginclude_HEADERS += $(I)/tsig.h libdnscore_la_SOURCES += src/tsig.c src/tsig_algorithms.c if HAS_NSID_SUPPORT pkginclude_HEADERS += $(I)/nsid.h libdnscore_la_SOURCES += src/nsid.c endif include ../../mk/common-labels.mk all: REVISION $(FEATURESSRC) REVISION: (svn info 2>/dev/null;if [ $$? -ne 0 ];then echo "Revision: 0";fi)|grep Revision:|sed 's/^Revision: *//' > REVISION $(srcdir)/src/alarm.c: $(FEATURES) $(FEATURESSRC) $(FEATURESSRC): ../../config.h mkdir -p $(top_builddir)/$(FEATURESDIR) cp ../../config.h $(FEATURESSRC) CLEANFILES += $(FEATURESSRC) features: $(FEATURES) $(FEATURES): ../../config.log REVISION VERSION $(FEATURESSRC) VP=DNSCORE mkdir -p $(I) echo "#pragma once" > $(FEATURES) grep "^#define" $(FEATURESSRC) | sed -e 's/^#define /#define $(VP)_/' >> $(FEATURES) echo '#undef $(VP)_VERSION' >> $(FEATURES) which printf > /dev/null 2>&1 if [ $$? -eq 0 ];then \ printf '// version %i.%i.%i.%i-%i\n' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ printf '#define $(VP)_VERSION 0x%02x%02x%02x%02x%04xLL' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ else \ echo "#define $(VP)_VERSION_(vmain_,vsub_,vminor_,vpatch_,vrevision_) ((vmain_)<<40)|((vsub_)<<32)|((vminor_)<<24)|((vpatch_)<<16)|(vrevision_)" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMAIN_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VSUB_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\2')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMINOR_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\3')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VPATCH_ 0 >> $(FEATURES)" ; \ echo "#define $(VP)_VERSION_VREVISION_ $$(cat REVISION)" >> $(FEATURES) ; \ echo '#define $(VP)_VERSION $(VP)_VERSION_($(VP)_VERSION_VMAIN_,$(VP)_VERSION_VSUB_,$(VP)_VERSION_VMINOR_,$(VP)_VERSION_VPATCH_,$(VP)_VERSION_VREVISION_)' >> $(FEATURES) ; \ fi echo "// $(FEATURES)" >> $(FEATURES) echo >> $(FEATURES) install-data-local: $(FEATURES) mkdir -p $(DESTDIR)$(prefix)/include/dnscore /usr/bin/install -c -m 644 $(FEATURES) $(DESTDIR)$(prefix)/$(FEATURES) yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/VERSION0000644000000000000000000000013214505005532017611 xustar000000000000000030 mtime=1695812442.362981043 30 atime=1695812445.797030225 30 ctime=1695812494.126722403 yadifa-2.6.5-11201/lib/dnscore/VERSION0000664000374500037450000000000614505005532017547 0ustar00signersigner000000000000002.6.5 yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/AUTHORS0000644000000000000000000000013214505005532017611 xustar000000000000000030 mtime=1695812442.361981028 30 atime=1695812445.786030067 30 ctime=1695812494.441726915 yadifa-2.6.5-11201/lib/dnscore/AUTHORS0000664000374500037450000000013514505005532017552 0ustar00signersigner00000000000000Gery Van Emelen Eric Diaz Fernandez yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/COPYING0000644000000000000000000000013214505005532017574 xustar000000000000000030 mtime=1695812442.516983248 30 atime=1695812445.786030067 30 ctime=1695812494.443726943 yadifa-2.6.5-11201/lib/dnscore/COPYING0000664000374500037450000000312414505005532017536 0ustar00signersigner00000000000000 Copyright (c) 2011-2023, EURid vzw. All rights reserved. The YADIFA TM software product is provided under the BSD 3-clause license: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of EURid nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/ChangeLog0000644000000000000000000000013214505005532020313 xustar000000000000000030 mtime=1695812442.364981071 30 atime=1695812445.786030067 30 ctime=1695812494.445726972 yadifa-2.6.5-11201/lib/dnscore/ChangeLog0000664000374500037450000017673414505005532020277 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ 20230906: YADIFA 2.6.5-public Secondaries will nolonger enforce the TTL value of the NSEC3PARAM record. Fixes an issue caused by a limitation of the select system call. 20230301: YADIFA 2.6.4-public Fixes an issue building for 32 bits targets. 20230213: YADIFA 2.6.3-public Fixes an issue where the answer to a DNSSEC query to a wild record right below the apex in a DNSSEC3 zone would not return all the relevant NSEC3 records Fixes an issue where the answer to a DNSSEC query to a wild record in an NSEC zone would incorrectly use the name of the query in the answer Fixes an issue where NSEC3-owning labels were not compressed Complies with Fedora https://fedoraproject.org/wiki/Changes/PortingToModernC (see m4/contributions/20230118-fedora-toolchain-porting-to-modern-c.patch) 20221209: YADIFA 2.6.2-public Fixes an issue trying to link the backtrace call while building yadifad on FreeBSD 20221130: YADIFA 2.6.1-public Fixes an issue where the answer of an TSIG-signed IXFR query over an undefined domain would not be properly signed. Fixes an issue building for big-endian architectures. 20221004: YADIFA 2.6.0-public The server can optionally load the locally stored zone before asking for the last version to its primary (load-local-first) The server now avoids storing temporary zone transfer images to disk if the zone is small enough (axfr-memory-threshold) zone transfers source address can now be specified in the configuration (transfer-source) The server now allows to sign a zone using only zone signing keys. Fixes online chain generation started from an zone that is not covered by DNSSEC. Fixes an issue where a generated DNSKEY could be missing smart fields if the storage became full right before they needed to be written. Fixes an issue that could occur using EDDSA on big-enough data sets. 20220228: YADIFA 2.5.4-public Fixes an issue handling CNAME records. 20211025: YADIFA 2.5.3-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet with privileged access. 20210929: YADIFA 2.5.2-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet with privileged access. Fixes an issue where a corrupted configuration file could lead to a crash while starting-up. 20210924: YADIFA 2.5.1-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet. Fixes an issue where yadifad would sometimes reply with an AXFR instead of an IXFR if the journal is under maintenance. Increased the pid column in the logger to 6 characters Drastically increased the limit for TCP queries. Note that using a high enough number compared to the available memory will cause yadifad to warn about limits and OOM kill risks. In practice a few hundred TCP queries should be enough. 20210602: YADIFA 2.5.0-public Adds a new, friendlier, TCP manager. When enabled, TCP connections aren't closed harshly after some time has elapased without any activity. In a nutshell: It is enabled using --enable-tcp-manager. It works using a quota of allowed parallel connections per host. There is one value for the registeres hosts and one for unknown hosts. All defined primaries are automatically added to the TCP manager as registered hosts. The server's local addresses are automatically added to the registered hosts. The default timeout is set to 3 seconds but doesn't imply a connection will be closed : only that it is a candidate for being closed. EDDSA support has been enable. Sending a TCP message now uses a single system call (message_send_tcp) Fixes an issue in some FreeBSD setups where UDP messages couldn't be sent by YADIFA. Fixes an issue in FreeBSD where TCP connections would sometimes be closed too quickly. Fixes an issue where failed dynamic updates prerequisites would return SERVFAIL instead of the more accurate error code. Fixes atomic usage for older C compilers. Fixes an issue where some RRSIG records may not be updated in time if they happened to have their update bundled with NSEC3 records updates while the incremental change could not be immediately written in the journal. Fixes the yadifa keygen module to understand "help" as a command and not as a domain. 20210223: YADIFA 2.4.2-public Fixes an issue where records below delegation are not ignored (https://github.com/yadifa/yadifa/issues/12). Fixes an issue in the _mm model where shutting down while still initializing may not stop properly. Changes default user/group to 'yadifa' user in example configuration. Fixes an issue with autoconf 2.70 obsolete functions. Fixes an issue where an unknown key configured in a zone acl may lead to a crash. Fixes an issue where an query without EDNS involving ACLs using optional keys would incorrectly be rejected. Fixes an issue where a network thread with a failed context would incorrectly have its context deleted. Adds a feature to yadifad to ensure that the dates in the key-roll section can be successfully applied for the next 10 years (--check-policies). Added support for primary and secondary variant options. Fixes builds for gcc 11. 20201209: YADIFA 2.4.1-public Fixes an issue in dnscore where a DNS TCP query would not return the real DNS error code. Fixes an issue that could happen when a network model isn't supported. Fixes the propagation of sendmmsg/recvmmsg function availability detection. Fixes an issue where yadifad would issue a warning when a key with algorithm > 7 is used with an NSEC zone. Fixes an issue that will occur on a chrooted environment where a managed-path would be used incorrectly. Fixes CNAME answers not following the aliases chain. Fixes CNAME recursion not returning the same answer as named in NXDOMAIN cases (reported by https://github.com/SivaKesava1, see https://github.com/yadifa/yadifa/issues/11) Adds patch for musl support (from https://github.com/kolbma, see https://github.com/yadifa/yadifa/issues/9#issuecomment-723047226) Adds stack size fix for musl support (the default size is way too small) Now imports a custom version of stdatomic.h for systems where it is missing, located in dnscore/thirdpary/stdatomic.h Made for CentOS 7 and any other release where that file is missing. The import is only active if strictly needed and will only be visible during the build. At the moment, it is not being installed with the other headers. The original source of the file was taken from https://gist.github.com/nhatminhle/5181506 YAKEYROLLD 2.4.1 Fixes the handling of incomplete TCP queries. Fixes a possible race-condition when initialising the keyroll context error codes. The keyroll now has another automatic recovery layer where it completely restarts the handling of a domain, generating a one-step update to put the zone in the expected state. 20201012: YADIFA 2.4.0-public Fixes an issue that could happen with multiprocess logging. Fixes an issue parsing a *. domain. Improves support for LibreSSL. Added contributions directories with community-provided patches. Readied the source for the release. Many changes have been made since version 2.3.x. Please read the manual for more information. YAKEYROLLD 2.4.0 Since version 2.4.0, yadifad optionally allows dynamic update of RRSIG records. The external key managing tool using this feature is being released along with it. Please read the manual for more information. YADIFA CTRL 2.4.0 The updated version of the command line controller has been made more user-friendly. Please read the manual for more information. 20200722: YADIFA 2.4.0-67 Default listen is now "0.0.0.0,::0" Added "do-not-listen" feature to avoid conflicts with systemd-resolved, default is empty. Added --enable-systemd-resolved-avoidance in the configure script to change the default of "do-not-listen" to "127.0.0.53 port 53" Zone file reader now decodes \ddd tokens. Text zone parsing is now more lenient in what it accepts: unescaped @ and $ in a domain will be read as '@' and '$', with a warning. Improves the configuration update by keeping a timestamp of all files involved and checking they have been modified. Logger configuration can now be reconfigured during runtime. In the event of an incorrect reconfiguration of the network, yadifad will periodically try to reconfigure itself reading the configuration files. Fixes a potential issue in NSEC3 replying. Fixes TXT parsing issues. Fixes a leak with the chroot remapping when reconfiguring. Fixes a leak processing the command line. Fixes a leak in the policies configuration. 20200630: YADIFA 2.4.0-64 Network setup errors will now stop yadifad if they occur during the first configuration. If they occur during a reconfiguration the error will be logged every minute instead of every second. Fixes DSA API usage with OpenSSL 1.1.0 Fixes an other side effect of FreeBSD's process-shared mutexes where a thread waiting on a condition wouldn't always be woken up. Fixes IPv6 handling in FreeBSD. Fixes an issue where the logging could lock when daemonizing. Fixes the build-time-configuration paths when using cmake. Fixes an issue where a sync clean command would not delete the journal if the zone wasn't dynamically updated since the start of yadifad. Fixes an issue where the size of the buffer given for a message would be slightly bigger than needed. Duplicate but identical definition of a TSIG key are nolonger considered an error. Increased the log output handling control commands (mostly error conditions) yadifa ctrl: The fqdn isn't set by default anymore (it used to be '.' by default) Adds the "freeze", "thaw", "unfreeze", "freezeall", "unfreezeall" and "thawall" friendly keywords to yadfia ctrl. Adds the "notify" command. The FQDN has no default value anymore. Fixes the friendly parsing of the command line. Fixes several minor issues with the console output of the command line. 20200608: YADIFA 2.4.0-52 This is version is going to production as primary and for public release. Fixes limit case issues giving NSEC3 answers for some zone structures (mostly *, * + CNAME) Fixes an issue where the packet reader may not allocate enough room for SOA records (found in yakeyrolld) YKEYROLL-1.0.5-4 This is version is going to production as primary and for public release. Fixes the handling of more limit cases (broken setup). 20200515: YADIFA 2.4.0-51 In an effort to find issues using different tools, the code has been partially ported to compile in Visual Studio 2019. (Doesn't run) The code analyser from Visual Studio 2019 reported 290 potential issues, 5 of which were valid (understand: errors) and not reported by other analysers. We have used a mmap.c MIT-licensed code from github to help in this task. We'll have to decide to keep it or to write ours when we will do a Windows release. Adds a DNS pcap analyser tool to measure DNS traffic from a network pcap file. Used to find why so many packets were lost in the benchmark. (resut: The benchmark tool was broken.) Adds a --disable-filepool-cache build configure option. Logs clarity has been improved. Improved usability:
network-model option can now use words instead of just numbers, respectively: single, buffered, multi for 0, 1, 2. Fixes an issue that could occur in the logger service with some settings. Fixes an issue in the new network model. Fixes a memory leak that could occur in the cirular_file layer of the journal. Fixes a memory leak that could occur in the journal depending on the reason it was closed. Fixes a memory leak that could occur at shutdown while destroying a file pool. Fixes an issue where trying to print a corrupted fqdn (e.g.: random bytes) could have an undefined behaviour. Fixes an issue using the drop-before-load feature where the memory of the previous zone would not be completely freed yet before the new version of the zone started to load. Fixes a race condition that could occur while detaching stdout/stderr from console. Fixes missing AA flag in primary notification. Fixes a rare issue where a signal could block the logger. Fixes TSIG-covered answers of an unsupported opcode. YKEYROLL-1.0.5-3 Fixes the handling of several limit cases (all coming from a broken, corrupted state). 20200320: YADIFA 2.4.0-50 Efforts have been made to reduce the memory usage in the case where a lot of specific listening addresses are defined. A new network-model taking advantage of the multiple-send/receive of some kernels has been added. (recvmmsg, sendmmsg) Back-ported gcc-10 compatibility fix from the main development branch (trunk) This issue was reported by several distributions already using the yet-to-be-released gcc-10 (We are using gcc-9) Adds the tcp_manager for experimentation (an alternative way to keep track of opened TCP connections). Fixes a potential memory leak that could sometimes happen freeing NSEC3 records without removing their attached RRSIG first. Fixes FreeBSD 12.1/libressl build issue. YKEYROLL-1.0.5-2 Now handles SIGHUP to reopen the log files. Imrpoved the command line options help. 20200212: YADIFA 2.4.0-49 This version is going for production. Fixes an issue with signature expiration value where the time was sometimes incorrectly taken from the oldest key. The RRL tables are now growing faster in order to avoid wasting resources. YKEYROLL-1.0.4-2 This version is going for production. Now keeps the expected starting point and end point for all steps. This is used to verify the state before and after each update. Now has a "print" mode that logs the "plan" out (logs all the known steps). 20200128: YADIFA 2.4.0-48 New nameserver infrastructure update. In
, adds a log_files_disabled flag to disable checking the log-path directory for existence and writing rights. Without this, yadifad would refuse to work without a proper log output directory like we have on our SELinux setup. Fixes an issue that would occur if SELinux would reject a write operation with EPERM to a socket we have succesfully opened for writing. yadifad would not complain and end-up hammering both the socket creation and the logs Fixes an issue that would occur if SELinux would reject a read operation with EPERM on a socket we have successfully opened for reading. This happens, notably, the notify service, producing a lot of log lines. Now such an issue will make yadifad pause for one second. 20200106: YADIFA 2.4.0-45 Fixes an issue where having no ZSK would trigger a useless maintenance pass. Fixes an issue where notifies could stop being sent when their queue was full. (New dynamic queue used at minimal increased CPU cost for this part) Fixes an issue where reopening or syncing would have their effect delayed. Fixes an issue that could occur for DSA T parameter deduction from a public key. Made the command line more friendly using the new features from dnscore. YKEYROLL 1.0.3-0 Now filters-out publish and unpublish meta lines. Fixes an issue where retrying to send a message to an unresponsive server could have the message content reset. 20191120: YKEYROLL-1.0.2-3 This version is going for production. Adds switching to a uid/gid set in the configuration file (must be set to the same as yadifad). Adds process mutual-exclusion for plan generation. Improves shutdown speed. Reduces logging. 20191118: YADIFA 2.4.0-43 Fixes an issue where enabling key activation leniency would incorrectly enable deactivation leniency. Fixes an issue where redundant signatures would be kept longuer than needed. The journal name for the root zone will now be root_zone.cjf (only one dot) intead of ..cjf, as that name was troublesome. YKEYROLL-1.0.1-9 This version is going for production. Can now work in a loop without detaching from console. 20191106: YADIFA 2.4.0-42 This version is going for production. Issues found by CLion's code inspector fixed or marked as invalid. Downgrades several "error" into "notice". More generally, an effort has been made to reduce the log size. Setting a policy field with an incorrect value will now log an error instead of stopping yadifad. Slave zones don't run sanitization anymore, as the primary is "right". This avoids thight rules being counter-productive in production environments. Fixes an issue that would occur if an update happens at tahe same time as the removal of a DNSKEY when a maintenance has started. Fixes an issue where the authoritative bit coudl be flipped off in some operations. Fixes an issue where removing and adding the same record in a single update would incorrectly drop its signature. Fixes an issue where a secondary receiving an inccorrect IXFR stream (specifically: finishing on an incomplete page) would not reject the broken page. Fixes an issue where a primary would cut an IXFR page in half if a shutdown was triggered while the page was being read from the journal. Fixes an issue in the policy date computation that could lead to a time period without signature coverage. 20191010: YADIFA 2.4.0-41 Fixes typos. YKEYROLL-1.0.0 Improved error codes returned by the keyroll policies. Fixes an error that could occur parsing a corrupted step file. 20190927: YADIFA 2.4.0-40 Adds a tool to append an IXFR in text form (so, from a dig command) to a journal. This is an unfriendly pure dev tool meant to create some tests scenarii. The cjf-scan tool, used to print the content of a journal, can now print its content in a way similar to the dig command. Simply use the "-clean" command line option before the journal file name. Both the above tools mean that a journal can be dumped as text, edited then re-created as binary. Although not initially created for this purpose, it can be a powerful fix tool. Fixes the "11:04" issue. It was triggered by an optimisation not being handled on all exit paths of the maintenance function, potentially leading to a buffer overflow. Fixes an issue in the journal: If the first update written into a dynamically sized journal is bigger that the default size of the journal (64KB) then yadifad incorrectly tries to shift-out content to make room, which it obviously cannot do. 20190920: YADIFA 2.4.0-39 In
, adds axfr-strict-authority option. Defaulted to enabled unless yadifad was built-configured using --enable-non-aa-axfr-support. Improves TXT parsing (github/ JZerf). Fixes an potential crash on SIGHUP if the zone loader calee gives an incorrect answer (github/kolbma). Fixes an issue where a UDP query with invalid return address (port 0) would trigger an EINVAL leading yadifa to shutdown the thread. Fixes an issue with IPv6 aliased replies. Depending on the OS/release the value could be wrong. The fix tries several options. This has been tested on several Debian and RedHat variants and seems to work properly. 20190919: YADIFA 2.4.0-38 note: Serial bump due to issues during rpm packaging. Reduces the number of warnings triggered by type bitmap fixes. Now only prints one and leaves the rest available as debug. Contains code to track the "11:04" issue and verify the hypothesis of its cause. 20190913: YADIFA 2.4.0-26 Timestamp in dns-udp are now human-readable. Writing a zone as text now computes and updates the approximate wire size for the zone (AXFR/IXFR trigger accuracy) yadifad now replies to ENDS# bad format. Fixes an issue in dns-udp where the message size would not be reset on the received side. Fixes an issue in dns-udp where the rate-limiter would fire before a message would be checked for actual IO (aggregated queries). Fixes an issue in dns-udp where a very slow call-back would slow down the processing part of the receiver enough to trigger a timeout of the query. Fixes a warning that would be shown for keys being both NSEC and NSEC3. Fixes an issue where the '#' character was incorrectly set as a zone comment. Fixes an issue where a journal with an invalid character in a name would trigger an infinite error loop (until program shutdown). Fixes an issue where a DNSKEY dynamic update coming with an RRSIG push could fail under certain conditions. Fixes some typos. YKEYROLL-beta Improves error reporting. Allows different configuration files. Fixes corrupted plan handling. Updates the configuration example. Correction updates are now merged in a single step, then played. Added error-retries-cases in daemon mode. Added a --timeus-offset parameter (not publicly documented) to lie about the current time. Added a --dryrun parameter. Fixes an issue handling key duplicates. 20190627: YADIFA 2.4.0-25 Fixes an issue where a corrupted journal would prevent a secondary from working. Fixes an issue replaying NSEC3 chain changes as a secondary that could occur when a discrepancy was found. If a corrupted journal is found, yadifad now renames it adding ".bad" to its name. 20190613: YADIFA 2.4.0-24 Adds safeguards for the logger shutdown. FreeBSD 12.0 issue diagnostic: There was an elusive issue occurring only on FreeBSD 12.0 related to shared mutexes. After posting an the issue anonymously with a proof-of-concept code, it turns out it was bug in FreeBSD: An unlocked mutex is still being accessed by the thread library right after the effective unlock has occurred. yadifad destroys a structure containing mutexes right after it is unlocked for the last time. FreeBSD has issued a fix, but at the moment the fix appeared to have side effects. This may have been us not rebuilding "world" properly (First time we do this), or it may be that the patch wasn't complete at the time. The matter is closed as far as yadifad's source code is concerned so this is something to watch after the next FreeBSD update. Added the "freebsd12-test" proof-of-concept code in the test section of the code. Adds the IP_MTU_DISCOVER IP_PMTUDISC_OMIT patch: patch received 20190323 from daisuke.higashi@gmail.com /* * Linux 3.15 has IP_PMTUDISC_OMIT which makes sockets * ignore PMTU information and send packets with DF=0. * Fragmentation is allowed if and only if the packet * size exceeds the outgoing interface MTU or the packet * encounters smaller MTU link in network. * This mitigates DNS fragmentation attacks by preventing * forged PMTU information. * FreeBSD already has same semantics without setting * the option. */ Added sereral fixes for NetBSD builds. Ultimately, NetBSD declares but does not implement PSHARED. This makes that platform unusable for the moment. Logs have been improved (level & verbosity, some have been downgraded to debug). Improves command-line help. Internally, INVALID and UNPROCESSABLE messages are now seen as the same error. In
, added log_unprocessable boolean to add a warning log for bad DNS messages. If yadifad is not started as root but requires elevated privileges in order to bind an addess, it will stop. Fixes build on older sytems (FreeBSD). Fixes an incorrect warning message related to TSIG. Fixes an issue with garbage collection at shutdown. Fixes an issue that would occur if the signature max-interval was set high enough to end up in an integer overflow. Fixes an issue where newly added keys would not always be taken into account in the computations. Fixes an issue where the nttl cache could overflow. Fixes an issue in the path provider of yadifad where an empty secondary zone file setting could lead to a NULL pointer reference. Fixes an issue where the KSK public key would not be stored, losing the flags of the key as seen by libdnscore. Fixes an issue in dns-udp that would occur when TCP fails with a DNS error. Fixes an issue in dns-udp where the thread_pool destruction order could trigger some issues. Fixes an issue where a TCP read time-out from a client (thus when the server is sending) could lead to an indefinitely held connection. Fixes an issue that could happen in the RRL, leading to the current state pool being misused. Fixes an issue where an error code sent from the socket server would nto be interpreted correctly. Fixes an issue in the text parser that was being tripped in the yakeyrolld. Fixes an issue where asking the help from the command line would return to the shell with a non-zero value. YKEYROLL-alpha Code commited in alpha state to avoid potential issues related to a certain event. The new keyroll software is being written in C. It is based on the YADIFA framework. It's main features are: _ cron-like timings, _ KSK/ZSK separation, _ RRSIG push usage, _ one event per file and one file per event, _ integrity milestones, _ extension of the time-line on demand. 20190326: YADIFA 2.4.0-23 Added autogen.sh in the make dist. Improved yadifad startup so that simply asking for its version would not go through service start. Improved AXFR log messages: now showing the peer's IP address. 20190322: YADIFA 2.4.0-22 EDDSA is known but not handled. (EDDSA handling code is in the 2.5.x branch) Sanitization now checks for DNSKEY matching RRSIG records. Fixes an issue where yadifad would abort in a specific condition: A zone that allows RRSIG pushed by dynamic updates with a bunch of inactive ZSK keys available, one of them still in the zone with said inactive ZSK key in the zone having signature expiring after its deactivation date AND in the future with an active key in the zone that does not expire and is fully usable (key pair available) with a single KSK key in the zone that has no private part available ... ... was considered fubar and triggering an emergency stop (ending up in an abort()) Fixes an issue handling BigNum from OpenSSL being sometimes smaller than expected. Fixes a double-free issue (crashed yadifad the 20190311). Fixes an issue that would occur on a secondary when the journal is too small to work optimally. Added a "dsfromkey" in the test section, to be added in the command line later 20190218: YADIFA 2.4.0-21 Fixes an issue where killing yadifad while thread creation is in limbo would not work. yadifad will now ignore all signals until notify service thread is up and running (thus outside of limbo) Fixes an issue where policies would be tried on non-policed zones. 20190213: YADIFA 2.4.0-19 Improves CPU usage by inlining several small domain-related functions. Sanitization now occurs only once, after the journal has been replayed. Code marked as obsolete has been removed. Fixes an issue where an internal update message woudln't be properly initialised. Fixes an irrelevant warning when "publish" equals "active" or "inactive" equals "delete" in a DNSKEY key. Fixes embedded delegation issues. _ Sanitization complaining about wrong glue resource records in embedded delegations _ Sanitization complaining about unexpected signatures in embedded delegations _ Internal state is now correctly set. Fixes a policy issue where a DNSSEC chain would not be added if the DNSKEY was not already generated and added. Fixes an issue where removing an RRSIG covering a type could sometimes invalidate an RRSIG covering another in the same domain. Fixes an issue where a query that would return an RDATA with a '.' domain and require additionals, would trigger a memory underflow with undefined results. Fixes an issue that could occur when replaying NSEC3 updates from the journal. Fixes dnssec-policy NSEC chain generation that could not be completed because of an interference by the internal integrity tests. Fixes an issue with NSEC3 type bitmap handling that would occur on an empty broken zone without RRSIG records. Fixes an issue where reading corrupted messages would not be handled properly. Fixes an issue where the illegal addition of a DS resource record would not be handled properly. 20190205: YADIFA 2.4.0-18 Signature verification now has an abstract API (easier extension to future algorithms e.g.: EDDSA). Added our own zone test program. This includes signatures verification. It's in the test section and the feature should be moved inside the command line later. Fixes an issue where deleting a DNSKEY in a dynamic update would not be handled properly. Fixes an issue where removing an RRSIG in signature maintenance would not change the type bitmap in the associated NSEC3 record. Fixes an issue where maintenance would remove an RRSIG for a replacement (exchange) that could not be created (e.g.: private key missing). Fixes an issue managing a zone with an NSEC3PARAM record but no NSEC3 chain. Fixes an issue where NSEC3 chain recomputation could be called before RRSIG changes would be known. Fixes an issue where stopping yadifad while it started a signature thread (in a window of a few instructions) would trigger an assertion. Fixes an issue where dnssec-policies could conflict with RRSIG pushed with a dynamic update. Fixes an issue parsing records with a class ANY in update messages. 20190109: YADIFA 2.4.0-17 Added a test for the keyroll feature (test section). Key creation time is now systematically set in newly created keys. 20181122: YADIFA 2.4.0-11 Fixes handling of several limit cases in chain updates (that should never happen in a sane system). Fixes some minor memory leaks. This is the first release that is meant to prevent DNSKEY with incorrect "smart" setup making yadifad trying to take them at every occasion (e.g.: dynamic update). 20181122: YADIFA-2.4.0-10 Made to caters for the needs of an internal project. 20180802: YADIFA 2.4.0-1 Fixes all fixable -Wextra warnings (that ar not in -Wall for some reason) One of these warnings would have showed the suprise-issue with the ACL ... These fixes needs to be thoroughly tested before being used on anything production. 20180725: YADIFA 2.4.0 alpha Fixes an issue where a secondary having downloaded a invalid zone from an primary will proceed re-download it and failing until the zone is fixed on the primary. Now it will wait until the axfr-retry + random(axfr-retry-jitter) elapsed. It is now possible to change the network configuration at runtime. It is now possible to have threads logged with a tag instead of an opaque hexadecimal ID. (--enable-log-thread-tag) It is now possible to pipe execute loggers output. e.g.: my-zipped-channel "|/usr/bin/gzip - >> /var/log/yadifa.log.gz" Obviously, outputs are run using the uid/gid set for the server. As the command can be restarted for several reasons so using >> is the obvious choice. The maximum number of queries that are queued on an overloaded server is now configurable. Note this is currently only used by network-model 1 and the ram usage in bytes is about (workers * size * 64) For a server that only needs to answer 10000 queries per second, it would be suitable to use: e.g.: network-model-worker-backlog-size 10000 Our artificial benchmark tests are showing that setting this value to 500000 is enough to handle about 2.5 millions queries per second on a server with the appropriate hardware configured properly (network queues, ...). The zone journal maximum size is now an hard limit instead of "best effort within a few bytes". The --disable-messages ./configure option has now been removed as the send & recv are not suitable for proper aliased addresses handling. The build system has been changed: From now on, to do a debug build, add CFLAGS='-O0 -g3 -DEBUG=1' to the configure command. e.g.: ./configure --enable-shared --enable-log-thread-tag CC=clang CFLAGS='-O0 -g3 -DDEBUG=1' A release build that keeps the symbols would be: ./configure --enable-log-thread-tag CC=clang CFLAGS='-O3 -g -DDEBUG=0' The dnszone library has been merged into dnscore and dnsdb. Several of our unit tests have been added as well as the valgrind suppression file (yadifad.supp). Several simplifications and abstractions have been made on the internal APIs. Network model 1 is the only model available from this version. dnssec-thread-count parameter is now obsolete 20180213: YADIFA 2.3.8 Fixes the OPT record Z flags not being cleared in server answers. 20171207: YADIFA 2.3.0 - 2.3.7 From now on, both primary and secondaries are updating the zone in the same manner (journal transactions) Messages are now default (--enable-messages). Disable them using --disable-messages. Adds more (dynamic) update validation. Adds a build option to remove compile date and time from various help messages (--disable-build-timestamp) A primary can now be configured to allow updating RRSIG records externally (e.g.: update add domain. RRSIG ...) Fixes an issue where closing an (a)XFR stream could lead to a race over the file descriptors. Fixes an issue where an AXFR query would return a version of the zone too old to be upgradable by following incremntal updates. Fixes an issue where zones with big-enough NSEC3 coverage (several millions NSEC3 record) could potentially reach an internal limit of the database. Fixes an issue where shutting down YADIFA while a zone is being downloaded (AXFR) may make it wait forever. Fixes an issue where the secondary would complain about a missing private key. Fixes an issue where a specifically truncated IXFR query may make YADIFA replying with an AXFR. Fixes an issue where an IXFR query returning "not implemented" instead of an AXFR would be retried later as an IXFR. Fixes an issue where hammering reopening the logs on an overloaded server would not work properly. 20170912: YADIFA 2.2.6 Fixes an issue where a maliciously crafted message may block the server. (CVE-2017-14339) 20170420: YADIFA 2.2.5 Fixes an issue on message-enabled servers where the return address would not be captured Increased the maximum number of network interfaces to 256 20170406: YADIFA 2.2.4 Fixes an issue with relative include names that would not always be properly computed Fixes an issue where concurrent configuration reloads could lead to a crash 20170223: YADIFA 2.3.1 (internal) Added thread_pool_try_enqueue_call to give up if a queue is full or overworked (distance project) Fixes an issue with the CW queuing mechanism when trying to fill a full queue. 20161124: YADIFA 2.3.0 (internal) ECDSA can now be disabled at ./configure time. The support of ECDSA is not available in the openssl package of older Linux distributions. You can now add --disable-ecdsa at configure time to allow a build on these systems. Processed signals are now logged upon processing (info level) to allow the admin to know when a signal has effectively gone through. CPU affinity can now be tuned to stick a worker on a core. In
: thread-affinity-multiplier can be used to use every (1) or every odd (2) logical CPU. Parameter range from 0 to 4. (default is 0 = autodetect) By default, if hypertheading is detected, the multiplier is set to 2, else to 1. thread-affinity-base can be used to chose the first local CPU to consider. Parameter range from 0 to 3. (default is 0) In the end, network workers will have their affinity set to (base + multiplier * workerindex). The main purpose is to avoid using the hyperthread logical CPU as it can be counterproductive in some setups for high (10Gbps) troughput. Fixes: - fixed an issue on servers using the network-model 1 model (
: network-model 1) - fixed an issue where the removal in a certain order of hash/hash* related domains would end-up triggering an abort - fixed an issue where querying a signed domain that was deleted would answer NOERROR instead of NXDOMAIN - fixed an issue where a zone loaded with a journal would not be marked "dirty" and thus would not be fully dumped on disk upon kill -USR1 - fixed an issue with network aliases not configured on all setups of --enable-messages - fixed an issue with the logger not releasing the log files before reconfiguration - fixed an issue with the journal where heavy load would prevent notification to secondaries 20161108: YADIFA 2.2.2 OpenSSL 1.1.0 crypto API support 20160719: YADIFA 2.2.1 Multi-primary support: Added axfr-retry-failure-delay-multiplier and axfr-retry-failure-delay-max
parameters to increase the time between two AXFR/IXFR retries on a primary. Fixes: - fixed an issue that would crash a YADIFA secondary when restarting with a journal present - fixed an issue in AXFR/IXFR retry timing management 20160715: YADIFA 2.2.0 Multi-primary support: In , the primaries field is now a list. When the primary fails to answer, it is moved to the end of the list and (new) first one is used instead. There is a true-multiprimary setting, defaulted to 'no'. In true multiprimary mode, changing the primary implies dropping local zone data and ignore serial values. This is to be used for a setup with truly independent primaries. By default, the primary change occurs at first failure. This can be changed to a higher value with multiprimary-retries (maximum: 255) This mostly makes sense on true-multiprimary mode as you want to be sure before reloading a zone completely. Smart signing: Keys with smart signing information are now handled by YADIFA. DNSSEC policies: YADIFA generates an rolls your keys and makes a non-DNSSEC zone into an NSEC or NSEC3 one. Support for ECDSA algorithm. Better support for huge incremental changes of a zone: YADIFA used to do the modification in one go, which could make it unresponsive for very big changes. Now the changes are applied more slowly, allowing queries to be answered. New network model: A new network model can be enabled. This model's main purpose is to be more resistent to system stalls with minimal, if any, performance loss.
network-model 1 NSEC3 management improved. Several improvements have been made on the way NSEC3 is handlded. Chains partially covering the zone are now accepted. Fixes: - fixed an issue where the maximum pid value supported was 99999 - fixed an issue with RRSIG TTL values that were not always at the expected value. - fixed an issue with the $TTL not being respected. 20160126: YADIFA 2.1.6 Fixes: - fixed an issue where the referral would not be measured for UDP on a optimised build. 20160108: YADIFA 2.1.5 Dynamic updates do not use temporary files anymore which improves their general performance. The statistics now shows the referrals. Fixes: - fixed an issue where getting a huge incremental transfer would prevent the server from answering queries while applying the changes. - fixed an issue serving IXFR that would occur when a incremental change step was bigger than 64KB - fixed an issue for Solaris with the memory alignment fix not active everywhere - fixed an issue on the Solaris build settings - fixed an issue where sometimes yadifad would not find a configuration file given as a parameter with a relative path - fixed an issue where a wild-card would not be properly returned with an AXFR - fixed an issue where dynamically updating a zone at a speed such that the zone file would need to be written multiple times on disk before finishing the previous write could lead to a deadlock 20151026: YADIFA 2.1.4 The zone reader error reporting has been improved. Stacktrace support added for Solaris. Known issue: - Adding and or removing NSEC3PARAM dynamically is not properly handled. Fixes: - fixed an issue where an NSEC3 answer proving a * query would lead to a crash - fixed an issue where a private key may be not recognised as such - fixed an issue where dynamic update prerequisite check would fail a valid match - fixed an issue where zone signature maintenance would only start if all private keys were available. 20150821: YADIFA 2.1.3 Fixes: - fixed an issue that could lead to a crash at startup - fixed an issue where parsing a TYPE#### record would stop the parser prematurely 20150814: YADIFA 2.1.2 The ./configure script has a new option: --enable-full-ascii7 This changes the behaviour of DNS name validation to accept all the ASCII7 characters instead of only the DNS-space ones. Enabling this option is not recommended. Fixes: - fixes an issue where the hmac-shaX identification string sent with a TSIG had the suffix ".sig-alg.reg.int". 20150714: YADIFA 2.1.1 The yadifa command line has a new option: --config|-c file : read the specific configuration file instead of ~/.yadifa.rc Issues detected on the NSEC3 database have now been upgraded from debug to info/warning Fixes: - fixed an issue where, on some cases; the garbage collector for the zones was not triggering for a long time. - fixed an issue in the Makefile (courtesy of DENIC) - fixed an issue where a few bytes could be leaked in some rare cases when failing to unload a zone - fixed an issue in RRL where some values of IPv6 prefix - fixed an issue accepting some answers on IXFR transfers 20150424: YADIFA 2.1.0 New journal file format: This new format addresses a few issues like having maximum journal file and a relatively constant random access time even for very big sizes. The internal messaging queue has been changed to address huge amount of zones. New CHaos queries supported: hostname id.server Known issues: _ building successfully with LTO may require to append both AR=gcc-ar and RANLIB=gcc-ranlib to the ./configure command 20150403: YADIFA 2.0.6 This release is a public release. This minor update's sole purpose is to fix YADIFA builds on OpenBSD. Fixes: - fixed a crash that could occur while sending a massive amount of notifications - OpenBSD builds are fixed. Tested on: OpenBSD 5.6 amd64, standard installation. Configure: ./configure Tested on: OpenBSD 5.6 amd64, with gcc 4.9 installed. Configure: ./configure CC=egcc 20150226: YADIFA 2.0.5 This release is a public release. Fixes: - fixed an issue with huge IXFR transfers as a primary - fixed an issue with notifications on secondary-secondary-primary setup - fixed an issue with a potential infinite loop loading an AXFR from a primary - fixed missing hmac-sha* from configuration - fixed an issue with TLSA records parsing - fixed an issue with base 16 encoding - fixed an issue parsing * domains - fixed an issue with some RRL motivated answers - increased the maximum number of network interfaces from 5 to 16 - fixed an error in the configuration examples where "statistics" was used instead of "stats" - minor fixes and improvements 20141216: YADIFA 2.0.4 This release is a public release. By popular demand, the default log file directory is now PREFIX/var/log/yadifa. It can be set using --with-logdir=/my/dir Improved build mechanism. It has been tested to work automatically on Linux, FreeBSD, OSX, SunOS. RedHat family builds will use -O2 as maximum optimisations. Note that some optional features are now enabled by default but can be disabled. Fixes: - fixed an issue with the AXFR transfer where the serial number would not be properly taken into account - fixed an issue with the notify mechanism that could occur if the server was only listening to 127.0.0.1 - fixed an issue with bogus DNSKEY records that may potentially lead to a crash in openssl - fixed a reported potential "tmpfile" vulnerability on DEBUG builds (generated with make debug) - fixed an issue with IPv6 connections on some architectures - typos fixes - minor fixes and improvements 20141104: Architecture portability enhancements. On Solaris, if no --enable-force32bits nor --enable-force64bits is set, then 64 bits will be forced (fixes an issue at link-time) ELF 64-bit MSB executable SPARCV9 Version 1, UltraSPARC3 Extensions Required, dynamically linked, not stripped, no debugging information available PATH=/opt/csw/bin:/usr/ccs/bin:$PATH ./configure --enable-force32bits PATH=/opt/csw/bin:/usr/ccs/bin:$PATH make 20141030: Architecture portability enhancements. FreeBSD 9 FreeBSD dnode3 9.0-RELEASE-p3 FreeBSD 9.0-RELEASE-p3 #0: Tue Jun 12 02:52:29 UTC 2012 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 gcc (GCC) 4.2.1 20070831 patched [FreeBSD] ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 9.0 (900044), not stripped Ubuntu Linux dnode10 3.2.0-49-generic #75-Ubuntu SMP Tue Jun 18 17:39:32 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xe3b8601b9b5e59f8c9ce519cacbe9b8ff544ff1d, not stripped OSX Darwin RD-Mac-Mini.local 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun 3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64 Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) Mach-O 64-bit executable x86_64 20141029: Architecture portability enhancements. uname -a gcc --version file yadifad YellowDog Linux Linux 2.6.29-3.ydl61.4 #1 SMP Mon Sep 7 14:50:27 PDT 2009 ppc64 ppc64 ppc64 GNU/Linux gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44) ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped note: using --enable-force64bits failed because of ssl, no simple/quick way to install openssl-devel.ppc64 seemed available Debian PPC64 Linux 3.2.0-3-powerpc64 #1 SMP Mon Jul 23 08:03:56 UTC 2012 ppc64 GNU/Linux gcc (Debian 4.6.3-8) 4.6.3 ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xedc47c984a4af7eb9a7ecbc0f135e4d064ba08f0, with unknown capability 0x41000000 = 0x13676e75, with unknown capability 0x10000 = 0xb0401, not stripped note: using --enable-force64bits failed because of ssl, no simple/quick way to install openssl-devel.ppc64 seemed available 20141016: YADIFA 2.0.2 TCP fallback support on truncation 20140905: YADIFA 2.0.0 This release is a public release Fixes: - fixed a log incorrectly reporting an error when the client didn't close the TCP connection fast enough - fixed an issue with the statistics on TCP queries Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. 20140829: YADIFA 2.0.0-beta3-public This release is a public release - --disable-master feature at configure now builds a secondary-only server Fixes: - fixed an issue with TSIG signed queries - fixed an issue with thread pool live resizing - fixed an issue where reading an undeleted obsolete journal ending at the start of a newly transferred zone from the primary would incorrectly trigger an error Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. 20140630: YADIFA 2.0.0-beta2-public This release is a public release - basepath disabled - pidpath removed, only pidfile remains - log reopen notification is now timestamped - secondary zones no longer complain about missing NSEC/NSEC3 private keys - the error code ZRE_FILE_NOT_FOUND has been replaced by the more accurate code ZRE_NO_VALID_FILE_FOUND - default logging settings no longer output debug Fixes: - fixed issue in flag computation (AD,CD) - fixed an issue with journal truncation sometimes leading to a crash - zone parsing now correctly accepts '#' as a comment marker - zone parsing now rejects wrong fqdn as soon as it reads them, leading to a more accurate error message - removing the last dnskey of a zone no longer crashes the server Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. yadifa remote client commands prototype is now available with the following supported commands: -shutdown shuts down yadifa e.g. ./yadifa -s "192.0.2.1 port 53" -t shutdown -cfgreload reloads the and sections of the yadifad configuration e.g. ./yadifa -s "192.0.2.1 port 53" -t cfgreload -logreopen closes and reopen the log files e.g. ./yadifa -s "192.0.2.1 port 53" -t logreopen -freezeall prevents all zones from being updated dynamically with nsupdate e.g. ./yadifa -s "192.0.2.1 port 53" -t freezeall -freeze prevents a zone from being updated dynamically with nsupdate e.g. ./yadifa -s "192.0.2.1 port 53" -t freeze -q somedomain.eu -unfreezeall enables updates of all zones again e.g. ./yadifa -s "192.0.2.1 port 53" -t unfreezeall -unfreeze enables updates of a zone again e.g. ./yadifa -s "192.0.2.1 port 53" -t unfreeze -q somedomain.eu In order to work, the allow-control ACL must be defined either in
for the global commands and may also be defined in for the ones targeting a specific zone. e.g. allow-control 127.0.0.1 Note that tsig is not supported in the client yet. 20140528: YADIFA 2.0.0-beta1-public This release is a public release - NSID implemented (enabled at ./configure time with --enable-nsid - generic parser for: - getops - zone file - resolv.conf - configuration - '@' can now be used in a zone file - new binary for controlling 'yadifad' (yadifa) - framework is rewritten for multi core systems - single core server has been removed Fixes: - fixed several minor issues Know issues: - removing all dnskeys from a zone file crashes the server - yadifa has some issues with nodelay, nocork 20130424: YADIFA 1.1.0 _ added DSA signature _ added SHA-256 SHA-384 SHA-512 digest algorithms _ now supports additional DNSSEC algorithms: DSASHA1 DSASHA1_NSEC3 RSASHA256_NSEC3 RSASHA512_NSEC3 _ Respone Rate Limitation implemented (enabled at ./configure time with --enable-rrl) _ --enable-tiny-footprint now reduces the memory usage further by reducing the standard log queue from 2^20 to 2^12 entries _ the general speed has been slightly improved _ dynamic updates pending for more than 3 seconds are now dropped with an error _ dynamic provisioning Fixes: _ fixed a memory leak that could occur at NSEC3 generation when loading the zone failed in a particular way _ fixed a memory leak at ixfr send _ fixed handling of '_' character that was improperly stored in the database _ fixed bandwidth limit settings (tcp stream in and out) not always being taken from the configuration _ fixed TSIG answer verification for notifies _ fixed error codes not being registered and thus logged as unknown hexadecimal error code. _ other minor fixes 20130612: YADIFA 1.0.3 Fixes only (backports from 1.1.0) Fixes: _ fixed an issue preventing YADIFA from being build from another directory _ fixed an issue with OSX systems where gsed has to be used instead of sed _ fixed an issue with the '_' character not being properly handled _ fixed an issue where reading MX record from a zone file would incorrecly be rejected as invalid _ fixed an issue where the OPT record would not be properly written _ fixed an issue where an undefined ACL reference would be silently ignored _ fixed missing code tags for several error codes. From now on unregistered codes are dumped in hexadicimal. _ fixed portability issues with BSD and OSX _ fixed several minor issues 20120921: YADIFA 1.0.2 Fixes only Fixes: _ fixed an issue where the journal file was sometimes not properly closed at the end of a task _ fixed an issue where the TCP usage slots would sometimes wrongly return that they were all being used _ fixed an issue on IXFR processing (secondary side) where the type of answer from the primary would not be properly detected _ fixed an issue with TSIG on secrets not exactly 16 bytes long (binary form) _ fixed an issue on 32 bits architectures where the sig-validity-* fields would not be properly handled if not set on each zone section. _ slightly improved the replay time of big journal files _ fixed several minor issues Known issues: _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120709: YADIFA 1.0.1 _ logging repeat compression is now by channel instead of global Fixes: _ fixed an issue where glibc whould assert if libgcc_s.so (libgcc_s.so.1) and libc.so (libc.so.6) where not available inside the chrooted directory of YADIFA _ fixed an issue in the syslog module Known issues: _ on 32 bits architectures, the sig-validity-* fields are not properly copied from
to as a workaround, set the sig-validity fields in each container in 32 bits architectures ie: sig-validity-interval 7 sig-validity-regeneration 168 sig-validity-jitter 3600 _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120625: YADIFA 1.0.0 _ LTO support can be enabled with --enable-lto but this is not working with clang. LTO does not increase the performance significally _ parallel processing of listening addresses can now be enabled. It can be set using thread-count-by-address in the
section. By default YADIFA will not use parallel processing as this feature has not been as thoroughly tested as the single-thread processing model _ default parameters tuning _ fixes Known issue: _ on 32 bits architectures, the sig-validity-* fields are not properly copied from
to as a workaround, set the sig-validity fields in each container in 32 bits architectures ie: sig-validity-interval 7 sig-validity-regeneration 168 sig-validity-jitter 3600 20120530: YADIFA 1.0.0RC3 _ the configuration parser now ignores undefined logger names and report them with a warning _ syslog messages are now put in the name of "yadifad" instead of the name used for the "syslog" channel _ syslog messages do not print the time from YADIFA anymore _ improved the steps involved in loading a locally cached secondary zone _ zones are now loaded in background _ man page yadifad-conf.man5 renamed into yadifad.conf.man5 Fixes: _ AXFR/IXFR answers with the RA bit set are nolonger rejected as invalid _ YADIFA now answers to SIGINT again (shutdown) _ fixed an issue where obsolete AXFR files were not always being deleted _ fixed an issue occurring when both IPv4 and IPv6 were available to handle a notify _ fixed journal replay issue where some RRSIGs records were not properly removed _ fixed an issue occurring with IPv6 queries _ fixed an issue in the generation of a specific NSEC3 error answer _ fixed named query style layout Known issue: _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120328: YADIFA 1.0.0RC2 _ fixed logging issue on work file creation error _ fixed an issue where IXFR queries could be rejected as being wrongly formatted _ fixed an issue in the query logging text _ enabled command line options ( -u uid -g gid -d ) 20120319: YADIFA 1.0.0RC1 Is a full functional authoritative name server: - works as primary or secondary name server - AXFR - IXFR - NOTIFY - NSUPDATE - TSIG - CLASSES: - IN - CH (just for version) - TYPES: - AAAA - CNAME - DNSKEY - DS - HINFO - MX - NAPTR - NS - NSEC3 - NSEC3PARAM - NSEC - PTR - RRSIG - SOA - SRV - SSHFP - TXT - Automatic resigning - DNSSEC algorithms: - 5 (RSASHA1) - 7 (RSASHA1-NSEC3 - ACL's KNOWN ISSUES: NSEC3: _ cannot work with multiple NSEC3PARAM chains with mixed OPT-IN/OUT settings _ adding a new NSEC3 chain expects that the primary sends the NSEC3PARAM first (it does not seems to be always the case) We have a case where a primary starts with 2 thousands NSEC3 opt-out records then adds 6 millions NSEC3 opt-in records but does not give the NSEC3PARAM record first. The secondary server rejects them all because it's unable to link them to a chain. (This one has high priority) DNSSEC: _ it is not allowed to change the zone security mode (unsecure, NSEC, or NSEC3). Once the zone is loaded it keeps its security mode. _ dynamic updates of NSEC as well as NSEC3 records are refused QUIT: the server will shutdown on the following conditions: _ detection of an impossible situation or an internal integrity issue (ie: for any reason the SOA has vanished from a zone) _ memory limit reached which prevents any more work _ ipc issue which prevent internal services communication ACL: _ since the access control is set by zone and CHAOS class is not implemented as a configurable zone, it is not possible (yet) to specifically block CHAOS queries. 20111121: YADIFA 0.5.5 - many fixes KNOWN ISSUE: NSEC3 secondary zone replay fails. 20110706: YADIFA 0.5.0 - secondary mode, AXFR/IXFR (no TSIG yet for the secondary-side transfer) - answers to a notify from the primary - polls the (first) primary on the primaries list - maintains the .axfr & .ix files (deletes the obsoletes ones) - TSIG queries are checked - Replays the zone journal on startup after the zone load (journaling) - Answers IXFR queries (journaling) 20110601: YADIFA 0.4.0 Operational: - It works as a no dnssec name server - No notifies to secondary name servers - daemon - Answers AXFR queries with TSIG - nsupdate functionality (journaling) - TSIG on client server side will be transmitted, but not checked - ACL works - The zone has SOA, NS A resource records. 20110524: YADIFA 0.3.0 First release internally of yadifad 20110524115500 GMT+1. Operational: - It works as a no dnssec name server - No notifies to secondary name servers - daemon - Answers AXFR queries - The zone has SOA, NS A resource records. 20091224: YADIFA 0.2.0 _ Answers AXFR queries _ ACL based on IP and TSIG (not all query types are ACL'ed yet) 20091104: YADIFA 0.1.0 YADIFA is a work in progress. The main goal is to have an alternative for BIND or NSD. Version 0.1.0 is an authoritative server only. It has no: - AXFR/IXFR functionality - dynupdate - support for NSEC - support for NSEC3 - caching mechanism - additional tools (eg.dig, dnssectools, drill,...) It has: - a very fast way to give authoritative answer - a very fast method for loading the database and checking the zone files This first release is to have a feeling how it works in an operational environment. TODO Everything what is not implemented, has to be implemented. Most of the code is there, but is not activated. No comformity tests has been done. (This of course is on the todo list) Bug Reports and Mailing Lists Bugs reports should be sent to bugreport@yadifa.eu yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/INSTALL0000644000000000000000000000013214505005532017572 xustar000000000000000030 mtime=1695812442.363981057 30 atime=1695812445.791030139 30 ctime=1695812494.447727001 yadifa-2.6.5-11201/lib/dnscore/INSTALL0000664000374500037450000004173114505005532017542 0ustar00signersigner00000000000000Quick installation ****************** You will need the most up-to-date aclocal, autoheader, automake, autoconf, make and a C compiler installed (clang, icc or gcc >= 4.6) By default gcc is used but you can specify your compiler adding CC=x in ./configure. ie: ./configure CC=clang openssl has to be build with shared Note that gcc < 4.6 will be build with -O0 and > 4.6 with -O3 ./configure make sudo make install cd /usr/local sudo mkdir -p var/run var/log var/zones/keys var/zones/masters var/zones/slaves var/zones/xfr Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" With "Homebrew" installed for openssl support: ./configure -with-openssl=/usr/local/opt/openssl@1.1 CFLAGS="-O2 -g -DDEBUG=0 -DNDEBUG=1" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `--with-openssl=DIR' Use the openssl from directory DIR (where DIR is the PREFIX of openssl) `--enable-tiny-footprint' This will change the behaviour of the memory allocation of the database. It will take the smallest increase in memory required to fulfill an allocation instead of getting a bunch at once. Disabled by default. `--enable-messages' Will use recvmsg/sendmsg instead of recvfrom/sendto. This is only useful if * any interface the server listens from has aliased IPs. (ie: eth0 & eth0:1) AND * the server is configured to listen to 0.0.0.0 (it's its default) Having aliased addresses on interfaces can also be handled without using messages but enumerating the listen addresses in yadifad.conf instead. ie: listen 192.0.2.1, 192.0.2.2 `--enable-lto' Will use the Link Time Optimisations of gcc (or ipo for ICC) The gain of speed is very marginal so it is not recommended `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/NEWS0000644000000000000000000000013214505005532017240 xustar000000000000000030 mtime=1695812442.519983291 30 atime=1695812445.791030139 30 ctime=1695812494.449727029 yadifa-2.6.5-11201/lib/dnscore/NEWS0000664000374500037450000000001414505005532017175 0ustar00signersigner00000000000000See README yadifa-2.6.5-11201/lib/dnscore/PaxHeaders.1636/README0000644000000000000000000000013214505005532017421 xustar000000000000000030 mtime=1695812442.521983319 30 atime=1695812445.791030139 30 ctime=1695812494.451727058 yadifa-2.6.5-11201/lib/dnscore/README0000664000374500037450000000377514505005532017377 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ 20230906: YADIFA 2.6.5-public Secondaries will nolonger enforce the TTL value of the NSEC3PARAM record. Fixes an issue caused by a limitation of the select system call. yadifa-2.6.5-11201/lib/PaxHeaders.1636/dnsdb0000644000000000000000000000012714505005617016131 xustar000000000000000029 mtime=1695812495.04673558 29 atime=1695812499.08179337 29 ctime=1695812495.04673558 yadifa-2.6.5-11201/lib/dnsdb/0000775000374500037450000000000014505005617016144 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/include0000644000000000000000000000013114505005616017546 xustar000000000000000030 mtime=1695812494.879733188 29 atime=1695812499.08179337 30 ctime=1695812494.879733188 yadifa-2.6.5-11201/lib/dnsdb/include/0000775000374500037450000000000014505005616017566 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnsdb/include/PaxHeaders.1636/dnsdb0000644000000000000000000000013114505005617020641 xustar000000000000000030 mtime=1695812495.034735408 29 atime=1695812499.08179337 30 ctime=1695812495.034735408 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/0000775000374500037450000000000014505005617020661 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/avl.h0000644000000000000000000000013114505005531021644 xustar000000000000000029 mtime=1695812441.51796894 30 atime=1695812445.798030239 30 ctime=1695812494.889733331 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/avl.h0000664000374500037450000003062714505005531021617 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief AVL structure and functions * * AVL structure and functions * * @{ */ #ifndef _AVL_H #define _AVL_H #include #include #ifndef ZDB_INLINES_AVL_FIND #error "ZDB_INLINES_AVL_FIND not defined" #endif #ifdef __cplusplus extern "C" { #endif #define DATABASE_AVL_NODE_TAG 0x0045444F4E4c5641 /* "AVLNODE" */ /* * In the worst case, AVL is Fibonacci-balanced. */ /* Python script to compute fibo nodes for each depth: import sys import math def fibonacci(n): a,b,c = 1,1,0 for i in range(0,n): c = c+a print "F#",i," Value=",a," Items=",c, " Log2=",math.log(c,2); a,b = b,a+b if __name__ == "__main__": fibonacci(64); */ /* And here are the first values: F# 0 Value= 1 Items= 1 Log2= 0.0 F# 1 Value= 1 Items= 2 Log2= 1.0 F# 2 Value= 2 Items= 4 Log2= 2.0 F# 3 Value= 3 Items= 7 Log2= 2.80735492206 F# 4 Value= 5 Items= 12 Log2= 3.58496250072 F# 5 Value= 8 Items= 20 Log2= 4.32192809489 F# 6 Value= 13 Items= 33 Log2= 5.04439411936 F# 7 Value= 21 Items= 54 Log2= 5.75488750216 F# 8 Value= 34 Items= 88 Log2= 6.45943161864 F# 9 Value= 55 Items= 143 Log2= 7.15987133678 F# 10 Value= 89 Items= 232 Log2= 7.85798099513 F# 11 Value= 144 Items= 376 Log2= 8.55458885168 F# 12 Value= 233 Items= 609 Log2= 9.25029841791 F# 13 Value= 377 Items= 986 Log2= 9.94544383638 F# 14 Value= 610 Items= 1596 Log2= 10.6402449362 F# 15 Value= 987 Items= 2583 Log2= 11.3348319281 F# 16 Value= 1597 Items= 4180 Log2= 12.029287227 F# 17 Value= 2584 Items= 6764 Log2= 12.7236609444 F# 18 Value= 4181 Items= 10945 Log2= 13.4179843341 F# 19 Value= 6765 Items= 17710 Log2= 14.1122765916 F# 20 Value= 10946 Items= 28656 Log2= 14.806549622 F# 21 Value= 17711 Items= 46367 Log2= 15.5008107652 F# 22 Value= 28657 Items= 75024 Log2= 16.1950645637 F# 23 Value= 46368 Items= 121392 Log2= 16.8893138224 F# 24 Value= 75025 Items= 196417 Log2= 17.5835602755 F# 25 Value= 121393 Items= 317810 Log2= 18.2778049947 F# 26 Value= 196418 Items= 514228 Log2= 18.9720486423 F# 27 Value= 317811 Items= 832039 Log2= 19.6662916275 F# 28 Value= 514229 Items= 1346268 Log2= 20.3605342035 F# 29 Value= 832040 Items= 2178308 Log2= 21.0547765264 F# 30 Value= 1346269 Items= 3524577 Log2= 21.749018693 F# 31 Value= 2178309 Items= 5702886 Log2= 22.443260763 F# 32 Value= 3524578 Items= 9227464 Log2= 23.1375027733 F# 33 Value= 5702887 Items= 14930351 Log2= 23.8317447466 F# 34 Value= 9227465 Items= 24157816 Log2= 24.5259866972 F# 35 Value= 14930352 Items= 39088168 Log2= 25.2202286336 F# 36 Value= 24157817 Items= 63245985 Log2= 25.9144705613 F# 37 Value= 39088169 Items= 102334154 Log2= 26.6087124837 F# 38 Value= 63245986 Items= 165580140 Log2= 27.3029544027 F# 39 Value= 102334155 Items= 267914295 Log2= 27.9971963197 F# 40 Value= 165580141 Items= 433494436 Log2= 28.6914382353 F# 41 Value= 267914296 Items= 701408732 Log2= 29.3856801502 F# 42 Value= 433494437 Items= 1134903169 Log2= 30.0799220647 F# 43 Value= 701408733 Items= 1836311902 Log2= 30.7741639788 F# 44 Value= 1134903170 Items= 2971215072 Log2= 31.4684058927 F# 45 Value= 1836311903 Items= 4807526975 Log2= 32.1626478065 F# 46 Value= 2971215073 Items= 7778742048 Log2= 32.8568897203 F# 47 Value= 4807526976 Items= 12586269024 Log2= 33.551131634 F# 48 Value= 7778742049 Items= 20365011073 Log2= 34.2453735476 F# 49 Value= 12586269025 Items= 32951280098 Log2= 34.9396154613 F# 50 Value= 20365011074 Items= 53316291172 Log2= 35.633857375 F# 51 Value= 32951280099 Items= 86267571271 Log2= 36.3280992886 F# 52 Value= 53316291173 Items= 139583862444 Log2= 37.0223412022 F# 53 Value= 86267571272 Items= 225851433716 Log2= 37.7165831159 F# 54 Value= 139583862445 Items= 365435296161 Log2= 38.4108250295 F# 55 Value= 225851433717 Items= 591286729878 Log2= 39.1050669431 F# 56 Value= 365435296162 Items= 956722026040 Log2= 39.7993088568 F# 57 Value= 591286729879 Items= 1548008755919 Log2= 40.4935507704 F# 58 Value= 956722026041 Items= 2504730781960 Log2= 41.187792684 F# 59 Value= 1548008755920 Items= 4052739537880 Log2= 41.8820345977 F# 60 Value= 2504730781961 Items= 6557470319841 Log2= 42.5762765113 F# 61 Value= 4052739537881 Items= 10610209857722 Log2= 43.2705184249 F# 62 Value= 6557470319842 Items= 17167680177564 Log2= 43.9647603385 F# 63 Value= 10610209857723 Items= 27777890035287 Log2= 44.6590022522 */ #define AVL_MAX_DEPTH 52 // 139*10^9 items max (worst case)*/ struct avl_leftrightchildren { struct avl_node_* left; struct avl_node_* right; }; struct avl_node_ { union { struct avl_node_ * child[2]; /* 2 ptr */ struct avl_leftrightchildren lr; } children; void* data; /* 1 ptr */ hashcode hash; /* hashcode of the data (32 bits) */ s8 balance; /* used for balance check */ // 3 unused bytes }; /* 17 29 => 24 32 */ typedef struct avl_node_ avl_node; typedef avl_node* avl_tree; typedef struct { s32 stack_pointer; avl_node *stack[AVL_MAX_DEPTH]; /* An AVL depth of 64 is HUGE */ } avl_iterator; #undef AVL_MAX_DEPTH /** @brief Initializes the tree * * Initializes the tree. * Basically : *tree=NULL; * * @param[in] tree the tree to initialize * */ void avl_init(avl_tree* tree); /** @brief Find a node in the tree * * Find a node in the tree matching a hash value. * * @param[in] tree the tree to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node or NULL if there is no such node. */ #if !ZDB_INLINES_AVL_FIND void* avl_find(avl_tree* tree, hashcode obj_hash); #else #define CHILD(node,id) ((node)->children.child[(id)]) static inline void* avl_find(const avl_tree* root, hashcode obj_hash) { assert(root != NULL); avl_node* node = *root; hashcode h; /* This is one of the parts I could try to optimize * I've checked the assembly, and it sucks ... */ /* Both the double-test while/ternary and the current one * are producing the same assembly code. */ while(node != NULL) { if((h = node->hash) == obj_hash) { return node->data; } node = CHILD(node, (obj_hash > h)&1); } /*return (node!=NULL)?node->data:NULL;*/ return NULL; } #endif /** @brief Find a node in the tree * * Find a node in the tree matching a hash value. * This is required for search that could lead to a change to the data. * * @param[in] tree the tree to search in * @param[in] obj_hash the hash to find * * @return A pointer to a pointer to the node or NULL if there is no such node. */ #if !ZDB_INLINES_AVL_FIND void** avl_findp(avl_tree* tree, hashcode obj_hash); #else static inline void** avl_findp(const avl_tree* root, hashcode obj_hash) { assert(root != NULL); avl_node* node = *root; hashcode h; while(node != NULL /* &&((h=node->hash)!=obj_hash) */) { if((h = node->hash) == obj_hash) { return &node->data; } node = CHILD(node, (obj_hash > h)&1); } /* return (node!=NULL)?&node->data:NULL; */ return NULL; } #undef CHILD #endif /** @brief Insert a node into the tree. * * Insert data into the tree. * Since hash can have collisions, the data will most likely be a collection * (another tree, a list, ...) * * NOTE: * If the node associated to the hash already exists, it is returned unaltered, * the caller will be responsible to manipulate the node's data. * Else a new node is created, pointing to the data. * * @param[in] tree the tree where the insertion should be made * @param[in] obj_hash the hash associated to the data * * @return The node associated to the hash */ void** avl_insert(avl_tree* tree, hashcode obj_hash); /** @brief Deletes a node from the tree. * * Deletes a node from the tree. * * @param[in] tree the tree from which the delete will be made * @param[in] obj_hash the hash associated to the node to remove * * @return The node associated to the hash, NULL if it did not exist. */ void* avl_delete(avl_tree* tree, hashcode obj_hash); /** @brief Releases all the nodes of a tree * * Releases all the nodes of a tree. Data is not destroyed. * * @param[in] tree the tree to empty */ void avl_destroy(avl_tree* tree); void avl_iterator_init(avl_tree tree, avl_iterator* iter); /** * Initialises an iterator from right after a given key. * Returns the node, or NULL if the node does not exist. * The next call to avl_iterator_next* will return the next node (provided the first one exists) * * @param tree the avl_tree collection * @param iter an iterator that will be initialised to the node following the returned one (if not NULL) * @param obj_hash the key of the node to look for * @return the sought node */ avl_node* avl_iterator_init_from_after(avl_tree tree, avl_iterator *iter, hashcode obj_hash); #if !ZDB_INLINES_AVL_FIND bool avl_iterator_hasnext(avl_iterator* iter); #else static inline bool avl_iterator_hasnext(avl_iterator* iter) { return iter->stack_pointer >= 0; } #endif void** avl_iterator_next(avl_iterator* iter); avl_node* avl_iterator_next_node(avl_iterator* iter); /** @brief Releases all the nodes of a tree * * Releases all the nodes of a tree. * Calls a function passed in parameter before destroying the data. * It's the responsibility of the callback to process (destroy) the data * in the tree. * * @param[in] tree the tree to empty */ void avl_callback_and_destroy(avl_tree tree, void (*callback)(void*)); #if DEBUG /** @brief DEBUG: check that a tree fits the AVL definition. * * DEBUG: check that a tree fits the AVL definition. * * @param[in] tree the tree to check * * @return A positive integer if the AVL is right (the depth actually) else * a negative integer. * */ ya_result avl_check(avl_tree tree); /** @brief DEBUG: check that a node fits the AVL definition. * * DEBUG: check that a node fits the AVL definition. * * @param[in] node the node to check * * @return A positive integer if the AVL is right (the depth actually) else * a negative integer. * */ s32 avl_checkdepth(avl_node* node); /** @brief DEBUG: Prints the (sorted) content of the AVL * * DEBUG: Prints the (sorted) content of the AVL * * @param[in] tree the tree to print * */ void avl_print(avl_tree tree); /** @brief DEBUG: Prints the content of the AVL node * * DEBUG: Prints the (sorted) content of the AVL node * * @param[in] node the node to print * */ void avl_printnode(avl_node* node); #endif #ifdef __cplusplus } #endif #endif /* _AVL_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/btree.h0000644000000000000000000000013014505005531022162 xustar000000000000000029 mtime=1695812441.48096841 30 atime=1695812445.797030225 29 ctime=1695812494.89173336 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/btree.h0000664000374500037450000000627414505005531022137 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Balanced Tree structures and functions for the database * * Definitions of the Balanced Tree structures and functions for the database. * * btree is the chosen balanced tree for the database. * The current choice right now is AVL Tree. * It could be set to something else. ie: Red-Black Tree. * * @{ */ #ifndef _btree_H #define _btree_H #include #ifdef __cplusplus extern "C" { #endif /* * The iterator returns the nodes sorted with their hash value. * * This macro is true for AVL */ #define BTREE_ITERATION_SORTED 1 typedef avl_node btree_node; typedef avl_tree btree; typedef avl_iterator btree_iterator; #define btree_init avl_init #define btree_find avl_find #define btree_findp avl_findp #define btree_insert avl_insert #define btree_delete avl_delete #define btree_destroy avl_destroy #define btree_callback_and_destroy avl_callback_and_destroy #define btree_iterator_init avl_iterator_init #define btree_iterator_init_from avl_iterator_init_from_after #define btree_iterator_hasnext avl_iterator_hasnext #define btree_iterator_next avl_iterator_next #define btree_iterator_next_node avl_iterator_next_node #define btree_notempty(tree) ((tree)!=NULL) #define btree_isempty(tree) ((tree)==NULL) #ifdef __cplusplus } #endif #endif /* _btree_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/dictionary.h0000644000000000000000000000013214505005531023230 xustar000000000000000030 mtime=1695812441.483968453 30 atime=1695812445.797030225 30 ctime=1695812494.893733388 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/dictionary.h0000664000374500037450000004504614505005531023203 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Hash-based collection designed to change it's structure to improve speed. * * Hash-based collection designed to change it's structure to improve speed. * * @{ */ #ifndef _dictionary_H #define _dictionary_H #include #include #include //#define DICTIONARY_NODE_MODE 0 // struct #define DICTIONARY_NODE_MODE 1 // union #ifdef __cplusplus extern "C" { #endif #if !DICTIONARY_NODE_MODE struct dictionary_node; typedef struct dictionary_node dictionary_node; #else union dictionary_node; typedef union dictionary_node dictionary_node; #endif /** * @brief Function type used to find a node match * * Function type used to find a node match * * @param[in] data an arbitrary data (whose meaning is known by the function, of course) * @param[in] node the node to checked for a match * * @return <0, 0, >0 if the node respectively is before the data, matches the data, or is above the data. */ typedef int dictionary_data_record_compare_function(const void* data, const dictionary_node* node); /** * @brief Function type used to create a node * * Function type used to create a node * * @param[in] data an arbitrary data (whose meaning is known by the function, of course) * * @return a pointer to a node created from the data */ typedef dictionary_node* dictionary_data_record_create_function(const void* data); /** * @brief Function type used to destroy a node * * Function type used to destroy a node * * @param[in] node the node to destroy */ typedef void dictionary_destroy_record_function(dictionary_node* node); /** * @brief Function type used to destroy a node * * Function type used to destroy a node * * @param[in] node the node to destroy */ typedef void dictionary_destroy_ex_record_function(dictionary_node* node, void* arg); /** * @brief Function type used to transfer a node just detached from a dictionary * * Function type used to transfer a node just detached from a dictionary to another * * @param[in] bucket_data an arbitrary data passed to the function * @param[in] key the hashcode of the node detached from the dicionary * @param[in] node the node detached from the dictionary */ typedef void dictionary_bucket_record_function(void* bucket_data, hashcode key, dictionary_node* node); #define COLLECTION_PROCESS_RETURNERROR -1 #define COLLECTION_PROCESS_STOP 0 #define COLLECTION_PROCESS_NEXT 1 #define COLLECTION_PROCESS_DELETENODE 2 /** * Function type called by a dictionary_process_method to do whatever is required on a node. * * Mostly used for deletion in a cascade of dictionaries (what the database is) * * In case of deletion of the node, the function cannot process the dictionary_node pointed * by the next field (node->next). * * Returns a control code to the caller. * * @param[in] data an arbitrary data passed to the callee. * @param[in] node the node to be processed by the callee. * * @return COLLECTION_PROCESS_NEXT if the next node must be proccessed. * @return COLLECTION_PROCESS_STOP if the process MUST be stopped immediately. * @return COLLECTION_PROCESS_DELETENODE if the node has been deleted and the process MUST be stopped immediately. * @return COLLECTION_PROCESS_RETURNERROR if an error occurred and the process MUST be stopped immediately. */ typedef ya_result dictionary_process_record_function(void* data, dictionary_node* node); struct dictionary_vtbl; typedef struct dictionary dictionary; /** * @brief The dictionary descriptor. * * The dictionary descriptor. * */ struct dictionary { union { btree btree_collection; /* 4 8 */ htbt htbt_collection; /* 4 8 */ } ct; /* Collection-type*/ const struct dictionary_vtbl* vtbl; /* 4 8 */ u32 count; /* 4 4 */ u32 threshold; /* 4 4 */ }; /* 16 24 */ typedef struct dictionary_iterator dictionary_iterator; /** * @brief The dictionary iterator. * * The dictionary iterator. * */ struct dictionary_iterator { const struct dictionary_iterator_vtbl* vtbl; dictionary_node* sll; union { btree_iterator as_btree; htbt_iterator as_htbt; } ct; }; /** * @brief Function type called to initialize a dictionary. * * Function type called to initialize a dictionary. * * @param[in] dico a pointer to the dictionary descriptor to initialize. * */ typedef void dictionary_init_method(dictionary* dico); /** * @brief Function type called to destroy a dictionary * * Function type called to destroy a dictionary * * @param[in] dico a pointer to the dictionary descriptor * @param[in] destroy a pointer to a function called for each node of the dictionary in order to delete them. * */ typedef void dictionary_destroy_method(dictionary* dico, dictionary_destroy_record_function destroy); /** * @brief Function type called to destroy a dictionary * * Function type called to destroy a dictionary * * @param[in] dico a pointer to the dictionary descriptor * @param[in] destroyex a pointer to a function called for each node of the dictionary in order to delete them. * @param[in] arg a pointer to an argument that will be passed to the destroyex function * */ typedef void dictionary_destroy_ex_method(dictionary* dico, dictionary_destroy_ex_record_function destroyex, void* arg); /** * @brief Function type called to add a record to a dictionary * * Function type called to add a record to a dictionary * * @param[in] dico a pointer to the dictionary descriptor * @param[in] key the hashcode of the record that will be inserted * @param[in] record_match_data arbitrary data for the compare and create functions * @param[in] compare pointer to a function called to check for duplicates (same hashcode) * @param[in] create pointer to a function called to create the new record * * @return Returns a pointer to the newly created record, or NULL if an error occurred. * */ typedef dictionary_node* dictionary_add_method(dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare, dictionary_data_record_create_function create); /** * @brief Function type called to find a record in a dictionary * * Function type called to find a record in a dictionary * * @param[in] dico a pointer to the dictionary descriptor * @param[in] key the hashcode of the record * @param[in] record_match_data arbitrary data for the compare function * @param[in] compare pointer to a function called to check for duplicates (same hashcode) * * @return Returns a pointer to the record matching the search, or NULL if no record has been found * */ typedef dictionary_node* dictionary_find_method(const dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare); /** * @brief Function type called to find a record in a dictionary * * Function type called to find a record in a dictionary * * @param[in] dico a pointer to the dictionary descriptor * @param[in] key the hashcode of the record * @param[in] record_match_data arbitrary data for the compare function * @param[in] compare pointer to a function called to check for a match * * @return Returns a pointer to a pointer to the record matching the search, or NULL if no record has been found * */ typedef dictionary_node** dictionary_findp_method(const dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare); /** * @brief Function type called to remove a record from a dictionary * * Function type called to remove a record from a dictionary * * @param[in] dico a pointer to the dictionary descriptor * @param[in] key the hashcode of the record that will be inserted * @param[in] record_match_data arbitrary data for the compare function * @param[in] compare pointer to a function called to check for a match * * @return Returns a pointer to a pointer to the record matching the search, or NULL if no record has been found * */ typedef dictionary_node* dictionary_remove_method(dictionary* dico, hashcode key, void* record_match_data, dictionary_data_record_compare_function compare); /** * @brief Function type called to process a record from a dictionary * * Function type called to process a record from a dictionary * * @param[in] dico a pointer to the dictionary descriptor * @param[in] key the hashcode of the record that will be inserted * @param[in] record_match_data arbitrary data for the compare function * @param[in] compare pointer to a function called to check for a match and do whatever operation on the record. * * @return COLLECTION_PROCESS_STOP if the process succeeded * @return COLLECTION_PROCESS_DELETENODE if the process succeeded and the node has been deleted * @return COLLECTION_PROCESS_RETURNERROR if an error occurred * */ typedef ya_result dictionary_process_method(dictionary* dico, hashcode key, void* record_match_data, dictionary_process_record_function compare); /** * @brief Function type called to empty a dictionary * * Function type called to empty a dictionary. * This is a part of the dictionary's mutating feature. * * @param[in] dico a pointer to the dictionary descriptor * @param[in] bucket a pointer to an arbitrary data passed to the bucket_record function (ie: the new dictionary) * @param[in] bucket_record pointer to a function called to take care of the removed record. (ie: add it to another dictionary) * */ typedef void dictionary_empties_method(dictionary* dico, void* bucket, dictionary_bucket_record_function bucket_record); /** * @brief Function type called to fill a dictionary * * Function type called to fill a dictionary * This is a part of the dictionary's mutating feature. * * Note there is no MATCH callback because collisions cannot occur. * (It's used to transfer node from a dictionary to another ... so ...) * * @param[in] dico a pointer to the dictionary descriptor * @param[in] key the hashcode of the node that needs to be added into the dictionary * @param[in] node the node that needs to be added into the dictionary * */ typedef void dictionary_fills_method(dictionary* dico, hashcode key, dictionary_node* node); /** * @brief Function type called to initialize a dictionary iterator * * Function type called to initialize a dictionary iterator * * @param[in] dico a pointer to the dictionary descriptor * @param[in] iter a pointer to the dictionary iterator */ typedef void dictionary_iterator_init_method(const dictionary* dico, dictionary_iterator* iter); /** * @brief Function type called check if the iterator still has items to return * * Function type called check if the iterator still has items to return * * @param[in] iter a pointer to the dictionary iterator * * @return TRUE if calling the dictionary_iterator_next_method will return an item, FALSE otherwise */ typedef bool dictionary_iterator_hasnext_method(dictionary_iterator* dico); /** * @brief Function type called to get the next item of the iterator * * Function type called to get the next item of the iterator * The caller should check for item availability by calling the "hasnext" method. * * @param[in] iter a pointer to the dictionary iterator * * @return A pointer to a pointer to the next item. */ typedef void** dictionary_iterator_next_method(dictionary_iterator* dico); /** * @brief Function type called to initialize a dictionary iterator from a starting point * * Function type called to initialize a dictionary iterator * If the key has not been found the previous or next key is used instead (whatever has been hit last) * * @param[in] dico a pointer to the dictionary descriptor * @param[in] iter a pointer to the dictionary iterator * @param[in] the key to start from. */ //typedef void dictionary_iterator_init_from_method(const dictionary* dico, dictionary_iterator* iter, hashcode key); typedef void dictionary_iterator_init_from_method(const dictionary* dico, dictionary_iterator* iter, const u8 *label); typedef const char * const dictionary_class; /** * @brief The dictionary virtual table * * The dictionary virtual table */ struct dictionary_vtbl { /*dictionary_init_method* dictionary_init_call;*/ dictionary_destroy_method * const dictionary_destroy_call; dictionary_add_method * const dictionary_add_call; dictionary_find_method * const dictionary_find_call; dictionary_findp_method * const dictionary_findp_call; dictionary_remove_method * const dictionary_remove_call; dictionary_process_method * const dictionary_process_call; dictionary_destroy_ex_method * const dictionary_destroy_ex_call; dictionary_iterator_init_method * const dictionary_iterator_init_call; dictionary_iterator_init_from_method * const dictionary_iterator_init_from_call; dictionary_empties_method * const dictionary_empties_call; dictionary_fills_method * const dictionary_fills_call; dictionary_class __class__; }; /** * @brief The dictionary_iterator virtual table * * The dictionary virtual table */ struct dictionary_iterator_vtbl { dictionary_iterator_hasnext_method * const dictionary_iterator_hasnext_call; dictionary_iterator_next_method * const dictionary_iterator_next_call; }; /** * @brief Used to initialize a dictionary * * Used to initialize a dictionary. * This will set the dictionary's initial type. * * @param[in] dico a pointer to the dictionary descriptor * */ void dictionary_init(dictionary* dico); /** * @brief Used to mutate a dictionary * * Used to mutate a dictionary * This will change the dictionary's type to the one adapted for its current * item count. * If dictionary_should_mutate(dico) is FALSE, then this function does nothing. * * @param[in] dico a pointer to the dictionary descriptor * */ void dictionary_mutate(dictionary* dico); /** * * Initialises the iterator so that it has no next items to return * * @param iter */ void dictionary_empty_iterator_init(dictionary_iterator* iter); /** * @brief Checks if a dictionary should be processed by dictionary_mutate * * Checks if a dictionary should be processed by dictionary_mutate * * @return TRUE if and only if the dictionary should be processed by dictionary_mutate */ #define dictionary_should_mutate(dico_) ((dico_)->count>(dico_)->threshold) /** @brief helper macro */ #define dictionary_destroy(dico_, destroy_) (dico_)->vtbl->dictionary_destroy_call((dico_), (destroy_)) /** @brief helper macro */ #define dictionary_destroy_ex(dico_, destroy_, arg_) (dico_)->vtbl->dictionary_destroy_ex_call((dico_), (destroy_), (arg_)) /** @brief helper macro */ #define dictionary_add(dico_, key_, record_match_data_, compare_, create_) (dico_)->vtbl->dictionary_add_call((dico_), (key_), (record_match_data_), (compare_), (create_)) /** @brief helper macro */ #define dictionary_find(dico_, key_, record_match_data_, compare_) (dico_)->vtbl->dictionary_find_call((dico_), (key_), (record_match_data_), (compare_)) /** @brief helper macro */ #define dictionary_findp(dico_, key_, record_match_data_, compare_) (dico_)->vtbl->dictionary_findp_call((dico_), (key_), (record_match_data_), (compare_)) /** @brief helper macro */ #define dictionary_remove(dico_, key_, record_match_data_, compare_) (dico_)->vtbl->dictionary_remove_call((dico_), (key_), (record_match_data_), (compare_)) /** @brief helper macro */ #define dictionary_process(dico_, key_, record_match_data_, compare_) (dico_)->vtbl->dictionary_process_call((dico_), (key_), (record_match_data_), (compare_)) /** @brief helper macro */ #define dictionary_iterator_init(dico_, iter_) (dico_)->vtbl->dictionary_iterator_init_call((dico_), (iter_)) /** @brief helper macro */ #define dictionary_iterator_init_from(dico_, iter_, key_) (dico_)->vtbl->dictionary_iterator_init_from_call((dico_), (iter_), (key_)) /** @brief helper macro */ #define dictionary_iterator_hasnext(iter_) (iter_)->vtbl->dictionary_iterator_hasnext_call((iter_)) /** @brief helper macro */ #define dictionary_iterator_next(iter_) (iter_)->vtbl->dictionary_iterator_next_call((iter_)) /** @brief helper macro */ #define dictionary_empties(dico_,bucket_data_,callback_) (dico_)->vtbl->dictionary_empties_call((dico_),(bucket_data_),(callback_)) /** @brief helper macro */ #define dictionary_fills(dico_,key_,node_) (dico_)->vtbl->dictionary_fills_call((dico_),(key_),(node_)) /** @brief helper macro*/ #define dictionary_size(dico_) ((dico_)->count) /** @brief Checks if a dictionary is not empty * * Checks if a dictionary is not empty * * @return TRUE if and only if the dictionary is not empty */ #define dictionary_notempty(dico_) ((dico_)->count!=0) /** @brief Checks if a dictionary is empty * * Checks if a dictionary is empty * * @return TRUE if and only if the dictionary is empty */ #define dictionary_isempty(dico_) ((dico_)->count==0) #ifdef __cplusplus } #endif #endif /* _dictionary_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/dictionary-node.h0000644000000000000000000000013214505005531024153 xustar000000000000000030 mtime=1695812441.522969012 30 atime=1695812445.799030253 30 ctime=1695812494.895733417 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/dictionary-node.h0000664000374500037450000000516314505005531024122 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Hash-based collection designed to change it's structure to improve speed. * * Hash-based collection designed to change it's structure to improve speed. * * @{ */ #pragma once #include #include #if !DICTIONARY_NODE_MODE /** * @brief All dictionary object/data/nodes MUST and will begin with/like this. * * All dictionary object/data/nodes MUST and will begin with/like this. * The first sizeof(void*) bytes are used for a single-linked list "next" pointer. * */ struct dictionary_node { dictionary_node* next; }; #else union dictionary_node { dictionary_node *next; zdb_rr_label *rr_label; zdb_zone_label *zone_label; }; #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/dnsrdata.h0000644000000000000000000000013214505005531022663 xustar000000000000000030 mtime=1695812441.478968381 30 atime=1695812445.797030225 30 ctime=1695812494.897733446 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/dnsrdata.h0000664000374500037450000001140614505005531022627 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup dnsdb * @brief * * @{ */ #ifndef _DNSRDATA_H #define _DNSRDATA_H #include #ifdef __cplusplus extern "C" { #endif /* * I need: * * NS,MD,MF,CNAME,SOA,MB,MG,MR,PTR,HINFO,MINFO,MX,RP,AFSDB,RT,SIG,PX,NXT,NAPTR,KX,SRV,DNAME,A6,RRSIG,NSEC * ++ ++ ++ +++++ +++ ++ ++ ++ +++ +++++ +++++ ++ ?? ????? ?? ++ +++++ ++++ */ typedef struct dnskey_rdata dnskey_rdata; struct dnskey_rdata { u16 flags; u8 protocol; u8 algorithm; u8* public_key; }; void rdata_to_dnskey(u8* rdata,struct dnskey_rdata* dnskey); struct rrsig_rdata { u16 type_covered; u8 algorithm; u8 labels; u32 original_ttl; u32 signature_expiration; u32 signature_inception; u8* signer_name; u8* signature; }; void rdata_to_rrsig(u8* rdata,struct rrsig_rdata* rrsig); typedef struct soa_rdata soa_rdata; struct soa_rdata { const u8* mname; const u8* rname; u32 serial; u32 refresh; u32 retry; u32 expire; u32 minimum; /* TTL / NTTL */ }; /* rfc3845 */ typedef struct { u8 window_number; u8 bitmap_length; u8* bitmap; /* NOT A NAME */ } nsec_rdata_typebitmap; /* rfc3845 */ struct nsec_rdata { u8* domain_name; nsec_rdata_typebitmap* type_bitmap; }; struct ns_rdata { u8* name; }; struct cname_rdata { u8* name; }; struct dname_rdata { u8* name; }; struct ptr_rdata { u8* name; }; struct mb_rdata { u8* madname; }; struct md_rdata { u8* madname; }; struct mf_rdata { u8* madname; }; struct mg_rdata { u8* madname; }; struct mr_rdata { u8* newname; }; struct mx_rdata { u16 preference; u8* exchange; }; struct hinfo_rdata { u8* cpu; u8* os; }; struct minfo_rdata { u8* rmailbx; u8* emailbx; }; /* rfc2782 */ struct srv_rdata { u16 priority; u16 weight; u16 port; u8* domain_name; }; /* rfc2874 */ struct a6_rdata { u8 prefix_length; u16 address_suffix; u8* prefix_name; }; typedef u64 u48; /* rfc2535 */ struct sig_rdata { u16 type_covered; u8 algorithm; u8 labels; u32 original_ttl; u32 signature_expiration; u32 signature_inception; u16 key_tag; u8* signer_name; u8* signature; /* NOT A NAME */ }; /* rfc2845 */ struct tsig_rdata { u8* domain_name; u48 time_signed; u16 fudge; u16 mac_size; u8* mac; u16 original_id; u16 error; u16 other_len; u8* other_data; }; /* No need to canonize */ struct txt_rdata { char* txt; }; struct a_rdata { u32 address; }; /** rfc1886 */ struct aaaa_rdata { u16 address[8]; }; struct wks_rdata { u32 address; u8 protocol; u8* bitmap; /* NOT A NAME */ }; #ifdef __cplusplus } #endif #endif /* _DNSRECORDS_H */ /* ------------------------------------------------------------ */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/dnssec.h0000644000000000000000000000013214505005531022342 xustar000000000000000030 mtime=1695812441.514968897 30 atime=1695812445.798030239 30 ctime=1695812494.899733474 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/dnssec.h0000664000374500037450000000605414505005531022311 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbdnssec DNSSEC functions * @ingroup dnsdb * @brief * * @{ */ #pragma once /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include #include #include #include #if DNSCORE_HAS_EDDSA_SUPPORT #include #endif #ifdef DNSKEY_ALGORITHM_DUMMY #include #endif #include #include #include #include #if ZDB_HAS_DNSSEC_SUPPORT #ifndef _DNSSEC_C #include extern logger_handle *g_dnssec_logger; #endif #ifdef __cplusplus extern "C" { #endif #define DEFAULT_ENGINE_NAME "openssl" #define DNSSEC_DIGEST_TYPE_SHA1 1 #define DNSSEC_DIGEST_TYPE_SHA256 2 #define DNSSEC_MINIMUM_KEY_SIZE_BYTES ((DNSSEC_MINIMUM_KEY_SIZE+7)/8) #define DNSSEC_MAXIMUM_KEY_SIZE_BYTES ((DNSSEC_MAXIMUM_KEY_SIZE+7)/8) #define ENGINE_PRESET_DELIMITER "," #define ENGINE_COMMAND_DELIMITER ":" ENGINE* dnssec_loadengine(const char *engine_name); void dnssec_unloadengine(ENGINE *engine); #ifdef __cplusplus } #endif #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/dnssec_config.h0000644000000000000000000000013214505005531023667 xustar000000000000000030 mtime=1695812441.528969098 30 atime=1695812445.799030253 30 ctime=1695812494.901733503 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/dnssec_config.h0000664000374500037450000000445414505005531023640 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbdnssec DNSSEC functions * @ingroup dnsdb * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #ifndef _DNSSEC_CONFIG_H #define _DNSSEC_CONFIG_H #if !ZDB_HAS_DNSSEC_SUPPORT #error "Please do not include dnssec_config.h if ZDB_HAS_DNSSEC_SUPPORT is 0 (Not NSEC3 nor NSEC)" #endif #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif #endif /* _DNSSEC_CONFIG_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/dnssec-keystore.h0000644000000000000000000000013214505005531024205 xustar000000000000000030 mtime=1695812441.505968768 30 atime=1695812445.798030239 30 ctime=1695812494.903733532 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/dnssec-keystore.h0000664000374500037450000002710414505005531024153 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @brief * * The dnssec keystore handles loading and updating of keys system-wide. * * It is required for an efficient key management and smart signing. * * It has knowledge of how to find keys for a zone. * It has the responsibility to update the keys when asked. * * Its responsibilities may be extended to notify the system about timings. * * @{ */ #pragma once /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include #include #include #include #if !ZDB_HAS_DNSSEC_SUPPORT #error "Please do not include dnssec_keystore.h if ZDB_HAS_DNSSEC_SUPPORT is 0 (Not NSEC3 nor NSEC)" #endif #ifdef __cplusplus extern "C" { #endif struct dnssec_keystore; /** * * Initialises the keystore * * @param ks */ void dnssec_keystore_init(); /** * Adds the knowledge of domain<->path * Set path to NULL to use the default value * * Can overwrite a previous value * * @param ks * @param domain * @param path */ void dnssec_keystore_add_domain(const u8 *domain, const char *path); /** * Remove the knowledge of domain<->path * * @param ks * @param domain * @param path */ void dnssec_keystore_remove_domain(const u8 *domain, const char *path); /** * * Add a key to the keystore, do nothing if a key with the same tag and algorithm is * in the keystore for that domain already * * RC ok * * @param ks * @param key * * @return TRUE iff the key was added */ bool dnssec_keystore_add_key(dnssec_key *key); /** * * Replace a key from the keystore, release the replaced key * * RC ok * * @param ks * @param key * * @return TRUE iff the key was added */ bool dnssec_keystore_replace_key(dnssec_key *key); /** * * Removes a key from the keystore * Does not releases the key * * RC ok * * @param ks * @param key * * @return the instance of the key from the keystore, or NULL if the key was not found */ dnssec_key *dnssec_keystore_remove_key(dnssec_key *key); /** * Removes a key from the keystore, if possible. * Renames both key files adding suffix of the creation time plus bak * Does not return any error code as it's a best effort kind of thing. * * @param key */ void dnssec_keystore_delete_key(dnssec_key *key); /** * * Retrieves a key from the keystore * * RC ok * * @param ks * @param domain * @param tag * @return the key or NULL if it does not exist */ dnssec_key *dnssec_keystore_acquire_key_from_fqdn_with_tag(const u8 *domain, u16 tag); /** * Returns the nth key from the domain or NULL if no such key exist * * RC ok * * @return a dnskey */ dnssec_key *dnssec_keystore_acquire_key_from_fqdn_by_index(const u8 *domain, int idx); /** * Returns TRUE iff the domain has a KSK. */ bool dnssec_keystore_has_any_ksk(const u8 *domain); /** * Returns TRUE iff the domain has an activaed KSK loaded. */ bool dnssec_keystore_has_activated_ksk(const u8 *domain, time_t attime); bool dnssec_keystore_has_activated_zsk(const u8 *domain, time_t attime); /** * Returns TRUE iff the domain has an activaed KSK with its private part loaded. */ bool dnssec_keystore_has_usable_ksk(const u8 *domain, time_t attime); bool dnssec_keystore_has_usable_zsk(const u8 *domain, time_t attime); /** * Returns true iff the key for theddomain+algorithm+tag is active at 'now' * * @param domain * @param algorithm * @param tag * @param now * * @return */ bool dnssec_keystore_is_key_active(const u8 *domain, u8 algorithm, u16 tag, time_t now); /** * Acquires all the currently activated keys and store them to the appropriate * KSK or ZSK collection ptr_vector. * * @param domain * @param ksks * @param zsks * @return */ int dnssec_keystore_acquire_activated_keys_from_fqdn_to_vectors(const u8 *domain, ptr_vector *ksks, ptr_vector *zsks); /** * Acquires all the currently publishable keys and store them to the appropriate * KSK or ZSK collection ptr_vector. * * If no publish/delete field is available, uses active/inactive fields instead. * No fields means no action. * * @param domain * @param ksks * @param zsks * @return */ int dnssec_keystore_acquire_published_keys_from_fqdn_to_vectors(const u8 *domain, ptr_vector *ksks, ptr_vector *zsks); /** * Acquires all the keys that should be published and deleted and store them to the appropriate collection ptr_vector. * * If no publish/delete field is available, uses active/inactive fields instead. * No fields means no action. * * @param domain * @param ksks * @param zsks * @return */ int dnssec_keystore_acquire_publish_delete_keys_from_fqdn_to_vectors(const u8 *domain, ptr_vector *publish_keys, ptr_vector *delete_keys); /** * Releases all the keys from a vector. * * @param keys */ void dnssec_keystore_release_keys_from_vector(ptr_vector *keys); /** * * Retrieves a key from the keystore * * RC ok * * @param ks * @param domain * @param tag * @return */ dnssec_key *dnssec_keystore_acquire_key_from_name(const char *domain, u16 tag); /** * Returns the nth key from the domain or NULL if no such key exist * * RC ok * * @return a dnskey */ dnssec_key *dnssec_keystore_acquire_key_from_name_by_index(const char *domain, int idx); /** * * (Re)loads keys found in the paths of the keystore * * @param ks * @return */ ya_result dnssec_keystore_reload(); /** * * (Re)loads keys found in the path of the keystore for the specified domain * * @param fqdn * @return */ ya_result dnssec_keystore_reload_domain(const u8 *fqdn); /** * Adds all the valid keys of the domain in the keyring * * @param fqdn the domain name * @param at_time the epoch at which the test is done ie: time(NULL) * @param kr the target keyring * * @return the number of keys effectively added in the keyring */ u32 dnssec_keystore_add_valid_keys_from_fqdn(const u8 *fqdn, time_t at_time, struct dnskey_keyring *kr); //////////////////////////////////////////////////////// void dnssec_keystore_resetpath(); const char *dnssec_keystore_getpath(); void dnssec_keystore_setpath(const char* path); /* ya_result dnssec_keystore_add(dnssec_key* key); dnssec_key* dnssec_keystore_get(u8 algorithm,u16 tag,u16 flags,const char *origin); dnssec_key* dnssec_keystore_remove(u8 algorithm,u16 tag,u16 flags,const char *origin); */ void dnssec_keystore_destroy(); struct dnskey_smart_fields_s { u32 created_epoch; u32 publish_epoch; u32 activate_epoch; u32 deactivate_epoch; u32 unpublish_epoch; u32 fields; }; typedef struct dnskey_smart_fields_s dnskey_smart_fields_t; /** * Generates a private key, store in the keystore * The caller is expected to create a resource record with this key and add it to the owner. * * @param algorithm the DNSKEY algorithm * @param size the size of the key. Not all algoritms are taking it into account. * @param flags the DNSKEY flags * @param origin the domain of the key * @param smart_fields all the smart fields to set, don't forget to set the "fields" field to tell which fields are valid * @param out_key the generated key * @returns an error code * */ ya_result dnssec_keystore_new_key(u8 algorithm, u32 size, u16 flags, const char *origin, dnskey_smart_fields_t *smart_fields, dnssec_key **out_key); /** * Loads a public key from the rdata, store in the keystore, then sets out_key to point to it * * RC ok * * @param rdata * @param rdata_size * @param origin * @param out_key * @return */ ya_result dnssec_keystore_load_public_key_from_rdata(const u8 *rdata, u16 rdata_size, const u8 *origin, dnssec_key **out_key); /** * Loads a private key from the disk or the keystore, then returns it. * NOTE: If the key already existed as a public-only key, the public version is released. * * RC ok * * @param algorithm * @param tag * @param flags * @param origin * @param out_key * @return SUCCESS if a key was loaded, 1 if the key was already loaded, or an error code */ ya_result dnssec_keystore_load_private_key_from_rdata(const u8 *rdata, u16 rdata_size, const u8 *fqdn, dnssec_key **out_key); /** * Loads a private key from the disk or the keystore, then returns it. * NOTE: If the key already existed as a public-only key, the public version is released. * * RC ok * * @param algorithm * @param tag * @param flags * @param origin * @param out_key * @return SUCCESS if a key was loaded, 1 if the key was already loaded, or an error code */ ya_result dnssec_keystore_load_private_key_from_parameters(u8 algorithm, u16 tag, u16 flags, const u8 *fqdn, dnssec_key **out_key); ya_result dnssec_keystore_get_key_path(dnssec_key* key, char *buffer, size_t buffer_size, bool private); /// does not remove the key from the keyring (so only call this if you know what you are doing) ya_result dnssec_keystore_delete_key_files(dnssec_key *key); /** Writes the key into g_keystore_path (which should be changed to whatever is the right path of the key */ ya_result dnssec_keystore_store_private_key(dnssec_key *key); /** Writes the key into g_keystore_path (which should be changed to whatever is the right path of the key */ ya_result dnssec_keystore_store_public_key(dnssec_key *key); /* void dnssec_key_addrecord_to_zone(dnssec_key* key, zdb_zone* zone); */ dnssec_key *dnssec_keystore_acquire_key_from_fqdn_at_index(const u8 *domain, int index); /** * Returns all the active keys, chained in a single linked list whose nodes need to be freed, * * @param zone * @param out_keys * @param out_ksk_count * @param out_zsk_count * @return */ ya_result zdb_zone_get_active_keys(zdb_zone *zone, dnssec_key_sll **out_keys, int *out_ksk_count, int *out_zsk_count); /** * * @param keys */ void zdb_zone_release_active_keys(dnssec_key_sll *keys); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/htable.h0000644000000000000000000000013114505005531022321 xustar000000000000000030 mtime=1695812441.496968639 30 atime=1695812445.798030239 29 ctime=1695812494.90573356 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/htable.h0000664000374500037450000001020614505005531022263 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Hash-Table structure and functions. * * Implementation of the Hash-Table structure and functions. * It can be configured to be thread-safe. (4 modes) * * It is used in the hash-table of balanced trees structure. (htbt) * * Mutex support has been removed the 2009/02/24. * * @{ */ #ifndef _HTABLE_H #define _HTABLE_H #define HTABLE_USE_MERSENE #ifdef __cplusplus extern "C" { #endif #define HTABLE_TAG 0x454c42415448 /* "HTABLE" */ typedef struct { void* data; /* 4 or 8 bytes (32 or 64 bits systems) */ } htable_entry; /* => 12 or 16 bytes (32 or 64 bits systems) */ /** @brief Allocates an hash table of the pre-defined size * * Allocates an hash table of the pre-defined size * * @return A pointer to the htable or NULL if an error occurred */ htable_entry* htable_alloc(); /** @brief Frees an htable * * Frees an htable * * @param[in] table a pointer to the htable to free * */ void htable_free(htable_entry* table); #if defined(HTABLE_USE_MERSENE) #define NOHASHTBL 0 #define MERSENE_1 3 #define MERSENE_2 7 #define MERSENE_3 31 #define MERSENE_4 127 #define MERSENE_5 8191 #define MERSENE_6 131071 #define MERSENE_7 524287 #define MERSENE_8 2147483647 /* This is, of course, not an option */ /* Given the statistics, MERSENE_7 is by far the best choice */ #define DEFAULT_HTABLE_SIZE (MERSENE_7+1) /** @brief Retrieve the htable entry for a given hash * * Retrieve the htable entry for a given hash. * This version uses a bitmask with a mersene prime. * * @param[in] table a pointer to the htable * @param[in] hash the hash value to look for. * */ #define htable_get(table,hash) ((table)[(hash)&(DEFAULT_HTABLE_SIZE-1)]) #else /* MODULO */ /* 1061 1063 */ /* 10007 10009 */ #define DEFAULT_HTABLE_SIZE 10007 /** @brief Retrieve the htable entry for a given hash * * Retrieve the htable entry for a given hash. * This version uses a modulo with a prime. * * @param[in] table a pointer to the htable * @param[in] hash the hash value to look for. * */ #define htable_get(table,hash) ((table)[(hash)%DEFAULT_HTABLE_SIZE]) #endif #ifdef __cplusplus } #endif #endif /* _HTABLE_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/htbt.h0000644000000000000000000000013114505005531022023 xustar000000000000000029 mtime=1695812441.51096884 30 atime=1695812445.798030239 30 ctime=1695812494.907733589 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/htbt.h0000664000374500037450000002277214505005531022000 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Hash-Table of Balanced trees structure and functions. * * Implementation of the Hash-Table of Balanced trees structure and functions. * An hashtable holding htbt collections. * * The idea behind this structure is that, although balanced trees are FAST, * the deeper, the slower they are. * * Another important thing is that btrees are accessed by a hash and thus, can collide. * * This structure is thus used for the top-level balanced tree in order to * * _ divide the top-level domains into smaller, faster trees. * _ reduce the number of potential collisions in said trees. * * @{ */ #ifndef _HHTBT_H #define _HHTBT_H /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include #include #include #ifdef __cplusplus extern "C" { #endif /** * This macro is the transformation on the hash to distribute the collided hashes * on different btree. * * To work as intended (potentially split collisions) it has to be generated with * another formula than the one used for the BT. * * The idea is: * * H(x) = H(y) => collision * h(x) != h(y) => no collision anymore * * h(x) must not be a function of H(x) * * */ #define HTBT_HASH_TRANSFORM(x) (x) typedef htable_entry* htbt; typedef btree_node htbt_node; /** @brief Initializes the collection * * Initializes the collection. * Basically : *collection=NULL; * * @param[in] collection the collection to initialize * */ htbt htbt_create(); void htbt_init(htbt* collection); #if !ZDB_INLINES_HTBT_FIND /** @brief Finds a node in the collection. * * Finds a node in the collection. * * THIS CALL IS NOT THREAD SAFE. * * @param[in] collection the collection to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node or NULL if there is no such node. */ void* htbt_find(htbt collection, hashcode obj_hash); /** @brief Finds a node in the collection. * * Finds a node in the collection. * * THIS CALL IS NOT THREAD SAFE. * * @param[in] collection the collection to search in * @param[in] obj_hash the hash to find * * @return A pointer to a pointer to the node or NULL if there is no such node. */ void** htbt_findp(htbt collection, hashcode obj_hash); /** @brief Inserts data into the collection. * * Insert datat into the collection. * The caller will then have to use the returned void** to set his data. * * THIS CALL IS NOT THREAD SAFE * * @param[in] collection the collection where the insertion should be made * @param[in] obj_hash the hash associated to the node * * @return A pointer to the data field associated to the hash, or NULL (out of memory) */ void** htbt_insert(htbt collection, hashcode obj_hash); /** @brief Deletes a node from the collection. * * Deletes a node from the collection. * * THIS CALL IS NOT THREAD SAFE * * @param[in] collection the collection from which the delete will be made * @param[in] obj_hash the hash associated to the node to remove * * @return The node associated to the hash */ void* htbt_delete(htbt collection, hashcode obj_hash); #endif /** @brief Destroys the collection. * * Destroys the collection. * No other thread should access it, obiviously. * * @param[in] collection the collection to destroy */ void htbt_destroy(htbt* collection); typedef struct htbt_iterator { htbt table; s32 count; btree_iterator iter; } htbt_iterator; void htbt_iterator_init(htbt tree, htbt_iterator* iter); //void htbt_iterator_init_from(htbt collection, htbt_iterator* iter, hashcode obj_hash); btree_node *htbt_iterator_init_from(htbt collection, htbt_iterator* iter, hashcode obj_hash); //avl_node *htbt_iterator_init_from(htbt collection, htbt_iterator* iter, const u8 *label); #if !ZDB_INLINES_HTBT_FIND bool htbt_iterator_hasnext(htbt_iterator* iter); #endif void** htbt_iterator_next(htbt_iterator* iter); htbt_node* htbt_iterator_next_node(htbt_iterator* iter); #if ZDB_INLINES_HTBT_FIND /** @brief Finds a node in the collection. * * Finds a node in the collection. * * THIS CALL IS NOT THREAD SAFE. * * @param[in] collection the collection to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node or NULL if there is no such node. */ static inline void* htbt_find(htbt collection, hashcode obj_hash) { /* compute the table hash from the object hash */ hashcode table_hash = HTBT_HASH_TRANSFORM(obj_hash); /* grab the entry for the given hash */ htable_entry* entry = &htable_get(collection, table_hash); /* search the tree of the entry */ return btree_find((btree*) & entry->data, obj_hash); } /** @brief Finds a node in the collection. * * Finds a node in the collection. * * THIS CALL IS NOT THREAD SAFE. * * @param[in] collection the collection to search in * @param[in] obj_hash the hash to find * * @return A pointer to a pointer to the node or NULL if there is no such node. */ static inline void** htbt_findp(htbt collection, hashcode obj_hash) { /* compute the table hash from the object hash */ hashcode table_hash = HTBT_HASH_TRANSFORM(obj_hash); /* grab the entry for the given hash */ htable_entry* entry = &htable_get(collection, table_hash); /* search the tree of the entry */ return btree_findp((btree*) & entry->data, obj_hash); } /** @brief Inserts data into the collection. * * Insert datat into the collection. * The caller will then have to use the returned void** to set his data. * * THIS CALL IS NOT THREAD SAFE * * @param[in] collection the collection where the insertion should be made * @param[in] obj_hash the hash associated to the node * * @return A pointer to the data field associated to the hash, or NULL (out of memory) */ static inline void** htbt_insert(htbt collection, hashcode obj_hash) { /* compute the table hash from the object hash */ hashcode table_hash = HTBT_HASH_TRANSFORM(obj_hash); /* grab the entry for the given hash */ htable_entry* entry = &htable_get(collection, table_hash); /* search the tree of the entry */ void** pdata = btree_insert((btree*) & entry->data, obj_hash); return pdata; } /** @brief Deletes a node from the collection. * * Deletes a node from the collection. * * THIS CALL IS NOT THREAD SAFE * * @param[in] collection the collection from which the delete will be made * @param[in] obj_hash the hash associated to the node to remove * * @return The node associated to the hash */ static inline void* htbt_delete(htbt collection, hashcode obj_hash) { /* compute the table hash from the object hash */ hashcode table_hash = HTBT_HASH_TRANSFORM(obj_hash); /* grab the entry for the given hash */ htable_entry* entry = &htable_get(collection, table_hash); /* search the tree of the entry */ void** pdata = btree_delete((btree*) & entry->data, obj_hash); return pdata; } static inline bool htbt_iterator_hasnext(htbt_iterator* iter) { if(btree_iterator_hasnext(&iter->iter)) { return TRUE; } else { if(iter->count > 0) { for(; (iter->count > 0) && (iter->table->data == NULL); iter->count--, iter->table++); if(iter->count > 0) { btree_iterator_init((btree)iter->table->data, &iter->iter); iter->table++; iter->count--; return TRUE; } } return FALSE; } } #endif #ifdef __cplusplus } #endif #endif /* _Hhtbt_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/journal.h0000644000000000000000000000013214505005531022535 xustar000000000000000030 mtime=1695812441.513968883 30 atime=1695812445.798030239 30 ctime=1695812494.909733618 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/journal.h0000664000374500037450000002540014505005531022500 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnsdb * @brief * * Journal API * * * @{ */ #ifndef JOURNAL_H #define JOURNAL_H #if !ZDB_JOURNAL_CODE /* * Direct usage of journal is risky. So now all allowed code (c files only) have : * #define ZDB_JOURNAL_CODE 1 before the includes. */ #error "Please do not include dnsdb/journal.h directly." #endif #define JOURNAL_IX_ENABLED 0 #define JOURNAL_CJF_ENABLED 0 #define JOURNAL_JNL_ENABLED 1 #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * We should handle multiple formats. So the journal can improve and the older formats still be loaded * At some point we could also register journal formats but it does not seems important for now. */ typedef struct journal journal; ya_result journal_init(u32 mru_size); void journal_finalize(); /** * * The default part for XFR'ing * * @param path */ void journal_set_xfr_path(const char *path); const char* journal_get_xfr_path(); /** * Opens (or create) the journal for the zone * * @param jh pointer will be set to the journal handling structure * @param origin origin of the zone * @param create create an empty journal if none has been found * * @return an error code */ typedef ya_result journal_open_method(journal **jh, u8* origin, bool create); typedef const char *journal_get_format_name_method(); typedef u32 journal_get_format_version_method(); /* * The stream is : [SOA- RR- RR- RR- SOA+ RR+ RR+ RR+]+ */ typedef ya_result journal_append_ixfr_stream_method(journal *jh, input_stream *ixfr_wire_is); /** * rr can be NULL */ typedef ya_result journal_get_ixfr_stream_at_serial_method(journal *jh, u32 serial_from, input_stream *out_input_stream, dns_resource_record* rr); typedef ya_result journal_get_first_serial_method(journal *jh, u32 *serial); typedef ya_result journal_get_last_serial_method(journal *jh, u32 *serial); typedef ya_result journal_get_serial_range_method(journal *jh, u32 *serial_start, u32 *serial_end); typedef ya_result journal_truncate_to_size_method(journal *jh, u32 size_); typedef ya_result journal_truncate_to_serial_method(journal *jh, u32 serial_); typedef ya_result journal_reopen_method(journal *jh); typedef void journal_flush_method(journal *jh); typedef ya_result journal_close_method(journal *jh); typedef ya_result journal_get_domain_method(journal *jh, u8 *out_domain); typedef const u8 *journal_get_domain_const_method(const journal *jh); typedef void journal_destroy_method(journal *jh); typedef void journal_log_dump_method(journal *jh); typedef void journal_minimum_serial_update_method(journal *jh, u32 stored_serial); typedef void journal_maximum_size_update_method(journal *jh, u32 maximum_size); typedef void journal_limit_size_update_method(journal *jh, u32 maximum_size); //typedef void journal_link_zone_method(journal *jh, zdb_zone *zone); struct journal_vtbl { journal_get_format_name_method *get_format_name; // returns a const char* journal_get_format_version_method *get_format_version; // returns the version journal_reopen_method *reopen; // opens the file, if it has temporarily been closed journal_flush_method *flush; // flushes to storage journal_close_method *close; // closes the file journal_append_ixfr_stream_method *append_ixfr_stream; // appends IXFR (without the first/last SOA) to the journal journal_get_ixfr_stream_at_serial_method *get_ixfr_stream_at_serial;// returns a stream starting at serial SN journal_get_first_serial_method *get_first_serial; // returns the first serial in the journal journal_get_last_serial_method *get_last_serial; // returns the last serial in the journal journal_get_serial_range_method *get_serial_range; // returns both the first and last serials in the journal journal_truncate_to_size_method *truncate_to_size; // truncates the journal size (probably never used) journal_truncate_to_serial_method *truncate_to_serial; // truncates the journal to a serial (probably never used) journal_log_dump_method *log_dump; // dumps the status of the journal on the database logger journal_get_domain_method *get_domain; // copies the domain to the output buffer journal_destroy_method *destroy; // destroys the journal at the first opportunity journal_get_domain_const_method *get_domain_const; // copies the domain to the output buffer journal_minimum_serial_update_method *minimum_serial_update; // stores the minimum serial the zone must contain (continuity from the zone) journal_maximum_size_update_method *maximum_size_update; // updates the maximum size of the journal, applied at the earliest convenience journal_limit_size_update_method *limit_size_update; // updates the limit size of the journal, applied at the earliest convenience const char* __class__; }; struct journal { volatile struct journal_vtbl *vtbl; volatile list_dl_node_s mru_node; // to list the journals by most to least recently used volatile int rc; volatile unsigned int _forget:1,_mru:1; /* The journal is not like a stream, it's a full standalone entity always returned as a pointer. * So the handler can do whatever it wants after "mru" */ }; #define journal_get_format_name(j_) (j_)->vtbl->get_format_name() #define journal_get_format_version(j_) (j_)->vtbl->get_format_version() //#define journal_close(j_) (j_)->vtbl->close(j_) #define journal_append_ixfr_stream(j_, ixfr_wire_is_) (j_)->vtbl->append_ixfr_stream((j_), (ixfr_wire_is_)) #define journal_get_ixfr_stream_at_serial(j_, serial_form_, out_input_stream_, \ dns_rr_) (j_)->vtbl->get_ixfr_stream_at_serial((j_), (serial_form_), (out_input_stream_), (dns_rr_)) #define journal_get_first_serial(j_, serial_) (j_)->vtbl->get_first_serial((j_),(serial_)) #define journal_get_last_serial(j_, serial_) (j_)->vtbl->get_last_serial((j_),(serial_)) #define journal_get_serial_range(j_, serial_start_, serial_end_) (j_)->vtbl->get_serial_range((j_),(serial_start_),(serial_end_)) #define journal_truncate_to_size(j_, size_) (j_)->vtbl->truncate_to_size((j_), (size_)) #define journal_truncate_to_serial(j_, serial_) (j_)->vtbl->truncate_to_serial((j_), (serial_)) //#define journal_link_zone(j_, zone_) (j_)->vtbl->link_zone((j_), (zone_)) #define journal_get_domain_const(j_) (j_)->vtbl->get_domain_const((j_)) /** * * Returns the journal for a loaded zone. * * DO NOT USE THE JOURNAL WITHOUT OPENING IT. * ie: TAKING IT DIRECTLY FROM THE ZONE NODE IN THE DATABASE. * IT ***WILL*** RACE-FAIL !!! * * @param jhp * @param zone * @param workingdir * @param create * @return */ ya_result journal_acquire_from_fqdn_ex(journal **jhp, const u8 *origin, bool create); ya_result journal_acquire_from_fqdn(journal **jhp, const u8 *origin); ya_result journal_acquire_from_zone_ex(journal **jhp, zdb_zone *zone, bool create); ya_result journal_acquire_from_zone(journal **jhp, zdb_zone *zone); void journal_acquire(journal *jh); /** * * Decrement the reference count and potentially closes it if it reaches 0 * * @param jh * @return */ void journal_release(journal *jh); /** * Returns the last available serial of a journal for a zone. * Does this by opening the journal. * This function should NOT be used for a loaded zone. */ ya_result journal_last_serial(const u8 *origin, u32 *serialp); ya_result journal_serial_range(const u8 *origin, u32 *serialfromp, u32 *serialtop); /* * Empties/deletes a journal * Does this by opening the journal and calling a truncate to size 0 * This function should NOT be used for a loaded zone. */ ya_result journal_truncate(const u8 *origin); /** * Returns the last SOA TTL + RDATA * * @param jh the journal * @param rr an initialised resource record * * @return an error code */ ya_result journal_get_last_soa(journal *jh, dns_resource_record *rr); /** * Flushes, closes and destroys all currently unused journals (from memory) */ void journal_close_unused(); /** * Logs the current status of the journaling system */ void journal_log_status(); #ifdef __cplusplus } #endif #endif /* JOURNAL_H */ /* @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/journal_ix.h0000644000000000000000000000013214505005531023235 xustar000000000000000030 mtime=1695812441.489968539 30 atime=1695812445.798030239 30 ctime=1695812494.911733646 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/journal_ix.h0000664000374500037450000000413014505005531023175 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #ifndef JOURNAL_IX_H #define JOURNAL_IX_H #include #ifdef __cplusplus extern "C" { #endif ya_result journal_ix_open(journal **jh, const u8* origin, const char *workingdir, bool create); #ifdef __cplusplus } #endif #endif /* JOURNAL_IX_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/journal-jnl.h0000644000000000000000000000013214505005531023316 xustar000000000000000030 mtime=1695812441.495968625 30 atime=1695812445.798030239 30 ctime=1695812494.913733675 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/journal-jnl.h0000664000374500037450000000553614505005531023271 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #ifdef __cplusplus extern "C" { #endif // Internal function, this is probably not the one you want to use. ya_result journal_jnl_open_file(journal **jhp, const char *filename, const u8* origin, bool create); /** * The caller guarantees not to call this on an already opened journal * * Should not be called directly (only by journal_* functions. * * Opens or create a journal handling structure. * If the journal did not exist, the structure is returned without a file opened * * @param jh * @param origin * @param workingdir * @param create * * @return */ ya_result journal_jnl_open(journal **jh, const u8 *origin, const char *workingdir, bool create); void journal_jnl_finalize(); /** * This function is only meant for debugging purposes. * Please do not use it for anything else but getting the pointer value. * Do not try to use the pointer itself. */ journal* journal_jnl_input_stream_get_journal(input_stream* stream); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/journal-cjf.h0000644000000000000000000000013214505005531023275 xustar000000000000000030 mtime=1695812441.487968511 30 atime=1695812445.797030225 30 ctime=1695812494.915733704 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/journal-cjf.h0000664000374500037450000000536714505005531023252 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #ifdef __cplusplus extern "C" { #endif #if JOURNAL_CJF_ENABLED // Internal function, this is probably not the one you want to use. ya_result journal_cjf_open_file(journal **jhp, const char *filename, const u8* origin, bool create); /** * The caller guarantees not to call this on an already opened journal * * Should not be called directly (only by journal_* functions. * * Opens or create a journal handling structure. * If the journal did not exist, the structure is returned without a file opened * * @param jh * @param origin * @param workingdir * @param create * * @return */ ya_result journal_cjf_open(journal **jh, const u8 *origin, const char *workingdir, bool create); void journal_cjf_finalize(); #else ya_result journal_cjf_ro_open_file(journal **jhp, const char *filename, const u8* origin, bool create); #endif #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/journal-cjf-common.h0000644000000000000000000000013214505005531024563 xustar000000000000000030 mtime=1695812441.479968396 30 atime=1695812445.797030225 30 ctime=1695812494.917733732 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/journal-cjf-common.h0000664000374500037450000001752114505005531024533 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #define ZDB_JOURNAL_CODE 1 #define JOURNAL_CJF 1 #include #include #include #include #include #ifdef CJF_HEADER_SIZE #error "CJF_HEADER_SIZE already defined" #endif #include /* * MAGIC 'JCS' 0 * offset to next (0 until the section is closed and followed by a new one) * list of last-serial + file_offset */ #define CJF_IDXT_MAGIC MAGIC4('I','D','X','T') #define JOURNAL_CFJ_FLAGS_OTHER_ENDIAN 0x8000 // journal endian is different #define JOURNAL_CFJ_FLAGS_MY_ENDIAN 0x0080 // journal endian is the same #define JOURNAL_CFJ_FLAGS_NOT_EMPTY 0x0001 // journal contains pages #define JOURNAL_CFJ_FLAGS_DIRTY 0x0002 // journal needs flushing #define JOURNAL_CFJ_FLAGS_UNINITIALISED 0x0004 struct cjf_header // Cyclic Journal File { u32 magic_plus_version; u32 serial_begin; u32 serial_end; u32 first_index_offset; // PAGE u32 table_index_offset; // IDXT // u32 last_soa_offset; // record u32 last_page_offset_next; // the byte after the last PAGE on the chain ends u16 flags; u8 __end_of_struct__; }; typedef struct cjf_header cjf_header; #define CJF_HEADER_REAL_SIZE offsetof(cjf_header,__end_of_struct__) /* #if CJF_HEADER_SIZE != CJF_HEADER_REAL_SIZE #error "CJF_HEADER_SIZE != CJF_HEADER_REAL_SIZE" #endif */ /* * PAGE * * Serial Number Stream Offset * * The table of serials streams (IXFR) and their offset * The value stored is of the serial ending the IXFR */ #define CJF_CJF0_MAGIC MAGIC4('C','J','F', 0x20) // ver 2.0 #define CJF_HEADER_SIZE 30 #ifndef MODULE_MSG_HANDLE extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #endif struct jnl_page { u32 file_offset; // position in the file u32 count; // number of updates u32 size; // size is fixed to CJF_SECTION_INDEX_SLOT_COUNT u32 serial_start; // first serial in this section. Could probably be lost if not for debugging u32 serial_end; // last serial in this section u32 records_limit; // starts at file_offset (position of the PAGE in the file) + CJF_SECTION_INDEX_SLOT_COUNT * 8 (4KB) u32 file_offset_limit; // if the section is about to break this limit, something has to be done. ie: // _ resynchronise serials in the file // _ write the zone to disk }; typedef struct jnl_page jnl_page; struct journal_cjf; struct journal_cjf_idxt_tbl_header { u32 magic; u16 size; }; typedef struct journal_cjf_idxt_tbl_header journal_cjf_idxt_tbl_header; #define JCJFITI_TAG 0x495449464a434a struct journal_cjf_idxt_tbl_item { u32 last_serial; u32 file_offset; }; typedef struct journal_cjf_idxt_tbl_item journal_cjf_idxt_tbl_item; struct journal_cjf_idxt { s16 count; s16 first; s16 size; bool dirty; bool marked; journal_cjf_idxt_tbl_item *entries; }; typedef struct journal_cjf_idxt journal_cjf_idxt; struct journal_cjf { /* common points with journal base */ volatile struct journal_vtbl *vtbl; volatile list_dl_node_s mru_node; volatile int rc; volatile unsigned int _forget:1,_mru:1; /* ******************************* */ journal_cjf_idxt idxt; jnl_page last_page; // current page u32 serial_begin; u32 serial_end; u32 first_page_offset; u32 page_table_file_offset; u32 last_soa_offset; u32 file_maximum_size; file_pool_file_t file; shared_group_mutex_t mtx; u16 flags; u8 *origin; // to not rely on zone char *journal_file_name; }; typedef struct journal_cjf journal_cjf; void log_debug_jnl(journal_cjf *jnl, const char *prefix); void journal_cjf_header_flush(journal_cjf *jnl); void journal_cjf_remove_first_page(journal_cjf *jnl); static inline u32 journal_cjf_get_last_page_offset_limit(journal_cjf *jnl) { return jnl->last_page.file_offset_limit; } static inline u32 journal_cjf_get_last_page_first_available_byte_offset(journal_cjf *jnl) { return jnl->last_page.records_limit; } static inline u32 journal_cjf_get_last_page_has_room_left(journal_cjf *jnl) { return jnl->last_page.file_offset_limit >= jnl->last_page.records_limit; } static inline s64 journal_cjf_get_last_page_available_space_left(journal_cjf *jnl) { s64 to = (s64)jnl->last_page.file_offset_limit; s64 from = (s64)jnl->last_page.records_limit; s64 ret = MAX(to - from, 0); return ret; } static inline u32 journal_cjf_maximum_size(journal_cjf *jnl) { return jnl->file_maximum_size; } static inline bool journal_cjf_has_flag(journal_cjf *jnl, u16 bits) { return (jnl->flags & bits) == bits; } static inline void journal_cjf_set_flag(journal_cjf *jnl, u16 bits) { jnl->flags |= bits; } static inline void journal_cjf_clear_flag(journal_cjf *jnl, u16 bits) { jnl->flags &= ~bits; } static inline void journal_cjf_set_dirty(journal_cjf *jnl) { journal_cjf_set_flag(jnl, JOURNAL_CFJ_FLAGS_DIRTY); } static inline bool journal_cjf_is_dirty(journal_cjf *jnl) { bool ret = journal_cjf_has_flag(jnl, JOURNAL_CFJ_FLAGS_DIRTY); return ret; } static inline void journal_cjf_clear_dirty(journal_cjf *jnl) { journal_cjf_clear_flag(jnl, JOURNAL_CFJ_FLAGS_DIRTY); } static inline void journal_cjf_set_empty(journal_cjf *jnl) { journal_cjf_clear_flag(jnl, JOURNAL_CFJ_FLAGS_NOT_EMPTY); } static inline void journal_cjf_clear_empty(journal_cjf *jnl) { journal_cjf_set_flag(jnl, JOURNAL_CFJ_FLAGS_NOT_EMPTY); } static inline bool journal_cjf_isempty(journal_cjf *jnl) { bool ret = !journal_cjf_has_flag(jnl, JOURNAL_CFJ_FLAGS_NOT_EMPTY); return ret; } static inline bool journal_cjf_is_my_endian(journal_cjf *jnl) { bool ret = journal_cjf_has_flag(jnl, JOURNAL_CFJ_FLAGS_MY_ENDIAN); return ret; } yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/journal-cjf-idxt.h0000644000000000000000000000013214505005531024243 xustar000000000000000030 mtime=1695812441.504968754 30 atime=1695812445.798030239 30 ctime=1695812494.919733761 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/journal-cjf-idxt.h0000664000374500037450000000745214505005531024215 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include void journal_cjf_idxt_flush(journal_cjf *jnl); const journal_cjf_idxt_tbl_item *journal_cjf_idxt_get_entry(const journal_cjf *jnl, s16 index); /** * * Returns the last serial number value at index in the IDXT * * @param jnl * @param index * @return */ u32 journal_cjf_idxt_get_last_serial(const journal_cjf *jnl, s16 index); /** * * Returns the file offset value at index in the current IDXT * * @param jnl * @param index * @return */ u32 journal_cjf_idxt_get_file_offset(const journal_cjf *jnl, s16 index); /** * Appends an PAGE after this one * * @param jnl */ void journal_cjf_idxt_append_page(journal_cjf *jnl); /** * Updates the value of the last serial at current position in the PAGE * * @param jnl * @param last_serial */ void journal_cjf_idxt_update_last_serial(journal_cjf *jnl, u32 last_serial); /** * * Flushes the IDXT to disk if needed, then destroys the structure content. * * @param jnl */ void journal_cjf_idxt_destroy(journal_cjf *jnl); /** * Creates an empty table of indexes (IDXT) for the journal, with a minimum number of entries. * Nothing is written to disk. * * @param jnl * @param entries */ void journal_cjf_idxt_create(journal_cjf *jnl, s16 entries); /** * Loads (or rebuilds) the table of indexes (IDXT) * * @param jnl */ void journal_cjf_idxt_load(journal_cjf *jnl); u32 journal_cjf_idxt_get_last_file_offset(const journal_cjf *jnl); u32 journal_cjf_idxt_get_page_serial_from_index(const journal_cjf *jnl, int idx); ya_result journal_cjf_idxt_get_page_offset_from_serial(const journal_cjf *jnl, u32 serial, u32 *file_offset); ya_result journal_cjf_idxt_get_page_index_from_serial(const journal_cjf *jnl, u32 serial); ya_result journal_cjf_idxt_get_page_serial_to(const journal_cjf *jnl, int idx); u32 journal_cjf_idxt_get_page_offset(const journal_cjf *jnl, int idx); static inline u32 journal_cjf_idxt_get_page_count(journal_cjf *jnl) { return jnl->idxt.count; } yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/journal-cjf-page-output-stream.h0000644000000000000000000000013114505005531027035 xustar000000000000000029 mtime=1695812441.50396874 30 atime=1695812445.798030239 30 ctime=1695812494.921733789 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/journal-cjf-page-output-stream.h0000664000374500037450000000615014505005531027002 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include /** * Prepares a stream for the next chunk (-SOA ... +SOA ...) * * @note before being closed, this stream MUST be either 'next'ed or 'cancel'ed */ void journal_cjf_page_output_stream_next(output_stream *stream); /** * Cancels a stream's currentchunk (-SOA ... +SOA ...) * * @note before being closed, this stream MUST be either 'next'ed or 'cancel'ed */ void journal_cjf_page_output_stream_cancel(output_stream *stream); void journal_cjf_page_output_stream_set_serial_from(output_stream *stream, u32 serial); void journal_cjf_page_output_stream_set_serial_to(output_stream *stream, u32 serial); void journal_cjf_page_output_stream_set_soa_to_offset(output_stream *stream, u32 offset); ya_result journal_cfj_page_output_stream_write_resource_record(output_stream *stream, dns_resource_record *rr); /** * * stream MUST be initalised with output_stream_set_void(stream) before first call * * @param stream * @param jnl * @return */ u32 journal_cjf_page_output_stream_reopen(output_stream *stream, journal_cjf *jnl); u32 journal_cfj_page_output_stream_get_size(output_stream *stream); u32 journal_cfj_page_output_stream_get_start_offset(output_stream *stream); u32 journal_cfj_page_output_stream_get_current_offset(output_stream *stream); yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/journal-cjf-page.h0000644000000000000000000000013214505005531024207 xustar000000000000000030 mtime=1695812441.519968969 30 atime=1695812445.799030253 30 ctime=1695812494.923733818 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/journal-cjf-page.h0000664000374500037450000000673414505005531024163 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include /** * Search from the offset of the stream for a serial, looking in an PAGE referenced by index * * @param jnl * @param idx * @param serial * @param out_offset * @return */ ya_result journal_cjf_page_get_stream_offset_from_serial(journal_cjf *jnl, int idx, u32 serial, u32 *out_offset); /** * * Returns true iff the current PAGE table is full * * @param jnl * @return */ bool journal_cjf_page_is_full(journal_cjf *jnl); /** * * Returns the file offset value at index in the current PAGE * * @param jnl * @param index * @return */ u32 journal_cjf_page_get_file_offset(journal_cjf *jnl); u32 journal_cjf_page_get_stream_file_offset(journal_cjf *jnl); /** * * Returns the last serial number value at index in the PAGE * * @param jnl * @param index * @return */ u32 journal_cjf_page_get_last_serial(journal_cjf *jnl, s16 index); bool journal_cjf_page_is_full(journal_cjf *jnl); bool journal_cjf_page_line_count(journal_cjf *jnl); /** * * Returns the file offset value at index in the current PAGE * * @param jnl * @param index * @return */ u32 journal_cjf_page_get_file_offset(journal_cjf *jnl); /** * * Returns the last serial number value at index in the PAGE * * @param jnl * @param index * @return */ u32 journal_cjf_page_get_last_serial(journal_cjf *jnl, s16 index); /** * Returns true if it's technically possible to overwrite the last page from our position * * @param jnl * @return */ static inline bool journal_cjf_page_current_output_stream_may_overwrite(journal_cjf *jnl) { return (jnl->first_page_offset > jnl->last_page.file_offset); } yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/journal-cjf-page-cache.h0000644000000000000000000000013214505005531025250 xustar000000000000000030 mtime=1695812441.507968797 30 atime=1695812445.798030239 30 ctime=1695812494.925733847 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/journal-cjf-page-cache.h0000664000374500037450000001017014505005531025211 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #include #if !JOURNAL_CJF_BASE #error "internal include for the CJF journal, don't use include it" #endif #ifdef __cplusplus extern "C" { #endif #define CJF_SECTION_INDEX_SLOT_HEAD 16 #define CJF_SECTION_INDEX_SLOT_SIZE 8 #define CJF_SECTION_INDEX_SLOT_COUNT 510 #define CJF_SECTION_INDEX_SIZE (CJF_SECTION_INDEX_SLOT_HEAD + CJF_SECTION_INDEX_SLOT_SIZE * CJF_SECTION_INDEX_SLOT_COUNT) // 4KB #define CJF_PAGE_SIZE_IN_BYTE (CJF_SECTION_INDEX_SLOT_HEAD + (CJF_SECTION_INDEX_SLOT_COUNT * CJF_SECTION_INDEX_SLOT_SIZE)) #define CJF_PAGE_ARBITRARY_UPDATE_SIZE 512 #define CJF_PAGE_MAGIC MAGIC4('P','A','G','E') struct journal_cjf_page_tbl_header { u32 magic; u32 next_page_offset; u16 count; u16 size; u32 stream_end_offset; u8 __end_of_struct__; }; typedef struct journal_cjf_page_tbl_header journal_cjf_page_tbl_header; #define JOURNAL_CJF_PAGE_HEADER_SIZE offsetof(journal_cjf_page_tbl_header,__end_of_struct__) #define JCJFTI_TAG 0x4954464a434a struct journal_cjf_page_tbl_item { u32 ends_with_serial; // the last SOA on the stream for this item has this serial u32 stream_file_offset; /// @note THIS MUST BE EXACTLY 8 BYTES LONG ! }; typedef struct journal_cjf_page_tbl_item journal_cjf_page_tbl_item; #define JOURNAL_CJF_PAGE_ITEM_SIZE 8 void journal_cjf_page_cache_init(); void journal_cjf_page_cache_flush(file_pool_file_t file); void journal_cjf_page_cache_close(file_pool_file_t file); void journal_cjf_page_cache_write_item(file_pool_file_t file, u64 file_offset, s16 offset, const journal_cjf_page_tbl_item *value); void journal_cjf_page_cache_read_item(file_pool_file_t file, u64 file_offset, s16 offset, journal_cjf_page_tbl_item *value); void journal_cjf_page_cache_write_new_header(file_pool_file_t file, u64 file_offset); void journal_cjf_page_cache_write_header(file_pool_file_t file, u64 file_offset, const journal_cjf_page_tbl_header *value); void journal_cjf_page_cache_read_header(file_pool_file_t file, u64 file_offset, journal_cjf_page_tbl_header *value); void journal_cjf_page_cache_flush_page(file_pool_file_t file, u64 file_offset); void journal_cjf_page_cache_clear(file_pool_file_t file, u64 file_offset); void journal_cjf_page_cache_finalize(); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/chain-replay.h0000644000000000000000000000013214505005531023437 xustar000000000000000030 mtime=1695812441.531969141 30 atime=1695812445.799030253 30 ctime=1695812494.927733875 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/chain-replay.h0000664000374500037450000000561214505005531023405 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #ifdef __cplusplus extern "C" { #endif struct chain_replay; typedef ya_result chain_replay_record_add_method(struct chain_replay *cr, const u8 *fqdn, u16 rtype, const zdb_ttlrdata *ttlrdata); typedef ya_result chain_replay_record_del_method(struct chain_replay *cr, const u8 *fqdn, u16 rtype, const zdb_ttlrdata *ttlrdata); typedef ya_result chain_replay_execute_method(struct chain_replay *cr); typedef void chain_replay_finalize_method(struct chain_replay *cr); struct chain_replay_vtbl { chain_replay_record_add_method * const record_add; chain_replay_record_del_method * const record_del; chain_replay_execute_method * const execute; chain_replay_finalize_method * const finalise; const char *__class__; }; struct chain_replay { const struct chain_replay_vtbl* vtbl; void *data; }; typedef struct chain_replay chain_replay; #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec.h0000644000000000000000000000013214505005531022013 xustar000000000000000030 mtime=1695812441.521968997 30 atime=1695812445.799030253 30 ctime=1695812494.929733904 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec.h0000664000374500037450000001272514505005531021764 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec NSEC functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _NSEC_H #define _NSEC_H #include #if !ZDB_HAS_NSEC_SUPPORT #error "Please do not include nsec.h if ZDB_HAS_NSEC_SUPPORT is 0" #endif #include #include #ifdef __cplusplus extern "C" { #endif #define ZDB_NSECLABEL_TAG 0x4c42414c4345534e #define NSEC_NEXT_DOMAIN_NAME(x__) (&(x__).rdata_start[0]) /** * Reverses the labels of the fqdn * * @param inverse_name * @param name * @return */ u32 nsec_inverse_name(u8 *inverse_name,const u8 *name); /** * * Updates/Verifies the NSEC structures of the zone. * * @param zone the zone * @param read_only a slave would not change the records. * * @return an error code (only fails if a slave got a zone with errors) */ ya_result nsec_update_zone(zdb_zone* zone, bool read_only); /* read_only a.k.a slave */ /** * Creates the NSEC node, creates or update the NSEC record * * @param zone * @param label * @param labels * @param labels_top */ void nsec_update_label(zdb_zone* zone, zdb_rr_label* label, dnslabel_vector_reference labels, s32 labels_top); /** * Verifies and, if needed, update the NSEC record. * There WILL be an NSEC record in the label at the end of the call. * It does NOT create the NSEC node (needs it created already). * It does NOT check for the relevancy of the NSEC record. * * @param label * @param node * @param next_node * @param name * @param ttl * @return */ bool nsec_update_label_record(zdb_zone *zone, zdb_rr_label *label, nsec_node *node, nsec_node *next_node, u8 *name); /** * Creates the NSEC node, link it to the label. * * @param zone * @param label * @param labels * @param labels_top * @return */ nsec_node *nsec_update_label_node(zdb_zone* zone, zdb_rr_label* label, dnslabel_vector_reference labels, s32 labels_top); /** * * Unlink the NSEC node from the label, then deletes said node from the chain. * * @param zone * @param labels * @param labels_top * @return */ bool nsec_delete_label_node(zdb_zone* zone, dnslabel_vector_reference labels, s32 labels_top); /** * * Find the label that has got the right NSEC interval for "nextname" * * @param zone * @param name_vector * @param dname_out * @return */ zdb_rr_label *nsec_find_interval(const zdb_zone *zone, const dnsname_vector *name_vector, u8 **out_dname_p, u8 * restrict * pool); void nsec_name_error(const zdb_zone* zone, const dnsname_vector *qname_not_const, s32 closest_index, u8 * restrict * pool, u8 **out_encloser_nsec_name_p, zdb_rr_label** out_encloser_nsec_label, u8 **out_wild_encloser_nsec_name_p, zdb_rr_label** out_wildencloser_nsec_label ); void nsec_destroy_zone(zdb_zone* zone); void nsec_logdump_tree(zdb_zone *zone); #define NSEC_ZONE_DISABLED 0 #define NSEC_ZONE_ENABLED 1 #define NSEC_ZONE_GENERATING 2 #define NSEC_ZONE_REMOVING 4 #define TYPE_NSECCHAINSTATE NU16(0xff01) /** * marks the zone with private records * * @param zone * @param status * * @return an error code */ ya_result nsec_zone_set_status(zdb_zone *zone, u8 secondary_lock, u8 status); /** * gets the zone status from private records * * @param zone * @param statusp * * @return an error code */ ya_result nsec_zone_get_status(zdb_zone *zone, u8 *statusp); #define ZONE_NSEC_AVAILABLE(zone_) zdb_rr_label_flag_isset((zone_)->apex, ZDB_RR_LABEL_NSEC) #ifdef __cplusplus } #endif #endif /* _NSEC_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec-chain-replay.h0000644000000000000000000000013214505005531024365 xustar000000000000000030 mtime=1695812441.481968425 30 atime=1695812445.797030225 30 ctime=1695812494.931733933 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec-chain-replay.h0000664000374500037450000000432714505005531024335 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #ifdef __cplusplus extern "C" { #endif ya_result nsec_chain_replay_init(chain_replay *cr, zdb_zone *zone); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3.h0000644000000000000000000000013214505005531022076 xustar000000000000000030 mtime=1695812441.530969126 30 atime=1695812445.799030253 30 ctime=1695812494.933733961 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3.h0000664000374500037450000002222114505005531022037 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ #pragma once #include #include #include #include #include #include #include #include #include #include /** * Set this to 1 to dump a lot more about the NSEC3 updates/generation. * I use this whenever something weird happens with NSEC3. * (It seems bind is more liberal about handling broken/invalid NSEC3 databases, * YADIFA only accepts valid ones) */ #define NSEC3_UPDATE_ZONE_DEBUG 0 /** * Used to be like this (NSEC3_INCLUDE_ZONE_PATH 1) with older bind * Not anymore in 9.7.1 (probably since 9.7.x) * Set this to 1 to comply with that old bind issue. (not recommended) * */ #define NSEC3_INCLUDE_ZONE_PATH 0 #if !DEBUG #undef NSEC3_UPDATE_ZONE_DEBUG #define NSEC3_UPDATE_ZONE_DEBUG 0 #endif #ifdef __cplusplus extern "C" { #endif /* The biggest allowed label is 63 bytes. Let's assume 64. => * Since the digest is base32hex encoded, is un-encoded size is max (64/8)*5 = 40 bytes. * This covers more than a SHA-256 (32 bytes), but it (40) should be the upper bound. */ #define MAX_DIGEST_LENGTH 40 #define MAX_SALT_LENGTH 255 #define NSEC3_DIGEST_ALGORITHM_SHA1 1 #define NSEC3_RDATA_IS_OPTIN(__rdata__) ((((u8*)(__rdata__))[1]&NSEC3_FLAGS_OPTOUT) == 0) #define NSEC3_RDATA_IS_OPTOUT(__rdata__) ((((u8*)(__rdata__))[1]&NSEC3_FLAGS_OPTOUT) != 0) #define NSEC3_RDATA_ALGORITHM(__rdata__) (((u8*)(__rdata__))[0]) #define NSEC3_RDATA_FLAGS(__rdata__) (((u8*)(__rdata__))[1]) #define NSEC3_RDATA_ITERATIONS_NE(__rdata__) (((u16*)(__rdata__))[1]) #define NSEC3_RDATA_ITERATIONS(__rdata__) NU16(NSEC3_RDATA_ITERATIONS_NE(__rdata__)) #define TYPE_NSEC3CHAINSTATE NU16(0xff02) #define TYPE_NSEC3PARAMQUEUED NU16(0xff03) /** * * Links a label to already existing nsec3 items * * This function is for when a label has been added "without intelligence". * It will find if the function has got a matching NSEC3 record (by digest) * If so, it will link to it. * * @param n3 * @param label * @param fqdn */ void nsec3_zone_label_update_chain_links(nsec3_zone *n3, zdb_rr_label* label, int n3_count, u16 coverage_mask, const u8 *fqdn); /** * Updates links for the first NSEC3 chain of the zone * Only links to existing NSEC3 records. * Only links label with an extension and self/wild set to NULL * * @param zone */ void nsec3_zone_update_chain0_links(zdb_zone *zone); void nsec3_destroy_zone(zdb_zone* zone); /** * This sets the flags of each NSEC3PARAM of the zone * Please use nsec3_edit_zone_start and nsec3_edit_zone_end * */ void nsec3_set_nsec3param_flags(zdb_zone* zone, u8 flags); const zdb_rr_label* nsec3_get_closest_provable_encloser( const zdb_rr_label* apex, const_dnslabel_vector_reference sections, s32* sections_topp); /* void nsec3_wild_closest_encloser_proof( const zdb_zone *zone, const dnsname_vector *qname, s32 apex_index, const nsec3_zone_item **wild_closest_provable_encloser_nsec3p); */ void nsec3_wild_closest_encloser_proof( const zdb_zone *zone, const dnsname_vector *qname, s32 apex_index, const nsec3_zone_item **wild_encloser_nsec3p, const nsec3_zone_item **closest_provable_encloser_nsec3p, const nsec3_zone_item **qname_encloser_nsec3p); void nsec3_closest_encloser_proof( const zdb_zone *zone, const dnsname_vector *qname, s32 apex_index, const nsec3_zone_item **encloser_nsec3p, const nsec3_zone_item **closest_provable_encloser_nsec3p, const nsec3_zone_item **wild_closest_provable_encloser_nsec3p ); /** * Verifies the coherence of the nsec3 database of a zone * * @param zone * */ void nsec3_check(zdb_zone *zone); /** * For generates the digest label name of an fqdn for a specified NSEC3PARAM chain * * @param n3 the NSEC3PARAM chain * @param fqdn the name to digest * @param fqdn_len the size of the name of the digest * @param out_digest the resulting digest in a Pascal kind of format (1 byte length, then the bytes) * * 1 use (zdb_zone_load) */ void nsec3_compute_digest_from_fqdn_with_len(const nsec3_zone *n3, const u8 *fqdn, u32 fqdn_len, u8 *digest, bool isstar); ya_result nsec3_get_next_digest_from_rdata(const u8 *rdata, u32 rdata_size, u8 *digest, u32 digest_size); // 1 -> 3 -> 9 => 4 #define NSEC3_ZONE_DISABLED 0 #define NSEC3_ZONE_ENABLED 1 #define NSEC3_ZONE_GENERATING 2 #define NSEC3_ZONE_REMOVING 4 // #define NSEC3_ZONE_REMOVING 8 signing chain /** * Sets the NSEC3 maintenance status for a specific chain. * Marks the zone using private records. * * @param zone * @param algorithm * @param optout * @param salt * @param salt_len * @param iterations * @param status * @return */ ya_result nsec3_zone_set_status(zdb_zone *zone, u8 secondary_lock, u8 algorithm, u8 optout, u16 iterations, const u8 *salt, u8 salt_len, u8 status); /** * Gets the NSEC3 maintenance status for a specific chain. * Get the information from the zone using private records. * * @param zone * @param algorithm * @param optout * @param salt * @param salt_len * @param iterations * @param status * @return */ ya_result nsec3_zone_get_status(zdb_zone *zone, u8 algorithm, u8 optout, u16 iterations, const u8 *salt, u8 salt_len, u8 *statusp); /** * Gets a copy of the salt bytes from the first matching NSEC3PARAM record. * * The zone must be locked. * * @param zone * @param algorithm * @param optout * @param salt_len * @param iterations * @param salt_buffer * @return */ ya_result nsec3_zone_get_first_salt_matching(zdb_zone *zone, u8 algorithm, u8 optout, u16 iterations, u8 salt_len, u8 *salt_buffer); /** * Gets the NSEC3 maintenance status for a specific chain. * Get the information from the zone using private records. * * The zone must be locked. * * @param zone * @param rdata * @param rdata_size * @param statusp * @return */ ya_result nsec3_zone_get_status_from_rdata(zdb_zone *zone, const u8 *rdata, u16 rdata_size, u8 *statusp); /** * Returns the number of known chains in the zone. * Inactive chains are also counted. * Zone must be locked. * * @param zone * @return */ int nsec3_zone_get_chain_count(zdb_zone *zone); /** * Returns pointers to the chains from the zone. * Inactive chains are also counted. * Zone must be locked. * * @param zone * @param n3p * @param max_count * @return */ int nsec3_zone_get_chains(zdb_zone *zone, nsec3_zone **n3p, int max_count); struct resource_record_view; void nsec3_item_resource_record_view_init(struct resource_record_view *rrv); void nsec3_item_resource_record_view_origin_set(struct resource_record_view *rrv, const u8 *origin); void nsec3_item_resource_record_view_nsec3_zone_set(struct resource_record_view *rrv, nsec3_zone *n3); void nsec3_item_resource_record_view_ttl_set(struct resource_record_view *rrv, s32 ttl); void nsec3_item_resource_record_view_item_set(struct resource_record_view *rrv, nsec3_node *item); void nsec3_item_resource_record_finalize(struct resource_record_view *rrv); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3_collection.h0000644000000000000000000000013014505005531024307 xustar000000000000000029 mtime=1695812441.49496861 30 atime=1695812445.798030239 29 ctime=1695812494.93573399 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3_collection.h0000664000374500037450000001421614505005531024257 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * This is the collection that holds the NSEC3 chain for one NSEC3PARAM * * @{ */ #pragma once #include #ifdef __cplusplus extern "C" { #endif /* * A digest is stored prefixed with its length ([1;255]) */ /* * A structure to hold both children with direct access */ typedef struct nsec3_node nsec3_node; struct nsec3_children { struct nsec3_node* left; struct nsec3_node* right; }; /* * An union to have access to the children with direct or indexed access */ typedef union nsec3_children_union nsec3_children_union; union nsec3_children_union { struct nsec3_children lr; struct nsec3_node * child[2]; }; typedef union nsec3_item_label_owner_array nsec3_item_label_owner_array; union nsec3_item_label_owner_array { zdb_rr_label* owner; zdb_rr_label** owners; }; /* * The node structure CANNOT have a varying size on a given collection * This means that the digest size is a constant in the whole tree */ #define N3NODE_TAG 0x45444f4e334e struct nsec3_node { union nsec3_children_union children; /**/ struct nsec3_node* parent; /**/ /* 64 bits aligned */ s8 balance; /* PAYLOAD BEYOND THIS POINT */ u8 flags; /* opt-out */ u16 type_bit_maps_size; s32 rc; /* label RC */ s32 sc; /* *.label RC */ /* 64 bits aligned */ zdb_packed_ttlrdata* rrsig; /**/ nsec3_item_label_owner_array label; nsec3_item_label_owner_array star_label; u8 *type_bit_maps; /* MUST be a ptr */ u8 digest[1]; /* 7*4 7*8 * 3*2 3*2 * 1*1 1*1 * * 35 63 * * +21 * *56 (56) 84 (88) * * For the 3M records of EU: * * 168MB 240MB * * To this, 2+1 ptrs must be added * by record * * The remaining overhead happens * if there are many references * for the same label, this should * be fairly negligible. * * 36MB 72MB * * => * * 204MB 312MB * */ }; #define NSEC3_NODE_SIZE_FOR_DIGEST(node,digest) ((sizeof(nsec3_node)-1)+digest[0]) #define NSEC3_NODE_DIGEST_SIZE(node) (node->digest[0]) #define NSEC3_NODE_DIGEST_PTR(node) (&node->digest[1]) #define NSEC3_NODE_SIZE(node) ((sizeof(nsec3_node)-1)+NSEC3_NODE_DIGEST_SIZE(node)) /* * AVL definition part begins here */ /* * The maximum depth of a tree. * 40 is enough for storing 433494436 items (worst case) * * Depth 0 is one node. * * Worst case : N is enough for sum[n = 0,N](Fn) where Fn is Fibonacci(n+1) * Best case : N is enough for (2^(N+1))-1 */ #define AVL_MAX_DEPTH 52 // 139*10^9 items max (worst case)64 /* * The previx that will be put in front of each function name */ #define AVL_PREFIX nsec3_ /* * The type that hold the node */ #define AVL_NODE_TYPE nsec3_node /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_TREE_TYPE AVL_NODE_TYPE* /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_CONST_TREE_TYPE AVL_NODE_TYPE* const /* * How to find the root in the tree */ #define AVL_TREE_ROOT(__tree__) (*(__tree__)) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u8* #define AVL_REFERENCE_IS_CONST FALSE #define AVL_REFERENCE_IS_POINTER TRUE /* * The node has got a pointer to its parent * * 0 : disable * !=0 : enable */ #define AVL_HAS_PARENT_POINTER 1 #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif AVL_NODE_TYPE* AVL_PREFIXED(find_interval_start)(AVL_CONST_TREE_TYPE* tree, const AVL_REFERENCE_TYPE obj_hash); AVL_NODE_TYPE* AVL_PREFIXED(find_interval_prev_mod)(AVL_CONST_TREE_TYPE* root, const AVL_REFERENCE_TYPE obj_hash); /* * I recommend setting a define to identify the C part of the template * So it can be used to undefine what is not required anymore for every * C file but that one. * */ #ifndef _NSEC3_COLLECTION_C #undef AVL_MAX_DEPTH #undef AVL_PREFIX #undef AVL_NODE_TYPE #undef AVL_TREE_TYPE #undef AVL_CONST_TREE_TYPE #undef AVL_TREE_ROOT #undef AVL_REFERENCE_TYPE #undef AVL_HAS_PARENT_POINTER #undef AVL_REFERENCE_IS_CONST #undef AVL_REFERENCE_IS_POINTER #undef _AVL_H_INC #endif /* _NSEC3_COLLECTION_C */ #ifdef __cplusplus } #endif /* * AVL definition part ends here */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3-chain-replay.h0000644000000000000000000000013214505005531024450 xustar000000000000000030 mtime=1695812441.535969198 30 atime=1695812445.799030253 30 ctime=1695812494.937734019 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3-chain-replay.h0000664000374500037450000000433014505005531024412 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #ifdef __cplusplus extern "C" { #endif ya_result nsec3_chain_replay_init(chain_replay *cr, zdb_zone *zone); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3_item.h0000644000000000000000000000013214505005531023114 xustar000000000000000030 mtime=1695812441.475968338 30 atime=1695812445.797030225 30 ctime=1695812494.940734062 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3_item.h0000664000374500037450000001635614505005531023071 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _NSEC3_ITEM_H #define _NSEC3_ITEM_H #include #include #ifdef __cplusplus extern "C" { #endif /* NOTE: The first byte of the digest is its length */ nsec3_zone_item *nsec3_zone_item_find_encloser_start(const nsec3_zone *n3, const u8 *digest); nsec3_zone_item* nsec3_zone_item_find(const nsec3_zone* n3, const u8 *digest); /** * * @param n3 * @param dnsnamedigest * @return */ nsec3_zone_item *nsec3_zone_item_find_by_name(const nsec3_zone *n3, const u8 *dnsnamedigest); /** * * Also returns the nsec3 chain. * * @param zone * @param nsec3_label * @param out_n3 * @return */ nsec3_zone_item *nsec3_zone_item_find_by_name_ext(const zdb_zone *zone, const u8 *nsec3_label, nsec3_zone **out_n3); nsec3_zone_item *nsec3_zone_item_find_by_record(const zdb_zone *zone, const u8 *fqdn, u16 rdata_size, const u8 *rdata); bool nsec3_zone_item_equals_rdata( const nsec3_zone* n3, const nsec3_zone_item *item, u16 rdata_size, const u8* rdata); bool nsec3_zone_item_equals_rdata_lenient(const nsec3_zone* n3, const nsec3_zone_item *item, u16 rdata_size, const u8* rdata); ya_result nsec3_zone_item_to_zdb_packed_ttlrdata( const nsec3_zone* n3, const nsec3_zone_item *item, const u8* origin, u8* out_owner, /* dnsname */ u32 ttl, zdb_packed_ttlrdata* nsec3, u32 nsec3_max_size); struct nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm { const nsec3_zone* n3; const nsec3_zone_item *item; const u8* origin; u8 * restrict * pool; // memory pool s32 ttl; }; typedef struct nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm; #define NSEC3_ZONE_ITEM_TO_NEW_ZDB_PACKED_TTLRDATA_SIZE (ALIGN16(MAX_DOMAIN_LENGTH) + ALIGN16(NSEC3_ZONE_STRUCT_SIZE_FROM_SALT(255))) void nsec3_zone_item_to_new_zdb_packed_ttlrdata( nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm *nsec3_parms, u8 **out_owner_p, /* dnsname */ zdb_packed_ttlrdata** out_nsec3, const zdb_packed_ttlrdata** out_nsec3_rrsig); u32 nsec3_zone_item_rdata_size(const nsec3_zone* n3, const nsec3_zone_item *item); u16 nsec3_zone_item_to_rdata(const nsec3_zone* n3, const nsec3_zone_item *item, u8 *out_rdata, u16 out_rdata_size); u32 nsec3_zone_item_get_label( const nsec3_zone_item *item, u8* output_buffer, u32 buffer_size); void nsec3_zone_item_write_owner( output_stream* os, const nsec3_zone_item *item, const u8* origin); void nsec3_zone_item_to_output_stream(output_stream* os, const nsec3_zone* n3, const nsec3_zone_item *item, const u8* origin, u32 ttl); void nsec3_zone_item_rrsig_del_by_keytag(nsec3_zone_item *item, u16 native_key_tag); void nsec3_zone_item_rrsig_del(nsec3_zone_item *item, const zdb_ttlrdata *nsec3_rrsig); void nsec3_zone_item_rrsig_add(nsec3_zone_item *item, zdb_packed_ttlrdata *nsec3_rrsig); /* * Deletes ALL rrsig in the NSEC3 item */ void nsec3_zone_item_rrsig_delete_all(nsec3_zone_item *item); /* * Empties an nsec3_zone_item * * Only frees the payload : owners, stars, bitmap, rrsig * * This should be followed by the destruction of the item itself */ void nsec3_zone_item_empties(nsec3_zone_item *item); /* * Sets the type bitmap of the nsec3 item to match the one in the rdata * Does nothing if the bitmap is already ok * * NOTE: Remember that the item does not contain * * _ hash_algorithm * _ iterations * _ salt_length * _ salt * _ hash_length * _ next_hashed_owner_name */ ya_result nsec3_zone_item_update_bitmap(nsec3_zone_item *nsec3_item, const u8 *rdata, u16 rdatasize); typedef struct nsec3_item_format_writer_args nsec3_item_format_writer_args; struct nsec3_item_format_writer_args { const u8 *origin; const nsec3_zone* n3; const nsec3_zone_item* item; s32 ttl; }; /** * This helper macro declares a format_writer variable to be used with %w * * It has been written for debug builds. * * usage: * DECLARE_NSEC3_ITEM_FORMAT_WRITER(myvar, origin, n3, nsec3_item, 600); * format("%w", &myvar); * * The implementation is not very efficient. It first writes the record as a wire, then prints the wire using the "normal" call. * * The callback should NOT be registered as a format class. */ #define DECLARE_NSEC3_ITEM_FORMAT_WRITER(variable_name_,origin_,n3_,item_,ttl_) \ const nsec3_item_format_writer_args variable_name_##args = {(origin_),(n3_),(item_),(ttl_)}; \ const format_writer variable_name_ = {nsec3_item_format_writer_callback, &variable_name_##args}; void nsec3_item_format_writer_callback(const void*, output_stream*, s32, char, bool, void* reserved_for_method_parameters); #ifdef __cplusplus } #endif #endif /* _NSEC3_ITEM_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3_load.h0000644000000000000000000000013114505005531023074 xustar000000000000000030 mtime=1695812441.489968539 30 atime=1695812445.798030239 29 ctime=1695812494.94273409 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3_load.h0000664000374500037450000000745214505005531023047 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #ifdef __cplusplus extern "C" { #endif /* * This struct and the five functions are handling the loading of the nsec3 * records of a zone file. */ struct nsec3_load_context { // based on the first bytes of the NSEC3(PARAM) record // contains an array of record ptr_vector nsec3chain; ptr_set postponed_rrsig; void *last_inserted_nsec3; zdb_zone* zone; u32 rrsig_added; u32 rrsig_ignored; u32 rrsig_discarded; u32 nsec3_accepted; u32 nsec3_rejected; u32 nsec3_discarded; bool opt_out; bool can_fix; bool fix_applied; }; typedef struct nsec3_load_context nsec3_load_context; typedef bool (nsec3_load_is_label_covered_function)(zdb_rr_label*); bool nsec3_load_is_label_covered(zdb_rr_label *label); bool nsec3_load_is_label_covered_optout(zdb_rr_label *label); ya_result nsec3_load_init(nsec3_load_context *context, zdb_zone* zone); static inline void nsec3_load_allowed_to_fix(nsec3_load_context *context, bool can_fix) { context->can_fix = can_fix; } void nsec3_load_destroy(nsec3_load_context *context); ya_result nsec3_load_add_nsec3param(nsec3_load_context *context, const u8 *entry_rdata, u16 entry_rdata_size); ya_result nsec3_load_add_nsec3(nsec3_load_context *context, const u8 *base32hex_digest, s32 entry_ttl, const u8 *entry_rdata, u16 entry_rdata_size); ya_result nsec3_load_add_rrsig(nsec3_load_context *context, const u8 *entry_name, s32 entry_ttl, const u8 *entry_rdata, u16 entry_rdata_size); ya_result nsec3_load_add_nsec3chainstate(nsec3_load_context *context, const u8 *rdata, u16 rdata_size); ya_result nsec3_load_generate(nsec3_load_context *context); bool nsec3_load_is_context_empty(nsec3_load_context *context); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3_name_error.h0000644000000000000000000000013214505005531024307 xustar000000000000000030 mtime=1695812441.519968969 30 atime=1695812445.799030253 30 ctime=1695812494.944734119 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3_name_error.h0000664000374500037450000001176414505005531024262 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifdef __cplusplus extern "C" { #endif void nsec3_wild_closest_encloser(const zdb_zone* zone, const dnsname_vector *qname, u32 apex_index, u8 * restrict * pool, u8 **out_wild_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_wild_encloser_nsec3, const zdb_packed_ttlrdata** out_wild_encloser_nsec3_rrsig, u8 **out_wild_closest_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_wild_closest_encloser_nsec3, const zdb_packed_ttlrdata** out_wild_closest_encloser_nsec3_rrsig, u8 **out_qname_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_qname_encloser_nsec3, const zdb_packed_ttlrdata** out_qname_encloser_nsec3_rrsig); /** * @note Name Error Responses * * Retrieve NSEC3 name error records * * To prove the nonexistence of QNAME, a closest encloser proof and an * NSEC3 RR covering the (nonexistent) wildcard RR at the closest * encloser MUST be included in the response. This collection of (up * to) three NSEC3 RRs proves both that QNAME does not exist and that a * wildcard that could have matched QNAME also does not exist. * * For example, if "gamma.example." is the closest provable encloser to * QNAME, then an NSEC3 RR covering "*.gamma.example." is included in * the authority section of the response. * * * * Z-Allocates and creates an NSEC3 record from an nsec3_zone_item * * This record is temporary. * * The function is supposed to be called by nsec3_name_error & nsec3_nodata_error * Said functions are called by the query function * * The record is supposed to be destroyed after usage (ie: at destroy query answer) * * @param zone * @param qname * @param apex_index * @param pool * @param out_next_closer_nsec3_owner_p * @param out_encloser_nsec3 * @param out_encloser_nsec3_rrsig * @param out_closest_encloser_nsec3_owner_p * @param out_closest_encloser_nsec3 * @param out_closest_encloser_nsec3_rrsig * @param out_wild_closest_encloser_nsec3_owner_p * @param out_wild_closest_encloser_nsec3 * @param out_wild_closest_encloser_nsec3_rrsig */ void nsec3_name_error(const zdb_zone *zone, const dnsname_vector *qname, u32 apex_index, u8 * restrict * pool, u8 **out_next_closer_nsec3_owner_p, zdb_packed_ttlrdata** out_encloser_nsec3, const zdb_packed_ttlrdata** out_encloser_nsec3_rrsig, u8 **out_closest_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_closest_encloser_nsec3, const zdb_packed_ttlrdata** out_closest_encloser_nsec3_rrsig, u8 **out_wild_closest_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_wild_closest_encloser_nsec3, const zdb_packed_ttlrdata** out_wild_closest_encloser_nsec3_rrsig ); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3_nodata_error.h0000644000000000000000000000013214505005531024635 xustar000000000000000030 mtime=1695812441.514968897 30 atime=1695812445.798030239 30 ctime=1695812494.946734147 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3_nodata_error.h0000664000374500037450000000716014505005531024603 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _NSEC3_NODATA_ERROR_H #define _NSEC3_NODATA_ERROR_H #include #ifdef __cplusplus extern "C" { #endif void nsec3_nodata_error(const zdb_zone *zone, const zdb_rr_label* owner, const dnsname_vector *qname, s32 apex_index, u8 * restrict * pool, u8 **out_owner_nsec3_owner_p, zdb_packed_ttlrdata** out_owner_nsec3, const zdb_packed_ttlrdata** out_owner_nsec3_rrsig, u8 **out_closest_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_closest_encloser_nsec3, const zdb_packed_ttlrdata** out_closest_encloser_nsec3_rrsig); void nsec3_wild_nodata_error(const zdb_zone* zone, const zdb_rr_label* owner, const dnsname_vector *qname, u32 apex_index, u8 * restrict * pool, u8 **out_next_closer_nsec3_owner_p, zdb_packed_ttlrdata** out_encloser_nsec3, const zdb_packed_ttlrdata** out_encloser_nsec3_rrsig, u8 **out_closest_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_closest_encloser_nsec3, const zdb_packed_ttlrdata** out_closest_encloser_nsec3_rrsig, u8 **out_qname_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_qname_encloser_nsec3, const zdb_packed_ttlrdata** out_qname_encloser_nsec3_rrsig ); #ifdef __cplusplus } #endif #endif /* _NSEC3_NODATA_ERROR_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3_owner.h0000644000000000000000000000013114505005531023307 xustar000000000000000029 mtime=1695812441.49496861 30 atime=1695812445.798030239 30 ctime=1695812494.948734176 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3_owner.h0000664000374500037450000000724214505005531023257 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #ifdef __cplusplus extern "C" { #endif bool nsec3_item_is_owned_by_label(const nsec3_zone_item *item, const zdb_rr_label *owner); /* * Adds an owner to the NSEC3 item */ void nsec3_item_add_owner(nsec3_zone_item *item, const zdb_rr_label *owner); /* * Removes an owner from the NSEC3 item * * The entry MUST have been set before */ void nsec3_item_remove_owner(nsec3_zone_item *item, const zdb_rr_label *owner); /* * Removes all owners from the NSEC3 item * * The entry MUST have been set before */ void nsec3_item_remove_all_owners(nsec3_zone_item *item); zdb_rr_label* nsec3_item_owner_get(const nsec3_zone_item *item, s32 index); static inline s32 nsec3_owner_count(const nsec3_zone_item *item) { return item->rc; } /* * Adds a "star" to the NSEC3 item */ void nsec3_item_add_star(nsec3_zone_item *item, const zdb_rr_label *owner); /* * Removes a star from the NSEC3 item * * The entry MUST have been set before */ void nsec3_item_remove_star(nsec3_zone_item *item, const zdb_rr_label *owner); /* * Removes all stars from the NSEC3 item * * The entry MUST have been set before */ void nsec3_item_remove_all_star(nsec3_zone_item *item); /* * Moves all stars from one NSEC3 item to another. * * This is used when an NSEC3 item is removed: All its NSEC3 must be moved * to his predecessor. */ void nsec3_item_move_all_star_to_nsec3_item(nsec3_zone_item* src, nsec3_zone_item* dst); zdb_rr_label* nsec3_item_star_get(const nsec3_zone_item *item, s32 n); static inline s32 nsec3_star_count(const nsec3_zone_item *item) { return item->sc; } #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3_types.h0000644000000000000000000000013214505005531023322 xustar000000000000000030 mtime=1695812441.525969055 30 atime=1695812445.799030253 30 ctime=1695812494.950734205 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3_types.h0000664000374500037450000002432414505005531023271 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _NSEC3_TYPES_H #define _NSEC3_TYPES_H #include #include #include #include #include #if !ZDB_HAS_NSEC3_SUPPORT #error "Please do not include nsec3.h if ZDB_HAS_NSEC3_SUPPORT is 0" #endif #ifdef __cplusplus extern "C" { #endif /* * There is no sense in using more than one. * Two can be a transition state * * This limit is actually used for ICMTL generation * The NSEC3 structure is cheap on memory (every bit count on a TLD) but * there is a price for this. It is mostly irrelevant, but for ICMTL and * anything trying to get specific NSEC3 rdata bits without knowing the * NSEC3PARAM as well. * */ #define MAX_SUPPORTED_NSEC3PARAM 4 #define NSEC3_DIGEST_TAG 0x474944334e /* N3DIG */ #define NSEC3_ZONE_TAG 0x454e4f5a334e /* N3ZONE */ #define NSEC3_CONTEXT_RECORD_TAG 0x585443334e /* N3CTX */ #define NSEC3_RDATA_TAG 0x4154414452334e /* N3RDATA */ #define NSEC3_LABELEXT_TAG 0x54584542414c334e /* N3LABEXT */ #define NSEC3_TYPEBITMAPS_TAG 0x5350414d4254334e /* N3TBMAPS */ #define NSEC3_LABELPTRARRAY_TAG 0x595252412a4c334e /* N3L*ARRY */ /** The NSEC3 node with this flag on is scheduled for a processing (ie: signature) * It is thus FORBIDDEN to delete it (but it MUST be removed from the NSEC3 collection) * * So instead of a delete the NSEC3_PROPRIETARY_FLAG_DELETED flag should be used and the NSEC3 record has to be put in a * "scheduled for delete" list. The schedule being done after the signature the nsec3 record will be effectively removed. * */ #define NSEC3_PROPRIETARY_FLAG_SCHEDULED 0x80 #define NSEC3_PROPRIETARY_FLAG_DELETED 0x40 /** * @note 20161011 edf -- to sum it up : * * 1 byte for the hash * 1 bytes for the flags * 1 byte for the opt-out flag * 2 bytes for the iterations * 1 byte for the salt length * 255 bytes for the salt * 1 byte for the hash len * 255 bytes for the hash * 256 * (1 + 1 +32) bytes for the type bitmap encoding */ #define TMP_NSEC3_TTLRDATA_SIZE (1 + 1 + 1 + 2 + 1 + MAX_DOMAIN_LENGTH + 1 + MAX_DOMAIN_LENGTH + TYPE_BIT_MAPS_MAX_RDATA_SIZE) //typedef struct nsec3_node nsec3_zone_item; #define nsec3_zone_item struct nsec3_node typedef nsec3_zone_item** nsec3_zone_item_pointer_array; typedef struct nsec3_label_extension nsec3_label_extension; typedef nsec3_label_extension** nsec3_label_extension_array; /* * Index instead of a pointer. * The relevant information are: * * index * (index+1) MOD count */ struct nsec3_label_extension { nsec3_zone_item* _self; nsec3_zone_item* _star; struct nsec3_label_extension *_next; }; static inline nsec3_zone_item *nsec3_label_extension_self(const struct nsec3_label_extension *n3le) { return n3le->_self; } static inline nsec3_zone_item *nsec3_label_extension_star(const struct nsec3_label_extension *n3le) { return n3le->_star; } static inline struct nsec3_label_extension *nsec3_label_extension_next(const struct nsec3_label_extension *n3le) { return n3le->_next; } static inline void nsec3_label_extension_set_self(struct nsec3_label_extension *n3le, nsec3_zone_item *self) { n3le->_self = self; } static inline void nsec3_label_extension_set_star(struct nsec3_label_extension *n3le, nsec3_zone_item *star) { n3le->_star = star; } static inline void nsec3_label_extension_set_next(struct nsec3_label_extension *n3le, struct nsec3_label_extension *next) { n3le->_next = next; } static inline struct nsec3_label_extension **nsec3_label_extension_next_ptr(struct nsec3_label_extension *n3le) { return &n3le->_next; } static inline nsec3_label_extension* nsec3_label_extension_get_from_label(zdb_rr_label *label, int index) { yassert(label != NULL); //yassert(index > 0); nsec3_label_extension *n3e = label->nsec.nsec3; while(index > 0) { yassert(n3e != NULL); n3e = nsec3_label_extension_next(n3e); index--; } return n3e; } /* typedef struct nsec3_zone nsec3_zone; */ struct nsec3_zone { struct nsec3_zone* next; // next chain nsec3_zone_item* items; // collection u8 rdata[]; // NSEC3PARAM head }; #define NSEC3PARAM_MINIMUM_LENGTH 5 #define NSEC3PARAM_RDATA_ALGORITHM(n3prd) (((const u8*)(n3prd))[0]) #define NSEC3PARAM_RDATA_FLAGS(n3prd) (((const u8*)(n3prd))[1]) #define NSEC3PARAM_RDATA_ITERATIONS_NE(n3prd) GET_U16_AT(((const u8*)(n3prd))[2]) // network order #define NSEC3PARAM_RDATA_ITERATIONS(n3prd) NU16(GET_U16_AT(((const u8*)(n3prd))[2])) // network order #define NSEC3PARAM_RDATA_SALT_LEN(n3prd) (((const u8*)(n3prd))[4]) #define NSEC3PARAM_RDATA_SALT(n3prd) (&((u8*)(n3prd))[NSEC3PARAM_MINIMUM_LENGTH]) #define NSEC3PARAM_RDATA_SIZE_FROM_SALT(salt_len) (NSEC3PARAM_MINIMUM_LENGTH + (salt_len)) #define NSEC3PARAM_RDATA_SIZE_FROM_RDATA(rdata_bytes_) (NSEC3PARAM_RDATA_SIZE_FROM_SALT(NSEC3PARAM_RDATA_SALT_LEN(rdata_bytes_))) #define NSEC3_ZONE_ALGORITHM(n3_) NSEC3PARAM_RDATA_ALGORITHM((n3_)->rdata) #define NSEC3_ZONE_FLAGS(n3_) NSEC3PARAM_RDATA_FLAGS((n3_)->rdata) #define NSEC3_ZONE_ITERATIONS(n3_) NSEC3PARAM_RDATA_ITERATIONS((n3_)->rdata) #define NSEC3_ZONE_SALT_LEN(n3_) NSEC3PARAM_RDATA_SALT_LEN((n3_)->rdata) #define NSEC3_ZONE_SALT(n3_) NSEC3PARAM_RDATA_SALT((n3_)->rdata) #define NSEC3PARAM_DEFAULT_TTL 0 /// @note: defined in rfc.h : NSEC3_FLAGS_OPTOUT 0x01 #define NSEC3_FLAGS_MARKED_FOR_ICMTL_ADD 0x80 /* DO NOT PUT THIS IN THE RFC * IT'S PROPRIETARY */ #define NSEC3_FLAGS_MARKED_FOR_ICMTL_DEL 0x40 /* DO NOT PUT THIS IN THE RFC * IT'S PROPRIETARY */ #define NSEC3_ZONE_STRUCT_SIZE_FROM_SALT(salt_len) (sizeof(nsec3_zone) + NSEC3PARAM_RDATA_SIZE_FROM_SALT(salt_len) - 1) #define NSEC3_ZONE_RDATA_SIZE(n3_) NSEC3PARAM_RDATA_SIZE_FROM_SALT(NSEC3_ZONE_SALT_LEN(n3_)) #define NSEC3_ZONE_STRUCT_SIZE(n3_) NSEC3_ZONE_STRUCT_SIZE_FROM_SALT(NSEC3_ZONE_SALT_LEN(n3_)) #define nsec3_zone_get_iterations(n3_) (ntohs(GET_U16_AT((n3_)->rdata[2]))) #define nsec3_zone_set_iterations(n3_,iter_) (GET_U16_AT((n3_)->rdata[2]) = htons(iter_)) #define nsec3_zone_get_item_next(n3_,idx_) ((nsec3_zone_item*)((n3_)->items.data[(idx_+1)%nsec3_zone_get_item_count(n3_)])) #define ZONE_HAS_NSEC3PARAM(zone_) (((zone_)->nsec.nsec3!=NULL) && (zdb_record_find(&(zone_)->apex->resource_record_set, TYPE_NSEC3PARAM)!=NULL)) #define ZONE_NSEC3_AVAILABLE(zone_) (zdb_rr_label_flag_isset(((zone_)->apex), ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT)) static inline bool zdb_rr_label_nsec_linked(const zdb_rr_label *label) { return (label->_flags & ZDB_RR_LABEL_NSEC) != 0; } static inline bool zdb_rr_label_nsec3_linked(const zdb_rr_label *label) { return (label->_flags & ZDB_RR_LABEL_NSEC3) != 0; } static inline bool zdb_rr_label_nsec3optout_linked(const zdb_rr_label *label) { return (label->_flags & ZDB_RR_LABEL_NSEC3_OPTOUT) != 0; } static inline bool zdb_rr_label_nsec3any_linked(const zdb_rr_label *label) { return (label->_flags & (ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT)) != 0; } static inline nsec3_label_extension *nsec3_label_extension_alloc() { nsec3_label_extension *n3le; ZALLOC_OBJECT_OR_DIE( n3le, nsec3_label_extension, NSEC3_LABELEXT_TAG); // in nsec3_label_link #if DEBUG memset(n3le, 0xac, sizeof(nsec3_label_extension)); #endif return n3le; } static inline nsec3_label_extension *nsec3_label_extension_alloc_list(int count) { nsec3_label_extension *n3le = nsec3_label_extension_alloc(); n3le->_self = NULL; n3le->_star = NULL; nsec3_label_extension *prev = n3le; while(--count > 0) { prev->_next = nsec3_label_extension_alloc(); prev = prev->_next; prev->_self = NULL; prev->_star = NULL; } prev->_next = NULL; return n3le; } static inline void nsec3_label_extension_free(nsec3_label_extension *n3le) { #if DEBUG memset(n3le, 0xfe, sizeof(nsec3_label_extension)); #endif ZFREE(n3le, nsec3_label_extension); } static inline u8 nsec3param_get_flags(void *rdata_) { u8 *rdata = (u8*)rdata_; return rdata[1]; } static inline void nsec3param_set_flags(void *rdata_, u8 flags) { u8 *rdata = (u8*)rdata_; rdata[1] = flags; } #ifdef __cplusplus } #endif #endif /* _NSEC3_TYPES_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3_zone.h0000644000000000000000000000013214505005531023131 xustar000000000000000030 mtime=1695812441.485968482 30 atime=1695812445.797030225 30 ctime=1695812494.952734234 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3_zone.h0000664000374500037450000001007114505005531023072 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _NSEC3_ZONE_H #define _NSEC3_ZONE_H #include #ifdef __cplusplus extern "C" { #endif int nsec3param_compare_by_rdata(const u8* a_rdata, const u8* b_rdata); int nsec3_zone_compare(nsec3_zone* a, nsec3_zone* b); void nsec3_zone_destroy(zdb_zone* zone, nsec3_zone* n3); nsec3_zone* nsec3_zone_new(const u8 *nsec3param_rdata, u16 nsec3param_rdata_size); /** * Frees the memory allocated by the nsec3_zone struct. * Must not be called for a nsec3_zone that's being linked into a zdb_zone or * that still contains items. * * @param n3 */ void nsec3_zone_free(nsec3_zone *n3); nsec3_zone* nsec3_zone_from_item(const zdb_zone* zone, const nsec3_zone_item* item); nsec3_zone* nsec3_zone_add_from_rdata(zdb_zone* zone, u16 nsec3param_rdata_size, const u8* nsec3param_rdata); nsec3_zone* nsec3_zone_get_from_rdata(const zdb_zone* zone, u16 nsec3param_rdata_size, const u8* nsec3param_rdata); bool nsec3_zone_detach(zdb_zone *zone, nsec3_zone *n3); ya_result nsec3_zone_chain_count(zdb_zone* zone); /** * * Adds the nsec3_zone (NSEC3PARAM "alter-ego") to the zone. * * Updates labels flags + nsec3 item references placeholders * using nsec3_insert_empty_nsec3 * * Uses nsec3zone_compare * * Used by nsec3_add_nsec3param and nsec3_load_add_nsec3param * * @note Does not add the record. * * @param zone * @param nsec3param_rdata * @param nsec3param_rdata_size * * @return an error code */ ya_result nsec3_zone_chain_add_with_rdata(zdb_zone* zone, const u8* nsec3param_rdata, u16 nsec3param_rdata_size); /** * Returns the index of an NSEC3PARAM in the zone, or an error code * * @param zone * @param nsec3param_rdata * @param nsec3param_rdata_size * @return */ ya_result nsec3_zone_chain_get_index_from_rdata(zdb_zone* zone, const u8* nsec3param_rdata, u16 nsec3param_rdata_size); ya_result nsec3_zone_chain_get_index_from_rdata(zdb_zone* zone, const u8* nsec3param_rdata, u16 nsec3param_rdata_size); #ifdef __cplusplus } #endif #endif /* _NSEC3_ZONE_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec_collection.h0000644000000000000000000000013214505005531024226 xustar000000000000000030 mtime=1695812441.527969083 30 atime=1695812445.799030253 30 ctime=1695812494.954734262 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec_collection.h0000664000374500037450000001333614505005531024176 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec NSEC functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ #ifndef _NSEC_COLLECTION_H #define _NSEC_COLLECTION_H #include #ifdef __cplusplus extern "C" { #endif /* * A digest is stored prefixed with its length ([1;255]) */ /* * A structure to hold both children with direct access */ typedef struct nsec_node nsec_node; struct nsec_children { struct nsec_node* left; struct nsec_node* right; }; /* * An union to have access to the children with direct or indexed access */ typedef union nsec_children_union nsec_children_union; union nsec_children_union { struct nsec_children lr; struct nsec_node * child[2]; }; typedef union nsec_label_pointer_array nsec_label_pointer_array; union nsec_label_pointer_array { zdb_rr_label* owner; zdb_rr_label** owners; }; /* * The node structure CANNOT have a varying size on a given collection * This means that the digest size is a constant in the whole tree */ #define NSECNODE_TAG 0x45444f4e4345534e struct nsec_node { union nsec_children_union children; /**/ struct nsec_node *parent; /**/ s8 balance; /* * The order is defined by the canonisation : I need the full dname (minus the origin) * * The name is stored inverse (ie: eu.eurid.www) beause its tested in that order * * I cannot use a nested name in this structure because the length is not a constant. * Allocating a constant size for every nsec would cost too much (memory, cache miss & cpu) */ zdb_rr_label *label; u8 *inverse_relative_name; /* * I'm tempted to add a pointer to the NSEC record here, but it would only help for * dynupdating and would cost 24MB for the TLD, all this for a few cycles: not worth it */ }; typedef struct nsec_node nsec_zone_item; /* * AVL definition part begins here */ /* * The maximum depth of a tree. * 40 is enough for storing 433494436 items (worst case) * * Depth 0 is one node. * * Worst case : N is enough for sum[n = 0,N](Fn) where Fn is Fibonacci(n+1) * Best case : N is enough for (2^(N+1))-1 */ #define AVL_MAX_DEPTH 52 // 139*10^9 items max (worst case)64 /* * The previx that will be put in front of each function name */ #define AVL_PREFIX nsec_ /* * The type that hold the node */ #define AVL_NODE_TYPE nsec_node /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_TREE_TYPE AVL_NODE_TYPE* /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_CONST_TREE_TYPE AVL_NODE_TYPE* const /* * How to find the root in the tree */ #define AVL_TREE_ROOT(__tree__) (*(__tree__)) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u8* #define AVL_REFERENCE_IS_CONST FALSE #define AVL_REFERENCE_IS_POINTER TRUE /* * The node has got a pointer to its parent * * 0 : disable * !=0 : enable */ #define AVL_HAS_PARENT_POINTER 1 #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif AVL_NODE_TYPE* AVL_PREFIXED(find_interval_start)(AVL_CONST_TREE_TYPE* tree, AVL_REFERENCE_TYPE obj_hash); AVL_NODE_TYPE* AVL_PREFIXED(find_interval_prev_mod)(AVL_CONST_TREE_TYPE* root, const AVL_REFERENCE_TYPE obj_hash); /* * I recommend setting a define to identify the C part of the template * So it can be used to undefine what is not required anymore for every * C file but that one. * */ #ifndef _NSEC_COLLECTION_C #undef AVL_MAX_DEPTH #undef AVL_PREFIX #undef AVL_NODE_TYPE #undef AVL_TREE_TYPE #undef AVL_CONST_TREE_TYPE #undef AVL_TREE_ROOT #undef AVL_REFERENCE_TYPE #undef AVL_HAS_PARENT_POINTER #undef AVL_REFERENCE_IS_CONST #undef AVL_REFERENCE_IS_POINTER #undef _AVL_H_INC #endif /* _NSEC_COLLECTION_C */ #ifdef __cplusplus } #endif /* * AVL definition part ends here */ #endif /* _NSEC_COLLECTION_H */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec_common.h0000644000000000000000000000013214505005531023363 xustar000000000000000030 mtime=1695812441.509968826 30 atime=1695812445.798030239 30 ctime=1695812494.956734291 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec_common.h0000664000374500037450000000467514505005531023341 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec NSEC functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _NSEC_COMMON_H #define _NSEC_COMMON_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif u32 nsec_type_bit_maps_initialise_from_label(type_bit_maps_context *context, zdb_rr_label *label, bool force_nsec, bool force_rrsig); #ifdef __cplusplus } #endif #endif /* _NSEC_COMMON_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/rrsig.h0000644000000000000000000000013214505005531022211 xustar000000000000000030 mtime=1695812441.520968983 30 atime=1695812445.799030253 30 ctime=1695812494.958734319 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/rrsig.h0000664000374500037450000003371514505005531022164 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup rrsig RRSIG functions * @ingroup dnsdbdnssec * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _RRSIG_H #define _RRSIG_H #include #include #include #include #if ZDB_HAS_NSEC3_SUPPORT #include #endif #define RRSIG_TTLRDATA_TAG 0x52544749535252 /* RRSIGTR */ #define DNSSEC_KEY_SLL_TAG 0x59454b43455344 /* DSECKEY */ #define DNSSEC_DEBUGLEVEL 0 // NOT FOR RELEASE (put a 0 here on RELEASE code) #define DNSSEC_DUMPSIGNCOUNT 0 #if !DEBUG #define SIGNER_THREAD_COUNT 2 #else #define SIGNER_THREAD_COUNT 1 /* EASIER FOR DEBUGGING */ #endif #define SIGNATURES_COUNT 1000 #define QUEUE_MAX_SIZE 65536 #define MAX_ENGINE_PRESET_COUNT 128 /** The label is not signed */ #define RRSIG_VERIFIER_RESULT_LABELNOTSIGNED 4 /** The type is not signed */ #define RRSIG_VERIFIER_RESULT_NOTSIGNED 3 /** The signature has not been verified */ #define RRSIG_VERIFIER_RESULT_BADSIGNATURE 2 /** The parameters of the RRSIG does not match the context */ #define RRSIG_VERIFIER_RESULT_BADRECORD 1 /** The signature has been verified */ #define RRSIG_VERIFIER_RESULT_OK 0 #define RRSIG_VERIFIER_RESULT_MAXVALUE 4 #define NO_SIGNATURES 0 #define HAD_SIGNATURES 1 #define UPDATED_SIGNATURES 2 #define RRSIG_DEFAULT_VALIDITY_DURATION (86400*31) /* * Extract fields from a packed record */ #define RRSIG_TYPE_COVERED(x__) (GET_U16_AT((x__)->rdata_start[0])) /** @note : NATIVETYPE */ #define RRSIG_ALGORITHM(x__) ((x__)->rdata_start[2]) #define RRSIG_LABELS(x__) ((x__)->rdata_start[3]) #define RRSIG_ORIGINAL_TTL(x__) (ntohl(GET_U32_AT((x__)->rdata_start[4]))) #define RRSIG_VALID_UNTIL(x__) (ntohl(GET_U32_AT((x__)->rdata_start[8]))) #define RRSIG_VALID_SINCE(x__) (ntohl(GET_U32_AT((x__)->rdata_start[12]))) #define RRSIG_KEY_TAG(x__) (ntohs(GET_U16_AT((x__)->rdata_start[16]))) /** @note : NATIVETAG (LOOK FOR ALL OF THEM) */ #define RRSIG_KEY_NATIVETAG(x__) (GET_U16_AT((x__)->rdata_start[16])) #define RRSIG_SIGNER_NAME(x__) (&(x__)->rdata_start[18]) #define RRSIG_RDATA_TO_TYPE_COVERED(x__) GET_U16_AT(x__) #define RRSIG_CONTEXT_NSEC 1 #define RRSIG_CONTEXT_NSEC3 2 #define RRSIG_CONTEXT_NSEC3_OPTOUT 3 #ifdef __cplusplus extern "C" { #endif bool rrsig_should_remove_signature_from_rdata(const void *rdata, u16 rdata_size, const ptr_vector *zsks, s32 now, s32 regeneration, s32 *key_indexp); typedef struct rrsig_context_s rrsig_context_s; #define RRSIGCTX_TAG 0x5854434749535252 struct rrsig_context_s { ENGINE *engine; dnssec_key_sll *key_sll; /* * Current rrsig_sll (ZALLOC) */ zdb_packed_ttlrdata *rrsig_sll; /* * New rrsig_ssl (MALLOC) */ zdb_packed_ttlrdata *added_rrsig_sll; /* * Expired/invalid rrsig_ssl (MALLOC) */ zdb_packed_ttlrdata *removed_rrsig_sll; const zdb_packed_ttlrdata *canonised_rrset; /* Used for RR canonization */ ptr_vector rrs; u8 *origin; /* Origin of the zone. The rrsig has to match * this. */ smp_int *loose_quota; // each signature will decrease this by 1 // since signatures are made by label, this // is a best effort deal and this value will // most likely drop below zero /**/ u32 rr_dnsname_len; u32 origin_len; /* dnsname_len(origin) */ u32 original_ttl; u32 min_ttl; /**/ u32 valid_from; /* epoch */ /**/ u32 sig_validity_regeneration_seconds; u32 sig_validity_interval_seconds; u32 sig_jitter_seconds; u32 sig_invalid_first; u32 sig_pre_validate_seconds; // the amounts of seconds before "now" the signature will be made valid (1h) /**/ u32 expired_signatures; u32 soon_expired_signatures; /**/ u32 wrong_signatures; u32 good_signatures; /**/ u32 rrsig_header_length; u32 record_header_label_type_class_ttl_length; /**/ u32 canonized_rr_type_offset; u16 zclass; u8 label_depth; u8 flags; u8 nsec_flags; bool must_verify_signatures; // once the signatures are in, there is no point doing it again // if we do them, they are right // if the master do them, he is right // the only time they should be verified is at load time bool signatures_are_invalid; // signatures verification will immediately see them as wrong. // must_verify_signatures must be set to TRUE for this to be used. bool rr_dnsname_processing_apex; /**/ /* * Owner of the RR * * STACK! */ dnsname_stack rr_dnsname; /* * Will contain the label + type + class + ttl * Common for all the records of the same label/type * The type will be edited in order to avoid computing it for * other records of the same label * * Candidate for the context */ u8 record_header_label_type_class_ttl[MAX_DOMAIN_LENGTH + 1 + 2 + 2]; /* * Will contain the type + alg + labels + orgttl + from + to + tag + name * Common for all the records of the same label * The type will be edited in order to avoid computing it for * other records of the same label * * Candidate for the context */ u8 rrsig_header[2+1+1+4+4+4+2+MAX_DOMAIN_LENGTH]; }; #define ZDB_RRSIGUPQ_TAG 0x5150554749535252 /* RRSIGUPQ */ struct rrsig_update_item_s { /// The zone being updated zdb_zone* zone; /// The label being processed zdb_rr_label* label; /// An rrset of records (mallocated) to add in the label zdb_packed_ttlrdata* added_rrsig_sll; /// An rrset of records (mallocated) to remove (and free) from the label zdb_packed_ttlrdata* removed_rrsig_sll; // The fqdn of the label dnsname_stack path; }; typedef struct rrsig_update_item_s rrsig_update_item_s; static inline rrsig_update_item_s* rrsig_update_item_alloc() { rrsig_update_item_s *ret; ZALLOC_OBJECT_OR_DIE( ret, rrsig_update_item_s, ZDB_RRSIGUPQ_TAG); return ret; } static inline void rrsig_update_item_free(rrsig_update_item_s *rui) { ZFREE_OBJECT(rui); } #if ZDB_HAS_NSEC3_SUPPORT struct nsec3_rrsig_update_item_s { zdb_zone* zone; nsec3_zone_item* item; nsec3_zone_item* next; /* * New rrsig (MALLOC) */ zdb_packed_ttlrdata* added_rrsig_sll; /* * Expired/invalid rrsig (MALLOC) */ zdb_packed_ttlrdata* removed_rrsig_sll; }; typedef struct nsec3_rrsig_update_item_s nsec3_rrsig_update_item_s; #endif /** * * @param context the signature context to be initialised * @param zone the zone that will be signed * @param engine_name the engine name (this parameter will be removed soon for a global setup) * @param sign_from the time to sign from * @param quota for multi-threaded operation, the amount of signature to target (this is not meant to be accurate) * * @return an error code if the initialisation failed */ ya_result rrsig_context_initialize(rrsig_context_s *context, const zdb_zone *zone, const char *engine_name, u32 sign_from, smp_int *quota); void rrsig_context_destroy(rrsig_context_s *context); static inline void rrsig_context_update_quota(rrsig_context_s *context, s32 sig_count) { if((sig_count > 0) && (context->loose_quota != NULL)) { smp_int_sub(context->loose_quota, sig_count); } } static inline s32 rrsig_context_get_quota(rrsig_context_s *context) { if(context->loose_quota != NULL) { s32 quota = smp_int_get(context->loose_quota); return quota; } else { return MAX_S32; } } /** * Updates the current algorithm and tag of a context using the given key * Meant to modify the current pre-computed header of the signature * * @param context * @param key */ void rrsig_context_set_current_key(rrsig_context_s *context, const dnssec_key* key); /* * Adds/Removes a label in the path in order to process it */ void rrsig_context_push_name_rrsigsll(rrsig_context_s *context, const u8 *name, zdb_packed_ttlrdata* rrsig_sll); /* Calls rrsig_update_context_push_name_rrsigsll using the label's fields */ void rrsig_context_push_label(rrsig_context_s *context, zdb_rr_label* label); void rrsig_context_pop_label(rrsig_context_s *context); /** * Adds the signature to the "to-be-deleted" set of the context. * * @param context * @param rrsig */ void rrsig_context_append_delete_signature(rrsig_context_s *context, zdb_packed_ttlrdata *rrsig); /** * Compute (the need for) updates by a DNSKEY over an RR set of a given type. * Updates timings of resignature in the context. * * If a public key is given instead of a private key, do_update is assumed FALSE * * @param context the signature context * @param key the signing key (can be public only) * @param rr_sll the rrset records * @param type the rrset type * @param do_update if TRUE, generated and pushes updates in the context, else only update timings * * @return the number of signatures computed */ ya_result rrsig_update_rrset_with_key(rrsig_context_s *context, const zdb_packed_ttlrdata *rr_sll, u16 type, const dnssec_key* key, bool do_update); /** * Computes the updates of an rrset of a given type (cannot be TYPE_ANY, obviously) * Changes are stored into the context and still needs to be committed. * * @param context the signature context * @param records_sll the rrset records * @param rrset_type the rrset type * @param delegation the signature is on a delegation (result of ZDB_LABEL_ATDELEGATION(label)) * * @return an error code or the number of signatures that have been made */ ya_result rrsig_update_rrset(rrsig_context_s *context, const zdb_packed_ttlrdata *records_sll, u16 rrset_type, bool delegation); /* * Takes the result of an update and commits it to the label */ void rrsig_update_commit(zdb_packed_ttlrdata* removed_rrsig_sll, zdb_packed_ttlrdata* added_rrsig_sll, zdb_rr_label* label, zdb_zone* zone, dnsname_stack* name); /** * * Returns the first RRSIG record that applies to the give type. * * @param label the label where to do the search * @param covered_type the type covered by the RRSIG * * @return the first RRSIG covering the type or NULL */ zdb_packed_ttlrdata* rrsig_find_first(const zdb_rr_label* label, u16 covered_type); /** * * Returns the next RRSIG record that applies to the give type. * * @param rrsig the previous RRSIG covering the type * @param covered_type the type covered by the RRSIG * * @return covered_type the next RRSIG covering the type or NULL */ zdb_packed_ttlrdata* rrsig_find_next(const zdb_packed_ttlrdata* rrsig, u16 covered_type); /** * Deletes all RRSIG covering the given type. */ void rrsig_delete_covering(const zdb_rr_label* label, u16 type); /** * * Removes all the RRSIG covering the type * * @param dname the fqdn of the label * @param label the label * @param covered_type the type covered by the RRSIG */ void rrsig_delete(const zdb_zone *zone, const u8 *dname, zdb_rr_label* label, u16 covered_type); void rrsig_delete_by_tag(const zdb_zone *zone, u16 tag); /** * * Signs an RRSET using a context. This is done single-threaded. * * @param context * @param fqdn * @param rtype * @param rrset * @return */ ya_result rrsig_generate_signatures(rrsig_context_s *context, const u8 *fqdn, u16 rtype, const zdb_packed_ttlrdata *rrset, zdb_packed_ttlrdata **out_rrsig_sll); /** * * Does all the steps required to update an rrset in a zone. * The zone is expected to be suitably locked. * * @param zone * @param fqdn * @param label * @param rtype * @return */ ya_result rrsig_rrset_update_helper(zdb_zone *zone, const u8 *fqdn, zdb_rr_label *label, u16 rtype); bool rrsig_should_label_be_signed(zdb_zone *zone, const u8 *fqdn, zdb_rr_label *rr_label); #ifdef __cplusplus } #endif #endif /* _RRSIGN_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/xfr_copy.h0000644000000000000000000000013114505005531022713 xustar000000000000000029 mtime=1695812441.52496904 30 atime=1695812445.799030253 30 ctime=1695812494.960734348 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/xfr_copy.h0000664000374500037450000000535414505005531022665 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup dnscore * @brief * * @{ */ #ifndef XFR_H #define XFR_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define XFR_FULL_FILE_MODE 0600 /** * * Deletes the AXFR wire dumps of a zone. Hashed folders are not removed. * * @param origin * @param base_data_path where to remove the file from (and its hashed folders) * @return */ ya_result xfr_delete_axfr(const u8 *origin); /** * * Copies an AXFR stream from an XFR (xfr_input_stream) into a wire dump (.axfr) * * @param xis the xfr_input_stream * @param base_data_path where to put the file (and its hashed folder) * * @return an error code */ ya_result xfr_copy(input_stream *xis, const char *base_data_path, bool base_data_path_is_target); #ifdef __cplusplus } #endif #endif /* XFR_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb.h0000644000000000000000000000013214505005531021642 xustar000000000000000030 mtime=1695812441.493968596 30 atime=1695812445.798030239 30 ctime=1695812494.962734377 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb.h0000664000374500037450000002170014505005531021604 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdb Zone database * @brief The zone database * * Implementation of structures and functions for the database * * Memory usage approxymation: * * let: * * "digest" the size of a digest * "n3pc" the number of nsec3param * "r" the number of records * * Memory usage =~ (233.3333 + ((446.666+digest) * n3pc) * r * * Or, if the digest size is different for each n3p: * * With "digest(n)" being the size of the digest for the n-th nsec3param * * =~ (233.3333 + SUM[n=1..n3pc](446.666+digest(n))) * r * * @{ */ #ifndef _ZDB_H #define _ZDB_H #include #include #include #include #include #include /* EDNS -> */ /* <- EDNS */ #ifdef __cplusplus extern "C" { #endif #define ZDB_ROOT_TAG 0x544f4f5242445a /* "ZDBROOT" */ #define ZDB_DOMAIN_ROOT_TAG 0x524e4d4442445a /* "ZDBDMNR" */ #define ZDBZONE_TAG 0x454e4f5a42445a /* "ZDBZONE" */ /* * This fingerprint feature has been added so libraries could check they are compatible */ typedef enum { DNSDB_TSIG=1, DNSDB_ACL=2, DNSDB_NSEC=4, DNSDB_NSEC3=8, DNSDB_ZALLOC=16, DNSDB_DEBUG=32, DNSDB_RRCACHE=64 } dnsdb_fingerprint; static inline dnsdb_fingerprint dnsdb_getmyfingerprint() { dnsdb_fingerprint ret = (dnsdb_fingerprint)(0 #if ZDB_HAS_TSIG_SUPPORT | DNSDB_TSIG #endif #if ZDB_HAS_ACL_SUPPORT | DNSDB_ACL #endif #if ZDB_HAS_NSEC_SUPPORT | DNSDB_NSEC #endif #if ZDB_HAS_NSEC3_SUPPORT | DNSDB_NSEC3 #endif #if ZDB_HAS_ZALLOC_SUPPORT | DNSDB_ZALLOC #endif #if DEBUG | DNSDB_DEBUG #endif ) ; return ret; } dnsdb_fingerprint dnsdb_getfingerprint(); u32 dnsdb_fingerprint_mask(); /** @brief Initializes the database internals. * * Initializes the database internals. * Multiple calls is a NOP. * * This is not thread safe. * */ void zdb_init(); void zdb_init_ex(u32 thread_pool_count); /** @brief Destroys the database internals. * * Destroys the database internals. * Multiple calls is a NOP. * * This is not thread safe. * */ void zdb_finalize(); /** @brief Initializes a database. * * Initializes a database. * * @param[in] db a pointer to the zdb structure that will be initialized. * */ void zdb_create(zdb *db); /** * * Puts a zone in the DB. * * If a zone with the same name did exist, returns the old zone (to be released) * and replaces it with the one given as a parameter. * * This function temporarily locks the database for writing. * The zone added gets its RC increased. * * @param db the database * @param zone the zone to mount (will be RC++) * @return the previously mounted zone (to be RC--) */ zdb_zone *zdb_set_zone(zdb *db, zdb_zone* zone); zdb_zone *zdb_remove_zone(zdb *db, dnsname_vector *name); zdb_zone *zdb_remove_zone_from_dnsname(zdb *db, const u8 *dnsname); static inline void zdb_query_ex_answer_create(zdb_query_ex_answer *ans_auth_add) { ZEROMEMORY(ans_auth_add, sizeof(zdb_query_ex_answer)); } /** * @brief Queries the database given a message * * @param db the database * @param mesg the message * @param pool_buffer a big enough buffer used for the memory pool */ void zdb_query_and_update(zdb *db, message_data *mesg, u8 * restrict pool_buffer); /** * @brief Queries the database given a message * * @param db the database * @param mesg the message * @param pool_buffer a big enough buffer used for the memory pool * @param rrl_process an RRL callback that controls if the answer is to be made, truncated or dropped * * @return the RRL status of the message (probably useless) */ ya_result zdb_query_and_update_with_rrl(zdb *db, message_data *mesg, u8 * restrict pool_buffer, rrl_process_callback *rrl_process); /** * Destroys a zdb_query_ex_answer structure created with zdb_query_* * Kept for compatibility. * * @param ans_auth_add */ #define zdb_query_ex_answer_destroy(unused__) ((void)unused__) /** * @brief Writes the answer into the message. * * Writes the content of a zdb_query_ex_answer into a message_data. * * Returns the offset in the packet. * * CANNOT FAIL ! * * @param message * @param answer_set * @return */ ya_result zdb_query_message_update(message_data* message, zdb_query_ex_answer* answer_set); /** * @brief Writes the answer into the message, using an RRL callback. * * Writes the content of a zdb_query_ex_answer into a message_data if the RRL callback allows it. * * Returns the offset in the packet. * * @param message * @param answer_set * @return */ #if 0 /* fix */ #else static inline ya_result zdb_query_message_update_with_rrl(message_data* mesg, zdb_query_ex_answer* answer_set, rrl_process_callback *rrl_process) { ya_result rrl = rrl_process(mesg, answer_set); return rrl; } #endif /** * This function should not be used anymore. Please consider using zdb_append_ip_records instead. * * @param db * @param name_ * @param ttlrdata_out_a * @param ttlrdata_out_aaaa * @return */ ya_result zdb_query_ip_records(zdb* db, const u8* name_, zdb_packed_ttlrdata **ttlrdata_out_a, zdb_packed_ttlrdata **ttlrdata_out_aaaa); /** * * Appends all A and AAAA records found in the database for the given fqdn * Given the nature of the list, what is returned is a copy. * The call locks the database for reading, then each involved zone for reading. * Locks are released before the function returns. * The port field of the host_address is set to a given port (network order) * * @param db database * @param name_ fqdn * @param target_list list * @param network_order_port u16 * @return */ ya_result zdb_append_ip_records_with_port_ne(zdb* db, const u8* name_, host_address *target_list, u16 network_order_port); /** * * Appends all A and AAAA records found in the database for the given fqdn * Given the nature of the list, what is returned is a copy. * The call locks the database for reading, then each involved zone for reading. * Locks are released before the function returns. * The port is set to 53 (in network order) * * @param db database * @param name_ fqdn * @param target_list list * @return */ ya_result zdb_append_ip_records(zdb* db, const u8* name_, host_address *target_list); /** @brief Destroys the database * * Destroys a database. (Empties it) * * @param[in] db the database to destroy * */ void zdb_destroy(zdb* db); /** * Looks for a zone and tells if zone is marked as invalid. * The zone can only be invalid if it exists. * * @param db * @param origin * @param zclass * @return */ bool zdb_is_zone_invalid(zdb *db, const u8 *origin); /** @brief DEBUG: Prints the content of the database. * * DEBUG: Prints the content of the database. * * @param[in] db the database to print * */ void zdb_signature_check(int so_zdb, int so_zdb_zone, int so_zdb_zone_label, int so_zdb_rr_label, int so_mutex_t); #define ZDB_API_CHECK() zdb_signature_check(sizeof(zdb),sizeof(zdb_zone),sizeof(zdb_zone_label),sizeof(zdb_rr_label),sizeof(mutex_t)) #if DEBUG /** * DEBUG */ void zdb_print(zdb *db, output_stream *os); #endif #ifdef __cplusplus } #endif #endif /* _ZDB_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_config.h0000644000000000000000000000013214505005531023167 xustar000000000000000030 mtime=1695812441.498968668 30 atime=1695812445.798030239 30 ctime=1695812494.964734405 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_config.h0000664000374500037450000001264614505005531023142 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup config Database configuration * @ingroup dnsdb * @brief Database configuration * * Database configuration #defines * * @{ */ #ifndef _ZDB_CONFIG_H #define _ZDB_CONFIG_H #include #include #ifdef __cplusplus extern "C" { #endif #define DEFAULT_ASSUMED_CPU_COUNT 2 /** * Inlines the find operation of the AVLs/BTREEs */ #define ZDB_INLINES_AVL_FIND 1 /** * Inlines the quick operation of the HTBT */ #define ZDB_INLINES_HTBT_FIND 1 /** * * Enables or disables the use of openssl for digital signatures. * Disabling this is not fully supported yet. (Not at all actually) * * MANDATORY: 1 (for now) * */ #define ZDB_OPENSSL_SUPPORT 1 /* * Use the threadpool system instead of the raw threads */ #define ZDB_USE_THREADPOOL 1 /* Here disable all the DNSSEC related third party libs */ #if !ZDB_HAS_DNSSEC_SUPPORT #undef ZDB_OPENSSL_SUPPORT #define ZDB_OPENSSL_SUPPORT 0 #endif /** * * Enables or disables caching. * * 0 => global_resource_record field not needed * 1 => global_resource_record field is the cache * */ #ifndef ZDB_HAS_RRCACHE_ENABLED //#error "ZDB_HAS_RRCACHE_ENABLED has not been defined" #define ZDB_HAS_RRCACHE_ENABLED 0 #endif /** * DEBUG: Ensures that the memory allocated by ZALLOC is trashed. * This is of course to avoid uninitialized memory issues. * * Please disable for production. * * Recommended value: 0 */ #define DNSCORE_DEBUG_ZALLOC_TRASHMEMORY 0 /*DEBUG*/ /** * If the number of items in a dictionnary goes beyond this number, the dictionnary * will change from a balanced tree (AVL) to an hash-table of balanced trees. * * Recommended value: 500000 * */ #define ZDB_HASHTABLE_THRESHOLD 500000 /** * * @note 20141006 edf -- ZDB_RECORDS_MAX_CLASS set to 1 allows several optimisations * * Number of classes [1..n] to support. * Set to 1 to support only the IN class * * Setting this to 1 also enables some code optimizations. * * Please note that the caller is responsible for checking that (qclass>0)&&(qclass<=ZDB_RECORDS_MAX_CLASS) * zdb_query_* does the check but really should not. * It's faster to check that a qclass is in that range or is not "CHaos" or "HeSiod" on the caller's side. * (ie: if ==IN -> query, else if ==CH answer chaos, else answer no match.) * * Recommended value: 1 * */ #define ZDB_RECORDS_MAX_CLASS 1 /** * Previously, readers had to be "stopped" before any write was done into the database. It's a reasonably fast mechanism. * With the drastic improve of the MT model on kernels > 3.x, the zone can now be explicitly locked by readers. * The first experiments tends to show that the price is minimal. * The lock can still be drastically improved. * * == 0: no lock * != 0: lock * * The locking mechanism itself can be vastly improved */ #define ZDB_EXPLICIT_READER_ZONE_LOCK 1 /** * The maximum number of loops allowed with a cname. */ #define ZDB_CNAME_LOOP_MAX 20 /** * The fixed minimum number of file descriptors opened at the same time for journals */ #define ZDB_JOURNAL_FD_MIN 4096 /** * The fixed maximum number of file descriptors opened at the same time for journals */ #define ZDB_JOURNAL_FD_MAX 4096 /** * The default maximum number of file descriptors opened at the same time for journals */ #define ZDB_JOURNAL_FD_DEFAULT 512 /** * How many signatures will be tried initially in the first batch. */ #define ZDB_ZONE_MAINTENANCE_LABELS_AT_ONCE_DEFAULT 50 // the initial value for labels processed at once #ifdef __cplusplus } #endif #endif /* _ZDB_CONFIG_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_error.h0000644000000000000000000000013214505005531023053 xustar000000000000000030 mtime=1695812441.523969026 30 atime=1695812445.799030253 30 ctime=1695812494.966734434 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_error.h0000664000374500037450000001371614505005531023025 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup error Database error handling * @ingroup dnsdb * @brief Database error handling * * @{ */ #ifndef _ZDB_ERROR_H #define _ZDB_ERROR_H #include #ifdef __cplusplus extern "C" { #endif /** @brief a negative number that marks the start of the ZDB error codes */ #define ZDB_ERROR_BASE 0x80040000 #define ZDB_ERROR_CODE(code_) ((s32)(ZDB_ERROR_BASE+(code_))) #define ZDB_ERROR_GENERAL ZDB_ERROR_CODE(0x0000) #define ZDB_ERROR_KEY_NOTFOUND ZDB_ERROR_CODE(0x0001) // DATABASE KEY #define ZDB_ERROR_DELETEFROMEMPTY ZDB_ERROR_CODE(0x0002) // DATABASE could not delete because collection is empty #define ZDB_ERROR_NOSUCHCLASS ZDB_ERROR_CODE(0x0003) // DATABASE class not found #define ZDB_ERROR_NOSOAATAPEX ZDB_ERROR_CODE(0x0004) // DATABASE zone has not SOA #define ZDB_ERROR_COULDNOTOOBTAINZONEIMAGE ZDB_ERROR_CODE(0x0005) #define ZDB_ERROR_CORRUPTEDSOA ZDB_ERROR_CODE(0x1001) // RECORD soa is corrupted #define ZDB_ERROR_ZONE_IS_NOT_SIGNED ZDB_ERROR_CODE(0x3001) // DATABASE zone dnssec // not used #define ZDB_ERROR_ZONE_IS_ALREADY_BEING_SIGNED ZDB_ERROR_CODE(0x3002) // DATABASE zone dnssec #define ZDB_ERROR_ZONE_INVALID ZDB_ERROR_CODE(0x3003) // DATABASE zone dynamic update #define ZDB_ERROR_ZONE_IS_NOT_DNSSEC ZDB_ERROR_CODE(0x3004) // DATABASE zone dnssec // not used #define ZDB_ERROR_ZONE_NO_ZSK_PRIVATE_KEY_FILE ZDB_ERROR_CODE(0x3005) // DATABASE zone dnssec #define ZDB_ERROR_ZONE_NO_ACTIVE_DNSKEY_FOUND ZDB_ERROR_CODE(0x3006) // DATABASE zone dnssec // not used #define ZDB_ERROR_ZONE_NOT_IN_DATABASE ZDB_ERROR_CODE(0x3007) // DATABASE zone #define ZDB_ERROR_ZONE_NOT_MAINTAINED ZDB_ERROR_CODE(0x3008) // DATABASE zone #define ZDB_ERROR_ZONE_OPERATION_WOULD_BLOCK ZDB_ERROR_CODE(0x3009) // DATABASE zone #define ZDB_READER_WRONGNAMEFORZONE ZDB_ERROR_CODE(0x4001) // DATABASE zone load // not used #define ZDB_READER_ZONENOTLOADED ZDB_ERROR_CODE(0x4002) // DATABASE zone load // not used #define ZDB_READER_FIRST_RECORD_NOT_SOA ZDB_ERROR_CODE(0x4003) // DATABASE zone load #define ZDB_READER_ANOTHER_DOMAIN_WAS_EXPECTED ZDB_ERROR_CODE(0x4004) // DATABASE zone load #define ZDB_READER_NSEC3WITHOUTNSEC3PARAM ZDB_ERROR_CODE(0x4005) // DATABASE zone load // not used #define ZDB_READER_MIXED_DNSSEC_VERSIONS ZDB_ERROR_CODE(0x4006) // DATABASE zone load // not used #define ZDB_READER_ALREADY_LOADED ZDB_ERROR_CODE(0x4007) // DATABASE zone load // not used #define ZDB_READER_NSEC3PARAMWITHOUTNSEC3 ZDB_ERROR_CODE(0x4008) // DATABASE zone load // not used #define ZDB_ERROR_ICMTL_NOTFOUND ZDB_ERROR_CODE(0x5001) // ICMTL #define ZDB_ERROR_ICMTL_STATUS_INVALID ZDB_ERROR_CODE(0x5002) // ICMTL // not used #define ZDB_ERROR_ICMTL_FOLDERPATHTOOLONG ZDB_ERROR_CODE(0x5003) // ICMTL // not used #define ZDB_JOURNAL_WRONG_PARAMETERS ZDB_ERROR_CODE(0x6001) #define ZDB_JOURNAL_READING_DID_NOT_FOUND_SOA ZDB_ERROR_CODE(0x6002) // nowhere in a scan // not used #define ZDB_JOURNAL_SOA_RECORD_EXPECTED ZDB_ERROR_CODE(0x6003) // record being read was expected to be an SOA // not used #define ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE ZDB_ERROR_CODE(0x6004) #define ZDB_JOURNAL_FEATURE_NOT_SUPPORTED ZDB_ERROR_CODE(0x6005) #define ZDB_JOURNAL_NOT_INITIALISED ZDB_ERROR_CODE(0x6006) #define ZDB_JOURNAL_IS_BUSY ZDB_ERROR_CODE(0x6007) #define ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY ZDB_ERROR_CODE(0x6008) #define ZDB_JOURNAL_SERIAL_RANGE_LOCKED ZDB_ERROR_CODE(0x6009) #define ZDB_JOURNAL_LOOKS_CORRUPTED ZDB_ERROR_CODE(0x6081) #define ZDB_JOURNAL_UNEXPECTED_MAGIC ZDB_ERROR_CODE(0x6082) #define ZDB_JOURNAL_SHORT_READ ZDB_ERROR_CODE(0x6083) #define ZDB_JOURNAL_SIZE_LIMIT_TOO_SMALL ZDB_ERROR_CODE(0x6084) #define ZDB_JOURNAL_SHOULD_NOT_BE_USED(err__) (((err__) >= ZDB_JOURNAL_LOOKS_CORRUPTED) && ((err__) <= ZDB_JOURNAL_SHORT_READ) ) void zdb_register_errors(); #ifdef __cplusplus } #endif #endif /* _ZDB_ERROR_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_icmtl.h0000644000000000000000000000013214505005531023032 xustar000000000000000030 mtime=1695812441.512968869 30 atime=1695812445.798030239 30 ctime=1695812494.968734463 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_icmtl.h0000664000374500037450000000644414505005531023004 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdb * @ingroup dnsdb * @brief journal file & incremental changes * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #ifndef HAS_DYNUPDATE_DIFF_ENABLED #error "HAS_DYNUPDATE_DIFF_ENABLED not defined" #endif #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define ZDB_ICMTL_REPLAY_SERIAL_OFFSET 1 // avoids scanning #define ZDB_ICMTL_REPLAY_SERIAL_LIMIT 2 // don't try to go beyond the set serial struct zdb_icmtl_replay_commit_state { u32 dnskey_removed; u32 dnskey_added; u32 end_serial; #if __SIZEOF_POINTER__ == 8 u32 reserved0; #endif #if HAS_EVENT_DYNAMIC_MODULE ptr_vector dnskey_added_list; ptr_vector dnskey_removed_list; #endif }; typedef struct zdb_icmtl_replay_commit_state zdb_icmtl_replay_commit_state; ya_result zdb_icmtl_replay_commit_ex(zdb_zone *zone, input_stream *is, zdb_icmtl_replay_commit_state *out_state); ya_result zdb_icmtl_replay_commit(zdb_zone *zone, input_stream *is, u32 *out_serial_after_replayp); /** * Replays incremental changes for the zone, looking in the directory for the files (.ix) */ ya_result zdb_icmtl_replay(zdb_zone *zone); #ifdef __cplusplus } #endif /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_record.h0000644000000000000000000000013214505005531023200 xustar000000000000000030 mtime=1695812441.490968553 30 atime=1695812445.798030239 30 ctime=1695812494.970734491 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_record.h0000664000374500037450000003202014505005531023137 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup records Internal functions for the database: resource records. * @ingroup dnsdb * @brief Internal functions for the database: resource records. * * Internal functions for the database: resource records. * * Handling of the class->type->ttl+rdata list. * * @{ */ #ifndef _ZDB_RECORD_H #define _ZDB_RECORD_H #include #include #include #define ZDB_RECORD_USES_INLINE 1 #if ZDB_RECORD_USES_INLINE #include #endif #ifdef __cplusplus extern "C" { #endif #define SUCCESS_STILL_RECORDS SUCCESS #define SUCCESS_LAST_RECORD SUCCESS + 1 /** * * Internal functions for the ZDB structure. */ #define ZDB_RECORDS_COLLECTION_TAG 0x4343455242445a /** "ZDBRECC" */ #define ZDB_RECORD_RDATA_TAG 0x5243455242445a /** "ZDBRECR" */ #define COULD_BE_GLUE(type) (((type)==TYPE_A)||((type)==TYPE_AAAA)||((type)==TYPE_A6)) /** @brief Inserts a resource record into the resource collection * * Inserts a ttl-rdata record into the rtl-rdata collection * * @param[in] collection the collection * @param[in] class_ the class of the resource record * @param[in] type the type of the resource record * @param[in] ttl the ttl of the resource record * @param[in] rdata_size the size of the rdata of the resource record * @param[in] rdata a pointer to the rdata of the resource record * * @return OK in case of success. */ /* 4 USES */ void zdb_record_insert(zdb_rr_collection* collection, u16 type, zdb_packed_ttlrdata* ttlrdata); /** @brief Inserts a resource record into the resource collection, checks for dups * * Do not assume anything. * Inserts a ttl-rdata record into the rtl-rdata collection * The caller loses the property of the record. * If the record is a dup, it is destroyed. * * @param[in] collection the collection * @param[in] class_ the class of the resource record * @param[in] type the type of the resource record * @param[in] ttl the ttl of the resource record * @param[in] rdata_size the size of the rdata of the resource record * @param[in] rdata a pointer to the rdata of the resource record * * @return OK in case of success. */ /* 1 USE */ bool zdb_record_insert_checked(zdb_rr_collection* collection, u16 type, zdb_packed_ttlrdata* record); /** @brief Inserts a resource record into the resource collection, checks for dups * * Do not assume anything. * Inserts a ttl-rdata record into the rtl-rdata collection * The caller loses the property of the record. * If the record is a dup, it is destroyed. * TTL value is not propagated through the resource record set * * @param[in] collection the collection * @param[in] class_ the class of the resource record * @param[in] type the type of the resource record * @param[in] ttl the ttl of the resource record * @param[in] rdata_size the size of the rdata of the resource record * @param[in] rdata a pointer to the rdata of the resource record * * @return TRUE in case of success. */ /* 1 USE */ bool zdb_record_insert_checked_keep_ttl(zdb_rr_collection* collection, u16 type, zdb_packed_ttlrdata* record); #if !ZDB_RECORD_USES_INLINE /** @brief Finds and return all the a resource record matching the class and type * * Finds and returl all the a resource record matching the class and type * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return the first record, or NULL of none has been found. */ /* 5 USES */ zdb_packed_ttlrdata* zdb_record_find(const zdb_rr_collection* collection, u16 type); /** @brief Finds and return a pointer to the list of all the a resource record matching the class and type * * Finds and returns a pointer to the list of all the a resource record matching the class and type * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return the first record, or NULL of none has been found. */ zdb_packed_ttlrdata** zdb_record_findp(const zdb_rr_collection* collection, u16 type); /** @brief Finds and return all the a resource record matching the class and type * Create the node if no such resource exists * * Finds and returl all the a resource record matching the class and type * Create the node if no such resource exists * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return the first record, or NULL of none has been found. */ zdb_packed_ttlrdata** zdb_record_find_insert(zdb_rr_collection* collection, u16 type); #else /** @brief Finds and return all the a resource record matching the class and type * * Finds and returns all the a resource record matching the class and type * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return the first record, or NULL of none has been found. */ static inline zdb_packed_ttlrdata* zdb_record_find(const zdb_rr_collection* collection, u16 type) { zdb_packed_ttlrdata* record_list = (zdb_packed_ttlrdata*)btree_find(collection, type); return record_list; } /** @brief Finds and return a pointer to the list of all the a resource record matching the class and type * * Finds and returns a pointer to the list of all the a resource record matching the class and type * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return the first record, or NULL of none has been found. */ static inline zdb_packed_ttlrdata** zdb_record_findp(const zdb_rr_collection* collection, u16 type) { zdb_packed_ttlrdata** record_list = (zdb_packed_ttlrdata**)btree_findp(collection, type); return record_list; } /** @brief Finds and return all the a resource record matching the class and type * Create the node if no such resource exists * * Finds and returl all the a resource record matching the class and type * Create the node if no such resource exists * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return the first record, or NULL of none has been found. */ static inline zdb_packed_ttlrdata** zdb_record_find_insert(zdb_rr_collection* collection, u16 type) { yassert(collection != NULL); zdb_packed_ttlrdata** record_list = (zdb_packed_ttlrdata**)btree_insert(collection, type); return record_list; } #endif /** @brief Deletes all the a resource record matching the class and type * * Deletes and return all the a resource record matching the class and type * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return OK in case of success. ERROR if no record were deleted. */ /* 2 USES */ ya_result zdb_record_delete(zdb_rr_collection* collection, u16 type); /** @brief Deletes the a resource record matching the class, type, ttl, rdata * * Deletes the a resource record matching the class, type, ttl, rdata * * @param[in] collection the collection * @param[in] type the type of the resource record to match * @param[in] ttl the ttl of the resource record to match * @param[in] rdata_size the size of the rdata of the resource record to match * @param[in] rdata a pointer to the rdata of the resource record to match * * @return SUCCESS if we removed the last record of this type. * >SUCCESS if we removed the record but other of this type are still available. * ERROR if no record were deleted. * */ /* 4 USES */ ya_result zdb_record_delete_exact(zdb_rr_collection* collection, u16 type, const zdb_ttlrdata* ttl_rdata); /** @brief Deletes the a resource record matching the class, type, ttl, rdata (safer) * * Makes a copy of the data to delete first. This allow using the record from the DB as a base for removal. * Deletes the a resource record matching the class, type, ttl, rdata * * @param[in] collection the collection * @param[in] type the type of the resource record to match * @param[in] ttl the ttl of the resource record to match * @param[in] rdata_size the size of the rdata of the resource record to match * @param[in] rdata a pointer to the rdata of the resource record to match * * @return SUCCESS if we removed the last record of this type. * >SUCCESS if we removed the record but other of this type are still available. * ERROR if no record were deleted. * */ ya_result zdb_record_delete_self_exact(zdb_rr_collection* collection, u16 type, const zdb_ttlrdata *ttlrdata_); /** @brief Destroys all the a resource record of the collection * * Destroys all the a resource record of the collection * * @param[in] collection the collection to destroy */ /* 23 USES */ void zdb_record_destroy(zdb_rr_collection* collection); /** @brief Checks if a collection is empty * * Checks if a collection is empty * * @return TRUE if the collection is empty, FALSE otherwise. */ /* 1 USE */ bool zdb_record_isempty(const zdb_rr_collection* collection); /** @brief Checks if two records are equal. * * Checks if two records are equal. * * @return TRUE if the records are equal, FALSE otherwise. */ /* 1 USE */ bool zdb_record_equals_unpacked(const zdb_packed_ttlrdata* a, const zdb_ttlrdata* b); /** @brief Checks if two records are equal. * * Checks if two records are equal. * * @return TRUE if the records are equal, FALSE otherwise. */ /* 1 USE */ bool zdb_record_equals(const zdb_packed_ttlrdata* a, const zdb_packed_ttlrdata* b); /** * @brief Copies the soa rdata to an soa_rdata native structure. * * Copies the soa of a zone to an soa_rdata structure. * No memory is allocated for the soa_rdata. If the zone is destroyed, * the soa_rdata becomes invalid. * * @param[in] zone a pointer to the zone * @param[out] soa_out a pointer to an soa_rdata structure */ ya_result zdb_record_getsoa(const zdb_packed_ttlrdata* soa, soa_rdata* soa_out); /** * @brief Allocated and duplicates the content of the source */ zdb_ttlrdata *zdb_ttlrdata_clone(const zdb_ttlrdata* source); /** * @brief Allocated and duplicates the first bytes of content of the source * This is mostly used to clone an NSEC3 record into an NSEC3PARAM */ zdb_ttlrdata *zdb_ttlrdata_clone_resized(const zdb_ttlrdata* source, u32 rdata_newsize); /** * @brief Frees the content of the source */ void zdb_ttlrdata_delete(zdb_ttlrdata* record); /** * DEBUG */ void zdb_record_print_indented(zdb_rr_collection collection, output_stream *os, int indent); void zdb_record_print(zdb_rr_collection collection, output_stream *os); /** * Initialises and sets-up a type_bit_maps_context from a zdb_rr_collection. * Returns the size of the bitmap. */ u16 zdb_record_bitmap_type_init(const zdb_rr_collection collection, type_bit_maps_context *bitmap); #ifdef __cplusplus } #endif #endif /* _ZDB_RECORD_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_rr_label.h0000644000000000000000000000013114505005531023503 xustar000000000000000030 mtime=1695812441.516968926 30 atime=1695812445.798030239 29 ctime=1695812494.97273452 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_rr_label.h0000664000374500037450000003211114505005531023444 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup records_labels Internal functions for the database: zoned resource records label. * @ingroup dnsdb * @brief Internal functions for the database: zoned resource records label. * * Internal functions for the database: zoned resource records label. * * @{ */ #ifndef _RR_LABEL_H #define _RR_LABEL_H #include #ifdef __cplusplus extern "C" { #endif #define ZDB_RR_LABEL_DELETE_NODE COLLECTION_PROCESS_DELETENODE /* = 2 matches the dictionary delete node */ #define ZDB_RR_LABEL_DELETE_TREE 3 /* */ #define ZDB_RRLABEL_TAG 0x4c424c525242445a /** "ZDBRRLBL" */ /** * Instanciate a new rr_label. */ zdb_rr_label* zdb_rr_label_new_instance(const u8* label_name); /** * @brief Finds the resource record label matching a path of labels starting from another rr label * * Finds the resource record label matching a path of labels starting from another rr label * Typically the starting label is a zone cut. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found */ /* 3 USES */ zdb_rr_label* zdb_rr_label_find_exact(zdb_rr_label* apex,dnslabel_vector_reference path,s32 path_index); /** * @brief Finds the resource record label matching a path of labels starting from another rr label or the wildcard label * * Finds the resource record label matching a path of labels starting from another rr label or the wildcard label * Typically the starting label is a zone cut. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label, the * label or NULL if none of them has not been found */ /* NOT USED (YET) */ zdb_rr_label* zdb_rr_label_find(zdb_rr_label* apex, dnslabel_vector_reference sections, s32 index); int zdb_rr_label_find_path(zdb_rr_label* apex, dnslabel_vector_reference sections, s32 index, zdb_rr_label** out_array_64); zdb_rr_label* zdb_rr_label_find_from_name(zdb_zone* zone, const u8 *fqdn); int zdb_rr_label_find_path_from_name(zdb_zone *zone, const u8 *fqdn, zdb_rr_label** out_array_64); zdb_rr_label* zdb_rr_label_find_from_name_delete_empty_terminal(zdb_zone* zone, const u8 *fqdn); zdb_rr_label* zdb_rr_label_stack_find(zdb_rr_label* apex, const_dnslabel_stack_reference sections, s32 pos, s32 index); zdb_rr_label* zdb_rr_label_find_child(zdb_rr_label* parent, const u8* dns_label); /** * @brief Finds the closest resource record label matching a path of labels starting from another rr label * * Finds the resource record label matching a path of labels starting from another rr label * Typically the starting label is a zone cut. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[inout] path_index the index of the top of the stack, set the index of the label in the stack at return * * @return the matching label or the apex if none has been found */ /* 3 USES */ zdb_rr_label* zdb_rr_label_find_closest(zdb_rr_label* apex, dnslabel_vector_reference path, s32* closest_level); zdb_rr_label* zdb_rr_label_find_closest_authority(zdb_rr_label* apex, dnslabel_vector_reference path, s32* closest_level); struct zdb_rr_label_find_ext_data { zdb_rr_label *authority; zdb_rr_label *closest; zdb_rr_label *answer; s32 authority_index; s32 closest_index; }; typedef struct zdb_rr_label_find_ext_data zdb_rr_label_find_ext_data; zdb_rr_label* zdb_rr_label_find_ext(zdb_rr_label* apex, dnslabel_vector_reference sections, s32 index_, zdb_rr_label_find_ext_data *ext); /** * @brief Returns the authority fqdn * * Returns the pointer to the authority fqdn located inside the qname (based on the rr_label_info) * * @param qname * @param rr_label_info * @return */ static inline const u8 * zdb_rr_label_info_get_authority_qname(const u8 *qname, const zdb_rr_label_find_ext_data *rr_label_info) { const u8 * authority_qname = qname; s32 i = rr_label_info->authority_index; while(i > 0) { authority_qname += authority_qname[0] + 1; i--; } return authority_qname; } /** * @brief Adds the resource record label matching a path of labels starting from another rr label * * Adds the resource record label matching a path of labels starting from another rr label * Typically the starting label is a zone cut. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found */ /* 1 USE */ zdb_rr_label* zdb_rr_label_add(zdb_zone* zone, dnslabel_vector_reference sections, s32 index); /** * @brief Deletes the resource record of the given type on the label matching a path of labels starting from another rr label * * Deletes the resource record of the given type on the label matching a path of labels starting from another rr label * Typically the starting label is a zone cut. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found */ /* 2 USES */ ya_result zdb_rr_label_delete_record(zdb_zone* zone, dnslabel_vector_reference path, s32 path_index, u16 type); /** * @brief Deletes the resource record of the given type on the label matching a path of labels starting from another rr label * * Deletes the resource record of the given type on the label matching a path of labels starting from another rr label * Typically the starting label is a zone cut. * This variation on zdb_rr_label_delete_record also removes labels that are empty terminals even if they are linked by a dnssec node. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found */ ya_result zdb_rr_label_delete_record_and_empty_terminal(zdb_zone* zone, dnslabel_vector_reference path, s32 path_index, u16 type); /** * @brief Deletes the resource record of the given type, ttl and rdata on the label matching a path of labels starting from another rr label * * Deletes the resource record of the given type, ttl and rdata on the label matching a path of labels starting from another rr label * Typically the starting label is a zone cut. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found */ /* 1 USE */ ya_result zdb_rr_label_delete_record_exact(zdb_zone* zone, dnslabel_vector_reference path, s32 path_index, u16 type, const zdb_ttlrdata* ttlrdata); /** * For all tool to browse all labels under this one * * @param rr_label * @param type * @return */ typedef ya_result zdb_rr_label_forall_cb(zdb_rr_label *rr_label, const u8 *rr_label_fqdn, void *data); ya_result zdb_rr_label_forall_children_of_fqdn(zdb_rr_label *rr_label, const u8 *rr_label_fqdn, zdb_rr_label_forall_cb *callback, void *data); /** * @brief Deletes an EMPTY label * * Deletes an EMPTY label an all it's EMPTY parents * Parents bound to an NSEC structures are not removed * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found */ static inline zdb_packed_ttlrdata* zdb_rr_label_get_rrset(const zdb_rr_label *rr_label, u16 type) { zdb_packed_ttlrdata* rrset = zdb_record_find(&rr_label->resource_record_set, type); return rrset; } static inline bool zdb_rr_label_has_rrset(const zdb_rr_label *rr_label, u16 type) { bool ret = (zdb_rr_label_get_rrset(rr_label, type) != NULL); // zone is locked return ret; } /** * @brief Destroys a zone label and its contents * * Destroys a zone label and its contents * * @param[in] zone_labep a pointer to a pointer to the label to destroy * */ /* 1 USE */ void zdb_rr_label_destroy(zdb_zone* zone, zdb_rr_label** rr_labelp); void zdb_rr_label_truncate(zdb_zone* zone, zdb_rr_label *rr_labelp); static inline bool zdb_rr_label_is_glue(const zdb_rr_label* label) { return (label->_flags & (ZDB_RR_LABEL_UNDERDELEGATION | ZDB_RR_LABEL_DELEGATION)) == ZDB_RR_LABEL_UNDERDELEGATION; } static inline bool zdb_rr_label_at_delegation(const zdb_rr_label* label) { return (label->_flags & ZDB_RR_LABEL_DELEGATION) != 0; } #if ZDB_HAS_DNSSEC_SUPPORT /* 2 USES */ #define RR_LABEL_RELEVANT(rr_label_) ((dictionary_notempty(&(rr_label_)->sub))||(btree_notempty((rr_label_)->resource_record_set))||(rr_label_->nsec.dnssec != NULL)) static inline bool zdb_rr_label_has_children(const zdb_rr_label *label) {return dictionary_notempty(&label->sub);} static inline bool zdb_rr_label_has_records(const zdb_rr_label *label) {return btree_notempty(label->resource_record_set);} static inline bool zdb_rr_label_has_no_children(const zdb_rr_label *label) {return dictionary_isempty(&label->sub);} static inline bool zdb_rr_label_has_no_records(const zdb_rr_label *label) {return btree_isempty(label->resource_record_set);} static inline bool zdb_rr_label_has_dnssec_extension(const zdb_rr_label *label) {return label->nsec.dnssec != NULL;} static inline bool zdb_rr_label_is_empty_terminal(const zdb_rr_label *label) { return zdb_rr_label_has_no_children(label) && zdb_rr_label_has_no_records(label); } static inline bool zdb_rr_label_must_keep(const zdb_rr_label *label) { return (label->_flags & ZDB_RR_LABEL_KEEP) != 0; } static inline bool zdb_rr_label_can_be_deleted(const zdb_rr_label *label) { return zdb_rr_label_is_empty_terminal(label) && (!zdb_rr_label_must_keep(label)); } static inline bool zdb_rr_label_cannot_be_deleted(const zdb_rr_label *label) { return (!zdb_rr_label_is_empty_terminal(label)) || zdb_rr_label_must_keep(label); } /* label is only alive because of NSEC3 */ #define RR_LABEL_HASSUB(rr_label_) (dictionary_notempty(&(rr_label_)->sub)) #define RR_LABEL_HASSUBORREC(rr_label_)((dictionary_notempty(&(rr_label_)->sub))||(btree_notempty((rr_label_)->resource_record_set))) #define RR_LABEL_NOSUBNORREC(rr_label_)((dictionary_notempty(&(rr_label_)->sub))&&(btree_notempty((rr_label_)->resource_record_set))) /* 9 USES */ #define RR_LABEL_IRRELEVANT(rr_label_) ((dictionary_isempty(&(rr_label_)->sub))&&(btree_isempty((rr_label_)->resource_record_set))&&(rr_label_->nsec.dnssec == NULL)) #define RR_LABEL_EMPTY_TERMINAL(rr_label_) ((dictionary_isempty(&(rr_label_)->sub))&&(btree_isempty((rr_label_)->resource_record_set))) #else /* 2 USES */ #define RR_LABEL_RELEVANT(rr_label_) (dictionary_notempty(&(rr_label_)->sub)||(btree_notempty((rr_label_)->resource_record_set))) /* 9 USES */ #define RR_LABEL_IRRELEVANT(rr_label_) (dictionary_isempty(&(rr_label_)->sub)&&(btree_isempty((rr_label_)->resource_record_set))) #endif u16 zdb_rr_label_bitmap_type_init(zdb_rr_label *rr_label, type_bit_maps_context *bitmap); void zdb_rr_label_print_indented(const zdb_rr_label *rr_label, output_stream *os, int indent); void zdb_rr_label_print(const zdb_rr_label *rr_label, output_stream *os); #ifdef __cplusplus } #endif #endif /* _rr_LABEL_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_sanitize.h0000644000000000000000000000013214505005531023550 xustar000000000000000030 mtime=1695812441.534969183 30 atime=1695812445.799030253 30 ctime=1695812494.974734549 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_sanitize.h0000664000374500037450000001121214505005531023507 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup zone Functions used to manipulate a zone * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #ifndef _ZDB_SANITIZE_H #define _ZDB_SANITIZE_H #include #ifdef __cplusplus extern "C" { #endif #define SANITY_ERROR_BASE 0x800b0000 #define SANITY_UNEXPECTEDSOA 1 // multiple SOA at apex, or SOA(s) oustide of APEX #define SANITY_MUSTDROPZONE 2 #define SANITY_CNAMENOTALONE 4 // other records along CNAME (only NSEC & RRSIG accepted) of course CNAME is forbidden at APEX #define SANITY_UNEXPECTEDCNAME 8 // CNAME at apex #define SANITY_EXPECTEDNS 16 // no NS at apex or DS found without NS #define SANITY_UNEXPECTEDDS 32 // DS found at APEX #define SANITY_TRASHATDELEGATION 64 #define SANITY_TRASHUNDERDELEGATION 128 #define SANITY_RRSIGTTLDOESNTMATCH 256 // RRSIG original TTL does not match RRSET #define SANITY_RRSIGWITHOUTKEYS 512 #define SANITY_RRSIGWITHOUTSET 1024 // RRSIG covers a record set that's not present in the label #define SANITY_RRSIGOVERRRSIG 2048 // RRSIG covers the RRSIG record set (nonsense) #define SANITY_RRSIGUNDERDELETATION 4096 // RRSIG under a delegation #define SANITY_RRSIGBYKSKOVERNONKEY 8192 // RRSIG by a KSK over a type that's not a DNSKEY #define SANITY_RRSIGBYKSKNOTINAPEX 16384 // RRSIG by a KSK should only appear in APEX (and over a DNSKEY) #define SANITY_LABEL_DELETED 32768 struct zdb_zone_load_parms; struct zdb_sanitize_parms { zdb_zone *zone; #if ZDB_HAS_DNSSEC_SUPPORT u32_set dnskey_set; #endif struct zdb_zone_load_parms *load_parms; u64 types_mask; u32 domains; #if ZDB_HAS_DNSSEC_SUPPORT u32 nsec_extraneous_rrsig; u32 nsec3in_extraneous_rrsig; u32 nsec3out_extraneous_rrsig; u32 nsec_missing_rrsig; u32 nsec3in_missing_rrsig; u32 nsec3out_missing_rrsig; bool has_bogus_rrsig; #endif }; typedef struct zdb_sanitize_parms zdb_sanitize_parms; ya_result zdb_sanitize_rr_set(zdb_zone *zone, zdb_rr_label *label); ya_result zdb_sanitize_rr_label(zdb_zone *zone, zdb_rr_label *label, dnsname_stack *name); ya_result zdb_sanitize_rr_label_with_parent(zdb_zone *zone, zdb_rr_label *label, dnsname_stack *name); ya_result zdb_sanitize_zone_ex(zdb_zone *zone, struct zdb_zone_load_parms *load_parms); ya_result zdb_sanitize_zone(zdb_zone *zone); void zdb_sanitize_parms_finalize(zdb_sanitize_parms *parms); /** * @param load_parms * @param dnssec_modes ZDB_ZONE_NOSEC ZDB_ZONE_NSEC ZDB_ZONE_NSEC3 ZDB_ZONE_NSEC3_OPTOUT */ bool zdb_sanitize_is_good(struct zdb_zone_load_parms *load_parms, u8 dnssec_mode); ya_result zdb_sanitize_zone_rrset_flags(zdb_zone *zone); #ifdef __cplusplus } #endif #endif /* _ZDB_ZONE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_types.h0000644000000000000000000000013214505005531023066 xustar000000000000000030 mtime=1695812441.482968439 30 atime=1695812445.797030225 30 ctime=1695812494.976734577 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_types.h0000664000374500037450000007201214505005531023032 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup types The types used in the database * @ingroup dnsdb * @brief The types used in the database * * The types used in the database * * @{ */ #ifndef _ZDB_TYPES_H #define _ZDB_TYPES_H #include #include #if DNSCORE_HAVE_STDATOMIC_H #include #else #include #endif #include #include #include #include #include #include #include #include #include //#include #include #ifdef __cplusplus extern "C" { #endif struct journal; #define ROOT_LABEL ((u8*)"") #define ZDB_ZONE_LOCK_HAS_OWNER_ID 0 // debug #if ZDB_ZONE_LOCK_HAS_OWNER_ID #pragma message("***********************************************************") #pragma message("***********************************************************") #pragma message("ZDB_ZONE_LOCK_HAS_OWNER_ID 1") #pragma message("***********************************************************") #pragma message("***********************************************************") #endif /* zdb_ttlrdata * * This record is allocated in: * * zdb_zone_load * zdb_add_global * * */ typedef struct zdb_packed_ttlrdata zdb_packed_ttlrdata; struct zdb_packed_ttlrdata { /* DO NOT CHANGE THE ORDER OF THE FIELDS !!! */ zdb_packed_ttlrdata* next; /* 4 8 */ s32 ttl; /* 4 4 */ u16 rdata_size; /* 2 2 */ u8 rdata_start[1]; }; static inline int zdb_packed_ttlrdata_count(const zdb_packed_ttlrdata *rrset) { int count = 0; const zdb_packed_ttlrdata* p = rrset; while(p != NULL) { ++count; p = p->next; } return count; } // a zdb_packed_ttlrdata ready to store a valid SOA struct zdb_packed_ttlrdata_soa { /* DO NOT CHANGE THE ORDER OF THE FIELDS !!! */ zdb_packed_ttlrdata* next; /* 4 8 */ u32 ttl; /* 4 4 */ u16 rdata_size; /* 2 2 */ u8 rdata_start[MAX_SOA_RDATA_LENGTH]; }; #define ZDB_RDATABUF_TAG 0x4655424154414452 #define ZDB_RECORD_TAG 0x4443455242445a /** "ZDBRECD" */ #define ZDB_RECORD_SIZE_FROM_RDATASIZE(rdata_size_) (sizeof(zdb_packed_ttlrdata)-1+(rdata_size_)) #define ZDB_RECORD_SIZE(record_) ZDB_RECORD_SIZE_FROM_RDATASIZE((record_)->rdata_size) #if !DNSCORE_HAS_ZALLOC_SUPPORT #define ZDB_RECORD_ZALLOC(record,ttl_,len_,rdata_) \ { \ MALLOC_OR_DIE(zdb_packed_ttlrdata*,(record),sizeof(zdb_packed_ttlrdata)-1+len_,ZDB_RECORD_TAG); /* ZALLOC IMPOSSIBLE */ \ (record)->ttl=ttl_; \ (record)->rdata_size=len_; \ MEMCOPY(&(record)->rdata_start[0],rdata_,len_); \ } #define ZDB_RECORD_ZALLOC_EMPTY(record,ttl_,len_) \ { \ MALLOC_OR_DIE(zdb_packed_ttlrdata*,(record),sizeof(zdb_packed_ttlrdata)-1+len_,ZDB_RECORD_TAG); /* ZALLOC IMPOSSIBLE */ \ (record)->ttl=ttl_; \ (record)->rdata_size=len_; \ } #define ZDB_RECORD_CLONE(record_s_,record_d_) \ { \ u32 size=sizeof(zdb_packed_ttlrdata)-1+(record_s_)->rdata_size; \ MALLOC_OR_DIE(zdb_packed_ttlrdata*,(record_d_),size,ZDB_RECORD_TAG); /* ZALLOC IMPOSSIBLE */ \ record_d_->ttl=record_s_->ttl; \ record_d_->rdata_size=record_s_->rdata_size; \ MEMCOPY(&(record_d_)->rdata_start[0],&(record_s_)->rdata_start[0],record_s_->rdata_size); \ } #define ZDB_RECORD_ZFREE(record) free(record) #define ZDB_RECORD_SAFE_ZFREE(record) free(record) #else // DNSCORE_HAS_ZALLOC_SUPPORT #define ZDB_RECORD_ZALLOC(record_,ttl_,len_,rdata_) \ { \ u32 size=ZDB_RECORD_SIZE_FROM_RDATASIZE(len_); \ record_=(zdb_packed_ttlrdata*)ZALLOC_BYTES(size, ZDB_RECORD_TAG); \ (record_)->ttl=ttl_; \ (record_)->rdata_size=len_; \ MEMCOPY(&(record_)->rdata_start[0],rdata_,len_); \ } #define ZDB_RECORD_ZALLOC_EMPTY(record_,ttl_,len_) \ { \ u32 size=ZDB_RECORD_SIZE_FROM_RDATASIZE(len_); \ record_=(zdb_packed_ttlrdata*)ZALLOC_BYTES(size, ZDB_RECORD_TAG); \ (record_)->ttl=ttl_; \ (record_)->rdata_size=len_; \ } #define ZDB_RECORD_CLONE(record_s_,record_d_) \ { \ u32 size=ZDB_RECORD_SIZE_FROM_RDATASIZE((record_s_)->rdata_size); \ record_=(zdb_packed_ttlrdata*)ZALLOC_BYTES(size, ZDB_RECORD_TAG); \ record_d_->ttl=record_s_->ttl; \ record_d_->rdata_size=record_s_->rdata_size; \ MEMCOPY(&(record_d_)->rdata_start[0],&(record_s_)->rdata_start[0],record_s_->rdata_size); \ } /* DOES NOT CHECKS FOR NULL */ #define ZDB_RECORD_ZFREE(record_) \ { \ u32 size=ZDB_RECORD_SIZE_FROM_RDATASIZE((record_)->rdata_size); \ ZFREE_BYTES(record_,size) \ } /* DOES CHECKS FOR NULL */ #define ZDB_RECORD_SAFE_ZFREE(record_) \ if(record_ != NULL) \ { \ u32 size=ZDB_RECORD_SIZE_FROM_RDATASIZE((record_)->rdata_size); \ ZFREE_BYTES(record_, size); \ } #endif // DNSCORE_HAS_ZALLOC_SUPPORT /* * These macros existed when 2 different ways for storing the record were * available at compile time. * * The zdb_packed_ttlrdata having proved to be the best (by far), * the other one has been removed. * */ #define ZDB_PACKEDRECORD_PTR_RDATAPTR(record_) (&(record_)->rdata_start[0]) #define ZDB_PACKEDRECORD_PTR_RDATASIZE(record_) ((record_)->rdata_size) static inline int zdb_packed_ttlrdata_compare_records(const zdb_packed_ttlrdata *rr0, const zdb_packed_ttlrdata *rr1) { int s0 = ZDB_PACKEDRECORD_PTR_RDATASIZE(rr0); int s1 = ZDB_PACKEDRECORD_PTR_RDATASIZE(rr1); int s = MIN(s0, s1); int d; if(s > 0) { d = memcmp(ZDB_PACKEDRECORD_PTR_RDATAPTR(rr0), ZDB_PACKEDRECORD_PTR_RDATAPTR(rr1), s); if(d == 0) { d = s0 - s1; if(d == 0) { d = rr0->ttl - rr1->ttl; } } } else { d = s0 - s1; if(d == 0) { d = rr0->ttl - rr1->ttl; } } return d; } #define ZDB_RECORD_PTR_RDATASIZE(record_) ((record_)->rdata_size) #define ZDB_RECORD_PTR_RDATAPTR(record_) ((record_)->rdata_pointer) typedef struct zdb_ttlrdata zdb_ttlrdata; struct zdb_ttlrdata { zdb_ttlrdata* next; /* 4 8 */ u32 ttl; /* 4 4 */ u16 rdata_size; /* 2 2 */ u16 padding_reserved; void* rdata_pointer; /* 4 8 */ }; #define ZDB_PACKEDRECORD_RDATADESC(type_,ttlrdata_) { (type_), ZDB_PACKEDRECORD_PTR_RDATASIZE(ttlrdata_), ZDB_PACKEDRECORD_PTR_RDATAPTR(ttlrdata_)} #define ZDB_RECORD_RDATADESC(type_,ttlrdata_) { (type_), ZDB_RECORD_PTR_RDATASIZE(ttlrdata_), ZDB_RECORD_PTR_RDATAPTR(ttlrdata_)} #define TTLRDATA_INLINESIZE THIS_SHOULD_NOT_BE_USED_IN_PACKED_MODE #define ZDB_RECORD_TTLRDATA_SET(record,ttl_,len_,rdata_) \ { \ (record).ttl=ttl_; \ (record).rdata_size=len_; \ (record).rdata_pointer=rdata_; \ } typedef btree zdb_rr_collection; #define ZDB_RESOURCERECORD_TAG 0x444345524c4c5546 /** "FULLRECD" */ /* zdb_zone */ typedef struct zdb_zone zdb_zone; #define LABEL_HAS_RECORDS(label_) ((label_)->resource_record_set != NULL) typedef struct zdb_resourcerecord zdb_resourcerecord; struct zdb_resourcerecord { zdb_resourcerecord* next; /* 4 8 */ zdb_packed_ttlrdata* ttl_rdata; /* 4 8 */ const u8* name; /* 4 8 */ u16 zclass; /* 2 2 */ u16 rtype; /* 2 2 */ u32 ttl; }; /* 16 28 => 16 32 */ /* zdb_rr_label */ typedef dictionary zdb_rr_label_set; typedef struct zdb_rr_label zdb_rr_label; #if ZDB_HAS_DNSSEC_SUPPORT #if ZDB_HAS_NSEC_SUPPORT typedef struct nsec_label_extension nsec_label; typedef struct nsec_label_extension nsec_label_extension; typedef struct nsec_node nsec_zone; #endif #if ZDB_HAS_NSEC3_SUPPORT typedef struct nsec3_zone nsec3_zone; #endif typedef struct dnssec_zone_extension dnssec_zone_extension; struct dnssec_zone_extension { #if ZDB_HAS_NSEC_SUPPORT /* * A pointer to an array of nsec_label (nsec_label buffer[]) * The size is the same as the dictionnary */ nsec_zone* nsec; #endif #if ZDB_HAS_NSEC3_SUPPORT nsec3_zone* nsec3; #endif }; typedef union nsec_label_union nsec_label_union; struct nsec_label_extension { struct nsec_node* node; }; union nsec_label_union { /* NSEC */ #if ZDB_HAS_NSEC_SUPPORT nsec_label_extension nsec; #endif /* NSEC3 */ #if ZDB_HAS_NSEC3_SUPPORT struct nsec3_label_extension* nsec3; #endif /* Placeholder */ void* dnssec; }; #endif /* * RR_LABEL flags */ /* * For the apex, marks a label as being the apex */ #define ZDB_RR_LABEL_APEX 0x0001 /* * For any label but the apex : marks it as being a delegation (contains an NS record) */ #define ZDB_RR_LABEL_DELEGATION 0x0002 /* * For any label, means there is a delegation (somewhere) above */ #define ZDB_RR_LABEL_UNDERDELEGATION 0x0004 /* * For any label : marks that one owns a '*' label */ #define ZDB_RR_LABEL_GOT_WILD 0x0008 /* * Explicitly mark a label as owner of a (single) CNAME */ #define ZDB_RR_LABEL_HASCNAME 0x0010 /* * Explicitly mark a label as owner of a something that is not a CNAME nor RRSIG nor NSEC */ #define ZDB_RR_LABEL_DROPCNAME 0x0020 #define ZDB_RR_LABEL_N3COVERED 0x0040 // expected coverage #define ZDB_RR_LABEL_N3OCOVERED 0x0080 // expected coverage #if ZDB_HAS_DNSSEC_SUPPORT /* * This flag means that the label has a valid NSEC structure * * IT IS NOT VALID TO CHECK THIS TO SEE IF A ZONE IS NSEC */ #define ZDB_RR_LABEL_NSEC 0x0100 /* * This flag means that the label has a valid NSEC3 structure * * IT IS NOT VALID TO CHECK THIS TO SEE IF A ZONE IS NSEC3 */ #define ZDB_RR_LABEL_NSEC3 0x0200 // structure /* * The zone is (NSEC3) + OPTOUT (NSEC3 should also be set) * * IT IS NOT VALID TO CHECK THIS TO SEE IF A ZONE IS NSEC3 */ #define ZDB_RR_LABEL_NSEC3_OPTOUT 0x0400 // structure #define ZDB_RR_LABEL_DNSSEC_MASK 0x0700 #define ZDB_RR_LABEL_DNSSEC_SHIFT 8 /* * Marks a label so it cannot be deleted. * Used for incremental changes when it is known that an empty terminal will have records added. * (Avoiding to delete then re-create several structures) */ #define ZDB_RR_LABEL_KEEP 0x0800 #endif #define ZDB_RR_LABEL_HAS_NS 0x1000 // quick check of the presence of an NS record #define ZDB_RR_LABEL_HAS_DS 0x2000 // quick check of the presence of an DS record #define ZDB_LABEL_UNDERDELEGATION(__l__) ((((__l__)->_flags)&ZDB_RR_LABEL_UNDERDELEGATION)!=0) #define ZDB_LABEL_ATDELEGATION(__l__) ((((__l__)->_flags)&ZDB_RR_LABEL_DELEGATION)!=0) #define ZDB_LABEL_ATORUNDERDELEGATION(__l__) ((((__l__)->_flags)&(ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION))!=0) struct zdb_rr_label { zdb_rr_label* next; /* dictionnary_node* next */ /* 4 8 */ zdb_rr_label_set sub; /* dictionnary of N children labels */ /* 16 24 */ zdb_rr_collection resource_record_set; /* resource records for the ²label (a btree)*/ /* 4 4 */ #if ZDB_HAS_DNSSEC_SUPPORT nsec_label_union nsec; #endif u16 _flags; /* NSEC, NSEC3, and 6 for future usage ... */ u8 name[1]; /* label */ /* 4 8 */ /* No zone ptr */ }; /* 28 44 => 32 48 */ static inline void zdb_rr_label_flag_or(zdb_rr_label *rr_label, u16 or_mask) { rr_label->_flags |= or_mask; } static inline void zdb_rr_label_flag_and(zdb_rr_label *rr_label, u16 and_mask) { rr_label->_flags &= and_mask; } static inline void zdb_rr_label_flag_or_and(zdb_rr_label *rr_label, u16 or_mask, u16 and_mask) { rr_label->_flags = (rr_label->_flags |or_mask) & and_mask; } static inline bool zdb_rr_label_flag_isset(const zdb_rr_label *rr_label, u16 and_mask) { return (rr_label->_flags & and_mask) != 0; } static inline bool zdb_rr_label_flag_matches(const zdb_rr_label *rr_label, u16 and_mask) { return (rr_label->_flags & and_mask) == and_mask; } static inline bool zdb_rr_label_flag_isclear(const zdb_rr_label *rr_label, u16 and_mask) { return (rr_label->_flags & and_mask) == 0; } static inline u16 zdb_rr_label_flag_get(const zdb_rr_label *rr_label) { return rr_label->_flags; } static inline bool zdb_rr_label_is_apex(const zdb_rr_label *rr_label) { return zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_APEX); } static inline bool zdb_rr_label_is_not_apex(const zdb_rr_label *rr_label) { return zdb_rr_label_flag_isclear(rr_label, ZDB_RR_LABEL_APEX); } #define ZDB_ZONE_MUTEX_EXCLUSIVE_FLAG 0x80 #define ZDB_ZONE_MUTEX_LOCKMASK_FLAG 0x7f #define ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG 0x7f #define ZDB_ZONE_MUTEX_NOBODY GROUP_MUTEX_NOBODY #define ZDB_ZONE_MUTEX_SIMPLEREADER 0x01 /* non-conflicting */ #define ZDB_ZONE_MUTEX_RRSIG_UPDATER 0x82 /* conflicting */ #define ZDB_ZONE_MUTEX_XFR 0x84 /* conflicting, cannot by nature be launched more than once in parallel. new ones have to be discarded */ #define ZDB_ZONE_MUTEX_REFRESH 0x85 /* conflicting, can never be launched more than once. new ones have to be discarded */ #define ZDB_ZONE_MUTEX_DYNUPDATE 0x86 /* conflicting */ #define ZDB_ZONE_MUTEX_UNFREEZE 0x87 /* conflicting, needs to be sure nobody else (ie: the freeze) is acting at the same time */ #define ZDB_ZONE_MUTEX_INVALIDATE 0x88 /* conflicting */ #define ZDB_ZONE_MUTEX_REPLACE 0x89 /* conflicting */ #define ZDB_ZONE_MUTEX_LOAD 0x8a /* conflicting but this case is impossible */ #define ZDB_ZONE_MUTEX_NSEC3 0x8b /* conflicting, marks an hard operation to be done */ #define ZDB_ZONE_MUTEX_DESTROY 0xff /* conflicting, can never be launched more than once. The zone will be destroyed before unlock. */ typedef ya_result zdb_zone_access_filter(const message_data* /*mesg*/, const void* /*zone_extension*/); #define ALARM_KEY_ZONE_SIGNATURE_UPDATE 1 #define ALARM_KEY_ZONE_AXFR_QUERY 2 #define ALARM_KEY_ZONE_REFRESH 3 #define ALARM_KEY_ZONE_DNSKEY_PUBLISH 4 #define ALARM_KEY_ZONE_DNSKEY_UNPUBLISH 5 #define ALARM_KEY_ZONE_DNSKEY_ACTIVATE 6 #define ALARM_KEY_ZONE_DNSKEY_DEACTIVATE 7 #define ALARM_KEY_ZONE_NEXT_AVAILABLE_ID 7 #define ALARM_KEY_ZONE_NOTIFY_SLAVES 8 #define ZDB_ZONE_KEEP_RAW_SIZE 1 #define ZDB_ZONE_STATUS_NEED_REFRESH 1 #define ZDB_ZONE_STATUS_DUMPING_AXFR 2 #define ZDB_ZONE_STATUS_WILL_NOTIFY 4 // in the queue #define ZDB_ZONE_STATUS_MODIFIED 8 // content has been changed since last time (typically, a replay has been done) #define ZDB_ZONE_STATUS_WILL_NOTIFY_AGAIN 16 #define ZDB_ZONE_STATUS_SAVE_CLEAR_JOURNAL_AFTER_MOUNT 32 // if a corrupted chain has been #define ZDB_ZONE_ERROR_STATUS_DIFF_FAILEDNOUSABLE_KEYS 1 /* * The zone has expired or is a stub (while the real zone is being loaded) */ #define ZDB_ZONE_STATUS_INVALID 64 /* * Forbid updates of the zone */ #define ZDB_ZONE_STATUS_FROZEN 128 #define ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF 256 #define ZDB_ZONE_STATUS_GENERATE_CHAIN 512 //#define ZDB_ZONE_STATUS_KEEP_TEXT_UNUSED 16 // when storing an image, always keep it as text (slower, bigger) #define ZDB_ZONE_HAS_OPTOUT_COVERAGE 1 // assumed true, until something else is found #define ZDB_ZONE_MAINTAIN_NOSEC 0 #define ZDB_ZONE_MAINTAIN_NSEC 2 #define ZDB_ZONE_MAINTAIN_NSEC3 4 #define ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT 5 #define ZDB_ZONE_MAINTAIN_MASK 7 #define ZDB_ZONE_RRSIG_PUSH_ALLOWED 8 // feature requested internally #define ZDB_ZONE_MAINTENANCE_ON_MOUNT 16 // means the sanity decided the zone should probably be maintained ASAP #define ZDB_ZONE_MAINTAIN_QUEUED 32 #define ZDB_ZONE_MAINTAINED 64 #define ZDB_ZONE_MAINTENANCE_PAUSED 128 struct dnskey_keyring; /* #define UNSIGNED_TYPE_VALUE_MAX(__type__) ((__type__)~0) #define SIGNED_TYPE_VALUE_MAX(__type__) (((__type__)~0)>>1) #define SIGNED_TYPE_VALUE_MIN(__type__) (((__type__)~0) - (((__type__)~0)>>1)) #define UNSIGNED_VAR_VALUE_MAX(__var__) ((~0ULL)>>((sizeof(~0ULL) - sizeof(__var__)) * 8LL)) #define SIGNED_VAR_VALUE_MAX(__var__) (UNSIGNED_VAR_VALUE_MAX(__var__)>>1) #define SIGNED_VAR_VALUE_MIN(__var__) (UNSIGNED_VAR_VALUE_MAX(__var__) - SIGNED_VAR_VALUE_MAX(__var__)) #define UNSIGNED_VAR_VALUE_IS_MAX(__var__) (__var__ == UNSIGNED_VAR_VALUE_MAX(__var__)) #define SIGNED_VAR_VALUE_IS_MAX(__var__) (__var__ == SIGNED_VAR_VALUE_MAX(__var__)) */ #define ZDB_ZONE_HAS_JNL_REFERENCE 0 struct zdb_zone_update_signatures_ctx { u8 *current_fqdn; s32 earliest_signature_expiration; u16 labels_at_once; s8 chain_index; }; typedef struct zdb_zone_update_signatures_ctx zdb_zone_update_signatures_ctx; struct zdb; struct zdb_zone; typedef ya_result zdb_zone_resolve(struct zdb_zone *zone, message_data *data, struct zdb *db); /** * A zone can be loaded from disk * A zone can be stored to disk * A zone image can be downloaded from a master * * A masters loads an image from a text oh hierarchical image. * If the hierarchical image is allowed as a source (meaning no text image anymore), no AXFR image should ever be stored. * If only the text image is allowed, then the AXFR image should be stored as hierarchical. * * A slave downloads an AXFR image, then incremental changes, and stores the image on disk when the journal requests it. * This last storage step can be done as an AXFR image, a hierarchical image, or even a text image (but that one should not exist on a slave). * It means the only time an AXFR image should (partially) exist on the disk from the time its being downloaded from a master to the time * it's stored again in a (better) form. * */ struct zdb_zone { u8 *origin; /* dnsname, origin */ zdb_rr_label *apex; /* pointer to the zone cut, 1 name for : SOA, NS, ... */ #if ZDB_HAS_DNSSEC_SUPPORT dnssec_zone_extension nsec; #endif zdb_zone_access_filter* query_access_filter; access_control *acl; /** * This pointer is meant to be used by the server so it can associate data with the zone * without having to do the match on its side too. * */ #if ZDB_HAS_DNSSEC_SUPPORT zdb_zone_update_signatures_ctx progressive_signature_update; #endif s32 min_ttl; /* a copy of the min-ttl from the SOA */ /* * AXFR handling. * * In order to be nicer with the resources of the machine and more reactive we are adding a pace mechanism. * MASTER: * init: ts=1, serial = real serial - 1 * axfr(1): ts=0, serial = real serial, writing on disk, streaming to client until axfr_timestamp>1 OR axfr_serial has changed * (both meaning the file has fully been written on disk) * axfr(2): ts=0, serial = real serial, reading from the file being written * axfr(3): ts=T, serial = real serial, reading from the written file * axfr(4): now - ts > too_much, do axfr(1) * SLAVE: * : ts=last time the axfr has been fully done, serial = serial in the axfr on file * */ volatile u32 axfr_timestamp; // The last time when an AXFR has ENDED to be written on disk, if 0, an AXFR is being written right now volatile u32 axfr_serial; // The serial number of the AXFR (being written) on disk volatile u32 text_serial; // The serial number of the TEXT on disk #if ZDB_HAS_DNSSEC_SUPPORT s32 sig_validity_interval_seconds; s32 sig_validity_regeneration_seconds; s32 sig_validity_jitter_seconds; u32 sig_quota; // starts at 100, updated so a batch does not takes more than a fraction of a second #endif alarm_t alarm_handle; // 32 bits volatile s32 rc; // reference counter when it reaches 0, the zone and its content should be destroyed asap volatile s32 lock_count; // the number of owners with the current lock ID volatile u8 lock_owner; // the ID of who can manipulate the zone volatile u8 lock_reserved_owner; // to the next-owner mechanism (reserve an ownership change) volatile u8 _flags; // extended flags (optout coverage) volatile u8 _error_status; // various error status used to avoid repetition volatile atomic_uint_fast32_t _status; // extended status flags for background tasks not part of the normal operations #if ZDB_RECORDS_MAX_CLASS u16 zclass; #endif mutex_t lock_mutex; cond_t lock_cond; #if ZDB_ZONE_LOCK_HAS_OWNER_ID thread_t lock_last_owner_id; thread_t lock_last_reserved_owner_id; #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT stacktrace lock_trace; thread_t lock_id; s64 lock_timestamp; #endif #if ZDB_ZONE_KEEP_RAW_SIZE volatile s64 wire_size; // approximation of the size of a zone. updated on load and store of the zone on disk volatile u64 write_time_elapsed; // the time that was spent writing the zone in a file (ie: axfr) #endif #if ZDB_ZONE_HAS_JNL_REFERENCE /** journal is only to be accessed trough the journal_* functions */ struct journal *_journal; #endif dnsname_vector origin_vector; // note: the origin vector is truncated to it's used length (sparing quite a lot of memory) }; /* 18 34 => 20 40 */ /* zdb_zone_label */ typedef dictionary zdb_zone_label_set; typedef struct zdb_zone_label zdb_zone_label; struct zdb_zone_label { zdb_zone_label* next; /* used to link labels with the same hash into a SLL */ zdb_zone_label_set sub; /* labels of the sub-level */ u8* name; /* label name */ zdb_zone *zone; /* zone cut starting at this level */ }; /* 32 56 */ typedef zdb_zone_label* zdb_zone_label_pointer_array[DNSNAME_MAX_SECTIONS]; /* zdb */ #define ZDB_MUTEX_NOBODY GROUP_MUTEX_NOBODY #define ZDB_MUTEX_READER 0x01 #define ZDB_MUTEX_WRITER 0x82 // only one allowed at once typedef struct zdb zdb; #define ZDBCLASS_TAG 0x5353414c4342445a struct zdb { zdb_zone_label* root; alarm_t alarm_handle; group_mutex_t mutex; u16 zclass; }; typedef zdb_ttlrdata** zdb_ttlrdata_pointer_array; /* * */ typedef struct zdb_query_ex_answer zdb_query_ex_answer; struct zdb_query_ex_answer { zdb_resourcerecord *answer; zdb_resourcerecord *authority; zdb_resourcerecord *additional; u8 depth; // CNAME u8 delegation; // set as an integer to avoid testing for it }; /** * Iterator through the (rr) labels in a zone */ typedef struct zdb_zone_label_iterator zdb_zone_label_iterator; #define ZDB_ZONE_LABEL_ITERATOR_CAN_SKIP_CHILDREN 0 struct zdb_zone_label_iterator /// 47136 bytes on a 64 bits architecture { const zdb_zone* zone; zdb_rr_label* current_label; s32 top; s32 current_top; /* "top" of the label pointer by current_label */ #if ZDB_ZONE_LABEL_ITERATOR_CAN_SKIP_CHILDREN s32 prev_top; /* "top" of the label returned with "_next" */ s32 __reserved__; #endif dnslabel_stack dnslabels; dictionary_iterator stack[DNSNAME_MAX_SECTIONS]; }; #define RRL_PROCEED 0 #define RRL_SLIP 1 #define RRL_DROP 2 typedef ya_result rrl_process_callback(message_data *mesg, zdb_query_ex_answer *ans_auth_add); u32 zdb_zone_get_status(zdb_zone *zone); u32 zdb_zone_set_status(zdb_zone *zone, u32 status); u32 zdb_zone_clear_status(zdb_zone *zone, u32 status); bool zdb_zone_error_status_getnot_set(zdb_zone *zone, u8 error_status); void zdb_zone_error_status_clear(zdb_zone *zone, u8 error_status); /* u8 zdb_zone_get_flags(zdb_zone *zone); u8 zdb_zone_set_flags(zdb_zone *zone, u8 flags); u8 zdb_zone_clear_flags(zdb_zone *zone, u8 flags); */ static inline bool zdb_zone_invalid(zdb_zone *zone) { return (zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_INVALID) != 0; } static inline bool zdb_zone_valid(zdb_zone *zone) { return (zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_INVALID) == 0; } static inline void zdb_zone_set_dumping_axfr(zdb_zone *zone) { zdb_zone_set_status(zone, ZDB_ZONE_STATUS_DUMPING_AXFR); } static inline bool zdb_zone_get_set_dumping_axfr(zdb_zone *zone) { u8 status = zdb_zone_set_status(zone, ZDB_ZONE_STATUS_DUMPING_AXFR); return (status & ZDB_ZONE_STATUS_DUMPING_AXFR) != 0; } static inline void zdb_zone_clear_dumping_axfr(zdb_zone *zone) { zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_DUMPING_AXFR); } static inline bool zdb_zone_is_dumping_axfr(zdb_zone *zone) { return (zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_DUMPING_AXFR) != 0; } static inline void zdb_zone_set_store_clear_journal_after_mount(zdb_zone *zone) { zdb_zone_set_status(zone, ZDB_ZONE_STATUS_SAVE_CLEAR_JOURNAL_AFTER_MOUNT); } static inline void zdb_zone_clear_store_clear_journal_after_mount(zdb_zone *zone) { zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_SAVE_CLEAR_JOURNAL_AFTER_MOUNT); } static inline bool zdb_zone_is_store_clear_journal_after_mount(zdb_zone *zone) { return (zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_SAVE_CLEAR_JOURNAL_AFTER_MOUNT) != 0; } static inline void zdb_zone_set_invalid(zdb_zone *zone) { zdb_zone_set_status(zone, ZDB_ZONE_STATUS_INVALID); } static inline void zdb_zone_clear_invalid(zdb_zone *zone) { zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_INVALID); } static inline bool zdb_zone_is_invalid(zdb_zone *zone) { return (zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_INVALID) != 0; } static inline void zdb_zone_set_frozen(zdb_zone *zone) { zdb_zone_set_status(zone, ZDB_ZONE_STATUS_FROZEN); } static inline void zdb_zone_clear_frozen(zdb_zone *zone) { zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_FROZEN); } static inline bool zdb_zone_is_frozen(zdb_zone *zone) { return (zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_FROZEN) != 0; } #ifdef __cplusplus } #endif #endif /* _ZDB_TYPES_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_utils.h0000644000000000000000000000013114505005531023061 xustar000000000000000030 mtime=1695812441.508968811 30 atime=1695812445.798030239 29 ctime=1695812494.97973462 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_utils.h0000664000374500037450000000613714505005531023033 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnsdb * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _ZDB_UTILS_H #define _ZDB_UTILS_H #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * FILE IOs FOR SPECIFIC TYPES * THE STORAGE IS NOT "RAW" * These will be obsoleted by the "streams" */ ya_result fread_u8(FILE* f, u8* value); ya_result fread_u16(FILE* f, u16* valuep); ya_result fread_u32(FILE* f, u32* valuep); ya_result fread_pstr(FILE* f, u8* value, u32 maxsize); ya_result fread_dnsname(FILE* f, u8* value, u32 maxsize); ya_result fread_buffer(FILE* f, u8* buffer, u32 size); u8* fread_zalloc_pstr(FILE* f); u8* fread_zalloc_buffer(FILE* f,u32* size); /* * PRINT ANSWER */ ya_result osprint_query_ex_section(output_stream* os, zdb_resourcerecord* section); void print_query_ex_section(zdb_resourcerecord* section); void osprint_query_ex(output_stream* os, zdb_query_ex_answer* answer); void print_query_ex(zdb_query_ex_answer* answer); #ifdef __cplusplus } #endif #endif /* _ZDB_UTILS_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_cache.h0000644000000000000000000000013214505005531022765 xustar000000000000000030 mtime=1695812441.497968653 30 atime=1695812445.798030239 30 ctime=1695812494.981734649 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_cache.h0000664000374500037450000000441514505005531022733 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Internal functions for the database: zoned resource records label. * * Internal functions for the database: zoned resource records label. * * The ZONE LABEL is a label that can: * * _ contains a zone cut * _ contains a cached label * * They should only be used as the top holding structure of the database * * @{ */ #pragma once #include yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_zone.h0000644000000000000000000000013214505005531022675 xustar000000000000000030 mtime=1695812441.502968725 30 atime=1695812445.798030239 30 ctime=1695812494.983734677 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_zone.h0000664000374500037450000003543414505005531022650 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #ifndef _ZDB_ZONE_H #define _ZDB_ZONE_H #include #include #if DNSCORE_HAS_DNSSEC_SUPPORT #include #endif #include #include #include #include #if ZDB_HAS_NSEC3_SUPPORT #include #include #endif #ifdef __cplusplus extern "C" { #endif #define ZDB_ZONETAG 0x454e4f5a52445a /* "ZDBZONE" */ /** * @brief Get the zone with the given name * * Get the zone with the given name * * @param[in] db a pointer to the database * @param[in] exact_match_origin the name of the zone * * @return a pointer to zone or NULL if the zone is not in the database * */ /* 2 USES */ zdb_zone *zdb_zone_find(zdb *db, dnsname_vector* exact_match_origin); /** * @brief Get the zone with the given name * * Get the zone with the given name * * @param[in] db a pointer to the database * @param[in] name the name of the zone (dotted c-string) * * @return a pointer to zone or NULL if the zone is not in the database * */ zdb_zone *zdb_zone_find_from_name(zdb *db, const char* name); /** * @brief Adds a record to a zone * * Adds a record to a zone. * * @param[in] zone the zone * @param[in] labels the stack of labels of the dns name * @param[in] labels_top the index of the top of the stack (the level) * @param[in] type the type of the record * @param[in] ttlrdata the ttl and rdata of the record. NOTE: the zone becomes its new owner !!! */ /* 2 USES */ void zdb_zone_record_add(zdb_zone* zone, dnslabel_vector_reference labels, s32 labels_top, u16 type, zdb_packed_ttlrdata* ttlrdata); /* class is implicit */ /** * @brief Search for a record in a zone * * Search for a record in a zone * * @param[in] zone the zone * @param[in] labels the stack of labels of the dns name * @param[in] labels_top the index of the top of the stack (the level) * @param[in] type the type of the record */ /* 4 USES */ zdb_packed_ttlrdata* zdb_zone_record_find(zdb_zone *zone, dnslabel_vector_reference labels, s32 labels_top, u16 type); /** * Searches the zone for the zdb_rr_label of an fqdn if it exists. * * @param[in] zone the zone * @parma[in] fqdn the fqdn of the the label * * @return a pointer the label, or NULL if it was not found. */ zdb_rr_label* zdb_zone_find_label_from_fqdn(zdb_zone *zone, const u8 *fqdn); /** * @brief Creates a zone * * Creates a zone * * @param[in] zone a pointer to the zone */ /* 2 USES */ zdb_zone *zdb_zone_create(const u8 *origin); /* * Sets a zone as invalid. * This will put the (content of the) zone in a garbage to be freed at some point in the future (when nolonger used) * Also an invalid zone ... the .axfr and journal files should probably be trashed * */ void zdb_zone_invalidate(zdb_zone *zone); void zdb_zone_truncate_invalidate(zdb_zone *zone); void zdb_zone_destroy_nolock(zdb_zone *zone); /** * @brief Destroys a zone and all its content * * Destroys a zone and all its content * * @param[in] zone a pointer to the zone */ /* 10 USES */ void zdb_zone_destroy(zdb_zone *zone); /** * @brief Copies the soa of a zone to an soa_rdata structure. * * Copies the soa of a zone to an soa_rdata structure. * No memory is allocated for the soa_rdata. If the zone is destroyed, * the soa_rdata becomes invalid. * * @param[in] zone a pointer to the zone * @param[out] soa_out a pointer to an soa_rdata structure */ ya_result zdb_zone_getsoa(const zdb_zone *zone, soa_rdata *soa_out); ya_result zdb_zone_getsoa_ttl_rdata(const zdb_zone* zone, u32 *ttl, u16 *rdata_size, const u8 **rdata); /** * @brief Retrieve the serial of a zone * * Retrieve the serial of a zone * * @param[in] zone a pointer to the zone * @param[out] serial a pointer to an u32 that will get the serial */ ya_result zdb_zone_getserial(const zdb_zone* zone, u32 *serial); /** * @brief Retrieve the minttl of a zone * * Retrieve the serial of a zone * * @param[in] zone a pointer to the zone * @param[out] serial a pointer to an u32 that will get the minttl */ static inline void zdb_zone_getminttl(const zdb_zone *zone, s32 *minttl) { *minttl = zone->min_ttl; } #if ZDB_RECORDS_MAX_CLASS == 1 static inline u16 zdb_zone_getclass(const zdb_zone *zone) { (void)zone; return CLASS_IN; } #else static inline u16 zdb_zone_getclass(const zdb_zone *zone) { return zone->zclass; } #endif ya_result zdb_zone_store_axfr(zdb_zone *zone, output_stream* os); const zdb_packed_ttlrdata *zdb_zone_get_dnskey_rrset(zdb_zone *zone); static inline u8 zdb_zone_get_flags(const zdb_zone *zone) { //mutex_lock(&zone->lock_mutex); u8 ret = zone->_flags; //mutex_unlock(&zone->lock_mutex); return ret; } static inline u8 zdb_zone_set_flags(zdb_zone *zone, u8 flags) { //mutex_lock(&zone->lock_mutex); u8 ret = zone->_flags; zone->_flags |= flags; //mutex_unlock(&zone->lock_mutex); return ret; } static inline u8 zdb_zone_clear_flags(zdb_zone *zone, u8 flags) { //mutex_lock(&zone->lock_mutex); u8 ret = zone->_flags; zone->_flags &= ~flags; //mutex_unlock(&zone->lock_mutex); return ret; } static inline u8 zdb_zone_set_clear_flags(zdb_zone *zone, u8 set_flags, u8 clear_flags) { //mutex_lock(&zone->lock_mutex); u8 ret = zone->_flags; zone->_flags &= ~clear_flags; zone->_flags |= set_flags; //mutex_unlock(&zone->lock_mutex); return ret; } /** * Tells if the apex of the zone has an NSEC3 extension * * @param zone * @return */ static inline bool zdb_zone_is_nsec3(const zdb_zone* zone) { #if ZDB_HAS_NSEC3_SUPPORT return (zone->apex->_flags & ZDB_RR_LABEL_NSEC3) != 0; #else return FALSE; #endif } /** * Tells if the apex of the zone has an NSEC3 extension with opt-out * * @param zone * @return */ static inline bool zdb_zone_is_nsec3_optout(const zdb_zone* zone) { #if ZDB_HAS_NSEC3_SUPPORT return ((zone->apex->_flags & ZDB_RR_LABEL_NSEC3_OPTOUT) != 0); #else return FALSE; #endif } /** * Tells if the apex of the zone has an NSEC3 extension without opt-out * * @param zone * @return */ static inline bool zdb_zone_is_nsec3_optin(const zdb_zone* zone) { #if ZDB_HAS_NSEC3_SUPPORT return ((zone->apex->_flags & ZDB_RR_LABEL_NSEC3_OPTOUT) == 0); #else return FALSE; #endif } #if ZDB_HAS_NSEC3_SUPPORT /** * Returns the nth nsec3 chain or NULL if the chain does not exists * * @param zone * @param idx * @return */ static inline nsec3_zone* zdb_zone_get_nsec3chain(const zdb_zone *zone, s8 idx) { nsec3_zone *n3 = zone->nsec.nsec3; while(n3 != NULL && --idx >= 0) { n3 = n3->next; } return n3; } /** * Tells if a zone has an NSEC3 chain * * @param zone * @return */ static inline bool zdb_zone_has_nsec3_chain(const zdb_zone *zone) { return zone->nsec.nsec3 != NULL; } /** * Tells if a zone has an NSEC3 chain with opt-out * * @param zone * @return */ static inline bool zdb_zone_has_nsec3_optout_chain(zdb_zone *zone) { return (zone->nsec.nsec3 != NULL) && (zdb_zone_get_flags(zone) & ZDB_ZONE_HAS_OPTOUT_COVERAGE); /// and ? } static inline bool zdb_zone_has_nsec3_records(const zdb_zone *zone) { nsec3_zone *n3 = zone->nsec.nsec3; while(n3 != NULL) { if(n3->items != NULL) { return TRUE; } n3 = n3->next; } return FALSE; } static inline bool zdb_zone_has_nsec3param_records(const zdb_zone *zone) { return zdb_record_find(&zone->apex->resource_record_set, TYPE_NSEC3PARAM) != NULL; } static inline bool zdb_zone_maintenance_queued(zdb_zone *zone) { bool ret = (zdb_zone_get_flags(zone) & ZDB_ZONE_MAINTAIN_QUEUED) != 0; return ret; } /** * Returns TRUE if the zne was not already marked as maintained */ static inline bool zdb_zone_set_maintenance_queued(zdb_zone *zone) { bool not_already_set = (zdb_zone_set_flags(zone, ZDB_ZONE_MAINTAIN_QUEUED) & ZDB_ZONE_MAINTAIN_QUEUED) == 0; return not_already_set; } static inline void zdb_zone_clear_maintenance_queued(zdb_zone *zone) { zdb_zone_clear_flags(zone, ZDB_ZONE_MAINTAIN_QUEUED); } #endif /** * Tells if the apex of the zone has an NSEC extension * * @param zone * @return */ static inline bool zdb_zone_is_nsec(const zdb_zone *zone) { #if ZDB_HAS_NSEC_SUPPORT return (zone->apex->_flags & ZDB_RR_LABEL_NSEC) != 0; #else return FALSE; #endif } #if ZDB_HAS_NSEC_SUPPORT /** * Tells if a zone has an NSEC chain * * @param zone * @return */ static inline bool zdb_zone_has_nsec_chain(const zdb_zone *zone) { return zone->nsec.nsec != NULL; } static inline bool zdb_zone_has_nsec_records(const zdb_zone *zone) { return zdb_zone_has_nsec_chain(zone); } #endif #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT /** * True for zones that are to be maintained. * This covers DNSSEC zones, but also zones in the process of being * DNSSEC. * * @param zone * @return */ static inline bool zdb_zone_is_maintained(zdb_zone *zone) { bool ret = (zdb_zone_get_flags(zone) & ZDB_ZONE_MAINTAINED) != 0; return ret; } static inline void zdb_zone_set_maintained(zdb_zone *zone, bool maintained) { if(maintained) { zdb_zone_set_flags(zone, ZDB_ZONE_MAINTAINED); } else { zdb_zone_clear_flags(zone, ZDB_ZONE_MAINTAINED); } } static inline bool zdb_zone_is_maintenance_paused(zdb_zone *zone) { u8 flags = zdb_zone_get_flags(zone); bool ret = (flags & (ZDB_ZONE_MAINTENANCE_PAUSED|ZDB_ZONE_MAINTAINED)) == ZDB_ZONE_MAINTENANCE_PAUSED; return ret; } static inline void zdb_zone_set_maintenance_paused(zdb_zone *zone, bool maintenance_paused) { mutex_lock(&zone->lock_mutex); if(maintenance_paused) { zdb_zone_set_clear_flags(zone, ZDB_ZONE_MAINTENANCE_PAUSED, ZDB_ZONE_MAINTAINED); } else { zdb_zone_set_clear_flags(zone, ZDB_ZONE_MAINTAINED, ZDB_ZONE_MAINTENANCE_PAUSED); } mutex_unlock(&zone->lock_mutex); } static inline void zone_set_maintain_mode(zdb_zone *zone, u8 mode) { yassert((mode & ZDB_ZONE_MAINTAIN_MASK) == mode); zdb_zone_set_clear_flags(zone, mode, ZDB_ZONE_MAINTAIN_MASK); #if OBSOLETE // this is part of a branch if((mode & ~ZDB_ZONE_HAS_OPTOUT_COVERAGE) == ZDB_ZONE_MAINTAIN_NSEC3) { u8 flags = mode & ZDB_ZONE_HAS_OPTOUT_COVERAGE; nsec3_zone *n3 = zone->nsec.nsec3; while(n3 != NULL) { n3->rdata[1] = flags; n3 = n3->next; } } #endif } static inline u8 zone_get_maintain_mode(zdb_zone *zone) { u8 ret = zdb_zone_get_flags(zone) & ZDB_ZONE_MAINTAIN_MASK; return ret; } #else // HAS_RRSIG_MANAGEMENT_SUPPORT static inline bool zdb_zone_is_maintained(const zdb_zone *zone) { (void)zone; return FALSE; } static inline u8 zone_get_maintain_mode(const zdb_zone *zone) { (void)zone; return 0; } static inline void zone_set_maintain_mode(zdb_zone *zone, u8 mode) { (void)zone; (void)mode; } #endif static inline bool zdb_zone_is_dnssec(zdb_zone *zone) { #if ZDB_HAS_DNSSEC_SUPPORT return (zone->apex->_flags & (ZDB_RR_LABEL_NSEC | ZDB_RR_LABEL_NSEC3)) != 0; #else return FALSE; #endif } static inline void zdb_zone_set_rrsig_push_allowed(zdb_zone *zone, bool allowed) { if(allowed) { zdb_zone_set_flags(zone, ZDB_ZONE_RRSIG_PUSH_ALLOWED); } else { zdb_zone_clear_flags(zone, ZDB_ZONE_RRSIG_PUSH_ALLOWED); } } static inline bool zdb_zone_get_rrsig_push_allowed(zdb_zone *zone) { bool ret = zdb_zone_get_flags(zone) & ZDB_ZONE_RRSIG_PUSH_ALLOWED; return ret; } bool zdb_zone_isinvalid(zdb_zone *zone); static inline bool zdb_zone_isvalid(zdb_zone *zone) { return !zdb_zone_isinvalid(zone); } #if DNSCORE_HAS_DNSSEC_SUPPORT /** * Adds a DNSKEY record in a zone from the dnssec_key object. * * @param key * @return TRUE iff the record has been added */ bool zdb_zone_add_dnskey_from_key(zdb_zone *zone, const dnssec_key *key); /** * Removes a DNSKEY record in a zone from the dnssec_key object. * * @param key * @return TRUE iff the record has been found and removed */ bool zdb_zone_remove_dnskey_from_key(zdb_zone *zone, const dnssec_key *key); /** * * Returns TRUE iff the key is present as a record in the zone * * @param zone * @param key * @return */ bool zdb_zone_contains_dnskey_record_for_key(zdb_zone *zone, const dnssec_key *key); /** * Returns TRUE iff there is at least one RRSIG record with the tag and algorithm of the key * * @param zone * @param key * @return */ bool zdb_zone_apex_contains_rrsig_record_by_key(zdb_zone *zone, const dnssec_key *key); void zdb_zone_update_keystore_keys_from_zone(zdb_zone *zone, u8 secondary_lock); #endif #if DEBUG /** * DEBUG */ void zdb_zone_print_indented(zdb_zone* zone, output_stream *os, int indent); void zdb_zone_print(zdb_zone *zone, output_stream *os); #endif #ifdef __cplusplus } #endif #endif /* _ZDB_ZONE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-lock.h0000644000000000000000000000013214505005531022570 xustar000000000000000030 mtime=1695812441.484968468 30 atime=1695812445.797030225 30 ctime=1695812494.985734706 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-lock.h0000664000374500037450000000610114505005531022530 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdb Zone database * @brief The zone database * * Implementation of structures and functions for the database * * Memory usage approxymation: * * let: * * "digest" the size of a digest * "n3pc" the number of nsec3param * "r" the number of records * * Memory usage =~ (233.3333 + ((446.666+digest) * n3pc) * r * * Or, if the digest size is different for each n3p: * * With "digest(n)" being the size of the digest for the n-th nsec3param * * =~ (233.3333 + SUM[n=1..n3pc](446.666+digest(n))) * r * * @{ */ #pragma once #include static inline void zdb_lock(zdb *db, u8 owner) { group_mutex_lock(&db->mutex, owner); } static inline void zdb_unlock(zdb *db, u8 owner) { group_mutex_unlock(&db->mutex, owner); } // used for assertions static inline bool zdb_ismutexlocked(zdb *db) { return group_mutex_islocked(&db->mutex); } static inline bool zdb_islocked(zdb *db) { mutex_lock(&db->mutex.mutex); bool r = db->mutex.owner != 0; mutex_unlock(&db->mutex.mutex); return r; } static inline bool zdb_islocked_by(zdb *db, u8 owner) { mutex_lock(&db->mutex.mutex); bool r = (db->mutex.owner == (owner & 0x7f)); mutex_unlock(&db->mutex.mutex); return r; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-arc.h0000644000000000000000000000013214505005531023356 xustar000000000000000030 mtime=1695812441.477968367 30 atime=1695812445.797030225 30 ctime=1695812494.987734735 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-arc.h0000664000374500037450000001141114505005531023316 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #pragma once #include #include #include #include /** * * Locks the database * Gets the zone * Starts locking the zone for the owner * Increment the zone RC * Unlocks the database * Resume locking the zone for the owner * returns the locked zone * * The read series implies no changes will be done to the database structure (no zone labels added/removed) * The write series implies changes will be done to the database structure. Most likely a removal of a zone label. * * @param db * @param fqdn/exact_match_origin * @param owner * @return */ zdb_zone *zdb_acquire_zone_read(zdb *db, const dnsname_vector *exact_match_origin); zdb_zone *zdb_acquire_zone_read_from_fqdn(zdb *db, const u8 *fqdn); zdb_zone *zdb_acquire_zone_read_trylock(zdb *db, dnsname_vector *exact_match_origin, u8 owner); zdb_zone *zdb_acquire_zone_read_trylock_from_name(zdb *db, const char *name, u8 owner); zdb_zone *zdb_acquire_zone_read_trylock_from_fqdn(zdb *db, const u8 *fqdn, u8 owner); zdb_zone *zdb_acquire_zone_read_lock(zdb *db, dnsname_vector *exact_match_origin, u8 owner); zdb_zone *zdb_acquire_zone_read_lock_from_name(zdb *db, const char *name, u8 owner); zdb_zone *zdb_acquire_zone_read_lock_from_fqdn(zdb *db, const u8 *fqdn, u8 owner); zdb_zone *zdb_acquire_zone_write_lock(zdb *db, dnsname_vector *exact_match_origin, u8 owner); zdb_zone *zdb_acquire_zone_write_lock_from_name(zdb *db, const char *name, u8 owner); zdb_zone *zdb_acquire_zone_write_lock_from_fqdn(zdb *db, const u8 *fqdn, u8 owner); /** * The double lock allows the caller to lock a zone for an owner with dibs to change the owner. * Typically: lock for the simple reader and then change the lock to a writer. * This is useful when lock-out the readers is not needed yet, but will most likely be in the near future. * * ie: lock reader + dynupdate * verify prerequisites * do the dry run * transfer lock to dynupdate * do the actual update * unlock * * @param db * @param exact_match_origin * @param owner * @param nextowner * @return */ zdb_zone *zdb_acquire_zone_read_double_lock(zdb *db, dnsname_vector *exact_match_origin, u8 owner, u8 nextowner); zdb_zone *zdb_acquire_zone_read_double_lock_from_name(zdb *db, const char *name, u8 owner, u8 nextowner); zdb_zone *zdb_acquire_zone_read_double_lock_from_fqdn(zdb *db, const u8 *fqdn, u8 owner, u8 nextowner); /** * * Dereference and unlocks the zone. * If the RC reached 0, enqueues it for destruction * * @param zone * @param owner */ void zdb_zone_acquire(zdb_zone *zone); void zdb_zone_release(zdb_zone *zone); void zdb_zone_release_unlock(zdb_zone *zone, u8 owner); void zdb_zone_release_double_unlock(zdb_zone *zone, u8 owner, u8 nextowner); /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-dnssec.h0000644000000000000000000000013214505005531024070 xustar000000000000000030 mtime=1695812441.485968482 30 atime=1695812445.797030225 30 ctime=1695812494.989734763 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-dnssec.h0000664000374500037450000000432314505005531024034 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbdnssec DNSSEC functions * @ingroup dnsdb * @brief * * @{ */ #include void zdb_zone_dnssec_keys_refresh(/*zdb_zone *zone*/); void zdb_zone_dnssec_keys_publish(zdb_zone *zone); void zdb_zone_dnssec_keys_activate(zdb_zone *zone); void zdb_zone_dnssec_keys_deactivate(zdb_zone *zone); void zdb_zone_dnssec_keys_unpublish(zdb_zone *zone); /** * @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-find.h0000644000000000000000000000013214505005531023531 xustar000000000000000030 mtime=1695812441.499968682 30 atime=1695812445.798030239 30 ctime=1695812494.991734792 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-find.h0000664000374500037450000000564014505005531023500 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #pragma once #include #include /** * Returns true if the zone exists in the LOCKED database * * @param[in] db a pointer to the database * @param[in] exact_match_origin the name of the zone * * @return TRUE if the zone is in the database * */ /* 2 USES */ bool zdb_zone_exists(zdb *db, dnsname_vector* exact_match_origin); /** * Returns true if the zone exists in the LOCKED database * * @param[in] db a pointer to the database * @param[in] name the name of the zone (dotted c-string) * * @return TRUE if the zone is in the database * */ bool zdb_zone_exists_from_name(zdb *db, const char* name); /** * Returns true if the zone exists in the LOCKED database * * @param[in] db a pointer to the database * @param[in] name the name of the zone (dns name) * * @return TRUE if the zone is in the database * */ bool zdb_zone_exists_from_dnsname(zdb *db, const u8* dns_name); /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-garbage.h0000644000000000000000000000013214505005531024201 xustar000000000000000030 mtime=1695812441.492968582 30 atime=1695812445.798030239 30 ctime=1695812494.993734821 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-garbage.h0000664000374500037450000000524114505005531024145 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #pragma once #include #ifdef DNSDB_BUILD void zdb_zone_garbage_init(); void zdb_zone_garbage_finalize(); bool zdb_zone_garbage_collect(zdb_zone *zone); zdb_zone *zdb_zone_garbage_get(); #endif // callback will be called once a zone is destroyed typedef void (zdb_zone_garbage_run_destroyed_cb)(const u8 *fqdn); void zdb_zone_garbage_run(); bool zdb_zone_garbage_empty(); typedef void zdb_zone_garbage_run_cb(zdb_zone *); void zdb_zone_garbage_run_ex(zdb_zone_garbage_run_cb *destroyer); void zdb_zone_garbage_run_callback_add(zdb_zone_garbage_run_destroyed_cb *cb); void zdb_zone_garbage_run_callback_remove(zdb_zone_garbage_run_destroyed_cb *cb); /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-journal.h0000644000000000000000000000013214505005531024263 xustar000000000000000030 mtime=1695812441.509968826 30 atime=1695812445.798030239 30 ctime=1695812494.995734849 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-journal.h0000664000374500037450000000657614505005531024243 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnsdb * @brief * * Journal API * * * @{ */ #pragma once #define ZDB_ZONE_JOURNAL_AVAILABLE 1 #include #include /** * Returns the first and last serial in the journal of a loaded zone. * If the journal has not been opened yet (and bound to the zone) then it will be. * * @param zone the zone * @param out_serial_from, can be NULL * @param out_serial_to, can be NULL * * @return an error code */ ya_result zdb_zone_journal_get_serial_range(zdb_zone *zone, u32 *out_serial_from, u32 *out_serial_to); /** * Opens a stream from the journal for reading an IXFR starting at a given serial. * * @param zone the zone * @param serial the serial to start from * @param out_is the stream to be initialised for reading the IXFR * @param out_last_soa_rr the last SOA record, can be NULL * * @return an error code */ ya_result zdb_zone_journal_get_ixfr_stream_at_serial(zdb_zone *zone, u32 serial, input_stream *out_is, dns_resource_record *out_last_soa_rr); /** * Appends an IXFR stream to the journal. * The expected stream lacks the repeated last SOA record at the first and last position. * * @param zone * @param is stream of uncompressed wire records : (SOA DEL DEL DEL ... SOA ADD ADD ADD ...)+ * @return an error code */ ya_result zdb_zone_journal_append_ixfr_stream(zdb_zone *zone, input_stream *is); /** * Deletes the file of the journal of a zone * * @param zone * @return an error code */ ya_result zdb_zone_journal_delete(const zdb_zone *zone); /** * @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-lock.h0000644000000000000000000000013214505005531023541 xustar000000000000000030 mtime=1695812441.491968567 30 atime=1695812445.798030239 30 ctime=1695812494.997734878 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-lock.h0000664000374500037450000001473614505005531023516 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #pragma once #include #ifdef __cplusplus extern "C" { #endif /** * Zone locking * * Sets the owner of a zone. * * The owner id has a format: the msb is reserved to say that the access is * exclusive to only one instance of the owner. * The remaining bits are the id. * * Mostly used for the simple reader and various writers. * * A new feature needs to be added: being able to pre-lock for an owner. * * Explanation: I want to lock for the signing process. But that process * is done in two or three phases. The first phase is read-only (thus allowing * the server to work normally). But I don't want somebody else, say, a dynamic * update, to lock the zone in the mean time. (Which would happen when the lock * is transferred from the reader to the signer (at the commit phase). * So I'll add a secondary owner, meant to tell "I lock as a reader BUT I also * reserve the right for myself later". And later a transfer can be done to * the secondary as soon as the last reader unlocks. * * zdb_zone_double_lock(zone, owner, secondary owner) * zdb_zone_try_double_lock(zone, owner, secondary owner) * zdb_zone_transfer_lock(zone, secondary owner) * * The parameter would need to be repeated to detect inconsistencies (bugs) * * This should have no effect on the normal locking mechanism, thus ensuring * no loss of speed. The only goal is to avoid a race changing the owner. * * Having only zdb_zone_transfer_lock(zone, old owner, new owner) cannot work * because nothing prevents two soon-to-be writers to lock and work in tandem. * */ void zdb_zone_lock(zdb_zone *zone, u8 owner); bool zdb_zone_trylock(zdb_zone *zone, u8 owner); bool zdb_zone_trylock_wait(zdb_zone *zone, u64 usec, u8 owner); void zdb_zone_unlock(zdb_zone *zone, u8 owner); bool zdb_zone_islocked(zdb_zone *zone); /** * Functions for internal testing, do not use. * * @param zone * @return */ bool zdb_zone_islocked_weak(const zdb_zone *zone); /** * Functions for internal testing, do not use. * * @param zone * @return */ bool zdb_zone_islocked_weak(const zdb_zone *zone); /** * Functions for internal testing, do not use. * * @param zone * @return */ bool zdb_zone_islocked_weak(const zdb_zone *zone); /** * Functions for internal testing, do not use. * * @param zone * @return */ bool zdb_zone_islocked_weak(const zdb_zone *zone); /** * Returns TRUE iff the zone is locked by a writer (any other owner value than nobody and simple reader) * * @param zone * @return */ bool zdb_zone_iswritelocked(zdb_zone *zone); /** * Reserves the secondary owner and to locks for the owner * * @param zone * @param owner * @param secondary_owner */ void zdb_zone_double_lock(zdb_zone *zone, u8 owner, u8 secondary_owner); /** * Tries to reserve the secondary owner and to lock for the owner * * @param zone * @param owner * @param secondary_owner */ bool zdb_zone_try_double_lock(zdb_zone *zone, u8 owner, u8 secondary_owner); /** * Tries to reserve the secondary owner and to lock for the owner. * Gets the current owner if the lock fails. * If the lock succeeds the current_ownerp and current_reserved_ownerp poited values's content is undefined. * * @param zone * @param owner * @param secondary_owner * @param current_ownerp * @param current_reserved_ownerp */ bool zdb_zone_try_double_lock_ex(zdb_zone *zone, u8 owner, u8 secondary_owner, u8 *current_ownerp, u8 *current_reserved_ownerp); /** * * Unlocks one owner and sets the secondary owner to nobody * * @param zone * @param owner * @param secondary_owner */ void zdb_zone_double_unlock(zdb_zone *zone, u8 owner, u8 secondary_owner); /** * * Puts the secondary lock in place of the lock when the locker count reaches 1 * Followed by a zdb_zone_unlock * * @param zone * @param owner * @param secondary_owner */ void zdb_zone_transfer_lock(zdb_zone *zone, u8 owner, u8 secondary_owner); /** * * Puts the secondary lock in place of the lock when the locker count reaches 1 * Followed by a zdb_zone_unlock * * @param zone * @param owner * @param secondary_owner */ bool zdb_zone_try_transfer_lock(zdb_zone *zone, u8 owner, u8 secondary_owner); /** * * Exchange the primary and secondary locks when the locker count reaches 1 * Followed by a zdb_zone_unlock * * @param zone * @param owner * @param secondary_owner */ void zdb_zone_exchange_locks(zdb_zone *zone, u8 owner, u8 secondary_owner); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT void zdb_zone_lock_set_monitor(); #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-lock-monitor.h0000644000000000000000000000013214505005531025226 xustar000000000000000030 mtime=1695812441.511968854 30 atime=1695812445.798030239 30 ctime=1695812494.999734907 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-lock-monitor.h0000664000374500037450000000541114505005531025171 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #if ZDB_HAS_LOCK_DEBUG_SUPPORT #include #ifdef __cplusplus extern "C" { #endif struct zdb_zone_lock_monitor; struct zdb_zone_lock_monitor *zdb_zone_lock_monitor_new(const zdb_zone *zone, u8 owner, u8 secondary); struct zdb_zone_lock_monitor *zdb_zone_lock_monitor_get(const zdb_zone *zone); bool zdb_zone_lock_monitor_release(struct zdb_zone_lock_monitor *holder); void zdb_zone_lock_monitor_waits(struct zdb_zone_lock_monitor *holder); void zdb_zone_lock_monitor_resumes(struct zdb_zone_lock_monitor *holder); void zdb_zone_lock_monitor_exchanges(struct zdb_zone_lock_monitor *holder); void zdb_zone_lock_monitor_locks(struct zdb_zone_lock_monitor *holder); void zdb_zone_lock_monitor_cancels(struct zdb_zone_lock_monitor *holder); void zdb_zone_lock_monitor_unlocks(struct zdb_zone_lock_monitor *holder); void zdb_zone_lock_monitor_log(); #ifdef __cplusplus } #endif #endif yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-answer-axfr.h0000644000000000000000000000013214505005531025046 xustar000000000000000030 mtime=1695812441.534969183 30 atime=1695812445.799030253 30 ctime=1695812495.001734935 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-answer-axfr.h0000664000374500037450000000722614505005531025017 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbdnssec DNSSEC functions * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #pragma once #include #include #if DNSCORE_HAS_TCP_MANAGER #include #endif #include /** * If the zone is relatively small, there is no need to prepare an image on the disk. * Instead, snapshot to memory. * The default treshold is set to 64KB (way more than the needs of 99% of use-cases) * TLDs are still expected use the through-storage branch of the code. */ /** * Returns the current value of the threshold. * Setting it to 0 will effectively disable the feature. * * @return The current value of the threshold, in bytes. * */ u32 zdb_zone_answer_axfr_memfile_size_threshold(); /** * Set the new value of the threshold. * Setting it to 0 will effectively disable the feature. * Returns the previous value of the threshold. * * @param new_threshold the new value of the threshold, in bytes. * @return The previous value of the threshold, in bytes. */ u32 zdb_zone_answer_axfr_memfile_size_threshold_set(u32 new_threshold); /** * * @param zone * @param mesg * @param tp * @param max_packet_size * @param max_record_by_packet * @param compress_packets */ #if DNSCORE_HAS_TCP_MANAGER void zdb_zone_answer_axfr(zdb_zone *zone, message_data *mesg, tcp_manager_socket_context_t *sctx, struct thread_pool_s *network_tp, struct thread_pool_s *disk_tp, u16 max_packet_size, u16 max_record_by_packet, bool compress_packets); #else void zdb_zone_answer_axfr(zdb_zone *zone, message_data *mesg, int sockfd, struct thread_pool_s *network_tp, struct thread_pool_s *disk_tp, u16 max_packet_size, u16 max_record_by_packet, bool compress_packets); #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-answer-ixfr.h0000644000000000000000000000013214505005531025056 xustar000000000000000030 mtime=1695812441.476968353 30 atime=1695812445.797030225 30 ctime=1695812495.003734964 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-answer-ixfr.h0000664000374500037450000000615614505005531025030 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbdnssec DNSSEC functions * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #pragma once #include #include #if DNSCORE_HAS_TCP_MANAGER #include #endif #include /** * * Replies an (I)XFR stream to a slave. * * @param zone The zone * @param mesg The original query * @param network_tp The network thread pool to use * @param disk_tp The disk thread pool to use * @param max_packet_size the maximum size of a packet/message in the stream * @param max_record_by_packet The maximum number of records in a single message (1 for very old servers) * @param compress_packets Allow fqdn compression * */ #if DNSCORE_HAS_TCP_MANAGER void zdb_zone_answer_ixfr(zdb_zone *zone, message_data *mesg, tcp_manager_socket_context_t *sctx, struct thread_pool_s *network_tp, struct thread_pool_s *disk_tp, u16 max_packet_size, u16 max_record_by_packet, bool compress_packets); #else void zdb_zone_answer_ixfr(zdb_zone *zone, message_data *mesg, int sockfd, struct thread_pool_s *network_tp, struct thread_pool_s *disk_tp, u16 max_packet_size, u16 max_record_by_packet, bool compress_packets); #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-maintenance.h0000644000000000000000000000013214505005531025073 xustar000000000000000030 mtime=1695812441.486968496 30 atime=1695812445.797030225 30 ctime=1695812495.005734992 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-maintenance.h0000664000374500037450000001120314505005531025032 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #pragma once #include #include #include #include // struct dnssec_chain #include #ifdef __cplusplus extern "C" { #endif #define ZDB_ZONE_MAINTENANCE_NSEC3CHAIN_MAX 16 struct zdb_zone_maintenance_ctx { dnssec_chain nsec_chain_updater; // @note 20170119 edf -- Given recent changes, and depending on the post-processing, I may be able to handle NSEC & NSEC3 chains with a single (modified) object. dnssec_chain nsec3_chains_updater; nsec3_zone* nsec3_chain[ZDB_ZONE_MAINTENANCE_NSEC3CHAIN_MAX]; u8 nsec3_chain_status[ZDB_ZONE_MAINTENANCE_NSEC3CHAIN_MAX]; zdb_zone *zone; zdb_rr_label *label; dnssec_key_sll *keys; intptr ksk_mask; intptr zsk_mask; int ksk_count; int zsk_count; ptr_vector ksks; ptr_vector zsks; time_t now; u8 nsec_chain_status; u8 nsec3_chain_count; u8 fqdn[MAX_DOMAIN_LENGTH]; dnsname_stack fqdn_stack; }; typedef struct zdb_zone_maintenance_ctx zdb_zone_maintenance_ctx; ya_result zdb_zone_maintenance(zdb_zone* zone); ya_result zdb_zone_sign(zdb_zone* zone); /** * Called by zdb_zone_maintenance * * Marks record sets that needs to be updated. * Removes expired signatures. * * @param mctx * @return */ ya_result zdb_zone_maintenance_rrsig(zdb_zone_maintenance_ctx* mctx, zone_diff_fqdn *diff_fqdn, ptr_vector *rrset_to_sign); /** * Called by zdb_zone_maintenance * * Updates the signatures of a zone incrementally. * Each call goes a bit further. * * @param zone * @param signature_count_loose_limit * @param present_signatures_are_verified * @return the number of actions counted */ int zdb_zone_maintenance_nsec(zdb_zone_maintenance_ctx* mctx, zone_diff_fqdn *diff_fqdn, ptr_vector *rrset_to_sign); /** * Called by zdb_zone_maintenance * * Updates the signatures of a zone incrementally. * Each call goes a bit further. * * @param zone * @param signature_count_loose_limit * @param present_signatures_are_verified * @return the number of actions counted */ int zdb_zone_maintenance_nsec3(zdb_zone_maintenance_ctx* mctx, zone_diff_fqdn *diff_fqdn); void zdb_zone_maintenance_nsec3_add_rrsig_type(zone_diff *diff, zdb_zone *zone, ptr_vector *rrset_to_sign_vector, ptr_vector *ksks, ptr_vector *zsks, ptr_vector *remove, ptr_vector* add, zone_diff_fqdn *covered_diff_fqdn); void zdb_zone_maintenance_nsec3_remove_rrsig_type(zone_diff *diff, zdb_zone *zone, ptr_vector *rrset_to_sign_vector, ptr_vector *ksks, ptr_vector *zsks, ptr_vector *remove, ptr_vector* add, zone_diff_fqdn *covered_diff_fqdn); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-packed-ttlrdata.h0000644000000000000000000000013214505005531024704 xustar000000000000000030 mtime=1695812441.515968911 30 atime=1695812445.798030239 30 ctime=1695812495.007735021 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-packed-ttlrdata.h0000664000374500037450000000605614505005531024655 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @brief database internal record type * * @{ */ #pragma once #include #include #define ZDBPTRVD_TAG 0x445652545042445a struct zdb_packed_ttlrdata_record_view_data { const u8 *fqdn; u16 rtype; u16 rclass; s32 rttl; }; typedef struct zdb_packed_ttlrdata_record_view_data zdb_packed_ttlrdata_record_view_data; void zdb_packed_ttlrdata_resource_record_view_init(struct resource_record_view *rrv); void zdb_packed_ttlrdata_resource_record_view_set_fqdn(struct resource_record_view *rrv, const u8 *fqdn); void zdb_packed_ttlrdata_resource_record_view_set_type(struct resource_record_view *rrv, u16 rtype); void zdb_packed_ttlrdata_resource_record_view_set_class(struct resource_record_view *rrv, u16 rclass); void zdb_packed_ttlrdata_resource_record_view_set_ttl(struct resource_record_view *rrv, s32 rttl); void zdb_packed_ttlrdata_resource_record_view_finalize(struct resource_record_view *rrv); zdb_packed_ttlrdata *zdb_packed_ttlrdata_clone(zdb_packed_ttlrdata *record); void zdb_packed_ttlrdata_insert_clone(zdb_packed_ttlrdata **list_head, zdb_packed_ttlrdata *record); void zdb_packed_ttlrdata_insert(zdb_packed_ttlrdata **list_head, zdb_packed_ttlrdata *new_head); /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_zone_axfr_input_stream.h0000644000000000000000000000013114505005531026506 xustar000000000000000030 mtime=1695812441.506968783 30 atime=1695812445.798030239 29 ctime=1695812495.00973505 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_zone_axfr_input_stream.h0000664000374500037450000000565414505005531026463 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef __ZDB_ZONE_AXFR_INPUT_STREAM__H__ #define __ZDB_ZONE_AXFR_INPUT_STREAM__H__ #include #include #ifdef __cplusplus extern "C" { #endif /** * Opens the specified file as an AXFR image for the given zone. * Will fail if the file cannot be opened. * * @param is * @param zone * @param filepath * @return */ ya_result zdb_zone_axfr_input_stream_open_with_path(input_stream *is, zdb_zone *zone, const char *filepath); /** * Opens the file on disk and starts to stream it until it has been marked as fully written * Used to send to slaves. * * @param is * @param zone * @return */ ya_result zdb_zone_axfr_input_stream_open(input_stream *is, zdb_zone *zone); #ifdef __cplusplus } #endif #endif /* __ZDB_ZONE_AXFR_INPUT_STREAM__H__ */ /* ------------------------------------------------------------ */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_zone_label.h0000644000000000000000000000013214505005531024034 xustar000000000000000030 mtime=1695812441.529969112 30 atime=1695812445.799030253 30 ctime=1695812495.011735078 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_zone_label.h0000664000374500037450000001205514505005531024001 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Internal functions for the database: zoned resource records label. * * Internal functions for the database: zoned resource records label. * * The ZONE LABEL is a label that can: * * _ contains a zone cut * _ contains a cached label * * They should only be used as the top holding structure of the database * * @{ */ #ifndef _ZONE_LABEL_H #define _ZONE_LABEL_H #include #ifdef __cplusplus extern "C" { #endif #define ZDB_ZONELABEL_TAG 0x4c424c4e5a42445a /* "ZDBZNLBL" */ #if 0 /* fix */ #else /** * @brief TRUE if the zone_label contains information (records, zone or a set of labels), else FALSE */ /* 2 USES */ #define ZONE_LABEL_RELEVANT(zone_label) ((zone_label)->zone!=NULL||dictionary_notempty(&(zone_label)->sub)) /** * @brief FALSE if the zone_label contains information (records, zone or a set of labels), else TRUE */ /* 4 USES */ #define ZONE_LABEL_IRRELEVANT(zone_label) ((zone_label)->zone==NULL&&dictionary_isempty(&(zone_label)->sub)) #endif /** * @brief Search for the label of a zone in the database * * Search for the label of a zone in the database * * @param[in] db the database to explore * @param[in] name the dnsname_vector mapping the label * * @return a pointer to the label or NULL if it does not exists in the database. * */ /* 3 USES */ zdb_zone_label* zdb_zone_label_find(zdb* db, const dnsname_vector* name); zdb_zone_label* zdb_zone_label_find_from_name(zdb* db, const char* name); zdb_zone_label* zdb_zone_label_find_from_dnsname(zdb* db, const u8* dns_name); zdb_zone_label* zdb_zone_label_find_from_dnsname_nolock(zdb* db, const u8* dns_name); zdb_zone_label* zdb_zone_label_find_nolock(zdb *db, const dnsname_vector* origin); zdb_zone_label* zdb_zone_label_add_nolock(zdb *db, const dnsname_vector* origin); /** * @brief Destroys a label and its collections. * * Destroys a label and its collections. * Most likely irrelevant outside of zdb. * * @param[in] zone_labelp a pointer to a pointer to the label to destroy. * */ /* 1 USE */ void zdb_zone_label_destroy(zdb_zone_label **zone_labelp); /** * @brief Gets pointers to all the zone labels along the path of a name. * * Gets pointers to all the zone labels along the path of a name. * * @param[in] db a pointer to the database * @param[in] name a pointer to the dns name * @param[in] zone_label_vector a pointer to the vector that will hold the labels pointers * * @return the top of the vector (-1 = empty) */ /* 1 USE */ s32 zdb_zone_label_match(zdb* db, const dnsname_vector *name, zdb_zone_label_pointer_array zone_label_vector); /** * @brief Destroys a zone label and all its collections * * Destroys a zone label and all its collections * * @parm[in] db a pointer to the database * @parm[in] name a pointer to the name * * @return an error code */ /* 2 USES */ ya_result zdb_zone_label_delete(zdb* db, dnsname_vector* name); #if DEBUG /** * DEBUG: prints the label content */ void zdb_zone_label_print_indented(zdb_zone_label* zone_label, output_stream *os, int indent); void zdb_zone_label_print(zdb_zone_label* zone_label, output_stream *os); #endif #ifdef __cplusplus } #endif #endif /* _ZONE_LABEL_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_zone_label_iterator.h0000644000000000000000000000013214505005531025745 xustar000000000000000030 mtime=1695812441.533969169 30 atime=1695812445.799030253 30 ctime=1695812495.014735122 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_zone_label_iterator.h0000664000374500037450000001036014505005531025707 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to iterate through the labels of a zone * * @{ */ #ifndef _ZDB_ZONE_LABEL_ITERATOR_H #define _ZDB_ZONE_LABEL_ITERATOR_H #include #ifdef __cplusplus extern "C" { #endif /** * @brief Initializes a zone label iterator * * Initializes a zone label iterator (iterates zdb_rr_label) * * @param[in] iter a pointer to the iterator to initialise * @param[in] zone The zone to explore * */ void zdb_zone_label_iterator_init(zdb_zone_label_iterator* iter, const zdb_zone* zone); /** * @brief Initializes a zone label iterator from a given starting name * * Initializes a zone label iterator (iterates zdb_rr_label) * * @param[in] iter a pointer to the iterator to initialise * @param[in] zone The zone to explore * @param[in] from_name the first name the iterator should start from * */ void zdb_zone_label_iterator_init_from(zdb_zone_label_iterator* iter, const zdb_zone* zone, const u8 *from_name); /** * @brief Checks if there is still data available from an iterator * * Checks if there is still data available from an iterator * * @param[in] iter a pointer to the iterator * * @return TRUE if data is available, FALSE otherwise. * */ bool zdb_zone_label_iterator_hasnext(zdb_zone_label_iterator* iter); /** * @brief Copies the full name of the next label returned by the "next" call. * * Copies the full name of the next label returned by the "next" call. * * CALL IT BEFORE USING zdb_zone_label_iterator_next * * @param[in] iter a pointer to the iterator * @param[in] buffer256 a pointer to a buffer that will hold the full dns name * * @return the size of the dns name * */ u32 zdb_zone_label_iterator_nextname_to_cstr(zdb_zone_label_iterator* iter, char* buffer256); u32 zdb_zone_label_iterator_nextname(zdb_zone_label_iterator* iter, u8* buffer256); /** * @brief Returns the next data available from an iterator * * Returns the next data available from an iterator * * @param[in] iter a pointer to the iterator * * @return a pointer to the next label * */ zdb_rr_label* zdb_zone_label_iterator_next(zdb_zone_label_iterator* iter); #if ZDB_ZONE_LABEL_ITERATOR_CAN_SKIP_CHILDREN /** * @brief Skips the children * * Skips the children * * @return * */ void zdb_zone_label_skip_children(zdb_zone_label_iterator* iter); #endif #ifdef __cplusplus } #endif #endif /* _ZDB_ITERATOR_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_zone_label_iterator_ex.h0000644000000000000000000000013114505005531026440 xustar000000000000000030 mtime=1695812441.504968754 30 atime=1695812445.798030239 29 ctime=1695812495.01673515 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_zone_label_iterator_ex.h0000664000374500037450000001063614505005531026411 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to iterate through the labels of a zone * * @{ */ #pragma once #include #if ZDB_HAS_NSEC3_SUPPORT #include #endif #ifdef __cplusplus extern "C" { #endif enum zdb_zone_label_iterator_ex_mode { ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS = 0, ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN = 1, ZDB_ZONE_LABEL_ITERATOR_END_OF_ITERATION = 2 }; struct zdb_zone_label_iterator_ex { s32 mode; s32 min_ttl; const zdb_zone *zone; struct nsec3_zone *n3; u8 *pool; u8 *nsec3_owner; //zdb_packed_ttlrdata *nsec3_record; //zdb_packed_ttlrdata *nsec3_rrsig; zdb_rr_label nsec3_label; avl_node nsec3_label_nsec3; avl_node nsec3_label_rrsig; union { struct zdb_zone_label_iterator label_iter; struct nsec3_iterator nsec3_iter; } iter; u8 pool_buffer[TMP_NSEC3_TTLRDATA_SIZE]; }; typedef struct zdb_zone_label_iterator_ex zdb_zone_label_iterator_ex; /** * @brief Initializes a zone label iterator that also iterates through NSEC3 * * Initializes a zone label iterator (iterates zdb_rr_label) * * @param[in] iter a pointer to the iterator to initialise * @param[in] zone The zone to explore * */ void zdb_zone_label_iterator_ex_init(zdb_zone_label_iterator_ex* iter, const zdb_zone* zone); /** * @brief Checks if there is still data available from an iterator * * Checks if there is still data available from an iterator * * @param[in] iter a pointer to the iterator * * @return TRUE if data is available, FALSE otherwise. * */ bool zdb_zone_label_iterator_ex_hasnext(zdb_zone_label_iterator_ex* iter); /** * @brief Copies the full name of the next label returned by the "next" call. * * Copies the full name of the next label returned by the "next" call. * * CALL IT BEFORE USING zdb_zone_label_iterator_next * * @param[in] iter a pointer to the iterator * @param[in] buffer256 a pointer to a buffer that will hold the full dns name * * @return the size of the dns name * */ u32 zdb_zone_label_iterator_ex_nextname_to_cstr(zdb_zone_label_iterator_ex* iter, char* buffer256); u32 zdb_zone_label_iterator_ex_nextname(zdb_zone_label_iterator_ex* iter, u8* buffer256); /** * @brief Returns the next data available from an iterator * * Returns the next data available from an iterator * * @param[in] iter a pointer to the iterator * * @return a pointer to the next label * */ zdb_rr_label* zdb_zone_label_iterator_ex_next(zdb_zone_label_iterator_ex* iter); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_zone_load.h0000644000000000000000000000013214505005531023674 xustar000000000000000030 mtime=1695812441.501968711 30 atime=1695812445.798030239 30 ctime=1695812495.018735179 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_zone_load.h0000664000374500037450000001514514505005531023644 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #pragma once #include #include #include #ifdef __cplusplus extern "C" { #endif /** * @brief Load a zone in the database. * * Load a zone in the database. * This is clearly MASTER oriented. * * @param[in] db a pointer to the database * @param[in] filename a pointer to the filename of the zone * @param[out] zone_pointer_out will contains a pointer to the loaded zone if the call is successful * * @return an error code. * */ #define ZDB_ZONE_NO_MAINTENANCE 0x01 // do not maintain the zone DNSSEC state #define ZDB_ZONE_REPLAY_JOURNAL 0x02 // replay the journal after the load #define ZDB_ZONE_DESTROY_JOURNAL 0x04 // destroys the journal after a successful load #define ZDB_ZONE_IS_SLAVE 0x08 // any NSEC3 inconsistencies must trigger an AXFR reload #define ZDB_ZONE_DNSSEC_SHIFT 4 #define ZDB_ZONE_DNSSEC_MASK 0x0070 #define ZDB_ZONE_NOSEC 0x0000 #define ZDB_ZONE_NSEC 0x0010 #define ZDB_ZONE_NSEC3 0x0020 #define ZDB_ZONE_NSEC3_OPTOUT 0x0030 #define ZDB_ZONE_NSEC3PARAM_TTL_NO_OVERRIDE 0x1000 // if set, the NSEC3PARAM TTL will not be set to 0 automatically #if BYTE_ORDER == LITTLE_ENDIAN struct zdb_zone_load_dnskey_id_fields { u16 tag; u8 algorithm; u8 must_be_zero; }; #elif BYTE_ORDER == BIG_ENDIAN struct zdb_zone_load_dnskey_id_fields { u8 must_be_zero; u8 algorithm; u16 tag; }; #else #error "BYTE_ORDER value is not supported" #endif union zdb_zone_load_dnskey_id { u32 id; struct zdb_zone_load_dnskey_id_fields fields; }; #define ZDB_ZONE_LOAD_DNSKEY_STATE_FLAG_HAS_PUBKEY 1 #define ZDB_ZONE_LOAD_DNSKEY_STATE_FLAG_HAS_PRIVKEY 2 #define ZDB_ZONE_LOAD_DNSKEY_STATE_FLAG_MISSING_SIGNATURES 4 #define ZDB_ZONE_LOAD_STATE_SANITIZE_FIELD_AVAIABLE 8 #define ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_AVAILABLE 16 #define ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_MAINTENANCE_REQUIRED 32 #define ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_NSEC3_CHAIN_FIXED 64 #define ZZLDSKEY_TAG 0x59454b53444c5a5a struct zdb_zone_load_dnskey_state_for_key { s32 signed_until; s32 signed_from; u32 rrsig_count; u16 key_flags; u8 flags; }; typedef u32_set zdb_zone_load_dnskey_state; struct zdb_zone_load_parms { zone_reader *zr; const u8 *expected_origin; zdb_zone_load_dnskey_state dnskey_state; zdb_zone *out_zone; struct zdb_sanitize_parms sanitize_parms; ya_result result_code; u16 flags; u16 state; u8 expected_dnssec; }; void zdb_zone_load_parms_init(struct zdb_zone_load_parms *parms, zone_reader *zr, const u8 *expected_origin, u16 flags); void zdb_zone_load_parms_dnskey_add(struct zdb_zone_load_parms *parms, const u8 *dnskey_rdata, u16 dnskey_rdata_size); u16 zdb_zone_load_parms_get_key_flags_from_rrsig_rdata(struct zdb_zone_load_parms *parms, const u8 *rrsig_rdata, u16 rrsig_rdata_size); void zdb_zone_load_parms_rrsig_add(struct zdb_zone_load_parms *parms, const u8 *rrsig_rdata, u16 rrsig_rdata_size); zdb_zone *zdb_zone_load_parms_zone_detach(struct zdb_zone_load_parms *parms); zdb_zone *zdb_zone_load_parms_zone_get(struct zdb_zone_load_parms *parms); ya_result zdb_zone_load_parms_result_code(struct zdb_zone_load_parms *parms); void zdb_zone_load_parms_finalize(struct zdb_zone_load_parms *parms); ya_result zdb_zone_load_ex(struct zdb_zone_load_parms *parms); /** * @brief Load a zone file. * * Load a zone file. * * @note It is not a good idea to scan the zone content in here. ie: getting the earliest signature expiration. (It's counter-productive and pointless) * * @param[in] db_UNUSED a pointer to the database, obsolete, should be set to NULL * @param[in] zr a pointer to an opened zone_reader * @param[in] zone_pointer_out a pointer to the pointer that will be set with the loaded zone * @param[in] expected_origin the expected origin for the loaded file, can be set to NULL * @param[in] flags various flags * * @return an error code. * */ ya_result zdb_zone_load(zdb* db_UNUSED, zone_reader* zr, zdb_zone** zone_out, const u8 *expected_origin, u16 flags); /** * @brief Load the zone SOA. * * Load the zone SOA record * This is meant mainly for the slave that could choose between, ie: zone file or axfr zone file * The SOA MUST BE the first record * * @param[in] db a pointer to the database * @param[in] zone_data a pointer to an opened zone_reader at its start * @param[out] zone_pointer_out will contains a pointer to the loaded zone if the call is successful * * @return an error code. * */ ya_result zdb_zone_get_soa(zone_reader *zone_data, u16 *rdata_size, u8 *rdata); #ifdef __cplusplus } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-path-provider.h0000644000000000000000000000013214505005531025375 xustar000000000000000030 mtime=1695812441.488968525 30 atime=1695812445.798030239 30 ctime=1695812495.020735207 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-path-provider.h0000664000374500037450000001456514505005531025352 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include /** * For backward compatibility * * @param path */ void journal_set_xfr_path(const char *path); /** * For backward compatibility * * @return */ const char* journal_get_xfr_path(); /** * The database does not know zone types. The only one that does is the server. * So it makes sense to provide it a way to chose where the DB will store journals. * This is especially important with the new master/slave journal separation * * The default provider returns something based on the XFR path (journal_set_xfr_path) * */ #define ZDB_ZONE_PATH_PROVIDER_ZONE_PATH 1 // want the full path of the directory for the zone #define ZDB_ZONE_PATH_PROVIDER_ZONE_FILE 2 // want the full path of the file for the zone #define ZDB_ZONE_PATH_PROVIDER_AXFR_PATH 3 // want the full path of the directory for the image of the zone (AXFR) #define ZDB_ZONE_PATH_PROVIDER_AXFR_FILE 4 // want the full path of the directory for the image of the zone (AXFR) #define ZDB_ZONE_PATH_PROVIDER_IXFR_PATH 5 // want the full path of the file for the incremental of the zone (IXFR/journal) #define ZDB_ZONE_PATH_PROVIDER_IXFR_FILE 6 // want the full path of the file for the incremental of the zone (IXFR/journal) #define ZDB_ZONE_PATH_PROVIDER_DNSKEY_PATH 7 // want the full path containing the DNSKEY keypairs for the zone (smart signing, key management) #define ZDB_ZONE_PATH_PROVIDER_RNDSUFFIX 64 // appends a suffix to the file name (.SUFFIX), useful for temporary files/files being build #define ZDB_ZONE_PATH_PROVIDER_MKDIR 128 // create the path before returning typedef ya_result zdb_zone_path_provider_callback(const u8* domain_fqdn, char *path_buffer, u32 path_buffer_size, u32 flags); /** * Sets the provider. * * Note that the provider should return the length of the strings it returns. * * @param provider the provider or NULL to reset to the default one. */ void zdb_zone_path_set_provider(zdb_zone_path_provider_callback *provider); zdb_zone_path_provider_callback *zdb_zone_path_get_provider(); struct zdb_zone_path_provider_buffer { void *ptr; u32 size; }; typedef struct zdb_zone_path_provider_buffer zdb_zone_path_provider_buffer; #if BYTE_ORDER == LITTLE_ENDIAN union zdb_zone_info_provider_data { bool _bool; u8 _u8; u16 _u16; u32 _u32; u64 _u64; ya_result _result; void *_ptr; zdb_zone_path_provider_buffer _buffer; }; #elif BYTE_ORDER == BIG_ENDIAN union zdb_zone_info_provider_data { struct { u8 _bool_0, _bool_1, _bool_2, _bool_3, _bool_4, _bool_5, _bool_6,_bool; }; struct { u8 _u8_0, _u8_1, _u8_2, _u8_3, _u8_4, _u8_5, _u8_6,_u8; }; struct { u16 _u16_0, _u16_1, _u16_2, _u16; }; struct { u32 _u32_0, _u32; }; u64 _u64; struct { ya_result _result_0, _result; }; void *_ptr; zdb_zone_path_provider_buffer _buffer; }; #else #error "BYTE_ORDER value not supported" #endif typedef union zdb_zone_info_provider_data zdb_zone_info_provider_data; /** * Zone info should be renamed into zone ctrl (not to be mixed with the server ctrl) * The zone ctrl may become a superset of the path provider * The zdb_zone_path_provider_data could become a generic high-level type */ typedef ya_result zdb_zone_info_provider_callback(const u8 *origin, zdb_zone_info_provider_data *data, u32 flags); #define ZDB_ZONE_INFO_PROVIDER_STORED_SERIAL 0x100 // u32 #define ZDB_ZONE_INFO_PROVIDER_MAX_JOURNAL_SIZE 0x101 // u32 #define ZDB_ZONE_INFO_PROVIDER_ZONE_TYPE 0x102 // u8 (ZT_MASTER, ZT_SLAVE, ...) #define ZDB_ZONE_INFO_PROVIDER_STORE_TRIGGER 0x10000 // NULL, enqueues the storage of the zone #define ZDB_ZONE_INFO_PROVIDER_STORE_NOW 0x10001 // ?, stores the zone now, in this thread #define ZDB_ZONE_INFO_PROVIDER_STORE_IN_PROGRESS 0x10002 // ?, stores the zone now, in this thread void zdb_zone_info_set_provider(zdb_zone_info_provider_callback *data); zdb_zone_info_provider_callback *zdb_zone_info_get_provider(); ya_result zdb_zone_info_get_stored_serial(const u8 *origin, u32 *serial); ya_result zdb_zone_info_get_zone_max_journal_size(const u8 *origin, u32 *size); ya_result zdb_zone_info_get_zone_type(const u8 *origin, u8 *zt); ya_result zdb_zone_info_store_locked_zone(const u8 *origin); ya_result zdb_zone_info_background_store_zone(const u8 *origin); /** * * Should not be used anymore. * * @param origin * @param minimum_serial * @return */ ya_result zdb_zone_info_background_store_zone_and_wait_for_serial(const u8 *origin, u32 minimum_serial); ya_result zdb_zone_info_background_store_in_progress(const u8 *origin); /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_zone_process.h0000644000000000000000000000013214505005531024433 xustar000000000000000030 mtime=1695812441.500968697 30 atime=1695812445.798030239 30 ctime=1695812495.022735236 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_zone_process.h0000664000374500037450000000764314505005531024407 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #pragma once #include #define ZDB_ZONE_PROCESS_CONTINUE 0 #define ZDB_ZONE_PROCESS_SKIP_LABEL 1 #define ZDB_ZONE_PROCESS_STOP 2 struct zdb_zone_process_rrset_callback_parms; typedef ya_result zdb_zone_process_rrset_callback(struct zdb_zone_process_rrset_callback_parms *parms); struct zdb_zone_process_rrset_callback_parms { zdb_zone_process_rrset_callback *cb; const zdb_zone *zone; void *args; const zdb_rr_label *rr_label; const zdb_packed_ttlrdata *rrset; u16 record_type; dnsname_stack fqdn_stack; }; typedef struct zdb_zone_process_rrset_callback_parms zdb_zone_process_rrset_callback_parms; struct zdb_zone_process_label_callback_parms; typedef ya_result zdb_zone_process_label_callback(struct zdb_zone_process_label_callback_parms *parms); struct zdb_zone_process_label_callback_parms { zdb_zone_process_label_callback *cb; zdb_zone *zone; void *args; zdb_rr_label *rr_label; dnsname_stack fqdn_stack; }; typedef struct zdb_zone_process_label_callback_parms zdb_zone_process_label_callback_parms; /** * * All zdb_rr_label of the zone will be passed to the callback * through a zdb_zone_process_label_callback_parms structure * * @param zone * @param cb * @param args * @return */ ya_result zdb_zone_process_all_labels_from_zone(zdb_zone *zone, zdb_zone_process_label_callback *cb, void *args); /** * * All zdb_packed_ttlrdata of all labels of the zone will be passed to the callback * through a zdb_zone_process_rrset_callback_parms * * If the zone is NSEC3, the NSEC3 records and their signature will also be passed * with a virtual/fake (most likely on stack) zdb_rr_label and zdb_packed_ttlrdata * These are meant to be read-only * * @param zone * @param cb * @param args * @return */ ya_result zdb_zone_process_all_rrsets_from_all_labels_from_zone(zdb_zone *zone, zdb_zone_process_rrset_callback *cb, void *args); /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb-zone-reader-filter.h0000644000000000000000000000013214505005531025336 xustar000000000000000030 mtime=1695812441.529969112 30 atime=1695812445.799030253 30 ctime=1695812495.024735265 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb-zone-reader-filter.h0000664000374500037450000000545314505005531025307 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone * @ingroup dnsdb * @brief Functions used to load a zone * * Functions used to load a zone * * @{ */ #pragma once #include #define ZONE_READER_FILTER_ACCEPT 0 #define ZONE_READER_FILTER_REJECT 1 /** * * The filter returns ACCEPT, REJECT or an error code. * */ typedef ya_result zone_file_reader_filter_callback(zone_reader *zr, resource_record *rr, void *callback_data); /** * * Wraps a zone_reader to a filter that skips records using a callback * * @param filtering_reader the filter * @param filtered_reader the filtered * @param callback the callback function * @param callback_data parameter given to the callback function */ void zone_file_reader_filter(zone_reader *filtering_reader, zone_reader *filtered_reader, zone_file_reader_filter_callback *callback, void *callback_data); /** * @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/zdb_zone_write.h0000644000000000000000000000013214505005531024107 xustar000000000000000030 mtime=1695812441.518968954 30 atime=1695812445.798030239 30 ctime=1695812495.026735293 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/zdb_zone_write.h0000664000374500037450000000532714505005531024060 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _ZDB_WRITE_ZONE_H #define _ZDB_WRITE_ZONE_H #include #include #ifdef __cplusplus extern "C" { #endif ya_result zdb_zone_write_text_ex(zdb_zone *zone, output_stream *fos, bool force_label, bool allow_shutdown); ya_result zdb_zone_write_text(zdb_zone* zone, output_stream *fos, bool force_label); #define ZDB_ZONE_WRITE_TEXT_FILE_DEFAULTS 0 #define ZDB_ZONE_WRITE_TEXT_FILE_FORCE_LABEL 1 #define ZDB_ZONE_WRITE_TEXT_FILE_IGNORE_SHUTDOWN 2 ya_result zdb_zone_write_text_file(zdb_zone* zone, const char* output_file, u8 flags); ya_result zdb_zone_write_unbound(const zdb_zone* zone, const char* output_file); #ifdef __cplusplus } #endif #endif /* _ZDB_WRITE_ZONE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/nsec3-forall-label.h0000644000000000000000000000013214505005531024430 xustar000000000000000030 mtime=1695812441.499968682 30 atime=1695812445.798030239 30 ctime=1695812495.028735322 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/nsec3-forall-label.h0000664000374500037450000000602014505005531024370 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include struct nsec3_forall_label_s; typedef ya_result nsec3_forall_label_callback(struct nsec3_forall_label_s*); struct nsec3_forall_label_s { zdb_zone* zone; nsec3_forall_label_callback *callback; void *callback_args; // 4 callback s32 label_stack_level; s32 name_len; s32 origin_len; unsigned int callback_need_fqdn:1,nsec3_covered:1,optout:1,can_ignore_signatures:1; s8 chain_index; u8 zone_lock_owner; // typically: read u8 zone_reserved_owner; // typically: write bool last_call; zdb_rr_label *label_stack[128]; u8 name[2 + MAX_DOMAIN_LENGTH]; }; typedef struct nsec3_forall_label_s nsec3_forall_label_s; static inline zdb_rr_label* nsec3_forall_label_get_label(nsec3_forall_label_s *ctx) { return ctx->label_stack[ctx->label_stack_level]; } /** * This function goes through all the nsec3 database, ie: for updating/creating an nsec3param chain. * This is meant to be used in a background thread. */ void nsec3_forall_label(zdb_zone *zone, s8 chain_index, bool callback_need_fqdn, bool opt_out, bool can_ignore_signatures, u8 lock_owner, u8 reserved_owner, nsec3_forall_label_callback *callback, void *callback_args); yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/dynupdate.h0000644000000000000000000000013014505005531023056 xustar000000000000000029 mtime=1695812441.52496904 30 atime=1695812445.799030253 29 ctime=1695812495.03073535 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/dynupdate.h0000664000374500037450000000603614505005531023027 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbupdate Dynamic update functions * @ingroup dnsdb * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef _ZDB_DYNUPDATE_H #define _ZDB_DYNUPDATE_H /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include #include #include #ifdef __cplusplus extern "C" { #endif #define HAS_DYNUPDATE_DIFF_ENABLED 1 /* * HOWTO : * * Get the query, and determine it's a dynupdate * Call dynupdate_check_prerequisites to verify the update is allowed * If OK Call dynupdate_update on dryrun mode to verify the update should run * smoothly * if OK Save the query on a permanent storage to recover it in case of crash * Answer to the querier * Call dynupdate_update on run mode (dryrun = FALSE) * * The result is * * either the number of bytes read from the buffer * either an encapsulated server error code retrievable with SERVER_ERROR_GETCODE(error) * */ ya_result dynupdate_check_prerequisites(zdb_zone* zone, packet_unpack_reader_data *reader, u16 count); #ifdef __cplusplus } #endif #endif /* _ZDB_DYNUPDATE_H */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/dynupdate-diff.h0000644000000000000000000000013214505005531023766 xustar000000000000000030 mtime=1695812441.526969069 30 atime=1695812445.799030253 30 ctime=1695812495.032735379 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/dynupdate-diff.h0000664000374500037450000006014614505005531023737 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * @{ */ #pragma once #include #include #include #include #include #include #include #include #include struct logger_handle; #define DNSSEC_CHAIN_SUPPORTED_MAX 16 #define DNSSEC_CHAIN_ADD 0x01 #define DNSSEC_CHAIN_DELETE 0x02 #define DNSSEC_CHAIN_REMAP 0x08 // to generate an update of the maps #define DNSSEC_CHAIN_EXISTS 0x10 #define DNSSEC_CHAIN_BEGIN 0x20 // implies that the node is actually in the chain #define DNSSEC_CHAIN_END 0x40 // implies that the node is actually in the chain #define DNSSEC_CHAIN_MARK 0x80 #define DYNUPDATE_DIFF_RETURN_DNSKEY_ADDED 1 // only covers ZSK #define DYNUPDATE_DIFF_RETURN_DNSKEY_REMOVED 2 // only covers ZSK #define DYNUPDATE_DIFF_RETURN_DNSKEY_UPDATED 4 // the reported ZSK status was actually applied #define DYNUPDATE_DIFF_RETURN_MASK 7 #define DYNUPDATE_DIFF_RETURN_NSEC3PARAM 8 #define DYNUPDATE_DIFF_DRYRUN 0x00000001 #define DYNUPDATE_DIFF_RUN 0x00000000 #define DYNUPDATE_DIFF_EXTERNAL 0x00000002 // comes from the network interface #define ZDLABELT_TAG 0x544c4542414c445a #define ZDFFLABL_TAG 0x4c42414c4646445a #define ZDFFLBRR_TAG 0x4242424c4646445a #define ZDFFFQDN_TAG 0x4e4451464646445a #define ZDFFRRST_TAG 0x545352524646445a #define DMSGPCKT_TAG 0x544b435047534d44 struct zone_diff_fqdn; struct zone_diff_fqdn_rr_set; struct dnssec_chain; struct zone_diff_label_tree { const u8 *label; struct zone_diff_fqdn *diff_fqdn; ptr_set sub; // maybe some flags ... }; typedef struct zone_diff_label_tree zone_diff_label_tree; struct zone_diff { ptr_set fqdn; zone_diff_label_tree root; // contains everything but the apex (that would be nuts resource-wise) const u8 *origin; struct zone_diff_fqdn *apex; // quick access to the apex s32 rrsig_validity_interval; s32 rrsig_validity_regeneration; s32 rrsig_validity_jitter; s32 nttl; s32 nsec_change_count; s32 nsec3_change_count; bool rrsig_update_allowed; bool has_active_zsk; bool has_active_ksk; bool may_remove_dnskey; bool may_add_dnskey; bool maintain_nsec; bool maintain_nsec3; }; typedef struct zone_diff zone_diff; struct dnssec_chain_node_t_anon { const int hidden; }; typedef struct dnssec_chain_node_t_anon* dnssec_chain_node_t; struct dnssec_chain_head_t_anon { const int hidden; }; typedef struct dnssec_chain_head_t_anon* dnssec_chain_head_t; typedef int dnssec_chain_node_compare_method(const void* a_, const void* b_); typedef bool dnssec_chain_node_fqdn_is_covered_method(const struct zone_diff_fqdn *diff_fqdn); typedef bool dnssec_chain_node_fqdn_was_covered_method(const struct zone_diff_fqdn *diff_fqdn); typedef dnssec_chain_node_t dnssec_chain_node_new_method(const u8 *fqdn, dnssec_chain_head_t chain); typedef dnssec_chain_node_t dnssec_chain_node_prev_method(const dnssec_chain_node_t node_); typedef void dnssec_chain_node_merge_method(dnssec_chain_node_t node_, dnssec_chain_node_t with_); typedef dnssec_chain_node_t dnssec_chain_node_next_method(const dnssec_chain_node_t node_); typedef void dnssec_chain_node_state_set_method(dnssec_chain_node_t node_, u8 value); typedef u8 dnssec_chain_node_state_get_method(const dnssec_chain_node_t node_); typedef void dnssec_chain_node_delete_method(dnssec_chain_node_t node_); typedef void dnssec_chain_node_publish_delete_method(dnssec_chain_head_t chain_, dnssec_chain_node_t from_, dnssec_chain_node_t to_, zone_diff *diff, ptr_vector *collection); typedef void dnssec_chain_node_publish_add_method(dnssec_chain_head_t chain_, dnssec_chain_node_t from_, dnssec_chain_node_t to_, zone_diff *diff, ptr_vector *collection); typedef void dnssec_chain_node_publish_log_method(dnssec_chain_node_t from_, dnssec_chain_node_t to_); typedef bool dnssec_chain_node_isempty_method(dnssec_chain_head_t chain_); typedef void dnssec_chain_node_format_writer_init(dnssec_chain_node_t node_, format_writer *outfw); typedef bool dnssec_chain_node_rrset_should_be_signed_method(const struct zone_diff_fqdn *diff_fqdn, const struct zone_diff_fqdn_rr_set *rr_set); struct dnssec_chain_node_vtbl { dnssec_chain_node_fqdn_is_covered_method *fqdn_is_covered; dnssec_chain_node_fqdn_was_covered_method *fqdn_was_covered; dnssec_chain_node_new_method *node_new; dnssec_chain_node_prev_method *node_prev; dnssec_chain_node_merge_method *node_merge; dnssec_chain_node_next_method *node_next; dnssec_chain_node_state_set_method *state_set; dnssec_chain_node_state_get_method *state_get; dnssec_chain_node_delete_method *node_delete; dnssec_chain_node_publish_delete_method *publish_delete; dnssec_chain_node_publish_add_method *publish_add; dnssec_chain_node_publish_log_method *publish_log; dnssec_chain_node_compare_method *compare; void (*ptr_set_node_delete_callback)(ptr_node*); dnssec_chain_node_isempty_method *isempty; dnssec_chain_node_format_writer_init *format_writer_init; dnssec_chain_node_rrset_should_be_signed_method *rrset_should_be_signed; const char * const __name__; }; typedef struct dnssec_chain_node_vtbl dnssec_chain_node_vtbl; struct dnssec_chain { zone_diff *diff; const dnssec_chain_node_vtbl *chain; ptr_set chain_diff[DNSSEC_CHAIN_SUPPORTED_MAX]; dnssec_chain_head_t chains[DNSSEC_CHAIN_SUPPORTED_MAX]; bool chain_being_deleted[DNSSEC_CHAIN_SUPPORTED_MAX]; int chains_count; }; typedef struct dnssec_chain dnssec_chain; const dnssec_chain_node_vtbl *dynupdate_nosec_chain_get_vtbl(); const dnssec_chain_node_vtbl *dynupdate_nsec_chain_get_vtbl(); const dnssec_chain_node_vtbl *dynupdate_nsec3_chain_get_vtbl(); const dnssec_chain_node_vtbl *dynupdate_nsec3_optout_chain_get_vtbl(); /** * Initialises a dnssec chain (editor). * NSEC and NSEC3 chains cannot be mixed. * The actual chain must be set using dnssec_chain_add_chain * * @param dc * @param chain_functions */ void dnssec_chain_init(dnssec_chain *dc, const dnssec_chain_node_vtbl *chain_functions, zone_diff* diff); /** * Adds a chain to the chain editor. * * NSEC3: one of the nsec3_zone* of the zone (add them one at a time). * NSEC: the nsec_zone* of the zone. * * @param dc * @param chain * @param being_deleted tells the chain is on its way out and records should be removed, not added */ void dnssec_chain_add_chain(dnssec_chain *dc, dnssec_chain_head_t chain, bool being_deleted); /** * Adds a node to the chain. * * @param dc * @param fqdn * @param rtype */ void dnssec_chain_add(dnssec_chain *dc, const u8 *fqdn, u16 rtype); /** * Removes a node from the chain. * * @param dc * @param fqdn * @param rtype */ void dnssec_chain_del(dnssec_chain *dc, const u8 *fqdn, u16 rtype); /** * Computes the changes of the chain into a del and an add records vector. * * @param diff * @param origin * @param nttl */ void dnssec_chain_store_diff(dnssec_chain *dc, zone_diff *diff, ptr_vector *keys, ptr_vector *del, ptr_vector *add); /** * Releases the memory used by a chain */ void dnssec_chain_finalize(dnssec_chain *dc); /** * Resource Record States */ #define ZONE_DIFF_RR_ADD 1 // + #define ZONE_DIFF_RR_REMOVE 2 // - #define ZONE_DIFF_RR_RDATA_OWNED 4 // O #define ZONE_DIFF_RR_VOLATILE 8 // V not in the diff set #define ZONE_DIFF_RR_IN_ZONE 16 // E #define ZONE_DIFF_RR_AUTOMATED 32 // A #define ZONE_DIFF_RR_ADDED 64 // . done #define ZONE_DIFF_RR_REMOVED 128 // . done /** * Diff changes */ #define ZONE_DIFF_CHANGES_NONE 0 #define ZONE_DIFF_CHANGES_ADD 1 #define ZONE_DIFF_CHANGES_REMOVE 2 #define ZONE_DIFF_CHANGES_KEPT 4 struct zone_diff_label_rr { u8 *fqdn; void *rdata; s32 ttl; u16 rtype; u16 rclass; u16 rdata_size; u8 state; }; typedef struct zone_diff_label_rr zone_diff_label_rr; struct zone_diff_fqdn_rr_set { ptr_set rr; intptr key_mask; s32 org_ttl; s32 new_ttl; u16 rtype; u16 rclass; }; typedef struct zone_diff_fqdn_rr_set zone_diff_fqdn_rr_set; struct zone_diff_fqdn { u32_set rrset; u8 *fqdn; /*struct zone_diff_fqdn *direct_parent; u32 nonempty_children;*/ unsigned int type_map_changed:1, all_rrset_added:1, // completely added all_rrset_removed:1, // completely removed is_apex:1, will_be_removed:1, at_delegation:1, under_delegation:1, will_have_ds:1, will_be_non_empty:1, will_have_children:1, will_have_new_nsec:1, was_at_delegation:1, was_under_delegation:1, had_ds:1, was_non_empty:1, had_children:1, rrsig_removed:1, rrsig_added:1, rrsig_kept:1, rrsig_expect_new_rrsig:1, rrsig_expect_no_rrsig:1, is_nsec3:1, children_added:1, // tells that the children are available in the diff, else it means that had_children = will_have_children records_flags_set:1, children_flags_set:1, has_active_zsk:1, has_active_ksk:1, is_in_database:1; }; typedef struct zone_diff_fqdn zone_diff_fqdn; /** * Initialises a zone diff * * @param diff * @param origin * @param nttl * @param rrsig_push_allowed allows updating an RRSIG "manually" (external signing process) */ void zone_diff_init(zone_diff *diff, zdb_zone *zone, bool rrsig_update_allowed); /** * Adds the SOA records for the incremental update. * * @param diff * @return */ ya_result zone_diff_set_soa(zone_diff *diff, zdb_rr_label *label); /** * Updates status and validates a diff. * * @param diff * @return */ ya_result zone_diff_validate(zone_diff *diff); /** * Stores changes of a diff into two vectors. * Optionally keep track of record sets that need to be signed. * Optionally notify a chain about changes. * * @param diff * @param dc can be NULL * @param rrset_to_sign_vector can be NULL * @param remove * @param add * @param regeneration_seconds * @return TRUE iff there is a DNSKEY rrset in the diff */ s32 zone_diff_get_changes(zone_diff *diff, ptr_vector *rrset_to_sign_vector, ptr_vector *ksks, ptr_vector *zsks, ptr_vector *remove, ptr_vector *add, s32 regeneration_seconds); /** * Returns TRUE iff there are changes in the diff * * @param diff * @param rrset_to_sign_vector can be NULL * * @return TRUE iff there are changes in the diff */ bool zone_diff_has_changes(zone_diff *diff, ptr_vector *rrset_to_sign_vector); static inline bool zone_diff_fqdn_is_covered_by_nsec3(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (diff_fqdn->at_delegation && !diff_fqdn->under_delegation)|| // has NS records (but is not below NS records) (!(diff_fqdn->at_delegation || diff_fqdn->under_delegation) && (diff_fqdn->will_be_non_empty || diff_fqdn->will_have_children)) // else it's under a delegation ; } static inline bool zone_diff_fqdn_was_covered_by__nsec3(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (diff_fqdn->was_at_delegation && !diff_fqdn->was_under_delegation) || // had NS records (but is not below NS records) (!(diff_fqdn->was_at_delegation || diff_fqdn->was_under_delegation) && (diff_fqdn->was_non_empty || diff_fqdn->had_children)) // else it was under a delegation ; } static inline bool zone_diff_fqdn_is_covered_by_nsec3_optout(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (diff_fqdn->at_delegation && !diff_fqdn->under_delegation && diff_fqdn->will_have_ds) || // has DS record(s) (!(diff_fqdn->at_delegation || diff_fqdn->under_delegation) && (diff_fqdn->will_be_non_empty || diff_fqdn->will_have_children)) // else it's under a delegation ; } static inline bool zone_diff_fqdn_was_covered_by_nsec3_optout(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (diff_fqdn->was_at_delegation && !diff_fqdn->was_under_delegation && diff_fqdn->had_ds) || // had DS record(s) (!(diff_fqdn->was_at_delegation || diff_fqdn->was_under_delegation) && (diff_fqdn->was_non_empty || diff_fqdn->had_children)) // else it was under a delegation ; } static inline bool zone_diff_fqdn_is_covered_by_nsec(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (!diff_fqdn->under_delegation && (diff_fqdn->will_be_non_empty /*|| diff_fqdn->will_have_children*/)); } static inline bool zone_diff_fqdn_was_covered_by_nsec(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (!diff_fqdn->was_under_delegation && (diff_fqdn->was_non_empty /*|| diff_fqdn->will_have_children*/)); } /** * debug * * @param rr_set * @param origin * @param handle * @param level */ void zone_diff_fqdn_rr_set_log(const zone_diff_fqdn_rr_set *rr_set, const u8* origin, struct logger_handle *handle, int level); /** * debug * * @param origin * @param diff_fqdn * @param level */ void zone_diff_fqdn_log(const zone_diff_fqdn* diff_fqdn, const u8 *origin, struct logger_handle *handle, int level); /** * debug * * @param diff * @param handle * @param level */ void zone_diff_log(const zone_diff *diff, struct logger_handle *handle, int level); /** * debug * * @param diff * @param handle * @param level */ int zone_diff_check_changes(const zone_diff *diff, struct logger_handle *handle, int level); /** * Signs RRSET with all active keys found in keys. * Doesn't do any pertinence tests. * It's only use now is to add RRSIG records to NSEC3 rrsets that have no valid signatures * */ void zone_diff_sign_rrset(zone_diff *diff, zdb_zone *zone, ptr_vector *keys, ptr_vector *add, zone_diff_fqdn_rr_set *rr_set, zone_diff_fqdn_rr_set *rrsig_rr_set); /** * Appends RRSIGs to remove/add vector, following the the need-to-be-signed RR set, using keys from KSK and ZSK vectors. * * @param diff * @param rrset_to_sign_vector * @param ksks * @param zsks * @param remove * @param add */ ya_result zone_diff_sign(zone_diff *diff, zdb_zone *zone, ptr_vector *rrset_to_sign_vector, ptr_vector *ksks, ptr_vector *zsks, ptr_vector *remove, ptr_vector* add); /** * Finalises a zone diff * * @param diff */ void zone_diff_finalize(zone_diff *diff); zone_diff_label_rr *zone_diff_label_rr_new(const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, void *rdata, u16 rdata_size, bool copy); zone_diff_label_rr *zone_diff_label_rr_new_nordata(const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size); void zone_diff_label_rr_init_tmp(zone_diff_label_rr *rr, const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, void *rdata, u16 rdata_size); zone_diff_fqdn *zone_diff_fqdn_add_empty(zone_diff *diff, const u8 *fqdn); zone_diff_fqdn *zone_diff_fqdn_add(zone_diff *diff, const u8 *fqdn, zdb_rr_label *label); zone_diff_fqdn* zone_diff_add_static_fqdn(zone_diff *diff, const u8 *fqdn, zdb_rr_label *label); void zone_diff_add_fqdn_children(zone_diff *diff, const u8 *fqdn, zdb_rr_label *label); struct nsec3_node; zone_diff_fqdn* zone_diff_add_nsec3(zone_diff *diff, const nsec3_zone* n3, const struct nsec3_node *item, s32 ttl, zone_diff_fqdn_rr_set **out_nsec3_rrset); zone_diff_fqdn* zone_diff_add_nsec3_ex(zone_diff *diff, const ptr_vector *zsk_keys, const nsec3_zone* n3, const struct nsec3_node *item, s32 ttl, zone_diff_fqdn_rr_set **out_nsec3_rrset, s32 now, s32 regeneration); // to detect empty non-terminals bool zone_diff_fqdn_has_children(zone_diff *diff, const u8 *fqdn); /** * Enables the or_state flags in every record of the set. * * @param rrset * @param or_state */ void zone_diff_fqdn_rr_set_set_state(zone_diff_fqdn_rr_set *rrset, u8 or_state); /** * Returns true iff an rrset of the given type will be present after applying * the diff. * * @param diff_fqdn * @param rtype * @return */ bool zone_diff_will_have_rrset_type(const zone_diff_fqdn *diff_fqdn, u16 rtype); bool zone_diff_remove_rrset_type(zone_diff_fqdn *diff_fqdn, u16 rtype); /** * Releases keys that will not be in the apex after the diff is applied. * * @param diff * @param keys */ void zone_diff_filter_out_keys(const zone_diff *diff, ptr_vector *keys); zone_diff_fqdn_rr_set *zone_diff_fqdn_rr_set_add(zone_diff_fqdn *diff_fqdn, u16 rtype); /** * Returns the local copy of the specified RRSET * DOES NOT create an emtpy set if it does not exist. * * @param diff_fqdn * @param rtype * @return */ zone_diff_fqdn_rr_set *zone_diff_fqdn_rr_set_get(const zone_diff_fqdn *diff_fqdn, u16 rtype); /** * Returns the local copy of the specified RRSET * * @param diff_fqdn * @param rtype * @return */ const zone_diff_fqdn_rr_set *zone_diff_fqdn_rr_get_const(const zone_diff_fqdn *diff_fqdn, u16 rtype); zone_diff_fqdn_rr_set *zone_diff_fqdn_rr_get_if_exists(const zone_diff_fqdn *diff_fqdn, u16 rtype); /** * Returns the TTL of the RRSET if it exists * * @param rrset * @return */ s32 zone_diff_fqdn_rr_set_get_ttl(zone_diff_fqdn_rr_set *rrset); /** * Returns the TTL of the RRSET if it exists * * @param diff_fqdn * @param rtype * @return */ s32 zone_diff_fqdn_rr_get_ttl(const zone_diff_fqdn *diff_fqdn, u16 rtype); // Adds a record, if the record exists already in the set, delete the one in the set void zone_diff_fqdn_rr_set_rr_add_replace(zone_diff_fqdn_rr_set *rr_set, zone_diff_label_rr *rr); // Adds a record, if the record exists already in the set, delete the record and returns the one in the set zone_diff_label_rr* zone_diff_fqdn_rr_set_rr_add_get(zone_diff_fqdn_rr_set *rr_set, zone_diff_label_rr *rr); /** * Deletes an RRSET if it's empty. * * @param diff_fqdn * @param rtype */ void zone_diff_fqdn_rr_clear(zone_diff_fqdn *diff_fqdn, u16 rtype); /** * Returns TRUE iff an rrset as been added or removed from the label. * Stressing out this concerns RRSET as a whole. * * @param diff_fqdn * @return */ bool zone_diff_fqdn_type_map_changed(const zone_diff_fqdn *diff_fqdn); /** * find label for fqdn ... * * @param diff * @param fqdn * @param label * @return */ const zone_diff_fqdn *zone_diff_fqdn_get_const(const zone_diff *diff, const u8 *fqdn); zone_diff_fqdn* zone_diff_fqdn_get(const zone_diff *diff, const u8 *fqdn); /** * Generates a type bit map based on the diff including records matching: * * (status & mask) == masked * * mask,masked * all pre records : ZONE_DIFF_REMOVE|ZONE_DIFF_ADD == 0 * all post records: ZONE_DIFF_REMOVE = 0 * * Note: it ignores the A and AAAA records when at or under a delegation. * * @param diff * @param fqdn * @param bitmap * @param mask * @param masked * @return */ u16 zone_diff_type_bit_map_generate(const zone_diff *diff, const u8 *fqdn, type_bit_maps_context *bitmap, u8 mask, u8 masked, const u8 *chain_node_fqdn, bool append_existing_signatures); /** * Adds a record on a diff * * @param diff * @param rr_label * @param fqdn * @param rtype * @param rttl * @param rdata_size * @param rdata */ zone_diff_label_rr* zone_diff_record_add(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn, u16 rtype, s32 rttl, u16 rdata_size, void *rdata); /** * * Adds the removal of a specific record on a diff * * @param diff * @param rr_label * @param fqdn * @param rtype * @param rttl * @param rdata_size * @param rdata */ void zone_diff_record_remove(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn, u16 rtype, s32 rttl, u16 rdata_size, void *rdata); bool zone_diff_record_remove_existing(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn, u16 rtype, s32 rttl, u16 rdata_size, void *rdata); void zone_diff_record_remove_automated(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn, u16 rtype, s32 rttl, u16 rdata_size, void *rdata); /** * Adds the removal of a record set on a diff * * @param diff * @param rr_label * @param fqdn * @param rtype */ void zone_diff_record_remove_all(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn, u16 rtype); /** * Adds the removal all record sets on a diff * * @param diff * @param rr_label * @param fqdn * @param rtype */ void zone_diff_record_remove_all_sets(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn); static inline s32 diff_generate_signature_interval(zone_diff *diff) { s32 maxinterval = diff->rrsig_validity_interval + rand() % (diff->rrsig_validity_jitter + 1); return maxinterval; } /** * Writes the del then add records to the journal, * deletes the records marked as volatile, * exchanges the locks of the zone, * replays the journal * exchanges the locks back. * * Returns the result of the replay or SUCCESS if there was nothing to replay. * * @param zone * @param secondary_lock * @param del_vector * @param add_vector * @return */ ya_result dynupdate_diff_write_to_journal_and_replay(zdb_zone *zone, u8 secondary_lock, ptr_vector *del_vector, ptr_vector *add_vector); /** * A format writer for the zone_diff_label state field * * Usage example: * format_writer state_flags = {zone_diff_label_state_flags_long_format, &rr->state}; * Then: * format("%w", &state_flags); */ void zone_diff_label_state_flags_long_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters); void zone_diff_store_diff_dnskey_get_keys(zone_diff *diff, ptr_vector *ksks, ptr_vector *zsks, s32 regeneration_seconds); /** * */ ya_result dynupdate_diff(zdb_zone *zone, packet_unpack_reader_data *reader, u16 count, u8 secondary_lock, u32 flags); /* ya_result dynupdate_diff_chain(zdb_zone *zone, u8 secondary_lock) { zone_diff diff; zone_diff_init(&diff, zone->origin, zone->min_ttl); zone_diff_fqdn* diff_fqdn = zone_diff_add_fqdn(&diff, fqdn, zdb_rr_label *label) zone_diff_finalize(&diff); } */ /** * Adds a node to the chain from a zone_diff_fqdn * * @param dc * @param fqdn * @param rtype * * @return number of operations counted */ int dnssec_chain_add_from_diff_fqdn(dnssec_chain *dc, zone_diff_fqdn* diff_fqdn, u16 rtype); /** * Removes a node from the chain from a zone_diff_fqdn * * @param dc * @param fqdn * @param rtype * * @return number of operations counted */ int dnssec_chain_del_from_diff_fqdn(dnssec_chain *dc, zone_diff_fqdn* diff_fqdn, u16 rtype); void zone_diff_record_state_format(const void* data, output_stream* os, s32 a, char b , bool c, void* reserved_for_method_parameters); /** @} */ yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/PaxHeaders.1636/dynupdate-message.h0000644000000000000000000000013214505005531024502 xustar000000000000000030 mtime=1695812441.532969155 30 atime=1695812445.799030253 30 ctime=1695812495.034735408 yadifa-2.6.5-11201/lib/dnsdb/include/dnsdb/dynupdate-message.h0000664000374500037450000001035314505005531024446 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * @{ */ #pragma once #include #include #include struct dynupdate_message { u8 *packet; u32 size; u16 rclass; packet_writer pw; }; typedef struct dynupdate_message dynupdate_message; /** * Initialises a simple update buffer * * @param dmsg */ void dynupdate_message_init(dynupdate_message *dmsg, const u8 *origin, u16 rclass); /** * Clears a simple update buffer * * @param dmsg */ void dynupdate_message_reset(dynupdate_message *dmsg, const u8 *origin, u16 rclass); /** * Releases resources. * * @param dmsg */ void dynupdate_message_finalize(dynupdate_message *dmsg); /** * Sets a reader up for the buffer. * * @param dmsg * @param purd */ void dynupdate_message_set_reader(dynupdate_message *dmsg, packet_unpack_reader_data *purd); /** * Return the number of update records. * * @param dmsg * @return */ u16 dynupdate_message_get_count(dynupdate_message *dmsg); /** * Adds a dnskey record to the buffer * * @param dmsg * @param ttl * @param key * @return */ ya_result dynupdate_message_add_dnskey(dynupdate_message *dmsg, s32 ttl, const dnssec_key *key); /** * Deletes a dnskey record to the buffer * * @param dmsg * @param ttl * @param key * @return */ ya_result dynupdate_message_del_dnskey(dynupdate_message *dmsg, const dnssec_key *key); /** * Appends a "add RR" command to the buffer. * * @param dmsg * @param fqdn * @param rtype * @param ttl * @param rdata_size * @param rdata * @return */ ya_result dynupdate_message_add_record(dynupdate_message *dmsg, const u8 *fqdn, u16 rtype, s32 ttl, u16 rdata_size, const void *rdata); /** * Appends a "delete RR" command to the buffer. * * @param dmsg * @param fqdn * @param rtype * @param ttl * @param rdata_size * @param rdata * @return */ ya_result dynupdate_message_del_record(dynupdate_message *dmsg, const u8 *fqdn, u16 rtype, s32 ttl, u16 rdata_size, const void *rdata); /** * * Appends a "delete RRSET" command to the buffer. * * @param dmsg * @param fqdn * @param rtype * @return */ ya_result dynupdate_message_del_record_set(dynupdate_message *dmsg, const u8 *fqdn, u16 rtype); /** * Appends a "delete fqdn" command to the buffer. * * @param dmsg * @param fqdn * @return */ ya_result dynupdate_message_del_fqdn(dynupdate_message *dmsg, const u8 *fqdn); /** @} */ yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/src0000644000000000000000000000013114505005617016713 xustar000000000000000030 mtime=1695812495.205737857 29 atime=1695812499.08179337 30 ctime=1695812495.205737857 yadifa-2.6.5-11201/lib/dnsdb/src/0000775000374500037450000000000014505005617016733 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/avl.c0000644000000000000000000000013214505005531017712 xustar000000000000000030 mtime=1695812441.735972062 30 atime=1695812445.801030282 30 ctime=1695812495.049735623 yadifa-2.6.5-11201/lib/dnsdb/src/avl.c0000664000374500037450000010443314505005531017661 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief AVL structure and functions * * AVL structure and functions * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #define DEBUG_LEVEL 0 #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include "dnsdb/zdb_error.h" #include #if 0 /* fix */ #else #define DUMP_NODE(...) #endif #include "dnsdb/avl.h" #ifdef LDEBUG #undef LDEBUG #define LDEBUG(...) #endif /* This should be closer to 40 */ #define MAX_DEPTH 40 /* 64 */ /* * The following macros are defining relevant fields in the node */ #define LEFT_CHILD(node) ((node)->children.lr.left) #define RIGHT_CHILD(node) ((node)->children.lr.right) #define CHILD(node,id) ((node)->children.child[(id)]) #define BALANCE(node) ((node)->balance) /* * The following macros are defining relevant operations in the node */ /* What is used to compare the nodes */ #define REFERENCE_TYPE hashcode #define INIT_NODE(node,reference) (node)->hash=(reference);(node)->data=NULL #define REFERENCE(node) (node)->hash /* Compare two references */ #define BIGGER(reference_a,reference_b) (reference_a)>(reference_b) /* What is returned when a node is created/found */ #define DATA(node) (node)->data #define DATAPTR(node) &(node)->data /* Copies the payload of a node (not the balance + pointers) */ #define COPY_PAYLOAD(node_trg,node_src) (node_trg)->data = (node_src)->data; (node_trg)->hash = (node_src)->hash /* * */ #define TOOLEFT (-2) #define LEFT (-1) #define MIDDLE 0 #define RIGHT 1 #define TOORIGHT 2 #define DIR_LEFT 0 #define DIR_RIGHT 1 #define DIR_CRASH 127 #define avl_destroy_node(node) LDEBUG(9, "avl_destroy_node(%p)\n",node);ZFREE_OBJECT(node); /* #define DIR_TO_BALANCE(dir) (((dir)==0)?LEFT:RIGHT) */ static s8 DIR_TO_BALANCE_[2] = {LEFT, RIGHT}; #define DIR_TO_BALANCE(dir) DIR_TO_BALANCE_[(dir)] /* #define BALANCE_TO_DIR(bal) (((bal)RIGHT)) static inline avl_node* avl_node_single_rotation2(avl_node* node) { avl_node* save; if(BALANCE(node) < 0) /* balance = LEFT -> dir = RIGHT other = LEFT */ { save = LEFT_CHILD(node); LEFT_CHILD(node) = RIGHT_CHILD(save); RIGHT_CHILD(save) = node; } else { save = RIGHT_CHILD(node); RIGHT_CHILD(node) = LEFT_CHILD(save); LEFT_CHILD(save) = node; } BALANCE(node) = MIDDLE; BALANCE(save) = MIDDLE; return save; } static inline avl_node* avl_node_double_rotation2(avl_node* node) { avl_node* save; if(BALANCE(node) < 0) /* balance = LEFT -> dir = RIGHT other = LEFT */ { save = RIGHT_CHILD(LEFT_CHILD(node)); if(BALANCE(save) == MIDDLE) { BALANCE(LEFT_CHILD(node)) = MIDDLE; BALANCE(node) = MIDDLE; } else if(BALANCE(save) > 0) /* dir right & balance right */ { BALANCE(LEFT_CHILD(node)) = LEFT; BALANCE(node) = MIDDLE; } else /* BALANCE(save)<0 */ { BALANCE(LEFT_CHILD(node)) = MIDDLE; BALANCE(node) = RIGHT; } BALANCE(save) = MIDDLE; RIGHT_CHILD(LEFT_CHILD(node)) = LEFT_CHILD(save); LEFT_CHILD(save) = LEFT_CHILD(node); LEFT_CHILD(node) = RIGHT_CHILD(save); RIGHT_CHILD(save) = node; } else /* balance = RIGHT -> dir = LEFT other = RIGHT */ { save = LEFT_CHILD(RIGHT_CHILD(node)); if(BALANCE(save) == MIDDLE) { BALANCE(RIGHT_CHILD(node)) = MIDDLE; BALANCE(node) = MIDDLE; } else if(BALANCE(save) < 0) /* dir left & balance left */ { BALANCE(RIGHT_CHILD(node)) = RIGHT; BALANCE(node) = MIDDLE; } else /* BALANCE(save)>0 */ { BALANCE(RIGHT_CHILD(node)) = MIDDLE; BALANCE(node) = LEFT; } BALANCE(save) = MIDDLE; LEFT_CHILD(RIGHT_CHILD(node)) = RIGHT_CHILD(save); RIGHT_CHILD(save) = RIGHT_CHILD(node); RIGHT_CHILD(node) = LEFT_CHILD(save); LEFT_CHILD(save) = node; } return save; } static avl_node* avl_create_node(hashcode hash) { avl_node* node; ZALLOC_OBJECT_OR_DIE( node, avl_node, DATABASE_AVL_NODE_TAG); LEFT_CHILD(node) = NULL; RIGHT_CHILD(node) = NULL; node->data = NULL; node->hash = hash; BALANCE(node) = MIDDLE; return node; } /* static void avl_destroy_node(avl_node* node) { avl_destroy_node(node); } */ /** @brief Initializes the tree * * Initializes the tree. * Basically : *tree=NULL; * * @param[in] tree the tree to initialize * */ void avl_init(avl_tree* tree) { *tree = NULL; } /** @brief Find a node in the tree * * Find a node in the tree matching a hash value. * * @param[in] root the tree to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node or NULL if there is no such node. */ #if !ZDB_INLINES_AVL_FIND void* avl_find(avl_tree* root, hashcode obj_hash) { #if 1 /* NOTE: If I do this in assembly code. I could probably win a few cycles * This is by far the most common call of the DB * NOTE: The compiler's job is very good. */ avl_node* node = *root; hashcode h; /* This is one of the parts I could try to optimize * I've checked the assembly, and it sucks ... */ /* Both the double-test while/ternary and the current one * are producing the same assembly code. */ while(node != NULL) { if((h = node->hash) == obj_hash) { return node->data; } node = CHILD(node, (obj_hash > h)&1); } /*return (node!=NULL)?node->data:NULL;*/ return NULL; #else /* * I would ... * * mov eax,node * test eax,eax ; node==NULL ? * jz exit_null ; YES -> JUMP * mov edx,obj_hash * loop: * cmp edx,[eax+hash_offs] ; node->hash==obj_hash ? * sbb ebx,ebx ; below=>ebx=~0 * jz exit_data ; EQUAL -> JUMP * and ebx,4 ; ebx=0 | 1 (left | right) * mov eax,[eax+child_offs+ebx] ; node=node->child[left|right] * test eax,eax ; node==NULL ? * jnz loop ; NO -> JUMP * exit_null: * ret ; return NULL * exit_data: * mov eax,[eax+data_offs] ; return node->data * ret */ /* NOT DONE YET !!! */ /* x86_64 : RDI = root, ESI = obj_hash */ __asm__ ( "movq (%rdi),%rax\n\t" "testq %rax,%rax\n\t" "jz avl_find_return_null\n\t" "\navl_find_loop:\n\t" "cmpl 16(%rax),%esi\n\t" "jz avl_find_return_data\n\t" "sbbq %rcx,%rcx\n\t" "andq 8,%rcx\n\t" "movq (%rcx,%rax),%rax\n\t" "testq %rax,%rax\n\t" "jnz avl_find_loop\n\t" "\navl_find_return_null:\n\t" #if DEBUG "leave\n\t" #endif "ret\n\t" "\navl_find_return_data:\n\t" "mov 16(%rax),%rax\n\t" #if DEBUG "leave\n\t" #endif "ret\n\t" ); #endif } #endif /** @brief Find a node in the tree * * Find a node in the tree matching a hash value. * This is required for search that could lead to a change to the data. * * @param[in] root the tree to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node or NULL if there is no such node. */ #if !ZDB_INLINES_AVL_FIND void** avl_findp(avl_tree* root, hashcode obj_hash) { avl_node* node = *root; hashcode h; while(node != NULL /* &&((h=node->hash)!=obj_hash) */) { if((h = node->hash) == obj_hash) { return &node->data; } node = CHILD(node, (obj_hash > h)&1); } /* return (node!=NULL)?&node->data:NULL; */ return NULL; } #endif /** @brief Insert a node into the tree. * * Insert data into the tree. * Since hash can have collisions, the data will most likely be a collection * (another tree, a list, ...) * * NOTE: * If the node associated to the hash already exists, it is returned unaltered, * the caller will be responsible to manipulate the node's data. * Else a new node is created, pointing to the data. * * @param[in] root the tree where the insertion should be made * @param[in] obj_hash the hash associated to the data * @param[out] obj the data to insert * * @return The node associated to the hash */ void** avl_insert(avl_tree* root, hashcode obj_hash) { LDEBUG(9, "avl_insert(%p,%08x) ------------------------------\n", root, obj_hash); if(*root == NULL) { *root = avl_create_node(obj_hash); LDEBUG(9, "First node (root) (%p)\n", *root); return &(*root)->data; } avl_node * nodes[MAX_DEPTH]; s8 balances[MAX_DEPTH]; s8 dirs[MAX_DEPTH]; avl_node* node = *root; hashcode node_hash; int level = 0; s8 dir = MIDDLE; while((node != NULL) && (obj_hash != (node_hash = node->hash))) { nodes[level] = node; balances[level] = BALANCE(node); /* DIR_LEFT = 0, DIR_RIGHT = 1 */ dir = (obj_hash > node_hash)&1; node = CHILD(node, dir); dirs[level++] = dir; } LDEBUG(9, "Level = %i\n", level); if(node != NULL) { /* match */ LDEBUG(9, "Got a match\n"); return &node->data; } /* Add a new node to the last one (the parent) */ node = nodes[--level]; /* the parent is node */ avl_node* ret = avl_create_node(obj_hash); CHILD(node, dir) = ret; LDEBUG(9, "Created a new node from %08x, going %i (%p)\n", node->hash, dir, ret); if(BALANCE(node) == MIDDLE) { /* There were no child, now there is one */ /* not balanced anymore */ BALANCE(node) = DIR_TO_BALANCE(dir); /* 0 or 1 => -1 or +1 */ LDEBUG(9, "parent was balanced, now it is not anymore : %i (%i)\n", dir, BALANCE(node)); } else { /* There was a child, now there is two */ /* balance */ BALANCE(node) = MIDDLE; LDEBUG(9, "parent was not balanced, now it is\n"); } avl_node* parent; /* Now I have to update the balance up to the root (if needed ...) * node is m_nodes[level] * we need the parent at m_nodes[level-1] * parent -> node -> (new node/processed node) */ while(level > 0) /* level points to the parent */ { LDEBUG(9, "\tUpdating balance at %i\n", level); if(BALANCE(node) == balances[level]) /* balance of the node */ { /* this branch will exit */ /* The node's balance has not been changed */ return &ret->data; } parent = nodes[level - 1]; /* The node's balance has been changed */ LDEBUG(9, "\t\tBalance of %08x was %i, now it is %i\n", node->hash, balances[level], BALANCE(node)); if(BALANCE(node) == MIDDLE) /* this branch will exit */ { /* BALANCE(node)==MIDDLE and we are balanced * balanced -> done */ LDEBUG(9, "Done (E)\n"); return &ret->data; } /* not balanced (anymore) */ /* Now dir child it is unbalanced ... */ /* Let's update the imbalance */ dir = dirs[level - 1]; LDEBUG(9, "\t\t\tIMBALANCE: dir=%i old parent balance=%i patch=%i\n", dir, BALANCE(parent), DIR_TO_BALANCE(dir)); BALANCE(parent) += DIR_TO_BALANCE(dir); if(MUST_REBALANCE(parent)) /* this branch will exit */ { /* parent is the "root" */ /* node is the pivot */ LDEBUG(9, "\t\t\t\tREBALANCING of %08x\n", parent->hash); BALANCE(parent) >>= 1; /* reset the balance to -1;1 ... */ LDEBUG(9, "\t\t\t\tBalance fix -> %i\n", BALANCE(parent)); /* HERE THE BALANCES ARE LOST/CORRUPTED !!! */ if(BALANCE(node) == BALANCE(parent)) /* if the sign is the same ... */ { /* BALANCE(node)=0; */ node = avl_node_single_rotation2(parent); /* the parent's parent has to be updated (to node) */ LDEBUG(9, "\t\t\t\tSingle rotation, new parent is %08x\n", node->hash); } else { /* BALANCE(node)=0; */ node = avl_node_double_rotation2(parent); /* the parent's parent has to be updated (to node) */ LDEBUG(9, "\t\t\t\tDouble rotation, new parent is %08x\n", node->hash); } /* typically ... * level--; * node=parent; * parent=m_nodes[level-1]; * here I have to reset the new parent * -> I have to get the parent on level-2 (oops if level is < 2 : * it means that the parent is the root, thus that we have to fix the root) * -> I have to get the dir used on level-2 and set it to node */ if(level > 1) /* 2 or more ... */ { CHILD(nodes[level - 2], dirs[level - 2]) = node; } else /* root */ { LDEBUG(9, "Root changing from %08x to %08x\n", (*root)->hash, node->hash); *root = node; } /* rebalancing -> done */ LDEBUG(9, "Done (I)\n"); return &ret->data; } node = parent; level--; } return &ret->data; } /** @brief Deletes a node from the tree. * * Deletes a node from the tree. * * @param[in] root the tree from which the delete will be made * @param[in] obj_hash the hash associated to the node to remove * * @return The node associated to the hash, NULL if it did not exist. */ void* avl_delete(avl_tree* root, hashcode obj_hash) { LDEBUG(9, "avl_delete(%p,%08x) ------------------------------\n", root, obj_hash); if(*root == NULL) { /* Already empty */ return NULL; } avl_node * nodes[MAX_DEPTH]; s8 balances[MAX_DEPTH]; s8 dirs[MAX_DEPTH]; #if DEBUG memset(&nodes, 0xff, sizeof(avl_node*) * MAX_DEPTH); memset(&balances, 0xff, MAX_DEPTH); memset(&dirs, 0xff, MAX_DEPTH); #endif avl_node* node = *root; hashcode node_hash; int level = 0; s8 dir = MIDDLE; while((node != NULL) && (obj_hash != (node_hash = node->hash))) { nodes[level] = node; balances[level] = BALANCE(node); /* DIR_LEFT = 0, DIR_RIGHT = 1 */ dir = (obj_hash > node_hash)&1; node = CHILD(node, dir); dirs[level++] = dir; } LDEBUG(9, "Level = %i\n", level); yassert(level < MAX_DEPTH); if(node == NULL) { /* no match : nothing to delete */ LDEBUG(9, "No match\n"); return NULL; } LDEBUG(9, "[%i] VICTIM IS ", level); DUMP_NODE(node); LDEBUG(9, "\n"); nodes[level] = node; balances[level] = BALANCE(node); dirs[level++] = dir; /* THIS IS WRONG */ /* Remove "node" from the parent */ /* Keep the pointer for the find & destroy operation */ void* data = node->data; avl_node* victim = node; avl_node* victim_left = LEFT_CHILD(node); avl_node* victim_right = RIGHT_CHILD(node); /** We have found the victim node. From here 3 cases can be found * * #1 : the victim has no child. We just have to remove it. * * #2 : the victim has only got one child. We just have to remove it and * put its children in its place. * * #3 : the victim has got two children. * * Method '1': Theoretical way: * * We move the successor of the victim instead of B, then delete using * #1 or #2. * * Actually this requires a lot of work. (5 to 10 times more than ...) * * Method '2': Fastest way: * * We have to find his "successor" (left or right). * We overwrite the data of the successor into the victim. * We link the parent of the successor * We then rebalance from the node right before where successor was. * * #3 is dependent on #1 and #2 so let's handle #3 first. */ if(victim_left != NULL && victim_right != NULL) { /** Case #3: * * NOTE: It is recommended to switch left/right successors * between each delete for a better balancing. * * NOTE: The path has to be completed. * */ LDEBUG(9, "#3\n"); /* Arbitraty: "<" successor */ /****************************/ dirs[level - 1] = DIR_LEFT; LDEBUG(9, "[%i] FROM ", level - 1); DUMP_NODE(victim); LDEBUG(9, ", GOING LEFT (VICTIM)\n"); avl_node* beforesuccessor = victim; /* actually it's "victim" here */ avl_node* successor = victim_left; avl_node* tmp_node; LDEBUG(9, "[%i] From ", level); DUMP_NODE(successor); LDEBUG(9, ", going RIGHT\n"); nodes[level] = successor; balances[level] = BALANCE(successor); dirs[level++] = DIR_RIGHT; while((tmp_node = RIGHT_CHILD(successor)) != NULL) { beforesuccessor = successor; LDEBUG(9, "[%i] From ", level); DUMP_NODE(successor); LDEBUG(9, ", going RIGHT\n"); successor = tmp_node; nodes[level] = successor; balances[level] = BALANCE(successor); dirs[level++] = DIR_RIGHT; } yassert(level < MAX_DEPTH); /* successor has at most one left child */ LDEBUG(9, "[%i] Replacement is ", level); DUMP_NODE(successor); LDEBUG(9, "\n"); /* Method 2 uses 3 moves, method 1 uses 10 */ victim->data = successor->data; victim->hash = successor->hash; if(beforesuccessor != victim) { RIGHT_CHILD(beforesuccessor) = LEFT_CHILD(successor); BALANCE(beforesuccessor)--; } else { LEFT_CHILD(beforesuccessor) = LEFT_CHILD(successor); BALANCE(beforesuccessor)++; } DUMP_NODE(successor); LDEBUG(9, " : avl_destroy_node(%p)\n", successor); avl_destroy_node(successor); /* avl_destroy_node(successor); */ level -= 2; } /* Case #3 done */ else { /* Only 2 cases could occur right now : #1 and #2 */ DUMP_NODE(victim); LDEBUG(9, " : avl_destroy_node(%p)\n", victim); avl_destroy_node(victim); /* avl_destroy_node(victim); */ if(level > 1) { avl_node* victim_parent = nodes[level - 2]; /* ONE or BOTH are NULL, this is the best alternative to the if/elseif/else above */ CHILD(victim_parent, dir) = (avl_node*)((intptr)victim_left | (intptr)victim_right); BALANCE(victim_parent) -= DIR_TO_BALANCE(dir); /* The balance has changed */ /* At this point the victim is detached from the tree */ /* I can delete it */ level -= 2; } else /* Else we have no parent, so we change the root */ { /* ONE or BOTH are NULL, this is the best alternative to the if/elseif/else above */ *root = (avl_node*)((intptr)victim_left | (intptr)victim_right); return data; } } /* Rebalance from the victim_parent */ /* NOTE: A delete-rebalance can occur many times, up to the root. */ node = nodes[level]; /* start at the parent of the deleted node */ /* Now I have to update the balance up to the root (if needed ...) * node is m_nodes[level] * we need the parent at m_nodes[level-1] * parent -> node -> (new node/processed node) */ while(level >= 0) /* level points to the parent */ { LDEBUG(9, "Updating balance at %i : ", level); DUMP_NODE(node); LDEBUG(9, "\n"); if(BALANCE(node) == balances[level]) /* balance of the node */ { /* this branch will exit */ /* The node's balance has not been changed */ LDEBUG(9, "Balance is the same\n"); return data; } /* The node's balance has been changed */ /* * Balance became 0 : It was -1 or +1 : the tree's height decreased. * It is balanced but a propagation is required. * * Balance became -1 or +1 : It was 0 : the tree's height didn't change. * It is a valid AVL and the propagation can stop. * * Balance became -2 or +2 : it was -1 or +1 : the tree is unbalanced. * It needs to be rebalanced and then a propagation is required. */ if(BALANCE(node) == MIDDLE) { /* Height decreased, tell it to the parent */ level--; if(level >= 0) { LDEBUG(9, "\tBalance [%i] changed for MIDDLE (%i) Fixing [%i] parent balance of %i (%i)\n", level + 1, balances[level + 1], level, DIR_TO_BALANCE(dirs[level]), dirs[level]); node = nodes[level]; BALANCE(node) -= DIR_TO_BALANCE(dirs[level]); } continue; } if(BALANCE(node) == LEFT || BALANCE(node) == RIGHT) /* this branch will exit */ { LDEBUG(9, "\tBalance changed for LEFT or RIGHT (%i)\n", balances[level]); return data; } LDEBUG(9, "\tBalance changed for imbalance (%i)\n", balances[level]); /* * We need to rotate in order to be AVL again. * * + cases: * * R(+) P(-) => R(0) P(0) (double rotation) * R(+) P(0) => R(+) P(-) (single rotation, delete special case) * R(+) P(+) => R(0) P(0) (single roration * * => if node&save balance are equal => MIDDLE for both * */ BALANCE(node) >>= 1; avl_node* child = CHILD(node, BALANCE_TO_DIR(BALANCE(node))); s8 parent_balance = BALANCE(node); s8 child_balance = BALANCE(child); if(child_balance == MIDDLE) /* patched single rotation */ { LDEBUG(9, "Single Rotation (delete)\n"); avl_node* root; root = avl_node_single_rotation2(node); yassert(root == child); BALANCE(child) = -parent_balance; BALANCE(node) = parent_balance; node = root; } else if(parent_balance == child_balance) /* single rotation case */ { LDEBUG(9, "Single Rotation\n"); node = avl_node_single_rotation2(node); yassert(node == child); } else { LDEBUG(9, "Double Rotation\n"); node = avl_node_double_rotation2(node); } if(level == 0) /* 2 or more ... */ { /* root */ LDEBUG(9, "Root changing from %08x to %08x\n", (*root)->hash, node->hash); *root = node; break; } /* link the parent to its new child */ /* level--; CHILD(nodes[level],dirs[level])=node; node=nodes[level]; */ /* The rotations could have changed something */ /* I'll process the same level again */ CHILD(nodes[level - 1], dirs[level - 1]) = node; /* node=nodes[level]; */ } LDEBUG(9, "avl_delete done (%p) level=%i\n", data, level); return data; } static void avl_destroy_(avl_node* node) { avl_node* child = LEFT_CHILD(node); if(child != NULL) { avl_destroy_(child); } child = RIGHT_CHILD(node); if(child != NULL) { avl_destroy_(child); } avl_destroy_node(node); /* avl_destroy_node(node); */ } /** @brief Releases all the nodes of a tree * * Releases all the nodes of a tree. Data is not destroyed. * * @param[in] tree the tree to empty */ void avl_destroy(avl_tree* tree) { if(*tree != NULL) { avl_destroy_(*tree); *tree = NULL; } } /* Iterators -> */ void avl_iterator_init(avl_tree tree, avl_iterator* iter) { /* Do we have a tree to iterate ? */ iter->stack_pointer = -1; if(tree != NULL) { /* Let's stack the whole left path */ register avl_node* node = tree; while(node != NULL) { iter->stack[++iter->stack_pointer] = node; node = LEFT_CHILD(node); } } } avl_node* avl_iterator_init_from_after(avl_tree tree, avl_iterator *iter, hashcode obj_hash) { /* Do we have a tree to iterate ? */ iter->stack_pointer = -1; if(tree != NULL) { /* Let's stack the path left path */ register avl_node* node = tree; while(node != NULL) { register hashcode h = node->hash; if(obj_hash < h) { iter->stack[++iter->stack_pointer] = node; node = LEFT_CHILD(node); } else if(obj_hash > h) { node = RIGHT_CHILD(node); } else { if(RIGHT_CHILD(node) != NULL) { // one right, full left register avl_node* next_node = RIGHT_CHILD(node); do { iter->stack[++iter->stack_pointer] = next_node; next_node = LEFT_CHILD(next_node); } while(next_node != NULL); return node; } return node; } } } return NULL; } #if !ZDB_INLINES_AVL_FIND bool avl_iterator_hasnext(avl_iterator* iter) { return iter->stack_pointer >= 0; } #endif void** avl_iterator_next(avl_iterator* iter) { yassert(iter->stack_pointer >= 0); register avl_node* node = iter->stack[iter->stack_pointer]; void** datapp = &node->data; /* we got the data, now let's ready the next node */ register avl_node* tmp; /* let's branch right if possible */ if((tmp = RIGHT_CHILD(node)) != NULL) { iter->stack[iter->stack_pointer] = tmp; /* replace TOP */ node = tmp; while((tmp = LEFT_CHILD(node)) != NULL) { iter->stack[++iter->stack_pointer] = tmp; /* PUSH @note edf 20180102 -- overflow is unlikely: the depth of the stack allows iteration on collections of tens of billions of items*/ node = tmp; } return datapp; } #if DEBUG iter->stack[iter->stack_pointer] = (avl_node*)(intptr)0xfefefefefefefefeLL; #endif iter->stack_pointer--; return datapp; } avl_node* avl_iterator_next_node(avl_iterator* iter) { yassert(iter->stack_pointer >= 0); avl_node* node = iter->stack[iter->stack_pointer]; avl_node* current = node; /* we got the data, now let's ready the next node */ register avl_node* tmp; /* let's branch right if possible */ if((tmp = RIGHT_CHILD(node)) != NULL) { iter->stack[iter->stack_pointer] = tmp; /* replace TOP */ node = tmp; while((tmp = LEFT_CHILD(node)) != NULL) { iter->stack[++iter->stack_pointer] = tmp; /* PUSH @note edf 20180102 -- overflow is unlikely: the depth of the stack allows iteration on collections of tens of billions of items */ node = tmp; } return current; } #if DEBUG iter->stack[iter->stack_pointer] = (avl_node*)(intptr)0xfefefefefefefefeLL; #endif iter->stack_pointer--; return current; } /* <- Iterators */ static void avl_callback_and_destroy_(avl_node* node, void (*callback)(void*)) { avl_node* child = LEFT_CHILD(node); if(child != NULL) { avl_callback_and_destroy_(child, callback); } child = RIGHT_CHILD(node); if(child != NULL) { avl_callback_and_destroy_(child, callback); } callback(node->data); avl_destroy_node(node); /* avl_destroy_node(node); */ } /** @brief Releases all the nodes of a tree * * Releases all the nodes of a tree. * Calls a function passed in parameter before destroying the data. * It's the responsibility of the callback to process (destroy) the data * in the tree. * * @param[in] tree the tree to empty */ void avl_callback_and_destroy(avl_tree tree, void (*callback)(void*)) { if(tree != NULL) { avl_callback_and_destroy_(tree, callback); } } #if DEBUG /** @brief DEBUG: check that a tree fits the AVL definition. * * DEBUG: check that a tree fits the AVL definition. * * @param[in] tree the tree to check * * @return A positive integer if the AVL is right (the depth actually) else * a negative integer. * */ ya_result avl_check(avl_tree tree) { int err = avl_checkdepth(tree); if(err < 0) { DIE(ERROR); } return err; } /** @brief DEBUG: check that a node fits the AVL definition. * * DEBUG: check that a node fits the AVL definition. * * @param[in] node the node to check * * @return A positive integer if the AVL is right (the depth actually) else * a negative integer. * */ s32 avl_checkdepth(avl_node* node) { if(node == NULL) { return 0; } int left_d = avl_checkdepth(LEFT_CHILD(node)); if(left_d < 0) { format("Child L of %08x\n", node->hash); return -1; } int right_d = avl_checkdepth(RIGHT_CHILD(node)); if(right_d < 0) { format("Child R of %08x\n", node->hash); return -1; } int max; int min; if(left_d > right_d) { max = left_d; min = right_d; } else { max = right_d; min = left_d; } if(max - min > 1) { format("AVL %08x is not balanced !!! %i %i\n", node->hash, left_d, right_d); return -1; } switch(BALANCE(node)) { case MIDDLE: if(left_d != right_d) { format("AVL %08x balance is broken (MIDDLE) %i %i\n", node->hash, left_d, right_d); return -1; } break; case LEFT: if(left_d <= right_d) { format("AVL %08x balance is broken (LEFT) %i %i\n", node->hash, left_d, right_d); return -1; } break; case RIGHT: if(left_d >= right_d) { format("AVL %08x balance is broken (RIGHT) %i %i\n", node->hash, left_d, right_d); return -1; } break; default: format("AVL balance is broken (%i) %i %i\n", BALANCE(node), left_d, right_d); return -1; } return max + 1; } static void avl_print_(avl_node* node) { if(LEFT_CHILD(node) != NULL) { avl_print_(LEFT_CHILD(node)); } format("[%08x]", node->hash); if(RIGHT_CHILD(node) != NULL) { avl_print_(RIGHT_CHILD(node)); } } /** @brief DEBUG: Prints the (sorted) content of the AVL * * DEBUG: Prints the (sorted) content of the AVL * * @param[in] tree the tree to print * */ void avl_print(avl_tree tree) { if(tree != NULL) { avl_print_(tree); } else { format("(empty)"); } } /** @brief DEBUG: Prints the content of the AVL node * * DEBUG: Prints the (sorted) content of the AVL node * * @param[in] node the node to print * */ #define HASH(x) (((x)!=NULL)?(x)->hash:0) /*#define MAX(x,y) (((x)>(y))?(x):(y))*/ int avl_getnodedepth(avl_node* node) { if(node == NULL) { return 0; } return MAX(avl_getnodedepth(LEFT_CHILD(node)), avl_getnodedepth(RIGHT_CHILD(node))) + 1; } void avl_printnode(avl_node* node) { if(node != NULL) { format("%08x@{%08x,%08x,%3i}", node->hash, HASH(LEFT_CHILD(node)), HASH(RIGHT_CHILD(node)), BALANCE(node)); } else { format("(empty)"); } } #endif /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dictionary.c0000644000000000000000000000013214505005531021275 xustar000000000000000030 mtime=1695812441.690971418 30 atime=1695812445.799030253 30 ctime=1695812495.051735651 yadifa-2.6.5-11201/lib/dnsdb/src/dictionary.c0000664000374500037450000001102714505005531021240 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Hash-based collection designed to change it's structure to improve speed. * * Hash-based collection designed to change it's structure to improve speed. * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include "dnsdb/zdb_config.h" #include "dnsdb/dictionary.h" #define ZDB_HASHTABLE_THRESHOLD_DISABLE (~0) void dictionary_btree_init(dictionary* dico); void dictionary_htbt_init(dictionary* dico); struct dictionary_mutation_table_entry { u32 threshold; /* Up to that number of items in the collection */ dictionary_init_method* init; }; static struct dictionary_mutation_table_entry dictionary_mutation_table[2] = { { ZDB_HASHTABLE_THRESHOLD, dictionary_btree_init}, { MAX_U32, dictionary_htbt_init}, }; static struct dictionary_mutation_table_entry* dictionary_get_mutation_entry(dictionary* dico) { struct dictionary_mutation_table_entry* entry = dictionary_mutation_table; for(; dico->count > entry->threshold; entry++); return entry; } /* * I could avoid this hook, the signature is almost the same * */ static void dictionary_bucket_record_callback(void* bucket_data, hashcode key, dictionary_node* node) { dictionary_fills((dictionary*)bucket_data, key, node); } static void dictionary_destroy_record_callback(dictionary_node* node) { (void)node; /* This should NEVER be called */ assert(FALSE); /* NOT zassert ! */ } void dictionary_init(dictionary* dico) { dictionary_mutation_table[0].init(dico); dico->threshold = dictionary_mutation_table[0].threshold; } void dictionary_mutate(dictionary* dico) { struct dictionary_mutation_table_entry* entry = dictionary_get_mutation_entry(dico); /* Check the mutation condition */ if(dico->threshold == entry->threshold) { return; } /* Mutate */ dictionary new_dico; entry->init(&new_dico); /* Update the default (MAX_UNSIGNED_INT) threshold */ new_dico.threshold = entry->threshold; dictionary_empties(dico, &new_dico, dictionary_bucket_record_callback); dictionary_destroy(dico, dictionary_destroy_record_callback); MEMCOPY(dico, &new_dico, sizeof(dictionary)); } static bool dictionary_empty_iterator_hasnext(dictionary_iterator* dico) { (void)dico; return FALSE; } static void** dictionary_empty_iterator_next(dictionary_iterator* dico) { (void)dico; return NULL; } static const struct dictionary_iterator_vtbl no_element_iterator = { dictionary_empty_iterator_hasnext, dictionary_empty_iterator_next }; void dictionary_empty_iterator_init(dictionary_iterator *iter) { iter->vtbl = &no_element_iterator; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dictionary_btree.c0000644000000000000000000000013114505005531022455 xustar000000000000000030 mtime=1695812441.722971876 30 atime=1695812445.801030282 29 ctime=1695812495.05373568 yadifa-2.6.5-11201/lib/dnsdb/src/dictionary_btree.c0000664000374500037450000003173514505005531022431 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Dictionary module based on a btree * * Dictionary module based on a btree * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include "dnsdb/zdb_error.h" #include "dnsdb/dictionary.h" #include "dnsdb/dictionary-node.h" /* * */ void dictionary_btree_init(dictionary* dico); void dictionary_btree_destroy(dictionary* dico, dictionary_destroy_record_function destroy); void dictionary_btree_destroy_ex(dictionary* dico, dictionary_destroy_ex_record_function destroyex, void* arg); dictionary_node* dictionary_btree_add(dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare, dictionary_data_record_create_function create); dictionary_node* dictionary_btree_find(const dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare); dictionary_node** dictionary_btree_findp(const dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare); dictionary_node* dictionary_btree_remove(dictionary* dico, hashcode key, void* record_match_data, dictionary_data_record_compare_function compare); ya_result dictionary_btree_process(dictionary* dico, hashcode key, void* record_match_data, dictionary_process_record_function compare); void dictionary_btree_iterator_init(const dictionary* dico, dictionary_iterator* iter); bool dictionary_btree_iterator_hasnext(dictionary_iterator* dico); void** dictionary_btree_iterator_next(dictionary_iterator* dico); void dictionary_btree_iterator_init_from(const dictionary* dico, dictionary_iterator* iter, const u8 *name); void dictionary_btree_empties(dictionary* dico, void* bucket, dictionary_bucket_record_function destroy); void dictionary_btree_fills(dictionary* dico, hashcode key, dictionary_node* node); static const struct dictionary_vtbl dictionary_btree_vtbl = { dictionary_btree_destroy, dictionary_btree_add, dictionary_btree_find, dictionary_btree_findp, dictionary_btree_remove, dictionary_btree_process, dictionary_btree_destroy_ex, dictionary_btree_iterator_init, dictionary_btree_iterator_init_from, dictionary_btree_empties, dictionary_btree_fills, "BTREE" }; static const struct dictionary_iterator_vtbl dictionary_iterator_btree_vtbl = { dictionary_btree_iterator_hasnext, dictionary_btree_iterator_next }; void dictionary_btree_init(dictionary* dico) { btree_init(&dico->ct.btree_collection); dico->vtbl = &dictionary_btree_vtbl; dico->count = 0; dico->threshold = MAX_U32; } void dictionary_btree_destroy(dictionary* dico, dictionary_destroy_record_function destroy) { yassert(dico != NULL); if(dico->ct.btree_collection != NULL) { btree_iterator iter; btree_iterator_init(dico->ct.btree_collection, &iter); while(btree_iterator_hasnext(&iter)) { dictionary_node** node_sll_p = (dictionary_node**)btree_iterator_next(&iter); dictionary_node* node = *node_sll_p; *node_sll_p = NULL; while(node != NULL) { dictionary_node* tmp = node; node = node->next; tmp->next = NULL; destroy(tmp); /* free, if any, is made here */ } } btree_destroy(&dico->ct.btree_collection); dico->count = 0; } } void dictionary_btree_destroy_ex(dictionary* dico, dictionary_destroy_ex_record_function destroyex, void* arg) { yassert(dico != NULL); if(dico->ct.btree_collection != NULL) { btree_iterator iter; btree_iterator_init(dico->ct.btree_collection, &iter); while(btree_iterator_hasnext(&iter)) { dictionary_node** node_sll_p = (dictionary_node**)btree_iterator_next(&iter); dictionary_node* node = *node_sll_p; *node_sll_p = NULL; while(node != NULL) { dictionary_node* tmp = node; node = node->next; tmp->next = NULL; destroyex(tmp, arg); /* free, if any, is made here */ } } btree_destroy(&dico->ct.btree_collection); dico->count = 0; } } dictionary_node* dictionary_btree_add(dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare, dictionary_data_record_create_function create) { dictionary_node** node_sll_p = (dictionary_node**)btree_insert(&dico->ct.btree_collection, key); dictionary_node* node = *node_sll_p; while(node != NULL) { if(compare(record_match_data, node)) { return node; } node = node->next; } node = create(record_match_data); node->next = (*node_sll_p); (*node_sll_p) = node; dico->count++; if(dictionary_should_mutate(dico)) { dictionary_mutate(dico); } return node; } dictionary_node* dictionary_btree_find(const dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare) { dictionary_node* node = (dictionary_node*)btree_find(&dico->ct.btree_collection, key); while(node != NULL) { if(compare(record_match_data, node)) { return node; } node = node->next; } return NULL; } dictionary_node** dictionary_btree_findp(const dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare) { dictionary_node** node_sll_p = (dictionary_node**)btree_findp(&dico->ct.btree_collection, key); if(node_sll_p != NULL) { while(*node_sll_p != NULL) { if(compare(record_match_data, *node_sll_p)) { return node_sll_p; } node_sll_p = &(*node_sll_p)->next; } } return NULL; } dictionary_node* dictionary_btree_remove(dictionary* dico, hashcode key, void* record_match_data, dictionary_data_record_compare_function compare) { dictionary_node** node_sll_p = (dictionary_node**)btree_findp(&dico->ct.btree_collection, key); dictionary_node* node = *node_sll_p; while(node != NULL) { if(compare(record_match_data, node)) { /* remove sll node * * I could have to remove the tree node too */ dico->count--; /* detach */ if(node->next == NULL) { /* remove tree node for the (now empty) sll */ btree_delete(&dico->ct.btree_collection, key); } else { *node_sll_p = node->next; node->next = NULL; } return node; } node_sll_p = &(node->next); node = node->next; } return NULL; } ya_result dictionary_btree_process(dictionary* dico, hashcode key, void* record_match_data, dictionary_process_record_function process) { dictionary_node** node_sll_p = (dictionary_node**)btree_findp(&dico->ct.btree_collection, key); if(node_sll_p == NULL) { return ZDB_ERROR_KEY_NOTFOUND; /* NOT FOUND */ } const dictionary_node** node_sll_head_p = (const dictionary_node**)node_sll_p; dictionary_node* node = *node_sll_p; while(node != NULL) { dictionary_node* node_next = node->next; int op = process(record_match_data, node); switch(op) { case COLLECTION_PROCESS_NEXT: { node_sll_p = &(node->next); node = node_next; continue; } case COLLECTION_PROCESS_DELETENODE: { /* remove sll node * * I could have to remove the tree node too */ dico->count--; *node_sll_p = node_next; /* detach */ if(*node_sll_head_p == NULL) { /* remove tree node for the (now empty) sll */ btree_delete(&dico->ct.btree_collection, key); } /* fall trough ... return op */ } FALLTHROUGH //fallthrough default: { return op; } } } return COLLECTION_PROCESS_NEXT; } void dictionary_btree_iterator_init(const dictionary *dico, dictionary_iterator *iter) { iter->vtbl = &dictionary_iterator_btree_vtbl; iter->sll = NULL; btree_iterator_init(dico->ct.btree_collection, &iter->ct.as_btree); } void dictionary_btree_iterator_init_from(const dictionary *dico, dictionary_iterator *iter, const u8 *name) { iter->vtbl = &dictionary_iterator_btree_vtbl; iter->sll = NULL; hashcode key = hash_dnslabel(name); btree_node *node = btree_iterator_init_from(dico->ct.btree_collection, &iter->ct.as_btree, key); zdb_rr_label *label = (zdb_rr_label*)node->data; while(label != NULL) { if(dnslabel_equals(label->name, name)) { iter->sll = (dictionary_node*)label; break; } label = label->next; } } bool dictionary_btree_iterator_hasnext(dictionary_iterator *iter) { /* If the Single Linked List is empty, fallback on the balanced tree, * else there is something next ... */ return (iter->sll != NULL && iter->sll->next != NULL) ? TRUE : btree_iterator_hasnext(&iter->ct.as_btree) ; } void** dictionary_btree_iterator_next(dictionary_iterator *iter) { void* vpp; if(iter->sll != NULL && iter->sll->next != NULL) { /* pointer is into a sll node */ vpp = &iter->sll->next; iter->sll = iter->sll->next; return vpp; } /* pointer is into a tree node */ vpp = btree_iterator_next(&iter->ct.as_btree); iter->sll = ((dictionary_node*)vpp)->next; return vpp; } void dictionary_btree_empties(dictionary* dico, void* bucket_data, dictionary_bucket_record_function bucket) { yassert(dico != NULL); if(dico->ct.btree_collection != NULL) { btree_iterator iter; btree_iterator_init(dico->ct.btree_collection, &iter); while(btree_iterator_hasnext(&iter)) { btree_node* bnode = (btree_node*)btree_iterator_next_node(&iter); hashcode key = bnode->hash; dictionary_node* node = (dictionary_node*)bnode->data; while(node != NULL) { dictionary_node* tmp = node; node = node->next; tmp->next = NULL; bucket(bucket_data, key, tmp); /* free, if any, is made here */ } } btree_destroy(&dico->ct.btree_collection); dico->count = 0; } } void dictionary_btree_fills(dictionary* dico, hashcode key, dictionary_node* node) { dictionary_node** node_sll_p = (dictionary_node**)btree_insert(&dico->ct.btree_collection, key); node->next = (*node_sll_p); *node_sll_p = node; dico->count++; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dictionary_htbt.c0000644000000000000000000000013214505005531022316 xustar000000000000000030 mtime=1695812441.737972091 30 atime=1695812445.802030296 30 ctime=1695812495.055735709 yadifa-2.6.5-11201/lib/dnsdb/src/dictionary_htbt.c0000664000374500037450000003166114505005531022267 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Dictionary module based on an hash table of binary trees * * Dictionary module based on an hash table of binary trees * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include "dnsdb/zdb_error.h" #include "dnsdb/dictionary.h" #include "dnsdb/dictionary-node.h" /* * */ void dictionary_htbt_init(dictionary* dico); void dictionary_htbt_destroy(dictionary* dico, dictionary_destroy_record_function destroy); void dictionary_htbt_destroy_ex(dictionary* dico, dictionary_destroy_ex_record_function destroy, void* arg); dictionary_node* dictionary_htbt_add(dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare, dictionary_data_record_create_function create); dictionary_node* dictionary_htbt_find(const dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare); dictionary_node** dictionary_htbt_findp(const dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare); dictionary_node* dictionary_htbt_remove(dictionary* dico, hashcode key, void* record_match_data, dictionary_data_record_compare_function compare); ya_result dictionary_htbt_process(dictionary* dico, hashcode key, void* record_match_data, dictionary_process_record_function compare); void dictionary_htbt_iterator_init(const dictionary* dico, dictionary_iterator* iter); bool dictionary_htbt_iterator_hasnext(dictionary_iterator* dico); void** dictionary_htbt_iterator_next(dictionary_iterator* dico); void dictionary_htbt_iterator_init_from(const dictionary* dico, dictionary_iterator* iter, const u8 *name); void dictionary_htbt_empties(dictionary* dico, void* bucket, dictionary_bucket_record_function destroy); void dictionary_htbt_fills(dictionary* dico, hashcode key, dictionary_node* node); static const struct dictionary_vtbl dictionary_htbt_vtbl = { /*dictionary_htbt_init,*/ dictionary_htbt_destroy, dictionary_htbt_add, dictionary_htbt_find, dictionary_htbt_findp, dictionary_htbt_remove, dictionary_htbt_process, dictionary_htbt_destroy_ex, dictionary_htbt_iterator_init, dictionary_htbt_iterator_init_from, dictionary_htbt_empties, dictionary_htbt_fills, "HTBT" }; static const struct dictionary_iterator_vtbl dictionary_iterator_htbt_vtbl = { dictionary_htbt_iterator_hasnext, dictionary_htbt_iterator_next }; void dictionary_htbt_init(dictionary* dico) { htbt_init(&(dico->ct.htbt_collection)); dico->vtbl = &dictionary_htbt_vtbl; dico->count = 0; dico->threshold = ~0; } void dictionary_htbt_destroy(dictionary* dico, dictionary_destroy_record_function destroy) { yassert(dico != NULL); if(dico->ct.htbt_collection != NULL) { htbt_iterator iter; htbt_iterator_init(dico->ct.htbt_collection, &iter); while(htbt_iterator_hasnext(&iter)) { dictionary_node** node_sll_p = (dictionary_node**)htbt_iterator_next(&iter); dictionary_node* node = *node_sll_p; *node_sll_p = NULL; while(node != NULL) { dictionary_node* tmp = node; node = node->next; tmp->next = NULL; destroy(tmp); } } htbt_destroy(&dico->ct.htbt_collection); dico->count = 0; } } void dictionary_htbt_destroy_ex(dictionary* dico, dictionary_destroy_ex_record_function destroyex, void* arg) { yassert(dico != NULL); if(dico->ct.htbt_collection != NULL) { htbt_iterator iter; htbt_iterator_init(dico->ct.htbt_collection, &iter); while(htbt_iterator_hasnext(&iter)) { dictionary_node** node_sll_p = (dictionary_node**)htbt_iterator_next(&iter); dictionary_node* node = *node_sll_p; *node_sll_p = NULL; while(node != NULL) { dictionary_node* tmp = node; node = node->next; tmp->next = NULL; destroyex(tmp, arg); } } htbt_destroy(&dico->ct.htbt_collection); dico->count = 0; } } dictionary_node* dictionary_htbt_add(dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare, dictionary_data_record_create_function create) { dictionary_node** node_sll_p = (dictionary_node**)htbt_insert(dico->ct.htbt_collection, key); dictionary_node* node = *node_sll_p; while(node != NULL) { if(compare(record_match_data, node)) { return node; } node = node->next; } node = create(record_match_data); node->next = (*node_sll_p); (*node_sll_p) = node; dico->count++; return node; } dictionary_node* dictionary_htbt_find(const dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare) { dictionary_node* node = (dictionary_node*)htbt_find(dico->ct.htbt_collection, key); while(node != NULL) { if(compare(record_match_data, node)) { return node; } node = node->next; } return NULL; } dictionary_node** dictionary_htbt_findp(const dictionary* dico, hashcode key, const void* record_match_data, dictionary_data_record_compare_function compare) { dictionary_node** node_sll_p = (dictionary_node**)htbt_findp(dico->ct.htbt_collection, key); if(node_sll_p != NULL) { while(*node_sll_p != NULL) { if(compare(record_match_data, *node_sll_p)) { return node_sll_p; } node_sll_p = &(*node_sll_p)->next; } } return NULL; } dictionary_node* dictionary_htbt_remove(dictionary* dico, hashcode key, void* record_match_data, dictionary_data_record_compare_function compare) { dictionary_node** node_sll_p = (dictionary_node**)htbt_findp(dico->ct.htbt_collection, key); dictionary_node* node = *node_sll_p; while(node != NULL) { if(compare(record_match_data, node)) { /* remove sll node * * I could have to remove the tree node too */ dico->count--; /* detach */ if(node->next == NULL) { /* remove tree node for the (now empty) sll */ htbt_delete(dico->ct.htbt_collection, key); } else { *node_sll_p = node->next; node->next = NULL; } return node; } node_sll_p = &(node->next); node = node->next; } return NULL; } ya_result dictionary_htbt_process(dictionary* dico, hashcode key, void* record_match_data, dictionary_process_record_function process) { dictionary_node** node_sll_p = (dictionary_node**)htbt_findp(dico->ct.htbt_collection, key); if(node_sll_p == NULL) { return ZDB_ERROR_KEY_NOTFOUND; /* NOT FOUND */ } const dictionary_node** node_sll_head_p = (const dictionary_node**)node_sll_p; dictionary_node* node = *node_sll_p; while(node != NULL) { /* To allow to destroy the node inside, I should ... * dictionary_node* node_next=node->next; */ dictionary_node* node_next = node->next; int op = process(record_match_data, node); switch(op) { case COLLECTION_PROCESS_NEXT: { node_sll_p = &(node->next); node = node_next; continue; } case COLLECTION_PROCESS_DELETENODE: { /* remove sll node * * I could have to remove the tree node too */ dico->count--; *node_sll_p = node_next; /* detach */ if(*node_sll_head_p == NULL) { /* remove tree node for the (now empty) sll */ htbt_delete(dico->ct.htbt_collection, key); } /* return op */ } FALLTHROUGH // fall through default: { return op; } } } return COLLECTION_PROCESS_NEXT; } void dictionary_htbt_iterator_init(const dictionary* dico, dictionary_iterator* iter) { iter->vtbl = &dictionary_iterator_htbt_vtbl; iter->sll = NULL; htbt_iterator_init(dico->ct.htbt_collection, &(iter->ct.as_htbt)); } void dictionary_htbt_iterator_init_from(const dictionary* dico, dictionary_iterator* iter, const u8 *name) { iter->vtbl = &dictionary_iterator_htbt_vtbl; iter->sll = NULL; //avl_node *node = htbt_iterator_init_from(dico->ct.htbt_collection, &(iter->ct.as_htbt), key); hashcode key = hash_dnslabel(name); avl_node *node = htbt_iterator_init_from(dico->ct.htbt_collection, &(iter->ct.as_htbt), key); zdb_rr_label *label = (zdb_rr_label*)node->data; while(label != NULL) { if(dnslabel_equals(label->name, name)) { iter->sll = (dictionary_node*)label; break; } label = label->next; } } bool dictionary_htbt_iterator_hasnext(dictionary_iterator* iter) { return (iter->sll != NULL && iter->sll->next != NULL) ? TRUE : htbt_iterator_hasnext(&iter->ct.as_htbt) ; } void** dictionary_htbt_iterator_next(dictionary_iterator* iter) { void* vpp; if(iter->sll != NULL && iter->sll->next != NULL) { /* pointer is into a sll node */ vpp = &iter->sll->next; iter->sll = iter->sll->next; return vpp; } /* pointer is into a tree node */ vpp = htbt_iterator_next(&iter->ct.as_htbt); iter->sll = ((dictionary_node*)vpp)->next; return vpp; } void dictionary_htbt_empties(dictionary* dico, void* bucket_data, dictionary_bucket_record_function bucket) { yassert(dico != NULL); if(dico->ct.htbt_collection != NULL) { htbt_iterator iter; htbt_iterator_init(dico->ct.htbt_collection, &iter); while(htbt_iterator_hasnext(&iter)) { htbt_node* hnode = htbt_iterator_next_node(&iter); hashcode key = hnode->hash; dictionary_node* node = (dictionary_node*)hnode->data; while(node != NULL) { dictionary_node* tmp = node; node = node->next; tmp->next = NULL; bucket(bucket_data, key, tmp); /* free, if any, is made here */ } } htbt_destroy(&dico->ct.htbt_collection); dico->count = 0; } } void dictionary_htbt_fills(dictionary* dico, hashcode key, dictionary_node* node) { dictionary_node** node_sll_p = (dictionary_node**)htbt_insert(dico->ct.htbt_collection, key); node->next = (*node_sll_p); *node_sll_p = node; dico->count++; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/htable.c0000644000000000000000000000013214505005531020367 xustar000000000000000030 mtime=1695812441.708971676 30 atime=1695812445.800030268 30 ctime=1695812495.057735737 yadifa-2.6.5-11201/lib/dnsdb/src/htable.c0000664000374500037450000000616114505005531020335 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Hash-Table structure and functions. * * Implementation of the Hash-Table structure and functions. * It can be configured to be thread-safe. (4 modes) * * It is used in the hash-table of balanced trees structure. (htbt) * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include "dnsdb/htable.h" /** @brief Allocates an hash table of the pre-defined size * * Allocates an hash table of the pre-defined size * * @return A pointer to the htable or NULL if an error occurred */ htable_entry* htable_alloc() { htable_entry *table; MALLOC_OR_DIE(htable_entry*, table, sizeof(htable_entry) * DEFAULT_HTABLE_SIZE, HTABLE_TAG); u32 i; for(i = 0; i < DEFAULT_HTABLE_SIZE; i++) { table[i].data = NULL; } return table; } /** @brief Frees an htable * * Frees an htable * * @param[in] table a pointer to the htable to free * */ void htable_free(htable_entry* table) { yassert(table != NULL); free(table); } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/htbt.c0000644000000000000000000000013214505005531020071 xustar000000000000000030 mtime=1695812441.727971948 30 atime=1695812445.801030282 30 ctime=1695812495.059735766 yadifa-2.6.5-11201/lib/dnsdb/src/htbt.c0000664000374500037450000002530014505005531020033 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbcollection Collections used by the database * @ingroup dnsdb * @brief Hash-Table of Balanced trees structure and functions. * * Implementation of the Hash-Table of Balanced trees structure and functions. * An hashtable holding htbt collections. * * The idea behind this structure is that, although balanced trees are FAST, * the deeper, the slower they are. * * Another important thing is that btrees are accessed by a hash and thus, can collide. * * This structure is thus used for the top-level balanced tree in order to * * _ divide the top-level domains into smaller, faster trees. * _ reduce the number of potential collisions in said trees. * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include "dnsdb/htbt.h" #include "dnsdb/htable.h" /** @brief Initializes the collection * * Initializes the collection. * Basically : *collection=NULL; * * @param[in] collection the collection to initialize * */ htbt htbt_create() { htbt ret = htable_alloc(); /* AVL does not requires this ... * But again it's not AVL-only anymore. * I now use btree that could map to any balanced tree * * That's what I should do, in theory ... * But btree_init just does "=NULL" and the htable_init has already set data to NULL * So ... #if 0 */ if(ret != NULL) { u32 i; for(i = 0; i < DEFAULT_HTABLE_SIZE; i++) { btree_init((btree*) & ret[i].data); } } return ret; } void htbt_init(htbt* collection) { *collection = htbt_create(); } #if !ZDB_INLINES_HTBT_FIND /** @brief Finds a node in the collection. * * Finds a node in the collection. * * THIS CALL IS NOT THREAD SAFE. * * @param[in] collection the collection to search in * @param[in] obj_hash the hash to find * * @return A pointer to the node or NULL if there is no such node. */ void* htbt_find(htbt collection, hashcode obj_hash) { /* compute the table hash from the object hash */ hashcode table_hash = HTBT_HASH_TRANSFORM(obj_hash); /* grab the entry for the given hash */ htable_entry* entry = &htable_get(collection, table_hash); /* search the tree of the entry */ return btree_find((btree*) & entry->data, obj_hash); } /** @brief Finds a node in the collection. * * Finds a node in the collection. * * THIS CALL IS NOT THREAD SAFE. * * @param[in] collection the collection to search in * @param[in] obj_hash the hash to find * * @return A pointer to a pointer to the node or NULL if there is no such node. */ void** htbt_findp(htbt collection, hashcode obj_hash) { /* compute the table hash from the object hash */ hashcode table_hash = HTBT_HASH_TRANSFORM(obj_hash); /* grab the entry for the given hash */ htable_entry* entry = &htable_get(collection, table_hash); /* search the tree of the entry */ return btree_findp((btree*) & entry->data, obj_hash); } /** @brief Inserts data into the collection. * * Insert datat into the collection. * The caller will then have to use the returned void** to set his data. * * THIS CALL IS NOT THREAD SAFE * * @param[in] collection the collection where the insertion should be made * @param[in] obj_hash the hash associated to the node * * @return A pointer to the data field associated to the hash, or NULL (out of memory) */ void** htbt_insert(htbt collection, hashcode obj_hash) { /* compute the table hash from the object hash */ hashcode table_hash = HTBT_HASH_TRANSFORM(obj_hash); /* grab the entry for the given hash */ htable_entry* entry = &htable_get(collection, table_hash); /* search the tree of the entry */ void** pdata = btree_insert((btree*) & entry->data, obj_hash); return pdata; } /** @brief Deletes a node from the collection. * * Deletes a node from the collection. * * THIS CALL IS NOT THREAD SAFE * * @param[in] collection the collection from which the delete will be made * @param[in] obj_hash the hash associated to the node to remove * * @return The node associated to the hash */ void* htbt_delete(htbt collection, hashcode obj_hash) { /* compute the table hash from the object hash */ hashcode table_hash = HTBT_HASH_TRANSFORM(obj_hash); /* grab the entry for the given hash */ htable_entry* entry = &htable_get(collection, table_hash); /* search the tree of the entry */ void** pdata = btree_delete((btree*) & entry->data, obj_hash); return pdata; } #endif /** @brief Destroys the collection. * * Destroys the collection. * No other thread should access it, obiviously. * * @param[in] collection the collection to destroy */ void htbt_destroy(htbt* collectionp) { yassert(collectionp != NULL); htbt collection = *collectionp; if(collection != NULL) { u32 i; for(i = 0; i < DEFAULT_HTABLE_SIZE; i++) { btree_destroy((btree*) & collection[i].data); collection[i].data = NULL; } htable_free(collection); *collectionp = NULL; } } void htbt_iterator_init(htbt collection, htbt_iterator* iter) { if(collection != NULL) { for(htbt const collection_limit = &collection[DEFAULT_HTABLE_SIZE]; collection < collection_limit; collection++) { if(collection->data != NULL) { /* We got one */ btree_iterator_init((btree)collection->data, &iter->iter); /* The next one, if any, can be found from the next hash-table slot*/ iter->table = collection + 1; iter->count = collection_limit - collection - 1; // the size of the remaining array (starts close to the size of the htbt hash) return; } } } iter->count = -1; iter->table = NULL; btree_iterator_init(NULL, &iter->iter); } avl_node * htbt_iterator_init_from(htbt collection, htbt_iterator* iter, hashcode obj_hash) { if(collection != NULL) { hashcode table_hash = HTBT_HASH_TRANSFORM(obj_hash); htbt const collection_limit = &collection[DEFAULT_HTABLE_SIZE]; collection = &htable_get(collection, table_hash); // if the tree exists if(collection->data != NULL) { /* We got one */ btree_node *node = btree_iterator_init_from((btree) collection->data, &iter->iter, obj_hash); /* The next one, if any, can be found from the next hash-table slot*/ iter->table = collection + 1; iter->count = collection_limit - collection - 1; return node; } // else find the first tree that exists for(collection++; collection < collection_limit; collection++) { if(collection->data != NULL) { /* We got one */ btree_iterator_init((btree)collection->data, &iter->iter); /* The next one, if any, can be found from the next hash-table slot*/ iter->table = collection + 1; iter->count = collection_limit - collection - 1; return NULL; } } } // else there is nothing to see here iter->count = -1; iter->table = NULL; btree_iterator_init(NULL, &iter->iter); return NULL; } #if !ZDB_INLINES_HTBT_FIND bool htbt_iterator_hasnext(htbt_iterator* iter) { return btree_iterator_hasnext(&iter->iter); } #endif void** htbt_iterator_next(htbt_iterator* iter) { void* vpp = btree_iterator_next(&iter->iter); /* Is there still something to iter in the current tree ? */ if(!btree_iterator_hasnext(&iter->iter)) { /* are there still hash-table slots available ? */ if(iter->count > 0) { for(; (iter->count > 0) && (iter->table->data == NULL); iter->count--, iter->table++); if(iter->count > 0) { btree_iterator_init((btree)iter->table->data, &iter->iter); iter->table++; iter->count--; } } } return vpp; } htbt_node* htbt_iterator_next_node(htbt_iterator* iter) { btree_node* node = btree_iterator_next_node(&iter->iter); /* Is there still something to iter in the current tree ? */ if(!btree_iterator_hasnext(&iter->iter)) { /* are there still hash-table slots available ? */ if(iter->count > 0) { for(; (iter->count > 0) && (iter->table->data == NULL); iter->count--, iter->table++); if(iter->count > 0) { btree_iterator_init((btree)iter->table->data, &iter->iter); iter->table++; iter->count--; } } } return node; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/journal.c0000644000000000000000000000013214505005531020602 xustar000000000000000030 mtime=1695812441.729971976 30 atime=1695812445.801030282 30 ctime=1695812495.061735795 yadifa-2.6.5-11201/lib/dnsdb/src/journal.c0000664000374500037450000007314714505005531020560 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ /** @brief Function ... * * ... * * @param ... * * @retval OK * @retval NOK */ #define ZDB_JOURNAL_CODE 1 #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #include #include #include "dnsdb/journal.h" //#include "dnsdb/journal_ix.h" //#include "dnsdb/journal-cjf.h" #include "dnsdb/journal-jnl.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/xfr_copy.h" #include "dnsdb/zdb-zone-path-provider.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger //#define journal_default_open journal_ix_open /* #define journal_default_open journal_cjf_open #define journal_default_finalize journal_cjf_finalize */ #define journal_default_open journal_jnl_open #define journal_default_finalize journal_jnl_finalize #ifndef JOURNAL_DEBUG #if DEBUG #define JOURNAL_DEBUG 1 #else #define JOURNAL_DEBUG 0 #endif #endif #define JOURNAL_DEBUG_TTY 0 /** * @note 20161028 edf -- this parameters tells how many dictionaries are can stay open when not used * * This is an MRU so when a journal is released, instead of being completely flushed and closed, it is only flushed. * This parameter can be small for slow updates but should ideally set as "number of dynupdate-hammered zones + K" * * Note that it keeps file descriptors open. * */ #define MRU_SIZE_DEFAULT 128 static ptr_set journal_set = PTR_SET_DNSNAME_EMPTY; static group_mutex_t journal_set_mtx = GROUP_MUTEX_INITIALIZER; static mutex_t journal_mutex = MUTEX_INITIALIZER; static list_dl_s journal_mru_list; static mutex_t journal_mru_mtx = MUTEX_INITIALIZER; static u32 journal_mru_size_max = 32; static s32 journal_count = 0; static bool journal_initialised = FALSE; static inline void journal_mru_flag_set(journal *jh, bool value) { #if JOURNAL_DEBUG log_debug("journal: %{dnsname}: MRU: journal@%p setting flag from %i to %i", journal_get_domain_const(jh), jh, jh->_mru, value); #endif jh->_mru = value; } static inline bool journal_mru_flag_get(const journal *jh) { #if JOURNAL_DEBUG log_debug("journal: %{dnsname}: MRU: journal@%p flag is %i", journal_get_domain_const(jh), jh, jh->_mru); #endif return jh->_mru != 0; } static inline void journal_forget_flag_set(journal *jh, bool value) { #if JOURNAL_DEBUG log_debug("journal: %{dnsname}: journal@%p forget flag set from %i to %i", journal_get_domain_const(jh), jh, (int)jh->_forget, (int)value); #endif jh->_forget = value; } static inline bool journal_forget_flag_get(const journal *jh) { #if JOURNAL_DEBUG log_debug("journal: %{dnsname}: journal@%p forget flag is %i", journal_get_domain_const(jh), jh, (int)jh->_forget); #endif return jh->_forget != 0; } ya_result journal_init(u32 mru_size) { log_debug("journal: initialising with an MRU of %i slots", mru_size); if(!journal_initialised) { // initialises journal open/close access mutex (avoid creation/destruction races) // will be responsible for the journal file-descriptor resources allocation (closes least recently used journal when no more FDs are available) if(mru_size < 1) { mru_size = MRU_SIZE_DEFAULT; } journal_mru_size_max = mru_size; list_dl_init(&journal_mru_list); journal_initialised = TRUE; } else { log_debug("journal: already initialised"); } return SUCCESS; } static void journal_mru_remove(journal *jh) { if(journal_mru_flag_get(jh)) { mutex_lock(&journal_mru_mtx); // safe list_dl_remove_node(&journal_mru_list, (list_dl_node_s*)&jh->mru_node); jh->mru_node.next = NULL; jh->mru_node.prev = NULL; journal_mru_flag_set(jh, FALSE); log_debug("journal: %{dnsname}: MRU: journal@%p removed", journal_get_domain_const(jh), jh); mutex_unlock(&journal_mru_mtx); // safe } #if JOURNAL_DEBUG else { yassert(jh->mru_node.prev == NULL); yassert(jh->mru_node.next == NULL); } #endif } /** * Must be called with the set locked * (checked) * * called from journal_mru_enqueue(), when the size of the mru is too big * called from journal_mru_clear(), to clear the mru of its content */ static void journal_mru_close_last_nolock() // journal_mru_mtx must be locked; { list_dl_node_s *victim_node = list_dl_remove_last_node(&journal_mru_list); if(victim_node != NULL) { victim_node->next = NULL; victim_node->prev = NULL; journal *victim = (journal*)((u8*)victim_node - offsetof(journal, mru_node)); /* cast */ u8 origin_buffer[MAX_DOMAIN_LENGTH]; u8 *origin = NULL; #if JOURNAL_DEBUG memcpy(origin_buffer, "\005BOGUS", 7); #endif victim->vtbl->get_domain(victim, origin_buffer); log_debug("journal: %{dnsname}: MRU: journal@%p is being finalized", origin_buffer, victim); yassert(victim->rc == 0); log_debug("journal: %{dnsname}: MRU: journal@%p is being removed", origin_buffer, victim); yassert(victim->mru_node.next == NULL); ptr_node *node = ptr_set_find(&journal_set, origin_buffer); if(node != NULL) { if(node->value == victim) { log_debug("journal: %{dnsname}: MRU: journal@%p is being removed from the set", origin_buffer, victim); origin = (u8*)node->key; ptr_set_delete(&journal_set, origin_buffer); --journal_count; } else { log_debug("journal: %{dnsname}: MRU: journal@%p was not in the set (another instance was)", origin_buffer, victim); } } if(origin != NULL) { dnsname_zfree(origin); } victim->vtbl->close(victim); // allowed close victim->vtbl->destroy(victim); log_debug("journal: %{dnsname}: MRU: journal@%p finalized", origin_buffer, victim); } else { log_debug("journal: MRU: empty"); } } /** * Must be called with the set locked * (checked) * * called from journal_release(journal *jh), when a journal is not referenced anymore and could thus be closed ... soon */ static void journal_mru_enqueue(journal *jh) { mutex_lock(&journal_mru_mtx); if(journal_mru_flag_get(jh)) { list_dl_remove_node(&journal_mru_list, (list_dl_node_s*)&jh->mru_node); jh->mru_node.next = NULL; jh->mru_node.prev = NULL; journal_mru_flag_set(jh, FALSE); } list_dl_insert_node(&journal_mru_list, (list_dl_node_s*)&jh->mru_node); journal_mru_flag_set(jh, TRUE); log_debug("journal: %{dnsname}: MRU: journal@%p added", journal_get_domain_const(jh), jh); while(list_dl_size(&journal_mru_list) > journal_mru_size_max) { log_debug("journal: %{dnsname}: MRU: size: %i/%i: closing oldest", journal_get_domain_const(jh), list_dl_size(&journal_mru_list), journal_mru_size_max); journal_mru_close_last_nolock(); // set locked } log_debug("journal: %{dnsname}: MRU: size: %i/%i", journal_get_domain_const(jh), list_dl_size(&journal_mru_list), journal_mru_size_max); mutex_unlock(&journal_mru_mtx); } /** * Must be called with the set locked * (checked) */ static void journal_mru_clear() { log_debug("journal: MRU: clear"); mutex_lock(&journal_mru_mtx); while(list_dl_size(&journal_mru_list) > 0) { journal_mru_close_last_nolock(); // set locked } mutex_unlock(&journal_mru_mtx); } void journal_finalize() { log_debug("journal: finalising"); bool initialised = journal_initialised; journal_initialised = FALSE; if(initialised) { // remove the natural victims first for(;;) { group_mutex_lock(&journal_set_mtx, GROUP_MUTEX_WRITE); log_debug("journal: finalising: instances: %u", journal_count); journal_mru_clear(); // set locked bool empty = ptr_set_isempty(&journal_set); if(empty) { break; } usleep(100000); // 0.1s } log_debug("journal: finalised"); journal_default_finalize(); #if JOURNAL_DEBUG logger_flush(); #endif } } static ya_result journal_acquire_from_fqdn_and_zone(journal **jhp, const u8 *origin, zdb_zone *zone, bool create) { ya_result ret; char data_path[PATH_MAX]; #if JOURNAL_DEBUG log_debug3("journal_acquire_from_fqdn_and_zone(%p, %{dnsname}, %p, %i)", jhp, origin, zone, (int)create); #endif if(origin == NULL) { log_err("journal_acquire_from_fqdn_and_zone(%p, NULL, %p, %i) failed: %r", jhp, zone, (int)create, ZDB_JOURNAL_WRONG_PARAMETERS); return ZDB_JOURNAL_WRONG_PARAMETERS; } group_mutex_lock(&journal_set_mtx, GROUP_MUTEX_WRITE); // MUST be a WRITE, not a double, not a read : a write ptr_node *node = ptr_set_find(&journal_set, origin); if(node == NULL || node->value == NULL) { // the journal is not in the set u32 path_flags = ZDB_ZONE_PATH_PROVIDER_ZONE_PATH; if(create) { path_flags |= ZDB_ZONE_PATH_PROVIDER_MKDIR; } if(FAIL(ret = zdb_zone_path_get_provider()(origin, data_path, sizeof(data_path), path_flags))) { group_mutex_unlock(&journal_set_mtx, GROUP_MUTEX_WRITE); #if JOURNAL_DEBUG log_debug3("journal_acquire_from_fqdn_and_zone(%p, %{dnsname}, %p, %i) failed: %r", jhp, origin, zone, (int)create, ret); #endif return ret; } if(FAIL(ret = journal_default_open(jhp, origin, data_path, create))) { group_mutex_unlock(&journal_set_mtx, GROUP_MUTEX_WRITE); #if JOURNAL_DEBUG log_debug3("journal_acquire_from_fqdn_and_zone(%p, %{dnsname}, %p, %i) failed: %r", jhp, origin, zone, (int)create, ret); #endif return ret; } log_debug3("journal: %{dnsname}: new journal instance %p", origin, *jhp); void *key = dnsname_zdup(origin); node = ptr_set_insert(&journal_set, key); (*jhp)->rc = 1; // nobody else has access yet, no point locking node->value = *jhp; ++journal_count; group_mutex_unlock(&journal_set_mtx, GROUP_MUTEX_WRITE); #if JOURNAL_DEBUG_TTY formatln("%{dnsname} %i -> %i (first acquire with fqdn)", journal_get_domain_const((*jhp)), (*jhp)->rc - 1, (*jhp)->rc); debug_stacktrace_print(termout, debug_stacktrace_get()); #endif } else { int rc; mutex_lock(&journal_mutex); // in set write lock *jhp = (journal*)node->value; #if JOURNAL_DEBUG_TTY formatln("%{dnsname} %i -> %i (acquire with fqdn)", journal_get_domain_const((*jhp)), (*jhp)->rc, (*jhp)->rc + 1); debug_stacktrace_print(termout, debug_stacktrace_get()); #endif rc = ++(*jhp)->rc; #if JOURNAL_DEBUG log_debug3("journal: %{dnsname}: acquired: rc=%i (set)", origin, rc); #endif yassert(((journal*)node->value)->_forget == 0); mutex_unlock(&journal_mutex); // in set write lock log_debug1("journal: %{dnsname}: got journal instance %p, rc=%i", origin, *jhp, rc); journal_mru_remove(*jhp); group_mutex_unlock(&journal_set_mtx, GROUP_MUTEX_WRITE); // the journal is not candidate for being closed anymore // at this point the journal has been found, removed from the MRU, and reference-counted // but the file may be closed (if we were in the MRU) so ... if(ISOK(ret = (*jhp)->vtbl->reopen(*jhp))) { // done } else { log_warn("journal: %{dnsname}: could not reopen the journal file: %r", origin, ret); // no journal file found, although it was in the set // it may have been deleted manually // there may be not enough file descriptors available in the system // no recovery from this state // dereference (release) and return an error journal_release(*jhp); *jhp = NULL; } } return ret; } ya_result journal_acquire_from_fqdn_ex(journal **jhp, const u8 *origin, bool create) { ya_result ret = journal_acquire_from_fqdn_and_zone(jhp, origin, NULL, create); return ret; } ya_result journal_acquire_from_fqdn(journal **jhp, const u8 *origin) { ya_result ret = journal_acquire_from_fqdn_ex(jhp, origin, FALSE); return ret; } /** * * Opens the journal for a zone * * Binds the journal to the zone (?) * * Increments the reference count to the journal * * @param jhp * @param zone * @param workingdir * @param create * @return */ ya_result journal_acquire_from_zone_ex(journal **jhp, zdb_zone *zone, bool create) { ya_result ret = SUCCESS; yassert((jhp != NULL) && (zone != NULL)); // DO NOT zdb_zone_acquire(zone); log_debug1("journal: %{dnsname}: opening journal for zone @%p", zone->origin, zone); *jhp = NULL; ret = journal_acquire_from_fqdn_and_zone(jhp, zone->origin, zone, create); return ret; } ya_result journal_acquire_from_zone(journal **jhp, zdb_zone *zone) { ya_result ret = journal_acquire_from_zone_ex(jhp, zone, FALSE); return ret; } void journal_acquire(journal *jh) { #if JOURNAL_DEBUG_TTY formatln("%{dnsname} %i -> %i (acquire)", journal_get_domain_const(jh), jh->rc, jh->rc + 1); debug_stacktrace_print(termout, debug_stacktrace_get()); #endif mutex_lock(&journal_mutex); // journal already acquired, set is safe yassert(jh->rc > 0); #if JOURNAL_DEBUG int rc = #endif ++jh->rc; #if JOURNAL_DEBUG u8 origin_buffer[MAX_DOMAIN_LENGTH]; jh->vtbl->get_domain(jh, origin_buffer); log_debug3("journal: %{dnsname}: acquired: rc=%i", origin_buffer, rc); #endif mutex_unlock(&journal_mutex); // journal already acquired, set is safe } /** * Closes the journal * * @param jh */ void journal_release(journal *jh) { if(jh != NULL) { #if JOURNAL_DEBUG_TTY formatln("%{dnsname} %i -> %i (release)", journal_get_domain_const(jh), jh->rc, jh->rc - 1); debug_stacktrace_print(termout, debug_stacktrace_get()); #endif group_mutex_lock(&journal_set_mtx, GROUP_MUTEX_WRITE); mutex_lock(&journal_mutex); // in set write lock #if JOURNAL_DEBUG int rc = --jh->rc; bool not_used = (rc == 0); u8 origin_buffer[MAX_DOMAIN_LENGTH]; jh->vtbl->get_domain(jh, origin_buffer); log_debug3("journal: %{dnsname}: released: rc=%i", origin_buffer, rc); yassert(jh->rc >= 0); #else yassert(jh->rc > 0); bool not_used = (--jh->rc) == 0; #endif mutex_unlock(&journal_mutex); // in set write lock if(not_used) { yassert(jh->rc == 0); // the journal is candidate for closing log_debug3("journal: %{dnsname}: closing journal@%p", journal_get_domain_const(jh), jh); yassert(journal_count >= 0); jh->vtbl->flush(jh); if(!journal_forget_flag_get(jh)) { log_debug3("journal: enqueuing journal@%p to MRU", jh); journal_mru_enqueue(jh); // set locked, close later } else { log_debug3("journal: closing journal@%p", jh); // if the journal is in the set, remove it ptr_node *node = ptr_set_find(&journal_set, journal_get_domain_const(jh)); if(node != NULL) { if(node->value == jh) { u8 *origin = (u8*)node->key; assert(origin != NULL); ptr_set_delete(&journal_set, journal_get_domain_const(jh)); --journal_count; dnsname_zfree(origin); } } jh->vtbl->close(jh); jh->vtbl->destroy(jh); } } group_mutex_unlock(&journal_set_mtx, GROUP_MUTEX_WRITE); } else { //log_debug("journal: close called on a NULL journal"); } } /** * * Returns the last serial stored in a file. * * Opens the journal file based on the fqdn. * Reads the serial. * Closes the journal. * * @param origin * @param workingdir * @param serialp * @return */ ya_result journal_last_serial(const u8 *origin, u32 *serialp) { journal *jh = NULL; ya_result ret; if(ISOK(ret = journal_acquire_from_fqdn(&jh, origin))) { ret = journal_get_last_serial(jh, serialp); journal_release(jh); } return ret; } ya_result journal_serial_range(const u8 *origin, u32 *serialfromp, u32 *serialtop) { journal *jh = NULL; ya_result ret; if(ISOK(ret = journal_acquire_from_fqdn(&jh, origin))) { ret = journal_get_serial_range(jh, serialfromp, serialtop); journal_release(jh); } return ret; } /** * * Reduces the size of the journal to 0. * * Opens the journal file based on the fqdn. * Truncates the journal * Closes the journal. * * Opens the journal file based on the fqdn. * Reads the serial. * Closes the journal. * * @param origin * @param workingdir * @return */ ya_result journal_truncate(const u8 *origin) { journal *jh = NULL; ya_result ret; #if JOURNAL_DEBUG log_debug3("journal: %{dnsname}: truncate", origin); #endif if(ISOK(ret = journal_acquire_from_fqdn(&jh, origin))) { ret = journal_truncate_to_size(jh, 0); journal_forget_flag_set(jh, TRUE); // if a journal file has been completely been emptied, then it should // be fully closed too group_mutex_lock(&journal_set_mtx, GROUP_MUTEX_WRITE); // if the journal is in the set, remove it ptr_node *node = ptr_set_find(&journal_set, journal_get_domain_const(jh)); if(node != NULL) { if(node->value == jh) { u8 *origin = (u8*)node->key; assert(origin != NULL); ptr_set_delete(&journal_set, journal_get_domain_const(jh)); --journal_count; dnsname_zfree(origin); } } // if the journal is in the mru, remove it journal_mru_remove(jh); group_mutex_unlock(&journal_set_mtx, GROUP_MUTEX_WRITE); journal_release(jh); #if JOURNAL_DEBUG log_debug3("journal: %{dnsname}: truncated", origin); #endif } #if JOURNAL_DEBUG else { log_debug3("journal: %{dnsname}: truncate failed with %r", origin, ret); } #endif return ret; } /** * Returns the last SOA TTL + RDATA * * @param jh the journal * @param rr an initialised resource record * * @return an error code */ ya_result journal_get_last_soa(journal *jh, dns_resource_record *rr) { ya_result ret = ERROR; input_stream is; u32 first_serial = 0; u32 last_serial = 0; journal_get_serial_range(jh, &first_serial, &last_serial); if(first_serial != last_serial) // clion inspection says this is always false, which ignores the update of the variables in the above call { for(u32 serial = last_serial - 1; serial_ge(serial, first_serial); --serial) { #if JOURNAL_DEBUG log_debug3("journal: %{dnsname}: get last soa, journal range is [%u, %u] looking at serial %u", journal_get_domain_const(jh), first_serial, last_serial, serial); #endif if(ISOK(ret = journal_get_ixfr_stream_at_serial(jh, serial, &is, rr))) { #if JOURNAL_DEBUG log_debug3("journal: %{dnsname}: get last soa, journal range is [%u, %u] looked at serial %u: %r", journal_get_domain_const(jh), first_serial, last_serial, serial, ret); #endif if(rr->tctr.qtype == TYPE_SOA) { ret = SUCCESS; } else { ret = ZDB_JOURNAL_SOA_RECORD_EXPECTED; } input_stream_close(&is); break; // from the scan-back } else { #if JOURNAL_DEBUG log_debug3("journal: %{dnsname}: get last soa, journal range is [%u, %u] looking at serial %u (error)", journal_get_domain_const(jh), first_serial, last_serial, serial); #endif } } } /* else { ret = ERROR; } */ #if JOURNAL_DEBUG log_debug3("journal: %{dnsname}: get last soa, journal range is [%u, %u] returning %r", journal_get_domain_const(jh), first_serial, last_serial, ret); #endif return ret; } /** * Flushes, closes and destroys all currently unused journals (from memory) */ void journal_close_unused() { group_mutex_lock(&journal_set_mtx, GROUP_MUTEX_WRITE); journal_mru_clear(); // set locked group_mutex_unlock(&journal_set_mtx, GROUP_MUTEX_WRITE); } /** * * Prints the status of the journal (mostly the ones in the MRU) to the logger. * */ void journal_log_status() { } ya_result journal_answer_ixfr(journal *jh, message_data* mesg, int tcpfd, s32 packet_records_limit) { const u8 *origin = message_get_canonised_fqdn(mesg); // TCP output stream output_stream tcpos; input_stream fis; packet_writer pw; ya_result return_value; u32 packet_size_limit; u32 packet_size_trigger; s32 packet_records_countdown; u32 serial; #if ZDB_HAS_TSIG_SUPPORT tsig_tcp_message_position pos = TSIG_START; #endif if(FAIL(return_value = message_get_ixfr_query_serial(mesg, &serial))) { return return_value; } dns_resource_record soa_rr; dns_resource_record_init(&soa_rr); if(FAIL(return_value = journal_get_ixfr_stream_at_serial(jh, serial, &fis, &soa_rr))) { dns_resource_record_clear(&soa_rr); return return_value; } dns_resource_record rr; dns_resource_record_init(&rr); packet_size_limit = message_get_buffer_size_max(mesg); packet_size_trigger = packet_size_limit / 2; // so, ~32KB, also : guarantees that there will be room for SOA & TSIG if(packet_records_limit) { packet_records_limit = MAX_S32; } packet_records_countdown = packet_records_limit; message_reset_buffer_size(mesg); /* attach the tcp descriptor and put a buffer filter in front of the input and the output*/ fd_output_stream_attach(&tcpos, tcpfd); buffer_input_stream_init(&fis, &fis, 4096); buffer_output_stream_init(&tcpos, &tcpos, 4096); size_t query_size = message_get_size(mesg); packet_writer_init(&pw, message_get_buffer(mesg), query_size, packet_size_limit - 780); /* * Init * * Write the final SOA (start of the IXFR stream) */ packet_writer_add_dnsrr(&pw, &soa_rr); u32 last_serial; rr_soa_get_serial(soa_rr.rdata, soa_rr.rdata_size, &last_serial); u16 an_count = 1 /*2*/; bool end_of_stream = FALSE; for(;;) { if(FAIL(return_value = dns_resource_record_read(&rr, &fis))) { log_err("journal ixfr: %{dnsname}: %{sockaddr}: read record #%d failed: %r", origin, message_get_sender_sa(mesg), an_count, return_value); break; } u32 record_length = return_value; if(rr.tctr.qtype == TYPE_SOA) { // ensure we didn't go too far u32 soa_serial; rr_soa_get_serial(rr.rdata, rr.rdata_size, &soa_serial); if(serial_gt(soa_serial, last_serial)) { record_length = 0; // will be seen as an EOF } } if(record_length == 0) { #if JOURNAL_DEBUG log_debug3("journal ixfr: %{dnsname}: %{sockaddr}: end of stream", origin, message_get_sender(mesg)); #endif #if ZDB_HAS_TSIG_SUPPORT if(pos != TSIG_START) { pos = TSIG_END; } else { pos = TSIG_WHOLE; } #endif // Last SOA // There is no need to check for remaining space as packet_size_trigger guarantees there is still room #if DEBUG { log_debug3("journal ixfr: %{dnsname}: closing: %{dnsrr}", origin, &soa_rr); } #endif packet_writer_add_dnsrr(&pw, &soa_rr); ++an_count; end_of_stream = TRUE; } else if(record_length > MAX_U16) // technically possible: a record too big to fit in an update (not likely) { // this is technically possible with an RDATA of 64K log_err("journal ixfr: %{dnsname}: %{sockaddr}: ignoring record of size %u", origin, message_get_sender_sa(mesg), record_length); log_err("journal ixfr: %{dnsname}: %{sockaddr}: record is: %{dnsrr}", origin, message_get_sender_sa(mesg), &rr); continue; } // if the record puts us above the trigger, or if there is no more record to read, send the message if(pw.packet_offset + record_length >= packet_size_trigger || (packet_records_countdown-- <= 0) || end_of_stream) { // flush message_set_answer_count(mesg, an_count); message_set_size(mesg, packet_writer_get_offset(&pw)); #if ZDB_HAS_TSIG_SUPPORT return_value = message_terminate_then_write(mesg, &tcpos, pos); #else return_value = message_terminate_then_write(mesg, &tcpos, 0); #endif if(FAIL(return_value)) { if(return_value == MAKE_ERRNO_ERROR(EPIPE)) { log_notice("journal ixfr: %{dnsname}: %{sockaddr}: send message failed: client closed connection", origin, message_get_sender_sa(mesg)); } else { log_notice("journal ixfr: %{dnsname}: %{sockaddr}: send message failed: %r", origin, message_get_sender_sa(mesg), return_value); } break; } #if ZDB_HAS_TSIG_SUPPORT pos = TSIG_MIDDLE; #endif packet_writer_init(&pw, message_get_buffer(mesg), query_size, packet_size_limit - 780); an_count = 0; if(end_of_stream) { break; } packet_records_countdown = packet_records_limit; } #if DEBUG { log_debug3("journal ixfr: %{dnsname}: sending: %{dnsrr}", origin, &rr); } #endif packet_writer_add_dnsrr(&pw, &rr); ++an_count; } dns_resource_record_clear(&rr); dns_resource_record_clear(&soa_rr); output_stream_close(&tcpos); if(input_stream_valid(&fis)) { input_stream_close(&fis); } return return_value; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/journal_ix.c0000644000000000000000000000013214505005531021302 xustar000000000000000030 mtime=1695812441.696971504 30 atime=1695812445.800030268 30 ctime=1695812495.063735823 yadifa-2.6.5-11201/lib/dnsdb/src/journal_ix.c0000664000374500037450000000401714505005531021246 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ const char *journal_ix = "journal-ix disabled"; /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/journal-cjf.c0000644000000000000000000000013214505005531021342 xustar000000000000000030 mtime=1695812441.697971518 30 atime=1695812445.800030268 30 ctime=1695812495.065735852 yadifa-2.6.5-11201/lib/dnsdb/src/journal-cjf.c0000664000374500037450000021755414505005531021322 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ /** @brief Function ... * * ... * * @param ... * * @retval OK * @retval NOK */ #include "dnsdb/dnsdb-config.h" #define ZDB_JOURNAL_CODE 1 #include "dnsdb/journal.h" #if JOURNAL_CJF_ENABLED #define JOURNAL_CJF_BASE 1 #include "dnsdb/journal-cjf-page.h" #include "dnsdb/journal-cjf-page-cache.h" #include "dnsdb/journal-cjf-page-output-stream.h" #include "dnsdb/journal-cjf-idxt.h" #include "dnsdb/journal-cjf-common.h" #include "dnsdb/journal-cjf.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dnsdb/zdb_error.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/journal.h" #include "dnsdb/zdb_types.h" #include "dnsdb/xfr_copy.h" #include "dnsdb/zdb-zone-path-provider.h" #include "dnsdb/zdb_zone.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define DEBUG_JOURNAL 1 #if !DEBUG #undef DEBUG_JOURNAL #define DEBUG_JOURNAL 0 #endif #define JOURNAL_FORMAT_NAME "cyclic" #define VERSION_HI 0 #define VERSION_LO 1 #define JOURNAL_CLASS_NAME "journal_cjf" #define LOCK_NONE 0 #define LOCK_READ 1 #define LOCK_WRITE 2 #define CJF_EXT "cjf" #define CJF_EXT_STRLEN 3 #define SOA_RDATA_SIZE_MAX 532 #define DO_SYNC 1 #define JRNLCJF_TAG 0x58494c4e524a /** * Two steps means that the journal is written in two passes. * Pass 1 gathers a full page from input and validates it. * Pass 2 stores it to the journal file. */ #define CJF_USE_TWO_STEPS 1 /* * Contains the journal (almost: not the matching start and end SOA) */ #define CJF_WIRE_FILE_FORMAT "%s/%{dnsname}." CJF_EXT #define FIRST_FROM_END (CJF_EXT_STRLEN + (1 + 8 + 1 + 8)) #define LAST_FROM_END (CJF_EXT_STRLEN + (1 + 8)) /******************************************************************************* * * JNL (HEADER) ---> IDXT * | | * +------+------+---+ * | | | * v v v * PAGE -> PAGE -> PAGE * | | | * v v v * IXFRs IXFRs IXFRs * ******************************************************************************/ /* * MAGIC 'JNL' + Version 0 * Serial begin * Serial end * Begin Index Offset * Table Index Offset */ /** * There is a need of lockable 4K pages in an MRU that points back to their user * That's where the PAGE will be stored * I'm not sure of what the ratio between allowed FDs and allowed PAGE pages should be. */ static shared_group_shared_mutex_t journal_shared_mtx; static bool journal_initialized = FALSE; static file_pool_t journal_file_pool = 0; void log_debug_jnl(journal_cjf *jnl, const char *text) { log_debug4("cjf: %s,%p: %s: header SN=[%08x; %08x] F=%08x L=%08x dirty=%i empty=%i", jnl->journal_file_name, jnl->file, text, jnl->serial_begin, jnl->serial_end, jnl->first_page_offset, jnl->page_table_file_offset, journal_cjf_is_dirty(jnl), journal_cjf_isempty(jnl)); s16 n = jnl->idxt.count; if(jnl->last_page.count == 0) { n--; } log_debug4("cjf: %s,%p: %s: idxt %3hi/%3hi [%3hi] dirty=%i marked=%i", jnl->journal_file_name, jnl->file, text, jnl->idxt.count, jnl->idxt.size, jnl->idxt.first, (jnl->idxt.dirty)?1:0, (jnl->idxt.marked)?1:0); log_debug4("cjf: %s,%p: %s: page: SN=[%08x; %08x] count=%3u size=%3u at=%08x next=%08x ... limit=%08x", jnl->journal_file_name, jnl->file, text, jnl->last_page.serial_start, jnl->last_page.serial_end, jnl->last_page.count,jnl->last_page.size, jnl->last_page.file_offset, jnl->last_page.records_limit, jnl->last_page.file_offset_limit); for(s16 idx = 0; idx < n; idx++) { journal_cjf_idxt_tbl_item *item = &jnl->idxt.entries[(jnl->idxt.first + idx) % jnl->idxt.size]; log_debug4("cjf: %s,%p: %s: idxt[%3i] = %08x %08x", jnl->journal_file_name, jnl->file, text, idx, item->last_serial, item->file_offset); } if(jnl->last_page.count == 0) { journal_cjf_idxt_tbl_item *item = &jnl->idxt.entries[(jnl->idxt.first + n) % jnl->idxt.size]; log_debug4("cjf: %s,%p: %s: idxt[%3i] = [empty] %08x", jnl->journal_file_name, jnl->file, text, n, item->file_offset); } } static void journal_cjf_writelock(journal_cjf *jnl) { #if DEBUG log_debug4("cjf: %s,%p: write lock", jnl->journal_file_name, jnl->file); #endif shared_group_mutex_lock(&jnl->mtx, GROUP_MUTEX_WRITE); } static void journal_cjf_writeunlock(journal_cjf *jnl) { #if DEBUG log_debug4("cjf: %s,%p: write unlock", jnl->journal_file_name, jnl->file); #endif shared_group_mutex_unlock(&jnl->mtx, GROUP_MUTEX_WRITE); } static void journal_cjf_readlock(journal_cjf *jnl) { #if DEBUG log_debug4("cjf: %s,%p: read lock", jnl->journal_file_name, jnl->file); #endif shared_group_mutex_lock(&jnl->mtx, GROUP_MUTEX_READ); } static void journal_cjf_readunlock(journal_cjf *jnl) { #if DEBUG log_debug4("cjf: %s,%p: read unlock", jnl->journal_file_name, jnl->file); #endif shared_group_mutex_unlock(&jnl->mtx, GROUP_MUTEX_READ); } bool journal_cjf_isreadlocked(journal_cjf *jnl) { bool ret = shared_group_mutex_islocked_by(&jnl->mtx, GROUP_MUTEX_READ); return ret; } bool journal_cjf_iswritelocked(journal_cjf *jnl) { bool ret = shared_group_mutex_islocked_by(&jnl->mtx, GROUP_MUTEX_WRITE); return ret; } void journal_cjf_release(journal_cjf *jnl) { journal_release((journal*)jnl); } static journal_cjf* journal_cjf_alloc_default(const u8 *origin, const char *filename); static void journal_cjf_load_idxt(journal_cjf *jnl) { if(jnl->idxt.entries != NULL) { return; } journal_cjf_idxt_load(jnl); if(jnl->idxt.count > 0) { jnl->last_page.file_offset = journal_cjf_idxt_get_last_file_offset(jnl); journal_cjf_page_tbl_header current_page_header; journal_cjf_page_cache_read_header(jnl->file, jnl->last_page.file_offset, ¤t_page_header); jnl->last_page.count = current_page_header.count; jnl->last_page.size = current_page_header.size; if(jnl->last_page.file_offset < jnl->first_page_offset) { jnl->last_page.file_offset_limit = jnl->first_page_offset; } else { jnl->last_page.file_offset_limit = jnl->file_maximum_size; } if(jnl->idxt.count > 1) { jnl->last_page.serial_start = journal_cjf_idxt_get_last_serial(jnl, jnl->idxt.count - 2); } else { jnl->last_page.serial_start = jnl->serial_begin; } } else { jnl->idxt.dirty = FALSE; jnl->flags |= JOURNAL_CFJ_FLAGS_DIRTY; journal_cjf_page_cache_flush(jnl->file); journal_cjf_idxt_destroy(jnl); jnl->serial_begin = 0; jnl->serial_end = 0; jnl->mtx.owner = LOCK_NONE; jnl->mtx.count = 0; jnl->first_page_offset = CJF_HEADER_SIZE; jnl->page_table_file_offset = 0; jnl->last_soa_offset = 0; jnl->file_maximum_size = MAX_U32; if(jnl->zone != NULL) { jnl->file_maximum_size = jnl->zone->wire_size >> 1; zdb_zone_info_get_zone_max_journal_size(jnl->origin, &jnl->file_maximum_size); } jnl->last_page.file_offset = CJF_HEADER_SIZE; jnl->last_page.count = 0; jnl->last_page.size = CJF_SECTION_INDEX_SLOT_COUNT; jnl->last_page.serial_start = 0; jnl->last_page.serial_end = 0; jnl->last_page.records_limit = jnl->last_page.file_offset + CJF_SECTION_INDEX_SIZE; jnl->last_page.file_offset_limit = jnl->file_maximum_size; #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || /* Since glibc 2.3.5: */ _POSIX_C_SOURCE >= 200112L file_pool_resize(jnl->file, CJF_HEADER_SIZE); #endif } } static int journal_cjf_create_file(journal_cjf **jnlp, const u8 *origin, const char *filename) { log_debug3("cjf: %{dnsname}: creating %s", origin, filename); int flags = O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC; #ifdef O_NOATIME flags |= O_NOATIME; #endif file_pool_file_t file; ya_result ret; cjf_header hdr; file = file_pool_open_ex(journal_file_pool, filename, flags, 0644); if(file != NULL) { journal_cjf *jnl = journal_cjf_alloc_default(origin, filename); hdr.magic_plus_version = CJF_CJF0_MAGIC; hdr.serial_begin = 0; hdr.serial_end = 0; hdr.first_index_offset = 0; hdr.table_index_offset = 0; hdr.last_soa_offset = 0, hdr.last_page_offset_next = 0; //hdr.last_page_item_count = 0; hdr.flags = JOURNAL_CFJ_FLAGS_MY_ENDIAN; // not dirty ssize_t n = file_pool_writefully(file, &hdr, CJF_HEADER_SIZE); if(n < 0) { ret = ERRNO_ERROR; return ret; } jnl->file = file; *jnlp = jnl; return SUCCESS; } else { ret = ERRNO_ERROR; log_err("cjf: %s: failed to create %s: %r", origin, filename, ret); *jnlp = NULL; return ret; } } /** * * Does NOT set the fd field in jnl * MUST return -1 in case of error * * @param jnl * @param create * @return the file descriptor or an error code */ static int journal_cjf_init_from_file(journal_cjf **jnlp, const u8 *origin, const char *filename, bool create) { log_debug3("cjf: %{dnsname}: opening%s %s", origin, (create)?"/creating":"", filename); int flags = O_RDWR|O_CLOEXEC; #ifdef O_NOATIME flags |= O_NOATIME; #endif file_pool_file_t file; ya_result ret; bool bad_journal = FALSE; cjf_header hdr; file = file_pool_open_ex(journal_file_pool, filename, flags, 0660); if(file == NULL) { ret = ERRNO_ERROR; log_debug3("cjf: %{dnsname}: failed to open %s: %r", origin, filename, ret); if(create) { ret = journal_cjf_create_file(jnlp, origin, filename); } return ret; } s64 size = filesize(filename); if(size < CJF_HEADER_SIZE) { bad_journal = TRUE; } // look if the journal makes sense if(FAIL(ret = file_pool_readfully(file, &hdr, sizeof(hdr)))) { ret = ERRNO_ERROR; log_err("cjf: %{dnsname}: could not read header on %s: %r", origin, filename, ret); bad_journal = TRUE; } else if((hdr.magic_plus_version != CJF_CJF0_MAGIC) || ((hdr.flags & JOURNAL_CFJ_FLAGS_MY_ENDIAN) == 0) ) { if(hdr.magic_plus_version != CJF_CJF0_MAGIC) { log_err("cjf: %{dnsname}: wrong magic on %s", origin, filename); } else { log_err("cjf: %{dnsname}: wrong endian on %s", origin, filename); } bad_journal = TRUE; } else if(hdr.first_index_offset == 0) { bad_journal = TRUE; } if(!bad_journal) { // it does makes sense // note: DO NOT jnl->file = fd; journal_cjf *jnl = journal_cjf_alloc_default(origin, filename); jnl->flags = hdr.flags; jnl->serial_begin = hdr.serial_begin; jnl->serial_end = hdr.serial_end; jnl->first_page_offset = hdr.first_index_offset; jnl->page_table_file_offset = hdr.table_index_offset; jnl->last_soa_offset = hdr.last_soa_offset; jnl->last_page.serial_end = jnl->serial_end; jnl->last_page.records_limit = hdr.last_page_offset_next; jnl->file = file; log_debug("cjf: %{dnsname}: journal expected to cover serials from %i to %i", jnl->origin, hdr.serial_begin, hdr.serial_end); log_debug("cjf: %{dnsname}: journal table index located at %x%s", jnl->origin, hdr.table_index_offset, (hdr.table_index_offset!=0)?"":", which means it has not been closed properly"); *jnlp = jnl; return SUCCESS; } else { // the journal content is unexpected file_pool_close(file); file = NULL; char broken_file_path[PATH_MAX]; if(ISOK(ret = snformat(broken_file_path, sizeof(broken_file_path),"%s.bad-journal", filename))) { bool try_again = create; // remove previous bad-journal if any if(unlink(broken_file_path) < 0) { ret = ERRNO_ERROR; if(ret == MAKE_ERRNO_ERROR(ENOENT)) { ret = SUCCESS; } else { log_err("cjf: %{dnsname}: unable to delete previous bad journal %s: %r", origin, broken_file_path, ret); try_again = FALSE; } } // successfully handled the previous .bad-journal if(ISOK(ret)) { // rename the journal into bad-journal if(rename(filename, broken_file_path) < 0) { ret = ERRNO_ERROR; log_err("cjf: %{dnsname}: unable to rename %s into %s: %r", origin, filename, broken_file_path, ret); if(unlink(filename) < 0) { ret = ERRNO_ERROR; log_err("cjf: %{dnsname}: unable to delete %s: %r", origin, filename, ret); try_again = FALSE; } } ret = ZDB_ERROR_ICMTL_NOTFOUND; } if(try_again) // we are allowed to create and got no counter-indication { int ret = journal_cjf_create_file(jnlp, origin, filename); // we are in a branch where "create = TRUE" return ret; } } else { log_err("cjf: %{dnsname}: %s is a bad journal, please remove it.", origin, filename); } } return ret; } void journal_cjf_header_flush(journal_cjf *jnl) { if(journal_cjf_is_dirty(jnl)) { yassert(jnl->file != NULL); log_debug("cjf: %s,%p: flushing header SN=[%08x; %08x] F=%08x T=%08x", jnl->journal_file_name, jnl->file, jnl->serial_begin, jnl->serial_end, jnl->first_page_offset, jnl->page_table_file_offset); off_t pos; if((pos = file_pool_seek(jnl->file, 4, SEEK_SET)) != 4) { log_err("cjf: %s,%p: failed to set file position: %lli instead of %i (%r)", jnl->journal_file_name, jnl->file, pos, 4, ERRNO_ERROR); logger_flush(); abort(); } cjf_header hdr; //hdr.magic_plus_version = 0; hdr.serial_begin = jnl->serial_begin; hdr.serial_end = jnl->serial_end; hdr.first_index_offset = jnl->first_page_offset; hdr.table_index_offset = jnl->page_table_file_offset; hdr.last_soa_offset = jnl->last_soa_offset; hdr.last_page_offset_next = jnl->last_page.records_limit; //hdr.last_page_item_count = jnl->page.count; hdr.flags = jnl->flags; file_pool_writefully(jnl->file, &hdr.serial_begin, CJF_HEADER_SIZE - 4); journal_cjf_clear_dirty(jnl); } } /** * * Removes the first PAGE from the journal. * Adjust the current PAGE limit; * * @param jnl */ void journal_cjf_remove_first_page(journal_cjf *jnl) { log_debug_jnl(jnl, "journal_cjf_remove_first_page: BEFORE"); u32 stored_serial = jnl->serial_begin + 1; // (ensure an error would trigger a flush) u8 zt = 0; if(ISOK(zdb_zone_info_get_zone_type(jnl->origin, &zt))) { if(zt == ZT_MASTER) { zdb_zone_info_get_stored_serial(jnl->origin, &stored_serial); // for master only if(serial_le(stored_serial, jnl->serial_begin)) { log_debug("cjf: %s,%p: journal page %u will be lost, flushing zone first", jnl->journal_file_name, jnl->file, jnl->journal_file_name, jnl->serial_begin); zdb_zone_info_background_store_zone(jnl->origin); } } } journal_cjf_page_tbl_header first_page_hdr; journal_cjf_page_cache_read_header(jnl->file, jnl->first_page_offset, &first_page_hdr); if(first_page_hdr.next_page_offset < jnl->first_page_offset) { // this is the last page, of the file, physically jnl->page_table_file_offset = jnl->last_page.records_limit; jnl->idxt.dirty = TRUE; } journal_cjf_page_cache_clear(jnl->file, jnl->first_page_offset); jnl->serial_begin = journal_cjf_idxt_get_last_serial(jnl, 0); jnl->first_page_offset = journal_cjf_idxt_get_file_offset(jnl, 1); ++jnl->idxt.first; --jnl->idxt.count; journal_cjf_set_dirty(jnl); if(jnl->last_page.file_offset < jnl->first_page_offset) { jnl->last_page.file_offset_limit = jnl->first_page_offset; } else // at or after { jnl->last_page.file_offset_limit = jnl->file_maximum_size; } log_debug_jnl(jnl, "journal_cjf_remove_first_page: AFTER"); log_debug("cjf: %s,%p: first PAGE now at %u (%08x), journal starts with serial %u (%08x", jnl->journal_file_name, jnl->file, jnl->first_page_offset, jnl->first_page_offset, jnl->serial_begin, jnl->serial_begin); } /******************************************************************************* * * Index table handling functions * ******************************************************************************/ /*****************************************************************************/ static void journal_cjf_writelock(journal_cjf *jnl); static void journal_cjf_writeunlock(journal_cjf *jnl); static void journal_cjf_readlock(journal_cjf *jnl); static void journal_cjf_readunlock(journal_cjf *jnl); static const char * journal_cjf_get_format_name() { return JOURNAL_FORMAT_NAME; } static u32 journal_cjf_get_format_version() { return VERSION_U32(VERSION_HI,VERSION_LO); } static ya_result journal_cjf_read_soa_record(dns_resource_record *rr, input_stream *ixfr_wire_is) { ya_result return_value; if((return_value = dns_resource_record_read(rr, ixfr_wire_is)) <= 0) { /* FAIL or EOF */ return return_value; } #if DEBUG rdata_desc rdatadesc = {rr->tctr.qtype, rr->rdata_size, rr->rdata}; log_debug("cjf: %{dnsname} %{typerdatadesc}", rr->name, &rdatadesc); #endif if((rr->tctr.qtype != TYPE_SOA) || (rr->rdata_size > SOA_RDATA_SIZE_MAX)) { log_err("cjf: expected SOA record but got %{dnstype} instead", &rr->tctr.qtype); return ZDB_JOURNAL_SOA_RECORD_EXPECTED; } return return_value; } struct journal_cjf_read_ixfr_s { input_stream *ixfr_wire_is; output_stream baos; dns_resource_record rr; u32 serial_from; u32 serial_to; u32 size; bool eof; }; typedef struct journal_cjf_read_ixfr_s journal_cjf_read_ixfr_s; ya_result journal_cjf_read_ixfr_init(journal_cjf_read_ixfr_s *ixfrinc, input_stream *ixfr_wire_is) { ya_result ret; ixfrinc->ixfr_wire_is = ixfr_wire_is; bytearray_output_stream_init_ex(&ixfrinc->baos, NULL, 65536, BYTEARRAY_DYNAMIC); dns_resource_record_init(&ixfrinc->rr); ixfrinc->serial_from = 0; ixfrinc->serial_to = 0; ixfrinc->size = 0; ixfrinc->eof = FALSE; ret = journal_cjf_read_soa_record(&ixfrinc->rr, ixfr_wire_is); #if DEBUG if(ISOK(ret)) { log_debug2("cjf: ---: started with %{dnsrr}", &ixfrinc->rr); } #endif return ret; } void journal_cjf_read_ixfr_finalize(journal_cjf_read_ixfr_s *ixfrinc) { ixfrinc->ixfr_wire_is = NULL; dns_resource_record_clear(&ixfrinc->rr); output_stream_close(&ixfrinc->baos); ixfrinc->serial_from = 0; ixfrinc->serial_to = 0; ixfrinc->size = 0; } /** * * Reads a single page of incremental changes (-SOA ... +SOA ...) * * @param ixfrinc * @return the size of the page (0 if there is nothing to be read), or an error code */ static ya_result journal_cjf_read_ixfr_read(journal_cjf_read_ixfr_s *ixfrinc) { if(ixfrinc->eof) { ixfrinc->size = 0; return 0; } input_stream *ixfr_wire_is = ixfrinc->ixfr_wire_is; output_stream *baos = &ixfrinc->baos; dns_resource_record *rr = &ixfrinc->rr; ya_result ret; bool need_another_soa = TRUE; bytearray_output_stream_reset(baos); // must start by an SOA if(rr->tctr.qtype == TYPE_SOA) { ret = rr_soa_get_serial(rr->rdata, rr->rdata_size, &ixfrinc->serial_from); } else { ret = ZDB_JOURNAL_SOA_RECORD_EXPECTED; } ixfrinc->size = 0; if(ISOK(ret)) { for(int idx = 0;; ++idx) { #if DEBUG log_debug2("cjf: ---: %4i: %{dnsrr}", idx, rr); #endif dns_resource_record_write(rr, baos); if((ret = dns_resource_record_read(rr, ixfr_wire_is)) <= 0) { if(ret == 0) { if(!need_another_soa) { ixfrinc->size = bytearray_output_stream_size(baos); #if DEBUG log_debug2("cjf: ===: IXFR incremental change size: %i", ixfrinc->size); #endif ret = ixfrinc->size; } else { #if DEBUG log_debug2("cjf: ===: still expected an SOA"); #endif // SOA expected ret = ZDB_JOURNAL_SOA_RECORD_EXPECTED; } ixfrinc->eof = TRUE; } else { #if DEBUG log_debug2("cjf: ===: failed to read the next record: %r", ret); #endif } break; } if(rr->tctr.qtype == TYPE_SOA) { if(need_another_soa) { if(FAIL(ret = rr_soa_get_serial(rr->rdata, rr->rdata_size, &ixfrinc->serial_to))) { #if DEBUG log_debug2("cjf: ===: failed parse serial from record: %r", ret); #endif break; } need_another_soa = FALSE; } else { // another page starts here // this record will written for the next page ixfrinc->size = bytearray_output_stream_size(baos); #if DEBUG log_debug2("cjf: ===: IXFR incremental change size: %i (followed ...)", ixfrinc->size); #endif ret = ixfrinc->size; break; } } } } return ret; } /** * The caller will take action that will end up removing the first page. * Either explicitly, either overwriting it (ie: looping). * * This function ensures that it's OK to do so. * * Returns: * * 0 if it's OK to do so, and no actions were taken, * 1 if it's OK to do so, but the zone needed to be stored * or an error code. * * @param jnl * * @return the state of the operation * */ static ya_result journal_cjf_append_ixfr_stream_first_page_removal(journal_cjf *jnl) { // the caller will remove first page to make room, prepare for it ya_result ret; u32 zone_stored_serial; // get the serial of the stored zone if(FAIL(ret = zdb_zone_info_get_stored_serial(jnl->origin, &zone_stored_serial))) { log_warn("cjf: %{dnsname}: could not get the serial of the stored zone: %r", jnl->origin, ret); return ret; } u8 zt = 0; if(ISOK(zdb_zone_info_get_zone_type(jnl->origin, &zt))) { if(zt == ZT_SLAVE) { u32 ts = jnl->zone->axfr_timestamp; u32 sr = jnl->zone->axfr_serial; if(ts > 1) { if(serial_gt(sr, zone_stored_serial)) { zone_stored_serial = sr; } } } } // get the page of the serial if(FAIL(ret = journal_cjf_idxt_get_page_offset_from_serial(jnl, zone_stored_serial, NULL))) { if(serial_le(jnl->serial_end, zone_stored_serial)) { log_debug("cjf: %{dnsname}: no need to store the zone again as it's already %i steps further", jnl->origin, zone_stored_serial - jnl->serial_end); return 0; } else { log_warn("cjf: %{dnsname}: could not get page of serial %u: %r", jnl->origin, zone_stored_serial, ret); return ret; } } // ret is the index of the page, if it is 0 we may need to save the current zone bool need_to_store_before_removing_first_page = (ret == 0); log_debug("cjf: %{dnsname}: zone currently stored up to serial %i, located on page %i of the journal", jnl->origin, zone_stored_serial, ret); if(need_to_store_before_removing_first_page) { // we are about to destroy the page of the currently stored serial AND // there are steps remaining to be safe log_warn("cjf: %{dnsname}: need to store the zone right now, consider increasing the journal size", jnl->origin); zdb_zone *zone = (zdb_zone*)jnl->zone; // the zone at this point is supposed to be locked // either simply with a simple reader // either doubly with something and a simple reader // if simply : do nothing // if doubly : with the simple reader : exchange them // with anything else : it cannot ever work u8 owner = zone->lock_owner; u8 reserved_owner = zone->lock_reserved_owner; if(owner == ZDB_ZONE_MUTEX_SIMPLEREADER) { zdb_zone_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); ret = zdb_zone_info_store_locked_zone(jnl->origin); zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); } else if(owner == ZDB_ZONE_MUTEX_NOBODY) { zdb_zone_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); ret = zdb_zone_info_store_locked_zone(jnl->origin); zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); } else if(reserved_owner == ZDB_ZONE_MUTEX_SIMPLEREADER) { zdb_zone_exchange_locks(zone, owner, ZDB_ZONE_MUTEX_SIMPLEREADER); ret = zdb_zone_info_store_locked_zone(jnl->origin); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, owner); } else { ret = ERROR; // obsolete } if(FAIL(ret)) { log_warn("cjf: %{dnsname}: cannot store the zone: %r", jnl->origin, ret); return ret; } return 1; // try again } else { return 0; // continue } } static s64 journal_cjf_get_space_left_until_need_storage_page(journal_cjf *jnl) { ya_result ret; u32 zone_stored_serial; if(FAIL(ret = zdb_zone_info_get_stored_serial(jnl->origin, &zone_stored_serial))) { log_warn("cjf: %{dnsname}: could not get teh serial of the stored zone: %r", jnl->origin, ret); // save asap return 0; } u8 zt = 0; if(ISOK(zdb_zone_info_get_zone_type(jnl->origin, &zt))) { if(zt == ZT_SLAVE) { u32 ts = jnl->zone->axfr_timestamp; u32 sr = jnl->zone->axfr_serial; if(ts > 1) { if(serial_gt(sr, zone_stored_serial)) { zone_stored_serial = sr; } } } } // get the page of the serial if(FAIL(ret = journal_cjf_idxt_get_page_offset_from_serial(jnl, zone_stored_serial, NULL))) { if(serial_le(jnl->serial_end, zone_stored_serial)) { log_debug("cjf: %{dnsname}: no need to store the zone again as it's already %i steps further", jnl->origin, zone_stored_serial - jnl->serial_end); // the journal is only there for the slaves, it could be completely replaced return jnl->file_maximum_size; } else { log_warn("cjf: %{dnsname}: could not get page of serial %u: %r", jnl->origin, zone_stored_serial, ret); // save asap return 0; } } const journal_cjf_idxt_tbl_item* need_storage = journal_cjf_idxt_get_entry(jnl, ret); if(jnl->last_page.file_offset == need_storage->file_offset) { // we are on the page : we basically have the size of our page minus the file size return MAX((s32)(jnl->file_maximum_size - (jnl->last_page.records_limit - jnl->last_page.file_offset)), 0); } else if(jnl->last_page.file_offset < need_storage->file_offset) { // we have everything until that page return MAX((s32)(need_storage->file_offset - jnl->last_page.records_limit), 0); } else // if(jnl->last_page.file_offset > need_storage->file_offset) { // we have the remaining space until the end of the file plus the offset of the page (minus the header) return MAX((s32)(jnl->file_maximum_size - jnl->last_page.records_limit), 0) + need_storage->file_offset; } } static ya_result journal_cjf_append_ixfr_stream_per_page(journal *jh, input_stream *ixfr_wire_is, bool is_slave) { journal_cjf *jnl = (journal_cjf*)jh; ya_result ret; log_debug("cjf: %s,%p: append IXFR (master)", jnl->journal_file_name, jnl->file); // ensure the zone locks are usable : locked by the reader, by nobody, or the reader is a reserved owner if(jnl->zone != NULL) { zdb_zone *zone = (zdb_zone*)jnl->zone; u8 owner = zone->lock_owner; u8 reserved_owner = zone->lock_reserved_owner; if( !( (owner == ZDB_ZONE_MUTEX_SIMPLEREADER) || (owner == ZDB_ZONE_MUTEX_NOBODY) || (reserved_owner == ZDB_ZONE_MUTEX_SIMPLEREADER) ) ) { log_err("cjf: %s,%p: append IXFR (master) cannot happen because the zone locks are not set properly", jnl->journal_file_name, jnl->file); return ERROR; } } int written_pages = 0; dns_resource_record rr; dns_resource_record_init(&rr); output_stream os; output_stream_set_void(&os); // very important journal_cjf_read_ixfr_s ixfrinc; journal_cjf_read_ixfr_init(&ixfrinc, ixfr_wire_is); journal_cjf_writelock(jnl); for(;;) { ret = journal_cjf_read_ixfr_read(&ixfrinc); if(ret <= 0) { journal_cjf_page_output_stream_cancel(&os); if(ret == 0) { log_info("cjf: %{dnsname}: no incremental changes remaining", jnl->origin); } else { log_err("cjf: %{dnsname}: failed to read changes: %r", jnl->origin, ret); } break; } // else records have been read yassert((ixfrinc.serial_from == ixfrinc.serial_to) || (ixfrinc.size != 0)); log_info("cjf: %{dnsname}: incremental changes read from %u to %u (%u bytes)", jnl->origin, ixfrinc.serial_from, ixfrinc.serial_to, ixfrinc.size); bool journal_is_empty = journal_cjf_isempty(jnl); if(!journal_is_empty) { // if the journal is not empty, ensure the page follows the last journal page if(serial_lt(ixfrinc.serial_from, jnl->serial_end)) { log_info("cjf: %{dnsname}: ignoring changes before serial %u", jnl->origin, jnl->serial_end); continue; // read next page } else if(serial_gt(ixfrinc.serial_from, jnl->serial_end)) { log_warn("cjf: %{dnsname}: missing changes between serials %u and %u", jnl->origin, jnl->serial_end, ixfrinc.serial_from); break; // full stop } } else { // create a journal with one entry journal_cjf_idxt_create(jnl, 1); } /***/ // reserve the known size of this single page with the serial range // write the page /***/ journal_cjf_append_ixfr_stream_master_accum_tryagain: journal_cjf_page_output_stream_reopen(&os, jnl); // the file is cycling, so we also need to see if we are writing at // a position before the first page's and thus risking to overwrite it s64 available = 0; while(journal_cjf_page_current_output_stream_may_overwrite(jnl)) { // if total available is smaller than half the file, the division will be >= 2 s64 total_available = journal_cjf_get_space_left_until_need_storage_page(jnl); // should not store in background. Handle it first-hand (maybe postpone the update) ... (obsolete) if( ((total_available > 0) && ((jnl->file_maximum_size / total_available) >= 2)) || (total_available == 0)) { // if not writing already, then write // 0 = not saving, 1 = saving, <0 = error if(zdb_zone_info_background_store_in_progress(jnl->origin) != 1) { zdb_zone_info_background_store_zone(jnl->origin); } } available = jnl->first_page_offset - jnl->last_page.records_limit; if(available >= ixfrinc.size) { log_debug("cjf: %{dnsname}: %lli >= %i storage available before overwriting the first page", jnl->origin, available, ixfrinc.size); break; } if(FAIL(ret = journal_cjf_append_ixfr_stream_first_page_removal(jnl))) { break; } if(ret == 1) { continue; } journal_cjf_remove_first_page(jnl); } // while may overwrite if(FAIL(ret)) { journal_cjf_page_output_stream_cancel(&os); break; } // available space between the first available byte to write records and // the file size limit if(!journal_cjf_page_current_output_stream_may_overwrite(jnl)) { s64 total_available = journal_cjf_get_space_left_until_need_storage_page(jnl); if( ((total_available > 0) && ((jnl->file_maximum_size / total_available) >= 2)) || (total_available == 0)) { // if not writing already, then write // 0 = not saving, 1 = saving, <0 = error if(zdb_zone_info_background_store_in_progress(jnl->origin) != 1) { zdb_zone_info_background_store_zone(jnl->origin); } } // space available until the current limit of the page (file size or first page offset) available = journal_cjf_get_last_page_available_space_left(jnl); if(available >= ixfrinc.size) { log_debug("cjf: %{dnsname}: %lli >= %i storage available in this page", jnl->origin, available, ixfrinc.size); } else { // not enough room, but can we handle it ? // // if there is only one NON-EMPTY page in the journal, // cut it and create a new one // if there are at least two NON-EMPTY pages and the available space between them is big enough, // cut the last page // remove the first // else just complain about the journal size and continue int page_count = journal_cjf_idxt_get_page_count(jnl); bool last_page_empty = journal_cjf_page_line_count(jnl) == 0; yassert(page_count > 0); if(page_count == 1) { if(!last_page_empty) { log_debug("cjf: %{dnsname}: one page: append another page", jnl->origin); // cut and proceed, as we will probably want to roll on the next update journal_cjf_page_output_stream_cancel(&os); journal_cjf_idxt_append_page(jnl); output_stream_close(&os); output_stream_set_void(&os); // very important //journal_cjf_page_output_stream_reopen(&os, jnl); // and loop ret = SUCCESS; goto journal_cjf_append_ixfr_stream_master_accum_tryagain; } else { log_debug("cjf: %{dnsname}: one empty page: write on it", jnl->origin); // just proceed } } else { if(!last_page_empty) { u32 available_from_beginning = jnl->last_page.file_offset - CJF_PAGE_SIZE_IN_BYTE - CJF_HEADER_SIZE; if(ixfrinc.size <= available_from_beginning) { // for a slave only, ensure the journal has been read before going further. if(is_slave) { // page_count > 1 u32 page_1_serial_from = journal_cjf_idxt_get_page_serial_from_index(jnl, 1); u32 starting_zone_serial = page_1_serial_from - 1; zdb_zone_lock((zdb_zone*)jnl->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); /*ret = */zdb_zone_getserial((zdb_zone*)jnl->zone, &starting_zone_serial); // zone is locked zdb_zone_unlock((zdb_zone*)jnl->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); // compare with start serial of second page if(serial_lt(starting_zone_serial, page_1_serial_from)) { // cutting the first page will break continuity :stop reading IXFR now, apply the journal and try later. journal_cjf_page_output_stream_cancel(&os); goto journal_cjf_append_ixfr_stream_master_accum_exit; } } log_debug("cjf: %{dnsname}: %u of %u bytes available on a loop: loop", jnl->origin, available_from_beginning, ixfrinc.size); // cutting now will allow to loop if(FAIL(ret = journal_cjf_append_ixfr_stream_first_page_removal(jnl))) { // could not remove first page break; } journal_cjf_page_output_stream_cancel(&os); u32 tmp = jnl->file_maximum_size; jnl->file_maximum_size = 0; // force the loop (thus removing the first page) journal_cjf_idxt_append_page(jnl); jnl->file_maximum_size = tmp; output_stream_close(&os); output_stream_set_void(&os); // very important journal_cjf_page_output_stream_reopen(&os, jnl); } else { log_debug("cjf: %{dnsname}: %u/%u bytes available on a loop: continue", jnl->origin, available_from_beginning, ixfrinc.size); // do a cut to allow to loop soon journal_cjf_page_output_stream_cancel(&os); u32 tmp = jnl->file_maximum_size; jnl->file_maximum_size = MAX_U32; journal_cjf_idxt_append_page(jnl); jnl->file_maximum_size = tmp; output_stream_close(&os); output_stream_set_void(&os); // very important journal_cjf_page_output_stream_reopen(&os, jnl); } } else { // just proceed log_debug("cjf: %{dnsname}: last page is empty: write on it", jnl->origin); } } } } // write the ixfr increment in the page input_stream bais; bytearray_input_stream_init_const(&bais, bytearray_output_stream_buffer(&ixfrinc.baos), bytearray_output_stream_size(&ixfrinc.baos)); for(;;) { if((ret = dns_resource_record_read(&rr, &bais)) <= 0) { if(ret != 0) { log_err("cjf: %{dnsname}: error re-reading record: %r", jnl->origin, ret); } break; } #if DEBUG log_debug("cjf: %{dnsname}: writing %{dnsrr}", jnl->origin, &rr); #endif if(FAIL(ret = journal_cfj_page_output_stream_write_resource_record(&os, &rr))) { log_err("cjf: %{dnsname}: could not store record: %r", jnl->origin, ret); break; } } input_stream_close(&bais); if(ISOK(ret)) { if(journal_is_empty) { jnl->serial_begin = ixfrinc.serial_from; journal_cjf_clear_empty(jnl); } jnl->serial_end = ixfrinc.serial_to; journal_cjf_set_dirty(jnl); ++written_pages; journal_cjf_page_output_stream_next(&os); // if we wrote records after the expected position for the IDXT, move the IDXT position if(jnl->last_page.records_limit > jnl->page_table_file_offset) { jnl->page_table_file_offset = jnl->last_page.records_limit; jnl->idxt.dirty = TRUE; journal_cjf_set_dirty(jnl); } } else { journal_cjf_page_output_stream_cancel(&os); break; } } journal_cjf_append_ixfr_stream_master_accum_exit: if(os.data != NULL) { output_stream_close(&os); } journal_cjf_read_ixfr_finalize(&ixfrinc); dns_resource_record_clear(&rr); if(written_pages > 0) { journal_cjf_page_cache_flush(jnl->file); journal_cjf_header_flush(jnl); } journal_cjf_writeunlock(jnl); if(ISOK(ret)) { log_info("cjf: %{dnsname}: added %i incremental changes to the journal", jnl->origin, written_pages); ret = TYPE_IXFR; } else { log_err("cjf: %{dnsname}: append IXFR (master) failed with: %r", jnl->origin, ret); } return ret; } static ya_result journal_cjf_append_ixfr_stream(journal *jh, input_stream *ixfr_wire_is) { u8 zt; journal_cjf *jnl = (journal_cjf*)jh; ya_result ret = zdb_zone_info_get_zone_type(jnl->origin, &zt); if(ISOK(ret)) { switch(zt) { case ZT_MASTER: ret = journal_cjf_append_ixfr_stream_per_page(jh, ixfr_wire_is, FALSE); break; case ZT_SLAVE: ret = journal_cjf_append_ixfr_stream_per_page(jh, ixfr_wire_is, TRUE); break; default: ret = ERROR; // obsolete break; } } return ret; } /****************************************************************************** * * Journal Input Stream * This one returns and IXFR stream * ******************************************************************************/ #define JCJFISDT_TAG 0x54445349464a434a struct journal_cjf_input_stream_data { journal_cjf *jnl; file_pool_file_t file; u32 available; u32 serial_from; u32 page_next; // DEBUG u16 idxt_index; u16 idxt_size; u16 todo_soa_record_size; bool first_stream; u8* todo_soa_record; }; typedef struct journal_cjf_input_stream_data journal_cjf_input_stream_data; static ya_result journal_cjf_input_stream_read(input_stream* stream, void *buffer_, u32 len) { journal_cjf_input_stream_data *data = (journal_cjf_input_stream_data*)stream->data; u8 *buffer = (u8*)buffer_; const u8 *base = buffer; const u8 *limit = &buffer[len]; intptr n; ya_result ret = 0; journal_cjf *jnl = data->jnl; log_debug("cjf: %s,%p: input: reading %u/%u bytes, pos is %lli", jnl->journal_file_name, jnl->file, len, data->available, file_pool_seek(data->file, 0, SEEK_CUR)); // while there is still room in the output buffer while((n = limit - buffer) > 0) { // if there is no data ready on input, fetch some more if(data->available == 0) { // get the next one if(data->idxt_index == data->idxt_size) { // EOF : we were at the last index in the IDXT break; } // get the offset of the current PAGE table u32 page_offset = journal_cjf_idxt_get_file_offset(data->jnl, data->idxt_index); u32 stream_offset; u32 stream_limit_offset; // look for the first SOA requested if(!data->first_stream) { // we are already streaming, the XFR stream starts at the end of the PAGE (4096 bytes until next version of the journal) stream_offset = page_offset + CJF_PAGE_SIZE_IN_BYTE; } else { // the starting stream offset is obtained through a bit more work if(FAIL(ret = journal_cjf_page_get_stream_offset_from_serial(data->jnl, data->idxt_index, data->serial_from, &stream_offset))) { return ret; } data->first_stream = FALSE; } journal_cjf_page_tbl_header page_header; journal_cjf_page_cache_read_header(data->jnl->file, page_offset, &page_header); if(page_header.count == 0) { // empty page, proably not flushed break; } stream_limit_offset = page_header.stream_end_offset; // we know where to start ... data->idxt_index++; (void)stream_limit_offset; #if DEBUG if(stream_limit_offset == 0) { log_err("impossible limit value read from the journal"); journal_cjf_page_cache_read_header(data->jnl->file, page_offset, &page_header); } #endif yassert(stream_limit_offset != 0); yassert(stream_limit_offset > page_offset); data->available = page_header.stream_end_offset - stream_offset; data->page_next = page_header.next_page_offset; if(file_pool_seek(data->file, stream_offset, SEEK_SET) < 0) { return ERRNO_ERROR; } } n = MIN(n, data->available); if(FAIL(ret = file_pool_readfully(data->file, buffer, n))) { return ret; } data->available -= n; buffer += n; } return buffer - base; } static ya_result journal_cjf_input_stream_skip(input_stream* is, u32 len) { u8 tmp[512]; journal_cjf_input_stream_data *data = (journal_cjf_input_stream_data*)is->data; journal_cjf *jnl = data->jnl; log_debug("cjf: %s,%p: input: skipping %u bytes", jnl->journal_file_name, jnl->file, len); while(len > 0) { ya_result ret; u32 n = MIN(len, sizeof(tmp)); if(FAIL(ret = journal_cjf_input_stream_read(is, tmp, n))) { return ret; } len -= n; } return len; } static void journal_cjf_input_stream_close(input_stream* is) { journal_cjf_input_stream_data *data = (journal_cjf_input_stream_data*)is->data; log_debug("cjf: %s,%p: input: close (%p)", data->jnl->journal_file_name, data->jnl->file, data->file); journal_cjf_readunlock(data->jnl); journal_cjf_release(data->jnl); file_pool_close(data->file); ZFREE_OBJECT(data); input_stream_set_void(is); } static const input_stream_vtbl journal_cjf_input_stream_vtbl = { journal_cjf_input_stream_read, journal_cjf_input_stream_skip, journal_cjf_input_stream_close, "journal_cjf_input_stream" }; /* * the last_soa_rr is used for IXFR transfers (it has to be a prefix & suffix to the returned stream) */ static ya_result journal_cjf_get_ixfr_stream_at_serial(journal *jh, u32 serial_from, input_stream *out_input_stream, dns_resource_record *out_last_soa_rr) { journal_cjf *jnl = (journal_cjf*)jh; log_debug("cjf: %s,%p: get IXFR stream at serial %i", jnl->journal_file_name, jnl->file, serial_from); journal_cjf_readlock(jnl); if(serial_lt(serial_from, jnl->serial_begin) || serial_ge(serial_from, jnl->serial_end)) { if(serial_from == jnl->serial_end) { log_debug("cjf: %s,%p: the journal ends at %i, returning empty stream", jnl->journal_file_name, jnl->file, serial_from); journal_cjf_readunlock(jnl); empty_input_stream_init(out_input_stream); return SUCCESS; // 0 } else { log_debug("cjf: %s,%p: the journal ends at %i, returning empty stream", jnl->journal_file_name, jnl->file, serial_from); journal_cjf_readunlock(jnl); #if DEBUG logger_flush(); #endif return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } } ya_result ret; dns_resource_record rr; dns_resource_record_init(&rr); // increment the reference count of the journal // lock the range in the file so it cannot be overwritten // create a stream that know where to start, where to end // it has to first send the last SOA // then to send the start // then to send the last SOA again if(FAIL(ret = journal_cjf_idxt_get_page_index_from_serial(jnl, serial_from))) { journal_cjf_readunlock(jnl); return ret; } yassert(ret < MAX_U16); u16 idxt_index = (u16)ret; journal_cjf_input_stream_data *data; ZALLOC_OBJECT_OR_DIE(data, journal_cjf_input_stream_data, JCJFISDT_TAG); journal_acquire((journal*)jnl); data->jnl = jnl; data->file = file_pool_open_ex(journal_file_pool, jnl->journal_file_name, O_RDONLY|O_CLOEXEC, 0660); if(data->file == NULL) { // the journal doess not exist (anymore ?) ZFREE_OBJECT(data); journal_cjf_readunlock(jnl); journal_cjf_release(jnl); return MAKE_ERRNO_ERROR(ENOENT); } data->serial_from = serial_from; if(out_last_soa_rr != NULL) { yassert(jnl->last_soa_offset != 0); // read the last SOA size_t from = ~0; file_pool_tell(data->file, &from); file_pool_seek(data->file, jnl->last_soa_offset, SEEK_SET); input_stream tmp; file_pool_file_input_stream_init(&tmp, data->file); ret = dns_resource_record_read(out_last_soa_rr, &tmp); file_pool_file_input_stream_detach(&tmp); file_pool_seek(data->file, from, SEEK_SET); if(FAIL(ret)) { journal_cjf_readunlock(jnl); journal_cjf_release(jnl); log_err("cjf: %s,%p: unable to read the SOA for serial %u at position %u: %r", jnl->journal_file_name, jnl->file, serial_from, jnl->last_soa_offset, ret); ZFREE_OBJECT(data); return ret; } } data->idxt_index = idxt_index; data->idxt_size = jnl->idxt.count; data->available = 0; data->first_stream = TRUE; out_input_stream->data = data; out_input_stream->vtbl = &journal_cjf_input_stream_vtbl; return ret; /* * In page_begin.file_offset, we get the first PAGE table * * That table may chain to a next PAGE, and so on and so forth * While this is happening, every stream between offsets: * * page_begin.file_offset + CJF_SECTION_INDEX_SIZE * * and * * @(page_begin.file_offset + 4) * * is to be sent by the stream * * When @(page_begin.file_offset + 4) is 0, it is the last PAGE * * Note that @(page_begin.file_offset + 4) is cached in the IDXT entries * * Every PAGE table but the last one has exactly CJF_SECTION_INDEX_SLOT_COUNT items * * jnl->page.count contains the count of items of the current (not full) PAGE * jnl->page.offset_next contains the supremum of input after the last PAGE * * This means a journal has to be fully initialised before being read (it was not the case for an IX file) * * The content of the PAGE itself is not required. Only the DNS part matters. * * All this also means a journal has to be flushed for its DNS on disk (since the file has to be opened separately because a cloned fd shares the file pointer) * * A range-locking mechanism is clearly needed. It should only be capable of locking up to two ranges (covers all cases). * * So here, in summary, return a stream that is linked to the journal * * It will start at offset: * * idxt[ret].file_offset + CJF_SECTION_INDEX_SIZE * * until: * * idxt[ret + 1].file_offset or page.offset_next * * and continue that way for every ret < idxt.count * */ } static ya_result journal_cjf_get_first_serial(journal *jh, u32 *serial) { ya_result ret = BUFFER_WOULD_OVERFLOW; journal_cjf *jnl = (journal_cjf*)jh; journal_cjf_readlock(jnl); u32 value = jnl->serial_begin; if(serial != NULL) { *serial = value; ret = SUCCESS; } journal_cjf_readunlock(jnl); log_debug("cjf: %s,%p: get first serial: %i", jnl->journal_file_name, jnl->file, value); return ret; } static ya_result journal_cjf_get_last_serial(journal *jh, u32 *serial) { ya_result ret = BUFFER_WOULD_OVERFLOW; journal_cjf *jnl = (journal_cjf*)jh; journal_cjf_readlock(jnl); u32 value = jnl->serial_end; if(serial != NULL) { *serial = value; ret = SUCCESS; } log_debug("cjf: %s,%p: get last serial: %i", jnl->journal_file_name, jnl->file, value); journal_cjf_readunlock(jnl); return ret; } static ya_result journal_cjf_get_serial_range(journal *jh, u32 *serial_start, u32 *serial_end) { journal_cjf *jnl = (journal_cjf*)jh; journal_cjf_readlock(jnl); if(serial_start != NULL) { *serial_start = jnl->serial_begin; } if(serial_end != NULL) { *serial_end = jnl->serial_end; } journal_cjf_readunlock(jnl); return SUCCESS; } static ya_result journal_cjf_truncate_to_size(journal *jh, u32 size_) { journal_cjf *jnl = (journal_cjf*)jh; if(size_ == 0) { journal_cjf_writelock(jnl); log_debug("cjf: %s,%p: truncate to size 0", jnl->journal_file_name, jnl->file); if(jnl->file == NULL) { journal_cjf_page_cache_close(jnl->file); file_pool_close(jnl->file); jnl->file = NULL; } file_pool_unlink_from_pool_and_filename(journal_file_pool, jnl->journal_file_name); jnl->idxt.dirty = FALSE; journal_cjf_idxt_destroy(jnl); jnl->file_maximum_size = MAX_U32; if(jnl->zone != NULL) { jnl->file_maximum_size = jnl->zone->wire_size >> 1; zdb_zone_info_get_zone_max_journal_size(jnl->origin, &jnl->file_maximum_size); } jnl->file = NULL; jnl->last_page.file_offset = CJF_HEADER_SIZE; jnl->last_page.count = 0; jnl->last_page.size = CJF_SECTION_INDEX_SLOT_COUNT; jnl->last_page.serial_start = 0; jnl->last_page.serial_end = 0; jnl->last_page.records_limit = CJF_HEADER_SIZE + CJF_SECTION_INDEX_SIZE; jnl->last_page.file_offset_limit = jnl->file_maximum_size; jnl->serial_begin = 0; jnl->serial_end = 0; jnl->first_page_offset = CJF_HEADER_SIZE; jnl->page_table_file_offset = 0; jnl->last_soa_offset = 0; //jnl->file_maximum_size = MAX_U32; //jnl->mtx.owner = LOCK_NONE; //jnl->mtx.count = 0; jnl->flags = JOURNAL_CFJ_FLAGS_MY_ENDIAN; jnl->last_page.records_limit = jnl->last_page.file_offset + CJF_SECTION_INDEX_SIZE; jnl->last_page.file_offset_limit = jnl->file_maximum_size; //jnl->journal_file_name = strdup(filename); journal_cjf_writeunlock(jnl); return SUCCESS; } else { log_err("cjf: %s,%p: truncate to size != 0 not implemented", jnl->journal_file_name, jnl->file); return ZDB_JOURNAL_FEATURE_NOT_SUPPORTED; } } static ya_result journal_cjf_truncate_to_serial(journal *jh, u32 serial_) { journal_cjf *jnl = (journal_cjf*)jh; (void)serial_; journal_cjf_readlock(jnl); log_err("cjf: %s,%p: truncate to serial not implemented", jnl->journal_file_name, jnl->file); journal_cjf_readunlock(jnl); return ZDB_JOURNAL_FEATURE_NOT_SUPPORTED; } /** * * @param jnl * @return */ static ya_result journal_cjf_reopen(journal *jh) { #if 0 /* fix */ #else return SUCCESS; #endif } static void journal_cjf_flush(journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; log_debug("cjf: %s,%p: flush", jnl->journal_file_name, jnl->file); journal_cjf_writelock(jnl); #if ZDB_ZONE_HAS_JNL_REFERENCE zdb_zone *zone; if((zone = (zdb_zone*)jnl->zone) != NULL) { yassert(zone->journal == jh); zone->journal = NULL; } #endif log_debug3("cjf: %s,%p: flushing to file", jnl->journal_file_name, jnl->file); log_debug3("cjf: %s,%p: flushing to file: flushing PAGE cache", jnl->journal_file_name, jnl->file, jnl->journal_file_name); journal_cjf_page_cache_flush(jnl->file); log_debug3("cjf: %s,%p: flushing to file: flushing IDXT", jnl->journal_file_name, jnl->file, jnl->journal_file_name); journal_cjf_idxt_flush(jnl); log_debug3("cjf: %s,%p: flushing to file: flushing header", jnl->journal_file_name, jnl->file, jnl->journal_file_name); journal_cjf_header_flush(jnl); journal_cjf_writeunlock(jnl); } static ya_result journal_cjf_close(journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; log_debug("cjf: %s,%p: close", jnl->journal_file_name, jnl->file); journal_cjf_writelock(jnl); #if ZDB_ZONE_HAS_JNL_REFERENCE zdb_zone *zone; if((zone = (zdb_zone*)jnl->zone) != NULL) { yassert(zone->journal == jh); zone->journal = NULL; } #endif log_debug3("cjf: %s,%p: closing file", jnl->journal_file_name, jnl->file); if(jnl->file != NULL) { log_debug3("cjf: %s,%p: closing file: closing PAGE cache", jnl->journal_file_name, jnl->file, jnl->journal_file_name); journal_cjf_page_cache_close(jnl->file); log_debug3("cjf: %s,%p: closing file: flushing IDXT", jnl->journal_file_name, jnl->file, jnl->journal_file_name); journal_cjf_idxt_flush(jnl); log_debug3("cjf: %s,%p: closing file: flushing header", jnl->journal_file_name, jnl->file, jnl->journal_file_name); journal_cjf_header_flush(jnl); log_debug3("cjf: %s,%p: closing file: closing file", jnl->journal_file_name, jnl->file, jnl->journal_file_name); journal_cjf_idxt_destroy(jnl); if(jnl->zone != NULL) { log_info("zone: %{dnsname}: closing journal file '%s'", jnl->origin, jnl->journal_file_name); } else { log_info("zone: : closing journal file '%s'", jnl->journal_file_name); } file_pool_close(jnl->file); jnl->file = NULL; } journal_cjf_writeunlock(jnl); return SUCCESS; } static void journal_cjf_log_dump(journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; journal_cjf_readlock(jnl); log_debug("cjf: %s,%p: [%u; %u] '%s' (%i) lck=%i rc=%i", jnl->journal_file_name, jnl->file, jnl->serial_begin, jnl->serial_end, jnl->journal_file_name, jnl->file, jnl->mtx.owner, jnl->mtx.count); journal_cjf_readunlock(jnl); } static ya_result journal_cjf_get_domain(journal *jh, u8 *out_domain) { journal_cjf *jnl = (journal_cjf*)jh; // don't: journal_cjf_readlock(jnl); as the field is constant until the destruction of the journal dnsname_copy(out_domain, jnl->origin); return SUCCESS; } /** * Links a zdb_zone and a journal * * @param jh * @param zone */ static void journal_cjf_link_zone(journal *jh, zdb_zone *zone) { journal_cjf *jnl = (journal_cjf*)jh; journal_cjf_writelock(jnl); if(jnl->zone != zone) { jnl->file_maximum_size = MAX_U32; #if !ZDB_ZONE_HAS_JNL_REFERENCE if(jnl->zone != NULL) { log_debug("cjf: %s,%p: unlinking zone %{dnsname},%p", jnl->journal_file_name, jnl->file, jnl->zone->origin, jnl->zone); zdb_zone_release((zdb_zone*)jnl->zone); //jnl->zone = NULL; } if(zone != NULL) { zdb_zone_acquire(zone); log_debug("cjf: %s,%p: linking to zone %{dnsname},%p", jnl->journal_file_name, jnl->file, zone->origin, zone); jnl->file_maximum_size = zone->wire_size >> 1; } #endif jnl->zone = zone; zdb_zone_info_get_zone_max_journal_size(jnl->origin, &jnl->file_maximum_size); jnl->last_page.file_offset_limit = jnl->file_maximum_size; } journal_cjf_writeunlock(jnl); } static void journal_cjf_destroy(journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; yassert(jnl->rc == 0); log_debug("cjf: %s,%p: destroy", jnl->journal_file_name, jnl->file); journal_cjf_link_zone(jh, NULL); shared_group_mutex_destroy(&jnl->mtx); free(jnl->origin); free(jnl->journal_file_name); #if DEBUG memset(jnl, 0xfe, sizeof(journal_cjf)); jnl->mru = FALSE; #endif ZFREE_OBJECT(jnl); } static const u8 * journal_cjf_get_domain_const(journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; return jnl->origin; } /******************************************************************************* * * vtbl handling functions * ******************************************************************************/ struct journal_vtbl journal_cjf_vtbl = { journal_cjf_get_format_name, journal_cjf_get_format_version, journal_cjf_reopen, journal_cjf_flush, journal_cjf_close, journal_cjf_append_ixfr_stream, journal_cjf_get_ixfr_stream_at_serial, journal_cjf_get_first_serial, journal_cjf_get_last_serial, journal_cjf_get_serial_range, journal_cjf_truncate_to_size, journal_cjf_truncate_to_serial, journal_cjf_log_dump, journal_cjf_get_domain, journal_cjf_destroy, journal_cjf_link_zone, journal_cjf_get_domain_const, JOURNAL_CLASS_NAME }; ya_result journal_cjf_load_index_table(journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; // check if the index table (referencing all indexes) if(jnl->page_table_file_offset == 0) { // the table does not exist or is corrupted // it has to be read again // from first_index_offset the index list has to be followed to recreate it // if such table only contains one entry, it could probably be ignored in most cases } else { // seek and load the table } return -1; } static journal_cjf* journal_cjf_alloc_default(const u8 *origin, const char *filename) { journal_cjf *jnl; ZALLOC_OBJECT_OR_DIE(jnl, journal_cjf, JRNLCJF_TAG); ZEROMEMORY(jnl, sizeof(journal_cjf)); jnl->vtbl = &journal_cjf_vtbl; jnl->mru_node.data = jnl; jnl->file = NULL; jnl->file_maximum_size = MAX_U32; jnl->first_page_offset = CJF_HEADER_SIZE; jnl->origin = dnsname_dup(origin); jnl->journal_file_name = strdup(filename); jnl->last_page.file_offset = CJF_HEADER_SIZE; jnl->last_page.size = CJF_SECTION_INDEX_SLOT_COUNT; jnl->last_page.records_limit = CJF_HEADER_SIZE + CJF_SECTION_INDEX_SIZE; jnl->last_page.file_offset_limit = jnl->file_maximum_size; jnl->flags = JOURNAL_CFJ_FLAGS_MY_ENDIAN|JOURNAL_CFJ_FLAGS_UNINITIALISED; shared_group_mutex_init(&jnl->mtx, &journal_shared_mtx, "journal-cjf"); return jnl; } /** * The caller guarantees not to call this on an already opened journal * * Should not be called directly (only by journal_* functions. * * Opens or create a journal handling structure. * If the journal did not exist, the structure is returned without a file opened * * @param jh * @param origin * @param workingdir * @param create * * @return */ ya_result journal_cjf_open_file(journal **jhp, const char *filename, const u8* origin, bool create) { // CFJ_PAGE_CACHE -> if(!journal_initialized) { journal_cjf_page_cache_init(); shared_group_shared_mutex_init(&journal_shared_mtx); journal_file_pool = file_pool_init("journal-file-pool", 256); journal_initialized = TRUE; } journal_cjf *jnl = NULL; ya_result ret; if(file_exists(filename) || create) { // instantiate and open the journal ret = journal_cjf_init_from_file(&jnl, origin, filename, create); if(ISOK(ret)) { yassert(jnl != NULL); // to help scan-build if(!((jnl->serial_begin == 0) && (jnl->serial_begin == jnl->serial_end))) // scan-build false-positive : if ISOK(ret) => jnl != NULL { journal_cjf_load_idxt(jnl); } } else { if(create) { log_err("cjf: %{dnsname}: failed to open %s: %r", origin, filename, ret); } else { log_debug("cjf: %{dnsname}: failed to open %s: %r", origin, filename, ret); } if(jnl != NULL) { journal_cjf_destroy((journal*)jnl); #if DEBUG log_debug("cjf: %{dnsname}: journal file cannot be opened/created", origin); #endif } return ZDB_ERROR_ICMTL_NOTFOUND; } #if DEBUG log_debug("cjf: %{dnsname}: journal opened", origin); #endif *jhp = (journal*)jnl; return SUCCESS; } else { #if DEBUG log_debug("cjf: %{dnsname}: journal file not found", origin); #endif return ZDB_ERROR_ICMTL_NOTFOUND; } } /** * The caller guarantees not to call this on an already opened journal * * Should not be called directly (only by journal_* functions. * * Opens or create a journal handling structure. * If the journal did not exist, the structure is returned without a file opened * * @param jh * @param origin * @param workingdir * @param create * * @return */ ya_result journal_cjf_open(journal **jhp, const u8* origin, const char *workingdir, bool create) { // CFJ_PAGE_CACHE <- ya_result ret; *jhp = NULL; // generate the file name char filename[PATH_MAX]; if((jhp == NULL) || (origin == NULL) || (workingdir == NULL)) { return ZDB_JOURNAL_WRONG_PARAMETERS; } #if DEBUG log_debug("cjf: trying to open journal for %{dnsname} in '%s'", origin, workingdir); #endif /* get the soa of the loaded zone */ if(FAIL(ret = snformat(filename, sizeof(filename), CJF_WIRE_FILE_FORMAT, workingdir, origin))) { #if DEBUG log_debug("cjf: %{dnsname}: journal file name is too long", origin); #endif return ret; } ret = journal_cjf_open_file(jhp, filename, origin, create); return ret; } void journal_cjf_finalize() { journal_cjf_page_cache_finalize(); file_pool_finalize(journal_file_pool); } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/journal-cjf-idxt.c0000644000000000000000000000013114505005531022307 xustar000000000000000030 mtime=1695812441.718971819 30 atime=1695812445.801030282 29 ctime=1695812495.06773588 yadifa-2.6.5-11201/lib/dnsdb/src/journal-cjf-idxt.c0000664000374500037450000010245714505005531022263 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /******************************************************************************* * * Indexes table handling functions * * These are the tables containing offsets to a serial * They are linked together * They are often referenced by an unique table of indexes * ******************************************************************************/ #define JOURNAL_CJF_BASE 1 #include "dnsdb/dnsdb-config.h" #define ZDB_JOURNAL_CODE 1 #include "dnsdb/journal.h" #if JOURNAL_CJF_ENABLED #include "dnsdb/journal-cjf-page-cache.h" #include "dnsdb/journal-cjf-idxt.h" #include "dnsdb/journal-cjf-common.h" #include #include #include #include #include #include #include extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define CJF_IDXT_SLOT_SIZE 8 const journal_cjf_idxt_tbl_item* journal_cjf_idxt_get_entry(const journal_cjf *jnl, s16 index) { yassert(index >= 0);yassert(jnl->idxt.first >= 0); journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + index) % jnl->idxt.size]; return entry; } s16 journal_cjf_idxt_size(const journal_cjf *jnl) { return jnl->idxt.count; } s16 journal_cjf_idxt_size_max(const journal_cjf *jnl) { return jnl->idxt.size; } /** * * Returns the file offset value at index in the current IDXT * * @param jnl * @param index * @return */ u32 journal_cjf_idxt_get_file_offset(const journal_cjf *jnl, s16 index) { u32 file_offset = journal_cjf_idxt_get_entry(jnl, index)->file_offset; return file_offset; } u32 journal_cjf_idxt_get_last_file_offset(const journal_cjf *jnl) { if(jnl->idxt.count > 0) { u32 n = journal_cjf_idxt_get_file_offset(jnl, jnl->idxt.count - 1); return n; } else { return 0; } } /** * * Returns the last serial number value at index in the IDXT * * @param jnl * @param index * @return */ u32 journal_cjf_idxt_get_last_serial(const journal_cjf *jnl, s16 index) { u32 last_serial = journal_cjf_idxt_get_entry(jnl, index)->last_serial; return last_serial; } /** * Creates an empty table of indexes (IDXT) for the journal, with a minimum number of entries. * Nothing is written to disk. * * @param jnl * @param entries */ void journal_cjf_idxt_create(journal_cjf *jnl, s16 entries) { yassert(jnl->idxt.size == 0); yassert(entries >= 0); jnl->idxt.count = 1; jnl->idxt.first = 0; jnl->idxt.size = entries + 1; jnl->idxt.dirty = TRUE; jnl->idxt.marked = 0; MALLOC_OR_DIE(journal_cjf_idxt_tbl_item*, jnl->idxt.entries, sizeof(journal_cjf_idxt_tbl_item) * jnl->idxt.size, JCJFITI_TAG); ZEROMEMORY(jnl->idxt.entries, sizeof(journal_cjf_idxt_tbl_item) * jnl->idxt.size); jnl->idxt.entries[0].last_serial = jnl->serial_begin; jnl->idxt.entries[0].file_offset = jnl->last_page.file_offset; jnl->first_page_offset = jnl->last_page.file_offset; } /** * Verifies the page table chain * To be used for small discrepancies between the header and the page table (idxt) * * @param jnl * @return */ static ya_result journal_cjf_idxt_verify(journal_cjf *jnl) { // check the values of the pages // serials have to be ordered in serial arithmetics // pages are supposed to start after each other except a looping ones that goes after the header // if the verify fails, a scan may be needed (other procedure) journal_cjf_page_tbl_header page_hdr; u32 previous_page_offset; u32 stream_end_offset; u32 next_page_offset; // uninitialised false positive: either size is <= 0, skipping for & if, either it's >= 0 and page_hrd is set and initialises next_page_offset u32 prev_serial = jnl->serial_begin; int loops = 0; bool error = FALSE; bool has_page_after_header = FALSE; s16 size = journal_cjf_idxt_size(jnl); for(int page = 0; page < size; ++page) { const journal_cjf_idxt_tbl_item* entry = journal_cjf_idxt_get_entry(jnl, page); has_page_after_header |= entry->file_offset == CJF_HEADER_SIZE; if(page > 0) { if(entry->file_offset != next_page_offset) // gcc false positive: next_page_offset is initialised when page == 0 { // page do not start at the expected position log_err("cjf: %{dnsname}: page[%i] starts at an unexpected position (%u != expected %u)", jnl->origin, page, entry->file_offset, next_page_offset); error = TRUE; } if(entry->file_offset == previous_page_offset) { // broken chain log_err("cjf: %{dnsname}: page[%i] is a duplicate at position %u", jnl->origin, page, entry->file_offset); error = TRUE; } if(entry->file_offset > previous_page_offset) { if(entry->file_offset != stream_end_offset) { // suspicious hole in the file log_err("cjf: %{dnsname}: page[%i] is %u bytes after the expected position", jnl->origin, page, entry->file_offset - stream_end_offset); error = TRUE; } } else { // just looped ... if(loops == 0) { if(entry->file_offset > CJF_HEADER_SIZE) { // looped at an unexpected position log_err("cjf: %{dnsname}: page[%i] looped at an unexpected position (%u != expected %u)", jnl->origin, page, entry->file_offset, CJF_HEADER_SIZE); error = TRUE; } else if(entry->file_offset > CJF_HEADER_SIZE) { // looped at an unexpected position log_err("cjf: %{dnsname}: page[%i] looped into the header position (%u < %u)", jnl->origin, page, entry->file_offset, CJF_HEADER_SIZE); error = TRUE; } loops = 1; } else { // should only have looped once log_err("cjf: %{dnsname}: page[%i] looped for a second time", jnl->origin, page); error = TRUE; } } if(error) { // got at least one error return ERROR; } } ssize_t pos = file_pool_seek(jnl->file, entry->file_offset, SEEK_SET); if(pos < 0) { // invalid position (as EBADF should not happen) ya_result ret = ERRNO_ERROR; log_err("cjf: %{dnsname}: page[%i] seek at %u returned %r", jnl->origin, page, entry->file_offset, ret); return ret; } int len = file_pool_readfully(jnl->file, &page_hdr, CJF_SECTION_INDEX_SLOT_HEAD); if(len != CJF_SECTION_INDEX_SLOT_HEAD) { if(len >= 0) { log_err("cjf: %{dnsname}: page[%i] short count reading the header (%u < %u)", jnl->origin, page, len, CJF_SECTION_INDEX_SLOT_HEAD); return ERROR; // short } else { log_err("cjf: %{dnsname}: page[%i] error reading the header: %r", jnl->origin, page, len); return len; // other error } } if(page_hdr.magic != CJF_PAGE_MAGIC) { // page is corrupted log_err("cjf: %{dnsname}: page[%i] corrupted magic", jnl->origin, page); return ERROR; } if(page_hdr.count > page_hdr.size) { // page is corrupted log_err("cjf: %{dnsname}: page[%i] says to contain more than allowed", jnl->origin, page); return ERROR; } if(page_hdr.count == 0) { // empty page (warning) log_warn("cjf: %{dnsname}: page[%i] is empty", jnl->origin, page); } if(serial_gt(prev_serial, entry->last_serial)) { // suspicious serial backward jump log_err("cjf: %{dnsname}: page[%i] serial jumped back from %u to %u", jnl->origin, page, prev_serial, entry->last_serial); } else if(serial_eq(prev_serial, entry->last_serial)) { // suspicious serial standstill log_err("cjf: %{dnsname}: page[%i] serial didn't changed from %u", jnl->origin, page, prev_serial); } previous_page_offset = entry->file_offset; next_page_offset = page_hdr.next_page_offset; // next page, 0 for the last one stream_end_offset = page_hdr.stream_end_offset; // start of next page, start of page table, or 0 for the last in the chain } if(size > 0) { if(next_page_offset != 0) // gcc false positive: size > 0 => next_page_offset has been set to page_hdr.next_page_offset (read from the disk) { // chain end was not marked log_err("cjf: %{dnsname}: page[%i] is last but points to a next at %u", jnl->origin, size - 1, next_page_offset); return ERROR; } if(!has_page_after_header) { // no page at an obvious position log_err("cjf: %{dnsname}: page table has no page at position %u", jnl->origin, CJF_HEADER_SIZE); return ERROR; } } else { // table is empty log_err("cjf: %{dnsname}: page table is empty", jnl->origin); return ERROR; } return SUCCESS; } /** * Loads (or rebuilds) the table of indexes (IDXT) * * @param jnl */ void journal_cjf_idxt_load(journal_cjf *jnl) { if(jnl->idxt.entries != NULL) { // already loaded ... return; } // the file is opened if(jnl->page_table_file_offset != 0) { log_debug1("journal_cjf_idxt_load: loading stored IDXT from '%s'", jnl->journal_file_name); // load file_pool_seek(jnl->file, jnl->page_table_file_offset, SEEK_SET); input_stream fis; input_stream bis; file_pool_file_input_stream_init(&fis, jnl->file); buffer_input_stream_init(&bis, &fis, 512); u8 magic[4]; input_stream_read(&bis, magic, 4); u32 *magic_u32p = (u32*)&magic[0]; if(*magic_u32p == CJF_IDXT_MAGIC) { s16 count; input_stream_read(&bis, (u8*)&count , 2); journal_cjf_idxt_create(jnl, count + 1); input_stream_read(&bis, (u8*)&jnl->idxt.entries[0], count * CJF_IDXT_SLOT_SIZE); file_pool_file_input_stream_detach(buffer_input_stream_get_filtered(&bis)); input_stream_close(&bis); jnl->idxt.count = count; u32 first_page_offset = journal_cjf_idxt_get_file_offset(jnl, 0); if(jnl->first_page_offset != first_page_offset) { // discrepancy : check the IDXT is valid if(ISOK(journal_cjf_idxt_verify(jnl))) { // the header is wrong, update it jnl->first_page_offset = first_page_offset; } } return; } file_pool_file_input_stream_detach(buffer_input_stream_get_filtered(&bis)); input_stream_close(&bis); // ERROR, need to rebuild } log_debug1("journal_cjf_idxt_load: rebuilding IDXT from '%s', following the PAGE", jnl->journal_file_name); // rebuild journal_cjf_page_tbl_item *tbl; u32 size = 512; journal_cjf_page_tbl_item tmp_tbl[512]; tbl = tmp_tbl; if(jnl->first_page_offset < JOURNAL_CJF_PAGE_HEADER_SIZE) { // the PAGE chain has been lost : start from HEAD and follow the chain // then after the 0, scan from the furthest known byte for PAGE+offset // and follow until the chain points back to offset sizeof(head) } // read the PAGE chain from the file (no caching) u32 index_offset = jnl->first_page_offset; //u32 current_serial = jnl->serial_begin; journal_cjf_page_tbl_header page_header; journal_cjf_page_tbl_item page_last_item; s16 idx = 0; u32 page_serial = 0; bool page_read = FALSE; do { // move to the page offset and read the header log_debug2("journal_cjf_idxt_load: reading '%s' PAGE header at %x", jnl->journal_file_name, index_offset); file_pool_seek(jnl->file, index_offset, SEEK_SET); if(file_pool_readfully(jnl->file, &page_header, JOURNAL_CJF_PAGE_HEADER_SIZE) != JOURNAL_CJF_PAGE_HEADER_SIZE) // next offset { log_err("journal_cjf_idxt_load: '%s' is too corrupt to go on further reading PAGE header at %x", jnl->journal_file_name, index_offset); break; } /* if(page_header.magic != CJF_PAGE_MAGIC) { // corrupt } */ if(page_header.count > 0) { u32 tail_offset = (page_header.count - 1) * CJF_SECTION_INDEX_SLOT_SIZE; log_debug2("journal_cjf_idxt_load: reading '%s' PAGE tail at %x", jnl->journal_file_name, index_offset + tail_offset); // the last serial is on the last slot file_pool_seek(jnl->file, tail_offset, SEEK_CUR); if(file_pool_readfully(jnl->file, &page_last_item, JOURNAL_CJF_PAGE_ITEM_SIZE) != JOURNAL_CJF_PAGE_ITEM_SIZE) { log_err("journal_cjf_idxt_load: '%s' is too corrupt to go on further reading PAGE tail at %x", jnl->journal_file_name, index_offset + CJF_SECTION_INDEX_SIZE - CJF_SECTION_INDEX_SLOT_HEAD - CJF_SECTION_INDEX_SLOT_SIZE); break; } // if there is a next page ... if(idx == size) { log_debug2("journal_cjf_idxt_load: growing IDXT table from %i to %i", size, size * 2); journal_cjf_page_tbl_item *tmp; MALLOC_OR_DIE(journal_cjf_page_tbl_item*, tmp, JOURNAL_CJF_PAGE_ITEM_SIZE * size * 2, JCJFTI_TAG); memcpy(tmp, tbl, JOURNAL_CJF_PAGE_ITEM_SIZE * size); if(tbl != tmp_tbl) { free(tbl); } tbl = tmp; size *= 2; } tbl[idx].stream_file_offset = index_offset; tbl[idx].ends_with_serial = page_last_item.ends_with_serial; log_debug2("journal_cjf_idxt_load: IDXT[%3i] = {%8x, %u}", idx, index_offset, page_last_item.ends_with_serial); page_serial = page_last_item.ends_with_serial; page_read = TRUE; ++idx; index_offset = page_header.next_page_offset; } else { // an empty page should not exist if(page_read) { if(serial_eq(page_serial, jnl->serial_end)) { log_info("journal_cjf_idxt_load: got up to expected serial %i", page_serial); } else if(serial_lt(page_serial, jnl->serial_end)) { log_err("journal_cjf_idxt_load: got up to serial %i, before the expected %i", page_serial, jnl->serial_end); } else if(serial_gt(page_serial, jnl->serial_end)) { log_err("journal_cjf_idxt_load: got up to serial %i, after the expected %i", page_serial, jnl->serial_end); } } else { log_err("journal_cjf_idxt_load: could not read the content of the journal"); } break; } } while(index_offset != 0); log_debug1("journal_cjf_idxt_load: IDXT table has size %i", idx + 1); // scan for an SOA record journal_cjf_idxt_create(jnl, idx + 1); memcpy(jnl->idxt.entries, tbl, JOURNAL_CJF_PAGE_ITEM_SIZE * idx); jnl->idxt.count = idx; } /** * * Writes the indexes table (IDXT) to the disk, if needed. * Updates the header on disk accordingly. * Clears the "dirty" and "makred" flags. * * @param jnl */ void journal_cjf_idxt_flush(journal_cjf *jnl) { // write the table on disk if not done already if(!jnl->idxt.dirty) { return; } if(jnl->page_table_file_offset == 0) { log_debug("cjf: %{dnsname}: table index not set", jnl->origin); return; } // write the table at the end off_t end = file_pool_seek(jnl->file, jnl->page_table_file_offset, SEEK_SET); if(end < 0) { int err = ERRNO_ERROR; log_err("cjf: forward to end of PAGE chain failed: %r", err); if(err == EBADF) { log_err("cjf: file has been closed before writing the summary"); } logger_flush(); return; } output_stream fos; output_stream bos; journal_cjf_set_dirty(jnl); log_debug3("cjf: flushing IDXT %u indexes at %08x", jnl->idxt.count, jnl->page_table_file_offset); file_pool_file_output_stream_init(&fos, jnl->file); file_pool_file_output_stream_set_full_writes(&fos, TRUE); // this makes the stream "write fully" buffer_output_stream_init(&bos, &fos, 512); output_stream_write(&bos, (const u8*)"IDXT", 4); output_stream_write(&bos, (const u8*)&jnl->idxt.count , 2); for(s16 idx = 0; idx < jnl->idxt.count; idx++) { output_stream_write(&bos, (const u8*)&jnl->idxt.entries[(jnl->idxt.first + idx) % jnl->idxt.size], CJF_IDXT_SLOT_SIZE); } output_stream_write(&bos, (const u8*)"END", 4); // yes, with the '\0' at the end output_stream_flush(&bos); file_pool_file_output_stream_detach(buffer_output_stream_get_filtered(&bos)); output_stream_close(&bos); // write the table offset journal_cjf_header_flush(jnl); #if DO_SYNC log_debug3("cjf: syncing to disk"); file_pool_flush(jnl->file); #endif jnl->idxt.dirty = FALSE; jnl->idxt.marked = FALSE; #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || /* Since glibc 2.3.5: */ _POSIX_C_SOURCE >= 200112L u32 file_size = jnl->page_table_file_offset + 4 + 2 + 4 + jnl->idxt.count * CJF_IDXT_SLOT_SIZE; file_pool_resize(jnl->file, file_size); #endif } /** * * Flushes the IDXT to disk if needed, then destroys the structure content. * * @param jnl */ void journal_cjf_idxt_destroy(journal_cjf *jnl) { journal_cjf_idxt_flush(jnl); free(jnl->idxt.entries); jnl->idxt.entries = NULL; jnl->idxt.size = 0; jnl->idxt.first = 0; jnl->idxt.count = 0; } /** * Updates the value of the last serial at current position in the PAGE * * @param jnl * @param last_serial */ void journal_cjf_idxt_update_last_serial(journal_cjf *jnl, u32 last_serial) { yassert(jnl->idxt.size > 0); journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + jnl->idxt.count - 1) % jnl->idxt.size]; log_debug2("cjf: IDXT current (%i) PAGE serial from %08x to %08x", jnl->idxt.count - 1, entry->last_serial, last_serial); entry->last_serial = last_serial; jnl->idxt.dirty = TRUE; } /** * Appends an PAGE table after the current one * * @param jcs * @param size_hint */ static void journal_cjf_idxt_append_page_nogrow(journal_cjf *jnl) { yassert(jnl->idxt.size > 0); journal_cjf_idxt_tbl_item *entry; jnl_page *page = &jnl->last_page; // last logical page on the (cycling) stream u32 page_offset = page->file_offset; // physical position of the page log_debug_jnl(jnl, "cjf: journal_cjf_idxt_append_page_nogrow: BEFORE"); yassert(page->count <= page->size); page->size = page->count; // we are forcing the change of page (adding but not growing, thus losing the first page if needed) if(jnl->idxt.count < jnl->idxt.size) { // there is still room left in the file : no need to grow, so no problem here log_debug2("cjf: append PAGE at [%i] offset %u (%08x)", jnl->idxt.count, page->records_limit, page->records_limit); // the entry is the next one (at position 'count'), modulo the size of the table entry = &jnl->idxt.entries[(jnl->idxt.first + jnl->idxt.count) % jnl->idxt.size]; jnl->idxt.count++; entry->last_serial = page->serial_end; entry->file_offset = page->records_limit; } else { // there is no room left thus we will replace the first page (increasing the first slot position) // overwrite of the start of the cyclic data, update the journal /* * No grow happens when the file is too big and we are about to loop */ u32 first_page_offset = journal_cjf_idxt_get_file_offset(jnl, 0); log_debug2("cjf: append PAGE at [%i] offset %u (%08x), losing first PAGE", jnl->idxt.count, first_page_offset, first_page_offset); entry = &jnl->idxt.entries[(jnl->idxt.first) % jnl->idxt.size]; yassert(jnl->first_page_offset == entry->file_offset); // removes first page, adjusts current PAGE offset_limit journal_cjf_remove_first_page(jnl); // will decrease the count and move the first jnl->idxt.count++; entry->last_serial = page->serial_end; entry->file_offset = first_page_offset; // update the section with the values for the next one } // update the section with the values for the next one page->file_offset = entry->file_offset; page->count = 0; page->size = CJF_SECTION_INDEX_SLOT_COUNT; page->records_limit = page->file_offset + CJF_SECTION_INDEX_SIZE; if(page->file_offset >= jnl->first_page_offset) { page->file_offset_limit = jnl->file_maximum_size; } else { page->file_offset_limit = jnl->first_page_offset; } page->serial_start = entry->last_serial; page->serial_end = entry->last_serial; // update the next pointer of the previous PAGE // CFJ_PAGE_CACHE -> log_debug3("cjf: updating PAGE chain (@%08x = %08x)", page_offset, page->file_offset); journal_cjf_page_tbl_header current_page_header; journal_cjf_page_cache_read_header(jnl->file, page_offset, ¤t_page_header); current_page_header.next_page_offset = page->file_offset; journal_cjf_page_cache_write_header(jnl->file, page_offset, ¤t_page_header); // writes an empty PAGE table for the current (new) PAGE log_debug3("cjf: writing new empty PAGE"); journal_cjf_page_cache_write_new_header(jnl->file, page->file_offset); // CFJ_PAGE_CACHE <- // the IDXT had some changes that need flushing jnl->idxt.dirty = TRUE; // only mark the file about its changes once if(!jnl->idxt.marked) { jnl->idxt.marked = TRUE; } journal_cjf_page_cache_flush(jnl->file); journal_cjf_header_flush(jnl); #if DO_SYNC log_debug3("cjf: syncing to disk"); file_pool_flush(jnl->file); #endif log_debug_jnl(jnl, "cjf: journal_cjf_idxt_append_page_nogrow: AFTER"); } /** * * Grows the IDTX table by one slot * * @param jnl */ static void journal_cjf_idxt_grow(journal_cjf *jnl) { yassert(jnl->idxt.size > 0); log_debug2("cjf: growing IDXT table to %u slots", jnl->idxt.size + 1); journal_cjf_idxt_tbl_item *tmp; MALLOC_OR_DIE(journal_cjf_idxt_tbl_item*, tmp, sizeof(journal_cjf_idxt_tbl_item) * (jnl->idxt.size + 1), JCJFITI_TAG); for(s16 idx = 0; idx < jnl->idxt.count; idx++) { tmp[idx] = jnl->idxt.entries[(jnl->idxt.first + idx) % jnl->idxt.size]; } ++jnl->idxt.size; for(s16 idx = jnl->idxt.count; idx < jnl->idxt.size; idx++) { tmp[idx].last_serial = 0; tmp[idx].file_offset = 0; } log_debug_jnl(jnl, "cjf: journal_cjf_idxt_grow: BEFORE"); free(jnl->idxt.entries); jnl->idxt.entries = tmp; jnl->idxt.first = 0; log_debug_jnl(jnl, "cjf: journal_cjf_idxt_grow: AFTER"); } /** * Ensures there is at least one empty available PAGE slot in the IDTX * * @param jnl */ static void journal_cjf_idxt_ensure_growth(journal_cjf *jnl) { log_debug2("cjf: ensuring IDXT growth"); if(jnl->idxt.count == jnl->idxt.size) { journal_cjf_idxt_grow(jnl); } } /** * * Prevent the IDXT table from growing further * * @param jnl */ static void journal_cjf_idxt_fix_size(journal_cjf *jnl) { yassert(jnl->idxt.size > 0); yassert(jnl->idxt.size >= jnl->idxt.count); if(jnl->idxt.size != jnl->idxt.count) { log_debug2("cjf: fixing IDXT size from %u to %u", jnl->idxt.size, jnl->idxt.count); journal_cjf_idxt_tbl_item *tmp; MALLOC_OR_DIE(journal_cjf_idxt_tbl_item*, tmp, sizeof(journal_cjf_idxt_tbl_item) * jnl->idxt.count, JCJFITI_TAG); for(s16 i = 0; i < jnl->idxt.count; ++i) { tmp[i] = jnl->idxt.entries[(jnl->idxt.first + i) % jnl->idxt.size]; } #if DEBUG memset(jnl->idxt.entries, 0xfe, sizeof(journal_cjf_idxt_tbl_item) * jnl->idxt.size); #endif free(jnl->idxt.entries); jnl->idxt.entries = tmp; jnl->idxt.first = 0; jnl->idxt.size = jnl->idxt.count; } else { log_debug2("cjf: fixing IDXT size to %u (nothing to do)", jnl->idxt.count); } } /** * Appends an PAGE after this one * * @param jnl */ void journal_cjf_idxt_append_page(journal_cjf *jnl) { // where are we in the file ? log_debug2("cjf: PAGE: @%08x -> %08x ... %08x [%08x; %08x]", jnl->last_page.file_offset, jnl->last_page.records_limit, jnl->last_page.file_offset_limit, jnl->last_page.serial_start, jnl->last_page.serial_end); // if the PAGE (offset) is before the first PAGE (offset) if(jnl->last_page.file_offset < jnl->first_page_offset) { log_debug2("cjf: IDXT adding PAGE (middle of the file)"); // we are in the middle of the physical file (meaning, physically before the first PAGE in the logical order) yassert(jnl->last_page.records_limit <= jnl->first_page_offset); // ensure there is enough room after us // while there is not enough room, remove one page while(jnl->first_page_offset - jnl->last_page.records_limit < CJF_SECTION_INDEX_SIZE + CJF_PAGE_ARBITRARY_UPDATE_SIZE) { journal_cjf_remove_first_page(jnl); if(jnl->last_page.file_offset >= jnl->first_page_offset) { break; } } // we made room or we reached a limit before we got enough yassert(jnl->first_page_offset - jnl->last_page.records_limit >= CJF_SECTION_INDEX_SIZE + CJF_PAGE_ARBITRARY_UPDATE_SIZE); // make the IDXT grow if it full already journal_cjf_idxt_ensure_growth(jnl); // create a new page at jnl->page.offset_next } else { // we are at the end of the physical file log_debug2("cjf: IDXT adding PAGE (end of the file)"); /// @note 20150210 edf -- A journal cannot loop with only one PAGE // if it is expected to go beyond the maximum size with the next update, prevent the growth of the idtx table // if we don't have at least two PAGE, then continue to grow the IDXT const bool has_at_least_two_pages = (jnl->idxt.count > 1); const bool too_close_to_the_file_size_limit = (jnl->last_page.records_limit + CJF_SECTION_INDEX_SIZE + CJF_PAGE_ARBITRARY_UPDATE_SIZE > jnl->file_maximum_size); if(has_at_least_two_pages && too_close_to_the_file_size_limit) { journal_cjf_idxt_fix_size(jnl); } else { journal_cjf_idxt_ensure_growth(jnl); } // create a new page in the idxt } journal_cjf_idxt_append_page_nogrow(jnl); } /* scans all the PAGE entries from the IDXT and get the one that contains the serial */ ya_result journal_cjf_idxt_get_page_index_from_serial(const journal_cjf *jnl, u32 serial) { u32 prev = jnl->serial_begin; if(serial_lt(serial, prev)) { return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } u32 prev_serial = jnl->serial_begin; s16 n = jnl->idxt.count; for(s16 i = 0; i < n; i++) { journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + i) % jnl->idxt.size]; // the last serial of an entry is the one of the last SOA added on it // we want to start after that one if(serial_lt(serial, entry->last_serial)) { log_debug1("journal_cjf_idxt_get_page_index_from_serial(%s, %d) returning %i (%i -> %i)", jnl->journal_file_name, serial, i, prev_serial, entry->last_serial); return i; } prev_serial = entry->last_serial; } return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } u32 journal_cjf_idxt_get_page_serial_from_index(const journal_cjf *jnl, int idx) { if(idx > 0) { journal_cjf_idxt_tbl_item *prev_entry; prev_entry = &jnl->idxt.entries[(jnl->idxt.first + idx - 1) % jnl->idxt.size]; return prev_entry->last_serial; } else { return jnl->serial_begin; } } /** * Returns the page index containing the serial, and optionally its position in the file. * * @param jnl * @param serial * @param file_offset * @return */ ya_result journal_cjf_idxt_get_page_offset_from_serial(const journal_cjf *jnl, u32 serial, u32 *file_offset) { u32 prev_serial = jnl->serial_begin; // ensure the journal starts at least from the serial we are looking for if(serial_lt(serial, prev_serial)) { return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } s16 n = jnl->idxt.count; for(s16 i = 0; i < n; i++) { journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + i) % jnl->idxt.size]; // entry->last_serial is the last_serial TO, so the start of the next page if(serial_lt(serial, entry->last_serial)) { log_debug1("journal_cjf_idxt_get_page_index_from_serial(%s, %d) returning %i (%i -> %i)", jnl->journal_file_name, serial, i, prev_serial, entry->last_serial); if(file_offset != NULL) { *file_offset = entry->file_offset; } return i; } prev_serial = entry->last_serial; } // too far ... return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } ya_result journal_cjf_idxt_get_page_serial_to(const journal_cjf *jnl, int idx) { journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + idx) % jnl->idxt.size]; return entry->last_serial; } u32 journal_cjf_idxt_get_page_offset(const journal_cjf *jnl, int idx) { journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + idx) % jnl->idxt.size]; return entry->file_offset; } #endif yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/journal-cjf-page.c0000644000000000000000000000013214505005531022254 xustar000000000000000030 mtime=1695812441.736972077 30 atime=1695812445.802030296 30 ctime=1695812495.069735909 yadifa-2.6.5-11201/lib/dnsdb/src/journal-cjf-page.c0000664000374500037450000001132114505005531022214 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #define JOURNAL_CJF_BASE 1 #include "dnsdb/dnsdb-config.h" #define ZDB_JOURNAL_CODE 1 #include "dnsdb/journal.h" #if JOURNAL_CJF_ENABLED #include "dnsdb/journal-cjf-page-output-stream.h" #include "dnsdb/journal-cjf-page.h" #include "dnsdb/journal-cjf-idxt.h" #include "dnsdb/journal-cjf-page-cache.h" /** * Search from the offset of the stream for a serial, looking in an PAGE referenced by index * * @param jnl * @param idx * @param serial * @param out_offset * @return */ ya_result journal_cjf_page_get_stream_offset_from_serial(journal_cjf *jnl, int idx, u32 serial, u32 *out_offset) { u32 file_offset = journal_cjf_idxt_get_page_offset(jnl, idx); journal_cjf_page_tbl_item value; if(journal_cjf_idxt_get_page_serial_from_index(jnl, idx) == serial) { // the first one journal_cjf_page_cache_read_item(jnl->file, file_offset, 0, &value); *out_offset = value.stream_file_offset; return SUCCESS; } // read how much items are in the PAGE journal_cjf_page_tbl_header hdr; journal_cjf_page_cache_read_header(jnl->file, file_offset, &hdr); if(hdr.magic == CJF_PAGE_MAGIC) { //for(int i = 1; i <= CJF_SECTION_INDEX_SLOT_COUNT - 1; i++) for(int i = 0; i < hdr.count - 1; i++) { journal_cjf_page_cache_read_item(jnl->file, file_offset, i, &value); if(value.ends_with_serial == serial) { // we found the item that ends with the requested serial, // the next item is the one that starts from the requested serial journal_cjf_page_cache_read_item(jnl->file, file_offset, i + 1, &value); *out_offset = value.stream_file_offset; return SUCCESS; } } //this is the wrong idx } else { // invalid } return ERROR; } /** * * Returns true iff the current PAGE table is full * * @param jnl * @return */ bool journal_cjf_page_is_full(journal_cjf *jnl) { yassert(jnl->last_page.size > 0); return jnl->last_page.count == jnl->last_page.size; } bool journal_cjf_page_line_count(journal_cjf *jnl) { return jnl->last_page.count; } /** * * Returns the file offset value at index in the current PAGE * * @param jnl * @param index * @return */ u32 journal_cjf_page_get_file_offset(journal_cjf *jnl) { return jnl->last_page.file_offset; } u32 journal_cjf_page_get_stream_file_offset(journal_cjf *jnl) { return jnl->last_page.records_limit; } /** * * Returns the last serial number value at index in the PAGE * * @param jnl * @param index * @return */ u32 journal_cjf_page_get_last_serial(journal_cjf *jnl, s16 index) { journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + index) % jnl->idxt.size]; return entry->last_serial; } #endif yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/journal-cjf-page-cache.c0000644000000000000000000000013214505005531023315 xustar000000000000000030 mtime=1695812441.721971862 30 atime=1695812445.801030282 30 ctime=1695812495.071735938 yadifa-2.6.5-11201/lib/dnsdb/src/journal-cjf-page-cache.c0000664000374500037450000006350214505005531023265 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ /** @brief Function ... * * ... * * @param ... * * @retval OK * @retval NOK */ #define ZDB_JOURNAL_CODE 1 #define JOURNAL_CJF_BASE 1 #include "dnsdb/dnsdb-config.h" #include "dnsdb/journal-cjf-page-cache.h" #include "dnsdb/journal-cjf-common.h" #include "dnsdb/journal-cjf.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dnsdb/zdb_error.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/journal.h" #include "dnsdb/zdb_types.h" #include "dnsdb/xfr_copy.h" #include "dnsdb/zdb-zone-path-provider.h" #if JOURNAL_CJF_ENABLED #define DEBUG_JOURNAL 0 #if !DEBUG #undef DEBUG_JOURNAL #define DEBUG_JOURNAL 0 #endif #define LOCK_NONE 0 #define LOCK_READ 1 #define LOCK_WRITE 2 #define CJF_EXT "cjf" #define CJF_EXT_STRLEN 3 #define SOA_RDATA_SIZE_MAX 532 #define DO_SYNC 1 extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger /* * Contains the journal (almost: not the matching start and end SOA) */ #define CJF_SECTION_INDEX_SLOT_HEAD 16 #define CJF_SECTION_INDEX_SLOT_SIZE 8 #define CJF_SECTION_INDEX_SLOT_COUNT 510 #define CJF_SECTION_INDEX_SIZE (CJF_SECTION_INDEX_SLOT_HEAD + CJF_SECTION_INDEX_SLOT_SIZE * CJF_SECTION_INDEX_SLOT_COUNT) // 4KB #define CJF_PAGE_SIZE_IN_BYTE (CJF_SECTION_INDEX_SLOT_HEAD + (CJF_SECTION_INDEX_SLOT_COUNT * CJF_SECTION_INDEX_SLOT_SIZE)) #define CJF_PAGE_ARBITRARY_UPDATE_SIZE 512 #define CJF_SECTION_INDEX_SLOT_HEAD_SLOT (CJF_SECTION_INDEX_SLOT_HEAD / CJF_SECTION_INDEX_SLOT_SIZE) //#define log_cjf_page_debug log_debug5 #define log_cjf_page_debug log_debug /* * PAGE * * Serial Number Stream Offset * * The table of serials streams (IXFR) and their offset * The value stored is of the serial ending the IXFR */ #define PAGE_INITIALIZER {CJF_PAGE_MAGIC, 0, 0, CJF_SECTION_INDEX_SLOT_COUNT, 0, 0} static bool empty_page_tbl_header_and_zeroes_initialised = FALSE; static u8 empty_page_tbl_header_and_zeroes[CJF_SECTION_INDEX_SIZE]; static u32 journal_cfj_page_mru_size = 64; // struct journal_cjf_page_tbl { journal_cjf_page_tbl_header hdr; journal_cjf_page_tbl_item items[CJF_SECTION_INDEX_SLOT_COUNT]; }; // PAGE are all over the place, going back to write into or read from one is a drag // the first idea would be to have the current PAGE along with the journal, and it would solve MOST problems // but PAGE may be needed at more than one place. // So the idea is to have them cached: // An PAGE cache entry is: // _ maybe a reference count // _ a file descriptor // _ a file position // _ a dirty flag, or a last_written offset // _ maybe a count // _ a 4K buffer // _ maybe an MRU entry ? // _ maybe a mutex // the key ... // // one should be able to // _ load an PAGE from the disk // _ flush an PAGE back to the disk // _ flush all PAGE linked to a file descriptor to the disk (KEY!) // _ update the PAGE of a given position in a file to the disk (KEY!) // // there should not be a lot of PAGE per file descriptor, and PAGE should be flushed back at key times // ie: closing the file descriptor, too many PAGE flush the least used ones, ... // // they should be pooled, I think #define JCJFPCI_TAG 0x494350464a434a struct journal_cjf_page_cache_item { u64 file_offset; journal_cjf_page_tbl_item *buffer; file_pool_file_t file; s16 first_written_entry; s16 last_written_entry; // set to the end means not dirty }; typedef struct journal_cjf_page_cache_item journal_cjf_page_cache_item; // fd => list_dl(page_cache_item) static ptr_set page_cache_item_by_file = PTR_SET_PTR_EMPTY; static list_dl_s page_cache_mru = {{NULL, NULL}, {NULL, NULL}, 0}; static group_mutex_t page_cache_mtx = GROUP_MUTEX_INITIALIZER; static void journal_cjf_page_cache_free(journal_cjf_page_cache_item *page_cache); void journal_cjf_page_cache_init() { if(empty_page_tbl_header_and_zeroes_initialised) { return; } journal_cjf_page_tbl_header head = PAGE_INITIALIZER; ZEROMEMORY(empty_page_tbl_header_and_zeroes, sizeof(empty_page_tbl_header_and_zeroes)); memcpy(empty_page_tbl_header_and_zeroes, &head, CJF_SECTION_INDEX_SLOT_HEAD); list_dl_init(&page_cache_mru); empty_page_tbl_header_and_zeroes_initialised = TRUE; } static void journal_cjf_page_cache_remove_from_mru(journal_cjf_page_cache_item *page_cache) { if(list_dl_size(&page_cache_mru) > 0) { list_dl_remove(&page_cache_mru, page_cache); } } static void journal_cjf_page_cache_add_to_mru(journal_cjf_page_cache_item *page_cache) { list_dl_insert(&page_cache_mru, page_cache); } /* void journal_cjf_page_cache_finalize() { } */ /** * called undirty because clear and clean are too similar * * @param page_cache */ static void journal_cjf_page_cache_item_undirty(journal_cjf_page_cache_item *page_cache) { page_cache->first_written_entry = (1 + CJF_SECTION_INDEX_SLOT_COUNT); page_cache->last_written_entry = -1; } static void journal_cjf_page_cache_item_flush_internal(journal_cjf_page_cache_item *page_cache) { file_pool_file_t file = page_cache->file; // at file_offset, write from first to last entries off_t first_offset = page_cache->file_offset + (page_cache->first_written_entry * CJF_SECTION_INDEX_SLOT_SIZE); size_t size = ((page_cache->last_written_entry - page_cache->first_written_entry) + 1) * CJF_SECTION_INDEX_SLOT_SIZE; log_cjf_page_debug("cjf: %s: flush page @%lli=%llx size=%i", file_pool_filename(file), first_offset, first_offset, size); for(;;) { file_pool_seek(file, first_offset, SEEK_SET); ya_result ret = file_pool_writefully(file, &page_cache->buffer[page_cache->first_written_entry], size); if(ret == (s32)size) { break; } // should no be reached, but if an issue occur, better not hammer the logs log_err("cjf: %s: flush page @%lli=%llx size=%i failed with: %r", file_pool_filename(file), first_offset, first_offset, size, ret); sleep(1); } // mark the entry as not being used journal_cjf_page_cache_item_undirty(page_cache); } /** * @param page_cache * @return */ static void journal_cjf_page_cache_item_flush(journal_cjf_page_cache_item *page_cache) { yassert(group_mutex_islocked(&page_cache_mtx)); if(page_cache != NULL) { if(page_cache->first_written_entry <= page_cache->last_written_entry) { file_pool_file_t file = page_cache->file; size_t here; file_pool_tell(file, &here); journal_cjf_page_cache_item_flush_internal(page_cache); file_pool_seek(file, (ssize_t)here, SEEK_SET); } } else { log_err("cjf: journal_cjf_page_cache_flush_item(NULL)"); } } static void journal_cjf_page_cache_cull() { yassert(group_mutex_islocked(&page_cache_mtx)); // culls a cache entry at the end of the MRU log_cjf_page_debug("cjf: cull pages"); while(list_dl_size(&page_cache_mru) > journal_cfj_page_mru_size) { // get the tail one journal_cjf_page_cache_item *page_cache = (journal_cjf_page_cache_item*)list_dl_remove_last(&page_cache_mru); // flush it journal_cjf_page_cache_item_flush(page_cache); // free it } log_cjf_page_debug("cjf: cull pages done"); } static void journal_cjf_page_mru_clear() { yassert(group_mutex_islocked(&page_cache_mtx)); // culls a cache entry at the end of the MRU log_cjf_page_debug("cjf: clear pages"); while(list_dl_size(&page_cache_mru) > 0) { // get the tail one journal_cjf_page_cache_item *page_cache = (journal_cjf_page_cache_item*)list_dl_remove_last(&page_cache_mru); // flush it journal_cjf_page_cache_item_flush(page_cache); // free it journal_cjf_page_cache_free(page_cache); } log_cjf_page_debug("cjf: clear pages done"); } static journal_cjf_page_cache_item * journal_cjf_page_cache_new(file_pool_file_t file, u32 file_offset) { journal_cjf_page_cache_item *page_cache; log_cjf_page_debug("cjf: %s: new page cache for offset %i", file_pool_filename(file), file_offset); ZALLOC_OBJECT_OR_DIE(page_cache, journal_cjf_page_cache_item, JCJFPCI_TAG); page_cache->file_offset = file_offset; MALLOC_OR_DIE(journal_cjf_page_tbl_item*, page_cache->buffer, CJF_PAGE_SIZE_IN_BYTE , JCJFTI_TAG); page_cache->file = file; journal_cjf_page_cache_item_undirty(page_cache); #if DEBUG memset(page_cache->buffer, 0xfe, CJF_PAGE_SIZE_IN_BYTE); #endif return page_cache; } static void journal_cjf_page_cache_free(journal_cjf_page_cache_item *page_cache) { #if DEBUG memset(page_cache->buffer, 0xfd, CJF_PAGE_SIZE_IN_BYTE); #endif free(page_cache->buffer); ZFREE_OBJECT(page_cache); } static inline u64_set* journal_cjf_page_cache_set_from_file(file_pool_file_t file) { yassert(group_mutex_islocked(&page_cache_mtx)); ptr_node *file_node = ptr_set_find(&page_cache_item_by_file, file); if(file_node != NULL) { return (u64_set*)&file_node->value; } else { log_warn("cjf: %s: file is not cached", file_pool_filename(file)); return NULL; } } static inline journal_cjf_page_cache_item* journal_cjf_page_cache_from_set(u64_set* page_cache_set, u32 file_offset) { u64_node *file_offset_node = u64_set_find(page_cache_set, file_offset); if(file_offset_node != NULL) { return (journal_cjf_page_cache_item*)file_offset_node->value; } else { log_err("cjf: page is not cached"); } return NULL; } static inline journal_cjf_page_cache_item* journal_cjf_page_cache_from_file(file_pool_file_t file, u32 file_offset) { u64_set* page_cache_set = journal_cjf_page_cache_set_from_file(file); if(page_cache_set != NULL) { journal_cjf_page_cache_item *page_cache = journal_cjf_page_cache_from_set(page_cache_set, file_offset); return page_cache; } return NULL; } static void journal_cjf_page_cache_delete_from_file_and_offset(const file_pool_file_t file, u32 file_offset) { yassert(group_mutex_islocked(&page_cache_mtx)); log_cjf_page_debug("cjf: %s: dropping page at offset %i", file_pool_filename(file), file_offset); u64_set* page_cache_set = journal_cjf_page_cache_set_from_file(file); if(page_cache_set != NULL) { // get the PAGE cache at the file_offset journal_cjf_page_cache_item *page_cache = journal_cjf_page_cache_from_set(page_cache_set, file_offset); if(page_cache != NULL) { u64_set_delete(page_cache_set, file_offset); journal_cjf_page_cache_item_flush(page_cache); journal_cjf_page_cache_remove_from_mru(page_cache); journal_cjf_page_cache_free(page_cache); } } } static journal_cjf_page_cache_item* journal_cjf_page_cache_get_for_rw(file_pool_file_t file, u64 file_offset) { // get or create a node for the fd ptr_node *file_node = ptr_set_insert(&page_cache_item_by_file, file); // make some room, if needed journal_cjf_page_cache_cull(); // get or create an PAGE cache at the file_offset u64_node *file_offset_node = u64_set_insert((u64_set*)&file_node->value, file_offset); journal_cjf_page_cache_item *page_cache; if(file_offset_node->value != NULL) { // already got that one page_cache = (journal_cjf_page_cache_item*)file_offset_node->value; } else { // have to create it page_cache = journal_cjf_page_cache_new(file, file_offset); // if the file is big enough: load it size_t the_file_size; if(ISOK(file_pool_get_size(file, &the_file_size))) { if(file_offset + CJF_PAGE_SIZE_IN_BYTE <= the_file_size) { size_t here = ~0ULL; file_pool_tell(file, &here); yassert(here != ~0ULL); #ifndef NDEBUG ssize_t there = #endif file_pool_seek(file, file_offset, SEEK_SET); yassert(there == (ssize_t)file_offset); // it is a READ, because to write the cache, it must first be loaded ssize_t size = file_pool_readfully(file, page_cache->buffer, CJF_PAGE_SIZE_IN_BYTE); #if DEBUG log_memdump_ex(g_database_logger, MSG_DEBUG6, page_cache->buffer, size, 32, OSPRINT_DUMP_ADDRESS|OSPRINT_DUMP_HEX); #endif yassert(size == CJF_PAGE_SIZE_IN_BYTE); (void)size; #ifndef NDEBUG there = #endif file_pool_seek(file, here, SEEK_SET); #ifndef NDEBUG yassert(there == (ssize_t)here); (void)size; (void)there; (void)here; #endif } } file_offset_node->value = page_cache; #if DEBUG log_debug("test"); #endif } return page_cache; } static void journal_cjf_page_cache_write(file_pool_file_t file, u64 file_offset, s16 offset, const void *value, u32 value_len) { log_cjf_page_debug("cjf: %s: writing slot %i from page at offset %llu", file_pool_filename(file), offset, file_offset); group_mutex_lock(&page_cache_mtx, GROUP_MUTEX_WRITE); // get or create a node for the fd journal_cjf_page_cache_item *page_cache = journal_cjf_page_cache_get_for_rw(file, file_offset); // update the last written entry to keep the highest value if(offset > page_cache->last_written_entry) { s16 value_len_slots = ((value_len + 7) >> 3) - 1; yassert(value_len_slots >= 0); page_cache->last_written_entry = offset + value_len_slots; } // update the last written entry to keep the smallest value if(offset < page_cache->first_written_entry) { page_cache->first_written_entry = offset; } // update the entry memcpy(&page_cache->buffer[offset], value, value_len); // move at the head of the MRU journal_cjf_page_cache_remove_from_mru(page_cache); journal_cjf_page_cache_add_to_mru(page_cache); group_mutex_unlock(&page_cache_mtx, GROUP_MUTEX_WRITE); } static void journal_cjf_page_cache_read(file_pool_file_t file, u64 file_offset, s16 offset, void *value, u32 value_len) { log_cjf_page_debug("cjf: %s: reading slot %i from page at offset %llu", file_pool_filename(file), offset, file_offset); group_mutex_lock(&page_cache_mtx, GROUP_MUTEX_WRITE); // get or create a node for the fd journal_cjf_page_cache_item *page_cache = journal_cjf_page_cache_get_for_rw(file, file_offset); yassert(offset + value_len <= CJF_PAGE_SIZE_IN_BYTE); memcpy(value, &page_cache->buffer[offset], value_len); // move at the head of the MRU journal_cjf_page_cache_remove_from_mru(page_cache); journal_cjf_page_cache_add_to_mru(page_cache); group_mutex_unlock(&page_cache_mtx, GROUP_MUTEX_WRITE); } /** * @param file * @param file_offset * @param offset in slot size units (8 bytes) * @param value */ void journal_cjf_page_cache_write_item(file_pool_file_t file, u64 file_offset, s16 offset, const journal_cjf_page_tbl_item *value) { yassert(file_offset >= CJF_HEADER_SIZE); log_cjf_page_debug("cjf: %s: %lli=%llx [ %i ] write {%08x,%08x}", file_pool_filename(file), file_offset, file_offset, offset, value->ends_with_serial, value->stream_file_offset); journal_cjf_page_cache_write(file, file_offset, offset + CJF_SECTION_INDEX_SLOT_HEAD_SLOT, value, sizeof(journal_cjf_page_tbl_item)); } void journal_cjf_page_cache_read_item(file_pool_file_t file, u64 file_offset, s16 offset, journal_cjf_page_tbl_item *value) { yassert(file_offset >= CJF_HEADER_SIZE); journal_cjf_page_cache_read(file, file_offset, offset + CJF_SECTION_INDEX_SLOT_HEAD_SLOT, value, sizeof(journal_cjf_page_tbl_item)); log_cjf_page_debug("cjf: %s: %lli=%llx [ %i ] read {%08x,%08x}", file_pool_filename(file), file_offset, file_offset, offset, value->ends_with_serial, value->stream_file_offset); } void journal_cjf_page_cache_write_header(file_pool_file_t file, u64 file_offset, const journal_cjf_page_tbl_header *value) { yassert(file_offset >= CJF_HEADER_SIZE); yassert(value->count <= value->size); yassert(((value->count <= value->size) && (value->next_page_offset < file_offset)) || (value->next_page_offset > file_offset) || (value->next_page_offset == 0)); yassert(value->stream_end_offset != 0); log_cjf_page_debug("cjf: %s: %lli=%llx update header {%08x,%3d,%3d,%08x}", file_pool_filename(file), file_offset, file_offset, value->next_page_offset, value->count, value->size, value->stream_end_offset); journal_cjf_page_cache_write(file, file_offset, 0, value, CJF_SECTION_INDEX_SLOT_HEAD); } void journal_cjf_page_cache_write_new_header(file_pool_file_t file, u64 file_offset) { static const journal_cjf_page_tbl_header new_page_header = PAGE_INITIALIZER; static const journal_cjf_page_tbl_item empty_item = {0,0}; const journal_cjf_page_tbl_header *value = &new_page_header; yassert(file_offset >= CJF_HEADER_SIZE); yassert(value->count <= value->size); yassert(((value->count <= value->size) && (value->next_page_offset < file_offset)) || (value->next_page_offset > file_offset) || (value->next_page_offset == 0)); log_cjf_page_debug("cjf: %s: %lli=%llx write header {%08x,%3d,%3d,%08x}", file_pool_filename(file), file_offset, file_offset, value->next_page_offset, value->count, value->size, value->stream_end_offset); journal_cjf_page_cache_write(file, file_offset, 0, value, CJF_SECTION_INDEX_SLOT_HEAD); for(int i = 0; i < CJF_SECTION_INDEX_SLOT_COUNT; ++i) { journal_cjf_page_cache_write_item(file, file_offset, i, &empty_item); } } void journal_cjf_page_cache_read_header(file_pool_file_t file, u64 file_offset, journal_cjf_page_tbl_header *value) { yassert(file_offset >= CJF_HEADER_SIZE); journal_cjf_page_cache_read(file, file_offset, 0, value, CJF_SECTION_INDEX_SLOT_HEAD); log_cjf_page_debug("cjf: %s: %lli=%llx read header {%08x,%3d,%3d,%08x}", file_pool_filename(file), file_offset, file_offset, value->next_page_offset, value->count, value->size, value->stream_end_offset); } static void journal_cjf_page_cache_items_flush(u64_set *page_cache_set) { yassert(group_mutex_islocked(&page_cache_mtx)); size_t here; file_pool_file_t file = NULL; u64_set_iterator iter; u64_set_iterator_init(page_cache_set, &iter); while(u64_set_iterator_hasnext(&iter)) { u64_node *file_offset_node = u64_set_iterator_next_node(&iter); journal_cjf_page_cache_item *page_cache = (journal_cjf_page_cache_item*)file_offset_node->value; if(page_cache->first_written_entry <= page_cache->last_written_entry) { if(file == NULL) { file = page_cache->file; yassert(file != NULL); file_pool_tell(file, &here); // can only fail if &here is NULL } yassert(file == page_cache->file); journal_cjf_page_cache_item_flush_internal(page_cache); // do not move in the MRU : it will naturally fall down if not used anymore // (yup, nothing to do) } } if(file != NULL) { file_pool_seek(file, here, SEEK_SET); } } static void journal_cjf_page_cache_items_close(u64_set *page_cache_set) { yassert(group_mutex_islocked(&page_cache_mtx)); /* list_sl_s delete_list; list_sl_init(&delete_list); */ size_t here; file_pool_file_t file = NULL; u64_set_iterator iter; u64_set_iterator_init(page_cache_set, &iter); while(u64_set_iterator_hasnext(&iter)) { u64_node *file_offset_node = u64_set_iterator_next_node(&iter); journal_cjf_page_cache_item *page_cache = (journal_cjf_page_cache_item*)file_offset_node->value; if(page_cache->first_written_entry <= page_cache->last_written_entry) // page needs to be flushed ? { if(file == NULL) { file = page_cache->file; yassert(file != NULL); file_pool_tell(file, &here); // remember the position } yassert(file == page_cache->file); journal_cjf_page_cache_item_flush_internal(page_cache); /* // delete the item list_sl_push(&delete_list, page_cache); */ file_offset_node->value = NULL; } journal_cjf_page_cache_remove_from_mru(page_cache); journal_cjf_page_cache_free(page_cache); } if(file != NULL) { file_pool_seek(file, here, SEEK_SET); // go back to the position // delete pages /* journal_cjf_page_cache_item *page_cache; while((page_cache = (journal_cjf_page_cache_item*)list_sl_pop(&delete_list)) != NULL) { journal_cjf_page_cache_remove_from_mru(page_cache); journal_cjf_page_cache_free(page_cache); } */ } u64_set_destroy(page_cache_set); } void journal_cjf_page_cache_flush(file_pool_file_t file) { group_mutex_lock(&page_cache_mtx, GROUP_MUTEX_WRITE); u64_set* page_cache_set = journal_cjf_page_cache_set_from_file(file); if(page_cache_set != NULL) { journal_cjf_page_cache_items_flush(page_cache_set); } else { log_warn("cjf: %s: is not cached", file_pool_filename(file)); } group_mutex_unlock(&page_cache_mtx, GROUP_MUTEX_WRITE); } void journal_cjf_page_cache_flush_page(file_pool_file_t file, u64 file_offset) { group_mutex_lock(&page_cache_mtx, GROUP_MUTEX_WRITE); journal_cjf_page_cache_item *page_cache = journal_cjf_page_cache_from_file(file, file_offset); if(page_cache != NULL) { journal_cjf_page_cache_item_flush(page_cache); } group_mutex_unlock(&page_cache_mtx, GROUP_MUTEX_WRITE); } void journal_cjf_page_cache_clear(file_pool_file_t file, u64 file_offset) { group_mutex_lock(&page_cache_mtx, GROUP_MUTEX_WRITE); journal_cjf_page_cache_delete_from_file_and_offset(file, file_offset); group_mutex_unlock(&page_cache_mtx, GROUP_MUTEX_WRITE); } void journal_cjf_page_cache_close(file_pool_file_t file) { group_mutex_lock(&page_cache_mtx, GROUP_MUTEX_WRITE); u64_set *page_cache_set = journal_cjf_page_cache_set_from_file(file); if(page_cache_set != NULL) { // destroy the u64_set content journal_cjf_page_cache_items_close(page_cache_set); // delete the file_node ptr_set_delete(&page_cache_item_by_file, file); } group_mutex_unlock(&page_cache_mtx, GROUP_MUTEX_WRITE); } static void journal_cjf_page_cache_finalize_cb(ptr_node *file_node) { u64_set *page_cache_set = (u64_set*)&file_node->value; journal_cjf_page_cache_items_close(page_cache_set); } void journal_cjf_page_cache_finalize() { group_mutex_write_lock(&page_cache_mtx); ptr_set_callback_and_destroy(&page_cache_item_by_file, journal_cjf_page_cache_finalize_cb); journal_cjf_page_mru_clear(); group_mutex_write_unlock(&page_cache_mtx); } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/journal-cjf-page-output-stream.c0000644000000000000000000000013214505005531025103 xustar000000000000000030 mtime=1695812441.717971805 30 atime=1695812445.801030282 30 ctime=1695812495.073735966 yadifa-2.6.5-11201/lib/dnsdb/src/journal-cjf-page-output-stream.c0000664000374500037450000003416714505005531025060 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #define JOURNAL_CJF_BASE 1 #include "dnsdb/dnsdb-config.h" #define ZDB_JOURNAL_CODE 1 #include "dnsdb/journal.h" #if JOURNAL_CJF_ENABLED #include #include #include "dnsdb/journal-cjf-page.h" #include "dnsdb/journal-cjf-idxt.h" #include "dnsdb/journal-cjf-page-cache.h" #include "dnsdb/zdb_utils.h" #define JCJFPOSD_TAG 0x44534f50464a434a struct journal_cjf_page_output_stream_data { output_stream filtered; journal_cjf *jnl; u32 serial_from; u32 serial_to; u32 soa_to_offset; u32 start_offset; u32 size; u8 flags; }; static ya_result journal_cjf_page_output_stream_write(output_stream* stream, const u8* buffer, u32 len); static ya_result journal_cjf_page_output_stream_flush(output_stream* stream); static void journal_cjf_page_output_stream_close(output_stream *stream); static const output_stream_vtbl journal_cjf_page_output_stream_vtbl = { journal_cjf_page_output_stream_write, journal_cjf_page_output_stream_flush, journal_cjf_page_output_stream_close, "journal_cjf_page_output_stream", }; typedef struct journal_cjf_page_output_stream_data journal_cjf_page_output_stream_data; static ya_result journal_cjf_page_output_stream_write(output_stream* stream, const u8* buffer, u32 len) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; ya_result ret = output_stream_write(&data->filtered, buffer, len); if(ISOK(ret)) { data->size += ret; } return ret; } static ya_result journal_cjf_page_output_stream_flush(output_stream* stream) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; ya_result ret = output_stream_flush(&data->filtered); return ret; } /** * * * * @param jnl the journal * @param os the current output for the records (SOA --- SOA +++) * @param size amount of bytes taken by the records * @param last_serial (the one of the SOA+++) */ void journal_cjf_page_output_stream_next(output_stream *stream) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; journal_cjf *jnl = data->jnl; // if the stream is not empty if(data->size > 0) { yassert(data->flags == 7); log_debug2("cjf: updating PAGE stream of size %u, ending at position %u (%08x), with serial %u", data->size, jnl->last_page.records_limit + data->size, jnl->last_page.records_limit + data->size, data->serial_to); journal_cjf_page_tbl_item item; journal_cjf_page_tbl_header head; item.ends_with_serial = data->serial_to; item.stream_file_offset = jnl->last_page.records_limit; // CFJ_PAGE_CACHE -> log_debug3("cjf: updating PAGE item at %u[(1 + %u) * 8]", jnl->last_page.file_offset, jnl->last_page.count); journal_cjf_page_cache_read_header(jnl->file, jnl->last_page.file_offset, &head); head.stream_end_offset = item.stream_file_offset + data->size; head.count = jnl->last_page.count + 1; journal_cjf_page_cache_write_header(jnl->file, jnl->last_page.file_offset, &head); journal_cjf_page_cache_write_item(jnl->file, jnl->last_page.file_offset, jnl->last_page.count, &item); // CFJ_PAGE_CACHE <- if(jnl->last_page.count == 0) { jnl->last_page.serial_start = data->serial_from; } jnl->last_page.serial_end = data->serial_to; journal_cjf_idxt_update_last_serial(jnl, data->serial_to); jnl->serial_end = data->serial_to; jnl->last_page.records_limit += data->size; jnl->last_page.count = head.count; jnl->last_soa_offset = data->soa_to_offset; if(journal_cjf_isempty(jnl)) { jnl->serial_begin = data->serial_from; } jnl->serial_end = data->serial_to; journal_cjf_set_dirty(jnl); journal_cjf_clear_empty(jnl); // reset the stream data data->start_offset += data->size; data->size = 0; data->serial_from = data->serial_to; data->soa_to_offset = 0; data->flags = 1; log_debug_jnl(jnl, "cjf: journal_cjf_page_next_output_stream: AFTER"); } else { log_debug2("cjf: PAGE stream is empty"); } } /** * * * * @param jnl the journal * @param os the current output for the records (SOA --- SOA +++) * @param size amount of bytes taken by the records * @param last_serial (the one of the SOA+++) */ static void journal_cjf_page_output_stream_close(output_stream *stream) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; log_debug2("cjf: finishing PAGE stream"); if(stream->vtbl == &journal_cjf_page_output_stream_vtbl) { // the stream must be empty (else we are losing stuff) yassert(data->size == 0); journal_cjf *jnl = data->jnl; if(is_buffer_output_stream(&data->filtered)) { log_debug3("cjf: flushing PAGE item"); journal_cjf_page_output_stream_flush(stream); file_pool_file_output_stream_detach(buffer_output_stream_get_filtered(&data->filtered)); output_stream_close(&data->filtered); } else { log_debug3("cjf: no PAGE item to flush"); } journal_cjf_page_cache_flush(jnl->file); log_debug3("cjf: closing PAGE item"); ZFREE(data, journal_cjf_page_output_stream_data); output_stream_set_void(stream); } else { log_debug3("cjf: there are no opened PAGE stream to close"); } } /** * * Closes the stream and do not update the current PAGE * * @param jnl * @param os */ void journal_cjf_page_output_stream_cancel(output_stream *stream) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; if(stream->vtbl == &journal_cjf_page_output_stream_vtbl) { log_debug2("cjf: cancelling PAGE stream, ending at position %u (%08x)", data->jnl->last_page.records_limit, data->jnl->last_page.records_limit); journal_cjf_page_output_stream_flush(stream); file_pool_file_output_stream_detach(buffer_output_stream_get_filtered(&data->filtered)); output_stream_close(&data->filtered); output_stream_set_void(&data->filtered); data->size = 0; data->serial_from = 0; data->serial_to = 0; data->soa_to_offset = 0; data->flags = 0; log_debug3("cjf: cancelling PAGE item"); log_debug_jnl(data->jnl, "cjf: journal_cjf_page_cancel_output_stream: AFTER"); } else { log_debug3("cjf: there are no opened PAGE stream to cancel"); } } void journal_cjf_page_output_stream_set_serial_from(output_stream *stream, u32 serial) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; data->serial_from = serial; data->flags |= 1; } void journal_cjf_page_output_stream_set_serial_to(output_stream *stream, u32 serial) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; data->serial_to = serial; data->flags |= 2; } void journal_cjf_page_output_stream_set_soa_to_offset(output_stream *stream, u32 offset) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; data->soa_to_offset = offset; data->flags |= 4; } ya_result journal_cfj_page_output_stream_write_resource_record(output_stream *stream, dns_resource_record *rr) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; yassert(dnsname_is_subdomain(rr->name, data->jnl->origin)); ya_result ret; if(rr->tctr.qtype == TYPE_SOA) { u32 serial; if(FAIL(ret = rr_soa_get_serial(rr->rdata, rr->rdata_size, &serial))) { return ret; } if(data->size == 0) { if((data->flags & 1) == 1) { // test that it matches the from } journal_cjf_page_output_stream_set_serial_from(stream, serial); } else { yassert((data->flags & 2) == 0); journal_cjf_page_output_stream_set_serial_to(stream, serial); journal_cjf_page_output_stream_set_soa_to_offset(stream, data->start_offset + data->size); } } ret = dns_resource_record_write(rr, stream); return ret; } u32 journal_cjf_page_output_stream_reopen(output_stream *out_os, journal_cjf *jnl) { // get the current page if((jnl->last_page.count == 0) && (jnl->last_page.file_offset == CJF_HEADER_SIZE) && (jnl->first_page_offset == CJF_HEADER_SIZE)) { // CFJ_PAGE_CACHE -> journal_cjf_page_cache_write_new_header(jnl->file, jnl->last_page.file_offset); // CFJ_PAGE_CACHE <- log_debug_jnl(jnl, "journal_cjf_page_open_next_output_stream: INIT"); } if(out_os->vtbl == &journal_cjf_page_output_stream_vtbl) { if(journal_cjf_page_is_full(jnl)) { // if there no room left, append a new page, it becomes the current pag // flush the stream journal_cjf_page_output_stream_flush(out_os); journal_cjf_idxt_append_page(jnl); // reposition the stream if(file_pool_seek(jnl->file, jnl->last_page.records_limit, SEEK_SET) < 0) { log_err("cjf: %{dnsname}: cannot move into journal at new page (file=%p, pos=%llu): %r", jnl->origin, jnl->file, jnl->last_page.records_limit, ERRNO_ERROR); logger_flush(); return ERRNO_ERROR; } } log_debug2("cjf: continuing next PAGE stream at position %u (%08x)", jnl->last_page.records_limit, jnl->last_page.records_limit); #ifndef NDEBUG journal_cjf_page_output_stream_data *data = (journal_cjf_page_output_stream_data*)out_os->data; yassert(data->size == 0); #endif // NDEBUG } else { if(journal_cjf_page_is_full(jnl)) { // if there no room left, append a new page, it becomes the current pag journal_cjf_idxt_append_page(jnl); } log_debug2("cjf: opening next PAGE stream at position %u (%08x)", jnl->last_page.records_limit, jnl->last_page.records_limit); if(file_pool_seek(jnl->file, jnl->last_page.records_limit, SEEK_SET) < 0) { log_err("cjf: %{dnsname}: cannot move into journal at next page (file=%p, pos=%llu): %r", jnl->origin, jnl->file, jnl->last_page.records_limit, ERRNO_ERROR); logger_flush(); return ERRNO_ERROR; } journal_cjf_page_output_stream_data *data; ZALLOC_OBJECT_OR_DIE( data, journal_cjf_page_output_stream_data, JCJFPOSD_TAG); ZEROMEMORY(data, sizeof(journal_cjf_page_output_stream_data)); // false positive: data cannot be NULL file_pool_file_output_stream_init(&data->filtered, jnl->file); // this initialises the stream file_output_stream_set_full_writes(&data->filtered, TRUE); // this makes the stream "write fully" buffer_output_stream_init(&data->filtered, &data->filtered, 512); data->jnl = jnl; data->start_offset = jnl->last_page.records_limit; out_os->data = data; out_os->vtbl = &journal_cjf_page_output_stream_vtbl; } return jnl->last_page.records_limit; } u32 journal_cfj_page_output_stream_get_size(output_stream *stream) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; return data->size; } u32 journal_cfj_page_output_stream_get_start_offset(output_stream *stream) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; return data->start_offset; } u32 journal_cfj_page_output_stream_get_current_offset(output_stream *stream) { journal_cjf_page_output_stream_data* data = (journal_cjf_page_output_stream_data*)stream->data; return data->start_offset + data->size; } #endif yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/journal-cjf-ro.c0000644000000000000000000000013114505005531021757 xustar000000000000000029 mtime=1695812441.72397189 30 atime=1695812445.801030282 30 ctime=1695812495.076736009 yadifa-2.6.5-11201/lib/dnsdb/src/journal-cjf-ro.c0000664000374500037450000016502614505005531021734 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ /** @brief Function ... * * ... * * @param ... * * @retval OK * @retval NOK */ #if !JOURNAL_CJF_ENABLED #include "dnsdb/dnsdb-config.h" #define ZDB_JOURNAL_CODE 1 #include "dnsdb/journal.h" #if !JOURNAL_CJF_ENABLED #define JOURNAL_CJF_BASE 1 #include "dnsdb/journal-cjf-page.h" #include "dnsdb/journal-cjf-page-cache.h" #include "dnsdb/journal-cjf-page-output-stream.h" #include "dnsdb/journal-cjf-idxt.h" #include "dnsdb/journal-cjf-common.h" #include "dnsdb/journal-cjf.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dnsdb/zdb_error.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/journal.h" #include "dnsdb/zdb_types.h" #include "dnsdb/xfr_copy.h" #include "dnsdb/zdb-zone-path-provider.h" #include "dnsdb/zdb_zone.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define DEBUG_JOURNAL 0 #if !DEBUG #undef DEBUG_JOURNAL #define DEBUG_JOURNAL 0 #endif #define JOURNAL_FORMAT_NAME "cyclic" #define VERSION_HI 0 #define VERSION_LO 1 #define JOURNAL_CLASS_NAME "journal_cjf" #define JNL_LOCK_NONE 0 #define JNL_LOCK_READ 1 #define JNL_LOCK_WRITE 2 #define CJF_EXT "cjf" #define CJF_EXT_STRLEN 3 #define CJF_IDXT_SLOT_SIZE 8 #define SOA_RDATA_SIZE_MAX 532 #define DO_SYNC 1 #define JRNLCJF_TAG 0x58494c4e524a /** * Two steps means that the journal is written in two passes. * Pass 1 gathers a full page from input and validates it. * Pass 2 stores it to the journal file. */ #define CJF_USE_TWO_STEPS 1 /* * Contains the journal (almost: not the matching start and end SOA) */ #define CJF_WIRE_FILE_FORMAT "%s/%{dnsname}." CJF_EXT #define FIRST_FROM_END (CJF_EXT_STRLEN + (1 + 8 + 1 + 8)) #define LAST_FROM_END (CJF_EXT_STRLEN + (1 + 8)) #define CJF_SECTION_INDEX_SLOT_HEAD 16 #define CJF_SECTION_INDEX_SLOT_SIZE 8 #define CJF_SECTION_INDEX_SLOT_COUNT 510 #define CJF_SECTION_INDEX_SIZE (CJF_SECTION_INDEX_SLOT_HEAD + CJF_SECTION_INDEX_SLOT_SIZE * CJF_SECTION_INDEX_SLOT_COUNT) // 4KB #define CJF_PAGE_SIZE_IN_BYTE (CJF_SECTION_INDEX_SLOT_HEAD + (CJF_SECTION_INDEX_SLOT_COUNT * CJF_SECTION_INDEX_SLOT_SIZE)) #define CJF_PAGE_ARBITRARY_UPDATE_SIZE 512 #define CJF_SECTION_INDEX_SLOT_HEAD_SLOT (CJF_SECTION_INDEX_SLOT_HEAD / CJF_SECTION_INDEX_SLOT_SIZE) /******************************************************************************* * * JNL (HEADER) ---> IDXT * | | * +------+------+---+ * | | | * v v v * PAGE -> PAGE -> PAGE * | | | * v v v * IXFRs IXFRs IXFRs * ******************************************************************************/ /* * MAGIC 'JNL' + Version 0 * Serial begin * Serial end * Begin Index Offset * Table Index Offset */ /** * There is a need of lockable 4K pages in an MRU that points back to their user * That's where the PAGE will be stored * I'm not sure of what the ratio between allowed FDs and allowed PAGE pages should be. */ static shared_group_shared_mutex_t journal_shared_mtx; static bool journal_initialized = FALSE; static file_pool_t journal_file_pool = 0; void log_debug_jnl(journal_cjf *jnl, const char *text) { log_debug4("cjf-ro: %s,%p: %s: header SN=[%08x; %08x] F=%08x L=%08x dirty=%i empty=%i", jnl->journal_file_name, jnl->file, text, jnl->serial_begin, jnl->serial_end, jnl->first_page_offset, jnl->page_table_file_offset, journal_cjf_is_dirty(jnl), journal_cjf_isempty(jnl)); s16 n = jnl->idxt.count; if(jnl->last_page.count == 0) { n--; } log_debug4("cjf-ro: %s,%p: %s: idxt %3hi/%3hi [%3hi] dirty=%i marked=%i", jnl->journal_file_name, jnl->file, text, jnl->idxt.count, jnl->idxt.size, jnl->idxt.first, (jnl->idxt.dirty)?1:0, (jnl->idxt.marked)?1:0); log_debug4("cjf-ro: %s,%p: %s: page: SN=[%08x; %08x] count=%3u size=%3u at=%08x next=%08x ... limit=%08x", jnl->journal_file_name, jnl->file, text, jnl->last_page.serial_start, jnl->last_page.serial_end, jnl->last_page.count,jnl->last_page.size, jnl->last_page.file_offset, jnl->last_page.records_limit, jnl->last_page.file_offset_limit); for(s16 idx = 0; idx < n; idx++) { journal_cjf_idxt_tbl_item *item = &jnl->idxt.entries[(jnl->idxt.first + idx) % jnl->idxt.size]; log_debug4("cjf-ro: %s,%p: %s: idxt[%3i] = %08x %08x", jnl->journal_file_name, jnl->file, text, idx, item->last_serial, item->file_offset); } if(jnl->last_page.count == 0) { journal_cjf_idxt_tbl_item *item = &jnl->idxt.entries[(jnl->idxt.first + n) % jnl->idxt.size]; log_debug4("cjf-ro: %s,%p: %s: idxt[%3i] = [empty] %08x", jnl->journal_file_name, jnl->file, text, n, item->file_offset); } } static void journal_cjf_ro_readlock(journal_cjf *jnl) { #if DEBUG log_debug4("cjf-ro: %s,%p: read lock", jnl->journal_file_name, jnl->file); #endif shared_group_mutex_lock(&jnl->mtx, GROUP_MUTEX_READ); } static void journal_cjf_ro_readunlock(journal_cjf *jnl) { #if DEBUG log_debug4("cjf-ro: %s,%p: read unlock", jnl->journal_file_name, jnl->file); #endif shared_group_mutex_unlock(&jnl->mtx, GROUP_MUTEX_READ); } bool journal_cjf_ro_isreadlocked(journal_cjf *jnl) { bool ret = shared_group_mutex_islocked_by(&jnl->mtx, GROUP_MUTEX_READ); return ret; } bool journal_cjf_ro_iswritelocked(journal_cjf *jnl) { bool ret = shared_group_mutex_islocked_by(&jnl->mtx, GROUP_MUTEX_WRITE); return ret; } void journal_cjf_ro_release(journal_cjf *jnl) { journal_release((journal*)jnl); } static journal_cjf* journal_cjf_ro_alloc_default(const u8 *origin, const char *filename); static const journal_cjf_idxt_tbl_item* journal_cjf_ro_idxt_get_entry(const journal_cjf *jnl, s16 index) { yassert(index >= 0);yassert(jnl->idxt.first >= 0); journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + index) % jnl->idxt.size]; return entry; } static u32 journal_cjf_ro_idxt_get_file_offset(const journal_cjf *jnl, s16 index) { u32 file_offset = journal_cjf_ro_idxt_get_entry(jnl, index)->file_offset; return file_offset; } static void journal_cjf_ro_page_cache_read_header(file_pool_file_t file, u64 file_offset, journal_cjf_page_tbl_header *value) { yassert(file_offset >= CJF_HEADER_SIZE); size_t current_position; file_pool_tell(file, ¤t_position); file_pool_seek(file, file_offset, SEEK_SET); file_pool_readfully(file, value, offsetof(journal_cjf_page_tbl_header, __end_of_struct__)); file_pool_seek(file, current_position, SEEK_SET); log_debug("cjf: %s: %lli=%llx read header {%08x,%3d,%3d,%08x}", file_pool_filename(file), file_offset, file_offset, value->next_page_offset, value->count, value->size, value->stream_end_offset); } static u32 journal_cjf_ro_idxt_get_page_offset(const journal_cjf *jnl, int idx) { journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + idx) % jnl->idxt.size]; return entry->file_offset; } static u32 journal_cjf_ro_idxt_get_page_serial_from_index(const journal_cjf *jnl, int idx) { if(idx > 0) { journal_cjf_idxt_tbl_item *prev_entry; prev_entry = &jnl->idxt.entries[(jnl->idxt.first + idx - 1) % jnl->idxt.size]; return prev_entry->last_serial; } else { return jnl->serial_begin; } } ya_result journal_cjf_ro_idxt_get_page_offset_from_serial(const journal_cjf *jnl, u32 serial, u32 *file_offset) { u32 prev_serial = jnl->serial_begin; // ensure the journal starts at least from the serial we are looking for if(serial_lt(serial, prev_serial)) { return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } s16 n = jnl->idxt.count; for(s16 i = 0; i < n; i++) { journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + i) % jnl->idxt.size]; // entry->last_serial is the last_serial TO, so the start of the next page if(serial_lt(serial, entry->last_serial)) { log_debug1("journal_cjf_idxt_get_page_index_from_serial(%s, %d) returning %i (%i -> %i)", jnl->journal_file_name, serial, i, prev_serial, entry->last_serial); if(file_offset != NULL) { *file_offset = entry->file_offset; } return i; } prev_serial = entry->last_serial; } // too far ... return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } /* scans all the PAGE entries from the IDXT and get the one that contains the serial */ static ya_result journal_cjf_ro_idxt_get_page_index_from_serial(const journal_cjf *jnl, u32 serial) { u32 prev = jnl->serial_begin; if(serial_lt(serial, prev)) { return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } u32 prev_serial = jnl->serial_begin; s16 n = jnl->idxt.count; for(s16 i = 0; i < n; i++) { journal_cjf_idxt_tbl_item *entry; entry = &jnl->idxt.entries[(jnl->idxt.first + i) % jnl->idxt.size]; // the last serial of an entry is the one of the last SOA added on it // we want to start after that one if(serial_lt(serial, entry->last_serial)) { log_debug1("journal_cjf_idxt_get_page_index_from_serial(%s, %d) returning %i (%i -> %i)", jnl->journal_file_name, serial, i, prev_serial, entry->last_serial); return i; } prev_serial = entry->last_serial; } return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } /** * * Does NOT set the fd field in jnl * MUST return -1 in case of error * * @param jnl * @param create * @return the file descriptor or an error code */ static int journal_cjf_ro_init_from_file(journal_cjf **jnlp, const u8 *origin, const char *filename, bool create) { (void)create; log_debug3("cjf-ro: %{dnsname}: opening %s", origin, filename); int flags = O_RDWR|O_CLOEXEC; #ifdef O_NOATIME flags |= O_NOATIME; #endif file_pool_file_t file; ya_result ret; bool bad_journal = FALSE; cjf_header hdr; file = file_pool_open_ex(journal_file_pool, filename, flags, 0660); if(file == NULL) { ret = ERRNO_ERROR; log_debug3("cjf-ro: %{dnsname}: failed to open %s: %r", origin, filename, ret); return ret; } s64 size = filesize(filename); if(size < CJF_HEADER_SIZE) { bad_journal = TRUE; } // look if the journal makes sense if(FAIL(ret = file_pool_readfully(file, &hdr, sizeof(hdr)))) { ret = ERRNO_ERROR; log_err("cjf-ro: %{dnsname}: could not read header on %s: %r", origin, filename, ret); bad_journal = TRUE; } else if((hdr.magic_plus_version != CJF_CJF0_MAGIC) || ((hdr.flags & JOURNAL_CFJ_FLAGS_MY_ENDIAN) == 0) ) { if(hdr.magic_plus_version != CJF_CJF0_MAGIC) { log_err("cjf-ro: %{dnsname}: wrong magic on %s", origin, filename); } else { log_err("cjf-ro: %{dnsname}: wrong endian on %s", origin, filename); } bad_journal = TRUE; } else if(hdr.first_index_offset == 0) { bad_journal = TRUE; } if(!bad_journal) { // it does makes sense // note: DO NOT jnl->file = fd; journal_cjf *jnl = journal_cjf_ro_alloc_default(origin, filename); jnl->flags = hdr.flags; jnl->serial_begin = hdr.serial_begin; jnl->serial_end = hdr.serial_end; jnl->first_page_offset = hdr.first_index_offset; jnl->page_table_file_offset = hdr.table_index_offset; jnl->last_soa_offset = hdr.last_soa_offset; jnl->last_page.serial_end = jnl->serial_end; jnl->last_page.records_limit = hdr.last_page_offset_next; jnl->file = file; log_debug("cjf-ro: %{dnsname}: journal expected to cover serials from %i to %i", jnl->origin, hdr.serial_begin, hdr.serial_end); log_debug("cjf-ro: %{dnsname}: journal table index located at %x%s", jnl->origin, hdr.table_index_offset, (hdr.table_index_offset!=0)?"":", which means it has not been closed properly"); *jnlp = jnl; return SUCCESS; } else { // the journal content is unexpected file_pool_close(file); file = NULL; char broken_file_path[PATH_MAX]; if(ISOK(ret = snformat(broken_file_path, sizeof(broken_file_path),"%s.bad-journal", filename))) { // remove previous bad-journal if any if(unlink(broken_file_path) < 0) { ret = ERRNO_ERROR; if(ret == MAKE_ERRNO_ERROR(ENOENT)) { ret = SUCCESS; } else { log_err("cjf-ro: %{dnsname}: unable to delete previous bad journal %s: %r", origin, broken_file_path, ret); } } // successfully handled the previous .bad-journal if(ISOK(ret)) { // rename the journal into bad-journal if(rename(filename, broken_file_path) < 0) { ret = ERRNO_ERROR; log_err("cjf-ro: %{dnsname}: unable to rename %s into %s: %r", origin, filename, broken_file_path, ret); if(unlink(filename) < 0) { ret = ERRNO_ERROR; log_err("cjf-ro: %{dnsname}: unable to delete %s: %r", origin, filename, ret); } } ret = ZDB_ERROR_ICMTL_NOTFOUND; } } else { log_err("cjf-ro: %{dnsname}: %s is a bad journal, please remove it.", origin, filename); } } return ret; } /******************************************************************************* * * Index table handling functions * ******************************************************************************/ /*****************************************************************************/ static void journal_cjf_ro_readlock(journal_cjf *jnl); static void journal_cjf_ro_readunlock(journal_cjf *jnl); static const char * journal_cjf_ro_get_format_name() { return JOURNAL_FORMAT_NAME; } static u32 journal_cjf_ro_get_format_version() { return VERSION_U32(VERSION_HI,VERSION_LO); } static ya_result journal_cjf_ro_read_soa_record(dns_resource_record *rr, input_stream *ixfr_wire_is) { ya_result return_value; if((return_value = dns_resource_record_read(rr, ixfr_wire_is)) <= 0) { /* FAIL or EOF */ return return_value; } #if DEBUG rdata_desc rdatadesc = {rr->tctr.qtype, rr->rdata_size, rr->rdata}; log_debug("cjf-ro: %{dnsname} %{typerdatadesc}", rr->name, &rdatadesc); #endif if((rr->tctr.qtype != TYPE_SOA) || (rr->rdata_size > SOA_RDATA_SIZE_MAX)) { log_err("cjf-ro: expected SOA record but got %{dnstype} instead", &rr->tctr.qtype); return ZDB_JOURNAL_SOA_RECORD_EXPECTED; } return return_value; } struct journal_cjf_ro_read_ixfr_s { input_stream *ixfr_wire_is; output_stream baos; dns_resource_record rr; u32 serial_from; u32 serial_to; u32 size; bool eof; }; typedef struct journal_cjf_ro_read_ixfr_s journal_cjf_ro_read_ixfr_s; ya_result journal_cjf_ro_read_ixfr_init(journal_cjf_ro_read_ixfr_s *ixfrinc, input_stream *ixfr_wire_is) { ya_result ret; ixfrinc->ixfr_wire_is = ixfr_wire_is; bytearray_output_stream_init_ex(&ixfrinc->baos, NULL, 65536, BYTEARRAY_DYNAMIC); dns_resource_record_init(&ixfrinc->rr); ixfrinc->serial_from = 0; ixfrinc->serial_to = 0; ixfrinc->size = 0; ixfrinc->eof = FALSE; ret = journal_cjf_ro_read_soa_record(&ixfrinc->rr, ixfr_wire_is); #if DEBUG if(ISOK(ret)) { log_debug2("cjf-ro: ---: started with %{dnsrr}", &ixfrinc->rr); } #endif return ret; } void journal_cjf_ro_read_ixfr_finalize(journal_cjf_ro_read_ixfr_s *ixfrinc) { ixfrinc->ixfr_wire_is = NULL; dns_resource_record_clear(&ixfrinc->rr); output_stream_close(&ixfrinc->baos); ixfrinc->serial_from = 0; ixfrinc->serial_to = 0; ixfrinc->size = 0; } static ya_result journal_cjf_ro_append_ixfr_stream(journal *jh, input_stream *ixfr_wire_is) { (void)jh; (void)ixfr_wire_is; return CIRCULAR_FILE_FULL; } /****************************************************************************** * * Journal Input Stream * This one returns and IXFR stream * ******************************************************************************/ #define JCJFISDT_TAG 0x54445349464a434a struct journal_cjf_ro_input_stream_data { journal_cjf *jnl; file_pool_file_t file; u32 available; u32 serial_from; u32 page_next; // DEBUG u16 idxt_index; u16 idxt_size; u16 todo_soa_record_size; bool first_stream; u8* todo_soa_record; }; typedef struct journal_cjf_ro_input_stream_data journal_cjf_ro_input_stream_data; static void journal_cjf_ro_page_cache_read(file_pool_file_t file, u64 file_offset, s16 offset, void *value, u32 value_len) { yassert(file_offset >= CJF_HEADER_SIZE); size_t current_position; file_pool_tell(file, ¤t_position); file_pool_seek(file, file_offset + CJF_SECTION_INDEX_SLOT_SIZE * offset , SEEK_SET); file_pool_readfully(file, value, value_len); file_pool_seek(file, current_position, SEEK_SET); log_debug("cjf: %s: %lli=%llx read {%4d, %p,%08x}", file_pool_filename(file), file_offset, file_offset, offset, value, value_len); } static void journal_cjf_ro_page_cache_read_item(file_pool_file_t file, u64 file_offset, s16 offset, journal_cjf_page_tbl_item *value) { yassert(file_offset >= CJF_HEADER_SIZE); journal_cjf_ro_page_cache_read(file, file_offset, offset + CJF_SECTION_INDEX_SLOT_HEAD_SLOT, value, sizeof(journal_cjf_page_tbl_item)); } /** * Search from the offset of the stream for a serial, looking in an PAGE referenced by index * * @param jnl * @param idx * @param serial * @param out_offset * @return */ static ya_result journal_cjf_ro_page_get_stream_offset_from_serial(journal_cjf *jnl, int idx, u32 serial, u32 *out_offset) { u32 file_offset = journal_cjf_ro_idxt_get_page_offset(jnl, idx); journal_cjf_page_tbl_item value; if(journal_cjf_ro_idxt_get_page_serial_from_index(jnl, idx) == serial) { // the first one journal_cjf_ro_page_cache_read_item(jnl->file, file_offset, 0, &value); *out_offset = value.stream_file_offset; return SUCCESS; } // read how much items are in the PAGE journal_cjf_page_tbl_header hdr; journal_cjf_ro_page_cache_read_header(jnl->file, file_offset, &hdr); if(hdr.magic == CJF_PAGE_MAGIC) { //for(int i = 1; i <= CJF_SECTION_INDEX_SLOT_COUNT - 1; i++) for(int i = 0; i < hdr.count - 1; i++) { journal_cjf_ro_page_cache_read_item(jnl->file, file_offset, i, &value); if(value.ends_with_serial == serial) { // we found the item that ends with the requested serial, // the next item is the one that starts from the requested serial journal_cjf_ro_page_cache_read_item(jnl->file, file_offset, i + 1, &value); *out_offset = value.stream_file_offset; return SUCCESS; } } //this is the wrong idx #endif } else { // invalid } return ERROR; } static ya_result journal_cjf_ro_input_stream_read(input_stream* stream, void *buffer_, u32 len) { journal_cjf_ro_input_stream_data *data = (journal_cjf_ro_input_stream_data*)stream->data; u8 *buffer = (u8*)buffer_; const u8 *base = buffer; const u8 *limit = &buffer[len]; intptr n; ya_result ret = 0; journal_cjf *jnl = data->jnl; log_debug("cjf-ro: %s,%p: input: reading %u/%u bytes, pos is %lli", jnl->journal_file_name, jnl->file, len, data->available, file_pool_seek(data->file, 0, SEEK_CUR)); // while there is still room in the output buffer while((n = limit - buffer) > 0) { // if there is no data ready on input, fetch some more if(data->available == 0) { // get the next one if(data->idxt_index == data->idxt_size) { // EOF : we were at the last index in the IDXT break; } // get the offset of the current PAGE table u32 page_offset = journal_cjf_ro_idxt_get_file_offset(data->jnl, data->idxt_index); u32 stream_offset; u32 stream_limit_offset; // look for the first SOA requested if(!data->first_stream) { // we are already streaming, the XFR stream starts at the end of the PAGE (4096 bytes until next version of the journal) stream_offset = page_offset + CJF_PAGE_SIZE_IN_BYTE; } else { // the starting stream offset is obtained through a bit more work if(FAIL(ret = journal_cjf_ro_page_get_stream_offset_from_serial(data->jnl, data->idxt_index, data->serial_from, &stream_offset))) { return ret; } data->first_stream = FALSE; } journal_cjf_page_tbl_header page_header; journal_cjf_ro_page_cache_read_header(data->jnl->file, page_offset, &page_header); if(page_header.count == 0) { // empty page, proably not flushed break; } stream_limit_offset = page_header.stream_end_offset; // we know where to start ... data->idxt_index++; (void)stream_limit_offset; #if DEBUG if(stream_limit_offset == 0) { log_err("impossible limit value read from the journal"); journal_cjf_ro_page_cache_read_header(data->jnl->file, page_offset, &page_header); } #endif yassert(stream_limit_offset != 0); yassert(stream_limit_offset > page_offset); data->available = page_header.stream_end_offset - stream_offset; data->page_next = page_header.next_page_offset; if(file_pool_seek(data->file, stream_offset, SEEK_SET) < 0) { return ERRNO_ERROR; } } n = MIN(n, data->available); if(FAIL(ret = file_pool_readfully(data->file, buffer, n))) { return ret; } data->available -= n; buffer += n; } return buffer - base; } static ya_result journal_cjf_ro_input_stream_skip(input_stream* is, u32 len) { u8 tmp[512]; journal_cjf_ro_input_stream_data *data = (journal_cjf_ro_input_stream_data*)is->data; journal_cjf *jnl = data->jnl; log_debug("cjf-ro: %s,%p: input: skipping %u bytes", jnl->journal_file_name, jnl->file, len); while(len > 0) { ya_result ret; u32 n = MIN(len, sizeof(tmp)); if(FAIL(ret = journal_cjf_ro_input_stream_read(is, tmp, n))) { return ret; } len -= n; } return len; } static void journal_cjf_ro_input_stream_close(input_stream* is) { journal_cjf_ro_input_stream_data *data = (journal_cjf_ro_input_stream_data*)is->data; log_debug("cjf-ro: %s,%p: input: close (%p)", data->jnl->journal_file_name, data->jnl->file, data->file); journal_cjf_ro_readunlock(data->jnl); data->jnl->_forget = TRUE; journal_cjf_ro_release(data->jnl); file_pool_close(data->file); ZFREE_OBJECT(data); input_stream_set_void(is); } static const input_stream_vtbl journal_cjf_ro_input_stream_vtbl = { journal_cjf_ro_input_stream_read, journal_cjf_ro_input_stream_skip, journal_cjf_ro_input_stream_close, "journal_cjf_ro_input_stream" }; /* * the last_soa_rr is used for IXFR transfers (it has to be a prefix & suffix to the returned stream) */ static ya_result journal_cjf_ro_get_ixfr_stream_at_serial(journal *jh, u32 serial_from, input_stream *out_input_stream, dns_resource_record *out_last_soa_rr) { journal_cjf *jnl = (journal_cjf*)jh; log_debug("cjf-ro: %s,%p: get IXFR stream at serial %i", jnl->journal_file_name, jnl->file, serial_from); journal_cjf_ro_readlock(jnl); if(serial_lt(serial_from, jnl->serial_begin) || serial_ge(serial_from, jnl->serial_end)) { if(serial_from == jnl->serial_end) { log_debug("cjf-ro: %s,%p: the journal ends at %i, returning empty stream", jnl->journal_file_name, jnl->file, serial_from); journal_cjf_ro_readunlock(jnl); empty_input_stream_init(out_input_stream); return SUCCESS; // 0 } else { log_debug("cjf-ro: %s,%p: the journal ends at %i, returning empty stream", jnl->journal_file_name, jnl->file, serial_from); journal_cjf_ro_readunlock(jnl); #if DEBUG logger_flush(); #endif return ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } } ya_result ret; dns_resource_record rr; dns_resource_record_init(&rr); // increment the reference count of the journal // lock the range in the file so it cannot be overwritten // create a stream that know where to start, where to end // it has to first send the last SOA // then to send the start // then to send the last SOA again if(FAIL(ret = journal_cjf_ro_idxt_get_page_index_from_serial(jnl, serial_from))) { journal_cjf_ro_readunlock(jnl); return ret; } yassert(ret < MAX_U16); u16 idxt_index = (u16)ret; journal_cjf_ro_input_stream_data *data; ZALLOC_OBJECT_OR_DIE(data, journal_cjf_ro_input_stream_data, JCJFISDT_TAG); journal_acquire((journal*)jnl); data->jnl = jnl; data->file = file_pool_open_ex(journal_file_pool, jnl->journal_file_name, O_RDONLY|O_CLOEXEC, 0660); if(data->file == NULL) { // the journal doess not exist (anymore ?) ZFREE_OBJECT(data); journal_cjf_ro_readunlock(jnl); journal_cjf_ro_release(jnl); return MAKE_ERRNO_ERROR(ENOENT); } data->serial_from = serial_from; if(out_last_soa_rr != NULL) { yassert(jnl->last_soa_offset != 0); // read the last SOA size_t from = ~0; file_pool_tell(data->file, &from); file_pool_seek(data->file, jnl->last_soa_offset, SEEK_SET); input_stream tmp; file_pool_file_input_stream_init(&tmp, data->file); ret = dns_resource_record_read(out_last_soa_rr, &tmp); file_pool_file_input_stream_detach(&tmp); file_pool_seek(data->file, from, SEEK_SET); if(FAIL(ret)) { journal_cjf_ro_readunlock(jnl); journal_cjf_ro_release(jnl); log_err("cjf-ro: %s,%p: unable to read the SOA for serial %u at position %u: %r", jnl->journal_file_name, jnl->file, serial_from, jnl->last_soa_offset, ret); ZFREE_OBJECT(data); return ret; } } data->idxt_index = idxt_index; data->idxt_size = jnl->idxt.count; data->available = 0; data->first_stream = TRUE; out_input_stream->data = data; out_input_stream->vtbl = &journal_cjf_ro_input_stream_vtbl; return ret; /* * In page_begin.file_offset, we get the first PAGE table * * That table may chain to a next PAGE, and so on and so forth * While this is happening, every stream between offsets: * * page_begin.file_offset + CJF_SECTION_INDEX_SIZE * * and * * @(page_begin.file_offset + 4) * * is to be sent by the stream * * When @(page_begin.file_offset + 4) is 0, it is the last PAGE * * Note that @(page_begin.file_offset + 4) is cached in the IDXT entries * * Every PAGE table but the last one has exactly CJF_SECTION_INDEX_SLOT_COUNT items * * jnl->page.count contains the count of items of the current (not full) PAGE * jnl->page.offset_next contains the supremum of input after the last PAGE * * This means a journal has to be fully initialised before being read (it was not the case for an IX file) * * The content of the PAGE itself is not required. Only the DNS part matters. * * All this also means a journal has to be flushed for its DNS on disk (since the file has to be opened separately because a cloned fd shares the file pointer) * * A range-locking mechanism is clearly needed. It should only be capable of locking up to two ranges (covers all cases). * * So here, in summary, return a stream that is linked to the journal * * It will start at offset: * * idxt[ret].file_offset + CJF_SECTION_INDEX_SIZE * * until: * * idxt[ret + 1].file_offset or page.offset_next * * and continue that way for every ret < idxt.count * */ } static ya_result journal_cjf_ro_get_first_serial(journal *jh, u32 *serial) { ya_result ret = UNEXPECTED_NULL_ARGUMENT_ERROR; journal_cjf *jnl = (journal_cjf*)jh; journal_cjf_ro_readlock(jnl); u32 value = jnl->serial_begin; if(serial != NULL) { *serial = value; ret = SUCCESS; } journal_cjf_ro_readunlock(jnl); log_debug("cjf-ro: %s,%p: get first serial: %i", jnl->journal_file_name, jnl->file, value); return ret; } static ya_result journal_cjf_ro_get_last_serial(journal *jh, u32 *serial) { ya_result ret = UNEXPECTED_NULL_ARGUMENT_ERROR; journal_cjf *jnl = (journal_cjf*)jh; journal_cjf_ro_readlock(jnl); u32 value = jnl->serial_end; if(serial != NULL) { *serial = value; ret = SUCCESS; } log_debug("cjf-ro: %s,%p: get last serial: %i", jnl->journal_file_name, jnl->file, value); journal_cjf_ro_readunlock(jnl); return ret; } static ya_result journal_cjf_ro_get_serial_range(journal *jh, u32 *serial_start, u32 *serial_end) { journal_cjf *jnl = (journal_cjf*)jh; journal_cjf_ro_readlock(jnl); if(serial_start != NULL) { *serial_start = jnl->serial_begin; } if(serial_end != NULL) { *serial_end = jnl->serial_end; } journal_cjf_ro_readunlock(jnl); return SUCCESS; } static ya_result journal_cjf_ro_truncate_to_size(journal *jh, u32 size_) { journal_cjf *jnl = (journal_cjf*)jh; if(size_ == 0) { // destroy and close return SUCCESS; } else { log_err("cjf-ro: %s,%p: truncate to size != 0 not implemented", jnl->journal_file_name, jnl->file); return ZDB_JOURNAL_FEATURE_NOT_SUPPORTED; } } static ya_result journal_cjf_ro_truncate_to_serial(journal *jh, u32 serial_) { journal_cjf *jnl = (journal_cjf*)jh; (void)serial_; journal_cjf_ro_readlock(jnl); log_err("cjf-ro: %s,%p: truncate to serial not implemented", jnl->journal_file_name, jnl->file); journal_cjf_ro_readunlock(jnl); return ZDB_JOURNAL_FEATURE_NOT_SUPPORTED; } /** * * @param jnl * @return */ static ya_result journal_cjf_ro_reopen(journal *jh) { (void)jh; return SUCCESS; } static void journal_cjf_ro_flush(journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; log_debug("cjf-ro: %s,%p: flush (nop)", jnl->journal_file_name, jnl->file); } static ya_result journal_cjf_ro_close(journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; log_debug("cjf-ro: %s,%p: close", jnl->journal_file_name, jnl->file); #if ZDB_ZONE_HAS_JNL_REFERENCE zdb_zone *zone; if((zone = (zdb_zone*)jnl->zone) != NULL) { yassert(zone->journal == jh); zone->journal = NULL; } #endif log_debug3("cjf-ro: %s,%p: closing file", jnl->journal_file_name, jnl->file); if(jnl->file != NULL) { log_info("zone: %{dnsname}: closing journal file '%s'", jnl->origin, jnl->journal_file_name); file_pool_close(jnl->file); jnl->file = NULL; } return SUCCESS; } static void journal_cjf_ro_log_dump(journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; journal_cjf_ro_readlock(jnl); log_debug("cjf-ro: %s,%p: [%u; %u] '%s' (%i) lck=%i rc=%i", jnl->journal_file_name, jnl->file, jnl->serial_begin, jnl->serial_end, jnl->journal_file_name, jnl->file, jnl->mtx.owner, jnl->mtx.count); journal_cjf_ro_readunlock(jnl); } static ya_result journal_cjf_ro_get_domain(journal *jh, u8 *out_domain) { journal_cjf *jnl = (journal_cjf*)jh; // don't: journal_cjf_ro_readlock(jnl); as the field is constant until the destruction of the journal dnsname_copy(out_domain, jnl->origin); return SUCCESS; } static void journal_cjf_ro_destroy(journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; yassert(jnl->rc == 0); log_debug("cjf-ro: %s,%p: destroy", jnl->journal_file_name, jnl->file); shared_group_mutex_destroy(&jnl->mtx); free(jnl->origin); free(jnl->journal_file_name); #if DEBUG memset(jnl, 0xfe, sizeof(journal_cjf)); jnl->_mru = FALSE; #endif ZFREE_OBJECT(jnl); } static const u8 * journal_cjf_ro_get_domain_const(const journal *jh) { journal_cjf *jnl = (journal_cjf*)jh; return jnl->origin; } static void journal_cjf_ro_minimum_serial_update(journal *jh, u32 stored_serial) { (void)jh; (void)stored_serial; } static void journal_cjf_ro_maximum_size_update_method(journal *jh, u32 maximum_size) { (void)jh; (void)maximum_size; } static void journal_cjf_ro_limit_size_update_method(journal *jh, u32 maximum_size) { (void)jh; (void)maximum_size; } /******************************************************************************* * * vtbl handling functions * ******************************************************************************/ struct journal_vtbl journal_cjf_ro_vtbl = { journal_cjf_ro_get_format_name, // ok journal_cjf_ro_get_format_version, // ok journal_cjf_ro_reopen, journal_cjf_ro_flush, // ok journal_cjf_ro_close, journal_cjf_ro_append_ixfr_stream, // ok (for now) journal_cjf_ro_get_ixfr_stream_at_serial, journal_cjf_ro_get_first_serial, // ok journal_cjf_ro_get_last_serial, // ok journal_cjf_ro_get_serial_range, // ok journal_cjf_ro_truncate_to_size, journal_cjf_ro_truncate_to_serial, journal_cjf_ro_log_dump, journal_cjf_ro_get_domain, // ok journal_cjf_ro_destroy, journal_cjf_ro_get_domain_const, // ok journal_cjf_ro_minimum_serial_update, // ok journal_cjf_ro_maximum_size_update_method, // ok journal_cjf_ro_limit_size_update_method, // ok JOURNAL_CLASS_NAME }; static journal_cjf* journal_cjf_ro_alloc_default(const u8 *origin, const char *filename) { journal_cjf *jnl; ZALLOC_OBJECT_OR_DIE(jnl, journal_cjf, JRNLCJF_TAG); ZEROMEMORY(jnl, sizeof(journal_cjf)); jnl->vtbl = &journal_cjf_ro_vtbl; jnl->mru_node.data = jnl; jnl->file = NULL; jnl->file_maximum_size = MAX_U32; jnl->first_page_offset = CJF_HEADER_SIZE; jnl->origin = dnsname_dup(origin); jnl->journal_file_name = strdup(filename); jnl->last_page.file_offset = CJF_HEADER_SIZE; jnl->last_page.size = CJF_SECTION_INDEX_SLOT_COUNT; jnl->last_page.records_limit = CJF_HEADER_SIZE + CJF_SECTION_INDEX_SIZE; jnl->last_page.file_offset_limit = jnl->file_maximum_size; jnl->flags = JOURNAL_CFJ_FLAGS_MY_ENDIAN|JOURNAL_CFJ_FLAGS_UNINITIALISED; shared_group_mutex_init(&jnl->mtx, &journal_shared_mtx, "journal-cjf"); return jnl; } static u32 journal_cjf_ro_idxt_get_last_file_offset(const journal_cjf *jnl) { if(jnl->idxt.count > 0) { u32 n = journal_cjf_ro_idxt_get_file_offset(jnl, jnl->idxt.count - 1); return n; } else { return 0; } } static u32 journal_cjf_ro_idxt_get_last_serial(const journal_cjf *jnl, s16 index) { u32 last_serial = journal_cjf_ro_idxt_get_entry(jnl, index)->last_serial; return last_serial; } static void journal_cjf_ro_idxt_create(journal_cjf *jnl, s16 entries) { yassert(jnl->idxt.size == 0); yassert(entries >= 0); jnl->idxt.count = 1; jnl->idxt.first = 0; jnl->idxt.size = entries + 1; jnl->idxt.dirty = TRUE; jnl->idxt.marked = 0; MALLOC_OR_DIE(journal_cjf_idxt_tbl_item*, jnl->idxt.entries, sizeof(journal_cjf_idxt_tbl_item) * jnl->idxt.size, JCJFITI_TAG); ZEROMEMORY(jnl->idxt.entries, sizeof(journal_cjf_idxt_tbl_item) * jnl->idxt.size); jnl->idxt.entries[0].last_serial = jnl->serial_begin; jnl->idxt.entries[0].file_offset = jnl->last_page.file_offset; jnl->first_page_offset = jnl->last_page.file_offset; } static s16 journal_cjf_idxt_size(const journal_cjf *jnl) { return jnl->idxt.count; } static ya_result journal_cjf_ro_idxt_verify(journal_cjf *jnl) { // check the values of the pages // serials have to be ordered in serial arithmetics // pages are supposed to start after each other except a looping ones that goes after the header // if the verify fails, a scan may be needed (other procedure) journal_cjf_page_tbl_header page_hdr; u32 previous_page_offset; u32 stream_end_offset; u32 next_page_offset; // uninitialised false positive: either size is <= 0, skipping for & if, either it's >= 0 and page_hrd is set and initialises next_page_offset u32 prev_serial = jnl->serial_begin; int loops = 0; bool error = FALSE; bool has_page_after_header = FALSE; s16 size = journal_cjf_idxt_size(jnl); for(int page = 0; page < size; ++page) { const journal_cjf_idxt_tbl_item* entry = journal_cjf_ro_idxt_get_entry(jnl, page); has_page_after_header |= entry->file_offset == CJF_HEADER_SIZE; if(page > 0) { if(entry->file_offset != next_page_offset) // gcc false positive: next_page_offset is initialised when page == 0 { // page do not start at the expected position log_err("cjf: %{dnsname}: page[%i] starts at an unexpected position (%u != expected %u)", jnl->origin, page, entry->file_offset, next_page_offset); error = TRUE; } if(entry->file_offset == previous_page_offset) { // broken chain log_err("cjf: %{dnsname}: page[%i] is a duplicate at position %u", jnl->origin, page, entry->file_offset); error = TRUE; } if(entry->file_offset > previous_page_offset) { if(entry->file_offset != stream_end_offset) { // suspicious hole in the file log_err("cjf: %{dnsname}: page[%i] is %u bytes after the expected position", jnl->origin, page, entry->file_offset - stream_end_offset); error = TRUE; } } else { // just looped ... if(loops == 0) { if(entry->file_offset < CJF_HEADER_SIZE) { // looped at an unexpected position log_err("cjf: %{dnsname}: page[%i] looped into the header position (%u < %u)", jnl->origin, page, entry->file_offset, CJF_HEADER_SIZE); error = TRUE; } else if(entry->file_offset != CJF_HEADER_SIZE) { // looped at an unexpected position log_err("cjf: %{dnsname}: page[%i] looped at an unexpected position (%u != expected %u)", jnl->origin, page, entry->file_offset, CJF_HEADER_SIZE); error = TRUE; } loops = 1; } else { // should only have looped once log_err("cjf: %{dnsname}: page[%i] looped for a second time", jnl->origin, page); error = TRUE; } } if(error) { // got at least one error return ERROR; } } ssize_t pos = file_pool_seek(jnl->file, entry->file_offset, SEEK_SET); if(pos < 0) { // invalid position (as EBADF should not happen) ya_result ret = ERRNO_ERROR; log_err("cjf: %{dnsname}: page[%i] seek at %u returned %r", jnl->origin, page, entry->file_offset, ret); return ret; } int len = file_pool_readfully(jnl->file, &page_hdr, CJF_SECTION_INDEX_SLOT_HEAD); if(len != CJF_SECTION_INDEX_SLOT_HEAD) { if(len >= 0) { log_err("cjf: %{dnsname}: page[%i] short count reading the header (%u < %u)", jnl->origin, page, len, CJF_SECTION_INDEX_SLOT_HEAD); return ERROR; // short } else { log_err("cjf: %{dnsname}: page[%i] error reading the header: %r", jnl->origin, page, len); return len; // other error } } if(page_hdr.magic != CJF_PAGE_MAGIC) { // page is corrupted log_err("cjf: %{dnsname}: page[%i] corrupted magic", jnl->origin, page); return ERROR; } if(page_hdr.count > page_hdr.size) { // page is corrupted log_err("cjf: %{dnsname}: page[%i] says to contain more than allowed", jnl->origin, page); return ERROR; } if(page_hdr.count == 0) { // empty page (warning) log_warn("cjf: %{dnsname}: page[%i] is empty", jnl->origin, page); } if(serial_gt(prev_serial, entry->last_serial)) { // suspicious serial backward jump log_err("cjf: %{dnsname}: page[%i] serial jumped back from %u to %u", jnl->origin, page, prev_serial, entry->last_serial); } else if(serial_eq(prev_serial, entry->last_serial)) { // suspicious serial standstill log_err("cjf: %{dnsname}: page[%i] serial didn't changed from %u", jnl->origin, page, prev_serial); } previous_page_offset = entry->file_offset; next_page_offset = page_hdr.next_page_offset; // next page, 0 for the last one stream_end_offset = page_hdr.stream_end_offset; // start of next page, start of page table, or 0 for the last in the chain } if(size > 0) { if(next_page_offset != 0) // gcc false positive: size > 0 => next_page_offset has been set to page_hdr.next_page_offset (read from the disk) { // chain end was not marked log_err("cjf: %{dnsname}: page[%i] is last but points to a next at %u", jnl->origin, size - 1, next_page_offset); return ERROR; } if(!has_page_after_header) { // no page at an obvious position log_err("cjf: %{dnsname}: page table has no page at position %u", jnl->origin, CJF_HEADER_SIZE); return ERROR; } } else { // table is empty log_err("cjf: %{dnsname}: page table is empty", jnl->origin); return ERROR; } return SUCCESS; } static void journal_cjf_ro_idxt_load(journal_cjf *jnl) { if(jnl->idxt.entries != NULL) { // already loaded ... return; } // the file is opened if(jnl->page_table_file_offset != 0) { log_debug1("journal_cjf_ro_idxt_load: loading stored IDXT from '%s'", jnl->journal_file_name); // load file_pool_seek(jnl->file, jnl->page_table_file_offset, SEEK_SET); input_stream fis; input_stream bis; file_pool_file_input_stream_init(&fis, jnl->file); buffer_input_stream_init(&bis, &fis, 512); u8 magic[4]; input_stream_read(&bis, magic, 4); u32 *magic_u32p = (u32*)&magic[0]; if(*magic_u32p == CJF_IDXT_MAGIC) { s16 count; input_stream_read(&bis, (u8*)&count , 2); journal_cjf_ro_idxt_create(jnl, count + 1); input_stream_read(&bis, (u8*)&jnl->idxt.entries[0], count * CJF_IDXT_SLOT_SIZE); file_pool_file_input_stream_detach(buffer_input_stream_get_filtered(&bis)); input_stream_close(&bis); jnl->idxt.count = count; u32 first_page_offset = journal_cjf_ro_idxt_get_file_offset(jnl, 0); if(jnl->first_page_offset != first_page_offset) { // discrepancy : check the IDXT is valid if(ISOK(journal_cjf_ro_idxt_verify(jnl))) { // the header is wrong, update it jnl->first_page_offset = first_page_offset; } } return; } file_pool_file_input_stream_detach(buffer_input_stream_get_filtered(&bis)); input_stream_close(&bis); // ERROR, need to rebuild } log_debug1("journal_cjf_ro_idxt_load: rebuilding IDXT from '%s', following the PAGE", jnl->journal_file_name); // rebuild journal_cjf_page_tbl_item *tbl; s16 size = 512; journal_cjf_page_tbl_item tmp_tbl[512]; tbl = tmp_tbl; if(jnl->first_page_offset < JOURNAL_CJF_PAGE_HEADER_SIZE) { // the PAGE chain has been lost : start from HEAD and follow the chain // then after the 0, scan from the furthest known byte for PAGE+offset // and follow until the chain points back to offset sizeof(head) } // read the PAGE chain from the file (no caching) u32 index_offset = jnl->first_page_offset; //u32 current_serial = jnl->serial_begin; journal_cjf_page_tbl_header page_header; journal_cjf_page_tbl_item page_last_item; s16 idx = 0; u32 page_serial = 0; bool page_read = FALSE; do { // move to the page offset and read the header log_debug2("journal_cjf_ro_idxt_load: reading '%s' PAGE header at %x", jnl->journal_file_name, index_offset); file_pool_seek(jnl->file, index_offset, SEEK_SET); if(file_pool_readfully(jnl->file, &page_header, JOURNAL_CJF_PAGE_HEADER_SIZE) != JOURNAL_CJF_PAGE_HEADER_SIZE) // next offset { log_err("journal_cjf_ro_idxt_load: '%s' is too corrupt to go on further reading PAGE header at %x", jnl->journal_file_name, index_offset); break; } /* if(page_header.magic != CJF_PAGE_MAGIC) { // corrupt } */ if(page_header.count > 0) { u32 tail_offset = (page_header.count - 1) * CJF_SECTION_INDEX_SLOT_SIZE; log_debug2("journal_cjf_ro_idxt_load: reading '%s' PAGE tail at %x", jnl->journal_file_name, index_offset + tail_offset); // the last serial is on the last slot file_pool_seek(jnl->file, tail_offset, SEEK_CUR); if(file_pool_readfully(jnl->file, &page_last_item, JOURNAL_CJF_PAGE_ITEM_SIZE) != JOURNAL_CJF_PAGE_ITEM_SIZE) { log_err("journal_cjf_ro_idxt_load: '%s' is too corrupt to go on further reading PAGE tail at %x", jnl->journal_file_name, index_offset + CJF_SECTION_INDEX_SIZE - CJF_SECTION_INDEX_SLOT_HEAD - CJF_SECTION_INDEX_SLOT_SIZE); break; } // if there is a next page ... if(idx == size) { log_debug2("journal_cjf_ro_idxt_load: growing IDXT table from %i to %i", size, size * 2); journal_cjf_page_tbl_item *tmp; MALLOC_OR_DIE(journal_cjf_page_tbl_item*, tmp, JOURNAL_CJF_PAGE_ITEM_SIZE * size * 2, JCJFTI_TAG); memcpy(tmp, tbl, JOURNAL_CJF_PAGE_ITEM_SIZE * size); if(tbl != tmp_tbl) { free(tbl); } tbl = tmp; size *= 2; } tbl[idx].stream_file_offset = index_offset; tbl[idx].ends_with_serial = page_last_item.ends_with_serial; log_debug2("journal_cjf_ro_idxt_load: IDXT[%3i] = {%8x, %u}", idx, index_offset, page_last_item.ends_with_serial); page_serial = page_last_item.ends_with_serial; page_read = TRUE; ++idx; index_offset = page_header.next_page_offset; } else { // an empty page should not exist if(page_read) { if(serial_eq(page_serial, jnl->serial_end)) { log_info("journal_cjf_ro_idxt_load: got up to expected serial %i", page_serial); } else if(serial_lt(page_serial, jnl->serial_end)) { log_err("journal_cjf_ro_idxt_load: got up to serial %i, before the expected %i", page_serial, jnl->serial_end); } else if(serial_gt(page_serial, jnl->serial_end)) { log_err("journal_cjf_ro_idxt_load: got up to serial %i, after the expected %i", page_serial, jnl->serial_end); } } else { log_err("journal_cjf_ro_idxt_load: could not read the content of the journal"); } break; } } while(index_offset != 0); log_debug1("journal_cjf_ro_idxt_load: IDXT table has size %i", idx + 1); // scan for an SOA record journal_cjf_ro_idxt_create(jnl, idx + 1); memcpy(jnl->idxt.entries, tbl, JOURNAL_CJF_PAGE_ITEM_SIZE * idx); // False positive from VS Code Analysis jnl->idxt.entries cannot be NULL at this point jnl->idxt.count = idx; } static void journal_cjf_ro_idxt_destroy(journal_cjf *jnl) { yassert(!jnl->idxt.dirty); free(jnl->idxt.entries); jnl->idxt.entries = NULL; jnl->idxt.size = 0; jnl->idxt.first = 0; jnl->idxt.count = 0; } static void journal_cjf_ro_load_idxt(journal_cjf *jnl) { if(jnl->idxt.entries != NULL) { return; } journal_cjf_ro_idxt_load(jnl); if(jnl->idxt.count > 0) { jnl->last_page.file_offset = journal_cjf_ro_idxt_get_last_file_offset(jnl); journal_cjf_page_tbl_header current_page_header; journal_cjf_ro_page_cache_read_header(jnl->file, jnl->last_page.file_offset, ¤t_page_header); jnl->last_page.count = current_page_header.count; jnl->last_page.size = current_page_header.size; if(jnl->last_page.file_offset < jnl->first_page_offset) { jnl->last_page.file_offset_limit = jnl->first_page_offset; } else { jnl->last_page.file_offset_limit = jnl->file_maximum_size; } if(jnl->idxt.count > 1) { jnl->last_page.serial_start = journal_cjf_ro_idxt_get_last_serial(jnl, jnl->idxt.count - 2); } else { jnl->last_page.serial_start = jnl->serial_begin; } } else { jnl->idxt.dirty = FALSE; jnl->flags |= JOURNAL_CFJ_FLAGS_DIRTY; journal_cjf_ro_idxt_destroy(jnl); jnl->serial_begin = 0; jnl->serial_end = 0; jnl->mtx.owner = JNL_LOCK_NONE; jnl->mtx.count = 0; jnl->first_page_offset = CJF_HEADER_SIZE; jnl->page_table_file_offset = 0; jnl->last_soa_offset = 0; jnl->file_maximum_size = MAX_S32; jnl->last_page.file_offset = CJF_HEADER_SIZE; jnl->last_page.count = 0; jnl->last_page.size = CJF_SECTION_INDEX_SLOT_COUNT; jnl->last_page.serial_start = 0; jnl->last_page.serial_end = 0; jnl->last_page.records_limit = jnl->last_page.file_offset + CJF_SECTION_INDEX_SIZE; jnl->last_page.file_offset_limit = jnl->file_maximum_size; #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || /* Since glibc 2.3.5: */ _POSIX_C_SOURCE >= 200112L file_pool_resize(jnl->file, CJF_HEADER_SIZE); #endif } } /** * The caller guarantees not to call this on an already opened journal * * Should not be called directly (only by journal_* functions. * * Opens or create a journal handling structure. * If the journal did not exist, the structure is returned without a file opened * * @param jh * @param origin * @param workingdir * @param create * * @return */ ya_result journal_cjf_ro_open_file(journal **jhp, const char *filename, const u8* origin, bool create) { // CFJ_PAGE_CACHE -> if(!journal_initialized) { shared_group_shared_mutex_init(&journal_shared_mtx); journal_file_pool = file_pool_init("journal-file-pool", 256); journal_initialized = TRUE; } journal_cjf *jnl = NULL; ya_result ret; if(file_exists(filename) || create) { // instantiate and open the journal ret = journal_cjf_ro_init_from_file(&jnl, origin, filename, create); if(ISOK(ret)) { yassert(jnl != NULL); // to help scan-build if(!((jnl->serial_begin == 0) && (jnl->serial_begin == jnl->serial_end))) // scan-build false-positive : if ISOK(ret) => jnl != NULL { journal_cjf_ro_load_idxt(jnl); } } else { if(create) { log_err("cjf-ro: %{dnsname}: failed to open %s: %r", origin, filename, ret); } else { log_debug("cjf-ro: %{dnsname}: failed to open %s: %r", origin, filename, ret); } if(jnl != NULL) { journal_cjf_ro_destroy((journal*)jnl); #if DEBUG log_debug("cjf-ro: %{dnsname}: journal file cannot be opened/created", origin); #endif } return ZDB_ERROR_ICMTL_NOTFOUND; } #if DEBUG log_debug("cjf-ro: %{dnsname}: journal opened", origin); #endif *jhp = (journal*)jnl; return SUCCESS; } else { #if DEBUG log_debug("cjf-ro: %{dnsname}: journal file not found", origin); #endif return ZDB_ERROR_ICMTL_NOTFOUND; } } /** * The caller guarantees not to call this on an already opened journal * * Should not be called directly (only by journal_* functions. * * Opens or create a journal handling structure. * If the journal did not exist, the structure is returned without a file opened * * @param jh * @param origin * @param workingdir * @param create * * @return */ ya_result journal_cjf_ro_open(journal **jhp, const u8* origin, const char *workingdir, bool create) { // CFJ_PAGE_CACHE <- ya_result ret; *jhp = NULL; // generate the file name char filename[PATH_MAX]; if((jhp == NULL) || (origin == NULL) || (workingdir == NULL)) { return ZDB_JOURNAL_WRONG_PARAMETERS; } #if DEBUG log_debug("cjf-ro: trying to open journal for %{dnsname} in '%s'", origin, workingdir); #endif /* get the soa of the loaded zone */ if(FAIL(ret = snformat(filename, sizeof(filename), CJF_WIRE_FILE_FORMAT, workingdir, origin))) { #if DEBUG log_debug("cjf-ro: %{dnsname}: journal file name is too long", origin); #endif return ret; } ret = journal_cjf_ro_open_file(jhp, filename, origin, create); return ret; } void journal_cjf_ro_finalize() { file_pool_finalize(journal_file_pool); } #else char journal_cjf_ro[] = "placeholder"; #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/journal-jnl.c0000644000000000000000000000013214505005531021363 xustar000000000000000030 mtime=1695812441.706971647 30 atime=1695812445.800030268 30 ctime=1695812495.078736038 yadifa-2.6.5-11201/lib/dnsdb/src/journal-jnl.c0000664000374500037450000027061014505005531021333 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ /** @brief Function ... * * ... * * @param ... * * @retval OK * @retval NOK */ #define ZDB_JOURNAL_CODE 1 #define JOURNAL_JNL_BASE 1 #include "dnsdb/dnsdb-config.h" #include "dnsdb/journal-jnl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dnsdb/zdb_error.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/journal.h" #include "dnsdb/zdb_types.h" #include "dnsdb/xfr_copy.h" #include "dnsdb/zdb-zone-path-provider.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/journal-cjf.h" #define JNLJNLPG_TAG 0x47504c4e4a4c4e4a #define JNLRNGLK_TAG 0x4b4c474e524c4e4a #define JNLCHPTE_TAG 0x45545048434c4e4a #define JNLISDBF_TAG 0x46424453494c4e4a #define JNLISDTA_TAG 0x41544453494c4e4a #define JNL_JNL0_MAGIC MAGIC4('J','N','L', 0) static const u8 jnl_magic[4] = {'J','N','L',0}; #define PAGE_MAGIC MAGIC4('P','A','G','E') #define CHPT_MAGIC MAGIC4('C','H','P','T') #define CHPT_SIZE_THRESHOLD 16384 #define JOURNAL_JNL_FLAGS_OTHER_ENDIAN 0x80000000 // journal endian is different #define JOURNAL_JNL_FLAGS_MY_ENDIAN 0x00000080 // journal endian is the same #define JOURNAL_JNL_FLAGS_INITIALISED 0x00000001 #define JOURNAL_JNL_PAGE_FROM_SET_SIZE_MAX 16 #define JOURNAL_JNL_LOCK_DEBUG 0 #define JOURNAL_JNL_REOPEN_DEBUG 0 #define JOURNAL_JNL_FLUSH_DEBUG 0 #if !DEBUG #undef JOURNAL_JNL_LOCK_DEBUG #define JOURNAL_JNL_LOCK_DEBUG 0 #undef JOURNAL_JNL_REOPEN_DEBUG #define JOURNAL_JNL_REOPEN_DEBUG 0 #undef JOURNAL_JNL_FLUSH_DEBUG #define JOURNAL_JNL_FLUSH_DEBUG 0 #endif struct journal_jnl_header { u32 serial_begin; u32 serial_end; u32 last_soa_offset; u32 flags; }; typedef struct journal_jnl_header journal_jnl_header; struct journal_jnl_chapter { u32 magic; u32 relative_prev; u32 relative_next; u32 serial_from; u32 serial_to; }; typedef struct journal_jnl_chapter journal_jnl_chapter; struct journal_jnl_chapter_entry { s32 position; journal_jnl_chapter chapter; }; typedef struct journal_jnl_chapter_entry journal_jnl_chapter_entry; struct journal_jnl_page { u32 magic; u32 serial_from; u32 serial_to; u32 size; }; typedef struct journal_jnl_page journal_jnl_page; struct journal_jnl_entry_base { u32 magic; u32 data; }; typedef struct journal_jnl_entry_base journal_jnl_entry_base; union journal_jnl_entry { u32 magic; journal_jnl_entry_base base; journal_jnl_chapter chapter; journal_jnl_page page; }; struct journal_range_lock { u32 serial_from; u32 serial_to; }; typedef struct journal_range_lock journal_range_lock; struct journal_jnl_page_header_cache { ptr_set page_from_set; // keeps only a given amount, needs to be updated with each shift list_dl_s page_mru; }; typedef struct journal_jnl_page_header_cache journal_jnl_page_header_cache; struct journal_jnl { volatile struct journal_vtbl *vtbl; volatile list_dl_node_s mru_node; volatile int rc; volatile unsigned int _forget:1,_mru:1; /* The journal is not like a stream, it's a full standalone entity always returned as a pointer. * So the handler can do whatever it wants after "mru" */ circular_file_t file; u8 *origin; // to not rely on zone shared_group_mutex_t mtx; journal_jnl_header hdr; list_dl_s chapters; list_dl_s range_lock; journal_jnl_page_header_cache page_cache; u32 safe_serial; // the first serial that cannot be discarded without losing data u32 size_limit; bool dirty; }; typedef struct journal_jnl journal_jnl; extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define DEBUG_JOURNAL 0 #if !DEBUG #undef DEBUG_JOURNAL #define DEBUG_JOURNAL 0 #endif #define JOURNAL_FORMAT_NAME "circular" #define VERSION_HI 0 #define VERSION_LO 1 #define JOURNAL_CLASS_NAME "journal_jnl" #define JNL_LOCK_NONE 0 #define JNL_LOCK_READ 1 #define JNL_LOCK_WRITE 2 #define JNL_EXT "cjf" #define JNL_EXT_STRLEN 3 #define SOA_RDATA_SIZE_MAX 532 #define DO_SYNC 1 #define JRNLJNL_TAG 0x58494c4e524a /* * Contains the journal (almost: not the matching start and end SOA) */ #define JNL_WIRE_FILE_FORMAT "%s/%{dnsname}." JNL_EXT #define JNL_WIRE_ROOT_NAME "root_zone" #define JNL_WIRE_ROOT_ZONE_FORMAT "%s/" JNL_WIRE_ROOT_NAME "." JNL_EXT #define FIRST_FROM_END (JNL_EXT_STRLEN + (1 + 8 + 1 + 8)) #define LAST_FROM_END (JNL_EXT_STRLEN + (1 + 8)) static shared_group_shared_mutex_t journal_shared_mtx = SHARED_GROUP_SHARED_MUTEX_INTIALIZER; static bool journal_initialized = FALSE; static file_pool_t journal_file_pool = 0; static u32 journal_file_pool_size = 512; static void journal_jnl_log_dump_nolock(journal *jh); static void journal_jnl_log_dump(journal *jh); static void journal_jnl_writelock(journal_jnl *jnl) { #if JOURNAL_JNL_LOCK_DEBUG log_debug4("jnl: %s,%p: write lock", circular_file_name(jnl->file), jnl->file); #endif shared_group_mutex_lock(&jnl->mtx, GROUP_MUTEX_WRITE); } static void journal_jnl_writeunlock(journal_jnl *jnl) { #if JOURNAL_JNL_LOCK_DEBUG log_debug4("jnl: %s,%p: write unlock", circular_file_name(jnl->file), jnl->file); #endif shared_group_mutex_unlock(&jnl->mtx, GROUP_MUTEX_WRITE); } static void journal_jnl_readlock(journal_jnl *jnl) { #if DEBUG log_debug4("jnl: %s,%p: read lock", circular_file_name(jnl->file), jnl->file); #endif shared_group_mutex_lock(&jnl->mtx, GROUP_MUTEX_READ); } static void journal_jnl_readunlock(journal_jnl *jnl) { #if JOURNAL_JNL_LOCK_DEBUG log_debug4("jnl: %s,%p: read unlock", circular_file_name(jnl->file), jnl->file); #endif shared_group_mutex_unlock(&jnl->mtx, GROUP_MUTEX_READ); } bool journal_jnl_isreadlocked(journal_jnl *jnl) { bool ret = shared_group_mutex_islocked_by(&jnl->mtx, GROUP_MUTEX_READ); return ret; } bool journal_jnl_iswritelocked(journal_jnl *jnl) { bool ret = shared_group_mutex_islocked_by(&jnl->mtx, GROUP_MUTEX_WRITE); return ret; } static inline bool journal_jnl_is_dirty_nolock(const journal_jnl *jnl) { return jnl->dirty; } #if UNUSED static inline bool journal_jnl_is_dirty(journal_jnl *jnl) { journal_jnl_readlock(jnl); bool ret = journal_jnl_is_dirty_nolock(jnl); journal_jnl_readunlock(jnl); return ret; } #endif static inline void journal_jnl_set_dirty_nolock(journal_jnl *jnl) { jnl->dirty = TRUE; } static inline void journal_jnl_clear_dirty_nolock(journal_jnl *jnl) { jnl->dirty = FALSE; } #if UNUSED static inline void journal_jnl_clear_dirty(journal_jnl *jnl) { journal_jnl_writelock(jnl); journal_jnl_clear_dirty_nolock(jnl); journal_jnl_writeunlock(jnl); } #endif /* void log_debug_jnl(journal_jnl *jnl, const char *text) { (void)jnl; (void)text; } */ void journal_jnl_release(journal_jnl *jnl) { journal_release((journal*)jnl); } static int journal_jnl_page_cache_node_compare(const void *key_a, const void *key_b) { intptr a = (intptr)key_a; intptr b = (intptr)key_b; return a - b; } static void journal_jnl_page_cache_init(journal_jnl *jnl) { ptr_set_init(&jnl->page_cache.page_from_set); // set of pages jnl->page_cache.page_from_set.compare = journal_jnl_page_cache_node_compare; // comparator for set list_dl_init(&jnl->page_cache.page_mru); // empty list of pages } static void journal_jnl_page_cache_add_nolock(journal_jnl *jnl, const journal_jnl_page *page, u32 page_offset) { journal_jnl_page *cached_page; #if DEBUG log_debug3("jnl: %s,%p: cache add page [%u; %u] of size %u at %u", circular_file_name(jnl->file), jnl->file, page->serial_from, page->serial_to, page->size, page_offset); #endif ptr_node *node = ptr_set_find(&jnl->page_cache.page_from_set, (void*)(intptr)page->serial_from); if(node != NULL) { list_dl_node_s *list_node = (list_dl_node_s*)node->value; if(list_node != list_dl_first_node(&jnl->page_cache.page_mru)) { // move node from its current position to the first position list_dl_remove_node(&jnl->page_cache.page_mru, list_node); //list_dl_insert(&jnl->page_cache.page_mru, list_node); list_dl_insert_node(&jnl->page_cache.page_mru, list_node); } return; } if(list_dl_size(&jnl->page_cache.page_mru) == JOURNAL_JNL_PAGE_FROM_SET_SIZE_MAX) { // clear the last page list_dl_move_last_to_first(&jnl->page_cache.page_mru); cached_page = (journal_jnl_page*)list_dl_peek_first(&jnl->page_cache.page_mru); ptr_set_delete(&jnl->page_cache.page_from_set, (void*)(intptr)cached_page->serial_from); } else { // there is still room: add a new page ZALLOC_OBJECT_OR_DIE(cached_page, journal_jnl_page, JNLJNLPG_TAG); list_dl_insert(&jnl->page_cache.page_mru, cached_page); } // update the new or cleared page cached_page->magic = page_offset; cached_page->serial_from = page->serial_from; cached_page->serial_to = page->serial_to; cached_page->size = page->size; // create an entry in the set (we know the entry doesn't exist) // the set contains list_dl_node_s as data node = ptr_set_insert(&jnl->page_cache.page_from_set, (void*)(intptr)page->serial_from); node->value = list_dl_first_node(&jnl->page_cache.page_mru); } static bool journal_jnl_page_cache_get_from_serial_nolock(journal_jnl *jnl, u32 serial_from, journal_jnl_page *page_out, u32 *page_offset_out) { journal_jnl_page *cached_page; ptr_node *node = ptr_set_find(&jnl->page_cache.page_from_set, (void*)(intptr)serial_from); if(node == NULL) { return FALSE; } list_dl_node_s *cached_page_node = (list_dl_node_s*)node->value; cached_page = (journal_jnl_page*)cached_page_node->data; if(page_out != NULL) { page_out->magic = PAGE_MAGIC; page_out->serial_from = cached_page->serial_from; page_out->serial_to = cached_page->serial_to; page_out->size = cached_page->size; } if(page_offset_out != NULL) { *page_offset_out = cached_page->magic; // magic holds the offset } return TRUE; } static void journal_jnl_page_cache_shift_nolock(journal_jnl* jnl, u32 offset) { list_dl_iterator_s iter; list_dl_iterator_init(&iter, &jnl->page_cache.page_mru); while(list_dl_iterator_has_next(&iter)) { journal_jnl_page *page = (journal_jnl_page*)list_dl_iterator_next(&iter); if(page->magic > offset) { #if DEBUG log_debug3("jnl: %s,%p: page cache [%u, %u] (%u bytes) shift from %u to %u", circular_file_name(jnl->file), jnl->file, page->serial_from, page->serial_to, page->size, page->magic, page->magic - offset); #endif page->magic -= offset; } else { #if DEBUG log_debug3("jnl: %s,%p: page cache [%u, %u] (%u bytes) shift out from %u to void", circular_file_name(jnl->file), jnl->file, page->serial_from, page->serial_to, page->size, page->magic); #endif ptr_node *node = ptr_set_find(&jnl->page_cache.page_from_set, (void*)(intptr)page->serial_from); assert(node != NULL); list_dl_node_s *list_node = (list_dl_node_s*)node->value; ptr_set_delete(&jnl->page_cache.page_from_set, (void*)(intptr)page->serial_from); list_dl_iterator_remove(&iter); list_dl_node_free(list_node); ZFREE_OBJECT(page); } } } static journal_jnl * journal_jnl_alloc_default(const u8 *origin, const char *filename); static void journal_jnl_free_default(journal_jnl* jnl); static journal_range_lock* journal_jnl_lock_range_add_nolock(journal_jnl* jnl, u32 serial) { #if DEBUG log_debug3("jnl: %s,%p: lock range [%u; %u] add", circular_file_name(jnl->file), jnl->file, serial, jnl->hdr.serial_end); #endif if(serial_le(jnl->hdr.serial_begin, serial) && serial_gt(jnl->hdr.serial_end, serial)) { journal_range_lock* lock; ZALLOC_OBJECT_OR_DIE(lock, journal_range_lock, JNLRNGLK_TAG); lock->serial_from = serial; lock->serial_to = jnl->hdr.serial_end; #if DEBUG if(serial_gt(lock->serial_from, lock->serial_to)) { abort(); } #endif list_dl_append(&jnl->range_lock, lock); #if DEBUG journal_jnl_log_dump_nolock((journal*)jnl); #endif return lock; } else { return NULL; } } static void journal_jnl_lock_range_remove_nolock(journal_jnl* jnl, journal_range_lock *lock) { #if DEBUG log_debug3("jnl: %s,%p: lock range [%u; %u] remove", circular_file_name(jnl->file), jnl->file, lock->serial_from, lock->serial_to); #endif bool ret = list_dl_remove(&jnl->range_lock, lock); if(!ret) { log_err("jnl: %s,%p: lock range [%u; %u] not set", circular_file_name(jnl->file), jnl->file, lock->serial_from, lock->serial_to); abort(); } ZFREE_OBJECT(lock); #if DEBUG journal_jnl_log_dump_nolock((journal*)jnl); #endif } static bool journal_jnl_lock_get_serial_range_nolock(journal_jnl* jnl, u32 *serial_fromp, u32 *serial_top) { #if DEBUG log_debug3("jnl: %s,%p: [%u; %u] lock serial range get", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end ); #endif if(list_dl_size(&jnl->range_lock) > 0) { u32 serial_from = jnl->hdr.serial_end; u32 serial_to = jnl->hdr.serial_begin; list_dl_iterator_s iter; list_dl_iterator_init(&iter, &jnl->range_lock); while(list_dl_iterator_has_next(&iter)) { journal_range_lock *lock = (journal_range_lock*)list_dl_iterator_next(&iter); #if DEBUG log_debug3("jnl: %s,%p: [%u; %u] locked for [%d; %d]", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, lock->serial_from, lock->serial_to ); #endif #if DEBUG if(serial_gt(lock->serial_from, lock->serial_to)) { abort(); } #endif if(serial_lt(lock->serial_from, serial_from)) { serial_from = lock->serial_from; } if(serial_gt(lock->serial_to, serial_to)) { serial_to = lock->serial_to; } } #if DEBUG if(serial_gt(serial_from, serial_to)) { abort(); } #endif *serial_fromp = serial_from; *serial_top = serial_to; return TRUE; } else { //#if DEBUG *serial_fromp = jnl->hdr.serial_end; *serial_top = jnl->hdr.serial_end; //#endif return FALSE; } } static int journal_jnl_create_file(journal_jnl **jnlp, const u8 *origin, const char *filename) { log_debug3("jnl: %{dnsname}: creating %s", origin, filename); circular_file_t file; ya_result ret; if(ISOK(ret = circular_file_create(&file, journal_file_pool, jnl_magic, filename, 65536, sizeof(journal_jnl_header)))) { journal_jnl *jnl = journal_jnl_alloc_default(origin, filename); jnl->file = file; jnl->hdr.serial_begin = 0; jnl->hdr.serial_end = 0; jnl->hdr.last_soa_offset = 0; jnl->hdr.flags = JOURNAL_JNL_FLAGS_MY_ENDIAN; if(ISOK(ret = circular_file_write_reserved_header(file, &jnl->hdr, sizeof(journal_jnl_header)))) { *jnlp = jnl; } else { journal_jnl_free_default(jnl); // does circular_file_close(file); } } else { log_err("jnl: %s: failed to create %s: %r", origin, filename, ret); *jnlp = NULL; } return ret; } static int journal_jnl_scan(journal_jnl* jnl) { #if EXPERIMENTAL union journal_jnl_entry last_good_entry = { 0 }; u64 last_good_position = 0; #endif union journal_jnl_entry entry; ya_result ret = SUCCESS; journal_jnl_chapter_entry *current_chapter = NULL; u64 prev_pos = 0; while(circular_file_get_read_available(jnl->file) > 0) { u64 position = circular_file_tell(jnl->file); entry.magic = 0; if(ISOK(ret = circular_file_read(jnl->file, &entry.magic, sizeof(u32)))) { switch(entry.magic) { case CHPT_MAGIC: { if(ISOK(ret = circular_file_read(jnl->file, &entry.base.data, sizeof(journal_jnl_chapter) - sizeof(u32)))) { #if DEBUG log_debug3("jnl: %s,%p: scan: read chapter header [%u, %u] size %u", circular_file_name(jnl->file), jnl->file, entry.chapter.serial_from, entry.chapter.serial_to, entry.chapter.relative_next); #endif if(ISOK(ret = circular_file_seek_relative(jnl->file, entry.chapter.relative_next))) { // store the chapter // read the next entry journal_jnl_chapter_entry *chapter_entry; ZALLOC_OBJECT_OR_DIE(chapter_entry, journal_jnl_chapter_entry, JNLCHPTE_TAG); chapter_entry->position = position; chapter_entry->chapter = entry.chapter; list_dl_append(&jnl->chapters, chapter_entry); prev_pos = position; } else { log_err("jnl: %s,%p: scan: failed to seek right after the chapter: %r", circular_file_name(jnl->file), jnl->file, ret); } } else { log_err("jnl: %s,%p: scan: failed to read chapter header: %r", circular_file_name(jnl->file), jnl->file, ret); } break; } case PAGE_MAGIC: { if(ISOK(ret = circular_file_read(jnl->file, &entry.base.data, sizeof(journal_jnl_page) - sizeof(u32)))) { #if DEBUG log_debug3("jnl: %s,%p: scan: read page header [%u, %u] size %u", circular_file_name(jnl->file), jnl->file, entry.page.serial_from, entry.page.serial_to, entry.page.size); #endif if(ISOK(ret = circular_file_seek_relative(jnl->file, entry.page.size))) { // add to the current virtual chapter (create it if needed) // if the current virtual chapter is "big enough", store it and clear it as "current" // read the next entry #if EXPERIMENTAL last_good_entry = entry; last_good_position = position; #endif journal_jnl_page_cache_add_nolock(jnl, &entry.page, position); if(current_chapter == NULL) { journal_jnl_chapter_entry *chatper_entry; ZALLOC_OBJECT_OR_DIE(chatper_entry, journal_jnl_chapter_entry, JNLCHPTE_TAG); chatper_entry->position = position - sizeof(journal_jnl_chapter); chatper_entry->chapter.magic = 0; // fake one chatper_entry->chapter.relative_prev = prev_pos; chatper_entry->chapter.relative_next = sizeof(journal_jnl_page) + entry.page.size - sizeof(journal_jnl_chapter); chatper_entry->chapter.serial_from = entry.page.serial_from; chatper_entry->chapter.serial_to = entry.page.serial_to; current_chapter = chatper_entry; prev_pos = chatper_entry->position; } else { current_chapter->chapter.relative_next += sizeof(journal_jnl_page) + entry.page.size; current_chapter->chapter.serial_to = entry.page.serial_to; } if(current_chapter->chapter.relative_next >= CHPT_SIZE_THRESHOLD) { list_dl_append(&jnl->chapters, current_chapter); current_chapter = NULL; } } else { log_err("jnl: %s,%p: scan: failed to seek right after the page: %r", circular_file_name(jnl->file), jnl->file, ret); } } else { log_err("jnl: %s,%p: scan: failed to read page header: %r", circular_file_name(jnl->file), jnl->file, ret); } break; } default: { log_err("jnl: %s,%p: scan: unknown magic %08x", circular_file_name(jnl->file), jnl->file, entry.magic); ret = ZDB_JOURNAL_UNEXPECTED_MAGIC; break; } } if(FAIL(ret)) { log_err("jnl: %s,%p: failed to scan file: %r", circular_file_name(jnl->file), jnl->file, ret); break; } } else { if(ISOK(ret)) { // short read, probable corruption log_err("jnl: %s,%p: failed to scan magic: got only %i bytes", circular_file_name(jnl->file), jnl->file, ret); ret = ZDB_JOURNAL_SHORT_READ; } else { log_err("jnl: %s,%p: failed to scan next magic: %r", circular_file_name(jnl->file), jnl->file, ret); #if EXPERIMENTAL if(ret == CIRCULAR_FILE_SHORT) { // the journal has been corrupted, the current page is lost if(last_good_entry.magic == PAGE_MAGIC) { // rollback jnl->hdr.serial_end = last_good_entry.page.serial_to; ssize_t records_position = circular_file_seek(jnl->file, last_good_position + 16); if(ISOK(records_position)) { // read records until the 2nd SOA is found u8 *update_message_records = (u8*)malloc(last_good_entry.page.size); if(update_message_records != NULL) { ya_result update_message_size = circular_file_read(jnl->file, update_message_records, last_good_entry.page.size); if(update_message_size == last_good_entry.page.size) { packet_unpack_reader_data pr; dns_resource_record *rr = dns_resource_record_new_instance(); packet_reader_init(&pr, update_message_records, update_message_size); int soa_count = 0; for(;;) { u32 rr_position = pr.offset; if(packet_reader_read_dns_resource_record(&pr, rr) <= 0) { break; } if(rr->tctr.qtype == TYPE_SOA) { if(soa_count++ > 0) { jnl->hdr.last_soa_offset = records_position + rr_position; circular_file_set_size(jnl->file, circular_file_tell(jnl->file)); break; } } } dns_resource_record_free(rr); free(update_message_records); } else { free(update_message_records); if(ISOK(update_message_size)) { // short read? } else { return ZDB_JOURNAL_SHORT_READ; } } } } } } #endif // EXPERIMENTAL } break; } } if(current_chapter != NULL) { list_dl_append(&jnl->chapters, current_chapter); current_chapter = NULL; } return ret; } /** * * MUST return -1 in case of error * * @param jnl * @param create * @return the file descriptor or an error code */ static int journal_jnl_init_from_file(journal_jnl **jnlp, const u8 *origin, const char *filename, bool create) { log_debug3("jnl: %{dnsname}: opening%s %s", origin, (create)?"/creating":"", filename); circular_file_t file; ya_result ret; if(ISOK(ret = circular_file_open(&file, journal_file_pool, jnl_magic, filename))) { journal_jnl *jnl = journal_jnl_alloc_default(origin, filename); jnl->file = file; if(ISOK(ret = circular_file_read_reserved_header(file, &jnl->hdr, sizeof(journal_jnl_header)))) { // scan the file ret = journal_jnl_scan(jnl); *jnlp = jnl; return ret; } journal_jnl_free_default(jnl); // does circular_file_close(file); } else if(ret == DATA_FORMAT_ERROR) { // journal is either corrupted, either in an older format // _ open the journal file // _ read the magic // _ if it's a CJF read it ... // ... with a specialised version that can only read and will scream about "journal full" whenever it's being written on // _ also, ensure the journal has been read completely before being written // _ at the moment we know the zone has been saved, destroy the file and create a new journal with the most recent features #if JOURNAL_CJF_ENABLED ret = journal_cjf_open_file((journal**)jnlp, filename, origin, FALSE); #else ret = journal_cjf_ro_open_file((journal**)jnlp, filename, origin, FALSE); if(ISOK(ret) && create) { (*jnlp)->vtbl->close((journal*)*jnlp); (*jnlp)->vtbl->destroy((journal*)*jnlp); file_pool_unlink_from_pool_and_filename(journal_file_pool, filename); ret = journal_jnl_init_from_file(jnlp, origin, filename, create); } #endif } else if(create) { ret = journal_jnl_create_file(jnlp, origin, filename); } return ret; } static ya_result journal_jnl_header_flush_nolock(journal_jnl *jnl) { ya_result ret = SUCCESS; if(journal_jnl_is_dirty_nolock(jnl)) { if(ISOK(ret = circular_file_write_reserved_header(jnl->file, &jnl->hdr, sizeof(journal_jnl_header)))) { if(ISOK(circular_file_flush(jnl->file))) { journal_jnl_clear_dirty_nolock(jnl); } } } return ret; } /*****************************************************************************/ static void journal_jnl_writelock(journal_jnl *jnl); static void journal_jnl_writeunlock(journal_jnl *jnl); static void journal_jnl_readlock(journal_jnl *jnl); static void journal_jnl_readunlock(journal_jnl *jnl); static const char * journal_jnl_get_format_name() // vtbl { return JOURNAL_FORMAT_NAME; } static u32 journal_jnl_get_format_version() // vtbl { return VERSION_U32(VERSION_HI,VERSION_LO); } static s32 journal_jnl_get_position_for_serial_nolock(journal_jnl *jnl, u32 serial) { s32 ret = -1; s32 position = -1; journal_jnl_page page; if(serial_le(jnl->hdr.serial_begin, serial) && serial_gt(jnl->hdr.serial_end, serial)) { if(journal_jnl_page_cache_get_from_serial_nolock(jnl, serial, &page, (u32*)&position)) { // it was recently used #if DEBUG log_debug("jnl: %s,%p: page for serial %u cached position is %u", circular_file_name(jnl->file), jnl->file, serial, position); #endif return position; } // follow the list of pages // first ensure known chapter covers journal_jnl_chapter_entry *first = (journal_jnl_chapter_entry*)list_dl_peek_first(&jnl->chapters); journal_jnl_chapter_entry *last = (journal_jnl_chapter_entry*)list_dl_peek_last(&jnl->chapters); if( ((((intptr)first)|((intptr)last)) != 0) && serial_ge(serial, first->chapter.serial_from) && serial_le(serial, last->chapter.serial_from)) { list_dl_iterator_s iter; list_dl_iterator_init(&iter, &jnl->chapters); bool found = FALSE; while(list_dl_iterator_has_next(&iter)) { journal_jnl_chapter_entry *entry = (journal_jnl_chapter_entry *)list_dl_iterator_next(&iter); if(serial_le(entry->chapter.serial_from, serial) && serial_gt(entry->chapter.serial_to, serial)) { // found the containing chapter // look from that position position = entry->position + sizeof(journal_jnl_chapter); #if DEBUG log_debug("jnl: %s,%p: page for serial %u position is %u (%u + %u)", circular_file_name(jnl->file), jnl->file, serial, position, entry->position, sizeof(journal_jnl_chapter)); #endif found = TRUE; break; } } if(!found) { log_err("jnl: %s,%p: failed to read page for serial %u: position was not found (serial range is [%u; %u]", circular_file_name(jnl->file), jnl->file, serial, jnl->hdr.serial_begin, jnl->hdr.serial_end); return ERROR; } } else { // the covering chapter may have been destroyed during a shift // look from 0 position = 0; } //u64 org_position = circular_file_tell(jnl->file); journal_jnl_page page; u32 prev_serial_from; bool prev_serial_from_ready = FALSE; for(;;) { ssize_t resulting_position = circular_file_seek(jnl->file, position); if(resulting_position != position) { if(FAIL(resulting_position)) { log_err("jnl: %s,%p: looking for %u at position %u: seek failed with %r", circular_file_name(jnl->file), jnl->file, serial, position, (ya_result)resulting_position); } else { log_err("jnl: %s,%p: looking for %u at position %u: seek gave position %llu", circular_file_name(jnl->file), jnl->file, serial, position, resulting_position); } log_err("jnl: %s,%p: trying to recover by marking the journal as corrupted", circular_file_name(jnl->file), jnl->file); ret = ZDB_JOURNAL_LOOKS_CORRUPTED; break; } if((ret = circular_file_read(jnl->file, &page, sizeof(journal_jnl_page))) == sizeof(journal_jnl_page)) { if(page.magic == PAGE_MAGIC) { if(prev_serial_from_ready && serial_ge(prev_serial_from, page.serial_from)) { log_err("jnl: %s,%p: looking for %u at position %u: page serial did not increment: previous was %u, current is %u", circular_file_name(jnl->file), jnl->file, serial, position, prev_serial_from, page.serial_from); ret = ZDB_JOURNAL_LOOKS_CORRUPTED; // something is fishy break; } if(page.serial_from == serial) { // got it ret = position; break; } else if(serial_gt(page.serial_from, serial)) { log_err("jnl: %s,%p: looking for %u at position %u: serial not found, current is %u, which is after it", circular_file_name(jnl->file), jnl->file, serial, position, page.serial_from); ret = ZDB_JOURNAL_LOOKS_CORRUPTED; // serial jumping the wrong way: probable corruption break; } else // next ... { position += sizeof(journal_jnl_page) + page.size; } prev_serial_from = page.serial_from; prev_serial_from_ready = TRUE; } else { log_err("jnl: %s,%p: failed to read page for serial %u at position %u: bad magic: expected %08x, got %08x", circular_file_name(jnl->file), jnl->file, serial, position, PAGE_MAGIC, page.magic); ret = ZDB_JOURNAL_UNEXPECTED_MAGIC; // bad magic break; } } else { if(ISOK(ret)) { // short read, probable corruption log_err("jnl: %s,%p: failed to read page for serial %u at position %u: got %i bytes instead of %i", circular_file_name(jnl->file), jnl->file, serial, position, ret, sizeof(journal_jnl_page)); ret = ZDB_JOURNAL_SHORT_READ; } else { log_err("jnl: %s,%p: failed to read page for serial %u at position %u: %r", circular_file_name(jnl->file), jnl->file, serial, position, ret); } break; } } //circular_file_seek(jnl->file, org_position); } else { return -1; } return ret; } static void journal_jnl_adjust_chapters_nolock(journal_jnl *jnl, s64 offset) { if(offset == 0) { return; } #if DEBUG log_debug("jnl: %s,%p: shifting out chapters by %u bytes", circular_file_name(jnl->file), jnl->file, offset); #endif list_dl_iterator_s iter; list_dl_iterator_init(&iter, &jnl->chapters); while(list_dl_iterator_has_next(&iter)) { journal_jnl_chapter_entry *entry = (journal_jnl_chapter_entry *)list_dl_iterator_next(&iter); if(entry->position < offset) { #if DEBUG log_debug("jnl: %s,%p: shifting out chapter [%u, %u] (%u bytes) from %u to void", circular_file_name(jnl->file), jnl->file, entry->chapter.serial_from, entry->chapter.serial_to, entry->chapter.relative_next + sizeof(journal_jnl_chapter), entry->position); #endif list_dl_iterator_remove(&iter); // free it ZFREE_OBJECT(entry); } else { #if DEBUG log_debug("jnl: %s,%p: shifting out chapter [%u, %u] (%u bytes) from %u to %u", circular_file_name(jnl->file), jnl->file, entry->chapter.serial_from, entry->chapter.serial_to, entry->chapter.relative_next + sizeof(journal_jnl_chapter), entry->position, entry->position - offset); #endif entry->position -= offset; } } } static ya_result journal_jnl_shift_nolock_grow_empty(journal_jnl *jnl, s64 required) { // if the file is empty, then try to grow it ... if allowed s64 file_maximum_size = (s64)circular_file_get_maximum_size(jnl->file); // jnl->size_limit // required if(required > file_maximum_size) { if(required < (s64)jnl->size_limit) { // grow instead // try to grow at twice the size if possible s64 new_size = MIN((s64)required * 2, (s64)jnl->size_limit); ya_result ret = circular_file_grow(jnl->file, new_size); if(ISOK(ret)) { log_debug("jnl: %s,%p: journal [%u, %u] shift triggered a regrow to %llu bytes", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, circular_file_get_size(jnl->file)); } else { ret = CIRCULAR_FILE_SHORT; } return ret; } else { return ZDB_JOURNAL_SIZE_LIMIT_TOO_SMALL; } } else { // there is nothing to shift, this should not have been called return SUCCESS; } } /** * Tries to make room on the journal by shifting the oldest page. * */ static ya_result journal_jnl_shift_nolock(journal_jnl *jnl, s64 required) { ya_result ret; ya_result serial_error; u32 serial_from; u32 serial_to; bool has_lock = journal_jnl_lock_get_serial_range_nolock(jnl, &serial_from, &serial_to); #if DEBUG log_debug("jnl: %s,%p: journal [%u, %u] must shift out at least %lli bytes, safe serial is %u, locked is [%u, %u], current size is %u, locked=%i", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, required, jnl->safe_serial, serial_from, serial_to, circular_file_get_size(jnl->file), has_lock); #endif if(has_lock) { #if DEBUG log_debug("jnl: %s,%p: range [%u; %u] locked", circular_file_name(jnl->file), jnl->file, serial_from, serial_to); #endif yassert(circular_file_get_size(jnl->file) > 0); if(serial_lt(jnl->safe_serial, serial_from)) { serial_from = jnl->safe_serial; serial_error = ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY; // in shift code } else { serial_error = ZDB_JOURNAL_SERIAL_RANGE_LOCKED; } } else { // there may be no locked range because the file is empty if(circular_file_get_size(jnl->file) > 0) { serial_from = jnl->safe_serial; serial_to = jnl->hdr.serial_end; serial_error = ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY; // in shift code } else { ret = journal_jnl_shift_nolock_grow_empty(jnl, required); return ret; } } if(serial_lt(jnl->hdr.serial_begin, serial_from)) { u64 position = circular_file_tell(jnl->file); s64 offset = 0; union journal_jnl_entry entry; u32 serial_begin; // = jnl->hdr.serial_begin; ret = SUCCESS; s64 originally_required = required; while(required > 0) { if(ISOK(ret = circular_file_seek(jnl->file, 0))) { // read what we got if((ret = circular_file_read(jnl->file, &entry.magic, sizeof(u32))) == sizeof(u32)) { switch(entry.magic) { case CHPT_MAGIC: { if(ISOK(ret = circular_file_read(jnl->file, &entry.base.data, sizeof(journal_jnl_chapter) - sizeof(u32)))) { if(serial_le(entry.chapter.serial_to, serial_from)) { // the whole chapter can be dropped offset = sizeof(journal_jnl_chapter) + entry.chapter.relative_next; // offset > 0 #if DEBUG log_debug("jnl: %s,%p: journal [%u, %u] shifting out chapter [%u, %u] (%u bytes)", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, entry.chapter.serial_from, entry.chapter.serial_to, offset); #endif if(ISOK(ret = circular_file_shift(jnl->file, offset))) { // adjust the indexes to reflect the removal of this entry required -= offset; // do the indexes adjustments jnl->hdr.last_soa_offset -= offset; journal_jnl_adjust_chapters_nolock(jnl, offset); journal_jnl_page_cache_shift_nolock(jnl, (u32)offset); serial_begin = entry.chapter.serial_to; jnl->hdr.serial_begin = serial_begin; journal_jnl_set_dirty_nolock(jnl); journal_jnl_header_flush_nolock(jnl); } } else if(serial_ge(entry.chapter.serial_from, serial_from)) { // remove the chunk itself, then proceed scanning the pages offset = sizeof(journal_jnl_chapter); #if DEBUG log_debug("jnl: %s,%p: journal [%u, %u] shifting out head of chapter [%u, %u] (%u bytes)", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, entry.chapter.serial_from, entry.chapter.serial_to, offset); #endif if(ISOK(ret = circular_file_shift(jnl->file, offset))) { // adjust the indexes to reflect the removal of this entry required -= offset; // do the indexes adjustments jnl->hdr.last_soa_offset -= offset; journal_jnl_adjust_chapters_nolock(jnl, offset); journal_jnl_page_cache_shift_nolock(jnl, offset); journal_jnl_set_dirty_nolock(jnl); journal_jnl_header_flush_nolock(jnl); } } else { // there is no continuity between the stored zone and the journal ret = serial_error; } } break; } case PAGE_MAGIC: { if(ISOK(ret = circular_file_read(jnl->file, &entry.base.data, sizeof(journal_jnl_page) - sizeof(u32)))) { if(serial_le(entry.page.serial_to, serial_from)) { // the page can be dropped offset = sizeof(journal_jnl_page) + entry.page.size; #if DEBUG log_debug("jnl: %s,%p: journal [%u, %u] shifting out page [%u, %u] (%u bytes)", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, entry.page.serial_from, entry.page.serial_to, offset); #endif if(ISOK(ret = circular_file_shift(jnl->file, offset))) { // adjust the indexes to reflect the removal of this page required -= offset; // do the indexes adjustments jnl->hdr.last_soa_offset -= offset; journal_jnl_adjust_chapters_nolock(jnl, offset); journal_jnl_page_cache_shift_nolock(jnl, offset); serial_begin = entry.page.serial_to; jnl->hdr.serial_begin = serial_begin; journal_jnl_set_dirty_nolock(jnl); journal_jnl_header_flush_nolock(jnl); } } else { // we reached the limit (and obviously failed reaching our quota) ret = serial_error; break; } } break; } default: { ret = ZDB_JOURNAL_UNEXPECTED_MAGIC; break; } } // switch if(FAIL(ret)) { log_debug("jnl: %s,%p: journal [%u, %u] failed to shift: %r", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, ret); break; } } else // read error reading magic { if(ret == CIRCULAR_FILE_SHORT) { log_err("jnl: %s,%p: journal [%u, %u] failed to shift: failed to read next magic at %llu/%llu: %r", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, circular_file_tell(jnl->file), circular_file_get_size(jnl->file), ret); } else { // nothing follows log_debug("jnl: %s,%p: journal [%u, %u] failed to shift: current size is of %llu is too small, trying to grow the file", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, circular_file_get_size(jnl->file)); if(ISOK(journal_jnl_shift_nolock_grow_empty(jnl, originally_required))) { if(circular_file_get_size(jnl->file) > 0) { ret = ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY; // in shift code } else { ret = SUCCESS; } } else { // could not grow : file is too small ret = ZDB_JOURNAL_SIZE_LIMIT_TOO_SMALL; } } break; } } else { // seek error ? (unlikely) log_err("jnl: %s,%p: journal [%u, %u] failed to shift: failed to move to the beginning of the file: %r", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, ret); break; } } // for circular_file_seek(jnl->file, position - offset); } else { // the journal is already following right after the stored zone ret = serial_error; } return ret; } static void journal_jnl_page_cache_clear_cb(ptr_node *node) { list_dl_node_s *cached_page_node = (list_dl_node_s*)node->value; journal_jnl_page *cached_page = (journal_jnl_page*)cached_page_node->data; ZFREE_OBJECT(cached_page); cached_page_node->data = NULL; } static void journal_jnl_page_cache_clear(journal_jnl *jnl) { ptr_set_callback_and_destroy(&jnl->page_cache.page_from_set, journal_jnl_page_cache_clear_cb); list_dl_clear(&jnl->page_cache.page_mru); } /** * * * @param jnl * @param baos MUST be a byte array output stream, full with the content of a single journal page * @param last_soa_relative_offset * @return */ static ya_result journal_jnl_append_ixfr_stream_write_page(journal_jnl *jnl, output_stream *baos, u32 last_soa_relative_offset) { journal_jnl_page *page = (journal_jnl_page*)bytearray_output_stream_buffer(baos); page->size = bytearray_output_stream_size(baos) - sizeof(journal_jnl_page); ya_result ret; journal_jnl_writelock(jnl); #if DEBUG log_debug("jnl: %s: writing journal page of %u bytes with last SOA relative offset of %u", circular_file_name(jnl->file), page->size, last_soa_relative_offset); #endif u32 page_offset = circular_file_get_size(jnl->file); circular_file_seek(jnl->file, page_offset); for(;;) { ret = circular_file_write(jnl->file, page, bytearray_output_stream_size(baos)); if(ISOK(ret)) { if(!(jnl->hdr.flags & JOURNAL_JNL_FLAGS_INITIALISED)) { // this is a new journal: initialise the base fields jnl->hdr.flags |= JOURNAL_JNL_FLAGS_INITIALISED; jnl->hdr.serial_begin = page->serial_from; } jnl->hdr.serial_end = page->serial_to; jnl->hdr.last_soa_offset = page_offset + last_soa_relative_offset; journal_jnl_set_dirty_nolock(jnl); // keep the page in the cache journal_jnl_page_cache_add_nolock(jnl, page, page_offset); } else if(ret == CIRCULAR_FILE_FULL) { // get the first chunk // see if it covers the safe serial // if not, drop it if(ISOK(ret = journal_jnl_shift_nolock(jnl, page->size))) { if( ((jnl->hdr.serial_end - jnl->hdr.serial_begin) <= 1) && (jnl->safe_serial == jnl->hdr.serial_end) && (circular_file_get_maximum_size(jnl->file) < circular_file_get_pending_size(jnl->file)) ) { // the journal is too small and is allowed to grow: tabula rasa will fix this: log_info("jnl: %s: file is locked too tight but is allowed to expand: clearing it.", circular_file_name(jnl->file)); if(ISOK(ret = journal_jnl_shift_nolock(jnl, circular_file_get_size(jnl->file)))) { log_info("jnl: %s: file is locked too tight but is allowed to expand: cleared it.", circular_file_name(jnl->file)); // done } else { log_err("jnl: %s: file is locked too tight and cannot be cleared.", circular_file_name(jnl->file)); } } page_offset = circular_file_get_size(jnl->file); circular_file_seek(jnl->file, page_offset); continue; } // else we cannot continue shifting: it would break continuity // or a page is (temporarily) locked } break; } journal_jnl_writeunlock(jnl); return ret; } /** * The caller will take action that will end up removing the first page. * Either explicitly, either overwriting it (ie: looping). * * This function ensures that it's OK to do so. * * Returns: * * 0 if it's OK to do so, and no actions were taken, * 1 if it's OK to do so, but the zone needed to be stored * or an error code. * * @param jnl * * @return the state of the operation * */ static const journal_jnl_page empty_page = {PAGE_MAGIC, 0, 0, 0}; static ya_result journal_jnl_append_ixfr_stream(journal *jh, input_stream *ixfr_wire_is) // vtbl { journal_jnl *jnl = (journal_jnl*)jh; output_stream baos; dns_resource_record rr; ya_result ret; int soa_count = 0; int pages_written = 0; u32 soa_serial; u32 last_soa_relative_offset = 0; u8 tmp[4096]; bytearray_output_stream_init_ex(&baos, tmp, sizeof(tmp), BYTEARRAY_DYNAMIC); output_stream_write(&baos, &empty_page, sizeof(journal_jnl_page)); dns_resource_record_init(&rr); for(;;) { if((ret = dns_resource_record_read(&rr, ixfr_wire_is)) <= 0) { // EOF or ERROR if(ret == 0) { if(soa_count == 2) { // ... // If the journal maximum size is to small then there will be a performance hit or worse: // it will be impossible to push the next page to the journal. u32 journal_size_max = (u32)MIN(circular_file_get_maximum_size(jnl->file), (u64)MAX_U32); u32 baos_size = bytearray_output_stream_size(&baos); bool possible_journal_overflow = (baos_size > (journal_size_max >> 1)); for(;;) { if(ISOK(ret = journal_jnl_append_ixfr_stream_write_page(jnl, &baos, last_soa_relative_offset))) { ++pages_written; break; } if(((ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) || (ret == CIRCULAR_FILE_FULL)) && possible_journal_overflow) // after trying to append a page { // the journal size should be set to be MAX(current + baos_size, baos_size * 2) u32 try_grow = MAX(baos_size * 2, journal_size_max + baos_size); try_grow = MIN(try_grow, jnl->size_limit); if(try_grow < journal_size_max) { log_err("jnl: %s: journal size may be too small: tried to write a page of %u bytes into a %u bytes journal", circular_file_name(jnl->file), baos_size, journal_size_max); break; } log_debug("jnl: %s: journal size may be too small: tried to write a page of %u bytes into a %u bytes journal. Growing to %u", circular_file_name(jnl->file), baos_size, journal_size_max, try_grow); circular_file_grow(jnl->file, try_grow); possible_journal_overflow = FALSE; // only try to do this once } else { break; } } } else // e.g.: the master did a shutdown mid-transmission { log_warn("jnl: %s: journal page is incomplete: dropping it", circular_file_name(jnl->file)); ret = 0; // it's not an error per se } } else { log_warn("jnl: %s: could not read next record on the stream: %r", circular_file_name(jnl->file), ret); } bytearray_output_stream_reset(&baos); break; } u16 rtype = rr.tctr.qtype; if(rtype == TYPE_SOA) { if(FAIL(ret = rr_soa_get_serial(rr.rdata, rr.rdata_size, &soa_serial))) { break; } if(soa_count == 0) { // start of the page if(jnl->hdr.flags & JOURNAL_JNL_FLAGS_INITIALISED) { if(jnl->hdr.serial_end != soa_serial) { ret = ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; // serial do not follow break; } } dns_resource_record_write(&rr, &baos); journal_jnl_page *page = (journal_jnl_page*)bytearray_output_stream_buffer(&baos); page->serial_from = soa_serial; } else if(soa_count == 1) { // second half of page last_soa_relative_offset = bytearray_output_stream_size(&baos); dns_resource_record_write(&rr, &baos); journal_jnl_page *page = (journal_jnl_page*)bytearray_output_stream_buffer(&baos); page->serial_to = soa_serial; } else // soa_count == 2 { // end of page: store and continue from here // ... // If the journal maximum size is to small then there will be a performance hit or worse: // it will be impossible to push the next page to the journal. u32 journal_size_max = (u32)MIN(circular_file_get_maximum_size(jnl->file), (u64)MAX_U32); u32 baos_size = bytearray_output_stream_size(&baos); bool possible_journal_overflow = (baos_size > (journal_size_max >> 1)); for(;;) { if(ISOK(ret = journal_jnl_append_ixfr_stream_write_page(jnl, &baos, last_soa_relative_offset))) { ++pages_written; break; } if(((ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) || (ret == CIRCULAR_FILE_FULL)) && possible_journal_overflow) // after trying to append a page { // the journal size should be set to be MAX(current + baos_size, baos_size * 2) u32 try_grow = MAX(baos_size * 2, journal_size_max + baos_size); try_grow = MIN(try_grow, jnl->size_limit); if(try_grow < journal_size_max) { log_err("jnl: %s: journal size may be too small: tried to write a page of %u bytes into a %u bytes journal", circular_file_name(jnl->file), baos_size, journal_size_max); break; } log_debug("jnl: %s: journal size may be too small: tried to write a page of %u bytes into a %u bytes journal. Growing to %u", circular_file_name(jnl->file), baos_size, journal_size_max, try_grow); circular_file_grow(jnl->file, try_grow); possible_journal_overflow = FALSE; // only try to do this once } else { break; } } bytearray_output_stream_reset(&baos); if(FAIL(ret)) { break; } soa_count = 0; output_stream_write(&baos, &empty_page, sizeof(journal_jnl_page)); dns_resource_record_write(&rr, &baos); journal_jnl_page *page = (journal_jnl_page*)bytearray_output_stream_buffer(&baos); page->serial_from = soa_serial; } ++soa_count; } else { dns_resource_record_write(&rr, &baos); } } dns_resource_record_finalize(&rr); output_stream_close(&baos); return ret; } /****************************************************************************** * * Journal Input Stream * This one returns and IXFR stream * ******************************************************************************/ #define JJNLISDT_TAG 0x54445349464a434a struct journal_jnl_input_stream_data { journal_jnl *jnl; journal_range_lock *lock; input_stream buffer_in; u8 *buffer; u8 *soa_record; u32 buffer_size; u16 soa_record_size; }; typedef struct journal_jnl_input_stream_data journal_jnl_input_stream_data; static ya_result journal_jnl_input_stream_read(input_stream* stream, void *buffer_, u32 len) { journal_jnl_input_stream_data *data = (journal_jnl_input_stream_data*)stream->data; u8 *buffer = (u8*)buffer_; ya_result total_bytes_read = 0; for(;;) { int n = input_stream_read(&data->buffer_in, buffer, len); if(FAIL(n)) { if(total_bytes_read == 0) { total_bytes_read = n; } break; } total_bytes_read += n; if(n == (s32)len) { break; } buffer += n; len -= n; // read the next page if(data->lock == NULL) { break; } journal_jnl *jnl = data->jnl; journal_jnl_writelock(jnl); s32 position = journal_jnl_get_position_for_serial_nolock(jnl, data->lock->serial_from); if(position < 0) { #if DEBUG log_debug("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: could not obtain position of first serial %u, data@%p", circular_file_name(jnl->file), jnl->file, data->lock->serial_from, data); #endif break; } circular_file_seek(jnl->file, position); journal_jnl_page page; if((n = circular_file_read(jnl->file, &page, sizeof(journal_jnl_page))) == sizeof(journal_jnl_page)) { if(page.magic == PAGE_MAGIC) { // expected if(serial_ge(page.serial_from, data->lock->serial_to)) { // we reached the end (short read) #if DEBUG log_debug("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: stopped at page [%u; %u] of %u bytes, data@%p", circular_file_name(jnl->file), jnl->file, page.serial_from, page.serial_to, page.size, data); #endif journal_jnl_writeunlock(jnl); break; } #if DEBUG log_debug("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: added page [%u; %u] of %u bytes, data@%p ...", circular_file_name(jnl->file), jnl->file, page.serial_from, page.serial_to, page.size, data); #endif if(data->buffer_size < page.size) { if(data->buffer != NULL) { free(data->buffer); } data->buffer_size = (page.size + 4095) & ~4095; MALLOC_OR_DIE(u8*, data->buffer, data->buffer_size, JNLISDBF_TAG); } if((n = circular_file_read(jnl->file, data->buffer, page.size)) == (s32)page.size) { bytearray_input_stream_update(&data->buffer_in, data->buffer, page.size, FALSE); bytearray_input_stream_reset(&data->buffer_in); // update the locked range data->lock->serial_from = page.serial_to; if(data->lock->serial_from == data->lock->serial_to) { // this is the last page we needed to read journal_jnl_lock_range_remove_nolock(jnl, data->lock); data->lock = NULL; } } else { if(ISOK(n)) { // short read, probable corruption log_err("jnl: %s,%p: failed to read journal page: got %i bytes instead of %i", circular_file_name(jnl->file), jnl->file, n, page.size); n = ZDB_JOURNAL_SHORT_READ; } else { log_err("jnl: %s,%p: failed to read journal page: bad magic number", circular_file_name(jnl->file), jnl->file); } if(total_bytes_read == 0) { total_bytes_read = n; } journal_jnl_writeunlock(jnl); break; } } else // bad magic { log_err("jnl: %s,%p: failed to read journal page header: bad magic number", circular_file_name(jnl->file), jnl->file); if(total_bytes_read == 0) { total_bytes_read = ZDB_JOURNAL_SHORT_READ; } journal_jnl_writeunlock(jnl); break; } } else // wrong read header return value { if(ISOK(n)) { // short read, probable corruption log_err("jnl: %s,%p: failed to read journal page header: got %i bytes instead of %i", circular_file_name(jnl->file), jnl->file, n, sizeof(journal_jnl_page)); n = ZDB_JOURNAL_SHORT_READ; } else { log_err("jnl: %s,%p: failed to read journal page header: %r", circular_file_name(jnl->file), jnl->file, n); } if(total_bytes_read == 0) { total_bytes_read = n; } journal_jnl_writeunlock(jnl); break; } journal_jnl_writeunlock(jnl); } return total_bytes_read; } static ya_result journal_jnl_input_stream_skip(input_stream* stream, u32 len) { //journal_jnl_input_stream_data *data = (journal_jnl_input_stream_data*)stream->data; ya_result ret = 0; u8 tmp[512]; while(len > 0) { int n = journal_jnl_input_stream_read(stream, tmp, MAX(len, sizeof(tmp))); if(FAIL(n)) { if(ret == 0) { ret = n; } break; } ret += n; len -= n; } return ret; } static void journal_jnl_input_stream_close(input_stream* stream) { journal_jnl_input_stream_data *data = (journal_jnl_input_stream_data*)stream->data; input_stream_close(&data->buffer_in); free(data->buffer); if(data->lock != NULL) { journal_jnl_writelock(data->jnl); journal_jnl_lock_range_remove_nolock(data->jnl, data->lock); journal_jnl_writeunlock(data->jnl); } journal_release((journal*)data->jnl); ZFREE_OBJECT(data); input_stream_set_void(stream); } journal* journal_jnl_input_stream_get_journal(input_stream* stream) { journal_jnl_input_stream_data *data = (journal_jnl_input_stream_data*)stream->data; return (journal*)data->jnl; } static const input_stream_vtbl journal_jnl_input_stream_vtbl = { journal_jnl_input_stream_read, journal_jnl_input_stream_skip, journal_jnl_input_stream_close, "journal_jnl_input_stream" }; /* * The last_soa_rr is used for IXFR transfers (it has to be a prefix & suffix to the returned stream) */ static ya_result journal_jnl_get_ixfr_stream_at_serial(journal *jh, u32 serial_from, input_stream *out_input_stream, dns_resource_record *out_last_soa_rr) // vtbl { journal_jnl *jnl = (journal_jnl*)jh; (void)jnl; // lock the journal from the serial_from until the current serial_to journal_jnl_writelock(jnl); journal_range_lock* lock = journal_jnl_lock_range_add_nolock(jnl, serial_from); if(lock == NULL) { #if DEBUG log_err("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: lock range [%u; %u] not in the journal (actually a debug info that I needed clearly visible)", circular_file_name(jnl->file), jnl->file, serial_from, jnl->hdr.serial_end); #endif journal_jnl_writeunlock(jnl); return ERROR; } s32 position = journal_jnl_get_position_for_serial_nolock(jnl, serial_from); #if DEBUG log_debug("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: lock range [%u; %u], position=%i", circular_file_name(jnl->file), jnl->file, serial_from, jnl->hdr.serial_end, position); debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_DEBUG, "jnl"); #endif if(position < 0) { #if DEBUG log_err("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: could not get position for serial %u", circular_file_name(jnl->file), jnl->file, serial_from); #endif journal_jnl_lock_range_remove_nolock(jnl, lock); journal_jnl_writeunlock(jnl); return ERROR; } // start reading ... journal_jnl_input_stream_data *data; ZALLOC_OBJECT_OR_DIE(data, journal_jnl_input_stream_data, JNLISDTA_TAG); journal_acquire((journal*)jnl); data->jnl = jnl; data->lock = lock; bytearray_input_stream_init(&data->buffer_in, NULL, 0, FALSE); data->buffer = NULL; data->buffer_size = 0; data->soa_record = NULL; data->soa_record_size = 0; out_input_stream->data = data; out_input_stream->vtbl = &journal_jnl_input_stream_vtbl; circular_file_seek(jnl->file, position); journal_jnl_page page; ya_result ret; if(ISOK(ret = circular_file_read(jnl->file, &page, sizeof(journal_jnl_page)))) { if(page.magic == PAGE_MAGIC) { // expected assert(page.serial_from == serial_from); if(data->buffer_size < page.size) { if(data->buffer != NULL) { free(data->buffer); } data->buffer_size = (page.size + 4095) & ~4095; MALLOC_OR_DIE(u8*, data->buffer, data->buffer_size, JNLISDBF_TAG); } if((ret = circular_file_read(jnl->file, data->buffer, page.size)) == (s32)page.size) { bytearray_input_stream_update(&data->buffer_in, data->buffer, page.size, FALSE); bytearray_input_stream_reset(&data->buffer_in); // puts the read pointer at the beginning data->buffer_size = page.size; #if DEBUG log_debug("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: added page [%u; %u] of %u bytes, data@%p", circular_file_name(jnl->file), jnl->file, page.serial_from, page.serial_to, page.size, data); #endif if(out_last_soa_rr != NULL) { // read the SOA input_stream is; circular_file_seek(jnl->file, jnl->hdr.last_soa_offset); circular_file_input_stream_noclose_init(&is, jnl->file); ret = dns_resource_record_read(out_last_soa_rr, &is); input_stream_close(&is); if(FAIL(ret)) { #if DEBUG log_err("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: could not read last SOA: %r", circular_file_name(jnl->file), jnl->file, ret); #endif // annoying goto to the error handling goto journal_jnl_get_ixfr_stream_at_serial_error; } } // update the locked range data->lock->serial_from = page.serial_to; if(data->lock->serial_from == data->lock->serial_to) { // this is the last page we needed to read journal_jnl_lock_range_remove_nolock(jnl, data->lock); data->lock = NULL; } #if DEBUG log_debug("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: success", circular_file_name(jnl->file), jnl->file); #endif journal_jnl_writeunlock(jnl); return SUCCESS; } else { if(ISOK(ret)) { // short read, probable corruption log_err("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: got %i bytes instead of %i", circular_file_name(jnl->file), jnl->file, ret, page.size); //ret = /**/ ERROR; } else { log_err("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: error reading page: %r", circular_file_name(jnl->file), jnl->file, ret); } } } #if DEBUG else { log_err("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: unexpected magic %08x", circular_file_name(jnl->file), jnl->file, position, page.magic); } #endif } #if DEBUG else { log_err("jnl: %s,%p: journal_jnl_get_ixfr_stream_at_serial: could not read page at position %u: %r", circular_file_name(jnl->file), jnl->file, position, ret); } #endif journal_jnl_get_ixfr_stream_at_serial_error: input_stream_close(&data->buffer_in); free(data->buffer); journal_jnl_lock_range_remove_nolock(jnl, data->lock); ZFREE_OBJECT(data); journal_jnl_writeunlock(jnl); journal_release((journal*)jnl); return ERROR; } static ya_result journal_jnl_get_first_serial(journal *jh, u32 *serial) // vtbl { ya_result ret = ZDB_JOURNAL_NOT_INITIALISED; journal_jnl *jnl = (journal_jnl*)jh; journal_jnl_readlock(jnl); if(jnl->hdr.flags & JOURNAL_JNL_FLAGS_INITIALISED) { if(serial != NULL) { *serial = jnl->hdr.serial_begin; ret = SUCCESS; } } #if DEBUG log_debug("jnl: %s,%p: returning first serial as %u", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin); #endif journal_jnl_readunlock(jnl); return ret; } static ya_result journal_jnl_get_last_serial(journal *jh, u32 *serial) // vtbl { ya_result ret = ZDB_JOURNAL_NOT_INITIALISED; journal_jnl *jnl = (journal_jnl*)jh; journal_jnl_readlock(jnl); if(jnl->hdr.flags & JOURNAL_JNL_FLAGS_INITIALISED) { if(serial != NULL) { *serial = jnl->hdr.serial_end; ret = SUCCESS; } } #if DEBUG log_debug("jnl: %s,%p: returning last serial as %u", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_end); #endif journal_jnl_readunlock(jnl); return ret; } static ya_result journal_jnl_get_serial_range(journal *jh, u32 *serial_start, u32 *serial_end) // vtbl { ya_result ret = ZDB_JOURNAL_NOT_INITIALISED; journal_jnl *jnl = (journal_jnl*)jh; journal_jnl_readlock(jnl); if(jnl->hdr.flags & JOURNAL_JNL_FLAGS_INITIALISED) { if(serial_start != NULL) { *serial_start = jnl->hdr.serial_begin; ret = SUCCESS; } if(serial_end != NULL) { *serial_end = jnl->hdr.serial_end; ret = SUCCESS; } } #if DEBUG log_debug("jnl: %s,%p: returning serial range %u to %u", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end); #endif journal_jnl_readunlock(jnl); return ret; } static ya_result journal_jnl_truncate_to_size(journal *jh, u32 size_) // vtbl { journal_jnl *jnl = (journal_jnl*)jh; (void)jnl; if(size_ == 0) { journal_jnl_writelock(jnl); #if DEBUG log_debug("jnl: %s,%p: truncating to 0", circular_file_name(jnl->file), jnl->file); #endif if(list_dl_size(&jnl->range_lock) == 0) { // change range // clear lists // delete file /* volatile struct journal_vtbl *vtbl; volatile list_dl_node_s mru_node; volatile int rc; volatile unsigned int _forget:1,_mru:1; */ /* The journal is not like a stream, it's a full standalone entity always returned as a pointer. * So the handler can do whatever it wants after "mru" */ circular_file_unlink(jnl->file); } journal_jnl_writeunlock(jnl); return SUCCESS; } else { #if DEBUG log_info("jnl: %s,%p: truncating to %u not supported (only 0 is)", circular_file_name(jnl->file), jnl->file, size_); #endif return ZDB_JOURNAL_FEATURE_NOT_SUPPORTED; } } static ya_result journal_jnl_truncate_to_serial(journal *jh, u32 serial_) // vtbl { journal_jnl *jnl = (journal_jnl*)jh; union journal_jnl_entry entry; ya_result ret = SUCCESS; journal_jnl_writelock(jnl); #if DEBUG log_debug("jnl: %s,%p: truncating to serial %u", circular_file_name(jnl->file), jnl->file, serial_); #endif while(serial_lt(jnl->hdr.serial_begin, serial_)) { circular_file_seek(jnl->file, 0); if(ISOK(ret = circular_file_read(jnl->file, &entry, sizeof(u32)))) { switch(entry.magic) { case CHPT_MAGIC: { if(ISOK(ret = circular_file_read(jnl->file, &entry, sizeof(entry.chapter) - sizeof(u32)))) { if(serial_le(entry.chapter.serial_to, serial_)) { if(ISOK(ret = journal_jnl_shift_nolock(jnl, entry.chapter.relative_next + sizeof(entry.chapter)))) { } } else { if(ISOK(ret = journal_jnl_shift_nolock(jnl, sizeof(entry.chapter)))) { } } } break; } case PAGE_MAGIC: { if(ISOK(ret = circular_file_read(jnl->file, &entry, sizeof(entry.page) - sizeof(u32)))) { if(ISOK(ret = journal_jnl_shift_nolock(jnl, entry.page.size + sizeof(entry.page)))) { } } break; } default: { break; } } } if(FAIL(ret)) { break; } } #if DEBUG if(FAIL(ret)) { log_err("jnl: %s,%p: truncating to serial %u failed: %r", circular_file_name(jnl->file), jnl->file, serial_, ret); } #endif journal_jnl_writeunlock(jnl); return ret; } /** * * @param jnl * @return */ static ya_result journal_jnl_reopen(journal *jh) // vtbl { #if JOURNAL_JNL_REOPEN_DEBUG journal_jnl *jnl = (journal_jnl*)jh; journal_jnl_writelock(jnl); log_debug("jnl: %s,%p: reopen (no operation)", circular_file_name(jnl->file), jnl->file); journal_jnl_writeunlock(jnl); #else (void)jh; #endif return SUCCESS; } static void journal_jnl_flush(journal *jh) // vtbl { journal_jnl *jnl = (journal_jnl*)jh; journal_jnl_writelock(jnl); #if JOURNAL_JNL_FLUSH_DEBUG log_debug("jnl: %s,%p: flush", circular_file_name(jnl->file), jnl->file); #endif journal_jnl_header_flush_nolock(jnl); journal_jnl_writeunlock(jnl); } static ya_result journal_jnl_close(journal *jh) // vtbl { journal_jnl *jnl = (journal_jnl*)jh; log_debug("jnl: %s,%p: close", circular_file_name(jnl->file), jnl->file); if(jnl->file != NULL) { journal_jnl_writelock(jnl); yassert(jnl->file != NULL); journal_jnl_header_flush_nolock(jnl); circular_file_close(jnl->file); jnl->file = NULL; journal_jnl_writeunlock(jnl); } #if DEBUG else { log_err("jnl: %s,%p: close of an already closed file", circular_file_name(jnl->file), jnl->file); } #endif return SUCCESS; } static void journal_jnl_log_dump_nolock(journal *jh) // vtbl { journal_jnl *jnl = (journal_jnl*)jh; u32 sf = 0; u32 st = 0; journal_jnl_lock_get_serial_range_nolock(jnl, &sf, &st); log_debug3("jnl: %s,%p: [%u; %u] '%s' (%p) lck=%i rc=%i, %u locks: {%u, %u}", circular_file_name(jnl->file), jnl->file, jnl->hdr.serial_begin, jnl->hdr.serial_end, circular_file_name(jnl->file), jnl->file, jnl->mtx.owner, jnl->mtx.count, list_dl_size(&jnl->range_lock), sf, st ); } static void journal_jnl_log_dump(journal *jh) // vtbl { journal_jnl *jnl = (journal_jnl*)jh; journal_jnl_readlock(jnl); journal_jnl_log_dump_nolock(jh); journal_jnl_readunlock(jnl); } static ya_result journal_jnl_get_domain(journal *jh, u8 *out_domain) // vtbl { journal_jnl *jnl = (journal_jnl*)jh; // don't: journal_jnl_readlock(jnl); as the field is constant until the destruction of the journal dnsname_copy(out_domain, jnl->origin); return SUCCESS; } static const u8 * journal_jnl_get_domain_const(const journal *jh) { const journal_jnl *jnl = (const journal_jnl*)jh; return jnl->origin; } static void journal_jnl_destroy(journal *jh) // vtbl { journal_jnl *jnl = (journal_jnl*)jh; journal_jnl_free_default(jnl); } static void journal_jnl_minimum_serial_update(journal *jh, u32 stored_serial) { journal_jnl *jnl = (journal_jnl*)jh; journal_jnl_writelock(jnl); #if DEBUG log_debug3("jnl: %s,%p: setting minimal safe serial to %u", circular_file_name(jnl->file), jnl->file, stored_serial); #endif jnl->safe_serial = stored_serial; journal_jnl_writeunlock(jnl); } static void journal_jnl_maximum_size_update(journal *jh, u32 maximum_size) { journal_jnl *jnl = (journal_jnl*)jh; journal_jnl_writelock(jnl); #if DEBUG log_debug3("jnl: %s,%p: allowing file to grow up to %u bytes", circular_file_name(jnl->file), jnl->file, maximum_size); #endif circular_file_grow(jnl->file, maximum_size); journal_jnl_writeunlock(jnl); } static void journal_jnl_limit_size_update(journal *jh, u32 limit_size) { journal_jnl *jnl = (journal_jnl*)jh; journal_jnl_writelock(jnl); #if DEBUG log_debug3("jnl: %s,%p: limiting file to grow up to %u bytes", circular_file_name(jnl->file), jnl->file, limit_size); #endif jnl->size_limit = limit_size; journal_jnl_writeunlock(jnl); } /******************************************************************************* * * vtbl handling functions * ******************************************************************************/ struct journal_vtbl journal_jnl_vtbl = { journal_jnl_get_format_name, journal_jnl_get_format_version, journal_jnl_reopen, journal_jnl_flush, journal_jnl_close, journal_jnl_append_ixfr_stream, journal_jnl_get_ixfr_stream_at_serial, journal_jnl_get_first_serial, journal_jnl_get_last_serial, journal_jnl_get_serial_range, journal_jnl_truncate_to_size, journal_jnl_truncate_to_serial, journal_jnl_log_dump, journal_jnl_get_domain, journal_jnl_destroy, journal_jnl_get_domain_const, journal_jnl_minimum_serial_update, journal_jnl_maximum_size_update, journal_jnl_limit_size_update, JOURNAL_CLASS_NAME }; static journal_jnl* journal_jnl_alloc_default(const u8 *origin, const char *filename) { (void)filename; journal_jnl *jnl; ZALLOC_OBJECT_OR_DIE(jnl, journal_jnl, JRNLJNL_TAG); ZEROMEMORY(jnl, sizeof(journal_jnl)); jnl->vtbl = &journal_jnl_vtbl; jnl->mru_node.data = jnl; jnl->file = NULL; jnl->origin = dnsname_zdup(origin); jnl->size_limit = MAX_U32; list_dl_init(&jnl->chapters); list_dl_init(&jnl->range_lock); shared_group_mutex_init(&jnl->mtx, &journal_shared_mtx, "journal-jnl"); journal_jnl_page_cache_init(jnl); return jnl; } static void journal_jnl_free_default(journal_jnl* jnl) { #if DEBUG journal_jnl_writelock(jnl); yassert(jnl->rc == 0); log_debug3("jnl: %s,%p: destroy", circular_file_name(jnl->file), jnl->file); journal_jnl_writeunlock(jnl); #endif for(;;) { journal_jnl_chapter_entry *data = (journal_jnl_chapter_entry*)list_dl_remove_first(&jnl->chapters); if(data == NULL) { break; } ZFREE_OBJECT(data); } journal_jnl_page_cache_clear(jnl); if(jnl->file != NULL) { circular_file_close(jnl->file); jnl->file = NULL; } dnsname_zfree(jnl->origin); shared_group_mutex_destroy(&jnl->mtx); #if DEBUG memset(jnl, 0xfe, sizeof(journal_jnl)); jnl->_mru = FALSE; #endif ZFREE_OBJECT(jnl); } /** * The caller guarantees not to call this on an already opened journal * * Should not be called directly (only by journal_* functions. * * Opens or create a journal handling structure. * If the journal did not exist, the structure is returned without a file opened * * @param jh * @param origin * @param workingdir * @param create * * @return */ ya_result journal_jnl_open_file(journal **jhp, const char *filename, const u8* origin, bool create) { // CFJ_PAGE_CACHE -> if(!journal_initialized) { journal_file_pool = file_pool_init_ex("jnl-journal-file-pool", journal_file_pool_size, 65536); if(journal_file_pool == NULL) { return INVALID_STATE_ERROR; } shared_group_shared_mutex_init_recursive(&journal_shared_mtx); journal_initialized = TRUE; } journal_jnl *jnl = NULL; ya_result ret; if(file_exists(filename) || create) { // instantiate and open the journal ret = journal_jnl_init_from_file(&jnl, origin, filename, create); if(ISOK(ret)) { log_debug("jnl: %{dnsname}: opened %s", origin, filename); } else { if(ZDB_JOURNAL_SHOULD_NOT_BE_USED(ret)) { log_err("jnl: %{dnsname}: the journal file %s appears to be corrupted: %r", origin, filename, ret); //#if DEBUG char tmp[PATH_MAX]; snformat(tmp, sizeof(tmp), "%s.%llu.bad", filename, timeus()); log_err("jnl: %{dnsname}: putting aside as %s (DEBUG)", origin, filename); if(rename(filename, tmp) < 0) { log_err("jnl: %{dnsname}: failed to preserve the corrupted journal by renaming '%s' to '%s': %r", origin, filename, tmp, ERRNO_ERROR); if(unlink(filename) < 0) { int err = ERRNO_ERROR; log_err("jnl: %{dnsname}: failed to delete the corrupted journal: %r", origin, err); return err; } } //#else // destroying journal //log_err("jnl: %{dnsname}: deleting %s", origin, filename); //unlink(filename); //#endif } if(create) { log_err("jnl: %{dnsname}: failed to open %s: %r", origin, filename, ret); } else { log_debug("jnl: %{dnsname}: failed to open %s: %r", origin, filename, ret); } if(jnl != NULL) { journal_jnl_destroy((journal*)jnl); #if DEBUG log_debug("jnl: %{dnsname}: journal file cannot be opened/created", origin); #endif } return ZDB_ERROR_ICMTL_NOTFOUND; } #if DEBUG log_debug("jnl: %{dnsname}: journal opened", origin); #endif *jhp = (journal*)jnl; return SUCCESS; } else { #if DEBUG log_debug("jnl: %{dnsname}: journal file not found", origin); #endif return ZDB_ERROR_ICMTL_NOTFOUND; } } /** * The caller guarantees not to call this on an already opened journal * * Should not be called directly (only by journal_* functions. * * Opens or create a journal handling structure. * If the journal did not exist, the structure is returned without a file opened * * @param jh * @param origin * @param workingdir * @param create * * @return */ ya_result journal_jnl_open(journal **jhp, const u8* origin, const char *workingdir, bool create) { // CFJ_PAGE_CACHE <- ya_result ret; *jhp = NULL; // generate the file name char filename[PATH_MAX]; if((jhp == NULL) || (origin == NULL) || (workingdir == NULL)) { return ZDB_JOURNAL_WRONG_PARAMETERS; } #if DEBUG log_debug("jnl: trying to open journal for %{dnsname} in '%s'", origin, workingdir); #endif /* get the soa of the loaded zone */ if(origin[0] != '\0') { if(FAIL(ret = snformat(filename, sizeof(filename), JNL_WIRE_FILE_FORMAT, workingdir, origin))) { #if DEBUG log_debug("jnl: %{dnsname}: journal file name is too long", origin); #endif return ret; } } else { if(FAIL(ret = snformat(filename, sizeof(filename), JNL_WIRE_ROOT_ZONE_FORMAT, workingdir))) { #if DEBUG log_debug("jnl: %{dnsname}: journal file name is too long", JNL_WIRE_ROOT_NAME); #endif return ret; } } ret = journal_jnl_open_file(jhp, filename, origin, create); return ret; } void journal_jnl_finalize() { file_pool_finalize(journal_file_pool); journal_file_pool = 0; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/xfr_copy.c0000644000000000000000000000013214505005531020761 xustar000000000000000030 mtime=1695812441.743972177 30 atime=1695812445.802030296 30 ctime=1695812495.080736067 yadifa-2.6.5-11201/lib/dnsdb/src/xfr_copy.c0000664000374500037450000001451514505005531020731 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup dnscore * @brief * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #include #include "dnsdb/zdb-zone-path-provider.h" #include "dnsdb/xfr_copy.h" #ifndef WIN32 /* it depends if host is DARWIN or LINUX */ #if HAVE_SYS_SYSLIMITS_H #include #elif HAVE_LINUX_LIMITS_H #include #endif /* HAVE_SYS_SYSLIMITS_H */ #endif extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger static ya_result xfr_copy_create_file(output_stream *xfrs, char *file_path, u32 file_path_len, const char* data_path, const u8 *origin, bool data_path_is_target) // should be temp { ya_result ret; (void)data_path; yassert(xfrs != NULL); if(!data_path_is_target) { if(ISOK(ret = zdb_zone_path_get_provider()( origin, file_path, file_path_len, ZDB_ZONE_PATH_PROVIDER_AXFR_FILE|ZDB_ZONE_PATH_PROVIDER_RNDSUFFIX|ZDB_ZONE_PATH_PROVIDER_MKDIR))) { if(ISOK(ret = file_output_stream_create(xfrs, file_path, 0644))) { return ret; } } ret = file_output_stream_create_excl(xfrs, file_path, 0644); } else { mkdir_ex(data_path, 0755, MKDIR_EX_PATH_TO_FILE); ret = file_output_stream_create_excl(xfrs, data_path, 0644); } /* * Do NOT use buffers yet. */ return ret; } ya_result xfr_delete_axfr(const u8 *origin) { ya_result ret; char file_path[PATH_MAX]; if(ISOK(ret = zdb_zone_path_get_provider()( origin, file_path, sizeof(file_path), ZDB_ZONE_PATH_PROVIDER_AXFR_FILE))) { if(unlink(file_path) < 0) // VS false positive: reaching this point, file_path is initialized (by contract) { ret = ERRNO_ERROR; if(ret != MAKE_ERRNO_ERROR(ENOENT)) { log_err("unlink '%s': %r", file_path, ret); } else { log_debug("unlink '%s': %r", file_path, ret); } } } return ret; } ya_result xfr_copy(input_stream *xis, const char *base_data_path, bool base_data_path_is_target) { output_stream xos; ya_result ret; char tmp_file_path[PATH_MAX]; char file_path[PATH_MAX]; u8 buffer[1024]; if(ISOK(ret = xfr_copy_create_file(&xos, tmp_file_path, sizeof(tmp_file_path), base_data_path, xfr_input_stream_get_origin(xis), base_data_path_is_target))) { buffer_output_stream_init(&xos, &xos, 4096); for(;;) { if(dnscore_shuttingdown()) { ret = STOPPED_BY_APPLICATION_SHUTDOWN; break; } ret = input_stream_read(xis, buffer, sizeof(buffer)); if(ret <= 0) { break; } output_stream_write(&xos, buffer, ret); } output_stream_close(&xos); if(ISOK(ret)) { u16 xfr_type = xfr_input_stream_get_type(xis); //u32 last_serial = xfr_input_stream_get_serial(xis); if(!base_data_path_is_target) { if(ISOK(ret = zdb_zone_path_get_provider()( xfr_input_stream_get_origin(xis), file_path, sizeof(file_path), ZDB_ZONE_PATH_PROVIDER_AXFR_FILE|ZDB_ZONE_PATH_PROVIDER_MKDIR))) { unlink(file_path); // VS false positive: reaching this point, file_path is initialized to an ASCIIZ (by contract) if(rename(tmp_file_path, file_path) < 0) { ret = ERRNO_ERROR; } if(ISOK(ret)) { ret = xfr_type; } } else { log_err("xfr_copy: %r", ret); } } } else { unlink(tmp_file_path); } } return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-answer-axfr.c0000644000000000000000000000013214505005531023113 xustar000000000000000030 mtime=1695812441.755972349 30 atime=1695812445.802030296 30 ctime=1695812495.082736095 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-answer-axfr.c0000664000374500037450000015671114505005531023070 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbscheduler Scheduled tasks of the database * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include "dnsdb/zdb-config-features.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #if DNSCORE_HAS_TCP_MANAGER #include #endif #include "dnsdb/zdb_types.h" #include "dnsdb/zdb-zone-arc.h" #include "dnsdb/zdb-zone-journal.h" #include "dnsdb/zdb_zone_axfr_input_stream.h" #include "dnsdb/zdb-zone-answer-axfr.h" #include "dnsdb/zdb-zone-path-provider.h" #define MODULE_MSG_HANDLE g_database_logger #define DEBUG_AXFR_MESSAGES 0 #define ZDB_ZONE_AXFR_MEMFILE_SIZE_THRESHOLD 65536 /** * * dig -p 8053 @172.20.1.69 eu AXFR +time=3600 > eu.axfr * * Max dns packet size / Max number of records in each packet / RDATA Compression enabled * * 65535 1 1 * * ;; Query time: 150452 msec * ;; SERVER: 172.20.1.69#8053(172.20.1.69) * ;; WHEN: Thu Dec 24 09:17:57 2009 * ;; XFR size: 6657358 records (messages 6657358, bytes 417268730) * * 65535 65535 0 * * ;; Query time: 82347 msec * ;; SERVER: 172.20.1.69#8053(172.20.1.69) * ;; WHEN: Wed Dec 23 15:31:23 2009 * ;; XFR size: 6657358 records (messages 4141, bytes 271280613) * * 4096 65535 1 * * ;; Query time: 78042 msec * ;; SERVER: 172.20.1.69#8053(172.20.1.69) * ;; WHEN: Thu Dec 24 09:04:54 2009 * ;; XFR size: 6657358 records (messages 44940, bytes 182745973) * * 65535 65535 1 * * ;; Query time: 88954 msec * ;; SERVER: 172.20.1.69#8053(172.20.1.69) * ;; WHEN: Thu Dec 24 09:08:47 2009 * ;; XFR size: 6657358 records (messages 3133, bytes 205197880) * * So it was obvious but the best system is 4K packets without any record count limit and with compression enabled: * * 4096 because compression only covers the first 4K of the packet * no limit because there is no point (1 is supposed to be nicer but at what cost !) * compression enabled because it reduces the bandwidth AND the time * * With buffering enabled this increases to: * * ;; Query time: 20130 msec * ;; SERVER: 172.20.1.69#8053(172.20.1.69) * ;; WHEN: Thu Dec 24 09:48:39 2009 * ;; XFR size: 6657358 records (messages 44940, bytes 182745973) * * The same transfer to another computer (Nicolas') took only 13 seconds with a release build. * */ #define TCP_BUFFER_SIZE 4096 #define FILE_BUFFER_SIZE 4096 #if DEBUG #define ZDB_ZONE_AXFR_MINIMUM_DUMP_PERIOD 1 // seconds #else #define ZDB_ZONE_AXFR_MINIMUM_DUMP_PERIOD 60 // seconds #endif extern logger_handle* g_database_logger; #ifndef PATH_MAX #error "PATH_MAX not defined" #endif typedef struct zdb_zone_answer_axfr_thread_args zdb_zone_answer_axfr_thread_args; #define SHDQZWAA_TAG 0x4141575a51444853 struct zdb_zone_answer_axfr_thread_args { zdb_zone *zone; message_data *mesg; struct thread_pool_s *disk_tp; #if DNSCORE_HAS_TCP_MANAGER tcp_manager_socket_context_t *sctx; #else int sockfd; #endif ya_result return_code; u32 packet_size_limit; u32 packet_records_limit; u32 journal_from; u32 journal_to; bool compress_dname_rdata; }; typedef struct zdb_zone_answer_axfr_write_file_args zdb_zone_answer_axfr_write_file_args; #define ZAAXFRWF_TAG 0x465752465841415a struct zdb_zone_answer_axfr_write_file_args { output_stream os; // (file) output stream to the AXFR file char *path; char *pathpart; zdb_zone *zone; u32 serial; ya_result return_code; }; #ifdef ZDB_ZONE_AXFR_MEMFILE_SIZE_THRESHOLD static u32 g_zdb_zone_answer_axfr_memfile_size_threshold = ZDB_ZONE_AXFR_MEMFILE_SIZE_THRESHOLD; u32 zdb_zone_answer_axfr_memfile_size_threshold() { return g_zdb_zone_answer_axfr_memfile_size_threshold; } u32 zdb_zone_answer_axfr_memfile_size_threshold_set(u32 new_threshold) { u32 old_threshold = g_zdb_zone_answer_axfr_memfile_size_threshold; g_zdb_zone_answer_axfr_memfile_size_threshold = new_threshold; return old_threshold; } #endif static void zdb_zone_answer_axfr_thread_exit(zdb_zone_answer_axfr_thread_args* data) { log_debug("zone write axfr: %{dnsname}: ended with: %r", data->zone->origin, data->return_code); zdb_zone_release(data->zone); //free(data->directory); free(data); } static void* zdb_zone_answer_axfr_write_file_thread(void* data_) { zdb_zone_answer_axfr_write_file_args* storage = (zdb_zone_answer_axfr_write_file_args*)data_; // os // zone // serial // *return_code /*-----------------------------------------------------------------------*/ buffer_output_stream_init(&storage->os, &storage->os, 4096); // ALEADY LOCKED BY THE CALLER SO NO NEED TO zdb_zone_lock(data->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); #if ZDB_ZONE_KEEP_RAW_SIZE s64 write_start_time = timeus(); output_stream counter_stream; counter_output_stream_data counter_data; counter_output_stream_init(&storage->os, &counter_stream, &counter_data); storage->return_code = zdb_zone_store_axfr(storage->zone, &counter_stream); // zone is locked zdb_zone_unlock(storage->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); output_stream_flush(&counter_stream); output_stream_close(&counter_stream); output_stream_close(&storage->os); storage->zone->wire_size = counter_data.written_count; storage->zone->write_time_elapsed = timeus() - write_start_time; #else storage->return_code = zdb_zone_store_axfr(storage->data->zone, &storage->os); zdb_zone_unlock(storage->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); output_stream_close(&storage->os); #endif if(ISOK(storage->return_code)) { log_info("zone write axfr: %{dnsname}: stored %d", storage->zone->origin, storage->serial); if((storage->pathpart != NULL) && (storage->path != NULL)) { if(rename(storage->pathpart, storage->path) >= 0) { storage->zone->axfr_timestamp = time(NULL); storage->zone->axfr_serial = storage->serial; // here, the zone exists as persistent storage on an .axfr file } else { // cannot rename error : SERVFAIL storage->zone->axfr_timestamp = 1; storage->return_code = ERRNO_ERROR; log_err("zone write axfr: %{dnsname}: error renaming '%s' into '%s': %r", storage->zone->origin, storage->pathpart, storage->path, storage->return_code); } } else { storage->zone->axfr_timestamp = 1; storage->zone->axfr_serial = storage->serial; } } else { log_err("zone write axfr: %{dnsname}: error writing '%s': %r", storage->zone->origin, storage->pathpart, storage->return_code); // cannot create error : SERVFAIL storage->zone->axfr_timestamp = 1; storage->zone->axfr_serial = storage->serial - 1; } zdb_zone_clear_dumping_axfr(storage->zone); zdb_zone_release(storage->zone); storage->zone = NULL; free(storage->path); free(storage->pathpart); free(storage); return NULL; } static void zdb_zone_answer_axfr_write(zdb_zone *data_zone, output_stream *os, u32 serial, const char *path, const char *pathpart, struct thread_pool_s *disk_tp) { zdb_zone_answer_axfr_write_file_args *store_axfr_args; MALLOC_OR_DIE(zdb_zone_answer_axfr_write_file_args*, store_axfr_args, sizeof(zdb_zone_answer_axfr_write_file_args), ZAAXFRWF_TAG); store_axfr_args->os = *os; store_axfr_args->pathpart = strdup(pathpart); store_axfr_args->path = strdup(path); store_axfr_args->zone = data_zone; store_axfr_args->serial = serial; store_axfr_args->return_code = SUCCESS; /* * This is how it is supposed to be. Double lock, unlocked when the file has been stored. * Again: do not try to remove this lock. */ zdb_zone_acquire(data_zone); zdb_zone_lock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); // RC was already + 1 by the (async) caller log_debug("zone write axfr: %{dnsname}: zone with serial %d is being written on disk", data_zone->origin, serial); // the ZDB_ZONE_STATUS_DUMPING_AXFR status will be cleared in the thread if(disk_tp != NULL) { thread_pool_enqueue_call(disk_tp, zdb_zone_answer_axfr_write_file_thread, store_axfr_args, NULL, "zone-writer-axfr"); } else { zdb_zone_answer_axfr_write_file_thread(store_axfr_args); } } static void* zdb_zone_answer_axfr_thread(void* data_) { zdb_zone_answer_axfr_thread_args* data = (zdb_zone_answer_axfr_thread_args*)data_; message_data *mesg = data->mesg; zdb_zone *data_zone = data->zone; // already RCed ... output_stream os; input_stream fis; u64 total_bytes_sent = 0; ya_result ret; u32 serial = 0; u32 now = time(NULL); u32 journal_from = data->journal_from; u32 journal_to = data->journal_to; int path_len; u8 data_zone_origin[MAX_DOMAIN_LENGTH]; char buffer[PATH_MAX + 8]; #if DNSCORE_HAS_TCP_MANAGER if(!tcp_manager_is_valid(data->sctx)) { data->return_code = MAKE_ERRNO_ERROR(ENOTSOCK); log_err("zone write axfr: %{dnsname}: invalid connection", data->zone->origin); zdb_zone_answer_axfr_thread_exit(data); message_free(mesg); return NULL; } tcp_manager_socket_context_t *sctx = data->sctx; #if DEBUG log_debug("zone write axfr: %{dnsname}: socket is %d", data->zone->origin, tcp_manager_socket(sctx)); #endif #else int tcpfd = data->sockfd; data->sockfd = -1; if(tcpfd < 0) { data->return_code = MAKE_ERRNO_ERROR(ENOTSOCK); log_err("zone write axfr: %{dnsname}: invalid socket", data->zone->origin); zdb_zone_answer_axfr_thread_exit(data); message_free(mesg); return NULL; } #if DEBUG log_debug("zone write axfr: %{dnsname}: socket is %d", data->zone->origin, tcpfd); #endif #endif /** * The zone could already be dumping in the disk. * If it's the case, then the dump file needs to be read and sent until marked as "done". */ /* locks the zone for a reader */ message_set_additional_count_ne(mesg, 0); #if DEBUG log_debug("zone write axfr: %{dnsname}: locking for AXFR", data->zone->origin); #endif zdb_zone_lock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); if(zdb_zone_invalid(data_zone)) { zdb_zone_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); log_err("zone write axfr: %{dnsname}: marked as invalid", data_zone->origin); #if DNSCORE_HAS_TCP_MANAGER if(ISOK(ret = message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcp_manager_socket(sctx)))) { tcp_manager_write_update(sctx, ret); } tcp_manager_close(sctx); #else message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcpfd); #endif zdb_zone_answer_axfr_thread_exit(data); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_abortive_close(tcpfd); close_ex(tcpfd); #endif message_free(mesg); return NULL; } #if DEBUG log_debug("zone write axfr: %{dnsname}: checking serial number", data_zone->origin); #endif if(FAIL(zdb_zone_getserial(data_zone, &serial))) // zone is locked { zdb_zone_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); log_err("zone write axfr: %{dnsname}: no SOA", data_zone->origin); #if DNSCORE_HAS_TCP_MANAGER if(ISOK(ret = message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcp_manager_socket(sctx)))) { tcp_manager_write_update(sctx, ret); } tcp_manager_close(sctx); #else message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcpfd); #endif zdb_zone_answer_axfr_thread_exit(data); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_abortive_close(tcpfd); close_ex(tcpfd); #endif message_free(mesg); return NULL; } u32 packet_size_limit = data->packet_size_limit; if(packet_size_limit < message_get_buffer_size_max(mesg)) { packet_size_limit = message_get_buffer_size_max(mesg); } u32 packet_records_limit = data->packet_records_limit; /* If it is set to 0, it means there is no limit. */ if(packet_records_limit == 0) { packet_records_limit = 0xffffffff; } bool compress_dname_rdata = data->compress_dname_rdata; dnsname_copy(data_zone_origin, data_zone->origin); empty_input_stream_init(&fis); #ifdef ZDB_ZONE_AXFR_MEMFILE_SIZE_THRESHOLD /* * @note 20220209 edf -- If the zone is relatively small, there is no need to prepare an image on the disk. * Instead, snapshot to memory. * The treshold is set to 64KB (way more than the needs of 99% of use-cases) * TLDs will still use the through-storage branch of the code. */ if(data->zone->wire_size < g_zdb_zone_answer_axfr_memfile_size_threshold) { output_stream counter_stream; counter_output_stream_data counter_data; output_stream os; s64 write_start_ts = timeus(); bytearray_output_stream_init_ex(&os, NULL, (data->zone->wire_size * 3) / 2, BYTEARRAY_DYNAMIC); counter_output_stream_init(&os, &counter_stream, &counter_data); zdb_zone_store_axfr(data_zone, &counter_stream); output_stream_flush(&counter_stream); size_t stream_size = bytearray_output_stream_size(&os); u8 *stream_buffer = bytearray_output_stream_detach(&os); bytearray_input_stream_init(&fis, stream_buffer, stream_size, TRUE); output_stream_close(&counter_stream); // NOTE: this does virtually nothing. Counter streams do not hold memory nor close their filtered stream output_stream_close(&os); data_zone->wire_size = counter_data.written_count; data_zone->write_time_elapsed = timeus() - write_start_ts; data->return_code = SUCCESS; log_debug("zone write axfr: %{dnsname}: zone with serial %d is being written on disk", data_zone_origin, serial); zdb_zone_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); data_zone = NULL; #if DNSCORE_HAS_TCP_MANAGER sctx = tcp_manager_context_acquire(sctx); // because it will be release zdb_zone_answer_axfr_thread_exit #endif zdb_zone_answer_axfr_thread_exit(data); data = NULL; // This ensures a crash if data is used } else { #endif /* * The zone could be being written to the disk right now. * axfr_timestamp = 0, file exists as a .part (or as a normal file, if race) * * The file could not being written to the disk * axfr_timestamp != 0, file exists as a normal file * axfr_timestamp = 1, no idea of the status * * Whatever of these two, the file existence should be tested * If the file does not exists, it should be dumped * * The file serial on disk may be too old, in that case it should be written again * (too old: time and/or serial increment and/or journal size) * */ for(int countdown = 5; countdown >= 0; --countdown) { if(countdown == 0) { // tried to many times: servfail zdb_zone_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); data->return_code = ZDB_ERROR_COULDNOTOOBTAINZONEIMAGE; // AXFR file creation failed log_warn("zone write axfr: %{dnsname}: could not prepare file", data_zone_origin); message_make_error(mesg, FP_CANNOT_HOLD_AXFR_DATA); if(message_has_tsig(mesg)) { tsig_sign_answer(mesg); } #if DEBUG_AXFR_MESSAGES LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG) message_log(MODULE_MSG_HANDLE, MSG_DEBUG, mesg); #endif #if DNSCORE_HAS_TCP_MANAGER if(ISOK(ret = message_send_tcp(mesg, tcp_manager_socket(sctx)))) { tcp_manager_write_update(sctx, ret); } else { log_warn("zone write axfr: %{dnsname}: tcp write error: %r", data_zone_origin, ret); tcp_set_abortive_close(tcp_manager_socket(sctx)); } tcp_manager_close(sctx); #else if(FAIL(ret = message_send_tcp(mesg, tcpfd))) { log_warn("zone write axfr: %{dnsname}: tcp write error: %r", data_zone_origin, ret); tcp_set_abortive_close(tcpfd); } tcp_set_abortive_close(tcpfd); close_ex(tcpfd); #endif zdb_zone_answer_axfr_thread_exit(data); message_free(mesg); return NULL; } if(dnscore_shuttingdown()) { /* Yes, it means there will be a "leak" but the app is shutting down anyway ... */ ret = STOPPED_BY_APPLICATION_SHUTDOWN; zdb_zone_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); log_warn("zone write axfr: %{dnsname}: %r", data_zone_origin, ret); data->return_code = ret; data_zone->axfr_timestamp = 1; #if DNSCORE_HAS_TCP_MANAGER if(ISOK(ret = message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcp_manager_socket(sctx)))) { tcp_manager_write_update(sctx, ret); } tcp_manager_close(sctx); #else message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcpfd); #endif zdb_zone_answer_axfr_thread_exit(data); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_abortive_close(tcpfd); close_ex(tcpfd); #endif message_free(mesg); return NULL; } // get the file path and name if(FAIL(ret = zdb_zone_path_get_provider()( data_zone_origin, buffer, sizeof(buffer), ZDB_ZONE_PATH_PROVIDER_AXFR_FILE|ZDB_ZONE_PATH_PROVIDER_MKDIR))) { // failed to get the name zdb_zone_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); // RC decremented log_err("zone write axfr: %{dnsname}: unable to get path: %r", data_zone_origin, ret); data->return_code = ret; #if DNSCORE_HAS_TCP_MANAGER if(ISOK(ret = message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcp_manager_socket(sctx)))) { tcp_manager_write_update(sctx, ret); } tcp_manager_close(sctx); #else message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcpfd); #endif zdb_zone_answer_axfr_thread_exit(data); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_abortive_close(tcpfd); close_ex(tcpfd); #endif message_free(mesg); return NULL; } path_len = ret; u32 axfr_dump_age = (now >= data_zone->axfr_timestamp)?now - data_zone->axfr_timestamp:0; // try to set the dumping axfr status bool have_writing_rights = !zdb_zone_get_set_dumping_axfr(data_zone); // if status didn't had the flag, we have ownership bool too_old = (axfr_dump_age > ZDB_ZONE_AXFR_MINIMUM_DUMP_PERIOD); bool different_serial = (data_zone->axfr_serial != serial); bool cannot_be_followed = FALSE; // the too_old rule should be instant if the zone on disk cannot be followed by the journal if(journal_from != journal_to) { if(serial_lt(data_zone->axfr_serial, journal_from)) { log_debug("zone write axfr: %{dnsname}: serial of axfr image older than journal start (%u lt %u)", data_zone_origin, data_zone->axfr_serial, journal_from); cannot_be_followed = TRUE; } } else { cannot_be_followed = TRUE; } bool should_write = have_writing_rights && (different_serial && (too_old || cannot_be_followed)); if(!should_write && have_writing_rights) { // if the file cannot be read (most likely doesn't exist) then it should be written should_write = FAIL(access_check(buffer, ACCESS_CHECK_READ)); } if(should_write) { // the serial on disk is not the one in memory AND // it has been written a sufficient long time ago ... // it is not being written log_debug("zone write axfr: %{dnsname}: serial = %d, zone serial = %d; AXFR timestamp = %d; last written %d seconds ago", data_zone_origin, data_zone->axfr_serial, serial, data_zone->axfr_timestamp, axfr_dump_age); // trigger a new update : delete the old files unlink(buffer); yassert((path_len > 0) && ((u32)path_len < sizeof(buffer) - 6)); memcpy(&buffer[path_len], ".part", 6); unlink(buffer); // trigger a new update // create a new file (pathpart) log_info("zone write axfr: %{dnsname}: storing at serial %d", data_zone_origin, serial); if(FAIL(ret = file_output_stream_create_excl(&os, buffer, 0644))) { zdb_zone_clear_dumping_axfr(data_zone); log_debug("zone write axfr: %{dnsname}: could not exclusively create '%s': %r", data_zone_origin, buffer, ret); if(ret == MAKE_ERRNO_ERROR(EEXIST)) { log_err("zone write axfr: %{dnsname}: file unexpectedly exists '%s': %r", data_zone_origin, buffer, ret); // race condition creating the file : try again continue; } zdb_zone_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); // RC decremented log_err("zone write axfr: %{dnsname}: file create error for '%s': %r", data_zone_origin, buffer, ret); data->return_code = ret; #if DNSCORE_HAS_TCP_MANAGER if(ISOK(ret = message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcp_manager_socket(sctx)))) { tcp_manager_write_update(sctx, ret); } tcp_manager_close(sctx); #else message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcpfd); #endif zdb_zone_answer_axfr_thread_exit(data); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_abortive_close(tcpfd); close_ex(tcpfd); #endif message_free(mesg); return NULL; } /* * Return value check irrelevant here. It can only fail if the filtered stream has a NULL vtbl * This is not the case here since we just opened successfully the file stream. */ data_zone->axfr_timestamp = 0; /* * Now that the file has been created, the background writing thread can be called * the readers will wait "forever" that the file is written but they need the file to exist */ char *pathpart = strdup(buffer); buffer[path_len] = '\0'; const char *path = buffer; zdb_zone_answer_axfr_write(data_zone, &os, serial, path, pathpart,data->disk_tp); free(pathpart); // the file seems ok, let's start streaming it ret = zdb_zone_axfr_input_stream_open_with_path(&fis, data_zone, buffer); if(FAIL(ret)) { // opening failed but it should not have : try again if(countdown > 0) { log_debug("zone write axfr: %{dnsname}: after write, could not open %s: %r", data_zone_origin, buffer, ret); } else { log_warn("zone write axfr: %{dnsname}: after write, could not open %s: %r", data_zone_origin, buffer, ret); } continue; } data->return_code = SUCCESS; log_debug("zone write axfr: %{dnsname}: zone with serial %d is being written on disk", data_zone_origin, serial); zdb_zone_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); data_zone = NULL; #if DNSCORE_HAS_TCP_MANAGER sctx = tcp_manager_context_acquire(sctx); // because it will be release zdb_zone_answer_axfr_thread_exit #endif zdb_zone_answer_axfr_thread_exit(data); data = NULL; // This ensures a crash if data is used break; } else { // if !have_writing_rights, somebody is writing the part file, // that's the one that should be followed if(!have_writing_rights) { memcpy(&buffer[path_len], ".part", 6); if(access(buffer, R_OK | F_OK) >= 0) { // file exists and the file seems usable, let's start streaming it ret = zdb_zone_axfr_input_stream_open_with_path(&fis, data_zone, buffer); if(FAIL(ret)) { // opening failed but it should not have: try again log_warn("zone write axfr: %{dnsname}: could not open %s: %r", data_zone_origin, buffer, ret); // or servfail ? continue; } data->return_code = SUCCESS; log_info("zone write axfr: %{dnsname}: releasing implicit write lock, serial is %d", data_zone_origin, serial); zdb_zone_acquire(data_zone); #if DNSCORE_HAS_TCP_MANAGER sctx = tcp_manager_context_acquire(sctx); // because it will be release zdb_zone_answer_axfr_thread_exit #endif zdb_zone_answer_axfr_thread_exit(data); // WARNING: From this point forward, 'data' cannot be used anymore data = NULL; // This ensures a crash if data is used zdb_zone_release_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); data_zone = NULL; break; } // file could not be properly accessed, maybe it just finished buffer[path_len] = '\0'; } if(access(buffer, R_OK | F_OK) >= 0) { // file exists and the file seems usable, let's start streaming it ret = zdb_zone_axfr_input_stream_open_with_path(&fis, data_zone, buffer); if(have_writing_rights) { zdb_zone_clear_dumping_axfr(data_zone); } if(FAIL(ret)) { // opening failed but it should not have: try again log_warn("zone write axfr: %{dnsname}: could not open %s: %r", data_zone_origin, buffer, ret); continue; } data->return_code = SUCCESS; log_info("zone write axfr: %{dnsname}: releasing implicit write lock, serial is %d", data_zone_origin, serial); zdb_zone_acquire(data_zone); #if DNSCORE_HAS_TCP_MANAGER sctx = tcp_manager_context_acquire(sctx); // because it will be release zdb_zone_answer_axfr_thread_exit #endif zdb_zone_answer_axfr_thread_exit(data); // WARNING: From this point forward, 'data' cannot be used anymore data = NULL; // This ensures a crash if data is used zdb_zone_release_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); data_zone = NULL; break; } // file does not exist, or there is an error accessing the file if(have_writing_rights) { zdb_zone_clear_dumping_axfr(data_zone); } if(errno != ENOENT) { // the error is not that the file does not exists : give up if(have_writing_rights) { zdb_zone_clear_dumping_axfr(data_zone); } ret = ERRNO_ERROR; zdb_zone_unlock(data_zone, ZDB_ZONE_MUTEX_SIMPLEREADER); // RC decremented log_err("zone write axfr: %{dnsname}: error accessing '%s': %r", data_zone_origin, buffer, ret); data->return_code = ret; data_zone->axfr_timestamp = 1; #if DNSCORE_HAS_TCP_MANAGER if(ISOK(ret = message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcp_manager_socket(sctx)))) { tcp_manager_write_update(sctx, ret); } tcp_manager_close(sctx); #else message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcpfd); #endif zdb_zone_answer_axfr_thread_exit(data); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_abortive_close(tcpfd); close_ex(tcpfd); #endif message_free(mesg); return NULL; } // could not access any of the two expected files, try again } } // for(;;) #if ZDB_ZONE_AXFR_MEMFILE_SIZE_THRESHOLD } #endif /****************************************************************************************************************** * * data pointer cannot be used beyond this point * ******************************************************************************************************************/ message_set_buffer_size(mesg, 0x8000); // limit to 32KB, knowing perfectly well the buffer is actually 64KB log_info("zone write axfr: %{dnsname}: sending AXFR with serial %d", data_zone_origin, serial); #if DEBUG if(fis.data == NULL) { log_err("zone write axfr: %{dnsname}: empty stream", data_zone_origin); goto scheduler_queue_zone_write_axfr_thread_exit; } #endif #define USE_TCPOS 0 #if USE_TCPOS output_stream tcpos; fd_output_stream_attach(&tcpos, tcpfd); buffer_output_stream_init(&tcpos, &tcpos, TCP_BUFFER_SIZE); #endif if(!bytearray_input_stream_is_instance_of(&fis)) { buffer_input_stream_init(&fis, &fis, FILE_BUFFER_SIZE); } // The correct AXFR answer sets authoritative message_set_authoritative_answer(mesg); // Microsoft DNS server do not set the authoritative flag //message_set_answer(mesg); message_set_answer_count_ne(mesg, NETWORK_ONE_16); packet_writer pw; u32 packet_count = 0; u16 an_count = 0; // @note 20091223 edf -- With TSIG enabled this limit will be dynamic and change to a lower bound for every 100th packet #if ZDB_HAS_TSIG_SUPPORT tsig_tcp_message_position pos = TSIG_NOWHERE; #endif yassert(message_get_size(mesg) <= packet_size_limit); // should have already been tested by the caller size_t message_base_size = message_get_size(mesg); packet_writer_init(&pw, message_get_buffer(mesg), message_base_size, packet_size_limit); for(;; packet_count--) /* using path as the buffer */ { struct type_class_ttl_rdlen tctrl; ya_result qname_len; ya_result n; if(dnscore_shuttingdown()) { log_info("zone write axfr: %{dnsname}: stopping transfer to %{sockaddr} because of application shutdown", data_zone_origin, message_get_sender_sa(mesg)); break; } /* Read the next DNAME from the stored AXFR */ if(FAIL(qname_len = input_stream_read_dnsname(&fis, (u8*)buffer))) // length checked { /* qname_len is an error code */ log_err("zone write axfr: %{dnsname}: error reading next record domain: %r", data_zone_origin, qname_len); break; } /* * NOTE: There cannot be an "EMPTY" AXFR. There is always the origin. So I don't have to * check TSIG for an empty message because there aren't any. */ /* If there are no records anymore */ if(qname_len == 0) { /* If records are still to be sent */ if(an_count > 0) { /* write them */ message_set_authoritative_answer(mesg); message_set_size(mesg, packet_writer_get_offset(&pw)); message_set_answer_count(mesg, an_count); #if ZDB_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) { message_set_additional_section_ptr(mesg, packet_writer_get_next_u8_ptr(&pw)); message_reset_buffer_size(mesg); if(pos != TSIG_START) { ret = tsig_sign_tcp_message(mesg, pos); } else { ret = tsig_sign_answer(mesg); } if(FAIL(ret)) { log_err("zone write axfr: %{dnsname}: failed to sign the answer: %r", data_zone_origin, ret); break; } packet_writer_set_offset(&pw, message_get_size(mesg)); } /* if message_has_tsig */ #endif #if DEBUG_AXFR_MESSAGES LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG) message_log(MODULE_MSG_HANDLE, MSG_DEBUG, mesg); #endif #if DNSCORE_HAS_TCP_MANAGER if(ISOK(n = message_send_tcp(mesg, tcp_manager_socket(sctx)))) { tcp_manager_write_update(sctx, n); } else { log_err("zone write axfr: %{dnsname}: error sending AXFR packet to %{sockaddr}: %r", data_zone_origin, message_get_sender_sa(mesg), n); } #else #if USE_TCPOS if(ISOK(n = message_write_tcp(mesg, &tcpos))) #else if(ISOK(n = message_send_tcp(mesg, tcpfd))) #endif { } else { log_err("zone write axfr: %{dnsname}: error sending AXFR packet to %{sockaddr}: %r", data_zone_origin, message_get_sender_sa(mesg), n); } #endif total_bytes_sent += message_get_size(mesg); message_set_buffer_size(mesg, 0x8000); // limit to 32KB, knowing perfectly well the buffer is actually 64KB // in effect, an_records_count = 0; } break; /* done */ } /* read the next type+class+ttl+rdatalen from the stored AXFR */ if(FAIL(n = input_stream_read_fully(&fis, &tctrl, 10))) { log_err("zone write axfr: %{dnsname}: error reading record: %r", data_zone_origin, n); break; } u16 rdata_len = ntohs(tctrl.rdlen); // if for any reason the rdata_len is bigger than the 4K buffer size (not supposed to happen as even keys are not bigger than 1K) if(rdata_len > sizeof(buffer)) { log_err("zone write axfr: %{dnsname}: record data length is too big (%i)", data_zone_origin, rdata_len); #if DEBUG log_memdump(g_database_logger, MSG_DEBUG, &tctrl, 10, 16); #endif break; } s32 record_len = qname_len + 10 + rdata_len; /* Check if we have enough room available for the next record */ s32 remaining_capacity = (packet_writer_get_limit(&pw) / 2) - packet_writer_get_offset(&pw); if((an_count >= packet_records_limit) || (remaining_capacity < record_len)) { // not enough room if(an_count == 0) { log_err("zone write axfr: %{dnsname}: error preparing packet: next record is too big (%d)", data_zone_origin, record_len); break; } message_set_authoritative_answer(mesg); message_set_answer_count(mesg, an_count); message_set_size(mesg, packet_writer_get_offset(&pw)); #if ZDB_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) { message_reset_buffer_size(mesg); message_set_additional_section_ptr(mesg, packet_writer_get_next_u8_ptr(&pw)); if(FAIL(ret = tsig_sign_tcp_message(mesg, pos))) { log_err("zone write axfr: %{dnsname}: failed to sign the answer: %r", data_zone_origin, ret); break; } packet_writer_set_offset(&pw, message_get_size(mesg)); } #endif /* Flush the packet. */ #if DEBUG_AXFR_MESSAGES LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG) message_log(MODULE_MSG_HANDLE, MSG_DEBUG, mesg); #endif #if DNSCORE_HAS_TCP_MANAGER if(ISOK(n = message_send_tcp(mesg, tcp_manager_socket(sctx)))) { tcp_manager_write_update(sctx, n); } else { log_err("zone write axfr: %{dnsname}: error sending packet to %{sockaddr}: %r", data_zone_origin, message_get_sender_sa(mesg), n); break; } #else #if USE_TCPOS if(FAIL(n = message_write_tcp(mesg, &tcpos))) #else if(FAIL(n = message_send_tcp(mesg, tcpfd))) #endif { log_err("zone write axfr: %{dnsname}: error sending packet to %{sockaddr}: %r", data_zone_origin, message_get_sender_sa(mesg), n); break; } #endif total_bytes_sent += message_get_size(mesg); #if ZDB_HAS_TSIG_SUPPORT pos = TSIG_MIDDLE; #endif an_count = 0; // Packet flushed ... // Reset the packet // Remove the TSIG. message_set_authoritative_answer(mesg); message_set_query_answer_authority_additional_counts_ne(mesg, NU16(1), 0, 0, 0); message_set_buffer_size(mesg, 0x8000); // limit to 32KB, knowing perfectly well the buffer is actually 64KB packet_writer_init(&pw, message_get_buffer(mesg), message_base_size, packet_size_limit); } /** NOTE: if tctrl.qtype == TYPE_SOA, then we are at the beginning OR the end of the AXFR stream */ #if ZDB_HAS_TSIG_SUPPORT if(tctrl.qtype == TYPE_SOA) { /* First SOA will make the pos move from NOWHERE to BEGIN */ /* Second SOA will make the pos move from MIDDLE to END */ /* EXCEPT that if there is only 1 packet for the whole zone the value must be TSIG_START */ if(pos != TSIG_START) { pos++; } } #endif an_count++; packet_writer_add_fqdn(&pw, (const u8*)buffer); packet_writer_add_bytes(&pw, (const u8*)&tctrl, 10); if(compress_dname_rdata != 0) { u16 rdata_offset = packet_writer_get_offset(&pw); switch(tctrl.qtype) { case TYPE_MX: { if(FAIL(n = input_stream_read_fully(&fis, buffer, rdata_len))) { log_err("zone write axfr: %{dnsname}: error reading MX record: %r", data_zone_origin, n); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } // verify fqdn u32 len = dnsname_len((const u8*)&buffer[2]); if(len > MAX_DOMAIN_LENGTH) { log_err("zone write axfr: %{dnsname}: rdata fqdn is too long", data_zone_origin); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } if(len + 2 != rdata_len) { log_err("zone write axfr: %{dnsname}: expected rdata of %i bytes but got %i", data_zone_origin, rdata_len, len + 2); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } packet_writer_add_bytes(&pw, (const u8*)buffer, 2); packet_writer_add_fqdn(&pw, (const u8*)&buffer[2]); SET_U16_AT(pw.packet[rdata_offset - 2], htons(pw.packet_offset - rdata_offset)); // set RDATA size continue; } case TYPE_NS: case TYPE_CNAME: case TYPE_DNAME: case TYPE_PTR: case TYPE_MB: case TYPE_MD: case TYPE_MF: case TYPE_MG: case TYPE_MR: { if(FAIL(n = input_stream_read_fully(&fis, buffer, rdata_len))) // rdata_len < sizeof(buffer) { log_err("zone write axfr: %{dnsname}: error reading %{dnstype} record: %r", data_zone_origin, &tctrl.qtype, n); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } // verify fqdn u32 len = dnsname_len((const u8*)buffer); if(len > MAX_DOMAIN_LENGTH) { log_err("zone write axfr: %{dnsname}: rdata fqdn is too long", data_zone_origin); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } if(len != rdata_len) { log_err("zone write axfr: %{dnsname}: expected rdata of %i bytes but got %i", data_zone_origin, rdata_len, len); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } // the write buffer is bigger than the limit and the fqdn size has been verified packet_writer_add_fqdn(&pw, (const u8*)buffer); SET_U16_AT(pw.packet[rdata_offset - 2], htons(pw.packet_offset - rdata_offset)); // set RDATA size continue; } case TYPE_SOA: { if(FAIL(n = input_stream_read_fully(&fis, buffer, rdata_len))) // rdata_len < sizeof(buffer) { log_err("zone write axfr: %{dnsname}: error reading SOA record: %r", data_zone_origin, n); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } // verify fqdn const u8 *m = (const u8*)buffer; u32 mlen = dnsname_len(m); if(mlen > MAX_DOMAIN_LENGTH) { log_err("zone write axfr: %{dnsname}: mname is too long", data_zone_origin); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } const u8 *r = &m[mlen]; u32 rlen = dnsname_len(r); if(rlen > MAX_DOMAIN_LENGTH) { log_err("zone write axfr: %{dnsname}: rname is too long", data_zone_origin); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } if(mlen + rlen + 20 != rdata_len) { log_err("zone write axfr: %{dnsname}: expected rdata of %i bytes but got %i", data_zone_origin, rdata_len, mlen + rlen + 20); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } // the write buffer is bigger than the limit and the fqdn size has been verified packet_writer_add_fqdn(&pw, m); // the write buffer is bigger than the limit and the fqdn size has been verified packet_writer_add_fqdn(&pw, r); packet_writer_add_bytes(&pw, &r[rlen], 20); SET_U16_AT(pw.packet[rdata_offset - 2], htons(pw.packet_offset - rdata_offset)); // set RDATA size continue; } case TYPE_RRSIG: { if(FAIL(n = input_stream_read_fully(&fis, buffer, rdata_len))) // rdata_len < sizeof(buffer) { log_err("zone write axfr: %{dnsname}: error reading RRSIG record: %r", data_zone_origin, n); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } s32 remaining = rdata_len; remaining -= RRSIG_RDATA_HEADER_LEN; if(remaining < 0) { log_err("zone write axfr: %{dnsname}: error reading RRSIG record: rdata is too short", data_zone_origin); /* * GOTO !!! (thread carefully ) */ goto scheduler_queue_zone_write_axfr_thread_exit; } packet_writer_add_bytes(&pw, (const u8*)buffer, RRSIG_RDATA_HEADER_LEN); const u8 *o = (const u8*)&buffer[18]; u32 olen = dnsname_len(o); remaining -= olen; if(remaining < 0) { log_err("zone write axfr: %{dnsname}: error reading RRSIG record: rdata is too short", data_zone_origin); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } packet_writer_add_fqdn(&pw, o); packet_writer_add_bytes(&pw, &o[olen], remaining); SET_U16_AT(pw.packet[rdata_offset - 2], htons(pw.packet_offset - rdata_offset)); // set RDATA size continue; } } // switch } // if // not a case handled with compression : raw copy while(rdata_len > 0) { if((n = input_stream_read(&fis, (u8*)buffer, MIN(rdata_len, sizeof(buffer)))) <= 0) { if(n == 0) { break; } log_err("zone write axfr: %{dnsname}: error reading %{dnstype} rdata: %r", data_zone_origin, &tctrl.qtype, n); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } #if DEBUG if(packet_writer_get_remaining_capacity(&pw) < n) { log_err("zone write axfr: %{dnsname}: would store %i bytes when %i were expected and %i remaining, from %i", data_zone_origin, n, rdata_len, packet_writer_get_remaining_capacity(&pw), remaining_capacity ); /* * GOTO !!! (thread carefully) */ goto scheduler_queue_zone_write_axfr_thread_exit; } #endif packet_writer_add_bytes(&pw, (const u8*)buffer, n); rdata_len -= n; } } // for /** * GOTO !!! */ scheduler_queue_zone_write_axfr_thread_exit: #if DNSCORE_HAS_TCP_MANAGER if(sctx != NULL) { tcp_manager_context_release(sctx); } #endif log_info("zone write axfr: %{dnsname}: closing file, %llu bytes sent to %{sockaddr}", data_zone_origin, total_bytes_sent, message_get_sender_sa(mesg)); #if DNSCORE_HAS_TCP_MANAGER #if DEBUG log_debug("zone write axfr: %{dnsname}: closing socket %i", data_zone_origin, tcp_manager_socket(sctx)); #endif #else #if DEBUG log_debug("zone write axfr: %{dnsname}: closing socket %i", data_zone_origin, tcpfd); #endif #if USE_TCPOS output_stream_close(&tcpos); #else close_ex(tcpfd); #endif #endif if(input_stream_valid(&fis)) { input_stream_close(&fis); } message_free(mesg); return NULL; } #if DNSCORE_HAS_TCP_MANAGER void zdb_zone_answer_axfr(zdb_zone *zone, message_data *mesg, tcp_manager_socket_context_t *sctx, struct thread_pool_s *network_tp, struct thread_pool_s *disk_tp, u16 max_packet_size, u16 max_record_by_packet, bool compress_packets) #else void zdb_zone_answer_axfr(zdb_zone *zone, message_data *mesg, int sockfd, struct thread_pool_s *network_tp, struct thread_pool_s *disk_tp, u16 max_packet_size, u16 max_record_by_packet, bool compress_packets) #endif { zdb_zone_answer_axfr_thread_args* args; log_info("zone write axfr: %{dnsname}: queueing", zone->origin); if(message_get_size(mesg) >= max_packet_size) { log_err("zone write axfr: %{dnsname}: received message is already bigger than maximum message size in answer: cancelled", zone->origin); return; } message_data *clone = message_dup(mesg); if(clone == NULL) { log_err("zone write axfr: %{dnsname}: received message : cancelled", zone->origin); return; // BUFFER_WOULD_OVERFLOW; } MALLOC_OBJECT_OR_DIE(args, zdb_zone_answer_axfr_thread_args, SHDQZWAA_TAG); ya_result ret; if(FAIL(ret = zdb_zone_journal_get_serial_range(zone, &args->journal_from, &args->journal_to))) { log_debug("zone write axfr: %{dnsname}: could not get the serial range of the journal: %r", zone->origin, ret); // ZDB_ERROR_ICMTL_NOTFOUND args->journal_from = 0; args->journal_to = 0; } zdb_zone_acquire(zone); args->zone = zone; args->disk_tp = disk_tp; #if DNSCORE_HAS_TCP_MANAGER args->sctx = sctx; #else args->sockfd = sockfd; #endif args->mesg = clone; args->packet_size_limit = max_packet_size; args->packet_records_limit = max_record_by_packet; args->compress_dname_rdata = compress_packets; if(network_tp != NULL) { thread_pool_enqueue_call(network_tp, zdb_zone_answer_axfr_thread, args, NULL, "zone-answer-axfr"); } else { zdb_zone_answer_axfr_thread(args); } } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-answer-ixfr.c0000644000000000000000000000013214505005531023123 xustar000000000000000030 mtime=1695812441.761972435 30 atime=1695812445.803030311 30 ctime=1695812495.084736124 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-answer-ixfr.c0000664000374500037450000007556014505005531023102 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbixfr IXFR answers * @ingroup dnsdb * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include "dnsdb/zdb-config-features.h" #include #include #include #include #include #include #include #include #include #include #include #if DNSCORE_HAS_TCP_MANAGER #include #endif #if DEBUG #include #endif #include "dnsdb/zdb-zone-journal.h" #include "dnsdb/zdb_icmtl.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_types.h" #include "dnsdb/zdb-zone-answer-axfr.h" #define TCP_BUFFER_SIZE 4096 #define FILE_BUFFER_SIZE 4096 #define RECORD_MODE_DELETE 0 #define RECORD_MODE_ADD 1 #define ZAIXFRRB_TAG 0x425252465849415a /* * Typically it goes 4 3 [2,1]+ 0 */ #define MODULE_MSG_HANDLE g_database_logger extern logger_handle* g_database_logger; #define TCP_BUFFER_SIZE 4096 #define FILE_BUFFER_SIZE 4096 #define IXFR_RECORD_SENDING_DEBUG 0 #define RECORD_MODE_DELETE 0 #define RECORD_MODE_ADD 1 /* * Typically it goes 4 3 [2,1]+ 0 */ extern logger_handle* g_database_logger; #ifndef PATH_MAX #error "PATH_MAX not defined" #endif typedef struct zdb_zone_answer_ixfr_args zdb_zone_answer_ixfr_args; #define ZAIXFRA_TAG 0x4152465849415a struct zdb_zone_answer_ixfr_args { zdb_zone *zone; message_data *mesg; struct thread_pool_s *disk_tp; #if DNSCORE_HAS_TCP_MANAGER tcp_manager_socket_context_t *sctx; #else int sockfd; #endif ya_result return_code; u32 packet_size_limit; u32 packet_records_limit; u32 from_serial; bool compress_dname_rdata; }; static void zdb_zone_answer_ixfr_thread_finalize(zdb_zone_answer_ixfr_args* data) { log_debug("zone write ixfr: ended with: %r", data->return_code); zdb_zone_release(data->zone); #if DNSCORE_HAS_TCP_MANAGER if(data->sctx != NULL) { tcp_manager_context_release(data->sctx); data->sctx = NULL; } #endif if(data->mesg != NULL) { message_free(data->mesg); } //free(data->directory); free(data); } static ya_result zdb_zone_answer_ixfr_read_record(input_stream *is, u8 *qname, u32 *qname_sizep, struct type_class_ttl_rdlen *tctrlp, u8 *rdata_buffer, u32 *rdata_sizep) { ya_result return_code; /* Read the next DNAME from the stored INCREMENTAL */ if((return_code = input_stream_read_dnsname(is, qname)) <= 0) { if(return_code < 0) { log_err("zone write ixfr: error reading IXFR qname: %r", return_code); } else { log_debug("zone write ixfr: eof reading IXFR qname: %r", return_code); } return return_code; } *qname_sizep = return_code; if(return_code > 0) { /* read the next type+class+ttl+rdatalen from the stored IXFR */ tctrlp->qtype = 0; tctrlp->rdlen = 0; if(FAIL(return_code = input_stream_read_fully(is, tctrlp, 10))) { log_err("zone write ixfr: error reading IXFR record: %r", return_code); return return_code; } if(FAIL(return_code = input_stream_read_fully(is, rdata_buffer, ntohs(tctrlp->rdlen)))) { log_err("zone write ixfr: error reading IXFR record rdata: %r", return_code); return return_code; } *rdata_sizep = return_code; return_code = *qname_sizep + 10 + *rdata_sizep; } else { *rdata_sizep = 0; } return return_code; } /* * mesg is needed for TSIG */ extern u16 edns0_maxsize; #if ZDB_HAS_TSIG_SUPPORT static ya_result zdb_zone_answer_ixfr_send_message(output_stream *tcpos, packet_writer *pw, message_data *mesg, tsig_tcp_message_position pos) #else static ya_result zdb_zone_answer_ixfr_send_message(output_stream *tcpos, packet_writer *pw, message_data *mesg) #endif { ya_result return_code; /* * Flush and stop */ #if DEBUG log_debug("zone write ixfr: %{dnsname}: sending message for %{dnsname} to %{sockaddr}", message_get_canonised_fqdn(mesg), message_get_canonised_fqdn(mesg), message_get_sender(mesg)); #endif if(message_is_edns0(mesg)) // Dig does a TCP query with EDNS0 { /* 00 00 29 SS SS rr vv 80 00 00 00 */ memset(packet_writer_get_next_u8_ptr(pw), 0, EDNS0_RECORD_SIZE); packet_writer_forward(pw, 2); packet_writer_add_u8(pw, 0x29); packet_writer_add_u16(pw, htons(edns0_maxsize)); packet_writer_add_u32(pw, message_get_rcode_ext(mesg)); packet_writer_forward(pw, 2); message_set_additional_count_ne(mesg, NETWORK_ONE_16); } else { message_set_additional_count_ne(mesg, 0); } message_set_size(mesg, packet_writer_get_offset(pw)); #if ZDB_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) { message_set_additional_section_ptr(mesg, packet_writer_get_next_u8_ptr(pw)); if(FAIL(return_code = tsig_sign_tcp_message(mesg, pos))) { log_err("zone write ixfr: failed to sign the answer: %r", return_code); return return_code; } } #endif packet_writer_set_offset(pw, message_get_size(mesg)); if(FAIL(return_code = write_tcp_packet(pw, tcpos))) { if(return_code == MAKE_ERRNO_ERROR(EPIPE)) { log_notice("zone write ixfr: %{dnsname}: %{sockaddr}: error sending IXFR message: client closed connection", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); } else { log_notice("zone write ixfr: %{dnsname}: %{sockaddr}: error sending IXFR message: %r", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg), return_code); } } return return_code; } static void zdb_zone_answer_ixfr_thread_close_finalize(zdb_zone_answer_ixfr_args* data, ya_result ret) { #if DNSCORE_HAS_TCP_MANAGER tcp_manager_close(data->sctx); #else shutdown(data->sockfd, SHUT_RDWR); close_ex(data->sockfd); data->sockfd = -1; #endif data->return_code = ret; zdb_zone_answer_ixfr_thread_finalize(data); } static ya_result zdb_zone_answer_ixfr_thread_read_SOA_serial(zdb_zone_answer_ixfr_args* data, packet_unpack_reader_data *purd, u32 *serialp) { struct type_class_ttl_rdlen tctr; u8 fqdn[MAX_DOMAIN_LENGTH]; if((data == NULL) || (purd == NULL) || (serialp == NULL)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } if(FAIL(packet_reader_read_fqdn(purd, fqdn, sizeof(fqdn)))) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(!dnsname_equals_ignorecase(fqdn, data->zone->origin)) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(FAIL(packet_reader_read(purd, &tctr, 10))) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(tctr.qtype != TYPE_SOA) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(FAIL(packet_reader_skip_fqdn(purd))) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(FAIL(packet_reader_skip_fqdn(purd))) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(packet_reader_available(purd) != 20) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(FAIL(packet_reader_read(purd, (u8*)serialp, 4))) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } return SUCCESS; } /* * writes the filtered stream to a file, then adds it to the journal * the journal needs to give fast access to the last SOA in it ... * */ static void* zdb_zone_answer_ixfr_thread(void* data_) { zdb_zone_answer_ixfr_args* data = (zdb_zone_answer_ixfr_args*)data_; message_data *mesg = data->mesg; /* The TCP output stream */ output_stream tcpos; /* The incremental file input stream */ input_stream fis; /* The packet writer */ /* Current SOA */ u32 current_soa_rdata_size; //u16 target_soa_rdata_size = MAX_SOA_RDATA_LENGTH; struct type_class_ttl_rdlen current_soa_tctrl; /* */ u8 *rdata_buffer = NULL; struct type_class_ttl_rdlen tctrl; u32 qname_size; u32 rdata_size = 0; packet_writer pw; u8 current_soa_rdata_buffer[MAX_SOA_RDATA_LENGTH]; u8 target_soa_rdata_buffer[MAX_SOA_RDATA_LENGTH]; u8 fqdn[MAX_DOMAIN_LENGTH]; /* */ ya_result return_value; u32 serial = 0; u16 an_count = 0; s32 pages_sent = 0; u32 current_to_serial = 0; u32 stream_serial = 0; u32 packet_size_limit; u32 packet_size_trigger; s32 packet_records_limit; s32 packet_records_countdown; #if ZDB_HAS_TSIG_SUPPORT tsig_tcp_message_position pos = TSIG_START; #endif /* * relevant data for when data is not usable anymore */ u8 origin[MAX_DOMAIN_LENGTH]; /* */ log_info("zone write ixfr: %{dnsname}: sending journal file", data->zone->origin); /***********************************************************************/ #if DNSCORE_HAS_TCP_MANAGER if(!tcp_manager_is_valid(data->sctx)) { log_err("zone write ixfr: %{dnsname}: no connection", data->zone->origin); data->return_code = MAKE_ERRNO_ERROR(ENOTSOCK); zdb_zone_answer_ixfr_thread_exit(data); return NULL; } #else if(data->sockfd < 0) { log_err("zone write ixfr: %{dnsname}: no TCP socket set for operation", data->zone->origin); data->return_code = MAKE_ERRNO_ERROR(ENOTSOCK); zdb_zone_answer_ixfr_thread_finalize(data); return NULL; } #endif /***********************************************************************/ zdb_zone_lock(data->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); /* Keep a snapshot of the current SOA */ zdb_packed_ttlrdata* soa = zdb_record_find(&data->zone->apex->resource_record_set, TYPE_SOA); // zone is locked if(soa == NULL) { zdb_zone_unlock(data->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); #if DNSCORE_HAS_TCP_MANAGER if(ISOK(message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, tcp_manager_socket(data->sctx)))) { tcp_manager_write_update(data->sctx, message_get_size(mesg)); } #else message_make_error_and_reply_tcp(mesg, RCODE_SERVFAIL, data->sockfd); #endif /** * @note This does an exit with error. */ #if DNSCORE_HAS_TCP_MANAGER tcp_manager_close(data->sctx); #else shutdown(data->sockfd, SHUT_RDWR); close_ex(data->sockfd); data->sockfd = -1; #endif data->return_code = ZDB_ERROR_NOSOAATAPEX; log_crit("zone write ixfr: %{dnsname}: no SOA in zone", data->zone->origin); /* will ultimately lead to the end of the program */ zdb_zone_answer_ixfr_thread_finalize(data); return NULL; } current_soa_rdata_size = soa->rdata_size; memcpy(current_soa_rdata_buffer, ZDB_PACKEDRECORD_PTR_RDATAPTR(soa), current_soa_rdata_size); current_soa_tctrl.qtype = TYPE_SOA; current_soa_tctrl.qclass = CLASS_IN; current_soa_tctrl.ttl = htonl(soa->ttl); current_soa_tctrl.rdlen = htons(soa->rdata_size); zdb_zone_unlock(data->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); /***********************************************************************/ /* * Adjust the message received size * get the queried serial number * Set the answer bit and clean the NS count */ packet_unpack_reader_data purd; packet_reader_init_from_message(&purd, mesg); /* Keep only the query */ if(FAIL( packet_reader_skip_fqdn(&purd))) { log_crit("zone write ixfr: %{dnsname}: format error", data->zone->origin); /* will ultimately lead to the end of the program */ zdb_zone_answer_ixfr_thread_close_finalize(data, MAKE_DNSMSG_ERROR(RCODE_FORMERR)); return NULL; } if(packet_reader_available(&purd) < 4 + 10) { log_crit("zone write ixfr: %{dnsname}: format error", data->zone->origin); /* will ultimately lead to the end of the program */ zdb_zone_answer_ixfr_thread_close_finalize(data, MAKE_DNSMSG_ERROR(RCODE_FORMERR)); return NULL; } purd.offset += 4; // type & class message_set_size(mesg, purd.offset); // the part after this will be overwritten later /* Get the queried serial from the expected SOA record */ if(FAIL(zdb_zone_answer_ixfr_thread_read_SOA_serial(data, &purd, &serial))) { log_crit("zone write ixfr: %{dnsname}: format error", data->zone->origin); /* will ultimately lead to the end of the program */ zdb_zone_answer_ixfr_thread_close_finalize(data, MAKE_DNSMSG_ERROR(RCODE_FORMERR)); return NULL; } serial = ntohl(serial); log_debug("zone write ixfr: %{dnsname}: %{sockaddr}: client requested changes from serial %08x (%d)", data->zone->origin, message_get_sender_sa(mesg), serial, serial); message_set_authoritative_answer(mesg); message_set_authority_count(mesg, 0); u32 journal_serial_from, journal_serial_to; return_value = zdb_zone_journal_get_serial_range(data->zone, &journal_serial_from, &journal_serial_to); dns_resource_record rr; dns_resource_record_init(&rr); if(ISOK(return_value)) { if(serial_ge(serial, journal_serial_from) && serial_le(serial, journal_serial_to)) { // good log_info("zone write ixfr: %{dnsname}: %{sockaddr}: host asked for serial %d which is in [%d; %d]", data->zone->origin, message_get_sender_sa(mesg), serial, journal_serial_from, journal_serial_to); return_value = zdb_zone_journal_get_ixfr_stream_at_serial(data->zone, serial, &fis, &rr); } else { log_notice("zone write ixfr: %{dnsname}: %{sockaddr}: host asked for serial %d which is out of [%d; %d]", data->zone->origin, message_get_sender_sa(mesg), serial, journal_serial_from, journal_serial_to); return_value = ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE; } } else { if(return_value == ZDB_ERROR_ICMTL_NOTFOUND) { log_notice("zone write ixfr: %{dnsname}: %{sockaddr}: host asked for serial %d but there is no journal to be found", data->zone->origin, message_get_sender_sa(mesg), serial); } else { if(return_value == ERROR) { return_value = ZDB_JOURNAL_IS_BUSY; } if(return_value == ZDB_JOURNAL_IS_BUSY) { log_notice("zone write ixfr: %{dnsname}: %{sockaddr}: host asked for serial %d but the journal is being maintained", data->zone->origin, message_get_sender_sa(mesg), serial); } } } if(FAIL(return_value)) { dns_resource_record_clear(&rr); if(return_value != ZDB_JOURNAL_IS_BUSY) { #if DNSCORE_HAS_TCP_MANAGER zdb_zone_answer_axfr(data->zone, mesg, data->sctx, NULL, data->disk_tp, data->packet_size_limit, data->packet_records_limit, data->compress_dname_rdata); #else zdb_zone_answer_axfr(data->zone, mesg, data->sockfd, NULL, data->disk_tp, data->packet_size_limit, data->packet_records_limit, data->compress_dname_rdata); data->sockfd = -1; #endif } else { #if DNSCORE_HAS_TCP_MANAGER output_stream_flush(&tcpos); output_stream *tcpos_filtered = buffer_output_stream_get_filtered(&tcpos); fd_output_stream_detach(tcpos_filtered); #endif message_set_status(mesg, RCODE_SERVFAIL); message_transform_to_signed_error(mesg); #if DNSCORE_HAS_TCP_MANAGER ya_result ret = message_send_tcp(mesg, tcp_manager_socket(data->sctx)); if(ISOK(ret)) { tcp_manager_write_update(data->sctx, ret); } #else message_send_tcp(mesg, data->sockfd); #endif } data->return_code = return_value; zdb_zone_answer_ixfr_thread_finalize(data); return NULL; } yassert(ISOK(return_value)); if(sizeof(target_soa_rdata_buffer) < rr.rdata_size) // scan-build (7) incoherence { u32 from, to; ya_result range_ret = zdb_zone_journal_get_serial_range(data->zone, &from, &to); if(ISOK(range_ret)) { log_warn("zone write ixfr: %{dnsname}: %{sockaddr}: unable to read journal from serial %d [%d; %d]", data->zone->origin, message_get_sender_sa(mesg), serial, from, to); } else { log_err("zone write ixfr: %{dnsname}: %{sockaddr}: unable to read journal from serial %d, cannot get its range: %r", data->zone->origin, message_get_sender_sa(mesg), serial, range_ret); } dns_resource_record_clear(&rr); #if DNSCORE_HAS_TCP_MANAGER zdb_zone_answer_axfr(data->zone, mesg, data->sctx, NULL, data->disk_tp, data->packet_size_limit, data->packet_records_limit, data->compress_dname_rdata); #else zdb_zone_answer_axfr(data->zone, mesg, data->sockfd, NULL, data->disk_tp, data->packet_size_limit, data->packet_records_limit, data->compress_dname_rdata); data->sockfd = -1; #endif data->return_code = BUFFER_WOULD_OVERFLOW; zdb_zone_answer_ixfr_thread_finalize(data); return NULL; } MEMCOPY(target_soa_rdata_buffer, rr.rdata, rr.rdata_size); // note: target_soa_rdata_size = rr.rdata_size; dns_resource_record_clear(&rr); /* fis points to the IX stream */ MALLOC_OR_DIE(u8*, rdata_buffer, RDATA_MAX_LENGTH, ZAIXFRRB_TAG); /* rdata max size */ /***********************************************************************/ /* * We will need to output the current SOA * But first, we have some setup to do. */ /* It's TCP, my limit is 16 bits */ // except if the buffer we are using is too small ... packet_size_limit = message_get_buffer_size_max(mesg); packet_size_trigger = packet_size_limit / 2; // so, ~32KB, also : guarantees that there will be room for SOA & TSIG packet_records_limit = data->packet_records_limit; if(packet_records_limit <= 0) { packet_records_limit = MAX_S32; } packet_records_countdown = packet_records_limit; message_reset_buffer_size(mesg); #if DNSCORE_HAS_TCP_MANAGER tcp_manager_socket_context_t *sctx = tcp_manager_context_acquire(data->sctx); #else int tcpfd = data->sockfd; data->sockfd = -1; #endif dnsname_copy(origin, data->zone->origin); /* Sends the "Write unlocked" notification */ log_info("zone write ixfr: %{dnsname}: %{sockaddr}: releasing implicit write lock", origin, message_get_sender(mesg)); data->mesg = NULL; // still need the message. do not destroy it data->return_code = SUCCESS; zdb_zone_answer_ixfr_thread_finalize(data); /* WARNING: From this point forward, 'data' cannot be used anymore */ data = NULL; /* WITH THIS I ENSURE A CRASH IF THE ABOVE COMMENT IS NOT FOLLOWED */ /***********************************************************************/ log_info("zone write ixfr: %{dnsname}: %{sockaddr}: sending journal from serial %d", origin, message_get_sender_sa(mesg), serial); /* attach the tcp descriptor and put a buffer filter in front of the input and the output*/ #if DNSCORE_HAS_TCP_MANAGER fd_output_stream_attach(&tcpos, tcp_manager_socket(sctx)); #else fd_output_stream_attach(&tcpos, tcpfd); #endif buffer_input_stream_init(&fis, &fis, FILE_BUFFER_SIZE); buffer_output_stream_init(&tcpos, &tcpos, TCP_BUFFER_SIZE); size_t query_size = message_get_size(mesg); packet_writer_init(&pw, message_get_buffer(mesg), query_size, packet_size_limit - 780); /* * Init * * Write the final SOA (start of the IXFR stream) */ packet_writer_add_fqdn(&pw, (const u8*)origin); packet_writer_add_bytes(&pw, (const u8*)¤t_soa_tctrl, 8); /* not 10 ? */ packet_writer_add_rdata(&pw, TYPE_SOA, current_soa_rdata_buffer, current_soa_rdata_size); u32 last_serial; rr_soa_get_serial(current_soa_rdata_buffer, current_soa_rdata_size, &last_serial); an_count = 1 /*2*/; bool end_of_stream = FALSE; int soa_count = 0; for(;;) { if(FAIL(return_value = zdb_zone_answer_ixfr_read_record(&fis, fqdn, &qname_size, &tctrl, rdata_buffer, &rdata_size))) { // critical error. log_err("zone write ixfr: %{dnsname}: %{sockaddr}: read record #%d failed: %r", origin, message_get_sender_sa(mesg), an_count, return_value); break; } #if DNSCORE_HAS_TCP_MANAGER tcp_manager_read_update(sctx, return_value); #endif // at this point, record_length >= 0 // if record_length > 0 then tctrl has been set u32 record_length = return_value; if(record_length > 0) { if(tctrl.qtype == TYPE_SOA) // scan-build (7) false positive: the path allegedly leading here lies on an incoherence (assuming record_length < 0 followed by assuming record_length <= 0) { ++soa_count; // ensure we didn't go too far u32 soa_serial; rr_soa_get_serial(rdata_buffer, rdata_size, &soa_serial); if(serial_gt(soa_serial, last_serial)) { log_info("zone write ixfr: %{dnsname}: %{sockaddr}: cutting at serial %u", origin, message_get_sender_sa(mesg), soa_serial); record_length = 0; // will be seen as an EOF } if((soa_count & 1) != 0) // do not cut mid-page { current_to_serial = soa_serial; if(dnscore_shuttingdown()) { log_info("zone write ixfr: %{dnsname}: %{sockaddr}: shutting down: cutting at serial %u", origin, message_get_sender_sa(mesg), soa_serial); record_length = 0; // will be seen as an EOF } } } } if(record_length == 0) { #if DEBUG log_debug("zone write ixfr: %{dnsname}: %{sockaddr}: end of stream", origin, message_get_sender(mesg)); #endif #if ZDB_HAS_TSIG_SUPPORT if(pos != TSIG_START) { pos = TSIG_END; } else { pos = TSIG_WHOLE; } #endif // Last SOA // There is no need to check for remaining space as packet_size_trigger guarantees there is still room #if DEBUG { rdata_desc rr_desc = {TYPE_SOA, current_soa_rdata_size, current_soa_rdata_buffer}; log_debug("zone write ixfr: %{dnsname}: closing: %{dnsname} %{typerdatadesc}", origin, origin, &rr_desc); } #endif packet_writer_add_fqdn(&pw, (const u8*)origin); packet_writer_add_bytes(&pw, (const u8*)¤t_soa_tctrl, 8); /* not 10 ? */ packet_writer_add_rdata(&pw, TYPE_SOA, current_soa_rdata_buffer, current_soa_rdata_size); ++an_count; end_of_stream = TRUE; } else if(record_length > MAX_U16) // technically possible: a record too big to fit in an update (not likely) { // this is technically possible with an RDATA of 64K log_err("zone write ixfr: %{dnsname}: %{sockaddr}: ignoring record of size %u", origin, message_get_sender_sa(mesg), record_length); rdata_desc rr_desc = {tctrl.qtype, rdata_size, rdata_buffer}; log_err("zone write ixfr: %{dnsname}: %{sockaddr}: record is: %{dnsname} %{typerdatadesc}", origin, message_get_sender_sa(mesg), fqdn, &rr_desc); continue; } // if the record puts us above the trigger, or if there is no more record to read, send the message if(pw.packet_offset + record_length >= packet_size_trigger || (packet_records_countdown-- <= 0) || end_of_stream) { // flush message_set_answer_count(mesg, an_count); //message_set_size(mesg, packet_writer_get_offset(&pw)); #if ZDB_HAS_TSIG_SUPPORT if(ISOK(return_value = zdb_zone_answer_ixfr_send_message(&tcpos, &pw, mesg, pos))) #else if(ISOK(return_value = zdb_zone_answer_ixfr_send_message(&tcpos, &pw, mesg))) #endif { #if DNSCORE_HAS_TCP_MANAGER tcp_manager_write_update(sctx, return_value); #endif ++pages_sent; stream_serial = current_to_serial; } else { if(return_value == MAKE_ERRNO_ERROR(EPIPE)) { log_notice("zone write ixfr: %{dnsname}: %{sockaddr}: send message failed: client closed connection", origin, message_get_sender_sa(mesg)); } else { log_notice("zone write ixfr: %{dnsname}: %{sockaddr}: send message failed: %r", origin, message_get_sender_sa(mesg), return_value); } break; } #if ZDB_HAS_TSIG_SUPPORT pos = TSIG_MIDDLE; #endif packet_writer_init(&pw, message_get_buffer(mesg), query_size, packet_size_limit - 780); an_count = 0; if(end_of_stream) { break; } packet_records_countdown = packet_records_limit; } #if IXFR_RECORD_SENDING_DEBUG { rdata_desc rr_desc = {tctrl.qtype, rdata_size, rdata_buffer}; log_debug("zone write ixfr: %{dnsname}: sending: %{dnsname} %{typerdatadesc}", origin, fqdn, &rr_desc); } #endif packet_writer_add_fqdn(&pw, (const u8*)fqdn); packet_writer_add_bytes(&pw, (const u8*)&tctrl, 8); packet_writer_add_rdata(&pw, tctrl.qtype, rdata_buffer, rdata_size); ++an_count; } if(ISOK(return_value)) { log_info("zone write ixfr: %{dnsname}: %{sockaddr}: incremental stream sent (serial %u)", origin, message_get_sender(mesg), stream_serial); } else { if(pages_sent == 0) { log_warn("zone write ixfr: %{dnsname}: %{sockaddr}: incremental stream not sent", origin, message_get_sender(mesg)); } else { log_notice("zone write ixfr: %{dnsname}: %{sockaddr}: incremental stream partially sent (serial %u instead of %u)", origin, message_get_sender(mesg), stream_serial, last_serial); } } #if DNSCORE_HAS_TCP_MANAGER output_stream_flush(&tcpos); output_stream *tcpos_filtered = buffer_output_stream_get_filtered(&tcpos); fd_output_stream_detach(tcpos_filtered); #endif output_stream_close(&tcpos); if(input_stream_valid(&fis)) { input_stream_close(&fis); } free(rdata_buffer); message_free(mesg); return NULL; } /** * * Replies an (I)XFR stream to a slave. * * @param zone The zone * @param mesg The original query * @param network_tp The network thread pool to use * @param disk_tp The disk thread pool to use * @param packet_size_limit the maximum size of a packet/message in the stream * @param packet_records_limit The maximum number of records in a single message (1 for very old servers) * @param compress_dname_rdata Allow fqdn compression * */ //zdb_zone_answer_ixfr_parm void zdb_zone_answer_ixfr( zdb_zone* zone, message_data *mesg, #if DNSCORE_HAS_TCP_MANAGER tcp_manager_socket_context_t *sctx, #else int sockfd, #endif struct thread_pool_s *network_tp, struct thread_pool_s *disk_tp, u32 packet_size_limit, u32 packet_records_limit, bool compress_dname_rdata) { zdb_zone_answer_ixfr_args* args; message_data *clone = message_dup(mesg); if(clone == NULL) { log_warn("zone write axfr: %{dnsname}: %{sockaddr}: cannot answer, message cannot be processed", zone->origin, message_get_sender_sa(mesg)); #if !DNSCORE_HAS_TCP_MANAGER close_ex(sockfd); #endif return; // BUFFER_WOULD_OVERFLOW; } log_info("zone write ixfr: %{dnsname}: %{sockaddr}: queueing answer", zone->origin, message_get_sender_sa(mesg)); MALLOC_OBJECT_OR_DIE(args, zdb_zone_answer_ixfr_args, ZAIXFRA_TAG); zdb_zone_acquire(zone); args->zone = zone; args->mesg = clone; args->disk_tp = disk_tp; #if DNSCORE_HAS_TCP_MANAGER args->sctx = sctx; #else args->sockfd = sockfd; #endif args->packet_size_limit = packet_size_limit; args->packet_records_limit = packet_records_limit; args->compress_dname_rdata = compress_dname_rdata; if(network_tp != NULL) { thread_pool_enqueue_call(network_tp, zdb_zone_answer_ixfr_thread, args, NULL, "zone-answer-ixfr"); } else { zdb_zone_answer_ixfr_thread(args); } } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-arc.c0000644000000000000000000000013114505005531021422 xustar000000000000000029 mtime=1695812441.76097242 30 atime=1695812445.803030311 30 ctime=1695812495.086736153 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-arc.c0000664000374500037450000005044414505005531021374 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #include "dnsdb/dnsdb-config.h" #include "dnsdb/zdb-config-features.h" #include #include #if DEBUG #include #endif #include #include #include #include "dnsdb/zdb.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb-zone-garbage.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_error.h" #include "dnsdb/dnsrdata.h" #if ZDB_HAS_NSEC_SUPPORT #include "dnsdb/nsec.h" #endif #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif #if ZDB_HAS_LOCK_DEBUG_SUPPORT #include "dnsdb/zdb-zone-lock-monitor.h" #endif #if DEBUG #define ZONE_MUTEX_LOG 0 // set this to 0 to disable in DEBUG #define DEBUG_ARC 0 // set this to 0 do disable in DEBUG #else #define ZONE_MUTEX_LOG 0 // never enable if not in DEBUG #define DEBUG_ARC 0 // never enable if not in DEBUG #endif extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #if DEBUG_ARC static inline bool zdb_zone_change_rc(zdb_zone *zone, s32 n, const char * txt) { char prefix[64]; int old_rc = zone->rc; int new_rc = old_rc + n; log_debug7("%s: %p going from %i to %i", txt, zone, old_rc, new_rc); snformat(prefix, sizeof(prefix), "%s: %p", txt, zone); debug_log_stacktrace(g_database_logger, MSG_DEBUG7, prefix); if(new_rc < 0) { abort(); } zone->rc = new_rc; if(new_rc == 0) { log_debug7("%s: good for the garbage", txt); } return new_rc == 0; } #define ZONE_RC_INC(zone_) zdb_zone_change_rc(zone_, 1, "rc++") #define ZONE_RC_DEC(zone_) zdb_zone_change_rc(zone_, -1, "rc--") #else #define ZONE_RC_INC(zone_) (++(zone_)->rc) #define ZONE_RC_DEC(zone_) ((--(zone_)->rc) == 0) #endif /** * * Locks the database * Gets the zone * Starts locking the zone for the owner * Increment the zone RC * Unlocks the database * Resume locking the zone for the owner * returns the locked zone * * @param db * @param exact_match_origin * @param owner * @return */ static inline zdb_zone * zdb_acquire_zone_resume_lock_from_label(zdb *db, const zdb_zone_label *label, u8 owner, u8 db_locktype) { yassert(zdb_islocked(db)); if(label != NULL && label->zone != NULL) { zdb_zone *zone = label->zone; mutex_t *mutex = &zone->lock_mutex; mutex_lock(mutex); zdb_unlock(db, db_locktype); ZONE_RC_INC(zone); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_new(zone, owner, 0); #endif for(;;) { /* A simple way to ensure that a lock can be shared by similar entities or not. Sharable entities have their msb off. */ u8 co = zone->lock_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(co == GROUP_MUTEX_NOBODY || co == owner) { yassert(!SIGNED_VAR_VALUE_IS_MAX(zone->lock_count)); zone->lock_owner = owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; zone->lock_count++; #if ZDB_ZONE_LOCK_HAS_OWNER_ID // if the owner changes, update the owning thread if(zone->lock_last_owner_id == 0) { zone->lock_last_owner_id = thread_self(); } #endif break; } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_waits(holder); #endif cond_wait(&zone->lock_cond, mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_resumes(holder); #endif } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_locks(holder); #endif mutex_unlock(mutex); return zone; } else { zdb_unlock(db, db_locktype); return NULL; } } static inline zdb_zone * zdb_acquire_zone_resume_trylock_from_label(zdb *db, const zdb_zone_label *label, u8 owner, u8 db_locktype) { yassert(zdb_islocked(db)); if(label != NULL && label->zone != NULL) { zdb_zone *zone = label->zone; mutex_t *mutex = &zone->lock_mutex; mutex_lock(mutex); zdb_unlock(db, db_locktype); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_new(zone, owner, 0); #endif /* A simple way to ensure that a lock can be shared by similar entities or not. Sharable entities have their msb off. */ u8 co = zone->lock_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(co == GROUP_MUTEX_NOBODY || co == owner) { yassert(!SIGNED_VAR_VALUE_IS_MAX(zone->lock_count)); zone->lock_owner = owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; zone->lock_count++; #if ZDB_ZONE_LOCK_HAS_OWNER_ID // if the owner changes, update the owning thread if(zone->lock_last_owner_id == 0) { zone->lock_last_owner_id = thread_self(); } #endif ZONE_RC_INC(zone); #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_locks(holder); #endif mutex_unlock(mutex); return zone; } else { #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_cancels(holder); #endif mutex_unlock(mutex); return NULL; } } else { zdb_unlock(db, db_locktype); return NULL; } } /** * Internal. * Second part of a double lock. * Works on a locked DB. * On success returns the double-locked zone. * On error, unlocks the DB and return NULL. * * @param db * @param label * @param owner * @param nextowner * @param db_locktype * @return */ static inline zdb_zone * zdb_acquire_zone_resume_double_lock_from_label(zdb *db, const zdb_zone_label *label, u8 owner, u8 nextowner, u8 db_locktype) { yassert((owner & 0x80) == 0); // the new standard use yassert(zdb_islocked(db)); if(label != NULL && label->zone != NULL) { zdb_zone *zone = label->zone; mutex_t *mutex = &zone->lock_mutex; mutex_lock(mutex); zdb_unlock(db, db_locktype); ZONE_RC_INC(zone); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_new(zone, owner, nextowner); #endif for(;;) { /* A simple way to ensure that a lock can be shared by similar entities or not. Sharable entities have their msb off. */ u8 so = zone->lock_reserved_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(so == ZDB_ZONE_MUTEX_NOBODY || so == nextowner) { u8 co = zone->lock_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(co == ZDB_ZONE_MUTEX_NOBODY || co == owner) { yassert(!SIGNED_VAR_VALUE_IS_MAX(zone->lock_count)); zone->lock_owner = owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; zone->lock_count++; zone->lock_reserved_owner = nextowner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; #if ZDB_ZONE_LOCK_HAS_OWNER_ID if(zone->lock_last_owner_id == 0) { zone->lock_last_owner_id = thread_self(); } #endif #if ZONE_MUTEX_LOG log_debug7("acquired lock for zone %{dnsname}@%p for %x (#%i)", zone->origin, zone, owner, zone->lock_count); #endif break; } } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_waits(holder); #endif cond_wait(&zone->lock_cond, mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_resumes(holder); #endif } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_locks(holder); #endif mutex_unlock(mutex); return zone; } else { zdb_unlock(db, db_locktype); return NULL; } } zdb_zone * zdb_acquire_zone_read(zdb *db, const dnsname_vector *exact_match_origin) { zdb_lock(db, ZDB_MUTEX_READER); const zdb_zone_label *label = zdb_zone_label_find(db, exact_match_origin); if(label != NULL && label->zone != NULL) { zdb_zone *zone = label->zone; mutex_t *mutex = &zone->lock_mutex; mutex_lock(mutex); zdb_unlock(db, ZDB_MUTEX_READER); ZONE_RC_INC(zone); mutex_unlock(mutex); return zone; } else { zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } } zdb_zone * zdb_acquire_zone_read_from_fqdn(zdb *db, const u8 *fqdn) { zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *label = zdb_zone_label_find_from_dnsname(db, fqdn); if(label != NULL && label->zone != NULL) { zdb_zone *zone = label->zone; mutex_t *mutex = &zone->lock_mutex; mutex_lock(mutex); zdb_unlock(db, ZDB_MUTEX_READER); ZONE_RC_INC(zone); mutex_unlock(mutex); return zone; } else { zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } } zdb_zone * zdb_acquire_zone_read_trylock(zdb *db, dnsname_vector *exact_match_origin, u8 owner) { zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *label = zdb_zone_label_find(db, exact_match_origin); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_trylock_from_label(db, label, owner, ZDB_MUTEX_READER); // this unlocks the DB return zone; } zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } zdb_zone * zdb_acquire_zone_read_trylock_from_name(zdb *db, const char *name, u8 owner) { zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *label = zdb_zone_label_find_from_name(db, name); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_trylock_from_label(db, label, owner, ZDB_MUTEX_READER); return zone; } zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } zdb_zone * zdb_acquire_zone_read_trylock_from_fqdn(zdb *db, const u8 *fqdn, u8 owner) { zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *label = zdb_zone_label_find_from_dnsname(db, fqdn); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_trylock_from_label(db, label, owner, ZDB_MUTEX_READER); return zone; } zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } zdb_zone * zdb_acquire_zone_read_lock(zdb *db, dnsname_vector *exact_match_origin, u8 owner) { zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *label = zdb_zone_label_find(db, exact_match_origin); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_lock_from_label(db, label, owner, ZDB_MUTEX_READER); return zone; } zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } zdb_zone * zdb_acquire_zone_read_lock_from_name(zdb *db, const char *name, u8 owner) { zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *label = zdb_zone_label_find_from_name(db, name); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_lock_from_label(db, label, owner, ZDB_MUTEX_READER); return zone; } zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } zdb_zone * zdb_acquire_zone_read_lock_from_fqdn(zdb *db, const u8 *fqdn, u8 owner) { zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *label = zdb_zone_label_find_from_dnsname(db, fqdn); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_lock_from_label(db, label, owner, ZDB_MUTEX_READER); return zone; } zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } zdb_zone * zdb_acquire_zone_write_lock(zdb *db, dnsname_vector *exact_match_origin, u8 owner) { zdb_lock(db, ZDB_MUTEX_WRITER); zdb_zone_label *label = zdb_zone_label_find(db, exact_match_origin); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_lock_from_label(db, label, owner, ZDB_MUTEX_WRITER); return zone; } zdb_unlock(db, ZDB_MUTEX_WRITER); return NULL; } zdb_zone * zdb_acquire_zone_write_lock_from_name(zdb *db, const char *name, u8 owner) { zdb_lock(db, ZDB_MUTEX_WRITER); zdb_zone_label *label = zdb_zone_label_find_from_name(db, name); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_lock_from_label(db, label, owner, ZDB_MUTEX_WRITER); return zone; } zdb_unlock(db, ZDB_MUTEX_WRITER); return NULL; } zdb_zone * zdb_acquire_zone_write_lock_from_fqdn(zdb *db, const u8 *fqdn, u8 owner) { zdb_lock(db, ZDB_MUTEX_WRITER); zdb_zone_label *label = zdb_zone_label_find_from_dnsname(db, fqdn); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_lock_from_label(db, label, owner, ZDB_MUTEX_WRITER); return zone; } zdb_unlock(db, ZDB_MUTEX_WRITER); return NULL; } zdb_zone * zdb_acquire_zone_read_double_lock(zdb *db, dnsname_vector *exact_match_origin, u8 owner, u8 nextowner) { zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *label = zdb_zone_label_find(db, exact_match_origin); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_double_lock_from_label(db, label, owner, nextowner, ZDB_MUTEX_READER); return zone; } zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } zdb_zone * zdb_acquire_zone_read_double_lock_from_name(zdb *db, const char *name, u8 owner, u8 nextowner) { zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *label = zdb_zone_label_find_from_name(db, name); if(label != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_double_lock_from_label(db, label, owner, nextowner, ZDB_MUTEX_READER); return zone; } zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } zdb_zone * zdb_acquire_zone_read_double_lock_from_fqdn(zdb *db, const u8 *fqdn, u8 owner, u8 nextowner) { zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *label = zdb_zone_label_find_from_dnsname(db, fqdn); if(fqdn != NULL) { zdb_zone *zone = zdb_acquire_zone_resume_double_lock_from_label(db, label, owner, nextowner, ZDB_MUTEX_READER); return zone; } zdb_unlock(db, ZDB_MUTEX_READER); return NULL; } void zdb_zone_acquire(zdb_zone *zone) { mutex_lock(&zone->lock_mutex); ZONE_RC_INC(zone); mutex_unlock(&zone->lock_mutex); } /** * * Dereference and unlocks the zone. * If the RC reached 0, enqueues it for destruction * * @param zone * @param owner */ void zdb_zone_release(zdb_zone *zone) { mutex_lock(&zone->lock_mutex); if(ZONE_RC_DEC(zone)) { if(!zdb_zone_garbage_collect(zone)) // zone mutex locked, as MUST be { // zone was not collected: it was destroyed return; } } mutex_unlock(&zone->lock_mutex); } void zdb_zone_release_unlock(zdb_zone *zone, u8 owner) { #if ZONE_MUTEX_LOG log_debug7("releasing lock for zone %{dnsname}@%p by %x (owned by %x)", zone->origin, zone, owner, zone->lock_owner); #else (void)owner; #endif mutex_lock(&zone->lock_mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_get(zone); #endif #if DEBUG if((zone->lock_owner != (owner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG)) || (zone->lock_count == 0)) { mutex_unlock(&zone->lock_mutex); yassert(zone->lock_owner == (owner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG)); yassert(zone->lock_count != 0); abort(); // unreachable } #endif zone->lock_count--; #if ZONE_MUTEX_LOG log_debug7("released lock for zone %{dnsname}@%p by %x (#%i)", zone->origin, zone, owner, zone->lock_count); #endif #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_unlocks(holder); #endif #if ZDB_ZONE_LOCK_HAS_OWNER_ID if(zone->lock_last_owner_id == thread_self()) { zone->lock_last_owner_id = 0; } #endif if(zone->lock_count == 0) { zone->lock_owner = ZDB_ZONE_MUTEX_NOBODY; cond_notify(&zone->lock_cond); } if(ZONE_RC_DEC(zone)) { if(!zdb_zone_garbage_collect(zone)) // zone mutex locked, as MUST be { // zone was not collected: it was destroyed return; } } cond_notify(&zone->lock_cond); mutex_unlock(&zone->lock_mutex); } void zdb_zone_release_double_unlock(zdb_zone *zone, u8 owner, u8 nextowner) { mutex_lock(&zone->lock_mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_get(zone); #else (void)owner; (void)nextowner; #endif #if DEBUG if((zone->lock_owner != (owner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG)) || (zone->lock_count == 0)) { yassert(zone->lock_owner == (owner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG)); yassert(zone->lock_count != 0); } if(zone->lock_reserved_owner != (nextowner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG)) { yassert(zone->lock_reserved_owner != (nextowner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG)); } #endif zone->lock_reserved_owner = ZDB_ZONE_MUTEX_NOBODY; --zone->lock_count; #if ZONE_MUTEX_LOG log_debug7("released lock for zone %{dnsname}@%p by %x (#%i)", zone->origin, zone, owner, zone->lock_count); #endif #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_unlocks(holder); #endif yassert((zone->lock_owner & 0xc0) == 0); // NO, because it does not always to a transfer lock yassert(zone->lock_count == 0); if(zone->lock_count == 0) { zone->lock_owner = ZDB_ZONE_MUTEX_NOBODY; } #if ZDB_ZONE_LOCK_HAS_OWNER_ID if(zone->lock_last_owner_id == thread_self()) { zone->lock_last_owner_id = 0; } #endif if(ZONE_RC_DEC(zone)) { #if !DEBUG_ARC #if DEBUG debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_DEBUG6, "GC: "); #endif #endif if(!zdb_zone_garbage_collect(zone)) // zone mutex locked, as MUST be { // zone was not collected: it was destroyed return; } } cond_notify(&zone->lock_cond); mutex_unlock(&zone->lock_mutex); } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-dnssec.c0000644000000000000000000000013214505005531022135 xustar000000000000000030 mtime=1695812441.691971432 30 atime=1695812445.799030253 30 ctime=1695812495.088736181 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-dnssec.c0000664000374500037450000001331014505005531022075 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbdnssec DNSSEC functions * @ingroup dnsdb * @brief * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include "dnsdb/zdb-zone-dnssec.h" #include "dnsdb/zdb-zone-path-provider.h" #include "dnsdb/zdb_types.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger static ya_result zdb_zone_dnssec_keys_getpath(zdb_zone *zone, char *buffer, u32 len) { ya_result ret; if(FAIL(ret = zdb_zone_path_get_provider()(zone->origin, buffer, len, ZDB_ZONE_PATH_PROVIDER_DNSKEY_PATH))) { log_err("unable to retrieve zone keys for %{dnsname}", zone->origin); } return ret; } struct zdb_zone_dnssec_callback_s { zdb_zone *zone; }; typedef struct zdb_zone_dnssec_callback_s zdb_zone_dnssec_callback_s; static ya_result zdb_zone_dnssec_readdir(const char *basedir, const char* file, u8 filetype, void *args_) { (void)basedir; (void)filetype; (void)args_; //zdb_zone_dnssec_callback_s *args = (zdb_zone_dnssec_callback_s*)args_; int alg; int tag; char name[256]; // Korigin.+alg+tag.private if(file[0] == 'K') { size_t len = strlen(file); if(len >= 9) { if(memcmp(&file[len - 8], ".private", 8) == 0) { if(sscanf(file, "K%255[^+]+%03d+%05d.private", name, &alg, &tag) == 3) { // this file contains a key for that zone // put the key in the keyring /* struct stat st; if(lstat(file, &st) >= 0) { st.st_mtim; } */ // open the file } } } } return 0; } void zdb_zone_dnssec_keys_path_init(string_set *set) { *set = STRING_SET_EMPTY; } void zdb_zone_dnssec_keys_path_add(string_set *set, const char *keys_path) { string_node *node = string_set_insert(set, keys_path); // assumes new value set to 0 if(node->value == 0) { node->key = strdup(keys_path); node->value = 1; } } void zdb_zone_dnssec_keys_path_update(string_set *set) { string_set_iterator iter; string_set_iterator_init(set, &iter); zdb_zone_dnssec_callback_s cb; while(string_set_iterator_hasnext(&iter)) { string_node* node = string_set_iterator_next_node(&iter); /*ya_result ret =*/ readdir_forall(node->key, zdb_zone_dnssec_readdir, &cb); } string_set_destroy(set); } void zdb_zone_dnssec_keys_path_finalize(string_set *set) { string_set_iterator iter; string_set_iterator_init(set, &iter); while(string_set_iterator_hasnext(&iter)) { string_node* node = string_set_iterator_next_node(&iter); free((void*)node->key); } string_set_destroy(set); } void zdb_zone_dnssec_keys_refresh() { } void zdb_zone_dnssec_keys_publish(zdb_zone *zone) { //time_t now = time(NULL); // dnskey_get_publish_epoch char keys_path[PATH_MAX]; if(FAIL(zdb_zone_dnssec_keys_getpath(zone, keys_path, sizeof(keys_path)))) { return; } } void zdb_zone_dnssec_keys_activate(zdb_zone *zone) { char keys_path[PATH_MAX]; if(FAIL(zdb_zone_dnssec_keys_getpath(zone, keys_path, sizeof(keys_path)))) { return; } } void zdb_zone_dnssec_keys_deactivate(zdb_zone *zone) { char keys_path[PATH_MAX]; if(FAIL(zdb_zone_dnssec_keys_getpath(zone, keys_path, sizeof(keys_path)))) { return; } } void zdb_zone_dnssec_keys_unpublish(zdb_zone *zone) { char keys_path[PATH_MAX]; if(FAIL(zdb_zone_dnssec_keys_getpath(zone, keys_path, sizeof(keys_path)))) { return; } } /** * @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-find.c0000644000000000000000000000013114505005531021575 xustar000000000000000030 mtime=1695812441.712971733 30 atime=1695812445.800030268 29 ctime=1695812495.09073621 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-find.c0000664000374500037450000001303414505005531021541 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include "dnsdb/zdb.h" #include "dnsdb/zdb-zone-find.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_error.h" #include "dnsdb/dnsrdata.h" #if ZDB_HAS_NSEC_SUPPORT #include "dnsdb/nsec.h" #endif #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif #if DEBUG #define ZONE_MUTEX_LOG 0 // set this to 0 to disable in DEBUG #else #define ZONE_MUTEX_LOG 0 #endif extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger /** * @brief Get the zone with the given name * * Get the zone with the given name * * No reference counting is done. This is ultimately used to find existence. * * @param[in] db a pointer to the database * @param[in] exact_match_origin the name of the zone * * @return a pointer to zone or NULL if the zone is not in the database * */ static inline zdb_zone* zdb_zone_find(zdb *db, dnsname_vector *exact_match_origin) // INTERNAL mutex checked { /* Find label */ yassert(zdb_ismutexlocked(db)); zdb_zone_label *zone_label = zdb_zone_label_find(db, exact_match_origin); // zdb_zone_find if(zone_label != NULL) { return zone_label->zone; } else { return NULL; } } bool zdb_zone_exists(zdb *db, dnsname_vector* exact_match_origin) { zdb_lock(db, ZDB_MUTEX_READER); bool does_exist = (zdb_zone_find(db, exact_match_origin) != NULL); // INTERNAL zdb_unlock(db, ZDB_MUTEX_READER); return does_exist; } /** * @brief Get the zone with the given name * * Get the zone with the given name * * No reference counting is done. This is ultimately used to find existence. * * @param[in] db a pointer to the database * @param[in] name the name of the zone (dotted c-string) * * @return a pointer to zone or NULL if the zone is not in the database * */ static inline zdb_zone * zdb_zone_find_from_name(zdb* db, const char* name) // INTERNAL mutex checked { dnsname_vector origin; u8 dns_name[MAX_DOMAIN_LENGTH]; if(ISOK(cstr_to_dnsname(dns_name, name))) { dnsname_to_dnsname_vector(dns_name, &origin); zdb_zone *zone = zdb_zone_find(db, &origin); // INTERNAL return zone; } return NULL; } bool zdb_zone_exists_from_name(zdb *db, const char* name) { zdb_lock(db, ZDB_MUTEX_READER); bool does_exist = (zdb_zone_find_from_name(db, name) != NULL); // INTERNAL zdb_unlock(db, ZDB_MUTEX_READER); return does_exist; } /** * @brief Get the zone with the given dns name * * Get the zone with the given dns name * * No reference counting is done. This is ultimately used to find existence. * * @param[in] db a pointer to the database * @param[in] name the name of the zone (dns name) * * @return a pointer to zone or NULL if the zone is not in the database * */ static inline zdb_zone * zdb_zone_find_from_dnsname(zdb* db, const u8 *dns_name) // INTERNAL mutex checked { dnsname_vector origin; yassert(zdb_ismutexlocked(db)); dnsname_to_dnsname_vector(dns_name, &origin); zdb_zone *zone = zdb_zone_find(db, &origin); // INTERNAL return zone; } bool zdb_zone_exists_from_dnsname(zdb *db, const u8* dns_name) { zdb_lock(db, ZDB_MUTEX_READER); bool does_exist = (zdb_zone_find_from_dnsname(db, dns_name) != NULL); // KEEP zdb_unlock(db, ZDB_MUTEX_READER); return does_exist; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-garbage.c0000644000000000000000000000013214505005531022246 xustar000000000000000030 mtime=1695812441.701971575 30 atime=1695812445.800030268 30 ctime=1695812495.092736238 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-garbage.c0000664000374500037450000002317314505005531022216 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include "dnsdb/dnsdb-config.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb-zone-garbage.h" #define ZDB_JOURNAL_CODE 1 // to be allowed to close it #include "dnsdb/journal.h" #if HAS_TRACK_ZONES_DEBUG_SUPPORT #include #endif extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger union zdb_zone_garbage_run_destroyed_cb_ptr { zdb_zone_garbage_run_destroyed_cb *cb; void *ptr; }; static threaded_dll_cw zone_garbage_queue; static ptr_vector zdb_zone_garbage_run_destroyed_callbacks = PTR_VECTOR_EMPTY; static mutex_t zdb_zone_garbage_run_destroyed_callbacks_mtx = MUTEX_INITIALIZER; #if HAS_TRACK_ZONES_DEBUG_SUPPORT extern smp_int g_zone_instanciated_count; extern ptr_set g_zone_instanciated_set; #endif void zdb_zone_garbage_run(); static bool zdb_zone_garbage_initialised = FALSE; void zdb_zone_garbage_init() { if(!zdb_zone_garbage_initialised) { threaded_dll_cw_init(&zone_garbage_queue, 0x100000); // 1M zones zdb_zone_garbage_initialised = TRUE; } } void zdb_zone_garbage_finalize() { if(zdb_zone_garbage_initialised) { log_debug("zdb_zone_garbage_finalize: releasing zones "); zdb_zone_garbage_run(); #if HAS_TRACK_ZONES_DEBUG_SUPPORT int count; if((count = smp_int_get(&g_zone_instanciated_count)) > 0) { log_err("zdb_zone_garbage_finalize: there are still %i zones instanciated (leaked?)", count); logger_flush(); ptr_set_iterator iter; ptr_set_iterator_init(&g_zone_instanciated_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); zdb_zone *zone = (zdb_zone*)node->key; log_err("%p: %{dnsname} is referenced %i times",zone, zone->origin, zone->rc); } } #endif threaded_dll_cw_finalize(&zone_garbage_queue); zdb_zone_garbage_initialised = FALSE; } } bool zdb_zone_garbage_collect(zdb_zone *zone) { yassert(zdb_rr_label_is_apex(zone->apex)); yassert(zone->rc == 0); /** @note consider adding a zone freed callback */ zdb_rr_label_flag_and(zone->apex, ~ZDB_RR_LABEL_APEX); #if ZDB_ZONE_HAS_JNL_REFERENCE journal *jh = zone->journal; // pointed to, to be closed as the zone is about to be destroyed journal_close(jh); #endif if(zdb_zone_garbage_initialised) { #if DEBUG log_debug("zdb_zone_garbage_collect: queuing zone %{dnsname}@%p for the collector", zone->origin, zone); #endif threaded_dll_cw_enqueue(&zone_garbage_queue, zone); return TRUE; } else { log_warn("zdb_zone_garbage_collect: collector disabled, destroying zone %{dnsname}@%p now", zone->origin, zone); #if DEBUG logger_flush(); #endif zdb_zone_destroy_nolock(zone); return FALSE; } } zdb_zone * zdb_zone_garbage_get() { if(zdb_zone_garbage_initialised) { zdb_zone *zone = (zdb_zone*)threaded_dll_cw_try_dequeue(&zone_garbage_queue); return zone; } else { log_warn("zdb_zone_garbage_get: collector disabled"); return NULL; } } bool zdb_zone_garbage_empty() { return threaded_dll_cw_size(&zone_garbage_queue) == 0; } void zdb_zone_garbage_run() { u8 fqdn[MAX_DOMAIN_LENGTH]; #if DEBUG log_debug("zdb_zone_garbage_run (%i)", zdb_zone_garbage_initialised); #endif if(zdb_zone_garbage_initialised) { bool has_callback = !ptr_vector_isempty(&zdb_zone_garbage_run_destroyed_callbacks); while(threaded_dll_cw_size(&zone_garbage_queue) > 0) { zdb_zone *zone = (zdb_zone*)threaded_dll_cw_try_dequeue(&zone_garbage_queue); if(zone != NULL) { if(has_callback) { dnsname_copy(fqdn, zone->origin); } #if DEBUG log_debug("zdb_zone_garbage_run: %{dnsname}@%p", zone->origin, zone); //logger_flush(); #endif zdb_zone_destroy(zone); if(has_callback) { mutex_lock(&zdb_zone_garbage_run_destroyed_callbacks_mtx); for(int i = 0; i <= ptr_vector_last_index(&zdb_zone_garbage_run_destroyed_callbacks); ++i) { union zdb_zone_garbage_run_destroyed_cb_ptr cb_ptr; cb_ptr.ptr = ptr_vector_get(&zdb_zone_garbage_run_destroyed_callbacks, i); cb_ptr.cb(fqdn); } mutex_unlock(&zdb_zone_garbage_run_destroyed_callbacks_mtx); } } } } else { log_warn("zdb_zone_garbage_run: collector disabled"); } #if DEBUG log_debug("zdb_zone_garbage_run done (%i)", zdb_zone_garbage_initialised); #endif } void zdb_zone_garbage_run_ex(zdb_zone_garbage_run_cb *destroyer) { u8 fqdn[MAX_DOMAIN_LENGTH]; #if DEBUG log_debug("zdb_zone_garbage_run_ex (%i)", zdb_zone_garbage_initialised); #endif if(zdb_zone_garbage_initialised) { if(destroyer == NULL) { destroyer = zdb_zone_destroy; } bool has_callback = !ptr_vector_isempty(&zdb_zone_garbage_run_destroyed_callbacks); while(threaded_dll_cw_size(&zone_garbage_queue) > 0) { zdb_zone *zone = (zdb_zone*)threaded_dll_cw_try_dequeue(&zone_garbage_queue); if(zone != NULL) { if(has_callback) { dnsname_copy(fqdn, zone->origin); } #if DEBUG log_debug("zdb_zone_garbage_run_ex: %{dnsname}", zone->origin); //logger_flush(); #endif destroyer(zone); if(has_callback) { mutex_lock(&zdb_zone_garbage_run_destroyed_callbacks_mtx); for(int i = 0; i <= ptr_vector_last_index(&zdb_zone_garbage_run_destroyed_callbacks); ++i) { union zdb_zone_garbage_run_destroyed_cb_ptr cb_ptr; cb_ptr.ptr = ptr_vector_get(&zdb_zone_garbage_run_destroyed_callbacks, i); cb_ptr.cb(fqdn); } mutex_unlock(&zdb_zone_garbage_run_destroyed_callbacks_mtx); } } } } else { log_warn("zdb_zone_garbage_run: collector disabled"); } #if DEBUG log_debug("zdb_zone_garbage_run_ex done (%i)", zdb_zone_garbage_initialised); #endif } void zdb_zone_garbage_run_callback_add(zdb_zone_garbage_run_destroyed_cb *cb) { mutex_lock(&zdb_zone_garbage_run_destroyed_callbacks_mtx); union zdb_zone_garbage_run_destroyed_cb_ptr cb_ptr; cb_ptr.cb = cb; ptr_vector_append(&zdb_zone_garbage_run_destroyed_callbacks, cb_ptr.ptr); mutex_unlock(&zdb_zone_garbage_run_destroyed_callbacks_mtx); } void zdb_zone_garbage_run_callback_remove(zdb_zone_garbage_run_destroyed_cb *cb) { union zdb_zone_garbage_run_destroyed_cb_ptr cb_ptr; cb_ptr.cb = cb; mutex_lock(&zdb_zone_garbage_run_destroyed_callbacks_mtx); for(int i = 0; i <= ptr_vector_last_index(&zdb_zone_garbage_run_destroyed_callbacks); ++i) { if(cb_ptr.ptr == ptr_vector_get(&zdb_zone_garbage_run_destroyed_callbacks, i)) { ptr_vector_remove_at(&zdb_zone_garbage_run_destroyed_callbacks, i); break; } } mutex_unlock(&zdb_zone_garbage_run_destroyed_callbacks_mtx); } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-journal.c0000644000000000000000000000013214505005531022330 xustar000000000000000030 mtime=1695812441.726971933 30 atime=1695812445.801030282 30 ctime=1695812495.094736267 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-journal.c0000664000374500037450000001322714505005531022277 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnsdb * @brief * * Journal API * * * @{ */ #define ZDB_JOURNAL_CODE 1 #include #include "dnsdb/dnsdb-config.h" #include "dnsdb/zdb-zone-journal.h" #include "dnsdb/journal.h" #include "dnsdb/zdb-zone-path-provider.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger /** * Returns the first and last serial in the journal of a loaded zone. * If the journal has not been opened yet (and bound to the zone) then it will be. * * @param zone the zone * @param out_serial_from, can be NULL * @param out_serial_to, can be NULL * * @return an error code */ ya_result zdb_zone_journal_get_serial_range(zdb_zone *zone, u32 *out_serial_from, u32 *out_serial_to) { ya_result ret; journal *jh; // opened (getting a reference to) for getting the serial range if(ISOK(ret = journal_acquire_from_zone(&jh, zone))) { ret = journal_get_serial_range(jh, out_serial_from, out_serial_to); journal_release(jh); } #if DEBUG else { log_warn("zdb_zone_journal_get_serial_range(%p, %p, %p) failed with %r (debug)", zone, out_serial_from, out_serial_to, ret); } #endif return ret; } /** * Opens a stream from the journal for reading an IXFR starting at a given serial. * * @param zone the zone * @param serial the serial to start from * @param out_is the stream to be initialised for reading the IXFR * @param out_last_soa_rr the last SOA record, can be NULL * * @return an error code */ ya_result zdb_zone_journal_get_ixfr_stream_at_serial(zdb_zone *zone, u32 serial, input_stream *out_is, dns_resource_record *out_last_soa_rr) { ya_result ret; journal *jh; // opened (getting a reference to) for getting the serial range if(ISOK(ret = journal_acquire_from_zone(&jh, zone))) { ret = journal_get_ixfr_stream_at_serial(jh, serial, out_is, out_last_soa_rr); journal_release(jh); } #if DEBUG else { log_debug("zdb_zone_journal_get_ixfr_stream_at_serial(%p, %d, %p, %p) failed with %r", zone, serial, out_is, out_last_soa_rr, ret); } #endif return ret; } /** * Appends an IXFR stream to the journal. * The expected stream lacks the repeated last SOA record at the first and last position. * * @param zone * @param is stream of uncompressed wire records : (SOA DEL DEL DEL ... SOA ADD ADD ADD ...)+ * @return an error code */ ya_result zdb_zone_journal_append_ixfr_stream(zdb_zone *zone, input_stream *is) { ya_result ret; journal *jh; // opened (getting a reference to) for getting the serial range if(ISOK(ret = journal_acquire_from_zone_ex(&jh, zone, TRUE))) { jh->vtbl->minimum_serial_update(jh, zone->text_serial); u32 journal_size_max = zone->wire_size / 3; u32 journal_size_limit = MAX_U32; zdb_zone_info_get_zone_max_journal_size(zone->origin, &journal_size_max); // ensure the max_size does not go beyond what was set by the admin zdb_zone_info_get_zone_max_journal_size(zone->origin, &journal_size_limit); // ensure the max_size does not go beyond what was set by the admin jh->vtbl->maximum_size_update(jh, journal_size_max); jh->vtbl->limit_size_update(jh, journal_size_limit); ret = journal_append_ixfr_stream(jh, is); // appends a whole stream journal_release(jh); } #if DEBUG else { log_debug("zdb_zone_journal_append_ixfr_stream(%p, %p) failed with %r", zone, is, ret); } #endif return ret; } /** * Deletes the file of the journal of a zone * * @param zone * @return */ ya_result zdb_zone_journal_delete(const zdb_zone *zone) { yassert(zone != NULL); #if DEBUG log_debug("zdb_zone_journal_delete(%p=%{dnsname})", zone, zone->origin); #endif ya_result ret = journal_truncate(zone->origin); return ret; } /** * @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-lock.c0000644000000000000000000000013214505005531021606 xustar000000000000000030 mtime=1695812441.702971589 30 atime=1695812445.800030268 30 ctime=1695812495.096736296 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-lock.c0000664000374500037450000006430314505005531021556 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include "dnsdb/zdb.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_error.h" #include "dnsdb/dnsrdata.h" #if ZDB_HAS_NSEC_SUPPORT #include "dnsdb/nsec.h" #endif #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #include #include #endif #if DEBUG #define ZONE_MUTEX_LOG 0 // set this to 0 to disable in DEBUG #else #define ZONE_MUTEX_LOG 0 #endif extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define MUTEX_LOCKED_TOO_MUCH_TIME_US 5000000 #define MUTEX_WAITED_TOO_MUCH_TIME_US 2000000 #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT static mutex_t zdb_zone_lock_set_mtx = MUTEX_INITIALIZER; static ptr_set zdb_zone_lock_set = PTR_SET_PTR_EMPTY; void zdb_zone_lock_set_add(zdb_zone *zone) { mutex_lock(&zdb_zone_lock_set_mtx); ptr_node *node = ptr_set_insert(&zdb_zone_lock_set, zone); node->value = zone; mutex_unlock(&zdb_zone_lock_set_mtx); } void zdb_zone_lock_set_del(zdb_zone *zone) { mutex_lock(&zdb_zone_lock_set_mtx); ptr_set_delete(&zdb_zone_lock_set, zone); mutex_unlock(&zdb_zone_lock_set_mtx); } static s64 zdb_zone_lock_set_monitor_last_duration = 0; static s64 zdb_zone_lock_set_monitor_last_time = 0; #if DEBUG const char* zdb_zone_lock_names[11]= { "NOBODY", // 0x00 "SIMPLEREADER", // 0x01 non-conflicting "RRSIG_UPDATER",// 0x82 conflicting "3?", "XFR", // 0x84 conflicting "REFRESH", // 0x85 conflicting "DYNUPDATE", // 0x86 conflicting "UNFREEZE", // 0x87 conflicting "INVALIDATE", // 0x88 conflicting "REPLACE", // 0x89 conflicting "LOAD" // 0x8a conflicting // "DESTROY" // 0xFF conflicting, can never be launched more than once. The zone will be destroyed before unlock. }; #endif void zdb_zone_lock_set_monitor() { s64 now = timeus(); if(now - zdb_zone_lock_set_monitor_last_time < zdb_zone_lock_set_monitor_last_duration) { return; } zdb_zone_lock_set_monitor_last_time = now; mutex_lock(&zdb_zone_lock_set_mtx); ptr_set_iterator iter; ptr_set_iterator_init(&zdb_zone_lock_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); zdb_zone *zone = (zdb_zone*)node->key; u8 owner = zone->lock_owner; if(owner == GROUP_MUTEX_NOBODY) { continue; } s64 ts = zone->lock_timestamp; stacktrace trace = zone->lock_trace; thread_t id = zone->lock_id; if(ts < now) { u64 dt = now - ts; if(dt > MUTEX_LOCKED_TOO_MUCH_TIME_US) { // locked for 5 seconds ... trouble #if !DEBUG log_warn("zdb_zone_lock@%p: %{dnsname}: locked by %x for %lluus by %p", zone, zone->origin, owner, dt, (intptr)id); #else if(owner <= 10) { log_warn("zdb_zone_lock@%p: %{dnsname}: locked by %s for %lluus by %p", zone, zone->origin, zdb_zone_lock_names[owner], dt, (intptr)id); } else { log_warn("zdb_zone_lock@%p: %{dnsname}: locked by %x for %lluus by %p", zone, zone->origin, owner, dt, (intptr)id); } #endif debug_stacktrace_log(MODULE_MSG_HANDLE, MSG_WARNING, trace); } } } mutex_unlock(&zdb_zone_lock_set_mtx); s64 after = timeus(); if(after - now > zdb_zone_lock_set_monitor_last_duration) { zdb_zone_lock_set_monitor_last_duration = after - now; } } #endif bool zdb_zone_islocked(zdb_zone *zone) { mutex_t *mutex = &zone->lock_mutex; mutex_lock(mutex); u8 owner = zone->lock_owner; mutex_unlock(mutex); return owner != 0; } bool zdb_zone_islocked_weak(const zdb_zone *zone) { u8 owner = zone->lock_owner; return owner != 0; } /** * Returns TRUE iff the zone is locked by a writer (any other owner value than nobody and simple reader) * * @param zone * @return */ bool zdb_zone_iswritelocked(zdb_zone *zone) { mutex_t *mutex = &zone->lock_mutex; mutex_lock(mutex); u8 owner = zone->lock_owner; mutex_unlock(mutex); return owner > ZDB_ZONE_MUTEX_SIMPLEREADER; } void zdb_zone_lock(zdb_zone *zone, u8 owner) { #if ZONE_MUTEX_LOG log_debug7("acquiring lock for zone %{dnsname}@%p for %x", zone->origin, zone, owner); #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT u64 start = timeus(); #endif #endif #if MUTEX_CONTENTION_MONITOR struct mutex_contention_monitor_s *mcm = mutex_contention_lock_begin(thread_self(), zone, debug_stacktrace_get(), "zdb_zone"); #endif mutex_t *mutex = &zone->lock_mutex; mutex_lock(mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_new(zone, owner, 0); #endif for(;;) { /* A simple way to ensure that a lock can be shared by similar entities or not. Sharable entities have their msb off. */ u8 co = zone->lock_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(co == GROUP_MUTEX_NOBODY || co == owner) { yassert(!SIGNED_VAR_VALUE_IS_MAX(zone->lock_count)); zone->lock_owner = owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; zone->lock_count++; break; } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_waits(holder); #endif #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT s64 d = timeus() - start; if(d > MUTEX_WAITED_TOO_MUCH_TIME_US) { log_warn("zdb_zone_lock(%{dnsname},%x) : waited for %llius already ...", zone->origin, owner, d); debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_WARNING, "zdb_zone_double_lock:"); } cond_timedwait(&zone->lock_cond, mutex, MUTEX_WAITED_TOO_MUCH_TIME_US); #else cond_wait(&zone->lock_cond, mutex); #endif #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_resumes(holder); #endif } #if ZDB_ZONE_LOCK_HAS_OWNER_ID zone->lock_last_owner_id = thread_self(); #endif #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_locks(holder); #endif mutex_unlock(mutex); #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT zone->lock_trace = debug_stacktrace_get(); zone->lock_id = thread_self(); zone->lock_timestamp = timeus(); zdb_zone_lock_set_add(zone); #endif } bool zdb_zone_trylock(zdb_zone *zone, u8 owner) { #if ZONE_MUTEX_LOG log_debug7("trying to acquire lock for zone %{dnsname}@%p for %x", zone->origin, zone, owner); #endif #if MUTEX_CONTENTION_MONITOR struct mutex_contention_monitor_s *mcm = mutex_contention_lock_begin(thread_self(), zone, debug_stacktrace_get(), "zdb_zone"); #endif mutex_lock(&zone->lock_mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_new(zone, owner, 0); #endif u8 co = zone->lock_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(co == ZDB_ZONE_MUTEX_NOBODY || co == owner) { yassert(!SIGNED_VAR_VALUE_IS_MAX(zone->lock_count)); zone->lock_owner = owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; zone->lock_count++; #if ZONE_MUTEX_LOG log_debug7("acquired lock for zone %{dnsname}@%p for %x (#%i)", zone->origin, zone, owner, zone->lock_count); #endif #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_locks(holder); #endif #if ZDB_ZONE_LOCK_HAS_OWNER_ID zone->lock_last_owner_id = thread_self(); #endif mutex_unlock(&zone->lock_mutex); #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT zone->lock_trace = debug_stacktrace_get(); zone->lock_id = thread_self(); zone->lock_timestamp = timeus(); zdb_zone_lock_set_add(zone); #endif #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif return TRUE; } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_cancels(holder); #endif mutex_unlock(&zone->lock_mutex); #if ZONE_MUTEX_LOG log_debug7("failed to acquire lock for zone %{dnsname}@%p for %x", zone->origin, zone, owner); #endif #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_fail(mcm); #endif return FALSE; } bool zdb_zone_trylock_wait(zdb_zone *zone, u64 usec, u8 owner) { #if ZONE_MUTEX_LOG log_debug7("trying to acquire lock for %lluus for zone %{dnsname}@%p for %x", usec, zone->origin, zone, owner); #endif #if MUTEX_CONTENTION_MONITOR struct mutex_contention_monitor_s *mcm = mutex_contention_lock_begin(thread_self(), zone, debug_stacktrace_get(), "zdb_zone"); #endif u64 start = timeus(); bool ret = FALSE; mutex_t *mutex = &zone->lock_mutex; mutex_lock(mutex); for(;;) { /* A simple way to ensure that a lock can be shared by similar entities or not. Sharable entities have their msb off. */ u8 co = zone->lock_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(co == GROUP_MUTEX_NOBODY || co == owner) { yassert(!SIGNED_VAR_VALUE_IS_MAX(zone->lock_count)); zone->lock_owner = owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; zone->lock_count++; ret = TRUE; break; } #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT s64 d = timeus() - start; if(d > MUTEX_WAITED_TOO_MUCH_TIME_US) { log_warn("zdb_zone_lock(%{dnsname},%x) : waited for %llius already ...", zone->origin, owner, d); debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_WARNING, "zdb_zone_double_lock:"); } cond_timedwait(&zone->lock_cond, mutex, MIN(MUTEX_WAITED_TOO_MUCH_TIME_US, usec)); #else cond_timedwait(&zone->lock_cond, mutex, usec); #endif u64 now = timeus(); if(now - start >= usec) { break; } } #if ZDB_ZONE_LOCK_HAS_OWNER_ID if(ret) { zone->lock_last_owner_id = thread_self(); } #endif mutex_unlock(mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT zone->lock_trace = debug_stacktrace_get(); zone->lock_id = thread_self(); zone->lock_timestamp = timeus(); zdb_zone_lock_set_add(zone); #endif #if MUTEX_CONTENTION_MONITOR if(ISOK(ret)) { mutex_contention_lock_end(mcm); } else { mutex_contention_lock_fail(mcm); } #endif return ret; } void zdb_zone_unlock(zdb_zone *zone, u8 owner) { #if ZONE_MUTEX_LOG log_debug7("releasing lock for zone %{dnsname}@%p by %x (owned by %x)", zone->origin, zone, owner, zone->lock_owner); #else (void)owner; #endif mutex_lock(&zone->lock_mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_get(zone); #endif #if DEBUG if(((zone->lock_owner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG) != (owner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG)) || (zone->lock_count == 0)) { yassert((zone->lock_owner == ZDB_ZONE_MUTEX_DESTROY) || (zone->lock_owner == (owner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG))); yassert(zone->lock_count != 0); abort(); // unreachable } #endif --zone->lock_count; #if ZONE_MUTEX_LOG log_debug7("released lock for zone %{dnsname}@%p by %x (#%i)", zone->origin, zone, owner, zone->lock_count); #endif if(zone->lock_count == 0) { zone->lock_owner = ZDB_ZONE_MUTEX_NOBODY; cond_notify(&zone->lock_cond); } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_unlocks(holder); #endif #if ZDB_ZONE_LOCK_HAS_OWNER_ID thread_t tid = thread_self(); if(zone->lock_last_owner_id == tid) { zone->lock_last_owner_id = 0; } #endif #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT zone->lock_trace = NULL; zone->lock_id = 0; zone->lock_timestamp = 0; zdb_zone_lock_set_del(zone); #endif mutex_unlock(&zone->lock_mutex); #if MUTEX_CONTENTION_MONITOR mutex_contention_unlock(thread_self(), zone); #endif } void zdb_zone_double_lock(zdb_zone *zone, u8 owner, u8 secondary_owner) { #if MUTEX_CONTENTION_MONITOR struct mutex_contention_monitor_s *mcm = mutex_contention_lock_begin(thread_self(), zone, debug_stacktrace_get(), "zdb_zone"); #endif #if ZONE_MUTEX_LOG log_debug7("acquiring lock for zone %{dnsname}@%p for %x", zone->origin, zone, owner); #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT u64 start = timeus(); #endif #endif mutex_lock(&zone->lock_mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_new(zone, owner, secondary_owner); #endif for(;;) { /* * A simple way to ensure that a lock can be shared * by similar entities or not. * Sharable entities have their msb off. */ u8 so = zone->lock_reserved_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(so == ZDB_ZONE_MUTEX_NOBODY || so == secondary_owner) { u8 co = zone->lock_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(co == ZDB_ZONE_MUTEX_NOBODY || co == owner) { yassert(!SIGNED_VAR_VALUE_IS_MAX(zone->lock_count)); zone->lock_owner = owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; zone->lock_count++; zone->lock_reserved_owner = secondary_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; #if ZDB_ZONE_LOCK_HAS_OWNER_ID thread_t tid = thread_self(); zone->lock_last_owner_id = tid; zone->lock_last_reserved_owner_id = tid; #endif #if ZONE_MUTEX_LOG log_debug7("acquired lock for zone %{dnsname}@%p for %x (#%i)", zone->origin, zone, owner, zone->lock_count); #endif break; } } else { // the secondary owner is already taken } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_waits(holder); #endif #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT s64 d = timeus() - start; if(d > MUTEX_WAITED_TOO_MUCH_TIME_US) { log_warn("zdb_zone_double_lock(%{dnsname},%x,%x) : waited for %llius already ...", zone->origin, owner, secondary_owner, d); debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_WARNING, "zdb_zone_double_lock:"); } cond_timedwait(&zone->lock_cond, &zone->lock_mutex, MUTEX_WAITED_TOO_MUCH_TIME_US); #else cond_wait(&zone->lock_cond, &zone->lock_mutex); #endif } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_locks(holder); #endif mutex_unlock(&zone->lock_mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT zone->lock_trace = debug_stacktrace_get(); zone->lock_id = thread_self(); zone->lock_timestamp = timeus(); zdb_zone_lock_set_add(zone); #endif #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif } bool zdb_zone_try_double_lock(zdb_zone *zone, u8 owner, u8 secondary_owner) { #if MUTEX_CONTENTION_MONITOR struct mutex_contention_monitor_s *mcm = mutex_contention_lock_begin(thread_self(), zone, debug_stacktrace_get(), "zdb_zone"); #endif #if ZONE_MUTEX_LOG log_debug7("trying to acquire lock for zone %{dnsname}@%p for %x", zone->origin, zone, owner); #endif mutex_lock(&zone->lock_mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_new(zone, owner, secondary_owner); #endif u8 so = zone->lock_reserved_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(so == ZDB_ZONE_MUTEX_NOBODY || so == secondary_owner) { u8 co = zone->lock_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(co == ZDB_ZONE_MUTEX_NOBODY || co == owner) { yassert(!SIGNED_VAR_VALUE_IS_MAX(zone->lock_count)); zone->lock_owner = owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; zone->lock_count++; zone->lock_reserved_owner = secondary_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; #if ZDB_ZONE_LOCK_HAS_OWNER_ID thread_t tid = thread_self(); zone->lock_last_owner_id = tid; zone->lock_last_reserved_owner_id = tid; #endif #if ZONE_MUTEX_LOG log_debug7("acquired lock for zone %{dnsname}@%p for %x (#%i)", zone->origin, zone, owner, zone->lock_count); #endif #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_locks(holder); #endif mutex_unlock(&zone->lock_mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT zone->lock_trace = debug_stacktrace_get(); zone->lock_id = thread_self(); zone->lock_timestamp = timeus(); zdb_zone_lock_set_add(zone); #endif #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif return TRUE; } } /* else { // already double-owned } */ #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_cancels(holder); #endif mutex_unlock(&zone->lock_mutex); #if ZONE_MUTEX_LOG log_debug7("failed to acquire lock for zone %{dnsname}@%p for %x", zone->origin, zone, owner); #endif #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_fail(mcm); #endif return FALSE; } bool zdb_zone_try_double_lock_ex(zdb_zone *zone, u8 owner, u8 secondary_owner, u8 *current_ownerp, u8 *current_reserved_ownerp) { #if MUTEX_CONTENTION_MONITOR struct mutex_contention_monitor_s *mcm = mutex_contention_lock_begin(thread_self(), zone, debug_stacktrace_get(), "zdb_zone"); #endif #if ZONE_MUTEX_LOG log_debug7("trying to acquire lock for zone %{dnsname}@%p for %x", zone->origin, zone, owner); #endif mutex_lock(&zone->lock_mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_new(zone, owner, secondary_owner); #endif *current_ownerp = zone->lock_owner; *current_reserved_ownerp = zone->lock_reserved_owner; u8 so = zone->lock_reserved_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(so == ZDB_ZONE_MUTEX_NOBODY || so == secondary_owner) { u8 co = zone->lock_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; if(co == ZDB_ZONE_MUTEX_NOBODY || co == owner) { yassert(!SIGNED_VAR_VALUE_IS_MAX(zone->lock_count)); zone->lock_owner = owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; zone->lock_count++; zone->lock_reserved_owner = secondary_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; #if ZDB_ZONE_LOCK_HAS_OWNER_ID thread_t tid = thread_self(); zone->lock_last_owner_id = tid; zone->lock_last_reserved_owner_id = tid; #endif #if ZONE_MUTEX_LOG log_debug7("acquired lock for zone %{dnsname}@%p for %x (#%i)", zone->origin, zone, owner, zone->lock_count); #endif #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_locks(holder); #endif mutex_unlock(&zone->lock_mutex); #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT zone->lock_trace = debug_stacktrace_get(); zone->lock_id = thread_self(); zone->lock_timestamp = timeus(); zdb_zone_lock_set_add(zone); #endif #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_end(mcm); #endif return TRUE; } } /* else { // already double-owned } */ #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_cancels(holder); #endif mutex_unlock(&zone->lock_mutex); #if ZONE_MUTEX_LOG log_debug7("failed to acquire lock for zone %{dnsname}@%p for %x", zone->origin, zone, owner); #endif #if MUTEX_CONTENTION_MONITOR mutex_contention_lock_fail(mcm); #endif return FALSE; } void zdb_zone_double_unlock(zdb_zone *zone, u8 owner, u8 secondary_owner) { #if ZONE_MUTEX_LOG log_debug7("releasing lock for zone %{dnsname}@%p by %x and %x (owned by %x and %x)", zone->origin, zone, owner, secondary_owner, zone->lock_owner, zone->lock_reserved_owner); #else (void)owner; (void)secondary_owner; #endif mutex_lock(&zone->lock_mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_get(zone); #endif #if ZDB_ZONE_LOCK_HAS_OWNER_ID thread_t tid = thread_self(); if(zone->lock_last_owner_id == tid) { zone->lock_last_owner_id = 0; } if(zone->lock_last_reserved_owner_id == tid) { zone->lock_last_reserved_owner_id = 0; } #endif assert(zone->lock_reserved_owner == (secondary_owner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG)); assert(zone->lock_owner == (owner & ZDB_ZONE_MUTEX_UNLOCKMASK_FLAG)); zone->lock_reserved_owner = ZDB_ZONE_MUTEX_NOBODY; --zone->lock_count; #if ZONE_MUTEX_LOG log_debug7("released lock for zone %{dnsname}@%p by %x (#%i)", zone->origin, zone, owner, zone->lock_count); #endif yassert((zone->lock_owner & 0xc0) == 0); // NO, because it does not always to a transfer lock yassert(zone->lock_count == 0); if(zone->lock_count == 0) { zone->lock_owner = ZDB_ZONE_MUTEX_NOBODY; cond_notify(&zone->lock_cond); } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_unlocks(holder); #endif #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT zone->lock_trace = NULL; zone->lock_id = 0; zone->lock_timestamp = 0; zdb_zone_lock_set_del(zone); #endif mutex_unlock(&zone->lock_mutex); #if MUTEX_CONTENTION_MONITOR mutex_contention_unlock(thread_self(), zone); #endif } void zdb_zone_exchange_locks(zdb_zone *zone, u8 owner, u8 secondary_owner) { #if ZONE_MUTEX_LOG log_debug7("exchanging locks for zone %{dnsname}@%p from %x to %x (owned by %x:%x)", zone->origin, zone, owner, secondary_owner, zone->lock_owner, zone->lock_reserved_owner); #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT u64 start = timeus(); #endif #endif mutex_lock(&zone->lock_mutex); #if ZDB_HAS_LOCK_DEBUG_SUPPORT struct zdb_zone_lock_monitor *holder = zdb_zone_lock_monitor_new(zone, owner, secondary_owner); #endif #if DEBUG if((zone->lock_owner != (owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG)) || (zone->lock_count == 0)) { yassert(zone->lock_owner == (owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG)); yassert(zone->lock_count != 0); abort(); // unreachable } if(zone->lock_reserved_owner != (secondary_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG)) { yassert(zone->lock_reserved_owner != (secondary_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG)); abort(); // unreachable } #endif // wait to be the last one while(zone->lock_count != 1) { #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_waits(holder); #endif #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT s64 d = timeus() - start; if(d > MUTEX_WAITED_TOO_MUCH_TIME_US) { log_warn("zdb_zone_transfer_lock(%{dnsname},%x,%x) : waited for %llius already ...", zone->origin, owner, secondary_owner, d); debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_WARNING, "zdb_zone_double_lock:"); } #endif cond_timedwait(&zone->lock_cond, &zone->lock_mutex, 100); #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_resumes(holder); #endif } zone->lock_owner = secondary_owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; zone->lock_reserved_owner = owner & ZDB_ZONE_MUTEX_LOCKMASK_FLAG; #if ZONE_MUTEX_LOG log_debug7("exchanged locks for zone %{dnsname}@%p from %x to %x (#%i)", zone->origin, zone, owner, secondary_owner, zone->lock_count); #endif if((secondary_owner & ZDB_ZONE_MUTEX_EXCLUSIVE_FLAG) == 0) { cond_notify(&zone->lock_cond); } #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_exchanges(holder); zdb_zone_lock_monitor_release(holder); #endif #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT zone->lock_trace = debug_stacktrace_get(); zone->lock_id = thread_self(); zone->lock_timestamp = timeus(); zdb_zone_lock_set_add(zone); #endif mutex_unlock(&zone->lock_mutex); } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-lock-monitor.c0000644000000000000000000000013214505005531023273 xustar000000000000000030 mtime=1695812441.727971948 30 atime=1695812445.801030282 30 ctime=1695812495.098736325 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-lock-monitor.c0000664000374500037450000005056414505005531023247 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnsdb/dnsdb-config.h" #include "dnsdb/zdb-config-features.h" #include #include #include #include "dnsdb/zdb-zone-lock-monitor.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #if ZDB_HAS_LOCK_DEBUG_SUPPORT #define ZNLCKMNT_TAG 0x544e4d4b434c4e5a #define log_arc log_debug6 #define MSG_ARC MSG_DEBUG6 struct zdb_zone_lock_monitor { const zdb_zone *zone; // not RCed, this is the key // stack trace stacktrace trace; // thread thread_t tid; // volatile u8 owner; volatile u8 secondary; // when s64 timestamp; // how many time waited volatile int waited; // how many are blocked volatile int blocks; // rc volatile int rc; }; typedef struct zdb_zone_lock_monitor zdb_zone_lock_monitor; static ptr_set_debug zdb_zone_arc_set = PTR_SET_DEBUG_EMPTY; static mutex_t zdb_zone_arc_set_mtx = MUTEX_INITIALIZER; static mutex_t zdb_zone_lock_monitor_mtx = MUTEX_INITIALIZER; static s64 zdb_zone_lock_set_monitor_last_duration = 0; static s64 zdb_zone_lock_set_monitor_last_time = 0; /* static const char* zdb_zone_lock_names[11]= { "NOBODY", // 0x00 "SIMPLEREADER", // 0x01 non-conflicting "RRSIG_UPDATER",// 0x82 conflicting "3?", "XFR", // 0x84 conflicting "REFRESH", // 0x85 conflicting "DYNUPDATE", // 0x86 conflicting "UNFREEZE", // 0x87 conflicting "INVALIDATE", // 0x88 conflicting "REPLACE", // 0x89 conflicting "LOAD" // 0x8a conflicting // "DESTROY" // 0xFF conflicting, can never be launched more than once. The zone will be destroyed before unlock. }; */ bool zdb_zone_lock_monitor_release(zdb_zone_lock_monitor *holder) { mutex_lock(&zdb_zone_lock_monitor_mtx); int rc = --holder->rc; mutex_unlock(&zdb_zone_lock_monitor_mtx); if(rc > 0) { return FALSE; } else { // do NOT try to free the track trace memset(holder, 0xfe, sizeof(zdb_zone_lock_monitor)); free(holder); return TRUE; } } /** * RC=2 * * @param zone * @return */ zdb_zone_lock_monitor *zdb_zone_lock_monitor_new(const zdb_zone *zone, u8 owner, u8 secondary) { zdb_zone_lock_monitor *holder; mutex_lock(&zdb_zone_arc_set_mtx); ptr_node_debug *node = ptr_set_debug_insert(&zdb_zone_arc_set, (zdb_zone*)zone); list_dl_s *list; if(node->value != NULL) { list = (list_dl_s*)node->value; } else { list = list_dl_new_instance(); node->value = list; } MALLOC_OR_DIE(zdb_zone_lock_monitor*,holder,sizeof(zdb_zone_lock_monitor), ZNLCKMNT_TAG); holder->zone = zone; holder->trace = debug_stacktrace_get(); holder->tid = thread_self(); holder->owner = owner; holder->secondary = secondary; holder->timestamp = timeus(); holder->waited = 0; holder->blocks = 0; holder->rc = 2; list_dl_append(list, holder); mutex_unlock(&zdb_zone_arc_set_mtx); log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): locking", holder->tid, zone->origin, zone, holder->owner, holder->secondary); debug_stacktrace_log(g_database_logger, MSG_ARC, holder->trace); return holder; } /* * RC++ */ zdb_zone_lock_monitor *zdb_zone_lock_monitor_get(const zdb_zone *zone) { mutex_lock(&zdb_zone_arc_set_mtx); ptr_node_debug *node = ptr_set_debug_find(&zdb_zone_arc_set, zone); if(node != NULL) { list_dl_s *list = (list_dl_s*)node->value; if(list != NULL) { if(list_dl_size(list) > 0) { zdb_zone_lock_monitor *holder = (zdb_zone_lock_monitor*)list_dl_peek_first(list); ++holder->rc; mutex_unlock(&zdb_zone_arc_set_mtx); log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): owner for %llu us", holder->tid, zone->origin, zone, holder->owner, holder->secondary, timeus()-holder->timestamp); debug_stacktrace_log(g_database_logger, MSG_ARC, holder->trace); return holder; } else { log_err("zone-lock: ? %{dnsname}@%p: zone has an empty list", zone->origin, zone); } } else { // weird log_err("zone-lock: ? %{dnsname}@%p: zone has no list", zone->origin, zone); } } else { // weird log_err("zone-lock: ? %{dnsname}@%p: zone has no key", zone->origin, zone); } mutex_unlock(&zdb_zone_arc_set_mtx); return NULL; } void zdb_zone_lock_monitor_waits(zdb_zone_lock_monitor *holder) { if(holder != NULL) { mutex_lock(&zdb_zone_lock_monitor_mtx); int waited = ++holder->waited; mutex_unlock(&zdb_zone_lock_monitor_mtx); zdb_zone_lock_monitor *blocker = zdb_zone_lock_monitor_get(holder->zone); if(blocker != NULL) { mutex_lock(&zdb_zone_lock_monitor_mtx); int blocked = ++blocker->blocks; mutex_unlock(&zdb_zone_lock_monitor_mtx); log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): waited %i time(s) for %lluus", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary, waited, timeus() - holder->timestamp); debug_stacktrace_log(g_database_logger, MSG_ARC, holder->trace); log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): blocked %i attempts in a period of %lluus", blocker->tid, blocker->zone->origin, blocker->zone, blocker->owner, blocker->secondary, blocked, timeus() - blocker->timestamp); debug_stacktrace_log(g_database_logger, MSG_ARC, blocker->trace); zdb_zone_lock_monitor_release(blocker); } else { // weird log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): should not be waiting (no known reason)", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } } else { // weird log_err("zone-lock: null holder"); } } void zdb_zone_lock_monitor_resumes(zdb_zone_lock_monitor *holder) { if(holder != NULL) { // nothing do do anyway log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): resumed %i time(s) for %lluus", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary, holder->waited, timeus() - holder->timestamp); debug_stacktrace_log(g_database_logger, MSG_ARC, holder->trace); } else { // weird log_err("zone-lock: null holder"); } } void zdb_zone_lock_monitor_exchanges(struct zdb_zone_lock_monitor *holder) { mutex_lock(&zdb_zone_arc_set_mtx); if(holder == NULL) { log_err("zone-lock: null holder"); mutex_unlock(&zdb_zone_arc_set_mtx); return; } ptr_node_debug *node = ptr_set_debug_find(&zdb_zone_arc_set, holder->zone); if(node != NULL) { list_dl_s *list = (list_dl_s*)node->value; if(list != NULL) { if(list_dl_size(list) > 0) { mutex_lock(&zdb_zone_lock_monitor_mtx); u8 o = holder->owner; u8 s = holder->secondary; holder->secondary = o; holder->owner = s; mutex_unlock(&zdb_zone_lock_monitor_mtx); if((holder->owner & 0x80) != 0) { zdb_zone_lock_monitor *head = (zdb_zone_lock_monitor*)list_dl_peek_first(list); if(holder != head) { // move it to the head list_dl_remove(list, holder); list_dl_insert(list, holder); } log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): exchanged after %i tries for %lluus", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary, holder->waited, timeus() - holder->timestamp); } else { log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): locked after %i tries for %lluus (shared)", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary, holder->waited, timeus() - holder->timestamp); } debug_stacktrace_log(g_database_logger, MSG_ARC, holder->trace); // no release here // zdb_zone_lock_monitor_release(holder); } else { log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): is from an empty list", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } } else { // weird log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): no list", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } } else { // weird log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): has no key)", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } mutex_unlock(&zdb_zone_arc_set_mtx); } /* * RC-- */ void zdb_zone_lock_monitor_locks(zdb_zone_lock_monitor *holder) { mutex_lock(&zdb_zone_arc_set_mtx); ptr_node_debug *node = ptr_set_debug_find(&zdb_zone_arc_set, holder->zone); if(node != NULL) { list_dl_s *list = (list_dl_s*)node->value; if(list != NULL) { if(list_dl_size(list) > 0) { if((holder->owner & 0x80) != 0) { zdb_zone_lock_monitor *head = (zdb_zone_lock_monitor*)list_dl_peek_first(list); if(holder != head) { // move it to the head list_dl_remove(list, holder); list_dl_insert(list, holder); } log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): locked after %i tries for %lluus", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary, holder->waited, timeus() - holder->timestamp); } else { log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): locked after %i tries for %lluus (shared)", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary, holder->waited, timeus() - holder->timestamp); } debug_stacktrace_log(g_database_logger, MSG_ARC, holder->trace); zdb_zone_lock_monitor_release(holder); } else { log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): is from an empty list", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } } else { // weird log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): no list", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } } else { // weird log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): has no key)", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } mutex_unlock(&zdb_zone_arc_set_mtx); } /* * RC -= 2 */ void zdb_zone_lock_monitor_cancels(zdb_zone_lock_monitor *holder) { mutex_lock(&zdb_zone_arc_set_mtx); ptr_node_debug *node = ptr_set_debug_find(&zdb_zone_arc_set, holder->zone); if(node != NULL) { list_dl_s *list = (list_dl_s*)node->value; if(list != NULL) { if(list_dl_size(list) > 0) { log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): cancelled after %i tries for %lluus", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary, holder->waited, timeus() - holder->timestamp); debug_stacktrace_log(g_database_logger, MSG_ARC, holder->trace); bool deleted = FALSE; if(list_dl_remove(list, holder)) { deleted = zdb_zone_lock_monitor_release(holder); yassert(list_dl_indexof(list,holder) < 0); } if(!deleted) { zdb_zone_lock_monitor_release(holder); yassert(list_dl_indexof(list,holder) < 0); } else { // weird } } else { log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): is from an empty list", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } } else { // weird log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): no list", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } } else { // weird log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): has no key)", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } mutex_unlock(&zdb_zone_arc_set_mtx); } /* * RC -= 2 */ void zdb_zone_lock_monitor_unlocks(zdb_zone_lock_monitor *holder) { if(holder == NULL) { log_err("zone-lock: unlocking NULL"); return; } mutex_lock(&zdb_zone_arc_set_mtx); ptr_node_debug *node = ptr_set_debug_find(&zdb_zone_arc_set, holder->zone); if(node != NULL) { list_dl_s *list = (list_dl_s*)node->value; if(list != NULL) { if(list_dl_size(list) > 0) { log_arc("zone-lock: %p %{dnsname}@%p (%02x/%02x): unlocked after blocking %i others for %lluus, zone is (%02x/%02x+%3i)", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary, holder->blocks, timeus() - holder->timestamp, holder->zone->lock_owner, holder->zone->lock_reserved_owner, holder->zone->lock_count ); debug_stacktrace_log(g_database_logger, MSG_ARC, holder->trace); bool deleted = FALSE; if(list_dl_remove(list, holder)) { deleted = zdb_zone_lock_monitor_release(holder); yassert(list_dl_indexof(list,holder) < 0); } if(!deleted) { zdb_zone_lock_monitor_release(holder); yassert(list_dl_indexof(list,holder) < 0); } else { // weird log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): bogus RC", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } } else { log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): is from an empty list", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } } else { // weird log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): no list", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } } else { // weird log_err("zone-lock: %p %{dnsname}@%p (%02x/%02x): has no key)", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary); } mutex_unlock(&zdb_zone_arc_set_mtx); } void zdb_zone_lock_monitor_log() { s64 now = timeus(); if((now - zdb_zone_lock_set_monitor_last_time) < zdb_zone_lock_set_monitor_last_duration) { return; } zdb_zone_lock_set_monitor_last_time = now; mutex_lock(&zdb_zone_arc_set_mtx); ptr_set_debug_iterator iter; ptr_set_debug_iterator_init(&zdb_zone_arc_set, &iter); while(ptr_set_debug_iterator_hasnext(&iter)) { ptr_node_debug *node = ptr_set_debug_iterator_next_node(&iter); list_dl_s *list = (list_dl_s*)node->value; if(list != NULL) { if(list_dl_size(list) > 0) { list_dl_iterator_s listiter; list_dl_iterator_init(&listiter, list); if(list_dl_iterator_has_next(&listiter)) { zdb_zone_lock_monitor *locker = (zdb_zone_lock_monitor*)list_dl_iterator_next(&listiter); s64 duration = timeus() - locker->timestamp; const char *toolong = (duration >= MUTEX_LOCKED_TOO_MUCH_TIME_US)?", which is too long":""; log_arc("zone-lock: lock: %p %{dnsname}@%p (%02x/%02x): blocked %i attempts in a period of %lluus%s", locker->tid, locker->zone->origin, locker->zone, locker->owner, locker->secondary, locker->blocks, timeus() - locker->timestamp, toolong); debug_stacktrace_log(g_database_logger, MSG_ARC, locker->trace); while(list_dl_iterator_has_next(&listiter)) { zdb_zone_lock_monitor *holder = (zdb_zone_lock_monitor*)list_dl_iterator_next(&listiter); duration = timeus() - locker->timestamp; toolong = (duration >= MUTEX_LOCKED_TOO_MUCH_TIME_US)?", which is too long":""; log_arc("zone-lock: wait: %p %{dnsname}@%p (%02x/%02x): waited %i time(s) for %lluus", holder->tid, holder->zone->origin, holder->zone, holder->owner, holder->secondary, holder->waited, timeus() - holder->timestamp, toolong); debug_stacktrace_log(g_database_logger, MSG_ARC, holder->trace); } } } } } mutex_unlock(&zdb_zone_arc_set_mtx); s64 after = timeus(); if((after - now) > zdb_zone_lock_set_monitor_last_duration) { zdb_zone_lock_set_monitor_last_duration = after - now; } } #endif yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-path-provider.c0000644000000000000000000000013214505005531023442 xustar000000000000000030 mtime=1695812441.698971533 30 atime=1695812445.800030268 30 ctime=1695812495.101736368 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-path-provider.c0000664000374500037450000002452514505005531023414 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include "dnsdb/zdb-zone-path-provider.h" static ya_result zdb_zone_path_provider_default(const u8* domain_fqdn, char *path_buffer, u32 path_buffer_size, u32 flags); static zdb_zone_path_provider_callback *zdb_zone_path_provider = zdb_zone_path_provider_default; static char *xfr_path = LOCALSTATEDIR "/zones/xfr"; static bool xfr_path_free = FALSE; /** * The hash function that gives a number from an ASCIIZ string * * @param p ASCIIZ string * * @return the hash */ static u32 zdb_zone_path_provider_copy_hash(const u8 *p) { u32 h = 0; u32 c; u8 s = 0; do { c = toupper(*p++); c &= 0x3f; h += c << (s & 15); h += 97; s += 13; } while(c != 0); return h; } /** * * Returns the hashed folder path for a zone. * * @param data_path the target buffer for the data path * @param data_path_size the target buffer size * @param base_data_path the base folder * @param origin the origin of the zone * * @return */ static ya_result zdb_zone_path_provider_get_data_path(char *data_path, u32 data_path_size, const char *base_data_path, const u8 *origin) { u32 h = zdb_zone_path_provider_copy_hash(origin); return snformat(data_path, data_path_size, "%s/%02x/%02x", base_data_path, h & 0xff, (h >> 8) & 0xff); } /** * For backward compatibility * * @param path */ void journal_set_xfr_path(const char *path) { if(xfr_path_free) { free((char*)xfr_path); } if(path == NULL) { xfr_path = LOCALSTATEDIR "/xfr"; xfr_path_free = FALSE; } else { xfr_path = strdup(path); xfr_path_free = TRUE; } } /** * For backward compatibility */ const char* journal_get_xfr_path() { return xfr_path; } static ya_result zdb_zone_path_provider_default(const u8* domain_fqdn, char *path_buffer, u32 path_buffer_size, u32 flags) { ya_result ret; char *suffix = ""; char dir_path[PATH_MAX]; if((flags & ZDB_ZONE_PATH_PROVIDER_RNDSUFFIX) != 0) { flags &= ~ZDB_ZONE_PATH_PROVIDER_RNDSUFFIX; suffix = ".part"; } if(FAIL(ret = zdb_zone_path_provider_get_data_path(dir_path, sizeof(dir_path), xfr_path, domain_fqdn))) // default path provider { return ret; } if((flags & ZDB_ZONE_PATH_PROVIDER_MKDIR) != 0) { flags &= ~ZDB_ZONE_PATH_PROVIDER_MKDIR; if(FAIL(ret = mkdir_ex(dir_path, 0755, 0))) { return ret; } } switch(flags) { case ZDB_ZONE_PATH_PROVIDER_ZONE_FILE: { ret = snformat(path_buffer, path_buffer_size, "%s/%{dnsname}%s", dir_path, domain_fqdn, suffix); break; } case ZDB_ZONE_PATH_PROVIDER_ZONE_PATH: { ret = snformat(path_buffer, path_buffer_size, "%s", dir_path); break; } case ZDB_ZONE_PATH_PROVIDER_DNSKEY_PATH: { ret = snformat(path_buffer, path_buffer_size, "%s/keys", dir_path); break; } default: { ret = INVALID_ARGUMENT_ERROR; // no handled flags have been used } } return ret; } /** * Sets the provider. * Note that the provider should return the length of the strings it returns. * * @param provider the provider or NULL to reset to the default one. */ void zdb_zone_path_set_provider(zdb_zone_path_provider_callback *provider) { if(provider == NULL) { provider = zdb_zone_path_provider_default; } zdb_zone_path_provider = provider; } /** * * @return */ static ya_result zdb_zone_info_provider_data_default(const u8 *origin, zdb_zone_info_provider_data *data, u32 flags); static zdb_zone_info_provider_callback *zdb_zone_info_provider = zdb_zone_info_provider_data_default; static ya_result zdb_zone_info_provider_data_default(const u8 *origin, zdb_zone_info_provider_data *data, u32 flags) { (void)origin; (void)data; (void)flags; return FEATURE_NOT_IMPLEMENTED_ERROR; } zdb_zone_path_provider_callback * zdb_zone_path_get_provider() { return zdb_zone_path_provider; } void zdb_zone_info_set_provider(zdb_zone_info_provider_callback *data) { if(data == NULL) { data = zdb_zone_info_provider_data_default; } zdb_zone_info_provider = data; } zdb_zone_info_provider_callback * zdb_zone_info_get_provider() { return zdb_zone_info_provider; } ya_result zdb_zone_info_get_stored_serial(const u8 *origin, u32 *serial) { yassert(origin != NULL); yassert(serial != NULL); zdb_zone_info_provider_data data; ya_result ret; if(ISOK(ret = zdb_zone_info_get_provider()(origin, &data, ZDB_ZONE_INFO_PROVIDER_STORED_SERIAL))) { *serial = data._u32; // VS false positive: reaching this point, data is initialized (by contract) } return ret; } ya_result zdb_zone_info_get_zone_max_journal_size(const u8 *origin, u32 *size) { yassert(origin != NULL); yassert(size != NULL); zdb_zone_info_provider_data data; data._u64 = *size; // known wire size / 2 ya_result ret; if(ISOK(ret = zdb_zone_info_get_provider()(origin, &data, ZDB_ZONE_INFO_PROVIDER_MAX_JOURNAL_SIZE))) { if(data._u64 > MAX_U32) { data._u64 = MAX_U32; } /// @note THX: here, if data._u64 is < 256*1024, then set to 256*1024 . *size = data._u64; } return ret; } ya_result zdb_zone_info_get_zone_type(const u8 *origin, u8 *zt) { yassert(origin != NULL); yassert(zt != NULL); zdb_zone_info_provider_data data; ya_result ret; if(ISOK(ret = zdb_zone_info_get_provider()(origin, &data, ZDB_ZONE_INFO_PROVIDER_ZONE_TYPE))) { *zt = data._u8; // VS false positive: reaching this point, data is initialized (by contract) } return ret; } ya_result zdb_zone_info_background_store_zone(const u8 *origin) { yassert(origin != NULL); ya_result ret; ret = zdb_zone_info_get_provider()(origin, NULL, ZDB_ZONE_INFO_PROVIDER_STORE_TRIGGER); return ret; } ya_result zdb_zone_info_store_locked_zone(const u8 *origin) { yassert(origin != NULL); ya_result ret; zdb_zone_info_provider_data already_locked_by; already_locked_by._u8 = 0; ret = zdb_zone_info_get_provider()(origin, &already_locked_by, ZDB_ZONE_INFO_PROVIDER_STORE_NOW); return ret; } /** * * Should not be used anymore. * * @param origin * @param minimum_serial * @return */ ya_result zdb_zone_info_background_store_zone_and_wait_for_serial(const u8 *origin, u32 minimum_serial) { // This mechanism should be improved : the zone should be unlocked, frozen, saved, unfrozen, re-locked yassert(origin != NULL); ya_result ret; ret = zdb_zone_info_get_provider()(origin, NULL, ZDB_ZONE_INFO_PROVIDER_STORE_TRIGGER); if(ISOK(ret)) { u64 start = timeus(); for(;;) { u32 serial; if(FAIL(ret = zdb_zone_info_get_stored_serial(origin, &serial))) { return ret; } if(serial_ge(serial, minimum_serial)) { return SUCCESS; } u64 now = timeus(); if(now < start) { start = now; //clock modified } if(now - start > ONE_SECOND_US) { zdb_zone_info_provider_data already_locked_by; already_locked_by._u8 = 0; if(FAIL(ret = zdb_zone_info_get_provider()(origin, &already_locked_by, ZDB_ZONE_INFO_PROVIDER_STORE_TRIGGER))) { return ret; } } usleep(500000); } } return ret; } ya_result zdb_zone_info_background_store_in_progress(const u8 *origin) { // This mechanism should be improved : the zone should be unlocked, frozen, saved, unfrozen, re-locked yassert(origin != NULL); ya_result ret; ret = zdb_zone_info_get_provider()(origin, NULL, ZDB_ZONE_INFO_PROVIDER_STORE_IN_PROGRESS); return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-reader-filter.c0000644000000000000000000000013214505005531023403 xustar000000000000000030 mtime=1695812441.750972277 30 atime=1695812445.802030296 30 ctime=1695812495.103736396 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-reader-filter.c0000664000374500037450000001303014505005531023342 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone * @ingroup dnsdb * @brief Functions used to load a zone * * Functions used to load a zone * * @{ */ #include #include "dnsdb/dnsdb-config.h" #include "dnsdb/zdb-zone-reader-filter.h" #define ZFRFDATA_TAG 0x415441444652465a struct zone_reader_text_filter_data { zone_reader *zr; zone_file_reader_filter_callback *callback; void *callback_data; }; typedef struct zone_reader_text_filter_data zone_reader_text_filter_data; static ya_result zone_reader_filter_read_record(zone_reader *zr, resource_record *rr) { zone_reader_text_filter_data *data = (zone_reader_text_filter_data*)zr->data; for(;;) { ya_result ret = zone_reader_read_record(data->zr, rr); if(ret != 0) // failure or end of input { return ret; } ya_result cb_ret = data->callback(data->zr, rr, data->callback_data); switch(cb_ret) { case ZONE_READER_FILTER_ACCEPT: return ret; case ZONE_READER_FILTER_REJECT: break; default: return cb_ret; } } } static ya_result zone_reader_filter_unread_record(zone_reader *zr, resource_record *rr) { zone_reader_text_filter_data *data = (zone_reader_text_filter_data*)zr->data; return zone_reader_unread_record(data->zr, rr); } static ya_result zone_reader_filter_free_record(zone_reader *zr, resource_record *rr) { zone_reader_text_filter_data *data = (zone_reader_text_filter_data*)zr->data; return zone_reader_free_record(data->zr, rr); } static void zone_reader_filter_close(zone_reader *zr) { zone_reader_text_filter_data *data = (zone_reader_text_filter_data*)zr->data; zone_reader_close(data->zr); ZFREE(data, zone_reader_text_filter_data); zr->data = NULL; zr->vtbl = NULL; } static bool zone_reader_filter_canwriteback(zone_reader *zr) { zone_reader_text_filter_data *data = (zone_reader_text_filter_data*)zr->data; yassert(zr != data->zr); bool b = zone_reader_canwriteback(data->zr); return b; } static void zone_reader_filter_handle_error(zone_reader *zr, ya_result error_code) { zone_reader_text_filter_data *data = (zone_reader_text_filter_data*)zr->data; zone_reader_handle_error(data->zr, error_code); } static const char* zone_reader_filter_get_last_error_message(zone_reader *zr) { zone_reader_text_filter_data *data = (zone_reader_text_filter_data*)zr->data; const char *ret = zone_reader_get_last_error_message(data->zr); return ret; } static const zone_reader_vtbl zone_reader_filter_vtbl = { zone_reader_filter_read_record, zone_reader_filter_unread_record, zone_reader_filter_free_record, zone_reader_filter_close, zone_reader_filter_handle_error, zone_reader_filter_canwriteback, zone_reader_filter_get_last_error_message, "zone_reader_filter" }; /** * * Wraps a zone_reader to a filter that skips records using a callback * * @param filtering_reader the filter * @param filtered_reader the filtered * @param callback the callback function * @param callback_data parameter given to the callback function */ void zone_reader_text_filter(zone_reader *filtering_reader, zone_reader *filtered_reader, zone_file_reader_filter_callback *callback, void *callback_data) { zone_reader_text_filter_data *data; ZALLOC_OBJECT_OR_DIE( data, zone_reader_text_filter_data, ZFRFDATA_TAG); data->zr = filtered_reader; data->callback = callback; data->callback_data = callback_data; filtering_reader->data = data; filtering_reader->vtbl = &zone_reader_filter_vtbl; } /** * @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb.c0000644000000000000000000000013214505005531017707 xustar000000000000000030 mtime=1695812441.703971604 30 atime=1695812445.800030268 30 ctime=1695812495.105736425 yadifa-2.6.5-11201/lib/dnsdb/src/zdb.c0000664000374500037450000004046414505005531017661 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdb Zone database * @brief The zone dataBase * * @{ */ #define ZDB_JOURNAL_CODE 1 #include "dnsdb/dnsdb-config.h" #include #include //#include #include #include #include #include #include #include extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #include "dnsdb/zdb.h" #if ZDB_HAS_DNSSEC_SUPPORT #include "dnsdb/dnssec-keystore.h" #endif #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/dictionary.h" #include "dnsdb/journal.h" #include "dnsdb/zdb-zone-garbage.h" #if ZDB_OPENSSL_SUPPORT #include #include #include #include // needed #ifndef SSL_API #error "SSL_API not defined" #endif /* * Required to handle openssl with multiple threads */ #define ZDB_SSLMUTEX_TAG 0x584554554d4c5353 #ifndef __DATE__ #define __DATE__ "date?" #endif #ifndef __TIME__ #define __TIME__ "time?" #endif #if HAS_BUILD_TIMESTAMP #if DEBUG const char *dnsdb_lib = "dnsdb " __DATE__ " " __TIME__ " debug"; #else const char *dnsdb_lib = "dnsdb " __DATE__ " " __TIME__ " release"; #endif #else #if DEBUG const char *dnsdb_lib = "dnsdb debug"; #else const char *dnsdb_lib = "dnsdb release"; #endif #endif void dnssec_keystore_init(); #if SSL_API_LT_110 static mutex_t *ssl_mutex = NULL; static int ssl_mutex_count = 0; static void ssl_lock(int mode, int type, const char* file, int line) { if((mode & CRYPTO_LOCK) != 0) { /* lock */ mutex_lock(&ssl_mutex[type]); } else { /* unlock */ mutex_unlock(&ssl_mutex[type]); } } static unsigned long ssl_thread_id() { return (unsigned long)thread_self(); } #endif #endif logger_handle* g_database_logger = LOGGER_HANDLE_SINK; /** @brief Initializes the database internals. * * Checks the architecture settings of the binary. * Initializes the database internals. * Multiple calls is a NOP. * * This is not thread safe. * */ static volatile bool zdb_init_done = FALSE; dnsdb_fingerprint dnsdb_getfingerprint() { dnsdb_fingerprint ret = dnsdb_getmyfingerprint(); return ret; } u32 dnsdb_fingerprint_mask() { return DNSCORE_TSIG|DNSCORE_ACL|DNSCORE_NSEC|DNSCORE_NSEC3; } int zalloc_init(); void zdb_init_ex(u32 thread_pool_count) { (void)thread_pool_count; if(zdb_init_done) { return; } /* DO or DIE */ if(dnscore_getfingerprint() != dnscore_getmyfingerprint()) { flushout(); flusherr(); printf("dnsdb: the linked dnscore features are %08x but the lib has been compiled against one with %08x", dnscore_getfingerprint(), dnscore_getmyfingerprint()); fflush(NULL); abort(); // binary incompatiblity : full stop } zdb_init_done = TRUE; /* Init the dns core */ dnscore_init(); zalloc_init(); zdb_zone_garbage_init(); /* Init the error table */ zdb_register_errors(); #if ZDB_OPENSSL_SUPPORT /* Init openssl */ #if SSL_API_LT_110 ENGINE_load_openssl(); #endif ENGINE_load_builtin_engines(); #if SSL_API_LT_110 SSL_load_error_strings(); ssl_mutex_count = CRYPTO_num_locks(); MALLOC_OR_DIE(mutex_t*, ssl_mutex, ssl_mutex_count * sizeof(mutex_t), ZDB_SSLMUTEX_TAG); int i; for(i = 0; i < ssl_mutex_count; i++) { mutex_init(&ssl_mutex[i]); } CRYPTO_set_id_callback(ssl_thread_id); CRYPTO_set_locking_callback(ssl_lock); #endif dnssec_keystore_init(); #endif journal_init(0); // uses the default mru size (512) logger_start(); } void zdb_init() { u32 thread_pool_count = sys_get_cpu_count() + 2; zdb_init_ex(thread_pool_count); } void zdb_finalize() { if(!zdb_init_done) { return; } zdb_init_done = FALSE; #if ZDB_HAS_DNSSEC_SUPPORT #if DEBUG dnssec_keystore_destroy(); dnssec_keystore_resetpath(); #endif #endif zdb_zone_garbage_finalize(); journal_finalize(); #if ZDB_OPENSSL_SUPPORT #if SSL_API_LT_110 ERR_remove_state(0); /* Init openssl */ CRYPTO_set_locking_callback(NULL); CRYPTO_set_id_callback(NULL); int i; for(i = 0; i < ssl_mutex_count; i++) { mutex_destroy(&ssl_mutex[i]); } ssl_mutex_count = 0; free(ssl_mutex); #endif ENGINE_cleanup(); #endif } /** @brief Initializes a database. * * Initializes a database. * * @param[in] db a pointer to the zdb structure that will be initialized. * */ void zdb_create(zdb* db) { zdb_zone_label* zone_label; ZALLOC_OBJECT_OR_DIE(zone_label, zdb_zone_label, ZDB_ZONELABEL_TAG); ZEROMEMORY(zone_label, sizeof(zdb_zone_label)); zone_label->name = dnslabel_zdup(ROOT_LABEL); /* . */ dictionary_init(&zone_label->sub); db->root = zone_label; /* native order */ db->alarm_handle = alarm_open((const u8*)"\010d@tabase"); // a name that is not likely to be used for a domain as it has invalid chars group_mutex_init(&db->mutex); } /** * * Puts a zone in the DB. * * If a zone with the same name did exist, returns the old zone (to be released) * and replaces it with the one given as a parameter. * * This function temporarily locks the database for writing. * The zone added gets its RC increased. * * @param db the database * @param zone the zone to mount (will be RC++) * @return the previously mounted zone (to be RC--) */ zdb_zone * zdb_set_zone(zdb *db, zdb_zone* zone) { yassert(zone != NULL); zdb_lock(db, ZDB_MUTEX_WRITER); zdb_zone_label *label = zdb_zone_label_add_nolock(db, &zone->origin_vector); // zdb_set_zone zdb_zone *old_zone = label->zone; zdb_zone_acquire(zone); label->zone = zone; #if DEBUG log_debug("zdb: added zone %{dnsname}@%p", zone->origin, zone); #endif zdb_unlock(db, ZDB_MUTEX_WRITER); return old_zone; } zdb_zone * zdb_remove_zone(zdb *db, dnsname_vector *name) { yassert(db != NULL && name != NULL); zdb_lock(db, ZDB_MUTEX_WRITER); zdb_zone_label *label = zdb_zone_label_find(db, name); // zdb_detach_zone zdb_zone *old_zone = NULL; if(label != NULL) { old_zone = label->zone; label->zone = NULL; #if DEBUG log_debug("zdb: removed zone %{dnsnamevector}@%p", name, old_zone); #endif if(ZONE_LABEL_IRRELEVANT(label)) { // removes the label from the database // if the label had been relevant (sub domains) // the zones below would be released and destroyed in due time zdb_zone_label_delete(db, name); } } zdb_unlock(db, ZDB_MUTEX_WRITER); return old_zone; } zdb_zone * zdb_remove_zone_from_dnsname(zdb *db, const u8 *fqdn) { dnsname_vector origin; dnsname_to_dnsname_vector(fqdn, &origin); zdb_zone *zone = zdb_remove_zone(db, &origin); return zone; } #if 1 /// @note 20190109 edf -- cannot be marked as OBSOLETE as the function is used on another project. /** @brief Search for a match in the database * * Search for a match in the database. * Only the most relevant match will be returned. * * @param[in] db the database * @param[in] dnsname_name the name dnsname to search for * @param[in] type the type to match * @param[out] ttl_rdara_out a pointer to a pointer set of results (single linked list) * * @return SUCCESS in case of success. */ ya_result zdb_query_ip_records(zdb* db, const u8* name_, zdb_packed_ttlrdata* * restrict ttlrdata_out_a, zdb_packed_ttlrdata* * restrict ttlrdata_out_aaaa) // mutex checked { yassert(ttlrdata_out_a != NULL && ttlrdata_out_aaaa != NULL); dnsname_vector name; dnsname_to_dnsname_vector(name_, &name); /* Find closest matching label * Should return a stack of zones */ zdb_lock(db, ZDB_MUTEX_READER); // zdb_query_ip_records zdb_zone_label_pointer_array zone_label_stack; s32 top = zdb_zone_label_match(db, &name, zone_label_stack); s32 sp = top; /* Got a stack of zone labels with and without zone cuts */ /* Search the label on the zone files */ while(sp >= 0) { zdb_zone_label* zone_label = zone_label_stack[sp]; if(zone_label->zone != NULL) { /* Get the label, instead of the type in the label */ zdb_rr_label* rr_label = zdb_rr_label_find_exact(zone_label->zone->apex, name.labels, name.size - sp); if(rr_label != NULL) { zdb_packed_ttlrdata* a = zdb_record_find(&rr_label->resource_record_set, TYPE_A); // zone is locked zdb_packed_ttlrdata* aaaa = zdb_record_find(&rr_label->resource_record_set, TYPE_AAAA); // zone is locked if(a != NULL || aaaa != NULL) { *ttlrdata_out_a = a; *ttlrdata_out_aaaa = aaaa; zdb_unlock(db, ZDB_MUTEX_READER); // zdb_query_ip_records (success) return SUCCESS; } } } sp--; } zdb_unlock(db, ZDB_MUTEX_READER); // zdb_query_ip_records (failure) return ZDB_ERROR_KEY_NOTFOUND; } #endif // OBSOLETE /** * * Appends all A and AAAA records found in the database for the given fqdn * Given the nature of the list, what is returned is a copy. * The call locks the database for reading, then each involved zone for reading. * Locks are released before the function returns. * The port field of the host_address is set to a given port (network order) * * @param db database * @param name_ fqdn * @param target_list list * @param network_order_port u16 * @return */ ya_result zdb_append_ip_records_with_port_ne(zdb* db, const u8* name_, host_address *target_list, u16 network_order_port) { yassert(target_list != NULL); dnsname_vector name; dnsname_to_dnsname_vector(name_, &name); /* Find closest matching label * Should return a stack of zones */ zdb_lock(db, ZDB_MUTEX_READER); // zdb_query_ip_records zdb_zone_label_pointer_array zone_label_stack; s32 top = zdb_zone_label_match(db, &name, zone_label_stack); s32 sp = top; /* Got a stack of zone labels with and without zone cuts */ /* Search the label on the zone files */ while(sp >= 0) { zdb_zone_label* zone_label = zone_label_stack[sp]; if(zone_label->zone != NULL) { zdb_zone_lock(zone_label->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); /* Get the label, instead of the type in the label */ zdb_rr_label* rr_label = zdb_rr_label_find_exact(zone_label->zone->apex, name.labels, name.size - sp); // zone is locked if(rr_label != NULL) { ya_result ret = 0; zdb_packed_ttlrdata* rrset; rrset = zdb_record_find(&rr_label->resource_record_set, TYPE_A); // zone is locked while(rrset != NULL) { host_address_append_ipv4(target_list, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrset), network_order_port); ++ret; rrset = rrset->next; } rrset = zdb_record_find(&rr_label->resource_record_set, TYPE_AAAA); // zone is locked while(rrset != NULL) { host_address_append_ipv6(target_list, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrset), network_order_port); ++ret; rrset = rrset->next; } zdb_zone_unlock(zone_label->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); zdb_unlock(db, ZDB_MUTEX_READER); // zdb_query_ip_records (success) return ret; } zdb_zone_unlock(zone_label->zone, ZDB_ZONE_MUTEX_SIMPLEREADER); } sp--; } zdb_unlock(db, ZDB_MUTEX_READER); // zdb_query_ip_records (failure) return ZDB_ERROR_KEY_NOTFOUND; } /** * * Appends all A and AAAA records found in the database for the given fqdn * Given the nature of the list, what is returned is a copy. * The call locks the database for reading, then each involved zone for reading. * Locks are released before the function returns. * * @param db database * @param name_ fqdn * @param target_list list * @return */ ya_result zdb_append_ip_records(zdb* db, const u8* name_, host_address *target_list) { ya_result ret = zdb_append_ip_records_with_port_ne(db, name_, target_list, NU16(DNS_DEFAULT_PORT)); return ret; } /** @brief Destroys the database * * Destroys a database. (Empties it) * * @param[in] db the database to destroy * */ void zdb_destroy(zdb* db) // mutex checked { zdb_lock(db, ZDB_MUTEX_WRITER); // zdb_destroy alarm_close(db->alarm_handle); db->alarm_handle = ALARM_HANDLE_INVALID; zdb_zone_label_destroy(&db->root); /* native order */ zdb_unlock(db, ZDB_MUTEX_WRITER); // zdb_destroy group_mutex_destroy(&db->mutex); } static void zdb_signature_check_one(const char* name, int should, int is) { if(is != should) { printf("critical: zdb: '%s' should be of size %i but is of size %i\n", name, is, should); fflush(stdout); abort(); } } void zdb_signature_check(int so_zdb, int so_zdb_zone, int so_zdb_zone_label, int so_zdb_rr_label, int so_mutex_t) { DNSCORE_API_CHECK(); zdb_signature_check_one("zdb", sizeof(zdb), so_zdb); zdb_signature_check_one("zdb_zone", sizeof(zdb_zone), so_zdb_zone); zdb_signature_check_one("zdb_zone_label", sizeof(zdb_zone_label), so_zdb_zone_label); zdb_signature_check_one("zdb_rr_label", sizeof(zdb_rr_label), so_zdb_rr_label); zdb_signature_check_one("mutex_t", sizeof(mutex_t), so_mutex_t); } #if DEBUG /** @brief DEBUG: Prints the content of the database. * * DEBUG: Prints the content of the database. * * @param[in] db the database to print * */ void zdb_print(zdb* db, output_stream *os) // mutex checked { osformatln(os, "zdb@%p\n", (void*)db); if(db != NULL) { zdb_lock(db, ZDB_MUTEX_READER); // for print db osformatln(os, "zdb@%p class=%{dnsclass}\n", (void*)db, &db->zclass); zdb_zone_label_print_indented(db->root, os, 1); /* native order */ zdb_unlock(db, ZDB_MUTEX_READER); // for print db } } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_cache.c0000644000000000000000000000013214505005531021032 xustar000000000000000030 mtime=1695812441.710971704 30 atime=1695812445.800030268 30 ctime=1695812495.107736453 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_cache.c0000664000374500037450000000445314505005531021002 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Internal functions for the database: zoned resource records label. * * Internal functions for the database: zoned resource records label. * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include "dnsdb/dictionary.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_error.h" /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_error.c0000644000000000000000000000013214505005531021120 xustar000000000000000030 mtime=1695812441.741972148 30 atime=1695812445.802030296 30 ctime=1695812495.109736482 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_error.c0000664000374500037450000001276014505005531021070 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup error Database error handling * @ingroup dnsdb * @brief Database error handling * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include "dnsdb/zdb_error.h" /* * */ static bool zdb_register_errors_done = FALSE; void zdb_register_errors() { if(zdb_register_errors_done) { return; } zdb_register_errors_done = TRUE; error_register(ZDB_ERROR_BASE, "An error occurred in the database."); error_register(ZDB_ERROR_KEY_NOTFOUND, "No match has been found for the current operation"); error_register(ZDB_ERROR_DELETEFROMEMPTY, "Delete from an empty collection."); error_register(ZDB_ERROR_NOSUCHCLASS, "There is no such class in the database."); error_register(ZDB_READER_WRONGNAMEFORZONE, "A name in the zone does not match the origin."); error_register(ZDB_READER_ZONENOTLOADED, "The zone has not been loaded."); error_register(ZDB_ERROR_NOSOAATAPEX, "ZDB_ERROR_NOSOAATAPEX"); error_register(ZDB_ERROR_COULDNOTOOBTAINZONEIMAGE, "ZDB_ERROR_COULDNOTOOBTAINZONEIMAGE"); error_register(ZDB_ERROR_CORRUPTEDSOA, "ZDB_ERROR_CORRUPTEDSOA"); error_register(ZDB_ERROR_ICMTL_NOTFOUND, "ZDB_ERROR_ICMTL_NOTFOUND"); error_register(ZDB_ERROR_ICMTL_STATUS_INVALID,"ZDB_ERROR_ICMTL_STATUS_INVALID"); error_register(ZDB_ERROR_ICMTL_FOLDERPATHTOOLONG,"ZDB_ERROR_ICMTL_FOLDERPATHTOOLONG"); error_register(ZDB_ERROR_ZONE_IS_NOT_SIGNED, "ZDB_ERROR_ZONE_IS_NOT_SIGNED"); error_register(ZDB_ERROR_ZONE_IS_ALREADY_BEING_SIGNED, "ZDB_ERROR_ZONE_IS_ALREADY_BEING_SIGNED"); error_register(ZDB_ERROR_ZONE_INVALID, "ZDB_ERROR_ZONE_INVALID"); error_register(ZDB_ERROR_ZONE_IS_NOT_DNSSEC, "ZDB_ERROR_ZONE_IS_NOT_DNSSEC"); error_register(ZDB_ERROR_ZONE_NO_ZSK_PRIVATE_KEY_FILE, "ZDB_ERROR_ZONE_NO_ZSK_PRIVATE_KEY_FILE"); error_register(ZDB_ERROR_ZONE_NO_ACTIVE_DNSKEY_FOUND, "ZDB_ERROR_ZONE_NO_ACTIVE_DNSKEY_FOUND"); error_register(ZDB_ERROR_ZONE_NOT_IN_DATABASE, "ZDB_ERROR_ZONE_NOT_IN_DATABASE"); error_register(ZDB_ERROR_ZONE_NOT_MAINTAINED,"ZDB_ERROR_ZONE_NOT_MAINTAINED"); error_register(ZDB_READER_FIRST_RECORD_NOT_SOA, "ZDB_READER_FIRST_RECORD_NOT_SOA"); error_register(ZDB_READER_ANOTHER_DOMAIN_WAS_EXPECTED, "ZDB_READER_ANOTHER_DOMAIN_WAS_EXPECTED"); error_register(ZDB_READER_NSEC3WITHOUTNSEC3PARAM, "ZDB_READER_NSEC3WITHOUTNSEC3PARAM"); error_register(ZDB_READER_MIXED_DNSSEC_VERSIONS, "ZDB_READER_MIXED_DNSSEC_VERSIONS"); error_register(ZDB_READER_ALREADY_LOADED, "ZDB_READER_ALREADY_LOADED"); error_register(ZDB_READER_NSEC3PARAMWITHOUTNSEC3, "ZDB_READER_NSEC3PARAMWITHOUTNSEC3"); error_register(ZDB_JOURNAL_WRONG_PARAMETERS, "ZDB_JOURNAL_WRONG_PARAMETERS"); error_register(ZDB_JOURNAL_READING_DID_NOT_FOUND_SOA, "ZDB_JOURNAL_READING_DID_NOT_FOUND_SOA"); error_register(ZDB_JOURNAL_SOA_RECORD_EXPECTED, "ZDB_JOURNAL_SOA_RECORD_EXPECTED"); error_register(ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE, "ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE"); error_register(ZDB_JOURNAL_FEATURE_NOT_SUPPORTED, "ZDB_JOURNAL_FEATURE_NOT_SUPPORTED"); error_register(ZDB_JOURNAL_NOT_INITIALISED, "ZDB_JOURNAL_NOT_INITIALISED"); error_register(ZDB_JOURNAL_IS_BUSY, "ZDB_JOURNAL_IS_BUSY"); error_register(ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY, "ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY"); error_register(ZDB_JOURNAL_LOOKS_CORRUPTED, "ZDB_JOURNAL_LOOKS_CORRUPTED"); error_register(ZDB_JOURNAL_UNEXPECTED_MAGIC, "ZDB_JOURNAL_UNEXPECTED_MAGIC"); error_register(ZDB_JOURNAL_SHORT_READ, "ZDB_JOURNAL_SHORT_READ"); error_register(ZDB_JOURNAL_SIZE_LIMIT_TOO_SMALL, "ZDB_JOURNAL_SIZE_LIMIT_TOO_SMALL"); } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_icmtl.c0000644000000000000000000000013214505005531021077 xustar000000000000000030 mtime=1695812441.728971962 30 atime=1695812445.801030282 30 ctime=1695812495.111736511 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_icmtl.c0000664000374500037450000011540114505005531021043 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnsdb * @brief * * ICMTL is actually INCREMENTAL. * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dnsdb/zdb_icmtl.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb-zone-journal.h" #include "dnsdb/nsec3.h" #include "dnsdb/nsec.h" #include "dnsdb/rrsig.h" #include "dnsdb/dnssec.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/nsec-chain-replay.h" #include "dnsdb/nsec3-chain-replay.h" #ifndef HAS_DYNUPDATE_DIFF_ENABLED #error "HAS_DYNUPDATE_DIFF_ENABLED not defined" #endif extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define ICMTL_DUMP_JOURNAL_RECORDS 0 #if ICMTL_DUMP_JOURNAL_RECORDS #pragma message("WARNING: ICMTL_DUMP_JOURNAL_RECORDS enabled !") #endif #define ZDB_ICMTL_REPLAY_GATHER 0 #define ZDB_ICMTL_REPLAY_COMMIT 1 #define ZDB_ICMTL_REPLAY_COMMIT_AND_STOP 3 #define ZDB_ICMTL_REPLAY_STOP 4 #define ZDB_ICMTL_REPLAY_SHUTDOWN_POLL_PERIOD 64 #define ZDB_ICMTL_REPLAY_BUFFER_SIZE 4096 static ya_result zdb_icmtl_replay_commit_label_forall_nsec3_del_cb(zdb_rr_label *rr_label, const u8 *rr_label_fqdn, void *data) { (void)rr_label; chain_replay *nsec3replayp = (chain_replay*)data; ya_result ret = nsec3replayp->vtbl->record_del(nsec3replayp, rr_label_fqdn, TYPE_NONE, NULL); return ret; } static ya_result zdb_icmtl_replay_commit_label_forall_nsec3_add_cb(zdb_rr_label *rr_label, const u8 *rr_label_fqdn, void *data) { (void)rr_label; chain_replay *nsec3replayp = (chain_replay*)data; ya_result ret = nsec3replayp->vtbl->record_add(nsec3replayp, rr_label_fqdn, TYPE_NONE, NULL); return ret; } static void zdb_icmtl_replay_remove_keep_flag(ptr_set *marked_labels, const u8 *origin) { ptr_set_iterator iter; ptr_set_iterator_init(marked_labels, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); if(node->value != (void*)(intptr)-1) { zdb_rr_label *rr_label = (zdb_rr_label*)node->value; zdb_rr_label_flag_and(rr_label, ~ZDB_RR_LABEL_KEEP); log_debug1("journal: %{dnsname}: un-keep @%p", origin, rr_label); } dnsname_zfree(node->key); } } void zdb_icmtl_replay_commit_state_init(zdb_icmtl_replay_commit_state *state) { state->dnskey_added = 0; state->dnskey_removed = 0; #if DNSCORE_HAS_EVENT_DYNAMIC_MODULE ptr_vector_init_empty(&state->dnskey_added_list); ptr_vector_init_empty(&state->dnskey_removed_list); #endif } void zdb_icmtl_replay_commit_state_finalize(zdb_icmtl_replay_commit_state *state) { #if DNSCORE_HAS_EVENT_DYNAMIC_MODULE ptr_vector_destroy(&state->dnskey_added_list); ptr_vector_destroy(&state->dnskey_removed_list); #else (void)state; #endif } ya_result zdb_icmtl_replay_commit_ex(zdb_zone *zone, input_stream *is, zdb_icmtl_replay_commit_state *out_state) { ya_result ret; /* * 0: DELETE, 1: ADD * The mode is switched every time an SOA is found. */ yassert(zdb_zone_islocked(zone) && (out_state != NULL)); yassert(bytearray_input_stream_is_instance_of(is)); #if ZDB_HAS_NSEC3_SUPPORT bool has_nsec3 = zdb_zone_is_nsec3(zone); #endif #if ZDB_HAS_NSEC_SUPPORT bool has_nsec = zdb_zone_is_nsec(zone); #endif #if ZDB_HAS_NSEC3_SUPPORT && ZDB_HAS_NSEC_SUPPORT if(has_nsec3 && has_nsec) { log_err("journal: %{dnsname}: zone has both NSEC and NSEC3 status, which is not supported by YADIFA", zone->origin); return ERROR; /// @note this is not entirely true anymore } #endif u8 mode = 1; // the first SOA will switch the mode to delete s32 changes = 0; zdb_ttlrdata ttlrdata; dns_resource_record rr; dns_resource_record_init(&rr); const u8 *fqdn = rr.name; dnslabel_vector labels; ttlrdata.next = NULL; /* * The plan for NSEC3 : * Store the fqdn + type class ttl rdata in collections * => the delete collection * => the add collection * Then there is the NSEC3 covered labels: keep a reference to them for later * * When a pass of SOA-/SOA+ has finished: * _ replace the NSEC3 in both collections (reading from delete) * _ delete NSEC3 to delete * _ add NSEC3 to add * * _ and finally update the NSEC3 for the labels kept above */ #if ZDB_HAS_NSEC3_SUPPORT chain_replay nsec3replay; nsec3_chain_replay_init(&nsec3replay, zone); #endif #if ZDB_HAS_NSEC_SUPPORT chain_replay nsecreplay; nsec_chain_replay_init(&nsecreplay, zone); #endif zdb_icmtl_replay_commit_state_init(out_state); /* * At this point : the next record, if it exists AND is not an SOA , has to be deleted * */ // mark the labels to keep no matter what u32 is_offset = bytearray_input_stream_offset(is); ptr_set marked_labels = PTR_SET_DNSNAME_EMPTY; for(;;) { /* * read the full record * * == 0 : no record (EOF) * < 0 : failed */ if((ret = dns_resource_record_read(&rr, is)) <= 0) { if(ISOK(ret)) { log_debug("journal: %{dnsname}: reached the end of the journal page", zone->origin); } else { log_err("journal: %{dnsname}: broken journal: %r", zone->origin, ret); logger_flush(); // broken journal (bad, keep me) } break; } if(rr.tctr.qtype == TYPE_SOA) { mode ^= 1; continue; } if(mode != 0) { // add // grab the fqdn // find the label, if it exists mark it and keep the mark if(rr.tctr.qtype != TYPE_NSEC3) { if((rr.tctr.qtype != TYPE_RRSIG) || ((rr.tctr.qtype == TYPE_RRSIG) && (rrsig_get_type_covered_from_rdata(rr.rdata, rr.rdata_size) != TYPE_NSEC3))) { ptr_node *node = ptr_set_insert(&marked_labels, rr.name); if(node->value == NULL) { s32 top = dnsname_to_dnslabel_vector(rr.name, labels); zdb_rr_label *rr_label = zdb_rr_label_find_exact(zone->apex, labels, (top - zone->origin_vector.size) - 1); if(rr_label != NULL) { #if DEBUG log_debug1("journal: %{dnsname}: keep %{dnsname} (@%p)", zone->origin, fqdn, rr_label); #endif node->value = rr_label; zdb_rr_label_flag_or(rr_label, ZDB_RR_LABEL_KEEP); } else { #if DEBUG log_debug1("journal: %{dnsname}: no-keep %{dnsname} because it's new", zone->origin, fqdn); #endif node->value = (void*)(intptr)-1; } node->key = dnsname_zdup(rr.name); } } #if DEBUG else { log_debug1("journal: %{dnsname}: cannot-keep %{dnsname} RRSIG on NSEC3", zone->origin, fqdn); } #endif } #if DEBUG else { log_debug1("journal: %{dnsname}: cannot-keep %{dnsname} NSEC3", zone->origin, fqdn); } #endif } else { // del // ignore } } // relevant labels have been marked bytearray_input_stream_set_offset(is, is_offset); bool did_remove_soa = FALSE; mode = 1; // something has to be committed for(;;) { /* * read the full record * * == 0 : no record (EOF) * < 0 : failed */ if(dns_resource_record_read(&rr, is) <= 0) { log_debug("journal: %{dnsname}: reached the end of the journal page", zone->origin); break; } ttlrdata.ttl = ntohl(rr.tctr.ttl); ttlrdata.rdata_pointer = rr.rdata; ttlrdata.rdata_size = rr.rdata_size; /* * Stop at the SOA */ if(rr.tctr.qtype == TYPE_SOA) { mode ^= 1; } if(!did_remove_soa) { #if DEBUG log_debug("journal: %{dnsname}: removing obsolete SOA", zone->origin); #endif if(FAIL(ret = zdb_record_delete(&zone->apex->resource_record_set, TYPE_SOA))) { /** * complain */ log_err("journal: %{dnsname}: removing current SOA gave an error: %r", zone->origin, ret); /* That's VERY bad ... */ changes = ret; break; } did_remove_soa = TRUE; } s32 top = dnsname_to_dnslabel_vector(fqdn, labels); if(mode == 0) { /* * "TO DEL" record */ #if ICMTL_DUMP_JOURNAL_RECORDS rdata_desc type_len_rdata = {rr.tctr.qtype, rr.rdata_size, rr.rdata }; log_debug("journal: del %{dnsname} %{typerdatadesc}", fqdn, &type_len_rdata); logger_flush(); #endif bool handled_by_chain = FALSE; #if ZDB_HAS_NSEC3_SUPPORT // 0 : proceed // 1 : ignore // ? : error handled_by_chain = (nsec3replay.vtbl->record_del(&nsec3replay, fqdn, rr.tctr.qtype, &ttlrdata) != 0); #if DEBUG log_debug3("journal: %{dnsname}: DEL: %{dnsname} %{dntype} handled_by_chain=%i", zone->origin, fqdn, &rr.tctr.qtype, handled_by_chain); #endif if(handled_by_chain) { ++changes; } else { if(top > zone->origin_vector.size) { const u8 *above_fqdn = fqdn; for(int i = 1; i < top - zone->origin_vector.size; ++i) { zdb_rr_label *above = zdb_rr_label_find_exact(zone->apex, &labels[i], top - zone->origin_vector.size - 1 - i); if(above != NULL) { if(btree_notempty(above->resource_record_set)) { break; } } above_fqdn += above_fqdn[0] + 1; nsec3replay.vtbl->record_del(&nsec3replay, above_fqdn, TYPE_NONE, NULL); } zdb_rr_label *rr_label = zdb_rr_label_find_exact(zone->apex, labels, (top - zone->origin_vector.size) - 1); if(rr_label != NULL) { zdb_rr_label_forall_children_of_fqdn(rr_label, fqdn, zdb_icmtl_replay_commit_label_forall_nsec3_del_cb, &nsec3replay); } } } #endif #if ZDB_HAS_NSEC_SUPPORT // 0 : proceed // 1 : ignore // ? : error if(!handled_by_chain && (handled_by_chain = nsecreplay.vtbl->record_del(&nsecreplay, fqdn, rr.tctr.qtype, &ttlrdata) != 0)) { ++changes; } //else #endif if(!handled_by_chain) { switch(rr.tctr.qtype) { case TYPE_SOA: { rdata_desc rdata = {TYPE_SOA, ttlrdata.rdata_size, ttlrdata.rdata_pointer}; log_debug("journal: %{dnsname}: SOA: del %{dnsname} %{typerdatadesc}", zone->origin, fqdn, &rdata); s32 m1 = (top - zone->origin_vector.size) - 1; if(m1 == -1) { if(FAIL(ret = zdb_record_delete_exact(&zone->apex->resource_record_set, TYPE_SOA, &ttlrdata))) /* FB done, APEX : no delegation, source is the journal */ { if(!did_remove_soa) { log_err("journal: %{dnsname}: SOA: %r", zone->origin, ret); } } } else { if(FAIL(ret = zdb_rr_label_delete_record_exact(zone, labels, (top - zone->origin_vector.size) - 1, rr.tctr.qtype, &ttlrdata))) // source is journal { if(!did_remove_soa) { log_err("journal: %{dnsname}: SOA: (2) %r", zone->origin, ret); } } } break; } case TYPE_NSEC3: { break; } case TYPE_DNSKEY: { ++out_state->dnskey_removed; dnssec_key *key = NULL; // add the public key to the keystore ya_result ret = dnskey_new_from_rdata(rr.rdata, rr.rdata_size, zone->origin, &key); if(ISOK(ret)) { /* #if HAS_EVENT_DYNAMIC_MODULE if(dynamic_module_dnskey_interface_chain_available()) { dynamic_module_on_dnskey_publish(key); } #endif */ dnskey_state_disable(key, DNSKEY_KEY_IS_IN_ZONE); if(dnssec_keystore_remove_key(key)) { #if DEBUG log_debug("journal: %{dnsname}: deleted key from record: K%{dnsname}+%03d+%05d/%d P=%T A=%T I=%T D=%T", zone->origin, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key) ); #endif } else { #if DEBUG log_debug("journal: %{dnsname}: deleted key from record: K%{dnsname}+%03d+%05d/%d P=%T A=%T I=%T D=%T (not in keyring)", zone->origin, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key) ); #endif dnskey_release(key); } } else { // could not generate key log_err("journal: %{dnsname}: could not make key from DNSKEY record: %r", zone->origin, ret); } } FALLTHROUGH //fallthrough default: { if(FAIL(ret = zdb_rr_label_delete_record_exact(zone, labels, (top - zone->origin_vector.size) - 1, rr.tctr.qtype, &ttlrdata))) // source is journal { // signatures can be removed automatically by maintenance if((rr.tctr.qtype != TYPE_RRSIG) && (ret != ZDB_ERROR_KEY_NOTFOUND)) { log_err("journal: %{dnsname}: del %{dnsrr}", zone->origin, &rr); log_err("journal: %{dnsname}: %{dnstype}: %r", zone->origin, &rr.tctr.qtype, ret); } else { log_debug("journal: %{dnsname}: del %{dnsrr}", zone->origin, &rr); log_debug("journal: %{dnsname}: %{dnstype}: %r", zone->origin, &rr.tctr.qtype, ret); } } } } } } else { /* * "TO ADD" record */ bool handled_by_chain = FALSE; #if DNSCORE_HAS_DNSSEC_SUPPORT if(rr.tctr.qtype == TYPE_RRSIG) { // get expiration, update resignature alarm if needed s32 rrsig_expiration = rrsig_get_valid_until_from_rdata(rr.rdata, rr.rdata_size); if(zone->progressive_signature_update.earliest_signature_expiration > rrsig_expiration) { zone->progressive_signature_update.earliest_signature_expiration = rrsig_expiration; } } #endif #if ZDB_HAS_NSEC3_SUPPORT // returns the number of changes taken into account (0 or 1) // 0 : proceed // 1 : ignore // ? : error handled_by_chain = (nsec3replay.vtbl->record_add(&nsec3replay, fqdn, rr.tctr.qtype, &ttlrdata) != 0); #if DEBUG log_debug3("journal: %{dnsname}: ADD: %{dnsname} %{dnstype} handled_by_chain=%i", zone->origin, fqdn, &rr.tctr.qtype, handled_by_chain); #endif if(handled_by_chain) { ++changes; } else { if( (top > zone->origin_vector.size) && (rr.tctr.qtype != TYPE_NSEC3) && ( (rr.tctr.qtype != TYPE_RRSIG) || ((rr.tctr.qtype == TYPE_RRSIG) && (GET_U16_AT_P(ZDB_RECORD_PTR_RDATAPTR(&ttlrdata)) != TYPE_NSEC3)) ) ) { const u8 *above_fqdn = fqdn; for(int i = 1; i < top - zone->origin_vector.size; ++i) { zdb_rr_label *above = zdb_rr_label_find_exact(zone->apex, &labels[i], top - zone->origin_vector.size - 1 - i); if(above != NULL) { if(btree_notempty(above->resource_record_set)) { break; } } above_fqdn += above_fqdn[0] + 1; nsec3replay.vtbl->record_add(&nsec3replay, above_fqdn, TYPE_NONE, NULL); } zdb_rr_label *rr_label = zdb_rr_label_find_exact(zone->apex, labels, (top - zone->origin_vector.size) - 1); if(rr_label != NULL) { zdb_rr_label_forall_children_of_fqdn(rr_label, fqdn, zdb_icmtl_replay_commit_label_forall_nsec3_add_cb, &nsec3replay); } } } #endif #if ZDB_HAS_NSEC_SUPPORT // returns the number of changes taken into account (0 or 1) // 0 : proceed // 1 : ignore // ? : error if(!handled_by_chain && (handled_by_chain = (nsecreplay.vtbl->record_add(&nsecreplay, fqdn, rr.tctr.qtype, &ttlrdata) != 0))) { ++changes; } //else #endif if(!handled_by_chain) { switch(rr.tctr.qtype) { #if ZDB_HAS_NSEC3_SUPPORT case TYPE_NSEC3CHAINSTATE: { // create chain if missing ... nsec3_zone_add_from_rdata(zone, rr.rdata_size, rr.rdata); // add the record zdb_packed_ttlrdata *packed_ttlrdata; ZDB_RECORD_ZALLOC_EMPTY(packed_ttlrdata, ttlrdata.ttl, rr.rdata_size); packed_ttlrdata->next = NULL; MEMCOPY(ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata), rr.rdata, rr.rdata_size); zdb_zone_record_add(zone, labels, top, rr.tctr.qtype, packed_ttlrdata); // class is implicit, flow verified break; } #endif // ZDB_HAS_NSEC3_SUPPORT case TYPE_DNSKEY: { ++out_state->dnskey_added; dnssec_key *key = NULL; // add the public key to the keystore ya_result ret = dnskey_new_from_rdata(rr.rdata, rr.rdata_size, zone->origin, &key); if(ISOK(ret)) { if(dnssec_keystore_add_key(key)) { #if DEBUG log_debug("journal: %{dnsname}: added key from record: K%{dnsname}+%03d+%05d/%d P=%T A=%T I=%T D=%T", zone->origin, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key) ); #endif dnskey_state_enable(key, DNSKEY_KEY_IS_IN_ZONE); } else { #if DEBUG log_debug("journal: %{dnsname}: added key from record: K%{dnsname}+%03d+%05d/%d P=%T A=%T I=%T D=%T (in keyring already)", zone->origin, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key) ); #endif dnskey_release(key); } } else { // could not generate key log_err("journal: %{dnsname}: could not make key from DNSKEY record: %r", zone->origin, ret); } } FALLTHROUGH // fall through default: { zdb_packed_ttlrdata *packed_ttlrdata; ZDB_RECORD_ZALLOC_EMPTY(packed_ttlrdata, ttlrdata.ttl, rr.rdata_size); packed_ttlrdata->next = NULL; MEMCOPY(ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata), rr.rdata, rr.rdata_size); #if ICMTL_DUMP_JOURNAL_RECORDS rdata_desc type_len_rdata = {rr.tctr.qtype, rr.rdata_size, ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata) }; log_debug("journal: add %{dnsname} %{typerdatadesc}", fqdn, &type_len_rdata); logger_flush(); #endif if(rr.tctr.qtype == TYPE_SOA) { rr_soa_get_serial(ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata), ZDB_PACKEDRECORD_PTR_RDATASIZE(packed_ttlrdata), &out_state->end_serial); rdata_desc rdata = {TYPE_SOA, ZDB_PACKEDRECORD_PTR_RDATASIZE(packed_ttlrdata), ZDB_PACKEDRECORD_PTR_RDATAPTR(packed_ttlrdata)}; log_debug("journal: %{dnsname}: SOA: add %{dnsname} %{typerdatadesc}", zone->origin, fqdn, &rdata); } zdb_zone_record_add(zone, labels, top, rr.tctr.qtype, packed_ttlrdata); // class is implicit, flow verified } } } } // end if ADD changes++; } /* * Yes, I know. If 2^32 changes (add batch + del batch) occurs then it will be seen as an error ... */ if(ISOK(changes)) { #if ZDB_HAS_NSEC3_SUPPORT && ZDB_HAS_NSEC_SUPPORT if(has_nsec3 && has_nsec) { log_warn("journal: %{dnsname}: both NSEC3 and NSEC operations happened, which is not supported by YADIFA. Keeping the original one.", zone->origin); has_nsec3 = zdb_zone_is_nsec3(zone); has_nsec = zdb_zone_is_nsec(zone); log_debug("journal: %{dnsname}: has NSEC3: %i, has NSEC: %i", zone->origin, has_nsec3, has_nsec); } #endif #if ZDB_HAS_NSEC3_SUPPORT nsec3replay.vtbl->execute(&nsec3replay); #endif #if ZDB_HAS_NSEC_SUPPORT nsecreplay.vtbl->execute(&nsecreplay); #endif zdb_zone_set_status(zone, ZDB_ZONE_STATUS_MODIFIED); } #if ZDB_HAS_NSEC3_SUPPORT // has_nsec3 = zdb_zone_is_nsec3(zone); nsec3replay.vtbl->finalise(&nsec3replay); #endif #if ZDB_HAS_NSEC_SUPPORT // has_nsec = zdb_zone_is_nsec(zone); nsecreplay.vtbl->finalise(&nsecreplay); #endif zdb_icmtl_replay_remove_keep_flag(&marked_labels, zone->origin); ptr_set_destroy(&marked_labels); dns_resource_record_clear(&rr); return changes; } ya_result zdb_icmtl_replay_commit(zdb_zone *zone, input_stream *is, u32 *out_serial_after_replayp) { ya_result ret; zdb_icmtl_replay_commit_state state; ret = zdb_icmtl_replay_commit_ex(zone, is, &state); if(ISOK(ret) && (out_serial_after_replayp != NULL)) { *out_serial_after_replayp = state.end_serial; } zdb_icmtl_replay_commit_state_finalize(&state); return ret; } /* * Replay the incremental stream */ ya_result zdb_icmtl_replay(zdb_zone *zone) { ya_result return_value; u32 serial; zdb_zone_double_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); return_value = zdb_zone_getserial(zone, &serial); // zone is locked if(FAIL(return_value)) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_err("journal: %{dnsname}: error reading serial for zone: %r", zone->origin, return_value); return return_value; } input_stream is; #if ICMTL_DUMP_JOURNAL_RECORDS log_debug("journal: zdb_icmtl_replay(%{dnsname})", zone->origin); logger_flush(); #endif u32 first_serial; u32 last_serial; if(FAIL(return_value = zdb_zone_journal_get_serial_range(zone, &first_serial, &last_serial))) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); if(return_value == ZDB_ERROR_ICMTL_NOTFOUND) { return_value = SUCCESS; } else { log_err("journal: %{dnsname}: error opening journal for zone: %r", zone->origin, return_value); } return return_value; } log_debug("journal: %{dnsname}: zone serial is %i, journal covers serials from %i to %i", zone->origin, serial, first_serial, last_serial); if(last_serial == serial) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_debug("journal: %{dnsname}: nothing to read from the journal", zone->origin); return 0; } if(serial_lt(serial, first_serial)) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_warn("journal: %{dnsname}: first serial from the journal is after the zone (deleting journal)", zone->origin); // should invalidate the journal zdb_zone_journal_delete(zone); return 0; } if(serial_gt(serial, last_serial)) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_warn("journal: %{dnsname}: last serial from the journal is before the zone (deleting journal)", zone->origin); // should invalidate the journal zdb_zone_journal_delete(zone); return 0; } if(FAIL(return_value = zdb_zone_journal_get_ixfr_stream_at_serial(zone, serial, &is, NULL))) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_err("journal: %{dnsname}: error reading journal from serial %d: %r",zone->origin, serial, return_value); return return_value; } log_debug("journal: %{dnsname}: replaying from serial %u",zone->origin, serial); buffer_input_stream_init(&is, &is, ZDB_ICMTL_REPLAY_BUFFER_SIZE); u16 shutdown_test_countdown = ZDB_ICMTL_REPLAY_SHUTDOWN_POLL_PERIOD; u32 current_serial = serial; /* * Read all records from [ SOA ... SOA ... [ SOA in memory */ output_stream baos; input_stream bais; dns_resource_record rr; int baos_rr_count = 0; int baos_soa_count = 0; bool was_nsec3 = zdb_zone_is_nsec3(zone); bytearray_output_stream_init_ex(&baos, NULL, ZDB_ICMTL_REPLAY_BUFFER_SIZE, BYTEARRAY_DYNAMIC); dns_resource_record_init(&rr); // 0: gather, 1: commit, 2: commit & stop static int test_count = 0; for(int replay_state = ZDB_ICMTL_REPLAY_GATHER; replay_state != ZDB_ICMTL_REPLAY_COMMIT_AND_STOP;) { // ensure it's not supposed to shutdown (every few iterations) if(--shutdown_test_countdown <= 0) { if(dnscore_shuttingdown()) { return_value = STOPPED_BY_APPLICATION_SHUTDOWN; break; } shutdown_test_countdown = ZDB_ICMTL_REPLAY_SHUTDOWN_POLL_PERIOD; } // read the next record ++test_count; if((return_value = dns_resource_record_read(&rr, &is)) <= 0) { if(ISOK(return_value)) { log_debug("journal: %{dnsname}: reached the end of the journal file", zone->origin); replay_state = ZDB_ICMTL_REPLAY_COMMIT_AND_STOP; } else { log_err("journal: broken journal: %r", return_value); logger_flush(); // broken journal (flush is slow, but this is bad, so : keep it) // replay_state = ZDB_ICMTL_REPLAY_STOP; // never read break; } } else // first record must be an SOA (or it's wrong) if(baos_rr_count == 0) // first record ? { if(rr.tctr.qtype != TYPE_SOA) // must be SOA { // expected an SOA return_value = ZDB_JOURNAL_SOA_RECORD_EXPECTED; break; } ++baos_soa_count; // 0 -> 1 // this is not mandatory but clearer to read } else // the page ends with an SOA or end of stream if(rr.tctr.qtype == TYPE_SOA) { if(baos_soa_count == 2) { // this record is the start of the next stream, keep it for the next iteration replay_state = ZDB_ICMTL_REPLAY_COMMIT; } ++baos_soa_count; } ++baos_rr_count; if((replay_state & ZDB_ICMTL_REPLAY_COMMIT) != 0) { log_debug("journal: %{dnsname}: applying changes", zone->origin); u64 ts_start = timeus(); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); bytearray_input_stream_init_const(&bais, bytearray_output_stream_buffer(&baos), bytearray_output_stream_size(&baos)); return_value = zdb_icmtl_replay_commit(zone, &bais, ¤t_serial); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_LOAD, ZDB_ZONE_MUTEX_SIMPLEREADER); input_stream_close(&bais); u64 ts_stop = timeus(); if(ts_stop < ts_start) // time change { ts_stop = ts_start; } u64 ts_delta = ts_stop - ts_start; if(ISOK(return_value)) { if(ts_delta < 1000) { log_debug("journal: %{dnsname}: applied changes (%lluus)", zone->origin, ts_delta); } else if(ts_delta < ONE_SECOND_US) { double ts_delta_s = ts_delta; ts_delta_s /= 1000.0; log_debug("journal: %{dnsname}: applied changes (%5.2fms)", zone->origin, ts_delta_s); } else { double ts_delta_s = ts_delta; ts_delta_s /= 1000000.0; log_debug("journal: %{dnsname}: applied changes (%5.2fs)", zone->origin, ts_delta_s); } } else { log_err("journal: %{dnsname}: failed to committed changes", zone->origin); break; } // the current page has been processed if(replay_state == ZDB_ICMTL_REPLAY_COMMIT_AND_STOP) { // no more page to read break; } // reset the state for the next page // note: the next written record will be the last read SOA baos_rr_count = 1; baos_soa_count = 1; replay_state = ZDB_ICMTL_REPLAY_GATHER; bytearray_output_stream_reset(&baos); } // end if replay_state is ZDB_ICMTL_REPLAY_COMMIT (mask) dns_resource_record_write(&rr, &baos); } input_stream_close(&is); output_stream_close(&baos); dns_resource_record_clear(&rr); // cleanup destroyed nsec3 chains if(ISOK(return_value)) { bool is_nsec3 = zdb_zone_is_nsec3(zone); if(is_nsec3 && !was_nsec3) { // the chain has just been created, but is probably missing internal links log_debug("journal: %{dnsname}: zone switched to NSEC3 by reading the journal: updating links", zone->origin); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); nsec3_zone_update_chain0_links(zone); zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_LOAD, ZDB_ZONE_MUTEX_SIMPLEREADER); log_debug("journal: %{dnsname}: zone switched to NSEC3 by reading the journal: links updated", zone->origin); } if(FAIL(return_value = zdb_zone_getserial(zone, &serial))) // zone is locked { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); log_err("journal: %{dnsname}: error reading confirmation serial for zone: %r",zone->origin, return_value); return return_value; } if(serial != last_serial) { log_warn("journal: %{dnsname}: expected serial to be %i but it is %i instead",zone->origin, last_serial, serial); } } zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); if(ISOK(return_value)) { log_info("journal: %{dnsname}: replayed until serial %u", zone->origin, current_serial); return_value = last_serial - first_serial; zdb_zone_set_status(zone, ZDB_ZONE_STATUS_MODIFIED); } return return_value; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_query_ex.c0000644000000000000000000000013214505005531021630 xustar000000000000000030 mtime=1695812441.710971704 30 atime=1695812445.800030268 30 ctime=1695812495.113736539 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_query_ex.c0000664000374500037450000074711514505005531021611 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup query_ex Database top-level query function * @ingroup dnsdb * @brief Database top-level query function * * Database top-level query function * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #define DEBUG_LEVEL 0 #include #include #include #include #include #include #include "dnsdb/zdb.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/dictionary.h" #if ZDB_HAS_NSEC_SUPPORT #include "dnsdb/nsec.h" #endif #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif #if ZDB_HAS_DNSSEC_SUPPORT #include "dnsdb/rrsig.h" #endif #if ZDB_EXPLICIT_READER_ZONE_LOCK #define LOCK(a_) zdb_zone_lock((a_), ZDB_ZONE_MUTEX_SIMPLEREADER) #define UNLOCK(a_) zdb_zone_unlock((a_), ZDB_ZONE_MUTEX_SIMPLEREADER) #else #define LOCK(a_) #define UNLOCK(a_) #endif #define ENFORCE_MINTTL 1 // keep it that way /** * In order to optimise-out the class parameter that is not required if ZDB_RECORDS_MAX_CLASS == 1 ... */ #if ZDB_RECORDS_MAX_CLASS != 1 #define DECLARE_ZCLASS_PARAMETER u16 zclass, #define PASS_ZCLASS_PARAMETER zclass, #define PASS_ZONE_ZCLASS_PARAMETER zone->zclass, #else #define DECLARE_ZCLASS_PARAMETER #define PASS_ZCLASS_PARAMETER #define PASS_ZONE_ZCLASS_PARAMETER #endif extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define DEBUG_LOG_POOL_USAGE 0 #if DEBUG_LOG_POOL_USAGE static inline void log_pool_usage(message_data *mesg, u8 * restrict *pool) { u8 *pool_position = *((u8**)pool); log_debug("pool usage: %llu", pool_position - (u8*)message_get_pool_buffer(mesg)); } #else #define log_pool_usage(...) #endif process_flags_t zdb_query_process_flags = ~0; /** @brief Creates a answer node from a database record * * @param source a pointer to the ttlrdata to put into the node * @param name the owner of the record * @param zclass (if more than one class is supported in the database) * @param rtype the type of the record * @param pool the memory pool * * @return a resource record suitable for network serialisation * * 5 uses * */ static inline zdb_resourcerecord* zdb_query_ex_answer_make(const zdb_packed_ttlrdata* source, const u8* name, DECLARE_ZCLASS_PARAMETER u16 rtype, u8 * restrict * pool) { yassert(source != NULL && name != NULL); zdb_resourcerecord* node = (zdb_resourcerecord*) * pool; #if DEBUG memset(node, 0xff, ALIGN16(sizeof(zdb_resourcerecord))); #endif *pool += ALIGN16(sizeof(zdb_resourcerecord)); node->next = NULL; node->ttl_rdata = (zdb_packed_ttlrdata*)source; /** @note I should not need to clone the name * It comes either from the query, either from an rdata in the database. */ node->name = name; #if ZDB_RECORDS_MAX_CLASS != 1 node->zclass = zclass; #else node->zclass = CLASS_IN; #endif node->rtype = rtype; node->ttl = source->ttl; return node; } /** @brief Creates a answer node from a database record with a specific TTL * * @param source a pointer to the ttlrdata to put into the node * @param name the owner of the record * @param zclass (if more than one class is supported in the database) * @param rtype the type of the record * @param ttl the TTL that replaces the one in the record * @param pool the memory pool * * @return a resource record suitable for network serialisation * * 5 uses */ static inline zdb_resourcerecord* zdb_query_ex_answer_make_ttl(const zdb_packed_ttlrdata* source, const u8* name, DECLARE_ZCLASS_PARAMETER u16 rtype, u32 ttl, u8 * restrict * pool) { yassert(source != NULL && name != NULL); zdb_resourcerecord* node = (zdb_resourcerecord*) * pool; #if DEBUG memset(node, 0xff, ALIGN16(sizeof(zdb_resourcerecord))); #endif *pool += ALIGN16(sizeof(zdb_resourcerecord)); node->next = NULL; node->ttl_rdata = (zdb_packed_ttlrdata*)source; /** @note I should not need to clone the name * It comes either from the query, either from an rdata in the database. */ node->name = name; #if ZDB_RECORDS_MAX_CLASS != 1 node->zclass = zclass; #else node->zclass = CLASS_IN; #endif node->rtype = rtype; node->ttl = ttl; return node; } /** @brief Appends a list of database records to a list of nodes at a random position * * @param source a pointer to the ttlrdata to put into the node * @param name the owner of the record * @param zclass (if more than one class is supported in the database) * @param rtype the type of the record * @param headp a pointer to the section list * @param pool the memory pool * * 6 uses */ static void zdb_query_ex_answer_appendrndlist(const zdb_packed_ttlrdata* source, const u8* label, DECLARE_ZCLASS_PARAMETER u16 type, zdb_resourcerecord** headp, u8 * restrict * pool) { yassert(source != NULL && label != NULL); zdb_resourcerecord* head = zdb_query_ex_answer_make(source, label, PASS_ZCLASS_PARAMETER type, pool); head->next = *headp; source = source->next; if(source != NULL) { random_ctx rndctx = thread_pool_get_random_ctx(); int rnd = random_next(rndctx); do { zdb_resourcerecord* node = zdb_query_ex_answer_make(source, label, PASS_ZCLASS_PARAMETER type, pool); if(rnd & 1) { /* put the new node in front of the head, * and assign the head to node */ node->next = head; head = node; } else { /* put the new node next to the head */ node->next = head->next; head->next = node; } rnd >>= 1; /** * @note: After 32 entries it will not be so randomized at all ... */ source = source->next; } while(source != NULL); } *headp = head; } /** @brief Appends a list of database records to a list of nodes * * @param source a pointer to the ttlrdata to put into the node * @param name the owner of the record * @param zclass (if more than one class is supported in the database) * @param rtype the type of the record * @param headp a pointer to the section list * @param headp a pointer to the section list * @param pool the memory pool * * 10 uses */ static void zdb_query_ex_answer_appendlist(const zdb_packed_ttlrdata* source, const u8* label, DECLARE_ZCLASS_PARAMETER u16 rtype, zdb_resourcerecord** headp, u8 * restrict * pool) { yassert(source != NULL && label != NULL); zdb_resourcerecord* head = *headp; while(source != NULL) { zdb_resourcerecord* node = zdb_query_ex_answer_make(source, label, PASS_ZCLASS_PARAMETER rtype, pool); node->next = head; head = node; source = source->next; } *headp = head; } #if ZDB_HAS_DNSSEC_SUPPORT /** @brief Appends a list of database records to a list of nodes with a specific TTL * * @param source a pointer to the ttlrdata to put into the node * @param name the owner of the record * @param zclass (if more than one class is supported in the database) * @param rtype the type of the record * @param ttl the ttl of the record set * @param headp a pointer to the section list * @param pool the memory pool * * 12 uses, NSEC3 only */ static void zdb_query_ex_answer_appendlist_ttl(const zdb_packed_ttlrdata* source, const u8* label, DECLARE_ZCLASS_PARAMETER u16 rtype, u32 ttl, zdb_resourcerecord** headp, u8 * restrict * pool) { yassert(source != NULL && label != NULL); zdb_resourcerecord* next = *headp; int countdown = 32; while(source != NULL) { zdb_resourcerecord* node = zdb_query_ex_answer_make_ttl(source, label, PASS_ZCLASS_PARAMETER rtype, ttl, pool); node->next = next; next = node; source = source->next; if(--countdown == 0) { break; } } *headp = next; } #endif /** @brief Appends a list of database records to a list of nodes * * At the end * * @param source a pointer to the ttlrdata to put into the node * @param name the owner of the record * @param zclass (if more than one class is supported in the database) * @param rtype the type of the record * @param headp a pointer to the section list * @param pool the memory pool * * 5 uses */ static void zdb_query_ex_answer_append(const zdb_packed_ttlrdata* source, const u8* label, DECLARE_ZCLASS_PARAMETER u16 type, zdb_resourcerecord** headp, u8 * restrict * pool) { yassert(source != NULL); yassert(label != NULL); zdb_resourcerecord* next = *headp; zdb_resourcerecord* head = zdb_query_ex_answer_make(source, label, PASS_ZCLASS_PARAMETER type, pool); if(next != NULL) { while(next->next != NULL) { next = next->next; } next->next = head; } else { *headp = head; } } /** @brief Appends a list of database records to a list of nodes with a specific TTL * * At the end * * @param source a pointer to the ttlrdata to put into the node * @param name the owner of the record * @param zclass (if more than one class is supported in the database) * @param rtype the type of the record * @param ttl the ttl of the record * @param headp a pointer to the section list * @param pool the memory pool * * 16 uses */ static void zdb_query_ex_answer_append_ttl(const zdb_packed_ttlrdata* source, const u8* label, DECLARE_ZCLASS_PARAMETER u16 rtype, u32 ttl, zdb_resourcerecord** headp, u8 * restrict * pool) { yassert(source != NULL); yassert(label != NULL); zdb_resourcerecord* next = *headp; zdb_resourcerecord* head = zdb_query_ex_answer_make_ttl(source, label, PASS_ZCLASS_PARAMETER rtype, ttl, pool); if(next != NULL) { while(next->next != NULL) /* look for the last node */ { next = next->next; } next->next = head; /* set the value */ } else { *headp = head; /* set the head */ } } /** @brief Appends an RRSIG record set to a list of nodes with a specific TTL * * At the end * * @param source a pointer to the ttlrdata to put into the node * @param name the owner of the record * @param zclass (if more than one class is supported in the database) * @param ttl the ttl of the record * @param headp a pointer to the section list * @param pool the memory pool * * @return a resource record suitable for network serialisation * * 2 uses */ static inline void zdb_query_ex_answer_append_rrsig(const zdb_packed_ttlrdata *source, const u8 *label, DECLARE_ZCLASS_PARAMETER u32 ttl, zdb_resourcerecord **headp, u8 * restrict * pool) { zdb_query_ex_answer_append_ttl(source, label, PASS_ZCLASS_PARAMETER TYPE_RRSIG, ttl, headp, pool); } #if ZDB_HAS_DNSSEC_SUPPORT /** @brief Appends the RRSIG rrset that covers the given type * * At the end * * @param label the database label that owns the rrset * @param label_fqdn the owner of the records * @param zclass (if more than one class is supported in the database) * @param ttl the ttl of the record * @param headp a pointer to the section list * @param pool the memory pool * * 20 uses */ static void zdb_query_ex_answer_append_type_rrsigs(const zdb_rr_label *label, const u8 *label_fqdn, u16 rtype, DECLARE_ZCLASS_PARAMETER u32 ttl, zdb_resourcerecord **headp, u8 * restrict * pool) { const zdb_packed_ttlrdata *type_rrsig = rrsig_find_first(label, rtype); // zone is locked while(type_rrsig != NULL) { zdb_query_ex_answer_append_rrsig(type_rrsig, label_fqdn, PASS_ZCLASS_PARAMETER ttl, headp, pool); type_rrsig = rrsig_find_next(type_rrsig, rtype); } } /** @brief Appends the RRSIG rrset that covers the given type * * At the end * * @param rrsig_list an RRSIG rrset to take the signatures from * @param label_fqdn the owner of the records * @param zclass (if more than one class is supported in the database) * @param ttl the ttl of the record * @param headp a pointer to the section list * @param pool the memory pool * * 2 uses */ static void zdb_query_ex_answer_append_type_rrsigs_from(const zdb_packed_ttlrdata *rrsig_list, const u8 *label_fqdn, u16 rtype, DECLARE_ZCLASS_PARAMETER u32 ttl, zdb_resourcerecord **headp, u8 * restrict * pool) { const zdb_packed_ttlrdata *rrsig = rrsig_list; do { if(RRSIG_TYPE_COVERED(rrsig) == rtype) { zdb_query_ex_answer_append_rrsig(rrsig, label_fqdn, PASS_ZCLASS_PARAMETER ttl, headp, pool); } rrsig = rrsig->next; } while(rrsig != NULL); } #if ZDB_HAS_NSEC_SUPPORT /** @brief Appends the NSEC interval for the given name * * At the end * * @param zone the zone * @param name the name path * @param dups the label that cannot be added (used for wildcards) * @param headp a pointer to the section list * @param pool the memory pool * * 3 uses */ static void zdb_query_ex_add_nsec_interval(const zdb_zone *zone, const dnsname_vector* name, zdb_rr_label* dups, zdb_resourcerecord** headp, u8 * restrict * pool) { zdb_rr_label *nsec_interval_label; u8* nsec_dnsname = NULL; s32 min_ttl; if(zone->nsec.nsec == NULL) { return; } zdb_zone_getminttl(zone, &min_ttl); nsec_interval_label = nsec_find_interval(zone, name, &nsec_dnsname, pool); yassert(nsec_interval_label != NULL); if(/*(nsec_interval_label != NULL) && */(nsec_interval_label != dups)) { zdb_packed_ttlrdata *nsec_interval_label_nsec = zdb_record_find(&nsec_interval_label->resource_record_set, TYPE_NSEC); if(nsec_interval_label_nsec != NULL) { zdb_packed_ttlrdata *nsec_interval_label_nsec_rrsig = rrsig_find_first(nsec_interval_label, TYPE_NSEC); // zone is locked if(nsec_interval_label_nsec_rrsig != NULL) { zdb_query_ex_answer_append_ttl(nsec_interval_label_nsec, nsec_dnsname, PASS_ZONE_ZCLASS_PARAMETER TYPE_NSEC, min_ttl, headp, pool); do { zdb_query_ex_answer_append_ttl(nsec_interval_label_nsec_rrsig, nsec_dnsname, PASS_ZONE_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, headp, pool); nsec_interval_label_nsec_rrsig = rrsig_find_next(nsec_interval_label_nsec_rrsig, TYPE_NSEC); } while(nsec_interval_label_nsec_rrsig != NULL); } } } } #endif // ZDB_HAS_NSEC_SUPPORT #endif // ZDB_HAS_DNSSEC_SUPPORT /** @brief Appends the SOA negative ttl record * * At the end * * @param zone the zone * @param headp a pointer to the section list * @param pool the memory pool * * 3 uses */ static void zdb_query_ex_answer_append_soa(const zdb_zone *zone, zdb_resourcerecord **headp,u8 * restrict * pool) { yassert(zone != NULL); const u8* label_fqdn = zone->origin; #if ZDB_RECORDS_MAX_CLASS != 1 u16 zclass = zone->zclass; #endif zdb_rr_collection* apex_records = &zone->apex->resource_record_set; zdb_packed_ttlrdata* zone_soa = zdb_record_find(apex_records, TYPE_SOA); if(zone_soa != NULL) { zdb_resourcerecord* next = *headp; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_resourcerecord* node = zdb_query_ex_answer_make(zone_soa, label_fqdn, PASS_ZCLASS_PARAMETER TYPE_SOA, pool); if(next != NULL) { while(next->next != NULL) { next = next->next; } next->next = node; } else { *headp = node; } } } /** @brief Appends the SOA negative ttl record and its signature * * At the end * * @param zone the zone * @param headp a pointer to the section list * @param pool the memory pool * * @returns the negative ttl (minimum TTL is obsolete) * * 3 uses */ static void zdb_query_ex_answer_append_soa_rrsig(const zdb_zone *zone, zdb_resourcerecord **headp, u8 * restrict * pool) { yassert(zone != NULL); const u8 *label_fqdn = zone->origin; #if ZDB_RECORDS_MAX_CLASS != 1 u16 zclass = zone->zclass; #endif zdb_rr_collection *apex_records = &zone->apex->resource_record_set; zdb_packed_ttlrdata *zone_soa = zdb_record_find(apex_records, TYPE_SOA); if(zone_soa != NULL) { zdb_resourcerecord* next = *headp; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_resourcerecord* node = zdb_query_ex_answer_make(zone_soa, label_fqdn, PASS_ZCLASS_PARAMETER TYPE_SOA, pool); if(next != NULL) { while(next->next != NULL) { next = next->next; } next->next = node; } else { *headp = node; } #if ZDB_HAS_DNSSEC_SUPPORT #if ENFORCE_MINTTL zdb_query_ex_answer_append_type_rrsigs(zone->apex, label_fqdn, TYPE_SOA, PASS_ZCLASS_PARAMETER min_ttl, headp, pool); #else zdb_query_ex_answer_append_type_rrsigs(zone->apex, label_fqdn, TYPE_SOA, PASS_ZCLASS_PARAMETER zone_soa->ttl, headp, pool); #endif #endif } } /** @brief Appends the SOA negative ttl record * * At the end * * @param zone the zone * @param headp a pointer to the section list * @param pool the memory pool * * 3 uses */ static void zdb_query_ex_answer_append_soa_nttl(const zdb_zone *zone, zdb_resourcerecord **headp,u8 * restrict * pool) { yassert(zone != NULL); const u8* label_fqdn = zone->origin; #if ZDB_RECORDS_MAX_CLASS != 1 u16 zclass = zone->zclass; #endif zdb_rr_collection* apex_records = &zone->apex->resource_record_set; zdb_packed_ttlrdata* zone_soa = zdb_record_find(apex_records, TYPE_SOA); if(zone_soa != NULL) { zdb_resourcerecord* next = *headp; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); #if ENFORCE_MINTTL zdb_resourcerecord* node = zdb_query_ex_answer_make_ttl(zone_soa, label_fqdn, PASS_ZCLASS_PARAMETER TYPE_SOA, min_ttl, pool); #else zdb_resourcerecord* node = zdb_query_ex_answer_make(zone_soa, label_fqdn, PASS_ZCLASS_PARAMETER TYPE_SOA, pool); #endif if(next != NULL) { while(next->next != NULL) { next = next->next; } next->next = node; } else { *headp = node; } } } /** @brief Appends the SOA negative ttl record and its signature * * At the end * * @param zone the zone * @param headp a pointer to the section list * @param pool the memory pool * * @returns the negative ttl (minimum TTL is obsolete) * * 3 uses */ static void zdb_query_ex_answer_append_soa_rrsig_nttl(const zdb_zone *zone, zdb_resourcerecord **headp, u8 * restrict * pool) { yassert(zone != NULL); const u8 *label_fqdn = zone->origin; #if ZDB_RECORDS_MAX_CLASS != 1 u16 zclass = zone->zclass; #endif zdb_rr_collection *apex_records = &zone->apex->resource_record_set; zdb_packed_ttlrdata *zone_soa = zdb_record_find(apex_records, TYPE_SOA); if(zone_soa != NULL) { zdb_resourcerecord* next = *headp; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); #if ENFORCE_MINTTL zdb_resourcerecord* node = zdb_query_ex_answer_make_ttl(zone_soa, label_fqdn, PASS_ZCLASS_PARAMETER TYPE_SOA, min_ttl, pool); #else zdb_resourcerecord* node = zdb_query_ex_answer_make(zone_soa, label_fqdn, PASS_ZCLASS_PARAMETER TYPE_SOA, pool); #endif if(next != NULL) { while(next->next != NULL) { next = next->next; } next->next = node; } else { *headp = node; } #if ZDB_HAS_DNSSEC_SUPPORT #if ENFORCE_MINTTL zdb_query_ex_answer_append_type_rrsigs(zone->apex, label_fqdn, TYPE_SOA, PASS_ZCLASS_PARAMETER min_ttl, headp, pool); #else zdb_query_ex_answer_append_type_rrsigs(zone->apex, label_fqdn, TYPE_SOA, PASS_ZCLASS_PARAMETER zone_soa->ttl, headp, pool); #endif #endif } } /** * @brief Returns the label for the dns_name, relative to the apex of the zone * * @param zone the zone * @param dns_name the name of the label to find * * @return a pointer the label * * 2 uses */ static zdb_rr_label* zdb_query_rr_label_find_relative(const zdb_zone* zone, const u8* dns_name) { /* * Get the relative path */ const dnslabel_vector_reference origin = (const dnslabel_vector_reference)zone->origin_vector.labels; s32 origin_top = zone->origin_vector.size; dnslabel_vector name; s32 name_top = dnsname_to_dnslabel_vector(dns_name, name); if(name_top >= origin_top) { s32 i; for(i = 0; i <= origin_top; i++) { if(!dnslabel_equals(origin[origin_top - i], name[name_top - i])) { return NULL; } } /* * At this point we got the relative path, get the label * */ zdb_rr_label* rr_label = zdb_rr_label_find(zone->apex, name, (name_top - origin_top) - 1); return rr_label; } else { return NULL; } } /** * @brief Appends all the IPs (A & AAAA) under a name on the given zone * * @param zone the zone * @param dns_name the name of the label to find * @param zclass (if more than one class is supported in the database) * @param headp a pointer to the section list * @param pool the memory pool * @param dnssec dnssec enabled or not * * 1 use */ static inline void zdb_query_ex_answer_append_ips(const zdb_zone* zone, const u8* dns_name, DECLARE_ZCLASS_PARAMETER zdb_resourcerecord** headp, u8 * restrict * pool, bool dnssec) { /* Find relatively from the zone */ yassert(dns_name != NULL); zdb_rr_label* rr_label = zdb_query_rr_label_find_relative(zone, dns_name); if(rr_label != NULL) { /* Get the label, instead of the type in the label */ zdb_packed_ttlrdata* a = zdb_record_find(&rr_label->resource_record_set, TYPE_A); if(a != NULL) { zdb_query_ex_answer_appendlist(a, dns_name, PASS_ZCLASS_PARAMETER TYPE_A, headp, pool); #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec) { zdb_query_ex_answer_append_type_rrsigs(rr_label, dns_name, TYPE_A, PASS_ZCLASS_PARAMETER a->ttl, headp, pool); } #endif } zdb_packed_ttlrdata* aaaa = zdb_record_find(&rr_label->resource_record_set, TYPE_AAAA); if(aaaa != NULL) { zdb_query_ex_answer_appendlist(aaaa, dns_name, PASS_ZCLASS_PARAMETER TYPE_AAAA, headp, pool); #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec) { zdb_query_ex_answer_append_type_rrsigs(rr_label, dns_name, TYPE_AAAA, PASS_ZCLASS_PARAMETER aaaa->ttl, headp, pool); } #endif } } } /** * @brief Update a name set with the name found in an RDATA * * @param source the record rdata containing the name to add * @param headp a pointer to the section list * @param rtype the type of the record * @param set collection where to add the name * * 10 use */ static void update_additionals_dname_set(const zdb_packed_ttlrdata* source, DECLARE_ZCLASS_PARAMETER u16 rtype, dnsname_set* set) { if(source == NULL) { return; } u32 offset = 0; switch(rtype) { case TYPE_MX: { offset = 2; } FALLTHROUGH // fall through case TYPE_NS: { do { /* ADD NS "A/AAAA" TO ADDITIONAL */ const u8 *dns_name = ZDB_PACKEDRECORD_PTR_RDATAPTR(source); dns_name += offset; if(!dnsname_set_insert(set, dns_name)) { break; } source = source->next; } while(source != NULL); break; } } } /** * @brief Update a name set with the name found in an RDATA * * @param zone * @param zclass (if more than one class is supported in the database) * @param set collection where to add the name * @param headp a pointer to the section list * @param pool the memory pool * @param dnssec dnssec enabled or not * * 10 use */ static void append_additionals_dname_set(const zdb_zone* zone, DECLARE_ZCLASS_PARAMETER dnsname_set* set, zdb_resourcerecord** headp, u8 * restrict * pool, bool dnssec) { dnsname_set_iterator iter; dnsname_set_iterator_init(set, &iter); while(dnsname_set_iterator_hasnext(&iter)) { /* ADD NS "A/AAAA" TO ADDITIONAL */ const u8* dns_name = dnsname_set_iterator_next_node(&iter)->key; zdb_query_ex_answer_append_ips(zone, dns_name, PASS_ZCLASS_PARAMETER headp, pool, dnssec); } } /** * @brief Appends NS records to a section * * Appends NS records from the label to the referenced section * Also appends RRSIG for these NS * * @param qname * @param rr_label_info * @param headp a pointer to the section list * @param pool the memory pool * @param dnssec dnssec enabled or not * * 3 uses */ static zdb_packed_ttlrdata* append_authority(const u8 * qname, DECLARE_ZCLASS_PARAMETER const zdb_rr_label_find_ext_data* rr_label_info, zdb_resourcerecord** headp, u8 * restrict * pool, bool dnssec) { zdb_packed_ttlrdata* authority = zdb_record_find(&rr_label_info->authority->resource_record_set, TYPE_NS); if(authority != NULL) { s32 i = rr_label_info->authority_index; while(i > 0) { qname += qname[0] + 1; i--; } zdb_query_ex_answer_appendrndlist(authority, qname, PASS_ZCLASS_PARAMETER TYPE_NS, headp, pool); #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec) { zdb_query_ex_answer_append_type_rrsigs(rr_label_info->authority, qname, TYPE_NS, PASS_ZCLASS_PARAMETER authority->ttl, headp, pool); zdb_packed_ttlrdata* dsset = zdb_record_find(&rr_label_info->authority->resource_record_set, TYPE_DS); if(dsset != NULL) { zdb_query_ex_answer_appendlist(dsset, qname, PASS_ZCLASS_PARAMETER TYPE_DS, headp, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label_info->authority, qname, TYPE_DS, PASS_ZCLASS_PARAMETER dsset->ttl, headp, pool); } } #endif } return authority; } #if ZDB_HAS_NSEC3_SUPPORT /** * @brief Appends the NSEC3 - NODATA answer to the section * * @param zone the zone * @param rr_label the covered label * @param name the owner name * @param apex_index the index of the apex in the name * @param type the type of record required * @param zclass (if more than one class is supported in the database) * @param headp a pointer to the section list * @param pool the memory pool * * 2 uses */ static inline void zdb_query_ex_append_nsec3_nodata(const zdb_zone *zone, const zdb_rr_label *rr_label, const dnsname_vector *name, s32 apex_index, u16 rtype, DECLARE_ZCLASS_PARAMETER zdb_resourcerecord** headp, u8 * restrict * pool) { //nsec3_zone *n3 = zone->nsec.nsec3; u8 *nsec3_owner = NULL; u8 *closest_nsec3_owner = NULL; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_packed_ttlrdata* nsec3 = NULL; const zdb_packed_ttlrdata* nsec3_rrsig; zdb_packed_ttlrdata* closest_nsec3; const zdb_packed_ttlrdata* closest_nsec3_rrsig; if(!IS_WILD_LABEL(rr_label->name)) { if(rtype != TYPE_DS) // type is DS (7.2.3) { nsec3_nodata_error(zone, rr_label, name, apex_index, pool, &nsec3_owner, &nsec3, &nsec3_rrsig, &closest_nsec3_owner, &closest_nsec3, &closest_nsec3_rrsig); } else // type is DS (7.2.4) { closest_nsec3 = NULL; closest_nsec3_rrsig = NULL; if((rr_label->nsec.dnssec != NULL)) // (7.2.3 a) { nsec3_zone_item *owner_nsec3 = nsec3_label_extension_self(rr_label->nsec.nsec3); nsec3_zone *n3 = zone->nsec.nsec3; if(owner_nsec3 != NULL) { nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm nsec3_parms = { n3, owner_nsec3, zone->origin, pool, min_ttl }; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, &nsec3_owner, &nsec3, &nsec3_rrsig); } } else // (7.2.4 b) { //u8 *wild_closest_nsec3_owner = NULL; //zdb_packed_ttlrdata* wild_closest_nsec3 = NULL; //const zdb_packed_ttlrdata* wild_closest_nsec3_rrsig = NULL; /* closest encloser proof */ nsec3_nodata_error(zone, rr_label, name, apex_index, pool, &nsec3_owner, &nsec3, &nsec3_rrsig, &closest_nsec3_owner, &closest_nsec3, &closest_nsec3_rrsig); if((nsec3 != NULL) && (nsec3_rrsig != NULL)) { #if DEBUG log_debug("zdb-query: nsec3_nodata_error: nsec3_owner: %{dnsname}", nsec3_owner); #endif zdb_query_ex_answer_append_ttl(nsec3, nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, headp, pool); zdb_query_ex_answer_appendlist_ttl(nsec3_rrsig, nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, headp, pool); } if((closest_nsec3 != NULL) && (closest_nsec3_owner != nsec3_owner) && (closest_nsec3_rrsig != NULL)) { #if DEBUG log_debug("zdb-query: nsec3_nodata_error: closest_nsec3_owner: %{dnsname}", closest_nsec3_owner); #endif zdb_query_ex_answer_append_ttl(closest_nsec3, closest_nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, headp, pool); zdb_query_ex_answer_appendlist_ttl(closest_nsec3_rrsig, closest_nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, headp, pool); } return; } } } else { u8 *wild_closest_nsec3_owner = NULL; zdb_packed_ttlrdata* wild_closest_nsec3 = NULL; const zdb_packed_ttlrdata* wild_closest_nsec3_rrsig = NULL; nsec3_wild_nodata_error(zone, rr_label, name, apex_index, pool, &nsec3_owner, &nsec3, &nsec3_rrsig, &closest_nsec3_owner, &closest_nsec3, &closest_nsec3_rrsig, &wild_closest_nsec3_owner, &wild_closest_nsec3, &wild_closest_nsec3_rrsig); if((wild_closest_nsec3 != NULL) && (wild_closest_nsec3_rrsig != NULL)) { #if DEBUG log_debug("zdb-query: nsec3_nodata_error: wild_closest_nsec3_owner: %{dnsname}", wild_closest_nsec3_owner); #endif zdb_query_ex_answer_append_ttl(wild_closest_nsec3, wild_closest_nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, headp, pool); zdb_query_ex_answer_appendlist_ttl(wild_closest_nsec3_rrsig, wild_closest_nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, headp, pool); } } if((nsec3 != NULL) && (nsec3_rrsig != NULL)) { #if DEBUG log_debug("zdb-query: nsec3_nodata_error: nsec3_owner: %{dnsname}", nsec3_owner); #endif /// @note part of the fix for https://github.com/yadifa/yadifa/issues/12 bool delegation = zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_UNDERDELEGATION); bool allowed_under_delegation = (rtype == TYPE_ANY) || (rtype == TYPE_A) || (rtype == TYPE_AAAA); if(NSEC3_RDATA_IS_OPTOUT(ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec3)) || (!delegation || (delegation && allowed_under_delegation))) { zdb_query_ex_answer_append_ttl(nsec3, nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, headp, pool); zdb_query_ex_answer_appendlist_ttl(nsec3_rrsig, nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, headp, pool); } } if((closest_nsec3 != NULL) && (closest_nsec3_rrsig != NULL)) { #if DEBUG log_debug("zdb-query: nsec3_nodata_error: closest_nsec3_owner: %{dnsname}", closest_nsec3_owner); #endif zdb_query_ex_answer_append_ttl(closest_nsec3, closest_nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, headp, pool); zdb_query_ex_answer_appendlist_ttl(closest_nsec3_rrsig, closest_nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, headp, pool); } } /** * @brief Appends the wildcard NSEC3 - DATA answer to the section * * @param zone the zone * @param rr_label the covered label * @param name the owner name * @param apex_index the index of the apex in the name * @param zclass (if more than one class is supported in the database) * @param headp a pointer to the section list * @param pool the memory pool * * 2 uses */ static inline void zdb_query_ex_append_wild_nsec3_data(const zdb_zone *zone, const zdb_rr_label *rr_label, const dnsname_vector *name, s32 apex_index, DECLARE_ZCLASS_PARAMETER zdb_resourcerecord** headp, u8 * restrict * pool) { yassert(IS_WILD_LABEL(rr_label->name)); //nsec3_zone *n3 = zone->nsec.nsec3; u8 *nsec3_owner = NULL; u8 *closest_nsec3_owner = NULL; u8 *qname_nsec3_owner = NULL; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_packed_ttlrdata* nsec3 = NULL; const zdb_packed_ttlrdata* nsec3_rrsig; zdb_packed_ttlrdata* closest_nsec3 = NULL; const zdb_packed_ttlrdata* closest_nsec3_rrsig; zdb_packed_ttlrdata* qname_nsec3 = NULL; const zdb_packed_ttlrdata* qname_nsec3_rrsig; nsec3_wild_nodata_error(zone, rr_label, name, apex_index, pool, &nsec3_owner, &nsec3, &nsec3_rrsig, &closest_nsec3_owner, &closest_nsec3, &closest_nsec3_rrsig, &qname_nsec3_owner, &qname_nsec3, &qname_nsec3_rrsig ); #if 1 if((qname_nsec3 != NULL) && (qname_nsec3_rrsig != NULL)) { #if DEBUG log_debug("zdb-query: nsec3_nodata_error: qname_nsec3_owner: %{dnsname}", qname_nsec3_owner); #endif zdb_query_ex_answer_append_ttl(qname_nsec3, qname_nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, headp, pool); zdb_query_ex_answer_appendlist_ttl(qname_nsec3_rrsig, qname_nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, headp, pool); } #endif } /** * @brief Appends the NSEC3 delegation answer to the section * * @param zone the zone * @param rr_label the covered label * @param name the owner name * @param apex_index the index of the apex in the name * @param zclass (if more than one class is supported in the database) * @param headp a pointer to the section list * @param pool the memory pool * * 3 uses */ static inline void zdb_query_ex_append_nsec3_delegation(const zdb_zone *zone, const zdb_rr_label_find_ext_data *rr_label_info, const dnsname_vector *name, s32 apex_index, DECLARE_ZCLASS_PARAMETER zdb_resourcerecord **headp, u8 * restrict * pool) { zdb_rr_label *authority = rr_label_info->authority; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); if((authority->nsec.nsec3 != NULL) && (nsec3_label_extension_self(authority->nsec.nsec3) != NULL)) { /* add it */ u8 *authority_nsec3_owner = NULL; nsec3_zone *n3 = zone->nsec.nsec3; zdb_packed_ttlrdata *authority_nsec3; const zdb_packed_ttlrdata *authority_nsec3_rrsig; nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm nsec3_parms = { n3, nsec3_label_extension_self(authority->nsec.nsec3), zone->origin, pool, min_ttl }; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, &authority_nsec3_owner, &authority_nsec3, &authority_nsec3_rrsig); zdb_query_ex_answer_append_ttl(authority_nsec3, authority_nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, headp, pool); if(authority_nsec3_rrsig != NULL) { zdb_query_ex_answer_appendlist_ttl(authority_nsec3_rrsig, authority_nsec3_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, headp, pool); } } else { // add closest provable encloser proof zdb_query_ex_append_nsec3_nodata(zone, authority, name, apex_index, 0, PASS_ZCLASS_PARAMETER headp, pool); } } #endif #if ZDB_HAS_NSEC_SUPPORT /** * @brief Appends the NSEC records of a label to the section * * @param rr_label the covered label * @param qname the owner name * @param min_ttl the minimum ttl (OBSOLETE) * @param zclass (if more than one class is supported in the database) * @param headp a pointer to the section list * @param pool the memory pool * * 2 uses */ static inline void zdb_query_ex_append_nsec_records(const zdb_rr_label *rr_label, const u8 * restrict qname, u32 min_ttl, DECLARE_ZCLASS_PARAMETER zdb_resourcerecord **headp, u8 * restrict * pool) { (void)min_ttl; zdb_packed_ttlrdata *rr_label_nsec_record = zdb_record_find(&rr_label->resource_record_set, TYPE_NSEC); if(rr_label_nsec_record != NULL) { zdb_query_ex_answer_append(rr_label_nsec_record, qname, PASS_ZCLASS_PARAMETER TYPE_NSEC, headp, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label, qname, TYPE_NSEC, PASS_ZCLASS_PARAMETER rr_label_nsec_record->ttl, headp, pool); } } #endif /** @brief Destroys a zdb_resourcerecord* single linked list. * * Destroys a zdb_resourcerecord* single linked list created by a zdb_query* * * @param[in] rr the head of the sll. * * 3 uses */ void zdb_destroy_resourcerecord_list(zdb_resourcerecord *rr) { (void)rr; } /** * @brief Handles what to do when a record has not been found (NXRRSET) * * @param zone the zone * @param rr_label_info details about the labels on the path of the query * @param qname name of the query * @param name name of the query (vector) * @param sp index of the label in the name (vector) * @param top * @param type * @param zclass (if more than one class is supported in the database) * @param ans_auth_add a pointer to the section list * @param pool the memory pool * @param additionals_dname_set * * 3 uses */ static inline ya_result zdb_query_ex_record_not_found(const zdb_zone *zone, const zdb_rr_label_find_ext_data *rr_label_info, const u8* qname, const dnsname_vector *name, s32 sp_label_index, s32 top, u16 type, DECLARE_ZCLASS_PARAMETER u8 * restrict * pool, bool dnssec, zdb_query_ex_answer *ans_auth_add, dnsname_set *additionals_dname_set) { (void)sp_label_index; zdb_rr_label *rr_label = rr_label_info->answer; // NXRRSET #if ZDB_HAS_NSEC3_SUPPORT if(dnssec && ZONE_NSEC3_AVAILABLE(zone)) { zdb_packed_ttlrdata *zone_soa = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA); s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); if( ((type == TYPE_DS) && (zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_UNDERDELEGATION))) || ((type != TYPE_DS) && (zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION))) ) { /* * Add all the NS and their signature */ zdb_rr_label *authority = rr_label_info->authority; zdb_packed_ttlrdata* rr_label_ns = zdb_record_find(&authority->resource_record_set, TYPE_NS); if(rr_label_ns != NULL) { const u8* auth_name = name->labels[rr_label_info->authority_index]; zdb_query_ex_answer_appendlist(rr_label_ns, auth_name, PASS_ZCLASS_PARAMETER TYPE_NS, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label, auth_name, PASS_ZCLASS_PARAMETER TYPE_NS, rr_label_ns->ttl, &ans_auth_add->authority, pool); update_additionals_dname_set(rr_label_ns, PASS_ZCLASS_PARAMETER TYPE_NS, additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER additionals_dname_set, &ans_auth_add->additional, pool, FALSE); zdb_packed_ttlrdata* label_ds = zdb_record_find(&authority->resource_record_set, TYPE_DS); if(label_ds != NULL) { zdb_query_ex_answer_appendlist(label_ds, auth_name, PASS_ZCLASS_PARAMETER TYPE_DS, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(authority, auth_name, TYPE_DS, PASS_ZCLASS_PARAMETER label_ds->ttl, &ans_auth_add->authority, pool); /* ans_auth_add->is_delegation = TRUE; later */ return FP_BASIC_RECORD_NOTFOUND; } } } else { zdb_query_ex_answer_append_ttl(zone_soa, zone->origin, PASS_ZCLASS_PARAMETER TYPE_SOA, min_ttl, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(zone->apex, zone->origin, TYPE_SOA, PASS_ZCLASS_PARAMETER min_ttl, &ans_auth_add->authority, pool); } if(ans_auth_add->delegation == 0) { zdb_query_ex_append_nsec3_nodata(zone, rr_label, name, top, type, PASS_ZCLASS_PARAMETER &ans_auth_add->authority, pool); } else { /* * If there is an NSEC3 RR that matches the delegation name, then that * NSEC3 RR MUST be included in the response. The DS bit in the type * bit maps of the NSEC3 RR MUST NOT be set. * * If the zone is Opt-Out, then there may not be an NSEC3 RR * corresponding to the delegation. In this case, the closest provable * encloser proof MUST be included in the response. The included NSEC3 * RR that covers the "next closer" name for the delegation MUST have * the Opt-Out flag set to one. (Note that this will be the case unless * something has gone wrong). */ zdb_query_ex_append_nsec3_delegation(zone, rr_label_info, name, top, PASS_ZCLASS_PARAMETER &ans_auth_add->authority, pool); } #if DEBUG log_debug("zdb-query: FP_NSEC3_RECORD_NOTFOUND (NSEC3)"); #endif return FP_NSEC3_RECORD_NOTFOUND; } else /* We had the label, not the record, it's not NSEC3 : */ #endif { /** Got label but no record : show the authority * AA */ if(zdb_rr_label_is_not_apex(rr_label_info->authority)) { zdb_packed_ttlrdata* authority; if( ( ((type == TYPE_DS) && zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_UNDERDELEGATION)) || ((type != TYPE_DS) && zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION)) ) && ( ((authority = zdb_record_find(&rr_label_info->authority->resource_record_set, TYPE_NS)) != NULL) ) ) { const u8* auth_name = name->labels[rr_label_info->authority_index]; zdb_query_ex_answer_appendrndlist(authority, auth_name, PASS_ZCLASS_PARAMETER TYPE_NS, &ans_auth_add->authority, pool); update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER additionals_dname_set, &ans_auth_add->additional, pool, FALSE); /* ans_auth_add->is_delegation = TRUE; later */ } else { /* append the SOA */ if(!dnssec) { zdb_query_ex_answer_append_soa(zone, &ans_auth_add->authority, pool); } else { zdb_query_ex_answer_append_soa_rrsig(zone, &ans_auth_add->authority, pool); } } } else // apex { /* append the SOA */ if(!dnssec) { zdb_query_ex_answer_append_soa_nttl(zone, &ans_auth_add->authority, pool); } else { zdb_query_ex_answer_append_soa_rrsig_nttl(zone, &ans_auth_add->authority, pool); } } #if ZDB_HAS_NSEC_SUPPORT if(dnssec && ZONE_NSEC_AVAILABLE(zone)) { zdb_rr_label* rr_label_authority = rr_label_info->authority; zdb_packed_ttlrdata *delegation_signer = zdb_record_find(&rr_label_authority->resource_record_set, TYPE_DS); if(delegation_signer != NULL) { const u8 * authority_qname = zdb_rr_label_info_get_authority_qname(qname, rr_label_info); zdb_query_ex_answer_appendlist(delegation_signer , authority_qname, PASS_ZCLASS_PARAMETER TYPE_DS, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label_authority, authority_qname, TYPE_DS, PASS_ZCLASS_PARAMETER delegation_signer->ttl, &ans_auth_add->authority, pool); } else { u8 *wild_name = (u8*)qname; if(IS_WILD_LABEL(rr_label->name)) { wild_name = *pool; *pool += ALIGN16(MAX_DOMAIN_LENGTH + 2); // take the name directly from the nsec node if(IS_WILD_LABEL(rr_label->name)) { // take the name directly from the nsec node if(rr_label_info->answer->nsec.nsec.node != NULL) { wild_name = *pool; *pool += ALIGN16(MAX_DOMAIN_LENGTH); nsec_inverse_name(&wild_name[0], rr_label_info->answer->nsec.nsec.node->inverse_relative_name); } else if(rr_label_info->closest->nsec.nsec.node != NULL) { //rr_label = rr_label_info->closest; wild_name = *pool; *pool += ALIGN16(MAX_DOMAIN_LENGTH + 2); wild_name[0] = 1; wild_name[1] = '*'; nsec_inverse_name(&wild_name[2], rr_label_info->closest->nsec.nsec.node->inverse_relative_name); } else { return FP_BASIC_RECORD_NOTFOUND; } } } zdb_packed_ttlrdata *rr_label_nsec_record = zdb_record_find(&rr_label->resource_record_set, TYPE_NSEC); if(rr_label_nsec_record != NULL) { zdb_query_ex_answer_append(rr_label_nsec_record, wild_name, PASS_ZCLASS_PARAMETER TYPE_NSEC, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label, wild_name, TYPE_NSEC, PASS_ZCLASS_PARAMETER rr_label_nsec_record->ttl, &ans_auth_add->authority, pool); } zdb_query_ex_add_nsec_interval(zone, name, rr_label, &ans_auth_add->authority, pool); } } #endif } return FP_BASIC_RECORD_NOTFOUND; } /** * @brief Handles what to do when a record has not been found (NXRRSET) * * @param zone the zone * @param rr_label_info details about the labels on the path of the query * @param qname name of the query * @param name name of the query (vector) * @param sp index of the label in the name (vector) * @param top * @param type * @param zclass (if more than one class is supported in the database) * @param ans_auth_add a pointer to the section list * @param pool the memory pool * @param additionals_dname_set * * 3 uses */ static inline ya_result zdb_query_ex_record_not_found_nttl(const zdb_zone *zone, const zdb_rr_label_find_ext_data *rr_label_info, const u8* qname, const dnsname_vector *name, s32 sp_label_index, s32 top, u16 type, DECLARE_ZCLASS_PARAMETER u8 * restrict * pool, bool dnssec, zdb_query_ex_answer *ans_auth_add, dnsname_set *additionals_dname_set) { (void)sp_label_index; zdb_rr_label *rr_label = rr_label_info->answer; // NXRRSET #if ZDB_HAS_NSEC3_SUPPORT if(dnssec && ZONE_NSEC3_AVAILABLE(zone)) { zdb_packed_ttlrdata *zone_soa = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA); s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); if( ((type == TYPE_DS) && (zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_UNDERDELEGATION))) || ((type != TYPE_DS) && (zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION))) ) { /* * Add all the NS and their signature */ zdb_rr_label *authority = rr_label_info->authority; zdb_packed_ttlrdata* rr_label_ns = zdb_record_find(&authority->resource_record_set, TYPE_NS); if(rr_label_ns != NULL) { const u8* auth_name = name->labels[rr_label_info->authority_index]; zdb_query_ex_answer_appendlist(rr_label_ns, auth_name, PASS_ZCLASS_PARAMETER TYPE_NS, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label, auth_name, PASS_ZCLASS_PARAMETER TYPE_NS, rr_label_ns->ttl, &ans_auth_add->authority, pool); update_additionals_dname_set(rr_label_ns, PASS_ZCLASS_PARAMETER TYPE_NS, additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER additionals_dname_set, &ans_auth_add->additional, pool, FALSE); zdb_packed_ttlrdata* label_ds = zdb_record_find(&authority->resource_record_set, TYPE_DS); if(label_ds != NULL) { zdb_query_ex_answer_appendlist(label_ds, auth_name, PASS_ZCLASS_PARAMETER TYPE_DS, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(authority, auth_name, TYPE_DS, PASS_ZCLASS_PARAMETER label_ds->ttl, &ans_auth_add->authority, pool); /* ans_auth_add->is_delegation = TRUE; later */ return FP_BASIC_RECORD_NOTFOUND; } } } else { zdb_query_ex_answer_append_ttl(zone_soa, zone->origin, PASS_ZCLASS_PARAMETER TYPE_SOA, min_ttl, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(zone->apex, zone->origin, TYPE_SOA, PASS_ZCLASS_PARAMETER min_ttl, &ans_auth_add->authority, pool); } if(ans_auth_add->delegation == 0) { zdb_query_ex_append_nsec3_nodata(zone, rr_label, name, top, type, PASS_ZCLASS_PARAMETER &ans_auth_add->authority, pool); } else { /* * If there is an NSEC3 RR that matches the delegation name, then that * NSEC3 RR MUST be included in the response. The DS bit in the type * bit maps of the NSEC3 RR MUST NOT be set. * * If the zone is Opt-Out, then there may not be an NSEC3 RR * corresponding to the delegation. In this case, the closest provable * encloser proof MUST be included in the response. The included NSEC3 * RR that covers the "next closer" name for the delegation MUST have * the Opt-Out flag set to one. (Note that this will be the case unless * something has gone wrong). */ zdb_query_ex_append_nsec3_delegation(zone, rr_label_info, name, top, PASS_ZCLASS_PARAMETER &ans_auth_add->authority, pool); } #if DEBUG log_debug("zdb-query: FP_NSEC3_RECORD_NOTFOUND (NSEC3)"); #endif return FP_NSEC3_RECORD_NOTFOUND; } else /* We had the label, not the record, it's not NSEC3 : */ #endif { /** Got label but no record : show the authority * AA */ if(zdb_rr_label_is_not_apex(rr_label_info->authority)) { zdb_packed_ttlrdata* authority; if( ( ((type == TYPE_DS) && zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_UNDERDELEGATION)) || ((type != TYPE_DS) && zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION)) ) && ( ((authority = zdb_record_find(&rr_label_info->authority->resource_record_set, TYPE_NS)) != NULL) ) ) { const u8* auth_name = name->labels[rr_label_info->authority_index]; zdb_query_ex_answer_appendrndlist(authority, auth_name, PASS_ZCLASS_PARAMETER TYPE_NS, &ans_auth_add->authority, pool); update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER additionals_dname_set, &ans_auth_add->additional, pool, FALSE); /* ans_auth_add->is_delegation = TRUE; later */ } else { /* append the SOA */ if(!dnssec) { zdb_query_ex_answer_append_soa_nttl(zone, &ans_auth_add->authority, pool); } else { zdb_query_ex_answer_append_soa_rrsig_nttl(zone, &ans_auth_add->authority, pool); } } } else // apex { /* append the SOA */ if(!dnssec) { zdb_query_ex_answer_append_soa_nttl(zone, &ans_auth_add->authority, pool); } else { zdb_query_ex_answer_append_soa_rrsig_nttl(zone, &ans_auth_add->authority, pool); } } #if ZDB_HAS_NSEC_SUPPORT if(dnssec && ZONE_NSEC_AVAILABLE(zone)) { zdb_rr_label* rr_label_authority = rr_label_info->authority; zdb_packed_ttlrdata *delegation_signer = zdb_record_find(&rr_label_authority->resource_record_set, TYPE_DS); if(delegation_signer != NULL) { const u8 * authority_qname = zdb_rr_label_info_get_authority_qname(qname, rr_label_info); zdb_query_ex_answer_appendlist(delegation_signer , authority_qname, PASS_ZCLASS_PARAMETER TYPE_DS, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label_authority, authority_qname, TYPE_DS, PASS_ZCLASS_PARAMETER delegation_signer->ttl, &ans_auth_add->authority, pool); } else { u8 *wild_name = (u8*)qname; if(IS_WILD_LABEL(rr_label->name)) { // take the name directly from the nsec node if(rr_label_info->answer->nsec.nsec.node != NULL) { wild_name = *pool; *pool += ALIGN16(MAX_DOMAIN_LENGTH); nsec_inverse_name(&wild_name[0], rr_label_info->answer->nsec.nsec.node->inverse_relative_name); } else if(rr_label_info->closest->nsec.nsec.node != NULL) { //rr_label = rr_label_info->closest; wild_name = *pool; *pool += ALIGN16(MAX_DOMAIN_LENGTH + 2); wild_name[0] = 1; wild_name[1] = '*'; nsec_inverse_name(&wild_name[2], rr_label_info->closest->nsec.nsec.node->inverse_relative_name); } else { return FP_BASIC_RECORD_NOTFOUND; } } zdb_packed_ttlrdata *rr_label_nsec_record = zdb_record_find(&rr_label->resource_record_set, TYPE_NSEC); if(rr_label_nsec_record != NULL) { zdb_query_ex_answer_append(rr_label_nsec_record, wild_name, PASS_ZCLASS_PARAMETER TYPE_NSEC, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label, wild_name, TYPE_NSEC, PASS_ZCLASS_PARAMETER rr_label_nsec_record->ttl, &ans_auth_add->authority, pool); } zdb_query_ex_add_nsec_interval(zone, name, rr_label, &ans_auth_add->authority, pool); } } #endif } return FP_BASIC_RECORD_NOTFOUND; } /** * @brief destroys an answer made by zdb_query* * * @param ans_auth_add a pointer to the answer structure * */ #ifndef zdb_query_ex_answer_destroy void zdb_query_ex_answer_destroy(zdb_query_ex_answer* ans_auth_add) { zdb_destroy_resourcerecord_list(ans_auth_add->answer); ans_auth_add->answer = NULL; zdb_destroy_resourcerecord_list(ans_auth_add->authority); ans_auth_add->authority = NULL; zdb_destroy_resourcerecord_list(ans_auth_add->additional); ans_auth_add->additional = NULL; } #endif /** * @brief Queries the database given a message * * @param db the database * @param mesg the message * @param ans_auth_add the structure that will contain the sections of the answer * @param pool_buffer a big enough buffer used for the memory pool * * @return the status of the message (probably useless) */ static finger_print zdb_query_from_cname(zdb *db, message_data *mesg, zdb_query_ex_answer *ans_auth_add, zdb_zone *in_zone, u8 * restrict pool_buffer) { yassert(ans_auth_add != NULL); //const u8 * restrict qname = message_get_canonised_fqdn(mesg); const u8 *qname = message_get_canonised_fqdn(mesg); #if ZDB_RECORDS_MAX_CLASS != 1 const u16 zclass = message_get_query_class(mesg); #endif zdb_rr_label_find_ext_data rr_label_info; u16 type = message_get_query_type(mesg); const process_flags_t flags = zdb_query_process_flags; /** Check that we are even allowed to handle that class */ #if ZDB_RECORDS_MAX_CLASS == 1 if(message_get_query_class(mesg) != CLASS_IN) { #if DEBUG log_debug("zdb-query-cname: FP_CLASS_NOTFOUND"); #endif return FP_CLASS_NOTFOUND; } #endif #if ZDB_RECORDS_MAX_CLASS != 1 u16 host_zclass = ntohs(zclass); /* no choice */ if(host_zclass > ZDB_RECORDS_MAX_CLASS) { return; // FP_CLASS_NOTFOUND; } #endif bool dnssec = message_has_rcode_ext_dnssec(mesg); /** * MANDATORY, INITIALISES A LOCAL MEMORY POOL * * This is actually a macro found in dnsname_set.h */ dnsname_vector name; DEBUG_RESET_dnsname(name); dnsname_to_dnsname_vector(qname, &name); u8 * restrict * pool = &pool_buffer; /* * Find closest matching label * Should return a stack of zones */ zdb_zone_label_pointer_array zone_label_stack; zdb_lock(db, ZDB_MUTEX_READER); s32 top = zdb_zone_label_match(db, &name, zone_label_stack); // value returned >= 0 s32 sp = top; // top >=0 => sp >= 0 zdb_packed_ttlrdata* answer; /* This flag means that there HAS to be an authority section */ bool authority_required = flags & PROCESS_FL_AUTHORITY_AUTH; /* This flag means the names in the authority must be (internally) resolved if possible */ bool additionals_required = flags & PROCESS_FL_ADDITIONAL_AUTH; switch(type) { case TYPE_A: case TYPE_AAAA: case TYPE_DNSKEY: { authority_required = FALSE; additionals_required = FALSE; break; } } /* Got a stack of zone labels with and without zone cuts */ /* Search the label on the zone files */ /* While we have labels along the path */ if(type == TYPE_DS) // This is the only type that can only be found outside of the zone { // In order to avoid to hit said zone, I skip the last label. if(name.size == sp - 1) // we have a perfect match (DS for an APEX), try to get outside ... { s32 parent_sp = sp; while(--parent_sp >= 0) { /* Get the "bottom" label (top being ".") */ zdb_zone_label* zone_label = zone_label_stack[parent_sp]; /* Is there a zone file at this level ? If yes, search into it. */ if(zone_label->zone != NULL) { // got it. sp = parent_sp; message_set_authoritative(mesg); break; } } authority_required = FALSE; } } bool outside_of_zone = TRUE; while(sp >= 0) { /* Get the "bottom" label (top being ".") */ zdb_zone_label* zone_label = zone_label_stack[sp]; /* Is there a zone file at this level ? If yes, search into it. */ if(zone_label->zone == in_zone) { outside_of_zone = FALSE; zdb_zone *zone = zone_label->zone; /* * lock */ LOCK(zone); #if DEBUG log_debug("zdb-query-cname: zone %{dnsname}, flags=%x", zone->origin, zdb_rr_label_flag_get(zone->apex)); #endif /* * We know the zone, and its extension here ... */ { /* * Filter handling (ACL) * NOTE: the return code has to be fingerprint-based */ if(FAIL(zone->query_access_filter(mesg, zone->acl))) { #if DEBUG log_debug("zdb-query-cname: FP_ACCESS_REJECTED"); #endif UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_ACCESS_REJECTED; } } /** * The ACL have been passed so ... now check that the zone is valid */ if(zdb_zone_invalid(zone)) { /** * @note the blocks could be reversed and jump if the zone is invalid (help the branch prediction) */ #if DEBUG log_debug("zdb-query-cname: FP_ZONE_EXPIRED"); #endif UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_INVALID_ZONE; } //message_set_authoritative(mesg); dnsname_set additionals_dname_set; dnsname_set_init(&additionals_dname_set); /* * In one query, get the authority and the closest (longest) path to the domain we are looking for. */ zdb_rr_label *rr_label = zdb_rr_label_find_ext(zone->apex, name.labels, name.size - sp, &rr_label_info); /* Has a label been found ? */ if(rr_label != NULL) { /* * Got the label. I will not find anything relevant by going * up to another zone file. * * We set the AA bit iff we are not at or under a delegation. * * The ZDB_RR_LABEL_DELEGATION flag means the label is a delegation. * This means that it only contains NS & DNSSEC records + may have sub-labels for glues * * ZDB_RR_LABEL_UNDERDELEGATION means we are below a ZDB_RR_LABEL_DELEGATION label * */ /* * CNAME alias handling */ // if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_HASCNAME) && (type != TYPE_CNAME) && (type != TYPE_ANY)) if(((zdb_rr_label_flag_get(rr_label) & (ZDB_RR_LABEL_HASCNAME|ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION)) == ZDB_RR_LABEL_HASCNAME) && (type != TYPE_CNAME) && (type != TYPE_ANY) && (type != TYPE_RRSIG)) { /* * The label is an alias: * * Add the CNAME and restart the query from the alias */ if(ans_auth_add->depth >= ZDB_CNAME_LOOP_MAX) { log_warn("CNAME depth at %{dnsname} is bigger than allowed %d>=%d", qname, ans_auth_add->depth, ZDB_CNAME_LOOP_MAX); message_set_authoritative(mesg); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_CNAME_MAXIMUM_DEPTH; } ans_auth_add->depth++; if((answer = zdb_record_find(&rr_label->resource_record_set, TYPE_CNAME)) != NULL) { /* The RDATA in answer is the fqdn to a label with an A record (list) */ /* There can only be one cname for a given owner */ /* Append all A/AAAA records associated to the CNAME AFTER the CNAME record */ zdb_resourcerecord *rr = ans_auth_add->answer; u32 cname_depth_count = 0; /* I don't want to allocate that globally for now */ while(rr != NULL) { if((rr->rtype == TYPE_CNAME) && (ZDB_PACKEDRECORD_PTR_RDATAPTR(rr->ttl_rdata) == ZDB_PACKEDRECORD_PTR_RDATAPTR(answer))) { /* LOOP */ log_warn("CNAME loop at %{dnsname}", qname); message_set_authoritative(mesg); UNLOCK(zone); /// @note 20220211 edf -- here zdb_unlock(db, ZDB_MUTEX_READER); return FP_CNAME_LOOP; } cname_depth_count++; rr = rr->next; } u8* cname_owner = *pool; *pool += ALIGN16(dnsname_copy(*pool, qname)); /* ONE record */ zdb_query_ex_answer_append(answer, cname_owner, PASS_ZCLASS_PARAMETER TYPE_CNAME, &ans_auth_add->answer, pool); #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec) { zdb_query_ex_answer_append_type_rrsigs(rr_label, cname_owner, TYPE_CNAME, PASS_ZCLASS_PARAMETER answer->ttl, &ans_auth_add->answer, pool); } #endif message_set_canonised_fqdn(mesg, ZDB_PACKEDRECORD_PTR_RDATAPTR(answer)); zdb_query_from_cname(db, mesg, ans_auth_add, in_zone, pool_buffer); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_RCODE_NOERROR; } else { /* * We expected a CNAME record but found none. * This is NOT supposed to happen. */ UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_CNAME_BROKEN; } } if(zdb_rr_label_flag_isclear(rr_label, ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION)) { message_set_authoritative(mesg); } else { /* * we are AT or UNDER a delegation * We can only find (show) NS, DS, RRSIG, NSEC records from the query * * The answer WILL be a referral ... */ switch(type) { /* for these ones : give the rrset for the type and clear AA */ case TYPE_DS: { if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { message_set_authoritative(mesg); } else if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_UNDERDELEGATION)) { message_disable_authoritative(mesg); } ans_auth_add->delegation = 1; authority_required = FALSE; break; } case TYPE_NSEC: { ans_auth_add->delegation = 1; // no answer, and we will answer with NS (as at or under delegation) if(zdb_rr_label_flag_isclear(rr_label, ZDB_RR_LABEL_UNDERDELEGATION)) { message_set_authoritative(mesg); } break; } /* for these ones : give the rrset for the type */ case TYPE_NS: ans_auth_add->delegation = 1; // no answer, and we will answer with NS (as at or under delegation) break; /* for this one : present the delegation */ case TYPE_ANY: ans_auth_add->delegation = 1; // no answer, and we will answer with NS (as at or under delegation) authority_required = FALSE; break; /* for the rest : NSEC ? */ default: /* * do not try to look for it * * faster: go to label but no record, but let's avoid gotos ... */ type = 0; break; } } /* * First let's handle "simple" cases. ANY will be handled in another part of the code. */ if(type != TYPE_ANY) { /* * From the label that has been found, get the RRSET for the required type (zdb_packed_ttlrdata*) */ if((answer = zdb_record_find(&rr_label->resource_record_set, type)) != NULL) { /* A match has been found */ /* NS case */ if(type == TYPE_NS) { zdb_resourcerecord **section; /* * If the label is a delegation, the NS have to be added into authority, * else they have to be added into answer. * */ if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { section = &ans_auth_add->authority; /* ans_auth_add->is_delegation = TRUE; later */ } else { section = &ans_auth_add->answer; } /* * Add the NS records in random order in the right section * */ zdb_query_ex_answer_appendrndlist(answer, qname, PASS_ZCLASS_PARAMETER type, section, pool); #if ZDB_HAS_DNSSEC_SUPPORT /* * Append all the RRSIG of NS from the label */ if(dnssec) { zdb_query_ex_answer_append_type_rrsigs(rr_label, qname, TYPE_NS, PASS_ZCLASS_PARAMETER answer->ttl, section, pool); if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { zdb_packed_ttlrdata* label_ds = zdb_record_find(&rr_label->resource_record_set, TYPE_DS); if(label_ds != NULL) { zdb_query_ex_answer_appendlist(label_ds, qname, PASS_ZCLASS_PARAMETER TYPE_DS, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label, qname, TYPE_DS, PASS_ZCLASS_PARAMETER label_ds->ttl, &ans_auth_add->authority, pool); } #if ZDB_HAS_NSEC3_SUPPORT else if(ZONE_NSEC3_AVAILABLE(zone)) { /** * If there is an NSEC3 RR that matches the delegation name, then that * NSEC3 RR MUST be included in the response. The DS bit in the type * bit maps of the NSEC3 RR MUST NOT be set. * * If the zone is Opt-Out, then there may not be an NSEC3 RR * corresponding to the delegation. In this case, the closest provable * encloser proof MUST be included in the response. The included NSEC3 * RR that covers the "next closer" name for the delegation MUST have * the Opt-Out flag set to one. (Note that this will be the case unless * something has gone wrong). * */ zdb_query_ex_append_nsec3_delegation(zone, &rr_label_info, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add->authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT else if(ZONE_NSEC_AVAILABLE(zone)) { /* * Append the NSEC of rr_label and all its signatures */ s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_query_ex_append_nsec_records(rr_label, qname, min_ttl, PASS_ZCLASS_PARAMETER &ans_auth_add->authority, pool); } #endif } } #endif /* * authority is never required since we have it already * */ /* * fetch all the additional records for the required type (NS and MX types) * add them to the additional section */ if(additionals_required) { update_additionals_dname_set(answer, PASS_ZCLASS_PARAMETER type, &additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add->additional, pool, dnssec); } } else /* general case */ { /* * Add the records from the answer in random order to the answer section */ zdb_query_ex_answer_appendrndlist(answer, qname, PASS_ZCLASS_PARAMETER type, &ans_auth_add->answer, pool); #if ZDB_HAS_DNSSEC_SUPPORT /* * Append all the RRSIG of NS from the label */ if(dnssec) { zdb_query_ex_answer_append_type_rrsigs(rr_label, qname, type, PASS_ZCLASS_PARAMETER answer->ttl, &ans_auth_add->answer, pool); if(IS_WILD_LABEL(rr_label->name)) { /** * If there is a wildcard match for QNAME and QTYPE, then, in addition * to the expanded wildcard RRSet returned in the answer section of the * response, proof that the wildcard match was valid must be returned. * * This proof is accomplished by proving that both QNAME does not exist * and that the closest encloser of the QNAME and the immediate ancestor * of the wildcard are the same (i.e., the correct wildcard matched). * * To this end, the NSEC3 RR that covers the "next closer" name of the * immediate ancestor of the wildcard MUST be returned. * It is not necessary to return an NSEC3 RR that matches the closest * encloser, as the existence of this closest encloser is proven by * the presence of the expanded wildcard in the response. */ #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { zdb_query_ex_append_wild_nsec3_data(zone, rr_label, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add->authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* add the NSEC of the wildcard and its signature(s) */ zdb_query_ex_add_nsec_interval(zone, &name, NULL, &ans_auth_add->authority, pool); } #endif } } #endif /* * if authority required */ if(authority_required) { if((type == TYPE_NSEC || type == TYPE_DS) && (rr_label_info.authority != zone->apex)) { rr_label_info.authority = zone->apex; rr_label_info.authority_index = sp - 1; } zdb_packed_ttlrdata* authority = append_authority(qname, PASS_ZCLASS_PARAMETER &rr_label_info, &ans_auth_add->authority, pool, dnssec); if(additionals_required) { update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, &additionals_dname_set); } } /* * fetch all the additional records for the required type (NS and MX types) * add them to the additional section */ if(additionals_required) { update_additionals_dname_set(answer, PASS_ZCLASS_PARAMETER type, &additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add->additional, pool, dnssec); } /* resolve authority */ } #if DEBUG log_debug("zdb-query-cname: FP_BASIC_RECORD_FOUND"); #endif UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_BASIC_RECORD_FOUND; } /* if found the record of the requested type */ else { /* label but no record */ /** * Got the label, but not the record. * This should branch to NSEC3 if it is supported. */ ya_result ret = zdb_query_ex_record_not_found(zone, &rr_label_info, qname, &name, sp, top, type, PASS_ZCLASS_PARAMETER pool, dnssec, ans_auth_add, &additionals_dname_set); #if DEBUG log_debug("zdb-query-cname: FP_BASIC_RECORD_NOTFOUND (done)"); #endif UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return (finger_print)ret; } } else /* We got the label BUT type == TYPE_ANY */ { if(zdb_rr_label_flag_isclear(rr_label, ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION)) { zdb_packed_ttlrdata *soa = NULL; #if ZDB_HAS_DNSSEC_SUPPORT zdb_packed_ttlrdata *rrsig_list = zdb_record_find(&rr_label->resource_record_set, TYPE_RRSIG); #endif bool answers = FALSE; /* We do iterate on ALL the types of the label */ btree_iterator iter; btree_iterator_init(rr_label->resource_record_set, &iter); while(btree_iterator_hasnext(&iter)) { btree_node* nodep = btree_iterator_next_node(&iter); u16 type = nodep->hash; answers = TRUE; zdb_packed_ttlrdata* ttlrdata = (zdb_packed_ttlrdata*)nodep->data; /** * @note: doing the list once may be faster ... * And YES maybe, because of the jump and because the list is supposed to * be VERY small (like 1-3) */ switch(type) { case TYPE_SOA: { soa = ttlrdata; continue; } case TYPE_NS: { /* NO NEED FOR AUTHORITY */ authority_required = FALSE; } FALLTHROUGH // fall through case TYPE_MX: case TYPE_CNAME: { /* ADD MX "A/AAAA/GLUE" TO ADDITIONAL */ if(additionals_required) { update_additionals_dname_set(ttlrdata, PASS_ZCLASS_PARAMETER type, &additionals_dname_set); } break; } case TYPE_RRSIG: { // signatures will be added by type continue; } default: { break; } } zdb_query_ex_answer_appendrndlist(ttlrdata, qname, PASS_ZCLASS_PARAMETER type, &ans_auth_add->answer, pool); #if ZDB_HAS_DNSSEC_SUPPORT if(rrsig_list != NULL) { zdb_query_ex_answer_append_type_rrsigs_from(rrsig_list, qname, type, PASS_ZCLASS_PARAMETER ttlrdata->ttl, &ans_auth_add->answer, pool); } #endif } /* now we can insert the soa, if any has been found, at the head of the list */ if(soa != NULL) { zdb_resourcerecord* soa_rr = zdb_query_ex_answer_make(soa, qname, PASS_ZCLASS_PARAMETER TYPE_SOA, pool); soa_rr->next = ans_auth_add->answer; ans_auth_add->answer = soa_rr; #if ZDB_HAS_DNSSEC_SUPPORT if(rrsig_list != NULL) { zdb_query_ex_answer_append_type_rrsigs_from(rrsig_list, qname, TYPE_SOA, PASS_ZCLASS_PARAMETER soa_rr->ttl, &ans_auth_add->answer, pool); } #endif } if(answers) { if(authority_required) { // not at or under a delegation zdb_packed_ttlrdata* authority = append_authority(qname, PASS_ZCLASS_PARAMETER &rr_label_info, &ans_auth_add->authority, pool, dnssec); if(additionals_required) { update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, &additionals_dname_set); } } /* if authority required */ if(additionals_required) { append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add->additional, pool, dnssec); } #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec && IS_WILD_LABEL(rr_label->name)) { /** * If there is a wildcard match for QNAME and QTYPE, then, in addition * to the expanded wildcard RRSet returned in the answer section of the * response, proof that the wildcard match was valid must be returned. * * This proof is accomplished by proving that both QNAME does not exist * and that the closest encloser of the QNAME and the immediate ancestor * of the wildcard are the same (i.e., the correct wildcard matched). * * To this end, the NSEC3 RR that covers the "next closer" name of the * immediate ancestor of the wildcard MUST be returned. * It is not necessary to return an NSEC3 RR that matches the closest * encloser, as the existence of this closest encloser is proven by * the presence of the expanded wildcard in the response. */ #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { zdb_query_ex_append_wild_nsec3_data(zone, rr_label, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add->authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* add the NSEC of the wildcard and its signature(s) */ zdb_query_ex_add_nsec_interval(zone, &name, NULL, &ans_auth_add->authority, pool); } #endif // ZDB_HAS_NSEC_SUPPORT } #endif // ZDB_HAS_DNSSEC_SUPPORT #if DEBUG log_debug("zdb-query-cname: FP_BASIC_RECORD_FOUND (any)"); #endif UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_BASIC_RECORD_FOUND; } else { /* no records found ... */ ya_result ret = zdb_query_ex_record_not_found(zone, &rr_label_info, qname, &name, sp, top, TYPE_ANY, PASS_ZCLASS_PARAMETER pool, dnssec, ans_auth_add, &additionals_dname_set); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return (finger_print)ret; } } else { /* ANY, at or under a delegation */ zdb_query_ex_record_not_found(zone, &rr_label_info, qname, &name, sp, top, 0, PASS_ZCLASS_PARAMETER pool, dnssec, ans_auth_add, &additionals_dname_set); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_BASIC_RECORD_FOUND; } } } /* end of if rr_label != NULL => */ else /* rr_label == NULL */ { zdb_rr_label* rr_label_authority = rr_label_info.authority; if(rr_label_authority != zone->apex) { message_disable_authoritative(mesg); zdb_packed_ttlrdata *authority = zdb_record_find(&rr_label_authority->resource_record_set, TYPE_NS); if(authority != NULL) { const u8 * authority_qname = zdb_rr_label_info_get_authority_qname(qname, &rr_label_info); zdb_query_ex_answer_appendrndlist(authority, authority_qname, PASS_ZCLASS_PARAMETER TYPE_NS, &ans_auth_add->authority, pool); update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, &additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add->additional, pool, FALSE); if(dnssec) { #if ZDB_HAS_DNSSEC_SUPPORT zdb_query_ex_answer_append_type_rrsigs(rr_label_authority, authority_qname, TYPE_NS, PASS_ZCLASS_PARAMETER authority->ttl, &ans_auth_add->authority, pool); #endif zdb_packed_ttlrdata *delegation_signer = zdb_record_find(&rr_label_authority->resource_record_set, TYPE_DS); if(delegation_signer != NULL) { zdb_query_ex_answer_appendlist(delegation_signer , authority_qname, PASS_ZCLASS_PARAMETER TYPE_DS, &ans_auth_add->authority, pool); #if ZDB_HAS_DNSSEC_SUPPORT zdb_query_ex_answer_append_type_rrsigs(rr_label_authority, authority_qname, TYPE_DS, PASS_ZCLASS_PARAMETER delegation_signer->ttl, &ans_auth_add->authority, pool); #endif } else { #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { // add ... ? it looks like the record that covers the path that has been found in the zone // is used for the digest, then the interval is shown // add apex NSEC3 (wildcard) zdb_query_ex_append_nsec3_delegation(zone, &rr_label_info, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add->authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* * Append the NSEC of rr_label and all its signatures */ s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_query_ex_append_nsec_records(rr_label_authority, authority_qname, min_ttl, PASS_ZCLASS_PARAMETER &ans_auth_add->authority, pool); } #endif // ZDB_HAS_NSEC_SUPPORT } } ans_auth_add->delegation = 1; // no answer, NS records in authority : referral #if DEBUG log_debug("zdb-query-cname: FP_BASIC_LABEL_NOTFOUND (done)"); #endif /* ans_auth_add->is_delegation = TRUE; later */ UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_BASIC_LABEL_DELEGATION; } } else { message_set_authoritative(mesg); } } /* LABEL NOT FOUND: We stop the processing and fall through NSEC(3) or the basic case. */ UNLOCK(zone); /* Stop looking, skip cache */ break; } /* if(zone!=NULL) */ sp--; } /* while ... */ if(outside_of_zone) { zdb_unlock(db, ZDB_MUTEX_READER); return FP_RCODE_NOERROR; } /************************************************* * * * At this point we are not an authority anymore. * * * *************************************************/ /*if(authority_required) { */ /* * Get the most relevant label (lowest zone). * Try to do NSEC3 or NSEC with it. */ zdb_zone* zone; #if DEBUG zone = (zdb_zone*)~0; #endif sp = top; // top >= 0, so we can enter here and zone is assigned yassert(sp >= 0); while(sp >= 0) // scan-build false positive: we ALWAYS get into this loop at least once { zdb_zone_label* zone_label = zone_label_stack[sp--]; if((zone = zone_label->zone) != NULL) // scan-build false positive: one alleged error relies on this being both NULL and not NULL at the same time (with zone_label_stack[sp=0]). { /* if type == DS && zone->origin = qname then the return value is NOERROR instead of NXDOMAIN */ break; } } if(zone == NULL) // zone is ALWAYS assigned because top is >= 0 (several false-positive) { #if DEBUG log_debug("zdb-query-cname: FP_NOZONE_FOUND (2)"); #endif // ??? zone_pointer_out->apex->flags |= ZDB_RR_LABEL_MASTER_OF; zdb_unlock(db, ZDB_MUTEX_READER); return FP_NOZONE_FOUND; } LOCK(zone); if(!zdb_zone_invalid(zone)) { // zone is the most relevant zone #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec) { #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { //nsec3_zone *n3 = zone->nsec.nsec3; u8 *next_closer_owner = NULL; zdb_packed_ttlrdata* next_closer; const zdb_packed_ttlrdata* next_closer_rrsig; u8 *closer_encloser_owner = NULL; zdb_packed_ttlrdata* closer_encloser; const zdb_packed_ttlrdata* closer_encloser_rrsig; u8 *wild_closer_encloser_owner = NULL; zdb_packed_ttlrdata* wild_closer_encloser; const zdb_packed_ttlrdata* wild_closer_encloser_rrsig; #if DEBUG log_debug("nsec3_name_error"); #endif nsec3_name_error( zone, &name, top, pool, &next_closer_owner, &next_closer, &next_closer_rrsig, &closer_encloser_owner, &closer_encloser, &closer_encloser_rrsig, &wild_closer_encloser_owner, &wild_closer_encloser, &wild_closer_encloser_rrsig); s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_query_ex_answer_append_soa_rrsig_nttl(zone, &ans_auth_add->authority, pool); #if DEBUG log_debug("zdb-query-cname: nsec3_name_error: next_closer_owner: %{dnsname}", next_closer_owner); #endif if(next_closer != NULL /*&& next_closer_rrsig != NULL*/) { zdb_query_ex_answer_append_ttl(next_closer, next_closer_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, &ans_auth_add->authority, pool); if(next_closer_rrsig != NULL) { zdb_query_ex_answer_appendlist_ttl(next_closer_rrsig, next_closer_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, &ans_auth_add->authority, pool); } } if(closer_encloser != NULL/* && closer_encloser_rrsig != NULL*/) { #if DEBUG log_debug("zdb-query-cname: nsec3_name_error: closer_encloser_owner: %{dnsname}", closer_encloser_owner); #endif zdb_query_ex_answer_append_ttl(closer_encloser, closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, &ans_auth_add->authority, pool); if(closer_encloser_rrsig != NULL) { zdb_query_ex_answer_appendlist_ttl(closer_encloser_rrsig, closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, &ans_auth_add->authority, pool); } } if(wild_closer_encloser != NULL) { #if DEBUG log_debug("zdb-query-cname: nsec3_name_error: wild_closer_encloser_owner: %{dnsname}", wild_closer_encloser_owner); #endif zdb_query_ex_answer_append_ttl(wild_closer_encloser, wild_closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, &ans_auth_add->authority, pool); if(wild_closer_encloser_rrsig != NULL) { zdb_query_ex_answer_appendlist_ttl(wild_closer_encloser_rrsig, wild_closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, &ans_auth_add->authority, pool); } } #if DEBUG log_debug("zdb-query-cname: FP_NSEC3_LABEL_NOTFOUND (done)"); #endif UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_NSEC3_LABEL_NOTFOUND; } #endif /* ZDB_HAS_NSEC3_SUPPORT != 0 */ /* NSEC, if possible */ #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else /* Following will be either the NSEC answer or just the SOA added in the authority */ #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* * Unknown and not in the cache : NSEC * */ /* * zone label stack * * #0 : top * #1 : com, org, ... * #2 : example, ... * * Which is the inverse of the dnslabel stack * * dnslabel stack * * #0 : example * #1 : com * #2 : NOTHING ("." is not stored) * * */ /* * Get the SOA + NSEC + RRIGs for the zone */ //zdb_rr_label *apex_label = zone->apex; zdb_query_ex_answer_append_soa_rrsig_nttl(zone, &ans_auth_add->authority, pool); u8 *encloser_nsec_name = NULL; u8 *wild_encloser_nsec_name = NULL; zdb_rr_label *encloser_nsec_label; zdb_rr_label *wildencloser_nsec_label; nsec_name_error(zone, &name, rr_label_info.closest_index, // scan-build (7) false positive: the path allegedly leading here lies on an incoherence (VS false positive too) pool, &encloser_nsec_name, &encloser_nsec_label, &wild_encloser_nsec_name, &wildencloser_nsec_label); if(encloser_nsec_label != NULL) { zdb_packed_ttlrdata *encloser_nsec_rr = zdb_record_find(&encloser_nsec_label->resource_record_set, TYPE_NSEC); if(encloser_nsec_rr != NULL) { zdb_query_ex_answer_append(encloser_nsec_rr, encloser_nsec_name, DECLARE_ZCLASS_PARAMETER TYPE_NSEC, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(encloser_nsec_label, encloser_nsec_name, TYPE_NSEC, DECLARE_ZCLASS_PARAMETER encloser_nsec_rr->ttl, &ans_auth_add->authority, pool); if(wildencloser_nsec_label != encloser_nsec_label) { zdb_packed_ttlrdata *wildencloser_nsec_rr = zdb_record_find(&wildencloser_nsec_label->resource_record_set, TYPE_NSEC); if(wildencloser_nsec_rr != NULL) { zdb_query_ex_answer_append(wildencloser_nsec_rr, wild_encloser_nsec_name, DECLARE_ZCLASS_PARAMETER TYPE_NSEC, &ans_auth_add->authority, pool); zdb_query_ex_answer_append_type_rrsigs(wildencloser_nsec_label, wild_encloser_nsec_name, TYPE_NSEC, DECLARE_ZCLASS_PARAMETER wildencloser_nsec_rr->ttl, &ans_auth_add->authority, pool); } } } } #if DEBUG log_debug("zdb-query-cname: FP_NSEC_LABEL_NOTFOUND (done)"); #endif UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_NSEC_LABEL_NOTFOUND; } #endif // ZDB_HAS_NSEC_SUPPORT } #endif // ZDB_HAS_DNSSEC_SUPPORT zdb_query_ex_answer_append_soa_nttl(zone, &ans_auth_add->authority, pool); #if DEBUG log_debug("zdb-query-cname: FP_BASIC_LABEL_NOTFOUND (done)"); #endif UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_BASIC_LABEL_NOTFOUND; } else // if(!zdb_zone_invalid(zone)) { #if DEBUG log_debug("zdb-query-cname: FP_ZONE_EXPIRED (2)"); #endif UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return FP_INVALID_ZONE; } } /** * @brief Queries the database given a message * * @param db the database * @param mesg the message * @param pool_buffer a big enough buffer used for the memory pool * * @return the status of the message (probably useless) */ void zdb_query_and_update(zdb *db, message_data *mesg, u8 * restrict pool_buffer) { zdb_query_ex_answer ans_auth_add; const u8 *qname = message_get_canonised_fqdn(mesg); #if ZDB_RECORDS_MAX_CLASS != 1 const u16 zclass = message_get_query_class(mesg); #endif zdb_rr_label_find_ext_data rr_label_info; u16 type = message_get_query_type(mesg); const process_flags_t flags = zdb_query_process_flags; /** Check that we are even allowed to handle that class */ #if ZDB_RECORDS_MAX_CLASS == 1 if(message_get_query_class(mesg) != CLASS_IN) { #if DEBUG log_debug("zdb_query_and_update: FP_CLASS_NOTFOUND"); #endif return; // FP_CLASS_NOTFOUND; } zdb_query_ex_answer_create(&ans_auth_add); #endif #if ZDB_RECORDS_MAX_CLASS != 1 u16 host_zclass = ntohs(zclass); /* no choice */ if(host_zclass > ZDB_RECORDS_MAX_CLASS) { return; // FP_CLASS_NOTFOUND; } #endif bool dnssec = message_has_rcode_ext_dnssec(mesg); /** * MANDATORY, INITIALISES A LOCAL MEMORY POOL * * This is actually a macro found in dnsname_set.h */ dnsname_vector name; DEBUG_RESET_dnsname(name); dnsname_to_dnsname_vector(qname, &name); u8 * restrict * pool = &pool_buffer; /* * Find closest matching label * Should return a stack of zones */ zdb_zone_label_pointer_array zone_label_stack; zdb_lock(db, ZDB_MUTEX_READER); s32 top = zdb_zone_label_match(db, &name, zone_label_stack); s32 sp = top; zdb_packed_ttlrdata* answer; /* This flag means that there HAS to be an authority section */ bool authority_required = flags & PROCESS_FL_AUTHORITY_AUTH; /* This flag means the names in the authority must be (internally) resolved if possible */ bool additionals_required = flags & PROCESS_FL_ADDITIONAL_AUTH; switch(type) { case TYPE_DNSKEY: { authority_required = FALSE; additionals_required = FALSE; break; } } /* Got a stack of zone labels with and without zone cuts */ /* Search the label on the zone files */ /* While we have labels along the path */ if(type == TYPE_DS) // This is the only type that can only be found outside of the zone { // In order to avoid to hit said zone, I skip the last label. if(name.size == sp - 1) // we have a perfect match (DS for an APEX), try to get outside ... { s32 parent_sp = sp; while(--parent_sp >= 0) { /* Get the "bottom" label (top being ".") */ zdb_zone_label* zone_label = zone_label_stack[parent_sp]; /* Is there a zone file at this level ? If yes, search into it. */ if(zone_label->zone != NULL) { // got it. sp = parent_sp; message_set_authoritative_answer(mesg); break; } } authority_required = FALSE; } } while(sp >= 0) { /* Get the "bottom" label (top being ".") */ zdb_zone_label* zone_label = zone_label_stack[sp]; /* Is there a zone file at this level ? If yes, search into it. */ if(zone_label->zone != NULL) { zdb_zone *zone = zone_label->zone; /* * lock */ LOCK(zone); #if DEBUG log_debug("zdb_query_and_update: zone %{dnsname}, flags=%x", zone->origin, zdb_rr_label_flag_get(zone->apex)); #endif /* * We know the zone, and its extension here ... */ { /* * Filter handling (ACL) * NOTE: the return code has to be fingerprint-based */ if(FAIL(zone->query_access_filter(mesg, zone->acl))) { #if DEBUG log_debug("zdb_query_and_update: FP_ACCESS_REJECTED"); #endif message_set_status(mesg, FP_ACCESS_REJECTED); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return; // FP_ACCESS_REJECTED; } } /** * The ACL have been passed so ... now check that the zone is valid */ if(zdb_zone_invalid(zone)) { /** * @note the blocks could be reversed and jump if the zone is invalid (help the branch prediction) */ #if DEBUG log_debug("zdb_query_and_update: FP_INVALID_ZONE"); #endif message_set_status(mesg, FP_INVALID_ZONE); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return; // FP_INVALID_ZONE; } //message_set_authoritative(mesg); dnsname_set additionals_dname_set; dnsname_set_init(&additionals_dname_set); /* * In one query, get the authority and the closest (longest) path to the domain we are looking for. */ zdb_rr_label *rr_label = zdb_rr_label_find_ext(zone->apex, name.labels, name.size - sp, &rr_label_info); /* Has a label been found ? */ if(rr_label != NULL) { /* * Got the label. I will not find anything relevant by going * up to another zone file. * * We set the AA bit iff we are not at or under a delegation. * * The ZDB_RR_LABEL_DELEGATION flag means the label is a delegation. * This means that it only contains NS & DNSSEC records + may have sub-labels for glues * * ZDB_RR_LABEL_UNDERDELEGATION means we are below a ZDB_RR_LABEL_DELEGATION label * */ /* * CNAME alias handling */ if(((zdb_rr_label_flag_get(rr_label) & (ZDB_RR_LABEL_HASCNAME|ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION)) == ZDB_RR_LABEL_HASCNAME) && (type != TYPE_CNAME) && (type != TYPE_ANY) && (type != TYPE_RRSIG)) { /* * The label is an alias: * * Add the CNAME and restart the query from the alias */ if(ans_auth_add.depth >= ZDB_CNAME_LOOP_MAX) { log_warn("CNAME depth at %{dnsname} is bigger than allowed %d>=%d", qname, ans_auth_add.depth, ZDB_CNAME_LOOP_MAX); message_set_authoritative(mesg); message_set_status(mesg, FP_CNAME_MAXIMUM_DEPTH); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return; // FP_CNAME_MAXIMUM_DEPTH; } ans_auth_add.depth++; if((answer = zdb_record_find(&rr_label->resource_record_set, TYPE_CNAME)) != NULL) { /* The RDATA in answer is the fqdn to a label with an A record (list) */ /* There can only be one cname for a given owner */ /* Append all A/AAAA records associated to the CNAME AFTER the CNAME record */ zdb_resourcerecord *rr = ans_auth_add.answer; u32 cname_depth_count = 0; /* I don't want to allocate that globally for now */ while(rr != NULL) { if((rr->rtype == TYPE_CNAME) && (ZDB_PACKEDRECORD_PTR_RDATAPTR(rr->ttl_rdata) == ZDB_PACKEDRECORD_PTR_RDATAPTR(answer))) { /* LOOP */ log_warn("CNAME loop at %{dnsname}", qname); message_set_authoritative(mesg); message_set_status(mesg, FP_CNAME_LOOP); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return; // FP_CNAME_LOOP; } cname_depth_count++; rr = rr->next; } u8* cname_owner = *pool; *pool += ALIGN16(dnsname_copy(*pool, qname)); /* ONE record */ zdb_query_ex_answer_append(answer, cname_owner, PASS_ZCLASS_PARAMETER TYPE_CNAME, &ans_auth_add.answer, pool); #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec) { zdb_query_ex_answer_append_type_rrsigs(rr_label, cname_owner, TYPE_CNAME, PASS_ZCLASS_PARAMETER answer->ttl, &ans_auth_add.answer, pool); } #endif message_set_canonised_fqdn(mesg, ZDB_PACKEDRECORD_PTR_RDATAPTR(answer)); finger_print fp = zdb_query_from_cname(db, mesg, &ans_auth_add, zone, pool_buffer); message_set_authoritative(mesg); /// @note 20200520 EDF -- flag missing in the test message_set_status(mesg, fp); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return; // fp; } else { /* * We expected a CNAME record but found none. * This is NOT supposed to happen. * */ message_set_status(mesg, FP_CNAME_BROKEN); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return; // FP_CNAME_BROKEN; } } if(zdb_rr_label_flag_isclear(rr_label, (ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION) )) { message_set_authoritative(mesg); authority_required = FALSE; } else { /* * we are AT or UNDER a delegation * We can only find (show) NS, DS, RRSIG, NSEC records from the query * * The answer WILL be a referral ... */ switch(type) { /* for these ones : give the rrset for the type and clear AA */ case TYPE_DS: { if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { message_set_authoritative(mesg); } else if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_UNDERDELEGATION)) { message_disable_authoritative(mesg); } ans_auth_add.delegation = 1; authority_required = FALSE; break; } case TYPE_NSEC: { if(zdb_rr_label_flag_isclear(rr_label, ZDB_RR_LABEL_UNDERDELEGATION)) { message_set_authoritative(mesg); } break; } /* for these ones : give the rrset for the type */ case TYPE_NS: ans_auth_add.delegation = 1; break; /* for this one : present the delegation */ case TYPE_ANY: ans_auth_add.delegation = 1; authority_required = FALSE; break; /* for the rest : NSEC ? */ default: ans_auth_add.delegation = 1; /* * do not try to look for it * * faster: go to label but no record, but let's avoid gotos ... */ type = 0; break; } } /* * First let's handle "simple" cases. ANY will be handled in another part of the code. */ if(type != TYPE_ANY) { /* * From the label that has been found, get the RRSET for the required type (zdb_packed_ttlrdata*) */ if((answer = zdb_record_find(&rr_label->resource_record_set, type)) != NULL) { /* A match has been found */ /* NS case */ if(type == TYPE_NS) { zdb_resourcerecord **section; /* * If the label is a delegation, the NS have to be added into authority, * else they have to be added into answer. * */ if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { section = &ans_auth_add.authority; /* ans_auth_add.is_delegation = TRUE; later */ } else { section = &ans_auth_add.answer; } /* * Add the NS records in random order in the right section * */ zdb_query_ex_answer_appendrndlist(answer, qname, PASS_ZCLASS_PARAMETER type, section, pool); #if ZDB_HAS_DNSSEC_SUPPORT /* * Append all the RRSIG of NS from the label */ if(dnssec && zdb_zone_is_dnssec(zone)) { zdb_query_ex_answer_append_type_rrsigs(rr_label, qname, TYPE_NS, PASS_ZCLASS_PARAMETER answer->ttl, section, pool); if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { zdb_packed_ttlrdata* label_ds = zdb_record_find(&rr_label->resource_record_set, TYPE_DS); if(label_ds != NULL) { zdb_query_ex_answer_appendlist(label_ds, qname, PASS_ZCLASS_PARAMETER TYPE_DS, &ans_auth_add.authority, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label, qname, TYPE_DS, PASS_ZCLASS_PARAMETER label_ds->ttl, &ans_auth_add.authority, pool); } #if ZDB_HAS_NSEC3_SUPPORT else if(ZONE_NSEC3_AVAILABLE(zone)) { /** * If there is an NSEC3 RR that matches the delegation name, then that * NSEC3 RR MUST be included in the response. The DS bit in the type * bit maps of the NSEC3 RR MUST NOT be set. * * If the zone is Opt-Out, then there may not be an NSEC3 RR * corresponding to the delegation. In this case, the closest provable * encloser proof MUST be included in the response. The included NSEC3 * RR that covers the "next closer" name for the delegation MUST have * the Opt-Out flag set to one. (Note that this will be the case unless * something has gone wrong). * */ zdb_query_ex_append_nsec3_delegation(zone, &rr_label_info, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT else if(ZONE_NSEC_AVAILABLE(zone)) { /* * Append the NSEC of rr_label and all its signatures */ s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_query_ex_append_nsec_records(rr_label, qname, min_ttl, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif } } #endif /* * authority is never required since we have it already * */ /* * fetch all the additional records for the required type (NS and MX types) * add them to the additional section */ if(additionals_required) { update_additionals_dname_set(answer, PASS_ZCLASS_PARAMETER type, &additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add.additional, pool, dnssec); } } else /* general case */ { /* * Add the records from the answer in random order to the answer section */ zdb_query_ex_answer_appendrndlist(answer, qname, PASS_ZCLASS_PARAMETER type, &ans_auth_add.answer, pool); #if ZDB_HAS_DNSSEC_SUPPORT /* * Append all the RRSIG of NS from the label */ if(dnssec && zdb_zone_is_dnssec(zone)) { zdb_query_ex_answer_append_type_rrsigs(rr_label, qname, type, PASS_ZCLASS_PARAMETER answer->ttl, &ans_auth_add.answer, pool); if(IS_WILD_LABEL(rr_label->name)) { /** * If there is a wildcard match for QNAME and QTYPE, then, in addition * to the expanded wildcard RRSet returned in the answer section of the * response, proof that the wildcard match was valid must be returned. * * This proof is accomplished by proving that both QNAME does not exist * and that the closest encloser of the QNAME and the immediate ancestor * of the wildcard are the same (i.e., the correct wildcard matched). * * To this end, the NSEC3 RR that covers the "next closer" name of the * immediate ancestor of the wildcard MUST be returned. * It is not necessary to return an NSEC3 RR that matches the closest * encloser, as the existence of this closest encloser is proven by * the presence of the expanded wildcard in the response. */ #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { zdb_query_ex_append_wild_nsec3_data(zone, rr_label, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* add the NSEC of the wildcard and its signature(s) */ zdb_query_ex_add_nsec_interval(zone, &name, NULL, &ans_auth_add.authority, pool); } #endif } } #endif /* * if authority required */ if(authority_required) { if((type == TYPE_NSEC || type == TYPE_DS) && (rr_label_info.authority != zone->apex)) { rr_label_info.authority = zone->apex; rr_label_info.authority_index = sp - 1; } zdb_packed_ttlrdata* authority = append_authority(qname, PASS_ZCLASS_PARAMETER &rr_label_info, &ans_auth_add.authority, pool, dnssec); if(additionals_required) { update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, &additionals_dname_set); } } /* * fetch all the additional records for the required type (NS and MX types) * add them to the additional section */ if(additionals_required) { update_additionals_dname_set(answer, PASS_ZCLASS_PARAMETER type, &additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add.additional, pool, dnssec); } /* resolve authority */ } #if DEBUG log_debug("zdb_query_and_update: FP_BASIC_RECORD_FOUND"); #endif message_set_status(mesg, FP_BASIC_RECORD_FOUND); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return; // FP_BASIC_RECORD_FOUND; } /* if found the record of the requested type */ else { /* label but no record */ /** * Got the label, but not the record. * This should branch to NSEC3 if it is supported. */ finger_print fp; #if ENFORCE_MINTTL fp = (finger_print)zdb_query_ex_record_not_found_nttl(zone, &rr_label_info, qname, &name, sp, top, type, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); #else if(ZONE_NSEC_AVAILABLE(zone) || ZONE_NSEC3_AVAILABLE(zone)) { fp = (finger_print)zdb_query_ex_record_not_found_nttl(zone, &rr_label_info, qname, &name, sp, top, type, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); } else { fp = (finger_print)zdb_query_ex_record_not_found(zone, &rr_label_info, qname, &name, sp, top, type, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); } #endif #if DEBUG log_debug("zdb_query_and_update: FP_BASIC_RECORD_NOTFOUND (done)"); #endif message_set_status(mesg, fp); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return; // (finger_print)return_value; } } else /* We got the label BUT type == TYPE_ANY */ { if(zdb_rr_label_flag_isclear(rr_label, (ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION) )) { zdb_packed_ttlrdata *soa = NULL; #if ZDB_HAS_DNSSEC_SUPPORT zdb_packed_ttlrdata *rrsig_list = zdb_record_find(&rr_label->resource_record_set, TYPE_RRSIG); #endif bool answers = FALSE; /* We do iterate on ALL the types of the label */ btree_iterator iter; btree_iterator_init(rr_label->resource_record_set, &iter); while(btree_iterator_hasnext(&iter)) { btree_node* nodep = btree_iterator_next_node(&iter); u16 type = nodep->hash; answers = TRUE; zdb_packed_ttlrdata* ttlrdata = (zdb_packed_ttlrdata*)nodep->data; /** * @note: doing the list once may be faster ... * And YES maybe, because of the jump and because the list is supposed to * be VERY small (like 1-3) */ switch(type) { case TYPE_SOA: { soa = ttlrdata; continue; } case TYPE_NS: { /* NO NEED FOR AUTHORITY */ authority_required = FALSE; } FALLTHROUGH // fall through case TYPE_MX: case TYPE_CNAME: { /* ADD MX "A/AAAA/GLUE" TO ADDITIONAL */ if(additionals_required) { update_additionals_dname_set(ttlrdata, PASS_ZCLASS_PARAMETER type, &additionals_dname_set); } break; } case TYPE_RRSIG: { // signatures will be added by type continue; } default: { break; } } zdb_query_ex_answer_appendrndlist(ttlrdata, qname, PASS_ZCLASS_PARAMETER type, &ans_auth_add.answer, pool); #if ZDB_HAS_DNSSEC_SUPPORT if(rrsig_list != NULL) { zdb_query_ex_answer_append_type_rrsigs_from(rrsig_list, qname, type, PASS_ZCLASS_PARAMETER ttlrdata->ttl, &ans_auth_add.answer, pool); } #endif } /* now we can insert the soa, if any has been found, at the head of the list */ if(soa != NULL) { zdb_resourcerecord* soa_rr = zdb_query_ex_answer_make(soa, qname, PASS_ZCLASS_PARAMETER TYPE_SOA, pool); soa_rr->next = ans_auth_add.answer; ans_auth_add.answer = soa_rr; #if ZDB_HAS_DNSSEC_SUPPORT if(rrsig_list != NULL) { zdb_query_ex_answer_append_type_rrsigs_from(rrsig_list, qname, TYPE_SOA, PASS_ZCLASS_PARAMETER soa_rr->ttl, &ans_auth_add.answer, pool); } #endif } if(answers) { if(authority_required) { // not at or under a delegation zdb_packed_ttlrdata* authority = append_authority(qname, PASS_ZCLASS_PARAMETER &rr_label_info, &ans_auth_add.authority, pool, dnssec); if(additionals_required) { update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, &additionals_dname_set); } } /* if authority required */ if(additionals_required) { append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add.additional, pool, dnssec); } #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec && IS_WILD_LABEL(rr_label->name)) { /** * If there is a wildcard match for QNAME and QTYPE, then, in addition * to the expanded wildcard RRSet returned in the answer section of the * response, proof that the wildcard match was valid must be returned. * * This proof is accomplished by proving that both QNAME does not exist * and that the closest encloser of the QNAME and the immediate ancestor * of the wildcard are the same (i.e., the correct wildcard matched). * * To this end, the NSEC3 RR that covers the "next closer" name of the * immediate ancestor of the wildcard MUST be returned. * It is not necessary to return an NSEC3 RR that matches the closest * encloser, as the existence of this closest encloser is proven by * the presence of the expanded wildcard in the response. */ #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { zdb_query_ex_append_wild_nsec3_data(zone, rr_label, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* add the NSEC of the wildcard and its signature(s) */ zdb_query_ex_add_nsec_interval(zone, &name, NULL, &ans_auth_add.authority, pool); } #endif } #endif // ZDB_HAS_DNSSEC_SUPPORT #if DEBUG log_debug("zdb_query_and_update: FP_BASIC_RECORD_FOUND (any)"); #endif message_set_status(mesg, FP_BASIC_RECORD_FOUND); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return; // FP_BASIC_RECORD_FOUND; } else { /* no records found ... */ finger_print fp; if(ZONE_NSEC_AVAILABLE(zone) || ZONE_NSEC3_AVAILABLE(zone)) { fp = (finger_print)zdb_query_ex_record_not_found_nttl(zone, &rr_label_info, qname, &name, sp, top, TYPE_ANY, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); } else { fp = (finger_print)zdb_query_ex_record_not_found(zone, &rr_label_info, qname, &name, sp, top, TYPE_ANY, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); } message_set_status(mesg, fp); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return; // fp; } } else { /* ANY, at or under a delegation */ zdb_query_ex_record_not_found(zone, &rr_label_info, qname, &name, sp, top, 0, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); message_set_status(mesg, FP_BASIC_RECORD_FOUND); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return; // FP_BASIC_RECORD_FOUND; } } } /* end of if rr_label!=NULL => */ else /* rr_label == NULL */ { zdb_rr_label* rr_label_authority = rr_label_info.authority; if(rr_label_authority != zone->apex) { message_disable_authoritative(mesg); zdb_packed_ttlrdata *authority = zdb_record_find(&rr_label_authority->resource_record_set, TYPE_NS); if(authority != NULL) { const u8 * authority_qname = zdb_rr_label_info_get_authority_qname(qname, &rr_label_info); zdb_query_ex_answer_appendrndlist(authority, authority_qname, PASS_ZCLASS_PARAMETER TYPE_NS, &ans_auth_add.authority, pool); update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, &additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add.additional, pool, FALSE); if(dnssec) { #if ZDB_HAS_DNSSEC_SUPPORT zdb_query_ex_answer_append_type_rrsigs(rr_label_authority, authority_qname, TYPE_NS, PASS_ZCLASS_PARAMETER authority->ttl, &ans_auth_add.authority, pool); #endif zdb_packed_ttlrdata *delegation_signer = zdb_record_find(&rr_label_authority->resource_record_set, TYPE_DS); if(delegation_signer != NULL) { zdb_query_ex_answer_appendlist(delegation_signer , authority_qname, PASS_ZCLASS_PARAMETER TYPE_DS, &ans_auth_add.authority, pool); #if ZDB_HAS_DNSSEC_SUPPORT zdb_query_ex_answer_append_type_rrsigs(rr_label_authority, authority_qname, TYPE_DS, PASS_ZCLASS_PARAMETER delegation_signer->ttl, &ans_auth_add.authority, pool); #endif } else { #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { // add ... ? it looks like the record that covers the path that has been found in the zone // is used for the digest, then the interval is shown // add apex NSEC3 (wildcard) zdb_query_ex_append_nsec3_delegation(zone, &rr_label_info, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* * Append the NSEC of rr_label and all its signatures */ s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_query_ex_append_nsec_records(rr_label_authority, authority_qname, min_ttl, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif } } ans_auth_add.delegation = 1; // no answer, NS records in authority : referral #if DEBUG log_debug("zdb_query_and_update: FP_BASIC_LABEL_NOTFOUND (done)"); #endif /* ans_auth_add.is_delegation = TRUE; later */ message_set_status(mesg, FP_BASIC_LABEL_DELEGATION); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return; // FP_BASIC_LABEL_DELEGATION; } } else { message_set_authoritative(mesg); } } /* LABEL NOT FOUND: We stop the processing and fall through NSEC(3) or the basic case. */ UNLOCK(zone); /* Stop looking, skip cache */ break; } /* if(zone!=NULL) */ sp--; } /* while ... */ /************************************************* * * * At this point we are not an authority anymore. * * * *************************************************/ /*if(authority_required) { */ /* * Get the most relevant label (lowest zone). * Try to do NSEC3 or NSEC with it. */ zdb_zone* zone; #if DEBUG zone = (zdb_zone*)~0; #endif sp = top; // top >= 0, so we can enter here and zone is assigned yassert(sp >= 0); while(sp >= 0) // scan-build false positive: we ALWAYS get into this loop at least once { zdb_zone_label* zone_label = zone_label_stack[sp--]; if((zone = zone_label->zone) != NULL) { /* if type == DS && zone->origin = qname then the return value is NOERROR instead of NXDOMAIN */ break; } } if(zone == NULL) // zone is ALWAYS assigned because top is >= 0 { #if DEBUG log_debug("zdb_query_and_update: FP_NOZONE_FOUND (2)"); #endif message_set_status(mesg, FP_NOZONE_FOUND); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); // ??? zone_pointer_out->apex->flags |= ZDB_RR_LABEL_MASTER_OF; zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return; // FP_NOZONE_FOUND; } LOCK(zone); if(!zdb_zone_invalid(zone)) { // zone is the most relevant zone #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec) { #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { //nsec3_zone *n3 = zone->nsec.nsec3; u8 *next_closer_owner = NULL; zdb_packed_ttlrdata* next_closer; const zdb_packed_ttlrdata* next_closer_rrsig; u8 *closer_encloser_owner = NULL; zdb_packed_ttlrdata* closer_encloser; const zdb_packed_ttlrdata* closer_encloser_rrsig; u8 *wild_closer_encloser_owner = NULL; zdb_packed_ttlrdata* wild_closer_encloser; const zdb_packed_ttlrdata* wild_closer_encloser_rrsig; #if DEBUG log_debug("nsec3_name_error"); #endif nsec3_name_error( zone, &name, top, pool, &next_closer_owner, &next_closer, &next_closer_rrsig, &closer_encloser_owner, &closer_encloser, &closer_encloser_rrsig, &wild_closer_encloser_owner, &wild_closer_encloser, &wild_closer_encloser_rrsig); s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_query_ex_answer_append_soa_rrsig_nttl(zone, &ans_auth_add.authority, pool); //zdb_query_ex_answer_append_soa_rrsig_ttl0(zone, &ans_auth_add.authority, pool); #if DEBUG log_debug("zdb_query_and_update: nsec3_name_error: next_closer_owner: %{dnsname}", next_closer_owner); #endif if(next_closer != NULL /*&& next_closer_rrsig != NULL*/) { zdb_query_ex_answer_append_ttl(next_closer, next_closer_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, &ans_auth_add.authority, pool); if(next_closer_rrsig != NULL) { zdb_query_ex_answer_appendlist_ttl(next_closer_rrsig, next_closer_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, &ans_auth_add.authority, pool); } } if(closer_encloser != NULL/* && closer_encloser_rrsig != NULL*/) { #if DEBUG log_debug("zdb_query_and_update: nsec3_name_error: closer_encloser_owner: %{dnsname}", closer_encloser_owner); #endif zdb_query_ex_answer_append_ttl(closer_encloser, closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, &ans_auth_add.authority, pool); if(closer_encloser_rrsig != NULL) { zdb_query_ex_answer_appendlist_ttl(closer_encloser_rrsig, closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, &ans_auth_add.authority, pool); } } if(wild_closer_encloser != NULL) { #if DEBUG log_debug("zdb_query_and_update: nsec3_name_error: wild_closer_encloser_owner: %{dnsname}", wild_closer_encloser_owner); #endif zdb_query_ex_answer_append_ttl(wild_closer_encloser, wild_closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, &ans_auth_add.authority, pool); if(wild_closer_encloser_rrsig != NULL) { zdb_query_ex_answer_appendlist_ttl(wild_closer_encloser_rrsig, wild_closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, &ans_auth_add.authority, pool); } } #if DEBUG log_debug("zdb_query_and_update: FP_NSEC3_LABEL_NOTFOUND (done)"); #endif message_set_status(mesg, FP_NSEC3_LABEL_NOTFOUND); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return; // FP_NSEC3_LABEL_NOTFOUND; } #endif /* ZDB_HAS_NSEC3_SUPPORT != 0 */ /* NSEC, if possible */ #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else /* Following will be either the NSEC answer or just the SOA added in the authority */ #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* * Unknown and not in the cache : NSEC * */ /* * zone label stack * * #0 : top * #1 : com, org, ... * #2 : example, ... * * Which is the inverse of the dnslabel stack * * dnslabel stack * * #0 : example * #1 : com * #2 : NOTHING ("." is not stored) * * */ /* * Get the SOA + NSEC + RRIGs for the zone */ //zdb_rr_label *apex_label = zone->apex; zdb_query_ex_answer_append_soa_rrsig_nttl(zone, &ans_auth_add.authority, pool); u8 *encloser_nsec_name = NULL; u8 *wild_encloser_nsec_name = NULL; zdb_rr_label *encloser_nsec_label; zdb_rr_label *wildencloser_nsec_label; nsec_name_error(zone, &name, rr_label_info.closest_index, // VS false positive: reaching this point, rr_label_info is initialized pool, &encloser_nsec_name, &encloser_nsec_label, &wild_encloser_nsec_name, &wildencloser_nsec_label); if(encloser_nsec_label != NULL) { zdb_packed_ttlrdata *encloser_nsec_rr = zdb_record_find(&encloser_nsec_label->resource_record_set, TYPE_NSEC); if(encloser_nsec_rr != NULL) { zdb_query_ex_answer_append(encloser_nsec_rr, encloser_nsec_name, DECLARE_ZCLASS_PARAMETER TYPE_NSEC, &ans_auth_add.authority, pool); zdb_query_ex_answer_append_type_rrsigs(encloser_nsec_label, encloser_nsec_name, TYPE_NSEC, DECLARE_ZCLASS_PARAMETER encloser_nsec_rr->ttl, &ans_auth_add.authority, pool); if(wildencloser_nsec_label != encloser_nsec_label) { zdb_packed_ttlrdata *wildencloser_nsec_rr = zdb_record_find(&wildencloser_nsec_label->resource_record_set, TYPE_NSEC); if(wildencloser_nsec_rr != NULL) { zdb_query_ex_answer_append(wildencloser_nsec_rr, wild_encloser_nsec_name, DECLARE_ZCLASS_PARAMETER TYPE_NSEC, &ans_auth_add.authority, pool); zdb_query_ex_answer_append_type_rrsigs(wildencloser_nsec_label, wild_encloser_nsec_name, TYPE_NSEC, DECLARE_ZCLASS_PARAMETER wildencloser_nsec_rr->ttl, &ans_auth_add.authority, pool); } } } } #if DEBUG log_debug("zdb_query_and_update: FP_NSEC_LABEL_NOTFOUND (done)"); #endif message_set_status(mesg, FP_NSEC_LABEL_NOTFOUND); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return; // FP_NSEC_LABEL_NOTFOUND; } #endif // ZDB_HAS_NSEC_SUPPORT } #endif // ZDB_HAS_DNSSEC_SUPPORT zdb_query_ex_answer_append_soa_nttl(zone, &ans_auth_add.authority, pool); #if DEBUG log_debug("zdb_query_and_update: FP_BASIC_LABEL_NOTFOUND (done)"); #endif message_set_status(mesg, FP_BASIC_LABEL_NOTFOUND); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return; // FP_BASIC_LABEL_NOTFOUND; } else // if(!zdb_zone_invalid(zone)) { #if DEBUG log_debug("zdb_query_and_update: FP_ZONE_EXPIRED (2)"); #endif message_set_status(mesg, FP_INVALID_ZONE); zdb_query_message_update(mesg, &ans_auth_add); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return; // FP_INVALID_ZONE; } } /** * @brief Queries the database given a message * * @param db the database * @param mesg the message * @param pool_buffer a big enough buffer used for the memory pool * * @return the status of the message (probably useless) */ ya_result zdb_query_and_update_with_rrl(zdb *db, message_data *mesg, u8 * restrict pool_buffer, rrl_process_callback *rrl_process) { zdb_query_ex_answer ans_auth_add; const u8 *qname = message_get_canonised_fqdn(mesg); #if ZDB_RECORDS_MAX_CLASS != 1 const u16 zclass = message_get_query_class(mesg); #endif zdb_rr_label_find_ext_data rr_label_info; const process_flags_t flags = zdb_query_process_flags; /** Check that we are even allowed to handle that class */ #if ZDB_RECORDS_MAX_CLASS == 1 if(message_get_query_class(mesg) != CLASS_IN) { #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_CLASS_NOTFOUND"); #endif return FP_CLASS_NOTFOUND; } zdb_query_ex_answer_create(&ans_auth_add); #endif #if ZDB_RECORDS_MAX_CLASS != 1 u16 host_zclass = ntohs(zclass); /* no choice */ if(host_zclass > ZDB_RECORDS_MAX_CLASS) { return FP_CLASS_NOTFOUND; } #endif bool dnssec = message_has_rcode_ext_dnssec(mesg); /** * MANDATORY, INITIALISES A LOCAL MEMORY POOL * * This is actually a macro found in dnsname_set.h */ dnsname_vector name; DEBUG_RESET_dnsname(name); dnsname_to_dnsname_vector(qname, &name); u8 * restrict * pool = &pool_buffer; /* * Find closest matching label * Should return a stack of zones */ zdb_zone_label_pointer_array zone_label_stack; zdb_lock(db, ZDB_MUTEX_READER); s32 top = zdb_zone_label_match(db, &name, zone_label_stack); s32 sp = top; zdb_packed_ttlrdata* answer; /* This flag means that there HAS to be an authority section */ bool authority_required = flags & PROCESS_FL_AUTHORITY_AUTH; /* This flag means the names in the authority must be (internally) resolved if possible */ bool additionals_required = flags & PROCESS_FL_ADDITIONAL_AUTH; u16 type = message_get_query_type(mesg); switch(type) { case TYPE_DNSKEY: { authority_required = FALSE; additionals_required = FALSE; break; } } /* Got a stack of zone labels with and without zone cuts */ /* Search the label on the zone files */ /* While we have labels along the path */ if(type == TYPE_DS) // This is the only type that can only be found outside of the zone { // In order to avoid to hit said zone, I skip the last label. if(name.size == sp - 1) // we have a perfect match (DS for an APEX), try to get outside ... { s32 parent_sp = sp; while(--parent_sp >= 0) { /* Get the "bottom" label (top being ".") */ zdb_zone_label* zone_label = zone_label_stack[parent_sp]; /* Is there a zone file at this level ? If yes, search into it. */ if(zone_label->zone != NULL) { // got it. sp = parent_sp; message_set_authoritative_answer(mesg); break; } } authority_required = FALSE; } } while(sp >= 0) { /* Get the "bottom" label (top being ".") */ zdb_zone_label* zone_label = zone_label_stack[sp]; /* Is there a zone file at this level ? If yes, search into it. */ if(zone_label->zone != NULL) { zdb_zone *zone = zone_label->zone; /* * lock */ LOCK(zone); #if DEBUG log_debug("zdb_query_and_update_with_rrl: zone %{dnsname}, flags=%x", zone->origin, zdb_rr_label_flag_get(zone->apex)); #endif /* * We know the zone, and its extension here ... */ { /* * Filter handling (ACL) * NOTE: the return code has to be fingerprint-based */ if(FAIL(zone->query_access_filter(mesg, zone->acl))) { #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_ACCESS_REJECTED"); #endif message_set_status(mesg, FP_ACCESS_REJECTED); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return rrl; } } /** * The ACL have been passed so ... now check that the zone is valid */ if(zdb_zone_invalid(zone)) { /** * @note the blocks could be reversed and jump if the zone is invalid (help the branch prediction) */ #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_ZONE_EXPIRED"); #endif message_set_status(mesg, FP_INVALID_ZONE); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return rrl; } //message_set_authoritative(mesg); dnsname_set additionals_dname_set; dnsname_set_init(&additionals_dname_set); /* * In one query, get the authority and the closest (longest) path to the domain we are looking for. */ zdb_rr_label *rr_label = zdb_rr_label_find_ext(zone->apex, name.labels, name.size - sp, &rr_label_info); /* Has a label been found ? */ if(rr_label != NULL) { /* * Got the label. I will not find anything relevant by going * up to another zone file. * * We set the AA bit iff we are not at or under a delegation. * * The ZDB_RR_LABEL_DELEGATION flag means the label is a delegation. * This means that it only contains NS & DNSSEC records + may have sub-labels for glues * * ZDB_RR_LABEL_UNDERDELEGATION means we are below a ZDB_RR_LABEL_DELEGATION label * */ /* * CNAME alias handling */ if(((zdb_rr_label_flag_get(rr_label) & (ZDB_RR_LABEL_HASCNAME|ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION)) == ZDB_RR_LABEL_HASCNAME) && (type != TYPE_CNAME) && (type != TYPE_ANY) && (type != TYPE_RRSIG)) { /* * The label is an alias: * * Add the CNAME and restart the query from the alias */ if(ans_auth_add.depth >= ZDB_CNAME_LOOP_MAX) { log_warn("CNAME depth at %{dnsname} is bigger than allowed %d>=%d", qname, ans_auth_add.depth, ZDB_CNAME_LOOP_MAX); message_set_authoritative(mesg); message_set_status(mesg, FP_CNAME_MAXIMUM_DEPTH); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return rrl; } ans_auth_add.depth++; if((answer = zdb_record_find(&rr_label->resource_record_set, TYPE_CNAME)) != NULL) { /* The RDATA in answer is the fqdn to a label with an A record (list) */ /* There can only be one cname for a given owner */ /* Append all A/AAAA records associated to the CNAME AFTER the CNAME record */ zdb_resourcerecord *rr = ans_auth_add.answer; u32 cname_depth_count = 0; /* I don't want to allocate that globally for now */ while(rr != NULL) { if((rr->rtype == TYPE_CNAME) && (ZDB_PACKEDRECORD_PTR_RDATAPTR(rr->ttl_rdata) == ZDB_PACKEDRECORD_PTR_RDATAPTR(answer))) { /* LOOP */ log_warn("CNAME loop at %{dnsname}", qname); message_set_authoritative(mesg); message_set_status(mesg, FP_CNAME_LOOP); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return rrl; } cname_depth_count++; rr = rr->next; } u8* cname_owner = *pool; *pool += ALIGN16(dnsname_copy(*pool, qname)); /* ONE record */ zdb_query_ex_answer_append(answer, cname_owner, PASS_ZCLASS_PARAMETER TYPE_CNAME, &ans_auth_add.answer, pool); #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec && zdb_zone_is_dnssec(zone)) { zdb_query_ex_answer_append_type_rrsigs(rr_label, cname_owner, TYPE_CNAME, PASS_ZCLASS_PARAMETER answer->ttl, &ans_auth_add.answer, pool); // take the STAR of the label, add it to authority } #endif message_set_canonised_fqdn(mesg, ZDB_PACKEDRECORD_PTR_RDATAPTR(answer)); finger_print fp = zdb_query_from_cname(db, mesg, &ans_auth_add, zone, pool_buffer); message_set_authoritative(mesg); /// @note 20200520 EDF -- flag missing in the test message_set_status(mesg, fp); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return rrl; } else { /* * We expected a CNAME record but found none. * This is NOT supposed to happen. * */ message_set_status(mesg, FP_CNAME_BROKEN); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return rrl; } } if(zdb_rr_label_flag_isclear(rr_label, (ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION) )) { message_set_authoritative(mesg); authority_required = FALSE; } else { /* * we are AT or UNDER a delegation * We can only find (show) NS, DS, RRSIG, NSEC records from the query * * The answer WILL be a referral ... */ switch(type) { /* for these ones : give the rrset for the type and clear AA */ case TYPE_DS: { if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { message_set_authoritative(mesg); } else if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_UNDERDELEGATION)) { message_disable_authoritative(mesg); } ans_auth_add.delegation = 1; authority_required = FALSE; break; } case TYPE_NSEC: { if(zdb_rr_label_flag_isclear(rr_label, ZDB_RR_LABEL_UNDERDELEGATION)) { message_set_authoritative(mesg); } break; } /* for these ones : give the rrset for the type */ case TYPE_NS: ans_auth_add.delegation = 1; break; /* for this one : present the delegation */ case TYPE_ANY: ans_auth_add.delegation = 1; authority_required = FALSE; break; /* for the rest : NSEC ? */ default: ans_auth_add.delegation = 1; /* * do not try to look for it * * faster: go to label but no record, but let's avoid gotos ... */ type = 0; break; } } /* * First let's handle "simple" cases. ANY will be handled in another part of the code. */ if(type != TYPE_ANY) { /* * From the label that has been found, get the RRSET for the required type (zdb_packed_ttlrdata*) */ if((answer = zdb_record_find(&rr_label->resource_record_set, type)) != NULL) { /* A match has been found */ /* NS case */ if(type == TYPE_NS) { zdb_resourcerecord **section; /* * If the label is a delegation, the NS have to be added into authority, * else they have to be added into answer. * */ if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { section = &ans_auth_add.authority; /* ans_auth_add.is_delegation = TRUE; later */ } else { section = &ans_auth_add.answer; } /* * Add the NS records in random order in the right section * */ zdb_query_ex_answer_appendrndlist(answer, qname, PASS_ZCLASS_PARAMETER type, section, pool); #if ZDB_HAS_DNSSEC_SUPPORT /* * Append all the RRSIG of NS from the label */ if(dnssec && zdb_zone_is_dnssec(zone)) { zdb_query_ex_answer_append_type_rrsigs(rr_label, qname, TYPE_NS, PASS_ZCLASS_PARAMETER answer->ttl, section, pool); if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { zdb_packed_ttlrdata* label_ds = zdb_record_find(&rr_label->resource_record_set, TYPE_DS); if(label_ds != NULL) { zdb_query_ex_answer_appendlist(label_ds, qname, PASS_ZCLASS_PARAMETER TYPE_DS, &ans_auth_add.authority, pool); zdb_query_ex_answer_append_type_rrsigs(rr_label, qname, TYPE_DS, PASS_ZCLASS_PARAMETER label_ds->ttl, &ans_auth_add.authority, pool); } #if ZDB_HAS_NSEC3_SUPPORT else if(ZONE_NSEC3_AVAILABLE(zone)) { /** * If there is an NSEC3 RR that matches the delegation name, then that * NSEC3 RR MUST be included in the response. The DS bit in the type * bit maps of the NSEC3 RR MUST NOT be set. * * If the zone is Opt-Out, then there may not be an NSEC3 RR * corresponding to the delegation. In this case, the closest provable * encloser proof MUST be included in the response. The included NSEC3 * RR that covers the "next closer" name for the delegation MUST have * the Opt-Out flag set to one. (Note that this will be the case unless * something has gone wrong). * */ zdb_query_ex_append_nsec3_delegation(zone, &rr_label_info, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT else if(ZONE_NSEC_AVAILABLE(zone)) { /* * Append the NSEC of rr_label and all its signatures */ s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_query_ex_append_nsec_records(rr_label, qname, min_ttl, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif } } #endif /* * authority is never required since we have it already * */ /* * fetch all the additional records for the required type (NS and MX types) * add them to the additional section */ if(additionals_required) { update_additionals_dname_set(answer, PASS_ZCLASS_PARAMETER type, &additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add.additional, pool, dnssec); } } else /* general case */ { /* * Add the records from the answer in random order to the answer section */ zdb_query_ex_answer_appendrndlist(answer, qname, PASS_ZCLASS_PARAMETER type, &ans_auth_add.answer, pool); #if ZDB_HAS_DNSSEC_SUPPORT /* * Append all the RRSIG of NS from the label */ if(dnssec && zdb_zone_is_dnssec(zone)) { zdb_query_ex_answer_append_type_rrsigs(rr_label, qname, type, PASS_ZCLASS_PARAMETER answer->ttl, &ans_auth_add.answer, pool); if(IS_WILD_LABEL(rr_label->name)) { /** * If there is a wildcard match for QNAME and QTYPE, then, in addition * to the expanded wildcard RRSet returned in the answer section of the * response, proof that the wildcard match was valid must be returned. * * This proof is accomplished by proving that both QNAME does not exist * and that the closest encloser of the QNAME and the immediate ancestor * of the wildcard are the same (i.e., the correct wildcard matched). * * To this end, the NSEC3 RR that covers the "next closer" name of the * immediate ancestor of the wildcard MUST be returned. * It is not necessary to return an NSEC3 RR that matches the closest * encloser, as the existence of this closest encloser is proven by * the presence of the expanded wildcard in the response. */ #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { zdb_query_ex_append_wild_nsec3_data(zone, rr_label, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* add the NSEC of the wildcard and its signature(s) */ zdb_query_ex_add_nsec_interval(zone, &name, NULL, &ans_auth_add.authority, pool); } #endif } } #endif /* * if authority required */ if(authority_required) { if((type == TYPE_NSEC || type == TYPE_DS) && (rr_label_info.authority != zone->apex)) { rr_label_info.authority = zone->apex; rr_label_info.authority_index = sp - 1; } zdb_packed_ttlrdata* authority = append_authority(qname, PASS_ZCLASS_PARAMETER &rr_label_info, &ans_auth_add.authority, pool, dnssec); if(additionals_required) { update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, &additionals_dname_set); } } /* * fetch all the additional records for the required type (NS and MX types) * add them to the additional section */ if(additionals_required) { update_additionals_dname_set(answer, PASS_ZCLASS_PARAMETER type, &additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add.additional, pool, dnssec); } /* resolve authority */ } #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_BASIC_RECORD_FOUND"); #endif message_set_status(mesg, FP_BASIC_RECORD_FOUND); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return rrl; } /* if found the record of the requested type */ else { /* label but no record */ /** * Got the label, but not the record. * This should branch to NSEC3 if it is supported. */ finger_print fp; #if ENFORCE_MINTTL fp = (finger_print)zdb_query_ex_record_not_found_nttl(zone, &rr_label_info, qname, &name, sp, top, type, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); #else if(ZONE_NSEC_AVAILABLE(zone) || ZONE_NSEC3_AVAILABLE(zone)) { fp = (finger_print)zdb_query_ex_record_not_found_nttl(zone, &rr_label_info, qname, &name, sp, top, type, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); } else { fp = (finger_print)zdb_query_ex_record_not_found(zone, &rr_label_info, qname, &name, sp, top, type, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); } #endif #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_BASIC_RECORD_NOTFOUND (done)"); #endif message_set_status(mesg, fp); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); return rrl; } } else /* We got the label BUT type == TYPE_ANY */ { if(zdb_rr_label_flag_isclear(rr_label, (ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION) )) { zdb_packed_ttlrdata *soa = NULL; #if ZDB_HAS_DNSSEC_SUPPORT zdb_packed_ttlrdata *rrsig_list = zdb_record_find(&rr_label->resource_record_set, TYPE_RRSIG); #endif bool answers = FALSE; /* We do iterate on ALL the types of the label */ btree_iterator iter; btree_iterator_init(rr_label->resource_record_set, &iter); while(btree_iterator_hasnext(&iter)) { btree_node* nodep = btree_iterator_next_node(&iter); u16 type = nodep->hash; answers = TRUE; zdb_packed_ttlrdata* ttlrdata = (zdb_packed_ttlrdata*)nodep->data; /** * @note: doing the list once may be faster ... * And YES maybe, because of the jump and because the list is supposed to * be VERY small (like 1-3) */ switch(type) { case TYPE_SOA: { soa = ttlrdata; continue; } case TYPE_NS: { /* NO NEED FOR AUTHORITY */ authority_required = FALSE; } FALLTHROUGH // fall through case TYPE_MX: case TYPE_CNAME: { /* ADD MX "A/AAAA/GLUE" TO ADDITIONAL */ if(additionals_required) { update_additionals_dname_set(ttlrdata, PASS_ZCLASS_PARAMETER type, &additionals_dname_set); } break; } case TYPE_RRSIG: { // signatures will be added by type continue; } default: { break; } } zdb_query_ex_answer_appendrndlist(ttlrdata, qname, PASS_ZCLASS_PARAMETER type, &ans_auth_add.answer, pool); #if ZDB_HAS_DNSSEC_SUPPORT if(rrsig_list != NULL) { zdb_query_ex_answer_append_type_rrsigs_from(rrsig_list, qname, type, PASS_ZCLASS_PARAMETER ttlrdata->ttl, &ans_auth_add.answer, pool); } #endif } /* now we can insert the soa, if any has been found, at the head of the list */ if(soa != NULL) { zdb_resourcerecord* soa_rr = zdb_query_ex_answer_make(soa, qname, PASS_ZCLASS_PARAMETER TYPE_SOA, pool); soa_rr->next = ans_auth_add.answer; ans_auth_add.answer = soa_rr; #if ZDB_HAS_DNSSEC_SUPPORT if(rrsig_list != NULL) { zdb_query_ex_answer_append_type_rrsigs_from(rrsig_list, qname, TYPE_SOA, PASS_ZCLASS_PARAMETER soa_rr->ttl, &ans_auth_add.answer, pool); } #endif } if(answers) { if(authority_required) { // not at or under a delegation zdb_packed_ttlrdata* authority = append_authority(qname, PASS_ZCLASS_PARAMETER &rr_label_info, &ans_auth_add.authority, pool, dnssec); if(additionals_required) { update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, &additionals_dname_set); } } /* if authority required */ if(additionals_required) { append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add.additional, pool, dnssec); } #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec && IS_WILD_LABEL(rr_label->name)) { /** * If there is a wildcard match for QNAME and QTYPE, then, in addition * to the expanded wildcard RRSet returned in the answer section of the * response, proof that the wildcard match was valid must be returned. * * This proof is accomplished by proving that both QNAME does not exist * and that the closest encloser of the QNAME and the immediate ancestor * of the wildcard are the same (i.e., the correct wildcard matched). * * To this end, the NSEC3 RR that covers the "next closer" name of the * immediate ancestor of the wildcard MUST be returned. * It is not necessary to return an NSEC3 RR that matches the closest * encloser, as the existence of this closest encloser is proven by * the presence of the expanded wildcard in the response. */ #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { zdb_query_ex_append_wild_nsec3_data(zone, rr_label, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* add the NSEC of the wildcard and its signature(s) */ zdb_query_ex_add_nsec_interval(zone, &name, NULL, &ans_auth_add.authority, pool); } #endif } #endif // ZDB_HAS_DNSSEC_SUPPORT #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_BASIC_RECORD_FOUND (any)"); #endif message_set_status(mesg, FP_BASIC_RECORD_FOUND); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return rrl; } else { /* no records found ... */ finger_print fp; if(ZONE_NSEC_AVAILABLE(zone) || ZONE_NSEC3_AVAILABLE(zone)) { fp = (finger_print)zdb_query_ex_record_not_found_nttl(zone, &rr_label_info, qname, &name, sp, top, TYPE_ANY, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); } else { fp = (finger_print)zdb_query_ex_record_not_found(zone, &rr_label_info, qname, &name, sp, top, TYPE_ANY, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); } message_set_status(mesg, fp); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return rrl; } } else { /* ANY, at or under a delegation */ zdb_query_ex_record_not_found(zone, &rr_label_info, qname, &name, sp, top, 0, PASS_ZCLASS_PARAMETER pool, dnssec, &ans_auth_add, &additionals_dname_set); message_set_status(mesg, FP_BASIC_RECORD_FOUND); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return rrl; } } } /* end of if rr_label!=NULL => */ else /* rr_label == NULL */ { zdb_rr_label* rr_label_authority = rr_label_info.authority; if(rr_label_authority != zone->apex) { message_disable_authoritative(mesg); zdb_packed_ttlrdata *authority = zdb_record_find(&rr_label_authority->resource_record_set, TYPE_NS); if(authority != NULL) { const u8 * authority_qname = zdb_rr_label_info_get_authority_qname(qname, &rr_label_info); zdb_query_ex_answer_appendrndlist(authority, authority_qname, PASS_ZCLASS_PARAMETER TYPE_NS, &ans_auth_add.authority, pool); update_additionals_dname_set(authority, PASS_ZCLASS_PARAMETER TYPE_NS, &additionals_dname_set); append_additionals_dname_set(zone, PASS_ZCLASS_PARAMETER &additionals_dname_set, &ans_auth_add.additional, pool, FALSE); if(dnssec) { #if ZDB_HAS_DNSSEC_SUPPORT zdb_query_ex_answer_append_type_rrsigs(rr_label_authority, authority_qname, TYPE_NS, PASS_ZCLASS_PARAMETER authority->ttl, &ans_auth_add.authority, pool); #endif zdb_packed_ttlrdata *delegation_signer = zdb_record_find(&rr_label_authority->resource_record_set, TYPE_DS); if(delegation_signer != NULL) { zdb_query_ex_answer_appendlist(delegation_signer , authority_qname, PASS_ZCLASS_PARAMETER TYPE_DS, &ans_auth_add.authority, pool); #if ZDB_HAS_DNSSEC_SUPPORT zdb_query_ex_answer_append_type_rrsigs(rr_label_authority, authority_qname, TYPE_DS, PASS_ZCLASS_PARAMETER delegation_signer->ttl, &ans_auth_add.authority, pool); #endif } else { #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { // add ... ? it looks like the record that covers the path that has been found in the zone // is used for the digest, then the interval is shown // add apex NSEC3 (wildcard) zdb_query_ex_append_nsec3_delegation(zone, &rr_label_info, &name, top, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* * Append the NSEC of rr_label and all its signatures */ s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_query_ex_append_nsec_records(rr_label_authority, authority_qname, min_ttl, PASS_ZCLASS_PARAMETER &ans_auth_add.authority, pool); } #endif } } ans_auth_add.delegation = 1; // no answer, NS records in authority : referral #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_BASIC_LABEL_NOTFOUND (done)"); #endif /* ans_auth_add.is_delegation = TRUE; later */ message_set_status(mesg, FP_BASIC_LABEL_DELEGATION); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return rrl; } } else { message_set_authoritative(mesg); } } /* LABEL NOT FOUND: We stop the processing and fall through NSEC(3) or the basic case. */ UNLOCK(zone); /* Stop looking, skip cache */ break; } /* if(zone!=NULL) */ sp--; } /* while ... */ /************************************************* * * * At this point we are not an authority anymore. * * * *************************************************/ /*if(authority_required) { */ /* * Get the most relevant label (lowest zone). * Try to do NSEC3 or NSEC with it. */ zdb_zone* zone; #if DEBUG zone = (zdb_zone*)~0; #endif sp = top; // top >= 0, so we can enter here and zone is assigned yassert(sp >= 0); while(sp >= 0) // scan-build false positive: we ALWAYS get into this loop at least once { zdb_zone_label* zone_label = zone_label_stack[sp--]; if((zone = zone_label->zone) != NULL) { /* if type == DS && zone->origin = qname then the return value is NOERROR instead of NXDOMAIN */ break; } } if(zone == NULL) // zone is ALWAYS assigned because top is >= 0 { #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_NOZONE_FOUND (2)"); #endif message_set_status(mesg, FP_NOZONE_FOUND); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); // ??? zone_pointer_out->apex->flags |= ZDB_RR_LABEL_MASTER_OF; zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return rrl; } LOCK(zone); if(!zdb_zone_invalid(zone)) { // zone is the most relevant zone #if ZDB_HAS_DNSSEC_SUPPORT if(dnssec) { #if ZDB_HAS_NSEC3_SUPPORT if(ZONE_NSEC3_AVAILABLE(zone)) { //nsec3_zone *n3 = zone->nsec.nsec3; u8 *next_closer_owner = NULL; zdb_packed_ttlrdata* next_closer; const zdb_packed_ttlrdata* next_closer_rrsig; u8 *closer_encloser_owner = NULL; zdb_packed_ttlrdata* closer_encloser; const zdb_packed_ttlrdata* closer_encloser_rrsig; u8 *wild_closer_encloser_owner = NULL; zdb_packed_ttlrdata* wild_closer_encloser; const zdb_packed_ttlrdata* wild_closer_encloser_rrsig; #if DEBUG log_debug("nsec3_name_error"); #endif nsec3_name_error( zone, &name, top, pool, &next_closer_owner, &next_closer, &next_closer_rrsig, &closer_encloser_owner, &closer_encloser, &closer_encloser_rrsig, &wild_closer_encloser_owner, &wild_closer_encloser, &wild_closer_encloser_rrsig); s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); zdb_query_ex_answer_append_soa_rrsig_nttl(zone, &ans_auth_add.authority, pool); //zdb_query_ex_answer_append_soa_rrsig_ttl0(zone, &ans_auth_add.authority, pool); #if DEBUG log_debug("zdb_query_and_update_with_rrl: nsec3_name_error: next_closer_owner: %{dnsname}", next_closer_owner); #endif if(next_closer != NULL /*&& next_closer_rrsig != NULL*/) { zdb_query_ex_answer_append_ttl(next_closer, next_closer_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, &ans_auth_add.authority, pool); if(next_closer_rrsig != NULL) { zdb_query_ex_answer_appendlist_ttl(next_closer_rrsig, next_closer_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, &ans_auth_add.authority, pool); } } if(closer_encloser != NULL/* && closer_encloser_rrsig != NULL*/) { #if DEBUG log_debug("zdb_query_and_update_with_rrl: nsec3_name_error: closer_encloser_owner: %{dnsname}", closer_encloser_owner); #endif zdb_query_ex_answer_append_ttl(closer_encloser, closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, &ans_auth_add.authority, pool); if(closer_encloser_rrsig != NULL) { zdb_query_ex_answer_appendlist_ttl(closer_encloser_rrsig, closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, &ans_auth_add.authority, pool); } } if(wild_closer_encloser != NULL) { #if DEBUG log_debug("zdb_query_and_update_with_rrl: nsec3_name_error: wild_closer_encloser_owner: %{dnsname}", wild_closer_encloser_owner); #endif zdb_query_ex_answer_append_ttl(wild_closer_encloser, wild_closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_NSEC3, min_ttl, &ans_auth_add.authority, pool); if(wild_closer_encloser_rrsig != NULL) { zdb_query_ex_answer_appendlist_ttl(wild_closer_encloser_rrsig, wild_closer_encloser_owner, PASS_ZCLASS_PARAMETER TYPE_RRSIG, min_ttl, &ans_auth_add.authority, pool); } } #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_NSEC3_LABEL_NOTFOUND (done)"); #endif message_set_status(mesg, FP_NSEC3_LABEL_NOTFOUND); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return rrl; } #endif /* ZDB_HAS_NSEC3_SUPPORT != 0 */ /* NSEC, if possible */ #if ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else /* Following will be either the NSEC answer or just the SOA added in the authority */ #endif if(ZONE_NSEC_AVAILABLE(zone)) { /* * Unknown and not in the cache : NSEC * */ /* * zone label stack * * #0 : top * #1 : com, org, ... * #2 : example, ... * * Which is the inverse of the dnslabel stack * * dnslabel stack * * #0 : example * #1 : com * #2 : NOTHING ("." is not stored) * * */ /* * Get the SOA + NSEC + RRIGs for the zone */ //zdb_rr_label *apex_label = zone->apex; zdb_query_ex_answer_append_soa_rrsig_nttl(zone, &ans_auth_add.authority, pool); u8 *encloser_nsec_name = NULL; u8 *wild_encloser_nsec_name = NULL; zdb_rr_label *encloser_nsec_label; zdb_rr_label *wildencloser_nsec_label; nsec_name_error(zone, &name, rr_label_info.closest_index, // VS false positive: reaching this point, rr_label_info is initialized pool, &encloser_nsec_name, &encloser_nsec_label, &wild_encloser_nsec_name, &wildencloser_nsec_label); if(encloser_nsec_label != NULL) { zdb_packed_ttlrdata *encloser_nsec_rr = zdb_record_find(&encloser_nsec_label->resource_record_set, TYPE_NSEC); if(encloser_nsec_rr != NULL) { zdb_query_ex_answer_append(encloser_nsec_rr, encloser_nsec_name, DECLARE_ZCLASS_PARAMETER TYPE_NSEC, &ans_auth_add.authority, pool); zdb_query_ex_answer_append_type_rrsigs(encloser_nsec_label, encloser_nsec_name, TYPE_NSEC, DECLARE_ZCLASS_PARAMETER encloser_nsec_rr->ttl, &ans_auth_add.authority, pool); if(wildencloser_nsec_label != encloser_nsec_label) { zdb_packed_ttlrdata *wildencloser_nsec_rr = zdb_record_find(&wildencloser_nsec_label->resource_record_set, TYPE_NSEC); if(wildencloser_nsec_rr != NULL) { zdb_query_ex_answer_append(wildencloser_nsec_rr, wild_encloser_nsec_name, DECLARE_ZCLASS_PARAMETER TYPE_NSEC, &ans_auth_add.authority, pool); zdb_query_ex_answer_append_type_rrsigs(wildencloser_nsec_label, wild_encloser_nsec_name, TYPE_NSEC, DECLARE_ZCLASS_PARAMETER wildencloser_nsec_rr->ttl, &ans_auth_add.authority, pool); } } } } #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_NSEC_LABEL_NOTFOUND (done)"); #endif message_set_status(mesg, FP_NSEC_LABEL_NOTFOUND); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return rrl; } #endif // ZDB_HAS_NSEC_SUPPORT } #endif // ZDB_HAS_DNSSEC_SUPPORT zdb_query_ex_answer_append_soa_nttl(zone, &ans_auth_add.authority, pool); #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_BASIC_LABEL_NOTFOUND (done)"); #endif message_set_status(mesg, FP_BASIC_LABEL_NOTFOUND); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return rrl; } else // if(!zdb_zone_invalid(zone)) { #if DEBUG log_debug("zdb_query_and_update_with_rrl: FP_ZONE_EXPIRED (2)"); #endif message_set_status(mesg, FP_INVALID_ZONE); ya_result rrl = zdb_query_message_update_with_rrl(mesg, &ans_auth_add, rrl_process); zdb_query_ex_answer_destroy(&ans_auth_add); UNLOCK(zone); zdb_unlock(db, ZDB_MUTEX_READER); log_pool_usage(mesg, pool); return rrl; } } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_query_ex_wire.c0000644000000000000000000000013214505005531022656 xustar000000000000000030 mtime=1695812441.758972392 30 atime=1695812445.803030311 30 ctime=1695812495.115736568 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_query_ex_wire.c0000664000374500037450000002646114505005531022631 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup query_ex Database top-level query function * @ingroup dnsdb * @brief Database top-level query function * * Database top-level query function * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include "dnsdb/dnsdb-config.h" #include "dnsdb/zdb_types.h" #include #include #include #include #include "dnsdb/htable.h" #include "dnscore/hash.h" #include "dnsdb/dnsdb-config.h" #if ZDB_HAS_NSID_SUPPORT #include #endif extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define ANSWER_DO_COMPRESSION 1 #if BYTE_ORDER==BIG_ENDIAN #define ENCODE_OFFSET(offset) (offset|0xc000) #else #define ENCODE_OFFSET(offset) ((offset>>8)|(offset<<8)|0x00c0) #endif extern process_flags_t zdb_query_process_flags; /** * @note I could also have tables by label depth. * But I'll need more time to experiment this. * * @note Only used in zdb_query_message_update */ static bool zdb_query_message_update_write_label(const zdb_resourcerecord* rr, u32* countp, packet_writer* pc, u32 max_size) { u32 count = 0; bool fully_written = TRUE; while(rr != NULL) { /* Store the name */ const u8* name = rr->name; u16 rdata_size = ZDB_PACKEDRECORD_PTR_RDATASIZE(rr->ttl_rdata); u32 offset_backup = pc->packet_offset; /* copy the name */ #if !ANSWER_DO_COMPRESSION packet_writer_add_fqdn_uncompressed(pc, name); #else if(FAIL(packet_writer_add_fqdn(pc, name))) { pc->packet_offset = offset_backup; return FALSE; } #endif /* copy the TYPE + CLASS + RDATA SIZE */ /* Here we do compression (or not) */ #if !ANSWER_DO_COMPRESSION if(pc->packet_offset + 2 + 2 + 4 + 2 + rdata_size >= pc->packet_limit) { pc->packet_offset = offset_backup; return FALSE; } packet_writer_add_u16(pc, (rr->rtype)); /** @note: NATIVETYPE */ packet_writer_add_u16(pc, (rr->zclass)); /** @note: NATIVECLASS */ packet_writer_add_u32(pc, htonl(rr->ttl)); /* Store the RDATA len (16 bits) */ u8* rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(rr->ttl_rdata); packet_writer_add_u16(pc, htons(rdata_size)); /* copy the RDATA */ packet_writer_add_bytes(pc, rdata, rdata_size); #else if(pc->packet_offset + 2 + 2 + 4 + 2 >= pc->packet_limit) { pc->packet_offset = offset_backup; return FALSE; } packet_writer_add_u16(pc, (rr->rtype)); /** @note: NATIVETYPE */ packet_writer_add_u16(pc, (rr->zclass)); /** @note: NATIVECLASS */ packet_writer_add_u32(pc, htonl(rr->ttl)); u32 offset = pc->packet_offset; u8* rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(rr->ttl_rdata); pc->packet_offset += 2; switch(rr->rtype) { case TYPE_MX: if(pc->packet_offset + 2 >= pc->packet_limit) { pc->packet_offset = offset_backup; return FALSE; } packet_writer_add_bytes(pc, rdata, 2); rdata += 2; /* Fallthrough */ case TYPE_NS: case TYPE_CNAME: case TYPE_DNAME: case TYPE_PTR: case TYPE_MB: case TYPE_MD: case TYPE_MF: case TYPE_MG: case TYPE_MR: /* ONE NAME record */ { if(FAIL(packet_writer_add_fqdn(pc, rdata))) { pc->packet_offset = offset_backup; return FALSE; } packet_writer_set_u16(pc, htons(pc->packet_offset - offset - 2), offset); break; } case TYPE_SOA: { u32 len1 = dnsname_len(rdata); if(FAIL(packet_writer_add_fqdn(pc, rdata))) { pc->packet_offset = offset_backup; return FALSE; } rdata += len1; u32 len2 = dnsname_len(rdata); if(FAIL(packet_writer_add_fqdn(pc, rdata))) { pc->packet_offset = offset_backup; return FALSE; } rdata += len2; if(pc->packet_offset + 20 >= pc->packet_limit) { pc->packet_offset = offset_backup; return FALSE; } packet_writer_add_bytes(pc, rdata, 20); packet_writer_set_u16(pc, htons(pc->packet_offset - offset - 2), offset); break; } default: { if(pc->packet_offset + rdata_size >= pc->packet_limit) { pc->packet_offset = offset_backup; return FALSE; } packet_writer_set_u16(pc, htons(rdata_size), offset); packet_writer_add_bytes(pc, rdata, rdata_size); break; } } /* switch(type) */ #endif /* * If we are beyond the limit, we restore the offset and stop here. */ if(pc->packet_offset > max_size) { pc->packet_offset = offset_backup; fully_written = FALSE; break; } count++; rr = rr->next; } *countp = count; /* stores the count */ return fully_written; /* returns the offset of the next writable byte */ } extern u16 edns0_maxsize; void zdb_query_message_update(message_data* mesg, const zdb_query_ex_answer* answer_set) { /* * * OPCODE (16 bits) * QUERY " * ANSWER " * AUTHORITY " * ADDITIONAL " * */ /* Insert the query */ message_header* header = message_get_header(mesg); message_set_referral(mesg, answer_set->delegation); u32 count; bool fully_written; /* Initialize the compression dictionnary with the query */ packet_writer pw; #if DEBUG count = ~0; memset(&pw, 0xff, sizeof(pw)); #endif if(message_is_edns0(mesg)) { #if ZDB_HAS_NSID_SUPPORT message_reserve_buffer_size(mesg, edns0_record_size); /* edns0 opt record */ #else message_reserve_buffer_size(mesg, EDNS0_RECORD_SIZE); /* edns0 opt record */ #endif } packet_writer_init_append_to_message(&pw, mesg); // write_label handles truncation u32 max_size = message_get_buffer_size(mesg); // valid use of message_get_buffer_size() fully_written = zdb_query_message_update_write_label(answer_set->answer, &count, &pw, max_size); header->ancount = htons(count); header->nscount = 0; header->arcount = 0; if(fully_written) { if((zdb_query_process_flags & PROCESS_FL_AUTHORITY_AUTH) != 0) { fully_written = zdb_query_message_update_write_label(answer_set->authority, &count, &pw, max_size); header->nscount = htons(count); } if(fully_written && ((zdb_query_process_flags & PROCESS_FL_ADDITIONAL_AUTH) != 0)) { /* fully_written = */ zdb_query_message_update_write_label(answer_set->additional, &count, &pw, max_size); header->arcount = htons(count); } } if(message_is_edns0(mesg)) { /* 00 00 29 SS SS rr vv 80 00 00 00 */ /* 00 00 29 SS SS rr vv 80 00 |opt| 00 03 |nsid| nsid */ #if ZDB_HAS_NSID_SUPPORT if(!message_has_nsid(mesg)) { message_increase_buffer_size(mesg, EDNS0_RECORD_SIZE); /* edns0 opt record */ memset(&pw.packet[pw.packet_offset], 0, EDNS0_RECORD_SIZE); pw.packet_offset += 2; pw.packet[pw.packet_offset++] = 0x29; packet_writer_add_u16(&pw, htons(edns0_maxsize)); packet_writer_add_u32(&pw, message_get_rcode_ext(mesg)); pw.packet_offset += 2; // rdata size already set to 0, skip it } else { message_increase_buffer_size(mesg, edns0_record_size); /* edns0 opt record */ packet_writer_add_u16(&pw, 0); // fqdn + 1st half of type pw.packet[pw.packet_offset++] = 0x29; // 2nd half of type packet_writer_add_u16(&pw, htons(edns0_maxsize)); packet_writer_add_u32(&pw, message_get_rcode_ext(mesg)); memcpy(&pw.packet[pw.packet_offset], edns0_rdatasize_nsid_option_wire, edns0_rdatasize_nsid_option_wire_size); pw.packet_offset += edns0_rdatasize_nsid_option_wire_size; } #else message_increase_buffer_size(mesg, EDNS0_RECORD_SIZE); /* edns0 opt record */ pw.packet_limit += EDNS0_RECORD_SIZE; memset(&pw.packet[pw.packet_offset], 0, EDNS0_RECORD_SIZE); pw.packet_offset += 2; pw.packet[pw.packet_offset++] = 0x29; packet_writer_add_u16(&pw, htons(edns0_maxsize)); packet_writer_add_u32(&pw, message_get_rcode_ext(mesg)); pw.packet_offset += 2; // rdata size already set to 0, skip it #endif header->arcount = htons(ntohs(header->arcount) + 1); } if(fully_written) { message_update_answer_status(mesg); } else { /* TC ! */ message_update_truncated_answer_status(mesg); } message_set_size(mesg, pw.packet_offset); } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_record.c0000644000000000000000000000013214505005531021245 xustar000000000000000030 mtime=1695812441.700971561 30 atime=1695812445.800030268 30 ctime=1695812495.117736597 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_record.c0000664000374500037450000005402714505005531021217 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup records Internal functions for the database: resource records. * @ingroup dnsdb * @brief Internal functions for the database: resource records. * * Internal functions for the database: resource records. * * Handling of the class->type->ttl+rdata list. * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_error.h" #include "dnsdb/btree.h" #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3_types.h" #endif #define TTLRDATA_TAG 0x41544144524c5454 #define ZDBRDATA_TAG 0x415441445242445a #define TMPRDATA_TAG 0x4154414452504d54 /** @brief Frees a resource record * * Inserts a ttl-rdata record into the rtl-rdata collection * * @param[in] record the ttl-rdata to free */ static void zdb_record_free(zdb_packed_ttlrdata* record) { /** MEMORY CANNOT BE TRASHED WHEN USING ZALLOC BECAUSE rdata_size IS USED TO FREE THE MEMORY ! */ /** DO NOT DO THIS : memset(record,0x8f,sizeof(zdb_packed_ttlrdata)+record->rdata_size-1); */ #if DEBUG //yassert((u32)(intptr)(record->next) != 0xfefefefeUL); u16 tmp = record->rdata_size; memset(record, 0xfe, sizeof(zdb_packed_ttlrdata) + tmp - 1); record->rdata_size = tmp; #endif ZDB_RECORD_ZFREE(record); } /** @brief Inserts a resource record into the resource collection, assume no dups * * Assume there are no dups. * Inserts a ttl-rdata record into the rtl-rdata collection * The caller loses the property of the record. * * @param[in] collection the collection * @param[in] class_ the class of the resource record * @param[in] type the type of the resource record * @param[in] ttl the ttl of the resource record * @param[in] rdata_size the size of the rdata of the resource record * @param[in] rdata a pointer to the rdata of the resource record * * @return OK in case of success. */ void zdb_record_insert(zdb_rr_collection* collection, u16 type, zdb_packed_ttlrdata* record) { zdb_packed_ttlrdata** record_sll = (zdb_packed_ttlrdata**)btree_insert(collection, type); #if DEBUG switch(type) { case TYPE_A: if(record->rdata_size != 4) abort(); break; case TYPE_AAAA: if(record->rdata_size != 16) abort(); break; #if ZDB_HAS_NSEC3_SUPPORT case TYPE_NSEC3PARAM: if(record->rdata_size != NSEC3PARAM_RDATA_SIZE_FROM_RDATA(record->rdata_start)) abort(); break; #endif default: break; } #endif record->next = *record_sll; *record_sll = record; } /** @brief Inserts a resource record into the resource collection, checks for dups * * Do not assume anything. * Inserts a ttl-rdata record into the rtl-rdata collection * The caller loses the property of the record. * If the record is a dup, it is destroyed. * * @param[in] collection the collection * @param[in] class_ the class of the resource record * @param[in] type the type of the resource record * @param[in] ttl the ttl of the resource record * @param[in] rdata_size the size of the rdata of the resource record * @param[in] rdata a pointer to the rdata of the resource record * * @return TRUE in case of success. */ bool zdb_record_insert_checked(zdb_rr_collection* collection, u16 type, zdb_packed_ttlrdata* record) { zdb_packed_ttlrdata** record_sll = (zdb_packed_ttlrdata**)btree_insert(collection, type); if(type != TYPE_CNAME) { u32 ttl = record->ttl; zdb_packed_ttlrdata* next = *record_sll; while(next != NULL) { next->ttl = ttl; if(next->rdata_size == record->rdata_size) { if(memcmp(next->rdata_start, record->rdata_start, record->rdata_size) == 0) /* dup */ { #if DEBUG switch(type) { case TYPE_A: if(record->rdata_size != 4) abort(); break; case TYPE_AAAA: if(record->rdata_size != 16) abort(); break; #if ZDB_HAS_NSEC3_SUPPORT case TYPE_NSEC3PARAM: if(record->rdata_size != NSEC3PARAM_RDATA_SIZE_FROM_RDATA(record->rdata_start)) abort(); break; #endif default: break; } #endif next = next->next; while(next != NULL) { next->ttl = ttl; next = next->next; } return FALSE; } } next = next->next; } record->next = *record_sll; *record_sll = record; } else { ZDB_RECORD_SAFE_ZFREE(*record_sll); record->next = NULL; *record_sll = record; } return TRUE; } /** @brief Inserts a resource record into the resource collection, checks for dups * * Do not assume anything. * Inserts a ttl-rdata record into the rtl-rdata collection * The caller loses the property of the record. * If the record is a dup, it is destroyed. * TTL value is not propagated through the resource record set * * @param[in] collection the collection * @param[in] class_ the class of the resource record * @param[in] type the type of the resource record * @param[in] ttl the ttl of the resource record * @param[in] rdata_size the size of the rdata of the resource record * @param[in] rdata a pointer to the rdata of the resource record * * @return TRUE in case of success. */ bool zdb_record_insert_checked_keep_ttl(zdb_rr_collection* collection, u16 type, zdb_packed_ttlrdata* record) { zdb_packed_ttlrdata** record_sll = (zdb_packed_ttlrdata**)btree_insert(collection, type); if(type != TYPE_CNAME) { zdb_packed_ttlrdata* next = *record_sll; while(next != NULL) { if(next->rdata_size == record->rdata_size) { if(memcmp(next->rdata_start, record->rdata_start, record->rdata_size) == 0) /* dup */ { #if DEBUG switch(type) { case TYPE_A: if(record->rdata_size != 4) abort(); break; case TYPE_AAAA: if(record->rdata_size != 16) abort(); break; #if ZDB_HAS_NSEC3_SUPPORT case TYPE_NSEC3PARAM: if(record->rdata_size != NSEC3PARAM_RDATA_SIZE_FROM_RDATA(record->rdata_start)) abort(); break; #endif default: break; } #endif return FALSE; } } next = next->next; } record->next = *record_sll; *record_sll = record; } else { ZDB_RECORD_SAFE_ZFREE(*record_sll); record->next = NULL; *record_sll = record; } return TRUE; } #if !ZDB_RECORD_USES_INLINE /** @brief Finds and return all the a resource record matching the class and type * * Finds and returns all the a resource record matching the class and type * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return the first record, or NULL of none has been found. */ zdb_packed_ttlrdata* zdb_record_find(const zdb_rr_collection* collection, u16 type) { zdb_packed_ttlrdata* record_list = (zdb_packed_ttlrdata*)btree_find(collection, type); return record_list; } /** @brief Finds and return a pointer to the list of all the a resource record matching the class and type * * Finds and returns a pointer to the list of all the a resource record matching the class and type * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return the first record, or NULL of none has been found. */ zdb_packed_ttlrdata** zdb_record_findp(const zdb_rr_collection* collection, u16 type) { zdb_packed_ttlrdata** record_list = (zdb_packed_ttlrdata**)btree_findp(collection, type); return record_list; } /** @brief Finds and return all the a resource record matching the class and type * Create the node if no such resource exists * * Finds and returl all the a resource record matching the class and type * Create the node if no such resource exists * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return the first record, or NULL of none has been found. */ zdb_packed_ttlrdata** zdb_record_find_insert(zdb_rr_collection* collection, u16 type) { yassert(collection != NULL); zdb_packed_ttlrdata** record_list = (zdb_packed_ttlrdata**)btree_insert(collection, type); return record_list; } #endif /** @brief Deletes all the a resource record matching the class and type * * Deletes and return all the a resource record matching the class and type * * @param[in] collection the collection * @param[in] class_ the class of the resource record to match * @param[in] type the type of the resource record to match * * @return OK in case of success. ERROR if no record were deleted. */ ya_result zdb_record_delete(zdb_rr_collection* collection, u16 type) { yassert(collection != NULL); if(type != TYPE_ANY) { zdb_packed_ttlrdata* record_list = (zdb_packed_ttlrdata*)btree_delete(collection, type); if(record_list != NULL) { /* We have the data of the node that has just been deleted */ do { zdb_packed_ttlrdata* tmp = record_list; record_list = record_list->next; zdb_record_free(tmp); } while(record_list != NULL); return SUCCESS; } return ZDB_ERROR_KEY_NOTFOUND; } else { zdb_record_destroy(collection); /* FB: This should be handled by the caller */ return SUCCESS; } } /** @brief Checks if two records are equal. * * Checks if two records are equal. * * @return TRUE if the records are equal, FALSE otherwise. */ bool zdb_record_equals_unpacked(const zdb_packed_ttlrdata* a, const zdb_ttlrdata* b) { int len; bool ret = FALSE; /* The TTL is irrelevant for matches */ if((len = ZDB_PACKEDRECORD_PTR_RDATASIZE(a)) == ZDB_RECORD_PTR_RDATASIZE(b)) { if(memcmp(ZDB_PACKEDRECORD_PTR_RDATAPTR(a), ZDB_RECORD_PTR_RDATAPTR(b), len) == 0) { ret = TRUE; } } return ret; } /** @brief Checks if two records are equal. * * Checks if two records are equal. * * @return TRUE if the records are equal, FALSE otherwise. */ bool zdb_record_equals(const zdb_packed_ttlrdata *a, const zdb_packed_ttlrdata *b) { int len; bool ret = FALSE; /* The TTL is irrelevant for matches */ if((len = ZDB_PACKEDRECORD_PTR_RDATASIZE(a)) == ZDB_PACKEDRECORD_PTR_RDATASIZE(b)) { if(memcmp(ZDB_PACKEDRECORD_PTR_RDATAPTR(a), ZDB_PACKEDRECORD_PTR_RDATAPTR(b), len) == 0) { ret = TRUE; } } return ret; } /** @brief Deletes the a resource record matching the class, type, ttl, rdata * * Deletes the a resource record matching the class, type, ttl, rdata * * @param[in] collection the collection * @param[in] type the type of the resource record to match * @param[in] ttl the ttl of the resource record to match * @param[in] rdata_size the size of the rdata of the resource record to match * @param[in] rdata a pointer to the rdata of the resource record to match * * @return SUCCESS if we removed the last record of this type. * >SUCCESS if we removed the record but other of this type are still available. * ERROR if no record were deleted. */ ya_result zdb_record_delete_exact(zdb_rr_collection* collection, u16 type, const zdb_ttlrdata *ttlrdata) { yassert((collection != NULL) && (type != TYPE_ANY)); zdb_packed_ttlrdata** record_listp = (zdb_packed_ttlrdata**)btree_findp(collection, type); if(record_listp != NULL) { /* We got all the records of the same type */ zdb_packed_ttlrdata* prev = NULL; zdb_packed_ttlrdata* record_list = *record_listp; while(record_list != NULL) { if(zdb_record_equals_unpacked(record_list, ttlrdata)) { /* got it */ /* first one of the list ? */ if(prev == NULL) /* head */ { /* assign NEXT then check for emptyness */ ya_result ret = SUCCESS_STILL_RECORDS; /* We destroyed the last record of this type */ if((*record_listp = record_list->next) == NULL) { /* delete the tree entry */ btree_delete(collection, type); ret = SUCCESS_LAST_RECORD; /* There is still at least one record of this type available */ } yassert(record_list->rdata_start != ttlrdata->rdata_pointer); zdb_record_free(record_list); return ret; } prev->next = record_list->next; yassert(record_list->rdata_start != ttlrdata->rdata_pointer); zdb_record_free(record_list); return SUCCESS_STILL_RECORDS; /* There is still at least one record of this type available */ } prev = record_list; record_list = record_list->next; } } return ZDB_ERROR_KEY_NOTFOUND; } ya_result zdb_record_delete_self_exact(zdb_rr_collection* collection, u16 type, const zdb_ttlrdata *ttlrdata_) { u8 *tmp; ya_result ret; u8 tmp_[512]; zdb_ttlrdata ttlrdata; ttlrdata.next = NULL; ttlrdata.rdata_size = ttlrdata_->rdata_size; if(ttlrdata.rdata_size <= sizeof(tmp_)) { tmp = &tmp_[0]; } else { MALLOC_OR_DIE(u8*, tmp, ttlrdata.rdata_size, TMPRDATA_TAG); } memcpy(tmp, ttlrdata_->rdata_pointer, ttlrdata.rdata_size); ttlrdata.rdata_pointer = tmp; ttlrdata.ttl = ttlrdata_->ttl; ret = zdb_record_delete_exact(collection, type, &ttlrdata); // safe if(ttlrdata.rdata_size <= sizeof(tmp_)) { } else { free(tmp); } return ret; } static void zdb_record_destroy_callback(void* record_list_) { zdb_packed_ttlrdata* record_list = (zdb_packed_ttlrdata*)record_list_; while(record_list != NULL) { zdb_packed_ttlrdata* tmp = record_list; record_list = record_list->next; zdb_record_free(tmp); } } /** @brief Destroys all the a resource record of the collection * * Destroys all the a resource record of the collection * * @param[in] collection the collection to destroy */ void zdb_record_destroy(zdb_rr_collection* collection) { yassert(collection != NULL); btree_callback_and_destroy(*collection, zdb_record_destroy_callback); *collection = NULL; } /** @brief Checks if a collection is empty * * Checks if a collection is empty * * @return TRUE if the collection is empty, FALSE otherwise. */ bool zdb_record_isempty(const zdb_rr_collection* collection) { yassert(collection != NULL); return *collection == NULL; } /** * @brief Copies the soa rdata to an soa_rdata native structure. * * Copies the soa of a zone to an soa_rdata structure. * No memory is allocated for the soa_rdata. If the zone is destroyed, * the soa_rdata becomes invalid. * * @param[in] zone a pointer to the zone * @param[out] soa_out a pointer to an soa_rdata structure */ ya_result zdb_record_getsoa(const zdb_packed_ttlrdata* soa, soa_rdata* soa_out) { s32 soa_size = ZDB_PACKEDRECORD_PTR_RDATASIZE(soa); const u8* soa_start = soa->rdata_start; soa_out->mname = soa_start; u32 len = dnsname_len(soa_start); soa_size -= len; if(soa_size <= 0) { return ZDB_ERROR_CORRUPTEDSOA; } soa_start += len; soa_out->rname = soa_start; len = dnsname_len(soa_start); soa_size -= len; if(soa_size != 5 * 4) /* Only the 5 32 bits (should) remain */ { return ZDB_ERROR_CORRUPTEDSOA; } soa_start += len; soa_out->serial = ntohl(GET_U32_AT(*soa_start)); soa_start += 4; soa_out->refresh = ntohl(GET_U32_AT(*soa_start)); soa_start += 4; soa_out->retry = ntohl(GET_U32_AT(*soa_start)); soa_start += 4; soa_out->expire = ntohl(GET_U32_AT(*soa_start)); soa_start += 4; soa_out->minimum = ntohl(GET_U32_AT(*soa_start)); //soa_start += 4; return SUCCESS; } /** * @brief Allocated and duplicates the content of the source */ zdb_ttlrdata* zdb_ttlrdata_clone(const zdb_ttlrdata* source) { zdb_ttlrdata *rec; int size = ((sizeof(zdb_ttlrdata) + 7) & ~7) + source->rdata_size; ZALLOC_ARRAY_OR_DIE(zdb_ttlrdata*, rec, size, TTLRDATA_TAG); rec->next = NULL; rec->ttl = source->ttl; rec->rdata_size = source->rdata_size; rec->rdata_pointer = &((u8*)rec)[(sizeof(zdb_ttlrdata) + 7) & ~7]; memcpy(rec->rdata_pointer, source->rdata_pointer, rec->rdata_size); return rec; } /** * @brief Allocated and duplicates the first bytes of content of the source * This is mostly used to clone an NSEC3 record into an NSEC3PARAM */ zdb_ttlrdata* zdb_ttlrdata_clone_resized(const zdb_ttlrdata* source, u32 rdata_newsize) { zdb_ttlrdata *rec; int size = ((sizeof(zdb_ttlrdata) + 7) & ~7) + rdata_newsize; ZALLOC_ARRAY_OR_DIE(zdb_ttlrdata*, rec, size, TTLRDATA_TAG); rec->next = NULL; rec->ttl = source->ttl; rec->rdata_size = rdata_newsize; rec->rdata_pointer = &((u8*)rec)[(sizeof(zdb_ttlrdata) + 7) & ~7]; memcpy(rec->rdata_pointer, source->rdata_pointer, rec->rdata_size); return rec; } /** * @brief Frees the content of the source */ void zdb_ttlrdata_delete(zdb_ttlrdata* record) { int size = ((sizeof(zdb_ttlrdata) + 7) & ~7) + record->rdata_size; ZFREE_ARRAY(record, size); (void)size; // silences warning in some builds setups } /** * DEBUG */ void zdb_record_print_indented(zdb_rr_collection collection, output_stream *os, int indent) { btree_iterator iter; btree_iterator_init(collection, &iter); while(btree_iterator_hasnext(&iter)) { btree_node* node = btree_iterator_next_node(&iter); u16 type = node->hash; zdb_packed_ttlrdata* ttlrdata_sll = (zdb_packed_ttlrdata*)node->data; if(ttlrdata_sll == NULL) { osformatln(os, "%t[%{dnstype}] EMPTY TYPE", indent, &type); continue; } do { osformat(os, "%t[%{dnstype} %9d] ", indent, &type, ttlrdata_sll->ttl); osprint_rdata(os, type, ZDB_PACKEDRECORD_PTR_RDATAPTR(ttlrdata_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(ttlrdata_sll)); osprintln(os, ""); ttlrdata_sll = ttlrdata_sll->next; } while(ttlrdata_sll != NULL); } } void zdb_record_print(zdb_rr_collection collection, output_stream *os) { zdb_record_print_indented(collection, os, 0); } u16 zdb_record_bitmap_type_init(const zdb_rr_collection collection, type_bit_maps_context *bitmap) { type_bit_maps_init(bitmap); btree_iterator iter; btree_iterator_init(collection, &iter); while(btree_iterator_hasnext(&iter)) { btree_node* node = btree_iterator_next_node(&iter); u16 type = node->hash; if((type != TYPE_A) && (type != TYPE_AAAA)) { type_bit_maps_set_type(bitmap, type); } } u16 bitmap_size = type_bit_maps_update_size(bitmap); return bitmap_size; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_rr_label.c0000644000000000000000000000013214505005531021551 xustar000000000000000030 mtime=1695812441.733972034 30 atime=1695812445.801030282 30 ctime=1695812495.119736625 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_rr_label.c0000664000374500037450000011500414505005531021514 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup records_labels Internal functions for the database: zoned resource records label. * @ingroup dnsdb * @brief Internal functions for the database: zoned resource records label. * * Internal functions for the database: zoned resource records label. * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include "dnsdb/zdb_types.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_error.h" #include "dnsdb/zdb-zone-lock.h" #include "dnsdb/nsec3_types.h" #include "dnsdb/dictionary.h" #include void nsec3_zone_label_detach(zdb_rr_label *label); void nsec_zone_label_detach(zdb_rr_label *label); extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger static void zdb_rr_label_destroy_callback(dictionary_node* rr_label_record, void* arg); /** * Removes the "under delegation" flag for all labels under rr_label */ static void zdb_rr_label_clear_underdelegation_under(zdb_rr_label *rr_label) { dictionary_iterator iter; dictionary_iterator_init(&rr_label->sub, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_rr_label** sub_labelp = (zdb_rr_label**)dictionary_iterator_next(&iter); zdb_rr_label_flag_and(*sub_labelp, ~ZDB_RR_LABEL_UNDERDELEGATION); if(!zdb_rr_label_has_rrset(*sub_labelp, TYPE_NS)) { zdb_rr_label_clear_underdelegation_under(*sub_labelp); } else // we reached a sub-delegation { zdb_rr_label_flag_or(*sub_labelp, ZDB_RR_LABEL_DELEGATION); } } } //typedef ya_result zdb_rr_label_forall_cb(zdb_rr_label *rr_label, const u8 *rr_label_fqdn, void *data); struct zdb_rr_label_forall_children_of_fqdn_recurse_parm { zdb_rr_label_forall_cb *callback; void *data; u8 *fqdn; u8 fqdn_storage[256]; }; static ya_result zdb_rr_label_forall_children_of_fqdn_recurse(zdb_rr_label *rr_label, struct zdb_rr_label_forall_children_of_fqdn_recurse_parm* parms) { ya_result ret = 0; dictionary_iterator iter; dictionary_iterator_init(&rr_label->sub, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_rr_label** sub_labelp = (zdb_rr_label**)dictionary_iterator_next(&iter); u8* sub_fqdn = parms->fqdn; sub_fqdn -= (*sub_labelp)->name[0] + 1; if(sub_fqdn < &parms->fqdn_storage[0]) { break; } memcpy(sub_fqdn, (*sub_labelp)->name, (*sub_labelp)->name[0] + 1); parms->callback(*sub_labelp, sub_fqdn, parms->data); if(zdb_rr_label_has_children(rr_label)) { parms->fqdn = sub_fqdn; ret += zdb_rr_label_forall_children_of_fqdn_recurse(*sub_labelp, parms); parms->fqdn += sub_fqdn[0] + 1; } } return ret; } ya_result zdb_rr_label_forall_children_of_fqdn(zdb_rr_label *rr_label, const u8 *rr_label_fqdn, zdb_rr_label_forall_cb *callback, void *data) { if(!zdb_rr_label_has_children(rr_label)) { return 0; } struct zdb_rr_label_forall_children_of_fqdn_recurse_parm parms; parms.callback = callback; parms.data = data; int len = dnsname_len(rr_label_fqdn); parms.fqdn = &parms.fqdn_storage[256 - len]; memcpy(parms.fqdn, rr_label_fqdn, len); ya_result ret = zdb_rr_label_forall_children_of_fqdn_recurse(rr_label, &parms); return ret; } /** * NSEC3: Zone possible * * @note The zdb_rr_label_free functions handles the NSEC3 extension. * */ static inline void zdb_rr_label_free(zdb_zone* zone, zdb_rr_label* label) { #if DEBUG bool must_keep = zdb_rr_label_must_keep(label); yassert(!must_keep); #endif dictionary_destroy_ex(&(label)->sub, zdb_rr_label_destroy_callback, zone); zdb_record_destroy(&(label)->resource_record_set); /// @note not an edition, use only for cleanup/delete #if ZDB_HAS_NSEC_SUPPORT if(zdb_rr_label_nsec_linked(label)) { /* * Here, if there are NSEC nodes pointing to the label they MUST have been destroyed */ nsec_zone_label_detach(label); #if DEBUG yassert(label->nsec.nsec.node == NULL); #endif } #else // ZDB_HAS_NSEC_SUPPORT if(FALSE) #endif // ZDB_HAS_NSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT else if(zdb_rr_label_nsec3any_linked(label)) { /* * Here, if there are NSEC3 nodes pointing to the label they MUST be destroyed */ if(label->nsec.nsec3 != NULL) { //yassert(nsec3_label_extension_self(label->nsec.nsec3) == NULL); //yassert(nsec3_label_extension_star(label->nsec.nsec3) == NULL); // free the nsec3 label extension of the label being freed // nsec3_label_extension_free(label->nsec.nsec3); nsec3_zone_label_detach(label); #if DEBUG label->nsec.nsec3 = (nsec3_label_extension*)0xbad; #endif } } #else // ZDB_HAS_NSEC3_SUPPORT else if(FALSE) { } #endif // ZDB_HAS_NSEC3_SUPPORT #if DEBUG else { yassert(label->nsec.dnssec == NULL); } #endif u32 len = label->name[0]; /* get the memory required to store the label name */ len++; u32 pad = (len > 2)?0:2-len; ZFREE_ARRAY(label, sizeof(zdb_rr_label) - 1 + len + pad); (void)pad; // silence warnings in some setups } /** * @brief INTERNAL callback */ static void zdb_rr_label_destroy_callback(dictionary_node* rr_label_record, void* zone) { if(rr_label_record == NULL) { return; } zdb_rr_label *rr_label = (zdb_rr_label*)rr_label_record; /* detach is made by destroy */ /* dictionary destroy will take every item in the dictionary and * iterate through it calling the passed function. * * Maybe I should use the iterator directly instead. */ zdb_rr_label_free((zdb_zone*)zone, rr_label); // valid call because in a delete } /** * @brief INTERNAL callback */ /* NSEC3: Zone possible */ static int zdb_rr_label_zlabel_match(const void* label, const dictionary_node* node) { const zdb_rr_label *rr_label = (const zdb_rr_label*)node; return dnslabel_equals(rr_label->name, label); } zdb_rr_label* zdb_rr_label_new_instance(const u8* label_name) { zdb_rr_label *rr_label; u32 len = label_name[0]; /* get the memory required to store the label name */ len++; u32 pad = (len > 2)?0:2-len; ZALLOC_ARRAY_OR_DIE(zdb_rr_label*, rr_label, sizeof(zdb_rr_label) - 1 + len + pad, ZDB_RRLABEL_TAG); #if DEBUG memset(rr_label, 0xac, sizeof(zdb_rr_label) - 1 + len); #endif rr_label->name[1] = (u8)0xee; // this slot is guaranteed by pad, and used by the wild card 16 bits test // specifically written a byte here avoid a valgrind check // (otherwise harmless : 8 bytes are allocated at least, no overrun is possible) MEMCOPY(rr_label->name, label_name, len); rr_label->next = NULL; btree_init(&rr_label->resource_record_set); dictionary_init(&rr_label->sub); rr_label->_flags = 0; #if ZDB_HAS_DNSSEC_SUPPORT /* I have to clean this pointer, the caller will be responsible * for setting it up. */ rr_label->nsec.dnssec = NULL; #endif return rr_label; } /** * @brief INTERNAL callback */ static dictionary_node* zdb_rr_label_create_callback(const void* data) { zdb_rr_label *rr_label = zdb_rr_label_new_instance((const u8*)data); return (dictionary_node*)rr_label; } /** * @brief Destroys an rr label and its contents * * Destroys an rr label and its contents * * @param[in] zone_labep a pointer to a pointer to the label to destroy * */ /* NSEC3: Zone possible */ void zdb_rr_label_destroy(zdb_zone* zone, zdb_rr_label** rr_labelp) { yassert(rr_labelp != NULL); zdb_rr_label *rr_label = *rr_labelp; if(rr_label != NULL) { zdb_rr_label_free(zone, rr_label); // valid call because in a delete *rr_labelp = NULL; } } /** * @brief Destroys an rr label and its contents * * Destroys an rr label and its contents * * @param[in] zone_labep a pointer to a pointer to the label to destroy * */ /* NSEC3: Zone possible */ void zdb_rr_label_truncate(zdb_zone* zone, zdb_rr_label *rr_label) { if(rr_label != NULL) { dictionary_destroy_ex(&rr_label->sub, zdb_rr_label_destroy_callback, zone); zdb_record_destroy(&rr_label->resource_record_set); /// @note not an edition, use only for cleanup/delete } } /** * @brief Finds the resource record label matching a path of labels starting from another rr label * * Finds the resource record label matching a path of labels starting from another rr label * Typically the starting label is a zone cut. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found */ zdb_rr_label* zdb_rr_label_find_exact(zdb_rr_label* apex, dnslabel_vector_reference sections, s32 index) { zdb_rr_label *rr_label = apex; /* the zone cut */ /* look into the sub level*/ while(rr_label != NULL && index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); rr_label = (zdb_rr_label*)dictionary_find(&rr_label->sub, hash, label, zdb_rr_label_zlabel_match); index--; } return rr_label; } zdb_rr_label* zdb_rr_label_find_child(zdb_rr_label* parent, const u8* dns_label) { hashcode hash = hash_dnslabel(dns_label); zdb_rr_label *rr_label = (zdb_rr_label*)dictionary_find(&parent->sub, hash, dns_label, zdb_rr_label_zlabel_match); return rr_label; } zdb_rr_label* zdb_rr_label_stack_find(zdb_rr_label* apex, const_dnslabel_stack_reference sections, s32 pos, s32 index) { zdb_rr_label *rr_label = apex; /* the zone cut */ /* look into the sub level*/ while(rr_label != NULL && index <= pos) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); rr_label = (zdb_rr_label*)dictionary_find(&rr_label->sub, hash, label, zdb_rr_label_zlabel_match); index++; } return rr_label; } /** * @brief Finds the resource record label matching a path of labels starting from another rr label or the wildcard label * * Finds the resource record label matching a path of labels starting from another rr label or the wildcard label * Typically the starting label is a zone cut. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label, the * label or NULL if none of them has not been found */ zdb_rr_label* zdb_rr_label_find(zdb_rr_label* apex, dnslabel_vector_reference sections, s32 index) { yassert(apex != NULL); zdb_rr_label *rr_label = apex; /* the zone cut */ /* look into the sub level*/ while(index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); zdb_rr_label* sub_rr_label = (zdb_rr_label*)dictionary_find(&rr_label->sub, hash, label, zdb_rr_label_zlabel_match); if(sub_rr_label == NULL) { /* If the label does not exist BUT we got a wildcard, THEN it is what we are looking for */ if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_GOT_WILD)) { rr_label = (zdb_rr_label*)dictionary_find(&rr_label->sub, WILD_HASH, (void*)WILD_LABEL, zdb_rr_label_zlabel_match); return rr_label; } return sub_rr_label; /* NULL */ } rr_label = sub_rr_label; index--; } return rr_label; } int zdb_rr_label_find_path(zdb_rr_label* apex, dnslabel_vector_reference sections, s32 index, zdb_rr_label** out_array_64) { yassert(apex != NULL); zdb_rr_label *rr_label = apex; /* the zone cut */ zdb_rr_label **p = out_array_64; /* look into the sub level*/ while(index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); zdb_rr_label* sub_rr_label = (zdb_rr_label*)dictionary_find(&rr_label->sub, hash, label, zdb_rr_label_zlabel_match); if(sub_rr_label != NULL) { *p++ = sub_rr_label; rr_label = sub_rr_label; --index; } else { /* If the label does not exist BUT we got a wildcard, THEN it is what we are looking for */ if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_GOT_WILD)) { sub_rr_label = (zdb_rr_label*)dictionary_find(&rr_label->sub, WILD_HASH, (void*)WILD_LABEL, zdb_rr_label_zlabel_match); // VS false positive: can't be NULL if(sub_rr_label != NULL) { *p++ = sub_rr_label; } } break; } } return p - out_array_64; } zdb_rr_label* zdb_rr_label_find_from_name(zdb_zone* zone, const u8 *fqdn) { s32 top; dnslabel_vector name; top = dnsname_to_dnslabel_vector(fqdn, name); top -= zone->origin_vector.size + 1; zdb_rr_label *label = zdb_rr_label_find(zone->apex, name, top); return label; } int zdb_rr_label_find_path_from_name(zdb_zone *zone, const u8 *fqdn, zdb_rr_label** out_array_64) { s32 top; dnslabel_vector name; top = dnsname_to_dnslabel_vector(fqdn, name); top -= zone->origin_vector.size + 1; int ret = zdb_rr_label_find_path(zone->apex, name, top, out_array_64); return ret; } /// @note used in nsec3_chain_replay_execute zdb_rr_label* zdb_rr_label_find_from_name_delete_empty_terminal(zdb_zone* zone, const u8 *fqdn) { s32 top; dnslabel_vector name; top = dnsname_to_dnslabel_vector(fqdn, name); top -= zone->origin_vector.size + 1; zdb_rr_label *label = zdb_rr_label_find(zone->apex, name, top); if((label != NULL) && zdb_rr_label_can_be_deleted(label)) { ya_result ret; if(ISOK(ret = zdb_rr_label_delete_record_and_empty_terminal(zone, name, top - zone->origin_vector.size, TYPE_ANY))) { label = NULL; } else { log_err("zdb_rr_label: %{dnsname} is an empty terminal but could not be removed from the zone: %r", fqdn, ret); } } return label; } zdb_rr_label* zdb_rr_label_find_ext(zdb_rr_label* apex, dnslabel_vector_reference sections, s32 index_, zdb_rr_label_find_ext_data *ext) { yassert(apex != NULL && sections != NULL); s32 index = index_; zdb_rr_label *rr_label = apex; /* the zone cut */ zdb_rr_label* authority = apex; zdb_rr_label* closest = apex; s32 authority_index = index_ + 1; s32 closest_index = index_ + 1; /* look into the sub level*/ while(index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); rr_label = (zdb_rr_label*)dictionary_find(&rr_label->sub, hash, label, zdb_rr_label_zlabel_match); if(rr_label == NULL) { /* If the label does not exist BUT we got a wildcard, THEN it is what we are looking for */ if(zdb_rr_label_flag_isset(closest, ZDB_RR_LABEL_GOT_WILD)) { /* got it all anyway, from previous node ... */ rr_label = (zdb_rr_label*)dictionary_find(&closest->sub, WILD_HASH, (void*)WILD_LABEL, zdb_rr_label_zlabel_match); closest_index = 0; } break; } if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { authority = rr_label; authority_index = index; } closest = rr_label; closest_index = index; index--; } ext->authority = authority; ext->closest = closest; ext->answer = rr_label; ext->authority_index = authority_index; ext->closest_index = closest_index; return rr_label; } /** * @brief Adds the resource record label matching a (relative) path of labels starting from another rr label * * Adds the resource record label matching a path of labels starting from another rr label * Typically the starting label is the apex of the zone. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found */ zdb_rr_label* zdb_rr_label_add(zdb_zone* zone, dnslabel_vector_reference labels, s32 labels_top) { yassert(zdb_zone_iswritelocked(zone)); zdb_rr_label *rr_label = zone->apex; /* the zone cut */ /* look into the sub level*/ u16 or_flags = 0; while(labels_top >= 0) { const u8* label = labels[labels_top]; hashcode hash = hash_dnslabel(label); /* If the current label is '*' (wild) then the parent is marked as owner of a wildcard. */ if(IS_WILD_LABEL(label)) { zdb_rr_label_flag_or(rr_label, ZDB_RR_LABEL_GOT_WILD); } rr_label = (zdb_rr_label*)dictionary_add(&rr_label->sub, hash, label, zdb_rr_label_zlabel_match, zdb_rr_label_create_callback); zdb_rr_label_flag_or(rr_label, or_flags); if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DELEGATION)) { /* the next one down is under a delegation */ or_flags = ZDB_RR_LABEL_UNDERDELEGATION; } labels_top--; } return rr_label; } /* once */ typedef struct zdb_rr_label_delete_record_process_callback_args zdb_rr_label_delete_record_process_callback_args; struct zdb_rr_label_delete_record_process_callback_args { dnslabel_vector_reference sections; zdb_zone* zone; s32 top; u16 type; }; /** * @brief INTERNAL callback */ static ya_result zdb_rr_label_delete_record_process_callback(void* a, dictionary_node* node) { yassert(node != NULL); zdb_rr_label *rr_label = (zdb_rr_label*)node; zdb_rr_label_delete_record_process_callback_args* args = (zdb_rr_label_delete_record_process_callback_args*)a; /* * a points to a kind of dnsname and we are going in * * we go down and down each time calling the dictionnary process for the next level * * at the last level we return the "delete" code * * from there, the dictionnary processor will remove the entry * * at that point the calling dictionnary will know if he has to delete his node or not * * and so on and so forth ... * */ s32 top = args->top; const u8* label = args->sections[top]; if(!dnslabel_equals(rr_label->name, label)) { return COLLECTION_PROCESS_NEXT; } /* match */ if(top > 0) { /* go to the next level */ label = args->sections[--args->top]; hashcode hash = hash_dnslabel(label); ya_result err; if((err = dictionary_process(&rr_label->sub, hash, args, zdb_rr_label_delete_record_process_callback)) == COLLECTION_PROCESS_DELETENODE) { /* check the node for relevance, return "delete" if irrelevant */ if(zdb_rr_label_can_be_deleted(rr_label)) { zdb_rr_label_free(args->zone, rr_label); // valid call because in a delete return COLLECTION_PROCESS_DELETENODE; } if(rr_label->resource_record_set == NULL) { zdb_rr_label_flag_and(rr_label, ~(ZDB_RR_LABEL_HASCNAME|ZDB_RR_LABEL_DROPCNAME)); } /* If the label just removed is a wildcard, then the parent is marked as not having a wildcard. */ if(IS_WILD_LABEL(label)) { zdb_rr_label_flag_and(rr_label, ~ZDB_RR_LABEL_GOT_WILD); } return COLLECTION_PROCESS_STOP; } /* or ... stop */ return err; } /* We are at the right place for the record */ ya_result err; if(ISOK(err = zdb_record_delete(&rr_label->resource_record_set, args->type))) /* FB done */ { if(zdb_rr_label_cannot_be_deleted(rr_label)) { /* If the type was XXXX and we deleted the last one the flag may change. * NS => not a delegation anymore * CNAME => no cname anymore * ANY => nothing anymore (and should not be relevant anymore either ...) */ u16 clear_mask = 0; switch(args->type) { case TYPE_NS: clear_mask = ~ZDB_RR_LABEL_DELEGATION; // will clear "delegation" if(!ZDB_LABEL_UNDERDELEGATION(rr_label)) { // must clear ZDB_RR_LABEL_UNDERDELEGATION from everything under this one zdb_rr_label_clear_underdelegation_under(rr_label); } break; case TYPE_CNAME: clear_mask = ~ZDB_RR_LABEL_HASCNAME; // will clear "has cname" break; case TYPE_ANY: clear_mask = ~(ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_DROPCNAME|ZDB_RR_LABEL_HASCNAME); // will clear "delegation", "drop cname" and "has cname" break; case TYPE_RRSIG: case TYPE_NSEC: break; default: // checks if there are any other types than CNAME, RRSIG and NSEC, clears DROPCNAME if it's true clear_mask = ~ZDB_RR_LABEL_DROPCNAME; // will clear "drop cname" break; } zdb_rr_label_flag_and(rr_label, clear_mask); // clears the bits using the mask return COLLECTION_PROCESS_STOP; } else { if(zdb_rr_label_has_dnssec_extension(rr_label)) { // remove the extension if(zdb_rr_label_nsec3any_linked(rr_label)) { // detach then destroy the ext nsec3_zone_label_detach(rr_label); } else if(zdb_rr_label_nsec_linked(rr_label)) { nsec_zone_label_detach(rr_label); } #if DEBUG else { yassert(rr_label->nsec.dnssec == NULL); } #endif } } /* NOTE: the 'detach' is made by destroy : do not touch to the "next" field */ /* NOTE: the free of the node is made by destroy : do not do it */ /* dictionary destroy will take every item in the dictionary and * iterate through it calling the passed function. */ zdb_rr_label_free(args->zone, rr_label); // valid call because in a delete return COLLECTION_PROCESS_DELETENODE; } return err /*COLLECTION_PROCESS_RETURNERROR*/; } /** * @brief Deletes the resource record of the given type on the label matching a path of labels starting from another rr label * * Deletes the resource record of the given type on the label matching a path of labels starting from another rr label * Typically the starting label is a zone cut. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found * * @note used in nsec_chain_replay_execute */ ya_result zdb_rr_label_delete_record(zdb_zone* zone, dnslabel_vector_reference path, s32 path_index, u16 type) { yassert(zone != NULL && path != NULL && path_index >= -1); yassert(zdb_zone_iswritelocked(zone)); zdb_rr_label* apex = zone->apex; if(apex == NULL) { return ZDB_ERROR_DELETEFROMEMPTY; } if(path_index < 0) { if(ISOK(zdb_record_delete(&apex->resource_record_set, type))) /* FB done, APEX : no delegation */ { return ZDB_RR_LABEL_DELETE_NODE; } return ZDB_ERROR_KEY_NOTFOUND; } zdb_rr_label_delete_record_process_callback_args args; args.sections = path; args.zone = zone; args.top = path_index; args.type = type; hashcode hash = hash_dnslabel(args.sections[args.top]); ya_result err; if((err = dictionary_process(&apex->sub, hash, &args, zdb_rr_label_delete_record_process_callback)) == COLLECTION_PROCESS_DELETENODE) { if(RR_LABEL_IRRELEVANT(apex)) { zdb_rr_label_free(zone, apex); // valid call because in a delete zone->apex = NULL; return ZDB_RR_LABEL_DELETE_TREE; } /* If the label just removed is a wildcard, then the parent is marked as not having a wildcard. */ if(IS_WILD_LABEL(args.sections[args.top])) { zdb_rr_label_flag_and(apex, ~ZDB_RR_LABEL_GOT_WILD); } return ZDB_RR_LABEL_DELETE_NODE; } return err; } /// @note used in zdb_rr_label_find_from_name_delete_empty_terminal -> nsec3_chain_replay_execute ya_result zdb_rr_label_delete_record_and_empty_terminal(zdb_zone* zone, dnslabel_vector_reference path, s32 path_index, u16 type) { yassert(zone != NULL && path != NULL && path_index >= -1); yassert(zdb_zone_iswritelocked(zone)); zdb_rr_label* apex = zone->apex; if(apex == NULL) { return ZDB_ERROR_DELETEFROMEMPTY; } if(path_index < 0) { if(ISOK(zdb_record_delete(&apex->resource_record_set, type))) /* FB done, APEX : no delegation */ { return ZDB_RR_LABEL_DELETE_NODE; } return ZDB_ERROR_KEY_NOTFOUND; } zdb_rr_label_delete_record_process_callback_args args; args.sections = path; args.zone = zone; args.top = path_index; args.type = type; hashcode hash = hash_dnslabel(args.sections[args.top]); ya_result err; if((err = dictionary_process(&apex->sub, hash, &args, zdb_rr_label_delete_record_process_callback)) == COLLECTION_PROCESS_DELETENODE) { if(zdb_rr_label_can_be_deleted(apex)) { zdb_rr_label_free(zone, apex); // valid call because in a delete zone->apex = NULL; return ZDB_RR_LABEL_DELETE_TREE; } /* If the label just removed is a wildcard, then the parent is marked as not having a wildcard. */ if(IS_WILD_LABEL(args.sections[args.top])) { zdb_rr_label_flag_and(apex, ~ZDB_RR_LABEL_GOT_WILD); } return ZDB_RR_LABEL_DELETE_NODE; } return err; } typedef struct zdb_rr_label_delete_record_exact_process_callback_args zdb_rr_label_delete_record_exact_process_callback_args; struct zdb_rr_label_delete_record_exact_process_callback_args { dnslabel_vector_reference sections; const zdb_ttlrdata* ttlrdata; zdb_zone* zone; s32 top; u16 type; u8 flags; }; /** * @brief INTERNAL callback */ /* NSEC3: Zone possible */ static ya_result zdb_rr_label_delete_record_exact_process_callback(void* a, dictionary_node* node) { yassert(node != NULL); zdb_rr_label *rr_label = (zdb_rr_label*)node; zdb_rr_label_delete_record_exact_process_callback_args* args = (zdb_rr_label_delete_record_exact_process_callback_args*)a; /* * a points to a kind of dnsname and we are going in * * we go down and down each time calling the dictionnary process for the next level * * at the last level we return the "delete" code * * from there, the dictionnary processor will remove the entry * * at that point the calling dictionnary will know if he has to delete his node or not * * and so on and so forth ... * */ s32 top = args->top; const u8* label = args->sections[top]; if(!dnslabel_equals(rr_label->name, label)) { return COLLECTION_PROCESS_NEXT; } /* match */ if(top > 0) { /* go to the next level */ label = args->sections[--args->top]; hashcode hash = hash_dnslabel(label); ya_result return_code; if((return_code = dictionary_process(&rr_label->sub, hash, args, zdb_rr_label_delete_record_exact_process_callback)) == COLLECTION_PROCESS_DELETENODE) { /* check the node for relevance, return "delete" if irrelevant */ if(zdb_rr_label_can_be_deleted(rr_label)) { zdb_rr_label_free(args->zone, rr_label); // valid call because in a delete args->flags |= 2; return COLLECTION_PROCESS_DELETENODE; } if(rr_label->resource_record_set == NULL) { zdb_rr_label_flag_and(rr_label, ~(ZDB_RR_LABEL_HASCNAME|ZDB_RR_LABEL_DROPCNAME)); } /* If the label just removed is a wildcard, then the parent is marked as not having a wildcard. */ if(IS_WILD_LABEL(label)) { zdb_rr_label_flag_and(rr_label, ~ZDB_RR_LABEL_GOT_WILD); } return COLLECTION_PROCESS_STOP; } /* or ... stop */ return return_code; } /* We are at the right place for the record */ ya_result delete_return_code; if(ISOK(delete_return_code = zdb_record_delete_exact(&rr_label->resource_record_set, args->type, args->ttlrdata))) /* FB done */ { /* * @NOTE delete_return_code can be either SUCCESS_STILL_RECORDS or SUCCESS_LAST_RECORD */ if(zdb_rr_label_cannot_be_deleted(rr_label)) { /* If the type was XXXX and we deleted the last one the flag may change. * NS => not a delegation anymore * CNAME => no cname anymore * ANY => nothing anymore (and should not be relevant anymore either ...) */ if(delete_return_code == SUCCESS_LAST_RECORD) { u16 clear_mask = ~0; switch(args->type) { case TYPE_NS: clear_mask = ~ZDB_RR_LABEL_DELEGATION; // will clear "delegation" if(!ZDB_LABEL_UNDERDELEGATION(rr_label)) { // must clear ZDB_RR_LABEL_UNDERDELEGATION from everything under this one zdb_rr_label_clear_underdelegation_under(rr_label); } break; case TYPE_CNAME: clear_mask = ~ZDB_RR_LABEL_HASCNAME; // will clear "has cname" break; case TYPE_ANY: clear_mask = ~(ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_DROPCNAME|ZDB_RR_LABEL_HASCNAME); // will clear "delegation", "drop cname" and "has cname" break; case TYPE_RRSIG: case TYPE_NSEC: break; default: // checks if there are any other types than CNAME, RRSIG and NSEC, clears DROPCNAME if it's true clear_mask = ~ZDB_RR_LABEL_DROPCNAME; // will clear "drop cname" break; } zdb_rr_label_flag_and(rr_label, clear_mask); } return COLLECTION_PROCESS_STOP; } else { if(zdb_rr_label_has_dnssec_extension(rr_label)) { // remove the extension if(zdb_rr_label_nsec3any_linked(rr_label)) { // detach then destroy the ext nsec3_zone_label_detach(rr_label); } else if(zdb_rr_label_nsec_linked(rr_label)) { nsec_zone_label_detach(rr_label); } #if DEBUG else { yassert(rr_label->nsec.dnssec == NULL); } #endif } } /* NOTE: the 'detach' is made by destroy : do not touch to the "next" field */ /* NOTE: the free of the node is made by destroy : do not do it */ /* dictionary destroy will take every item in the dictionary and * iterate through it calling the passed function. */ zdb_rr_label_free(args->zone, rr_label); // valid call because in a delete args->flags |= 1; return COLLECTION_PROCESS_DELETENODE; } return delete_return_code /*COLLECTION_PROCESS_RETURNERROR*/; } /** * @brief Deletes the resource record of the given type, ttl and rdata on the label matching a path of labels starting from another rr label * * Deletes the resource record of the given type, ttl and rdata on the label matching a path of labels starting from another rr label * Typically the starting label is a zone cut. * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found */ /* NSEC3: Zone possible */ ya_result zdb_rr_label_delete_record_exact(zdb_zone* zone, dnslabel_vector_reference path, s32 path_index, u16 type, const zdb_ttlrdata *ttlrdata) { yassert(zdb_zone_iswritelocked(zone)); zdb_rr_label* apex = zone->apex; if(apex == NULL) { return ZDB_ERROR_DELETEFROMEMPTY; } /* Are we working on the apex ? */ if(path_index < 0) { if(ISOK(zdb_record_delete_exact(&apex->resource_record_set, type, ttlrdata))) /* FB done, APEX : no delegation */ { if(RR_LABEL_IRRELEVANT(apex)) { zdb_rr_label_free(zone, apex); // valid call because in a delete zone->apex = NULL; return ZDB_RR_LABEL_DELETE_TREE; } return ZDB_RR_LABEL_DELETE_NODE; } return ZDB_ERROR_KEY_NOTFOUND; } /* We are not working on the apex */ zdb_rr_label_delete_record_exact_process_callback_args args; args.sections = path; args.ttlrdata = ttlrdata; args.zone = zone; args.top = path_index; args.type = type; args.flags = 0; hashcode hash = hash_dnslabel(args.sections[args.top]); ya_result err; err = dictionary_process(&apex->sub, hash, &args, zdb_rr_label_delete_record_exact_process_callback); if(ISOK(err)) // == COLLECTION_PROCESS_DELETENODE { if(err == COLLECTION_PROCESS_DELETENODE) { if(RR_LABEL_IRRELEVANT(apex)) { zdb_rr_label_free(zone, apex); // valid call because in a delete zone->apex = NULL; return COLLECTION_PROCESS_DELETENODE; } /* If the label just removed is a wildcard, then the parent is marked as not having a wildcard. */ if(IS_WILD_LABEL(args.sections[args.top])) { zdb_rr_label_flag_and(apex, ~ZDB_RR_LABEL_GOT_WILD); } } /* If the label just removed is a wildcard, then the parent is marked as not having a wildcard. */ if(args.flags & 1) { return COLLECTION_PROCESS_DELETENODE; // LEAF } else { return COLLECTION_PROCESS_STOP; } } return err; } u16 zdb_rr_label_bitmap_type_init(zdb_rr_label *rr_label, type_bit_maps_context *bitmap) { const zdb_rr_collection collection = rr_label->resource_record_set; type_bit_maps_init(bitmap); btree_iterator iter; btree_iterator_init(collection, &iter); if(ZDB_LABEL_ATORUNDERDELEGATION(rr_label)) { while(btree_iterator_hasnext(&iter)) { btree_node* node = btree_iterator_next_node(&iter); u16 type = node->hash; if((type != TYPE_A) && (type != TYPE_AAAA)) { type_bit_maps_set_type(bitmap, type); } } } else { while(btree_iterator_hasnext(&iter)) { btree_node* node = btree_iterator_next_node(&iter); u16 type = node->hash; type_bit_maps_set_type(bitmap, type); } } u16 bitmap_size = type_bit_maps_update_size(bitmap); return bitmap_size; } void zdb_rr_label_print_indented(const zdb_rr_label *rr_label, output_stream *os, int indent) { osformatln(os, "%tl: '%{dnslabel}'(%u) #[%08x]", indent, rr_label->name, zdb_rr_label_flag_get(rr_label), hash_dnslabel(rr_label->name)); indent++; zdb_record_print_indented(rr_label->resource_record_set, os, indent); dictionary_iterator iter; dictionary_iterator_init(&rr_label->sub, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_rr_label** sub_labelp = (zdb_rr_label**)dictionary_iterator_next(&iter); zdb_rr_label_print_indented(*sub_labelp, os, indent); } } void zdb_rr_label_print(const zdb_rr_label *rr_label, output_stream *os) { zdb_rr_label_print_indented(rr_label, os, 0); } yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_sanitize.c0000644000000000000000000000013214505005531021615 xustar000000000000000030 mtime=1695812441.757972378 30 atime=1695812445.803030311 30 ctime=1695812495.122736668 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_sanitize.c0000664000374500037450000013555214505005531021572 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup zone Functions used to sanitize a zone * @ingroup dnsdb * @brief Functions used to sanitize a zone * * Functions used to sanitize a zone * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include "dnsdb/zdb_sanitize.h" #include "dnsdb/zdb_zone_load.h" #include "dnsdb/rrsig.h" #if DNSCORE_HAS_DNSSEC_SUPPORT #include "dnsdb/rrsig.h" #endif #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_error.h" #define SANITIZE_OVERSHARE 0 // don't, this is dev/debugging #define SANITIZE_LABEL_SUMMARY 0 // don't, this is dev/debugging #define SANTIZE_DROP_LONELY_DS 0 #define SANITIZE_DETECT_MISSING_GLUES 1 extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define TYPES_INIT(b_) u64 b_ = 0 #define TYPES_HAS(b_,t_) (((b_) & (1ULL << NU16(t_))) != 0) #define TYPES_ONLY_HAS(b_,t_) ((b_) == (1ULL << NU16(t_))) #define TYPES_SET(b_,t_) ((b_) |= (1ULL << NU16(t_))) #define TYPES_SET_OTHER(b_) ((b_) |= (1ULL << 0)) // zero must never be used, so it's a perfect place holder #define TYPES_CLEAR(b_,t_) ((b_) &= ~(1ULL << (t))) #define TYPES_AND_MASK(b_,m_) ((b_) & (m_)) static u8 u64_count_bits(u64 value) { static const u8 bitcount[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; u8 total = 0; while(value != 0) { total += bitcount[value & 0xff]; value >>= 8; } return total; } static void zdb_sanitize_parms_init(zdb_sanitize_parms *parms, zdb_zone *zone, struct zdb_zone_load_parms *load_parms) { memset(parms, 0, sizeof(*parms)); parms->zone = zone; u32_set_init(&parms->dnskey_set); parms->load_parms = load_parms; } #if ZDB_HAS_DNSSEC_SUPPORT static void zdb_sanitize_parms_update_keys(zdb_sanitize_parms *parms) { const zdb_packed_ttlrdata *dnskey_rrset = zdb_zone_get_dnskey_rrset(parms->zone); while(dnskey_rrset != NULL) { const u8 *dnskey_rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(dnskey_rrset); u32 dnskey_rdata_size = ZDB_PACKEDRECORD_PTR_RDATASIZE(dnskey_rrset); u16 keytag = dnskey_get_tag_from_rdata(dnskey_rdata, dnskey_rdata_size); u32_set_insert(&parms->dnskey_set, keytag); dnskey_rrset = dnskey_rrset->next; } } #endif void zdb_sanitize_parms_finalize(zdb_sanitize_parms *parms) { u32_set_destroy(&parms->dnskey_set); } #if SANITIZE_LABEL_SUMMARY static void zdb_sanitize_log(dnsname_stack *dnsnamev, ya_result err) { if(err & SANITY_UNEXPECTEDSOA) { log_warn("sanity: %{dnsnamestack} failed: unexpected SOA", dnsnamev); } if(err & SANITY_TOOMANYSOA) { log_err("sanity: %{dnsnamestack} failed: too many SOA", dnsnamev); } if(err & SANITY_CNAMENOTALONE) { log_warn("sanity: %{dnsnamestack} failed: CNAME must be alone", dnsnamev); } if(err & SANITY_UNEXPECTEDCNAME) { log_warn("sanity: %{dnsnamestack} failed: unexpected CNAME", dnsnamev); } if(err & SANITY_EXPECTEDNS) { log_warn("sanity: %{dnsnamestack} failed: expected NS", dnsnamev); } if(err & SANITY_UNEXPECTEDDS) { log_warn("sanity: %{dnsnamestack} failed: unexpected DS", dnsnamev); } if(err & SANITY_MUSTDROPZONE) { log_err("sanity: %{dnsnamestack} critical error : the zone will be dropped", dnsnamev); } if(err & SANITY_TRASHATDELEGATION) { log_warn("sanity: %{dnsnamestack} failed: delegation has unexpected records", dnsnamev); } if(err & SANITY_TRASHUNDERDELEGATION) { log_warn("sanity: %{dnsnamestack} failed: non-glue record(s) found under delegation", dnsnamev); } // SANITY_TOOMANYNSEC is not used if(err & SANITY_RRSIGWITHOUTKEYS) { log_warn("sanity: %{dnsnamestack} failed: RRSIG record(s) without matched DNSKEY", dnsnamev); } if(err & SANITY_RRSIGWITHOUTSET) { log_warn("sanity: %{dnsnamestack} failed: RRSIG record(s) over an absent RRSET", dnsnamev); } if(err & SANITY_RRSIGTTLDOESNTMATCH) { log_warn("sanity: %{dnsnamestack} failed: RRSIG record(s) TTL does not match the one of the covered RRSET", dnsnamev); } } #endif /** * There must be an NS rrset on the path that matches the name */ static void zdb_sanitize_rr_set_useless_glue(zdb_zone *zone, zdb_rr_label *label, dnsname_stack *name, zdb_rr_label** parent) { zdb_rr_label** delegation = parent; // start from the parent // while there is a delegation while(*delegation != NULL) { zdb_packed_ttlrdata* delegation_ns_record_list_head = zdb_record_find(&(*delegation)->resource_record_set, TYPE_NS); // if there is an NS rrset if(delegation_ns_record_list_head != NULL) { do { if(dnsname_equals_dnsname_stack(ZDB_PACKEDRECORD_PTR_RDATAPTR(delegation_ns_record_list_head), name)) { // if the fqdn in the rdata matches the glue, there is nothing further return; } delegation_ns_record_list_head = delegation_ns_record_list_head->next; } while(delegation_ns_record_list_head != NULL); } --delegation; } // the NS fqdn has not been found : warn about it static const u16 ip_types[2] = {TYPE_A, TYPE_AAAA}; for(int i = 0; i < 2; ++i) { zdb_packed_ttlrdata* ip_record_list = zdb_record_find(&label->resource_record_set, ip_types[i]); if(ip_record_list != NULL) { rdata_desc rdatadesc; rdatadesc.type = ip_types[i]; rdatadesc.len = ZDB_PACKEDRECORD_PTR_RDATASIZE(ip_record_list); rdatadesc.rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(ip_record_list); log_warn("sanity: %{dnsname}: consider removing wrong glue: %{dnsnamestack} %{typerdatadesc}", zone->origin, name, &rdatadesc); } } } static u32 zdb_sanitize_rr_set_ext(zdb_sanitize_parms *parms, zdb_rr_label *label, dnsname_stack *name, u16 flags, zdb_rr_label** parent) { zdb_zone *zone = parms->zone; /* * CNAME : nothing else than RRSIG & NSEC */ // record counts for ... (can overlap) const u64 not_cmake_nsec_rrsig_mask = ~((1ULL<apex == label; bool at_delegation = flags & ZDB_RR_LABEL_DELEGATION; bool under_delegation = flags & ZDB_RR_LABEL_UNDERDELEGATION; btree_iterator iter; btree_iterator_init(label->resource_record_set, &iter); while(btree_iterator_hasnext(&iter)) { btree_node* node = btree_iterator_next_node(&iter); u16 type = node->hash; zdb_packed_ttlrdata* record_list = (zdb_packed_ttlrdata*)node->data; if(type != TYPE_RRSIG) { s32 ttl = record_list->ttl; while((record_list = record_list->next) != NULL) { record_list->ttl = ttl; } } else { u16 keytag = rrsig_get_key_tag_from_rdata(ZDB_PACKEDRECORD_PTR_RDATAPTR(record_list), ZDB_PACKEDRECORD_PTR_RDATASIZE(record_list)); u32_node *node = u32_set_find(&parms->dnskey_set, keytag); if(node != NULL) { // no key for this signature u16 rrsig_ctype = rrsig_get_type_covered_from_rdata(ZDB_PACKEDRECORD_PTR_RDATAPTR(record_list), ZDB_PACKEDRECORD_PTR_RDATASIZE(record_list)); s32 rrsig_ttl = rrsig_get_original_ttl_from_rdata(ZDB_PACKEDRECORD_PTR_RDATAPTR(record_list), ZDB_PACKEDRECORD_PTR_RDATASIZE(record_list)); record_list->ttl = rrsig_ttl; zdb_packed_ttlrdata *rrsig_ctype_rrset = zdb_record_find(&label->resource_record_set, rrsig_ctype); if(rrsig_ctype_rrset != NULL) { s32 rrsig_ctype_ttl = rrsig_ctype_rrset->ttl; if(rrsig_ctype_ttl != rrsig_ttl) { // signature TTL is wrong rr_set_status |= SANITY_RRSIGTTLDOESNTMATCH; parms->has_bogus_rrsig = TRUE; } } else { // signature covered type wrong rr_set_status |= SANITY_RRSIGWITHOUTSET; parms->has_bogus_rrsig = TRUE; log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: RRSIG covers a non-existing resource record set %{dnstype}", zone->origin, name, &rrsig_ctype); } /// @note : maybe also verify RRSIG signature } else { rr_set_status |= SANITY_RRSIGWITHOUTKEYS; parms->has_bogus_rrsig = TRUE; log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: RRSIG made with key with tag=%hu but there is no such key", zone->origin, name, keytag); } } if((type & NU16(0xffc0)) == 0) // only handle the 64 first types { if(type == TYPE_SOA) { if(TYPES_HAS(dns_rrset_types, TYPE_SOA)) { if(isapex) { rr_set_status |= SANITY_UNEXPECTEDSOA | SANITY_MUSTDROPZONE; log_warn("zone: sanitize: %{dnsname}: too many SOA", zone->origin); } else { rr_set_status |= SANITY_UNEXPECTEDSOA; log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: unexpected SOA", zone->origin, name); } } } TYPES_SET(dns_rrset_types, type); // types bitmap } else { TYPES_SET_OTHER(dns_rrset_types); } } parms->types_mask |= dns_rrset_types; #if ZDB_HAS_DNSSEC_SUPPORT if(parms->load_parms != NULL) // gather information about signature status { if(TYPES_HAS(dns_rrset_types, TYPE_DNSKEY)) { const zdb_packed_ttlrdata* dnskey_record_list = zdb_record_find(&label->resource_record_set, TYPE_DNSKEY); const zdb_packed_ttlrdata* dnskey = dnskey_record_list; while(dnskey != NULL) { zdb_zone_load_parms_dnskey_add(parms->load_parms, ZDB_PACKEDRECORD_PTR_RDATAPTR(dnskey), ZDB_PACKEDRECORD_PTR_RDATASIZE(dnskey)); dnskey = dnskey->next; } } TYPES_INIT(rrsig_covered_types); if(TYPES_HAS(dns_rrset_types, TYPE_RRSIG)) { // bool has_ds = TYPES_HAS(dns_rrset_types, TYPE_DS); const zdb_packed_ttlrdata* rrsig_record_list = zdb_record_find(&label->resource_record_set, TYPE_RRSIG); const zdb_packed_ttlrdata* rrsig = rrsig_record_list; // the signing key must be known while(rrsig != NULL) { u16 covered_type = rrsig_get_type_covered_from_rdata(ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig)); u16 flags = zdb_zone_load_parms_get_key_flags_from_rrsig_rdata(parms->load_parms, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig)); if(flags == 0) { flags = DNSKEY_FLAGS_ZSK; // assume ZSK } if((covered_type & NU16(0xffc0)) == 0) { TYPES_SET(rrsig_covered_types, covered_type); // types bitmap if(covered_type != TYPE_RRSIG) { TYPES_SET(rrsig_covered_types, covered_type); // types bitmap if(flags == DNSKEY_FLAGS_ZSK) { if(TYPES_HAS(dns_rrset_types, covered_type)) { // signed ... // should type signed for NSEC ? // yes, always at or above delegations // should type signed for NSEC3 OPTIN ? // yes, always at or above delegations // should type signed for NSEC3 OPTOUT ? // everything but delegations without a DS and under delegations if(at_delegation) { // NS & DS for NSEC & NSEC3IN // if has_ds DS for NSEC3OUT switch(covered_type) { case TYPE_NS: #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: N3O: NS at delegation should not be signed", name); #endif ++parms->nsec3out_extraneous_rrsig; break; case TYPE_DS: break; default: #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: ANY: %{dnstype} at delegation should not be signed", name, &covered_type); #endif ++parms->nsec_extraneous_rrsig; ++parms->nsec3in_extraneous_rrsig; ++parms->nsec3out_extraneous_rrsig; break; } } else if(under_delegation) { // nothing if((dns_rrset_types & ns_ds_mask) == 0) { #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: ANY: %{dnstype} under delegation should not be signed", name, &covered_type); #endif ++parms->nsec_extraneous_rrsig; ++parms->nsec3in_extraneous_rrsig; ++parms->nsec3out_extraneous_rrsig; rr_set_status |= SANITY_RRSIGUNDERDELETATION; log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: unexpected RRSIG under a delegation", zone->origin, name); } } else { // should be signed so it's all right } } else { // signature covers a type that's not present #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: ANY: %{dnstype} is signed but not present", name, &covered_type); #endif rr_set_status |= SANITY_RRSIGWITHOUTSET; log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: RRSIG covers a non-existing resource record set %{dnstype}", zone->origin, name, &covered_type); } } else if(flags == DNSKEY_FLAGS_KSK) { if(covered_type != TYPE_DNSKEY) { rr_set_status |= SANITY_RRSIGBYKSKOVERNONKEY; #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: ANY: %{dnstype} is signed by a key signing key", name, &covered_type); #endif log_warn("zone: sanitize: %{dnsname}: key-signing-key used to sign a %{dnstype} rrset", zone->origin, &covered_type); ++parms->nsec_extraneous_rrsig; ++parms->nsec3in_extraneous_rrsig; ++parms->nsec3out_extraneous_rrsig; } else if(!isapex) { #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: ANY: %{dnstype} is used out of the apex", name, &covered_type); #endif log_warn("zone: sanitize: %{dnsname}: key-signing-key used out of the apex", zone->origin); ++parms->nsec_extraneous_rrsig; ++parms->nsec3in_extraneous_rrsig; ++parms->nsec3out_extraneous_rrsig; rr_set_status |= SANITY_RRSIGBYKSKNOTINAPEX; } } else { // ignored } } else { rr_set_status |= SANITY_RRSIGOVERRRSIG; log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: unexpected RRSIG of an RRSIG", zone->origin, name); } } else { if(at_delegation) { // NS & DS for NSEC & NSEC3IN // if has_ds DS for NSEC3OUT #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: ANY: %{dnstype} at delegation should not be signed", name, &covered_type); #endif ++parms->nsec_extraneous_rrsig; ++parms->nsec3in_extraneous_rrsig; ++parms->nsec3out_extraneous_rrsig; } else if(under_delegation) { // nothing if((dns_rrset_types & ns_ds_mask) == 0) { #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: ANY: %{dnstype} under delegation should not be signed", name, &covered_type); #endif ++parms->nsec_extraneous_rrsig; ++parms->nsec3in_extraneous_rrsig; ++parms->nsec3out_extraneous_rrsig; rr_set_status |= SANITY_RRSIGUNDERDELETATION; log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: unexpected RRSIG under a delegation", zone->origin, name); } else { // we are in the delegation under a delegation case } } else { // should be signed so it's all right } TYPES_SET_OTHER(rrsig_covered_types); } zdb_zone_load_parms_rrsig_add(parms->load_parms, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig)); rrsig = rrsig->next; } // dns_rrset_types // rrsig_covered_types u64 missing_types = dns_rrset_types & ~rrsig_covered_types & not_rrsig_mask; // missing type is the mask of missing signatures for types if(missing_types != 0) { if(at_delegation) { // NS & DS for NSEC & NSEC3IN // if has_ds DS for NSEC3OUT if((missing_types & ns_ds_mask) != 0) { u8 count = u64_count_bits(missing_types & ns_ds_mask); #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: NSEC,N3I: %i types at delegation are not covered by any signature", name, count); #endif parms->nsec_missing_rrsig += count; parms->nsec3in_missing_rrsig += count; } if((missing_types & ds_mask) != 0) { u8 count = u64_count_bits(missing_types & ds_mask); #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: N3O: %i types at delegation are not covered by any signature", name, count); #endif parms->nsec3out_missing_rrsig += count; } } else if(under_delegation) { // nothing } else { // everything should be signed u8 count = u64_count_bits(missing_types); #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: ANY: %i types are not covered by any signature", name, count); #endif parms->nsec_missing_rrsig += count; parms->nsec3in_missing_rrsig += count; parms->nsec3out_missing_rrsig += count; } } } else // no signature found in this label { // dns_rrset_types // rrsig_covered_types u64 missing_types = dns_rrset_types & ~rrsig_covered_types; // missing type is the mask of missing signatures for types if(missing_types != 0) { if(at_delegation) { // NS & DS for NSEC & NSEC3IN // if has_ds DS for NSEC3OUT if((missing_types & ns_ds_mask) != 0) { u8 count = u64_count_bits(missing_types & ns_ds_mask); #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: NSEC,N3I: %i types at delegation are not covered by any signature (there are none)", name, count); #endif parms->nsec_missing_rrsig += count; parms->nsec3in_missing_rrsig += count; } if((missing_types & ds_mask) != 0) { u8 count = u64_count_bits(missing_types & ds_mask); #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: N3O: %i types at delegation are not covered by any signature (there are none)", name, count); #endif parms->nsec3out_missing_rrsig += count; } } else if(under_delegation) { // nothing } else { // everything should be signed u8 count = u64_count_bits(missing_types); #if SANITIZE_OVERSHARE log_warn("sanity: %{dnsnamestack}: ANY: %i types are not covered by any signature (there are none)", name, count); #endif parms->nsec_missing_rrsig += count; parms->nsec3in_missing_rrsig += count; parms->nsec3out_missing_rrsig += count; } } } } #endif // ZDB_HAS_DNSSEC_SUPPORT if(isapex) { if(TYPES_HAS(dns_rrset_types, TYPE_CNAME)) { /* * No CNAME at apex */ rr_set_status |= SANITY_UNEXPECTEDCNAME; /* * Remove them all */ log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: CNAME record is not allowed at the apex", zone->origin, name); } /* * supposed to have one NS at apex */ if(!TYPES_HAS(dns_rrset_types, TYPE_NS)) { rr_set_status |= SANITY_EXPECTEDNS; /* * Just report it */ log_warn("zone: sanitize: %{dnsname}: expected NS record at apex", zone->origin); } if(TYPES_HAS(dns_rrset_types, TYPE_DS)) { /* * cannot have a DS at apex */ rr_set_status |= SANITY_UNEXPECTEDDS; log_warn("zone: sanitize: %{dnsname}: unexpected DS record at apex", zone->origin); } zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED|ZDB_RR_LABEL_N3OCOVERED); } else // ! apex { if(TYPES_HAS(dns_rrset_types, TYPE_CNAME)) { // Cannot accept anything else other than RRSIG & NSEC if((TYPES_AND_MASK(dns_rrset_types, not_cmake_nsec_rrsig_mask)) != 0) { rr_set_status |= SANITY_CNAMENOTALONE; log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: CNAME record can only be next to NSEC and/or RRSIG records", zone->origin, name); } /* * Other DNS record types, such as NS, MX, PTR, SRV, etc. that point to other names should never point to a CNAME alias. * => insanely expensive to test */ } if(TYPES_HAS(dns_rrset_types, TYPE_DS)) { /* * MUST have an NS with a DS */ if(TYPES_HAS(dns_rrset_types, TYPE_NS)) { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED|ZDB_RR_LABEL_N3OCOVERED); } else { rr_set_status |= SANITY_EXPECTEDNS; zdb_rr_label_flag_and(label, ~(ZDB_RR_LABEL_N3COVERED|ZDB_RR_LABEL_N3OCOVERED)); log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: expected NS record or unexpected DS record", zone->origin, name); } } if(at_delegation) { #if SANITIZE_DETECT_MISSING_GLUES /// The 3 SANITIZE_DETECT_MISSING_GLUES blocs are for the detection of NS that should have a glue but do not have one. const zdb_packed_ttlrdata* ns_record_list = NULL; #endif // SANITIZE_DETECT_MISSING_GLUES if(TYPES_HAS(dns_rrset_types, TYPE_NS)) { #if SANITIZE_DETECT_MISSING_GLUES ns_record_list = zdb_record_find(&label->resource_record_set, TYPE_NS); /* verify if the NS warrants a glue and if said glue exists */ const zdb_packed_ttlrdata* record_list = ns_record_list; while(record_list != NULL) { const u8* nameserver_name = ZDB_PACKEDRECORD_PTR_RDATAPTR(record_list); /* * check if the nameserver ends with our name * if it does then it needs a glue * look if said glue exists * _ any A/AAAA record at or under delegation that is not in this list needs to be removed * _ any missing A/AAAA record at or under delegation that is in this list needs to be added */ if(dnsname_under_dnsname_stack(nameserver_name, name)) { /** * needs glue * * @todo 20120123 edf -- check if the glue is present * */ } record_list = record_list->next; } #endif // SANITIZE_DETECT_MISSING_GLUES } else { rr_set_status |= SANITY_EXPECTEDNS; #if SANITIZE_DETECT_MISSING_GLUES ns_record_list = NULL; #endif // SANITIZE_DETECT_MISSING_GLUES } if((TYPES_AND_MASK(dns_rrset_types, a_aaaa_mask) != 0) && (parent != NULL)) { zdb_sanitize_rr_set_useless_glue(zone, label, name, parent); } /* * If we have anything except NS DS NSEC RRSIG ... */ if(TYPES_AND_MASK(dns_rrset_types, not_ns_ds_nsec_rrsig_mask) != 0) { // If A/AAAA is all we have (+ NS and + DS) if((TYPES_AND_MASK(dns_rrset_types, not_a_aaaa_ns_ds_mask) == 0) && (TYPES_AND_MASK(dns_rrset_types, a_aaaa_mask) != 0)) { //zdb_packed_ttlrdata* record_list = ns_record_list; if(ns_record_list == NULL) { ns_record_list = zdb_record_find(&label->resource_record_set, TYPE_NS); } const zdb_packed_ttlrdata* record_list = ns_record_list; // sanitize while(record_list != NULL) { if(dnsname_equals_dnsname_stack(ZDB_PACKEDRECORD_PTR_RDATAPTR(record_list), name)) { ns_points_to_itself = TRUE; break; } record_list = record_list->next; } } if(!ns_points_to_itself) { rr_set_status |= SANITY_TRASHATDELEGATION; // A or AAAA record at delegation } } zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED); // delegation case } else if(under_delegation) { if((TYPES_AND_MASK(dns_rrset_types, a_aaaa_mask) != 0) && (parent != NULL)) { zdb_sanitize_rr_set_useless_glue(zone, label, name, parent); } if(TYPES_AND_MASK(dns_rrset_types & not_ns_ds_nsec_rrsig_mask, not_a_aaaa_mask) != 0) { rr_set_status |= SANITY_TRASHUNDERDELEGATION; log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: unexpected types under a delegation", zone->origin, name); } // zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED); } else // not under delegation either { #if SANTIZE_DROP_LONELY_DS if(!TYPES_ONLY_HAS(dns_rrset_types, TYPE_DS)) { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED|ZDB_RR_LABEL_N3OCOVERED); } else { // lonley DS record log_warn("zone: sanitize: %{dnsname}: %{dnsnamestack}: isolated DS record", zone->origin, name); u8 name_fqdn[MAX_DOMAIN_LENGTH]; dnsname_vector name_vector; dnsname_stack_to_dnsname(name, name_fqdn); dnsname_to_dnsname_vector(name_fqdn, &name_vector); zdb_rr_label_delete_record(zone, name_vector.labels, (name_vector.size - zone->origin_vector.size) - 1, TYPE_ANY); rr_set_status |= SANITY_LABEL_DELETED; } #else zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED|ZDB_RR_LABEL_N3OCOVERED); #endif } } if(rr_set_status != 0) { rr_set_status |= SANITY_ERROR_BASE; } return rr_set_status; } static ya_result zdb_sanitize_rr_label_ext(zdb_sanitize_parms *parms, zdb_rr_label *label, dnsname_stack *name, u16 flags, zdb_rr_label** parent) { /** * * For all labels: check the label is right. * */ ya_result return_value; if((flags & (ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION)) != 0) { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_UNDERDELEGATION); } else { zdb_rr_label_flag_and(label, ~ZDB_RR_LABEL_UNDERDELEGATION); } if(parent != NULL) { parent++; *parent = label; } u32 rr_set_status; if((rr_set_status = zdb_sanitize_rr_set_ext(parms, label, name, zdb_rr_label_flag_get(label), parent)) != 0) { #if SANITIZE_LABEL_SUMMARY zdb_sanitize_log(name, return_value); #endif if((rr_set_status & SANITY_MUSTDROPZONE) != 0) { /** * Can stop here */ return ERROR; } } if(rr_set_status & SANITY_LABEL_DELETED) { return SUCCESS; } u16 shutdown_test_countdown = 10000; dictionary_iterator iter; dictionary_iterator_init(&label->sub, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_rr_label **sub_labelp = (zdb_rr_label**)dictionary_iterator_next(&iter); dnsname_stack_push_label(name, (*sub_labelp)->name); return_value = zdb_sanitize_rr_label_ext(parms, *sub_labelp, name, zdb_rr_label_flag_get(label), parent); /* * If this label is under (or at) delegation * For each A/AAAA record * Ensure there are NS at delegation linked to said records. */ dnsname_stack_pop_label(name); if(FAIL(return_value)) { return return_value; } if(--shutdown_test_countdown == 0) { if(dnscore_shuttingdown()) { return STOPPED_BY_APPLICATION_SHUTDOWN; } shutdown_test_countdown = 1000; } } return SUCCESS; } #if ZDB_HAS_NSEC3_SUPPORT static ya_result zdb_sanitize_zone_nsec3(zdb_sanitize_parms *parms) { zdb_zone *zone = parms->zone; nsec3_zone* n3 = zone->nsec.nsec3; s32 soa_nttl = zone->min_ttl; while(n3 != NULL) { #if DNSSEC_DEBUGLEVEL>2 u32 nsec3_count = 0; log_debug("dnssec_process_zone_nsec3_body: processing NSEC3 collection"); #endif nsec3_iterator nsec3_items_iter; nsec3_iterator_init(&n3->items, &nsec3_items_iter); if(nsec3_iterator_hasnext(&nsec3_items_iter)) { nsec3_zone_item* first = nsec3_iterator_next_node(&nsec3_items_iter); nsec3_zone_item* item = first; nsec3_zone_item* next; do { if(dnscore_shuttingdown()) { #if DNSSEC_DEBUGLEVEL>2 log_debug("dnssec_process_zone_nsec3_body: STOPPED_BY_APPLICATION_SHUTDOWN"); #endif return STOPPED_BY_APPLICATION_SHUTDOWN; } if(nsec3_iterator_hasnext(&nsec3_items_iter)) { next = nsec3_iterator_next_node(&nsec3_items_iter); } else { next = first; } zdb_packed_ttlrdata *rrsig = item->rrsig; // the signing key must be known while(rrsig != NULL) { s32 rrsig_ttl = rrsig_get_original_ttl_from_rdata(ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig)); if(rrsig_ttl != soa_nttl) { log_warn("%{digest32h}.%{dnsname} RRSIG's TTL does not match the NTTL (%i != %i)", item->digest, zone->origin, rrsig_ttl, soa_nttl); // RRSIG TTL does not match NTTL parms->has_bogus_rrsig = TRUE; } rrsig->ttl = soa_nttl; zdb_zone_load_parms_rrsig_add(parms->load_parms, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig)); rrsig = rrsig->next; } item = next; #if DNSSEC_DEBUGLEVEL>2 nsec3_count++; #endif } while(next != first); } /* If there is a first item*/ #if DNSSEC_DEBUGLEVEL>2 log_debug("dnssec_process_zone_nsec3_body: processed NSEC3 collection (%d items)", nsec3_count); #endif n3 = n3->next; } /* while n3 != NULL */ return SUCCESS; } #endif ya_result zdb_sanitize_zone_ex(zdb_zone *zone, struct zdb_zone_load_parms *load_parms) { if(zone->apex == NULL) { return ERROR; } zdb_sanitize_parms *parmsp = &load_parms->sanitize_parms; zdb_sanitize_parms_init(parmsp, zone, load_parms); zdb_sanitize_parms_update_keys(parmsp); zdb_rr_label* label_stack[256]; label_stack[0] = NULL; dnsname_stack name; dnsname_to_dnsname_stack(zone->origin, &name); ya_result return_code = zdb_sanitize_rr_label_ext(parmsp, zone->apex, &name, 0, label_stack); if(ISOK(return_code)) { #if ZDB_HAS_NSEC3_SUPPORT if((zone_get_maintain_mode(zone) & ZDB_ZONE_MAINTAIN_NSEC3) != 0) { if(zdb_zone_is_nsec3(zone)) { return_code = zdb_sanitize_zone_nsec3(parmsp); } } #endif } load_parms->state |= ZDB_ZONE_LOAD_STATE_SANITIZE_FIELD_AVAIABLE; // zdb_sanitize_parms_finalize(parmsp); return return_code; } ya_result zdb_sanitize_zone(zdb_zone *zone) { if(zone->apex == NULL) { return ERROR; } zdb_sanitize_parms parms; zdb_sanitize_parms_init(&parms, zone, NULL); zdb_sanitize_parms_update_keys(&parms); zdb_rr_label* label_stack[256]; label_stack[0] = NULL; dnsname_stack name; dnsname_to_dnsname_stack(zone->origin, &name); ya_result return_code = zdb_sanitize_rr_label_ext(&parms, zone->apex, &name, 0, label_stack); if(ISOK(return_code)) { #if ZDB_HAS_NSEC3_SUPPORT if((zone_get_maintain_mode(zone) & ZDB_ZONE_MAINTAIN_NSEC3) != 0) { if(zdb_zone_is_nsec3(zone)) { return_code = zdb_sanitize_zone_nsec3(&parms); } } #endif } zdb_sanitize_parms_finalize(&parms); return return_code; } bool zdb_sanitize_is_good_for_chains(struct zdb_zone_load_parms *load_parms, u8 dnssec_mode) { if((load_parms->state & ZDB_ZONE_LOAD_STATE_SANITIZE_FIELD_AVAIABLE) != 0) { switch(dnssec_mode) { case ZDB_ZONE_NOSEC: { return TRUE; } case ZDB_ZONE_NSEC: { return !(load_parms->sanitize_parms.has_bogus_rrsig) && (load_parms->sanitize_parms.nsec_missing_rrsig + load_parms->sanitize_parms.nsec_extraneous_rrsig) == 0; } case ZDB_ZONE_NSEC3: { return !(load_parms->sanitize_parms.has_bogus_rrsig) &&(load_parms->sanitize_parms.nsec3in_missing_rrsig + load_parms->sanitize_parms.nsec3in_extraneous_rrsig) == 0; } case ZDB_ZONE_NSEC3_OPTOUT: { return !(load_parms->sanitize_parms.has_bogus_rrsig) &&(load_parms->sanitize_parms.nsec3out_missing_rrsig + load_parms->sanitize_parms.nsec3out_extraneous_rrsig) == 0; } default: { return FALSE; // unexpected state, assume sanitisaiton is useless } } } else { return dnssec_mode == ZDB_ZONE_NOSEC; // no sanitisation results available, only consider it "good" if DNSSEC is not used for the zone } } bool zdb_sanitize_is_good(struct zdb_zone_load_parms *load_parms, u8 dnssec_mode) { if((load_parms->state & ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_AVAILABLE) == 0) { if(zdb_sanitize_is_good_for_chains(load_parms, dnssec_mode)) { load_parms->state |= ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_AVAILABLE; return TRUE; } else { load_parms->state |= ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_AVAILABLE|ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_MAINTENANCE_REQUIRED; return FALSE; } } else { return (load_parms->state & ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_MAINTENANCE_REQUIRED) == 0; } } static void zdb_sanitize_zone_rrset_flags_records(zdb_rr_label *label, dnsname_stack *name, u16 flags, zdb_rr_label** parent) { (void)name; (void)parent; TYPES_INIT(dns_rrset_types); bool under_delegation = flags & ZDB_RR_LABEL_UNDERDELEGATION; if(under_delegation) { zdb_rr_label_flag_and(label, ~(ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_N3COVERED|ZDB_RR_LABEL_N3OCOVERED)); return; } bool at_delegation = flags & ZDB_RR_LABEL_DELEGATION; if(at_delegation) { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED); // delegation case btree_iterator iter; btree_iterator_init(label->resource_record_set, &iter); while(btree_iterator_hasnext(&iter)) { btree_node* node = btree_iterator_next_node(&iter); u16 type = node->hash; zdb_packed_ttlrdata* record_list = (zdb_packed_ttlrdata*)node->data; if(type != TYPE_RRSIG) { s32 ttl = record_list->ttl; while((record_list = record_list->next) != NULL) { record_list->ttl = ttl; } } if((type & NU16(0xffc0)) == 0) // only handle the 64 first types { TYPES_SET(dns_rrset_types, type); // types bitmap } else { TYPES_SET_OTHER(dns_rrset_types); } if(TYPES_HAS(dns_rrset_types, TYPE_DS)) { /* * MUST have an NS with a DS */ if(TYPES_HAS(dns_rrset_types, TYPE_NS)) { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED|ZDB_RR_LABEL_N3OCOVERED); } else { zdb_rr_label_flag_and(label, ~ZDB_RR_LABEL_N3OCOVERED); } } } return; } // not under delegation either zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED|ZDB_RR_LABEL_N3OCOVERED); } static ya_result zdb_sanitize_zone_rrset_flags_label(zdb_rr_label *label, dnsname_stack *name, u16 flags, zdb_rr_label **parent) { if((label == NULL) || (name == NULL) || (parent == NULL)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } u16 shutdown_test_countdown = 10000; ya_result ret = SUCCESS; if((flags & (ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION)) != 0) { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_UNDERDELEGATION); } else { zdb_rr_label_flag_and(label, ~ZDB_RR_LABEL_UNDERDELEGATION); } zdb_sanitize_zone_rrset_flags_records(label, name, zdb_rr_label_flag_get(label), parent); dictionary_iterator iter; dictionary_iterator_init(&label->sub, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_rr_label **sub_labelp = (zdb_rr_label**)dictionary_iterator_next(&iter); dnsname_stack_push_label(name, (*sub_labelp)->name); ret = zdb_sanitize_zone_rrset_flags_label(*sub_labelp, name, zdb_rr_label_flag_get(label), parent); /* * If this label is under (or at) delegation * For each A/AAAA record * Ensure there are NS at delegation linked to said records. */ dnsname_stack_pop_label(name); if(FAIL(ret)) { return ret; } if(--shutdown_test_countdown == 0) { if(dnscore_shuttingdown()) { return STOPPED_BY_APPLICATION_SHUTDOWN; } shutdown_test_countdown = 1000; } } return ret; } ya_result zdb_sanitize_zone_rrset_flags(zdb_zone *zone) { if(zone->apex == NULL) { return ERROR; } zdb_rr_label* label_stack[256]; label_stack[0] = NULL; dnsname_stack name; dnsname_to_dnsname_stack(zone->origin, &name); ya_result ret = zdb_sanitize_zone_rrset_flags_label(zone->apex, &name, 0, label_stack); return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_utils.c0000644000000000000000000000013214505005531021127 xustar000000000000000030 mtime=1695812441.724971905 30 atime=1695812445.801030282 30 ctime=1695812495.124736697 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_utils.c0000664000374500037450000000720014505005531021070 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #include #if ZDB_HAS_DNSSEC_SUPPORT #include "dnsdb/dnssec.h" #endif #include "dnsdb/zdb_error.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_zone_label_iterator.h" /* * */ ya_result osprint_query_ex_section(output_stream* os, zdb_resourcerecord* section) { while(section != NULL) { osformat(os, "%{dnsname} %-6d %{dnsclass} %{dnstype} ", section->name, section->ttl_rdata->ttl, §ion->zclass, §ion->rtype); osprint_rdata(os, section->rtype, ZDB_PACKEDRECORD_PTR_RDATAPTR(section->ttl_rdata), ZDB_PACKEDRECORD_PTR_RDATASIZE(section->ttl_rdata)); osprintln(os, ""); section = section->next; } osprint_char(os, '\n'); return 0; } void print_query_ex_section(zdb_resourcerecord* section) { osprint_query_ex_section(termout, section); } void osprint_query_ex(output_stream* os, zdb_query_ex_answer* answer) { if(answer->answer != NULL) { osprint(os, ";; ANSWER SECTION:\n"); osprint_query_ex_section(os, answer->answer); } if(answer->authority != NULL) { osprint(os, ";; AUTHORITY SECTION:\n"); osprint_query_ex_section(os, answer->authority); } if(answer->additional != NULL) { osprint(os, ";; ADDITIONAL SECTION:\n"); osprint_query_ex_section(os, answer->additional); } } void print_query_ex(zdb_query_ex_answer* answer) { osprint_query_ex(termout, answer); } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_zone.c0000644000000000000000000000013114505005531020741 xustar000000000000000029 mtime=1695812441.71697179 30 atime=1695812445.801030282 30 ctime=1695812495.126736726 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_zone.c0000664000374500037450000011232714505005531020712 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #define DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS 0 #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS #pragma message("WARNING: DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS enabled !") #endif #define ZDB_JOURNAL_CODE 1 #include "dnsdb/dnsdb-config.h" #include #include #include #if DEBUG #include #endif #include #include #include #include "dnsdb/dnsdb-config.h" #include "dnsdb/dnssec-keystore.h" #include "dnsdb/zdb_icmtl.h" #include "dnsdb/zdb.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_error.h" #include "dnsdb/dnsrdata.h" #include "dnsdb/journal.h" #include "dnsdb/dynupdate-diff.h" #include "dnsdb/dynupdate-message.h" #include "dnsdb/zdb-zone-path-provider.h" #if DNSCORE_HAS_DNSSEC_SUPPORT #include "dnsdb/rrsig.h" #if ZDB_HAS_NSEC_SUPPORT #include "dnsdb/nsec.h" #endif #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif #endif #ifndef HAS_DYNUPDATE_DIFF_ENABLED #error "HAS_DYNUPDATE_DIFF_ENABLED not defined" #endif #if DEBUG #define ZONE_MUTEX_LOG 0 // set this to 0 to disable in DEBUG #else #define ZONE_MUTEX_LOG 0 #endif extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define TMPRDATA_TAG 0x4154414452504d54 #if HAS_TRACK_ZONES_DEBUG_SUPPORT smp_int g_zone_instanciated_count = SMP_INT_INITIALIZER; ptr_set g_zone_instanciated_set = PTR_SET_PTR_EMPTY; #endif static void zdb_zone_record_or_and_flags_to_subdomains(zdb_rr_label *rr_label, u16 orflags, u16 andflags) { dictionary_iterator iter; dictionary_iterator_init(&rr_label->sub, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_rr_label** sub_labelp = (zdb_rr_label**)dictionary_iterator_next(&iter); zdb_rr_label_flag_or_and(*sub_labelp, orflags, andflags), zdb_zone_record_or_and_flags_to_subdomains(*sub_labelp, orflags, andflags); } } /** * @brief Adds a record to a zone * * Adds a record to a zone. * * @note Expects the full fqdn in the labels parameter. "." has a labels_top at -1 * * * @param[in] zone the zone * @param[in] labels the stack of labels of the dns name * @param[in] labels_top the index of the top of the stack (the level) * @param[in] type the type of the record * @param[in] ttlrdata the ttl and rdata of the record. NOTE: the zone becomes its new owner !!! */ void zdb_zone_record_add(zdb_zone *zone, dnslabel_vector_reference labels, s32 labels_top, u16 type, zdb_packed_ttlrdata *ttlrdata) { zdb_rr_label *rr_label = zdb_rr_label_add(zone, labels, labels_top - zone->origin_vector.size - 1); // flow verified /* This record will be put as it is in the DB */ #if ZDB_HAS_NSEC_SUPPORT /* * At this point I could add empty nsec3 records, or schedule the nsec3 signature */ #endif u16 flag_mask = 0; switch(type) { case TYPE_CNAME: { if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_DROPCNAME)) { log_err("zone %{dnsname}: ignoring CNAME add on non-CNAME", zone->origin); ZDB_RECORD_ZFREE(ttlrdata); return; } flag_mask = ZDB_RR_LABEL_HASCNAME; break; } case TYPE_RRSIG: { if(!zdb_record_insert_checked_keep_ttl(&rr_label->resource_record_set, type, ttlrdata)) /* FB done */ { ZDB_RECORD_ZFREE(ttlrdata); return; } zdb_rr_label_flag_or(rr_label, flag_mask); return; } case TYPE_NSEC: break; case TYPE_NS: { if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_HASCNAME)) { log_err("zone %{dnsname}: ignoring NS add on CNAME", zone->origin); ZDB_RECORD_ZFREE(ttlrdata); return; } if(zdb_rr_label_is_not_apex(rr_label)) { // handle the sub-delegation case if(zdb_rr_label_flag_isclear(rr_label, ZDB_RR_LABEL_UNDERDELEGATION)) { flag_mask = ZDB_RR_LABEL_DELEGATION; //if(!ZDB_LABEL_UNDERDELEGATION(flag_mask & ZDB_RR_LABEL_UNDERDELEGATION)) { /* all labels under are "under delegation" */ //zdb_zone_record_or_flags_to_subdomains(rr_label, ZDB_RR_LABEL_UNDERDELEGATION); zdb_zone_record_or_and_flags_to_subdomains(rr_label, ZDB_RR_LABEL_UNDERDELEGATION, ~ZDB_RR_LABEL_DELEGATION); } } } flag_mask |= ZDB_RR_LABEL_DROPCNAME /*| ZDB_RR_LABEL_HAS_NS*/; break; } case TYPE_DS: { if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_HASCNAME)) { log_err("zone %{dnsname}: ignoring non-CNAME add on CNAME", zone->origin); ZDB_RECORD_ZFREE(ttlrdata); return; } flag_mask |= ZDB_RR_LABEL_DROPCNAME /*| ZDB_RR_LABEL_HAS_DS*/; break; } default: { if(zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_HASCNAME)) { log_err("zone %{dnsname}: ignoring non-CNAME add on CNAME", zone->origin); ZDB_RECORD_ZFREE(ttlrdata); return; } flag_mask = ZDB_RR_LABEL_DROPCNAME; break; } } if(!zdb_record_insert_checked(&rr_label->resource_record_set, type, ttlrdata)) /* FB done */ { ZDB_RECORD_ZFREE(ttlrdata); return; } zdb_rr_label_flag_or(rr_label, flag_mask); } /** * @brief Search for a record in a zone * * Search for a record in a zone * * @param[in] zone the zone * @param[in] labels the stack of labels of the dns name * @param[in] labels_top the index of the top of the stack (the level) * @param[in] type the type of the record * * @return a pointer to the RRSET or NULL if it was not found */ zdb_packed_ttlrdata* zdb_zone_record_find(zdb_zone *zone, dnslabel_vector_reference labels, s32 labels_top, u16 type) { zdb_rr_label* rr_label = zdb_rr_label_find_exact(zone->apex, labels, labels_top); if(rr_label != NULL) { return zdb_record_find(&rr_label->resource_record_set, type); } return NULL; } /** * Searches the zone for the zdb_rr_label of an fqdn if it exists. * * @param[in] zone the zone * @parma[in] fqdn the fqdn of the the label * * @return a pointer the label, or NULL if it was not found. */ zdb_rr_label* zdb_zone_find_label_from_fqdn(zdb_zone *zone, const u8 *fqdn) { dnslabel_vector labels; s32 labels_top = dnsname_to_dnslabel_vector(fqdn, labels); zdb_rr_label* label = zdb_rr_label_find_exact(zone->apex, labels, labels_top - zone->origin_vector.size - 1); return label; } static ya_result zdb_default_query_access_filter(const message_data *mesg, const void *extension) { (void)mesg; (void)extension; return SUCCESS; } static u32 zdb_zone_get_struct_size(const u8 *origin) { u32 zone_footprint = sizeof(zdb_zone) - sizeof(dnsname_vector) + sizeof(u8*) * (dnsname_getdepth(origin) + 1); return zone_footprint; } zdb_zone* zdb_zone_create(const u8* origin) { zdb_zone *zone; u32 zone_footprint = zdb_zone_get_struct_size(origin); ZALLOC_ARRAY_OR_DIE(zdb_zone*, zone, zone_footprint, ZDB_ZONETAG); #if DEBUG memset(zone, 0xac, zone_footprint); #endif #if HAS_TRACK_ZONES_DEBUG_SUPPORT smp_int_inc(&g_zone_instanciated_count); mutex_lock(&g_zone_instanciated_count.mutex); ptr_node *node = ptr_set_insert(&g_zone_instanciated_set, zone); mutex_unlock(&g_zone_instanciated_count.mutex); node->value = NULL; #endif log_debug7("zdb_zone_create %{dnsname}@%p", origin, zone); zone->origin = dnsname_zdup(origin); dnsname_to_dnsname_vector(zone->origin, &zone->origin_vector); #if ZDB_RECORDS_MAX_CLASS > 1 zone->zclass = CLASS_IN; #elif ZDB_RECORDS_MAX_CLASS <= 0 #error "ZDB_RECORDS_MAX_CLASS must be > 0" #endif zone->axfr_timestamp = 1; /* zone->axfr_serial = 0; implicit */ #if ZDB_HAS_DNSSEC_SUPPORT ZEROMEMORY(&zone->nsec, sizeof(dnssec_zone_extension)); zone->sig_validity_interval_seconds = 30*24*3600; /* 1 month */ zone->sig_validity_regeneration_seconds = 7*24*3600; /* 1 week */ zone->sig_validity_jitter_seconds = 86400; /* 1 day */ zone->sig_quota = 100; #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS zone->sig_validity_regeneration_seconds = 90; zone->sig_validity_interval_seconds = 180; zone->sig_validity_jitter_seconds = 5; #endif #endif zone->alarm_handle = alarm_open(zone->origin); zone->apex = zdb_rr_label_new_instance(ROOT_LABEL); zone->apex->_flags = ZDB_RR_LABEL_APEX; zone->query_access_filter = zdb_default_query_access_filter; zone->acl = NULL; #if ZDB_HAS_DNSSEC_SUPPORT zone->progressive_signature_update.current_fqdn = NULL; zone->progressive_signature_update.earliest_signature_expiration = MAX_S32; zone->progressive_signature_update.labels_at_once = ZDB_ZONE_MAINTENANCE_LABELS_AT_ONCE_DEFAULT; #endif mutex_init(&zone->lock_mutex); cond_init(&zone->lock_cond); zone->rc = 1; zone->lock_owner = ZDB_ZONE_MUTEX_NOBODY; zone->lock_count = 0; zone->lock_reserved_owner = ZDB_ZONE_MUTEX_NOBODY; atomic_store(&zone->_status, 0); zone->_flags = 0; #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT zone->lock_trace = NULL; zone->lock_id = 0; zone->lock_timestamp = 0; #endif #if ZDB_ZONE_HAS_JNL_REFERENCE zone->journal = NULL; #endif return zone; } void zdb_zone_invalidate(zdb_zone *zone) { yassert(zone != NULL); zdb_zone_set_invalid(zone); } /** * @brief Destroys a zone and all its content * * Destroys a zone and all its content * * @param[in] zone a pointer to the zone */ void zdb_zone_truncate_invalidate(zdb_zone *zone) { if(zone != NULL) { // remove all alarms linked to the zone alarm_close(zone->alarm_handle); zone->alarm_handle = ALARM_HANDLE_INVALID; // empty the zone records if(zone->apex != NULL) { #if ZDB_HAS_NSEC_SUPPORT nsec_destroy_zone(zone); #endif #if ZDB_HAS_NSEC3_SUPPORT nsec3_destroy_zone(zone); #endif // zdb_rr_label_destroy(zone, &zone->apex); /* * Destroy ALL the content of the apex but not the apex itself. */ zdb_rr_label_truncate(zone, zone->apex); zdb_zone_set_invalid(zone); } } } void zdb_zone_destroy_nolock(zdb_zone *zone) { if(zone != NULL) { assert(zone->rc == 0); log_debug("zone: %{dnsname}: releasing memory (nolock)", zone->origin); int rc = zone->rc; if(rc != 0) { log_debug("zone: %{dnsname}: rc=%i != 0 (nolock)", zone->origin, rc); } #if HAS_TRACK_ZONES_DEBUG_SUPPORT mutex_lock(&g_zone_instanciated_count.mutex); bool known_zone = (ptr_set_find(&g_zone_instanciated_set, zone) != NULL); yassert(known_zone); ptr_set_delete(&g_zone_instanciated_set, zone); mutex_unlock(&g_zone_instanciated_count.mutex); smp_int_dec(&g_zone_instanciated_count); yassert(smp_int_get(&g_zone_instanciated_count) >= 0); #endif if(zone->alarm_handle != ALARM_HANDLE_INVALID) { log_debug("zone: %{dnsname}: removing alarm events (%p) (nolock)", zone->origin, zone->alarm_handle); alarm_close(zone->alarm_handle); zone->alarm_handle = ALARM_HANDLE_INVALID; } #if ZDB_ZONE_HAS_JNL_REFERENCE if(zone->journal != NULL) { journal *jh = zone->journal; // pointed for closing/releasing journal_close(jh); // only authorised usage of this call zone->journal = NULL; } #endif #if !DEBUG // do not bother clearing the memory if it's for a shutdown (faster) if(!dnscore_shuttingdown()) #endif { if(zone->apex != NULL) { #if ZDB_HAS_NSEC_SUPPORT log_debug("zone: %{dnsname}: deleting NSEC chain (if any) (nolock)", zone->origin); nsec_destroy_zone(zone); #endif #if ZDB_HAS_NSEC3_SUPPORT log_debug("zone: %{dnsname}: deleting NSEC3 chain (if any) (nolock)", zone->origin); nsec3_destroy_zone(zone); #endif log_debug("zone: %{dnsname}: deleting records (nolock)", zone->origin); zdb_rr_label_destroy(zone, &zone->apex); zone->apex = NULL; } else { log_debug("zone: %{dnsname}: apex is empty (nolock)", zone->origin); } } #if !DEBUG else { log_debug("zone: %{dnsname}: will not spend time carefully releasing the memory used by the records and the chains (shutting down) (nolock)", zone->origin); } #endif u32 zone_footprint = zdb_zone_get_struct_size(zone->origin); #if DNSCORE_HAS_DNSSEC_SUPPORT if(zone->progressive_signature_update.current_fqdn != NULL) { log_debug("zone: %{dnsname}: releasing progressive signature update (nolock)", zone->origin); dnsname_zfree(zone->progressive_signature_update.current_fqdn); zone->progressive_signature_update.current_fqdn = NULL; } #endif #if DEBUG zone->min_ttl= 0xbadbad01; zone->acl = NULL; zone->axfr_serial = 0xbadbad00; #endif log_debug("zone: %{dnsname}: releasing name and structure (nolock)", zone->origin); dnsname_zfree(zone->origin); #if DEBUG zone->origin = NULL; #endif ZFREE_ARRAY(zone, zone_footprint); } #if DEBUG else { log_debug("zone: NULL: zdb_zone_destroy_nolock called on NULL (nolock)"); } #endif } /** * @brief Destroys a zone and all its content * * Destroys a zone and all its content * * @param[in] zone a pointer to the zone */ void zdb_zone_destroy(zdb_zone *zone) { if(zone != NULL) { log_debug("zone: %{dnsname}: releasing memory", zone->origin); zdb_zone_lock(zone, ZDB_ZONE_MUTEX_DESTROY); int rc = zone->rc; zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_DESTROY); if(rc != 0) { log_debug("zone: %{dnsname}: rc=%i != 0", zone->origin, rc); logger_flush(); abort(); } #if HAS_TRACK_ZONES_DEBUG_SUPPORT mutex_lock(&g_zone_instanciated_count.mutex); bool known_zone = (ptr_set_find(&g_zone_instanciated_set, zone) != NULL); yassert(known_zone); ptr_set_delete(&g_zone_instanciated_set, zone); mutex_unlock(&g_zone_instanciated_count.mutex); smp_int_dec(&g_zone_instanciated_count); yassert(smp_int_get(&g_zone_instanciated_count) >= 0); #endif zdb_zone_lock(zone, ZDB_ZONE_MUTEX_DESTROY); if(zone->alarm_handle != ALARM_HANDLE_INVALID) { log_debug("zone: %{dnsname}: removing alarm events (%p)", zone->origin, zone->alarm_handle); alarm_close(zone->alarm_handle); zone->alarm_handle = ALARM_HANDLE_INVALID; } #if ZDB_ZONE_HAS_JNL_REFERENCE if(zone->journal != NULL) { journal *jh = zone->journal; // pointed for closing/releasing zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_DESTROY); journal_close(jh); // only authorised usage of this call zone->journal = NULL; } else #endif { zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_DESTROY); } #if !DEBUG // do not bother clearing the memory if it's for a shutdown (faster) if(!dnscore_shuttingdown()) #endif { if(zone->apex != NULL) { #if ZDB_HAS_NSEC_SUPPORT log_debug("zone: %{dnsname}: deleting NSEC chain (if any)", zone->origin); nsec_destroy_zone(zone); #endif #if ZDB_HAS_NSEC3_SUPPORT log_debug("zone: %{dnsname}: deleting NSEC3 chain (if any)", zone->origin); nsec3_destroy_zone(zone); #endif log_debug("zone: %{dnsname}: deleting records", zone->origin); zdb_rr_label_destroy(zone, &zone->apex); zone->apex = NULL; } else { log_debug("zone: %{dnsname}: apex is empty", zone->origin); } } #if !DEBUG else { log_debug("zone: %{dnsname}: will not spend time carefully releasing the memory used by the records and the chains (shutting down)", zone->origin); } #endif u32 zone_footprint = zdb_zone_get_struct_size(zone->origin); #if DNSCORE_HAS_DNSSEC_SUPPORT if(zone->progressive_signature_update.current_fqdn != NULL) { log_debug("zone: %{dnsname}: releasing progressive signature update", zone->origin); dnsname_zfree(zone->progressive_signature_update.current_fqdn); zone->progressive_signature_update.current_fqdn = NULL; } #endif #if DEBUG zone->min_ttl= 0xbadbad01; zone->acl = NULL; zone->axfr_serial = 0xbadbad00; #endif cond_finalize(&zone->lock_cond); mutex_destroy(&zone->lock_mutex); log_debug("zone: %{dnsname}: releasing name and structure", zone->origin); dnsname_zfree(zone->origin); #if DEBUG zone->origin = NULL; #endif ZFREE_ARRAY(zone, zone_footprint); } #if DEBUG else { log_debug("zone: NULL: zdb_zone_destroy called on NULL"); } #endif } /** * @brief Copies the soa of a zone to an soa_rdata structure. * * Copies the soa of a zone to an soa_rdata structure. * No memory is allocated for the soa_rdata. If the zone is destroyed, * the soa_rdata becomes invalid. * * @param[in] zone a pointer to the zone * @param[out] soa_out a pointer to an soa_rdata structure */ ya_result zdb_zone_getsoa(const zdb_zone *zone, soa_rdata* soa_out) { #if DEBUG if(zone->lock_owner == ZDB_ZONE_MUTEX_NOBODY) { log_err("zdb_zone_getsoa called on an unlocked zone: %{dnsname}", zone->origin); debug_log_stacktrace(MODULE_MSG_HANDLE, LOG_ERR, "zdb_zone_getsoa"); //logger_flush(); } else { log_debug("zdb_zone_getsoa called on a zone locked by %02hhx (%{dnsname})", zone->lock_owner, zone->origin); } #endif const zdb_rr_label *apex = zone->apex; const zdb_packed_ttlrdata *soa = zdb_record_find(&apex->resource_record_set, TYPE_SOA); // zone is locked ya_result return_code; if(soa != NULL) { return_code = zdb_record_getsoa(soa, soa_out); } else { return_code = ZDB_ERROR_NOSOAATAPEX; } return return_code; } ya_result zdb_zone_getsoa_ttl_rdata(const zdb_zone *zone, u32 *ttl, u16 *rdata_size, const u8 **rdata) { #if DEBUG if(zone->lock_owner == ZDB_ZONE_MUTEX_NOBODY) { log_err("zdb_zone_getsoa_ttl_rdata called on an unlocked zone: %{dnsname}", zone->origin); debug_log_stacktrace(MODULE_MSG_HANDLE, LOG_ERR, "zdb_zone_getsoa_ttl_rdata"); logger_flush(); } else { log_debug("zdb_zone_getsoa_ttl_rdata called on a zone locked by %02hhx (%{dnsname})", zone->lock_owner, zone->origin); } #endif const zdb_rr_label *apex = zone->apex; const zdb_packed_ttlrdata *soa = zdb_record_find(&apex->resource_record_set, TYPE_SOA); // zone is locked if(soa == NULL) { return ZDB_ERROR_NOSOAATAPEX; } if(ttl != NULL) { *ttl = soa->ttl; } if(rdata_size != NULL && rdata != NULL) { *rdata_size = soa->rdata_size; *rdata = &soa->rdata_start[0]; } return SUCCESS; } /** * @brief Retrieve the serial of a zone * * Retrieve the serial of a zone * * @param[in] zone a pointer to the zone * @param[out] soa_out a pointer to an soa_rdata structure */ ya_result zdb_zone_getserial(const zdb_zone *zone, u32 *serial) { #if DEBUG if(zone->lock_owner == ZDB_ZONE_MUTEX_NOBODY) { log_err("zdb_zone_getserial called on an unlocked zone (%{dnsname})", zone->origin); debug_log_stacktrace(MODULE_MSG_HANDLE, LOG_ERR, "zdb_zone_getserial"); logger_flush(); } else { log_debug1("zdb_zone_getserial called on a zone locked by %02hhx (%{dnsname})", zone->lock_owner, zone->origin); } #endif yassert(serial != NULL); zdb_rr_label *apex = zone->apex; zdb_packed_ttlrdata *soa = zdb_record_find(&apex->resource_record_set, TYPE_SOA); // zone is locked if(soa != NULL) { return rr_soa_get_serial(soa->rdata_start, soa->rdata_size, serial); } return ZDB_ERROR_NOSOAATAPEX; } const zdb_packed_ttlrdata* zdb_zone_get_dnskey_rrset(zdb_zone *zone) { return zdb_record_find(&zone->apex->resource_record_set, TYPE_DNSKEY); // zone is locked } bool zdb_zone_isinvalid(zdb_zone *zone) { bool invalid = TRUE; if((zone != NULL) && (zone->apex != NULL)) { invalid = zdb_zone_is_invalid(zone); } return invalid; } #if DNSCORE_HAS_DNSSEC_SUPPORT /** * * Returns TRUE iff the key is present as a record in the zone * * @param zone * @param key * @return */ bool zdb_zone_contains_dnskey_record_for_key(zdb_zone *zone, const dnssec_key *key) { yassert(zdb_zone_islocked(zone)); const zdb_packed_ttlrdata *dnskey_rrset = zdb_record_find(&zone->apex->resource_record_set, TYPE_DNSKEY); // zone is locked const zdb_packed_ttlrdata *dnskey_record = dnskey_rrset; while(dnskey_record != NULL) { if(dnskey_matches_rdata(key, ZDB_PACKEDRECORD_PTR_RDATAPTR(dnskey_record), ZDB_PACKEDRECORD_PTR_RDATASIZE(dnskey_record))) { return TRUE; } dnskey_record = dnskey_record->next; } return FALSE; } /** * Returns TRUE iff there is at least one RRSIG record with the tag and algorithm of the key * * @param zone * @param key * @return */ bool zdb_zone_apex_contains_rrsig_record_by_key(zdb_zone *zone, const dnssec_key *key) { yassert(zdb_zone_islocked(zone)); const zdb_packed_ttlrdata *rrsig_rrset = zdb_record_find(&zone->apex->resource_record_set, TYPE_RRSIG); // zone is locked if(rrsig_rrset != NULL) { const zdb_packed_ttlrdata *rrsig_record = rrsig_rrset; u16 tag = dnskey_get_tag_const(key); u8 algorithm = dnskey_get_algorithm(key); while(rrsig_record != NULL) { if((RRSIG_ALGORITHM(rrsig_record) == algorithm) && (RRSIG_KEY_TAG(rrsig_record) == tag)) { return TRUE; } rrsig_record = rrsig_record->next; } } return FALSE; } #if HAS_MASTER_SUPPORT /** * Adds a DNSKEY record in a zone from the dnssec_key object. * * @param key * @return TRUE iff the record has been added */ bool zdb_zone_add_dnskey_from_key(zdb_zone *zone, const dnssec_key *key) { yassert(zdb_zone_islocked(zone)); zdb_packed_ttlrdata *dnskey_record; u32 rdata_size = key->vtbl->dnssec_key_rdatasize(key); ZDB_RECORD_ZALLOC_EMPTY(dnskey_record, 86400, rdata_size); key->vtbl->dnssec_key_writerdata(key, ZDB_PACKEDRECORD_PTR_RDATAPTR(dnskey_record), rdata_size); // store the record if(zdb_record_insert_checked(&zone->apex->resource_record_set, TYPE_DNSKEY, dnskey_record)) /* FB done */ { return TRUE; } else { ZDB_RECORD_ZFREE(dnskey_record); return FALSE; } } /** * Removes a DNSKEY record in a zone from the dnssec_key object. * * @param key * @return TRUE iff the record has been found and removed */ bool zdb_zone_remove_dnskey_from_key(zdb_zone *zone, const dnssec_key *key) { yassert(zdb_zone_islocked(zone)); zdb_packed_ttlrdata *dnskey_record; u32 rdata_size = key->vtbl->dnssec_key_rdatasize(key); ZDB_RECORD_ZALLOC_EMPTY(dnskey_record, 86400, rdata_size); key->vtbl->dnssec_key_writerdata(key, ZDB_PACKEDRECORD_PTR_RDATAPTR(dnskey_record), rdata_size); zdb_ttlrdata unpacked_dnskey_record; unpacked_dnskey_record.rdata_pointer = ZDB_PACKEDRECORD_PTR_RDATAPTR(dnskey_record); unpacked_dnskey_record.rdata_size = ZDB_PACKEDRECORD_PTR_RDATASIZE(dnskey_record); unpacked_dnskey_record.ttl = dnskey_record->ttl; // remove the record if(zdb_record_delete_self_exact(&zone->apex->resource_record_set, TYPE_DNSKEY, &unpacked_dnskey_record) >= 0) { // remove all RRSIG on DNSKEY rrsig_delete(zone, zone->origin,zone->apex, TYPE_DNSKEY); rrsig_delete_by_tag(zone, dnskey_get_tag_const(key)); // zdb_listener_notify_remove_type(zone, zone->origin, &zone->apex->resource_record_set, TYPE_RRSIG); ZDB_RECORD_ZFREE(dnskey_record); return TRUE; } else { ZDB_RECORD_ZFREE(dnskey_record); return FALSE; } } static ya_result zdb_zone_update_zone_remove_add_dnskeys(zdb_zone *zone, ptr_vector *removed_keys, ptr_vector *added_keys, u8 secondary_lock) { dynupdate_message dmsg; packet_unpack_reader_data reader; const u8 *fqdn = NULL; if(!ptr_vector_isempty(removed_keys)) { dnssec_key *key = (dnssec_key*)ptr_vector_get(removed_keys, 0); yassert(key != NULL); fqdn = dnskey_get_domain(key); } else if(!ptr_vector_isempty(added_keys)) { dnssec_key *key = (dnssec_key*)ptr_vector_get(added_keys, 0); yassert(key != NULL); fqdn = dnskey_get_domain(key); } else { return 0; // EMPTY } ya_result ret; int add_index = 0; int del_index = 0; bool work_to_do = FALSE; do { dynupdate_message_init(&dmsg, fqdn, CLASS_IN); for(; add_index <= ptr_vector_last_index(added_keys); ++add_index) { dnssec_key *key = (dnssec_key*)ptr_vector_get(added_keys, add_index); if(FAIL(ret = dynupdate_message_add_dnskey(&dmsg, zone->min_ttl, key))) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d key cannot be sent with this update, postponing",dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); work_to_do = TRUE; break; } log_info("dnskey: %{dnsname}: +%03d+%05d/%d key will be added", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); } if(!work_to_do) { for(; del_index <= ptr_vector_last_index(removed_keys); ++del_index) { dnssec_key *key = (dnssec_key*)ptr_vector_get(removed_keys, del_index); if(FAIL(ret = dynupdate_message_del_dnskey(&dmsg, key))) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d key cannot be sent with this update, postponing", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); work_to_do = TRUE; break; } log_info("dnskey: %{dnsname}: +%03d+%05d/%d key will be removed", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); } } dynupdate_message_set_reader(&dmsg, &reader); u16 count = dynupdate_message_get_count(&dmsg); packet_reader_skip(&reader, DNS_HEADER_LENGTH); // checked below packet_reader_skip_fqdn(&reader); // checked below packet_reader_skip(&reader, 4); // checked below if(!packet_reader_eof(&reader)) { // the update is ready : push it if(ISOK(ret = dynupdate_diff(zone, &reader, count, secondary_lock, DYNUPDATE_DIFF_RUN))) { // done log_info("dnskey: %{dnsname}: keys update successful", fqdn); } if(FAIL(ret)) { if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { // trigger a background store of the zone zdb_zone_info_background_store_zone(fqdn); } dynupdate_message_finalize(&dmsg); log_err("dnskey: %{dnsname}: keys update failed", fqdn); break; } } else { log_err("dnskey: %{dnsname}: keys update failed: FORMERR", fqdn); ret = RCODE_ERROR_CODE(RCODE_FORMERR); } dynupdate_message_finalize(&dmsg); } while(work_to_do); return ret; } /** * From the keystore (files/pkcs12) for that zone * * Remove the keys that should not be in the zone anymore. * Add the keys that should be in the zone. * * @param zone */ void zdb_zone_update_keystore_keys_from_zone(zdb_zone *zone, u8 secondary_lock) { // keystore keys with a publish time that did not expire yet have to be added // keystore keys with an unpublish time that passed have to be removed // // after (and only after) the signature is done, set alarms at all the (relevant) timings of the keys (publish, activate, inactivate, unpublish) yassert(zdb_zone_islocked(zone)); ptr_vector dnskey_add = PTR_VECTOR_EMPTY; ptr_vector dnskey_del = PTR_VECTOR_EMPTY; bool rrsig_push_allowed = zdb_zone_get_rrsig_push_allowed(zone); for(int i = 0; ; ++i) { dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_at_index(zone->origin, i); if(key == NULL) { break; } if(dnskey_is_private(key)) { time_t now = time(NULL); if(dnskey_is_published(key, now) || !dnskey_has_explicit_publish(key)) // if published or no publication set { if(!dnskey_is_expired_now(key)) // if the key hasn't expired (includes a test for activation) { if(!zdb_zone_contains_dnskey_record_for_key(zone, key)) // if the key is not in the zone { if(!rrsig_push_allowed) { dnskey_acquire(key); // then add the key in the zone ptr_vector_append(&dnskey_add, key); } } } // else there is no point publishing it if it was not already } } dnskey_release(key); } zdb_packed_ttlrdata *dnskey_rrset = zdb_record_find(&zone->apex->resource_record_set, TYPE_DNSKEY); // zone is locked zdb_packed_ttlrdata *dnskey_record = dnskey_rrset; while(dnskey_record != NULL) { dnssec_key *key; ya_result ret; if(ISOK(ret = dnssec_keystore_load_private_key_from_rdata( ZDB_PACKEDRECORD_PTR_RDATAPTR(dnskey_record), ZDB_PACKEDRECORD_PTR_RDATASIZE(dnskey_record), zone->origin, &key))) // key properly released { if(dnskey_has_explicit_delete(key) && dnskey_is_unpublished(key, time(NULL))) { if(!rrsig_push_allowed) { // need to unpublish dnskey_acquire(key); ptr_vector_append(&dnskey_del, key); } } // note: the key alarms are not set dnskey_release(key); } dnskey_record = dnskey_record->next; } if(ptr_vector_size(&dnskey_add) + ptr_vector_size(&dnskey_del) > 0) { if(ISOK(zdb_zone_update_zone_remove_add_dnskeys(zone, &dnskey_del, &dnskey_add, secondary_lock))) { log_info("zone: %{dnsname}: keys added: %i, keys deleted: %i", zone->origin, ptr_vector_size(&dnskey_add), ptr_vector_size(&dnskey_del)); } else { log_warn("zone: %{dnsname}: failed to update keys (keys meant to be added: %i, keys meant to be deleted: %i)", zone->origin, ptr_vector_size(&dnskey_add), ptr_vector_size(&dnskey_del)); } for(s32 i = 0; i <= ptr_vector_last_index(&dnskey_add); ++i) { dnskey_release(ptr_vector_get(&dnskey_add, i)); } ptr_vector_destroy(&dnskey_add); for(s32 i = 0; i <= ptr_vector_last_index(&dnskey_del); ++i) { dnskey_release(ptr_vector_get(&dnskey_del, i)); } ptr_vector_destroy(&dnskey_del); } } #endif // HAS_MASTER_SUPPORT #endif #if DEBUG /** * DEBUG */ void zdb_zone_print_indented(zdb_zone *zone, output_stream *os, int indent) { if(zone == NULL) { osformatln(os, "%tz: NULL", indent); return; } u16 zclass = zdb_zone_getclass(zone); osformatln(os, "%tzone@%p(CLASS=%{dnsclass},ORIGIN='%{dnsname}'", indent, (void*)zone, &zclass, zone->origin); zdb_rr_label_print_indented(zone->apex, os, indent + 1); osformatln(os, "%t+:", indent); } void zdb_zone_print(zdb_zone *zone, output_stream *os) { zdb_zone_print_indented(zone, os, 0); } #endif u32 zdb_zone_get_status(zdb_zone *zone) { u32 ret = atomic_load(&zone->_status); return ret; } u32 zdb_zone_set_status(zdb_zone *zone, u32 status) { #if DEBUG log_debug4("zdb_zone_set_status(%{dnsname},%08x)", zone->origin, status); #endif for(;;) { uint_fast32_t expected = atomic_load(&zone->_status); if((expected & status) != status) { uint_fast32_t desired = expected | status; if(atomic_compare_exchange_strong(&zone->_status, &expected, desired)) { return expected; // old value } // the update failed, try a gain } else { return expected; // no work to do } } } u32 zdb_zone_clear_status(zdb_zone *zone, u32 status) { #if DEBUG log_debug4("zdb_zone_clear_status(%{dnsname},%08x)", zone->origin, status); #endif uint_fast32_t not_status = ~status; for(;;) { uint_fast32_t expected = atomic_load(&zone->_status); if((expected & status) != 0) { uint_fast32_t desired = expected & not_status; if(atomic_compare_exchange_strong(&zone->_status, &expected, desired)) { return expected; // old value } // the update failed, try a gain } else { return expected; // no work to do } } } bool zdb_zone_error_status_getnot_set(zdb_zone *zone, u8 error_status) { bool ret = (zone->_error_status & error_status) == 0; zone->_error_status &= ~error_status; return ret; } void zdb_zone_error_status_clear(zdb_zone *zone, u8 error_status) { zone->_error_status &= ~error_status; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_zone_axfr_input_stream.c0000644000000000000000000000013214505005531024554 xustar000000000000000030 mtime=1695812441.720971848 30 atime=1695812445.801030282 30 ctime=1695812495.128736754 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_zone_axfr_input_stream.c0000664000374500037450000001764514505005531024533 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnsdb/dnsdb-config.h" #include #include "dnscore/file_input_stream.h" #include "dnscore/format.h" #include "dnscore/logger.h" #include "dnsdb/zdb_types.h" #include "dnsdb/zdb_zone_axfr_input_stream.h" #include "dnsdb/zdb-zone-path-provider.h" /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define AXFRIS_TAG 0x534952465841 /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ /** @brief Function ... * * ... * * @param ... * * @retval OK * @retval NOK */ typedef struct zdb_zone_axfr_input_stream_data zdb_zone_axfr_input_stream_data; struct zdb_zone_axfr_input_stream_data { input_stream filtered; zdb_zone* zone; u32 serial; }; static ya_result zdb_zone_axfr_input_stream_read(input_stream* stream_, void* buffer_, u32 len) { zdb_zone_axfr_input_stream_data* stream = (zdb_zone_axfr_input_stream_data*)stream_->data; u8 *buffer = (u8*)buffer_; bool first_chance_eof = FALSE; for(;;) { ya_result n = input_stream_read(&stream->filtered, buffer, len); // ERROR or SUCCESS if(n != 0) { /* log_debug("zdb_zone_axfr_input_stream_read: got %d", n); */ return n; } // EOF ... or is it ? if(first_chance_eof) { // already broken once : EOF /* log_debug("zdb_zone_axfr_input_stream_read: final EOF"); */ return 0; } if((stream->zone->axfr_timestamp != 0) || (stream->zone->axfr_serial != stream->serial)) { // file written OR file written and a new one starts to be written => done /* log_debug("zdb_zone_axfr_input_stream_read: first chance EOF"); */ first_chance_eof = TRUE; } else { // just wait /* log_debug("zdb_zone_axfr_input_stream_read: wait"); */ } usleep(100000); // 10ms } } static ya_result zdb_zone_axfr_input_stream_skip(input_stream* stream_, u32 len) { // Yes, this is not the usual pattern : skip will simply read from the stream into // a buffer so the call is simply forwarded to the reader. //zdb_zone_axfr_input_stream_data* stream = (zdb_zone_axfr_input_stream_data*)stream_; ya_result total = 0; u8 tmp[512]; while(len > 0) { // Yes, I meant to use stream_ and not "stream" ya_result n = zdb_zone_axfr_input_stream_read(stream_, tmp, MIN(len, sizeof(tmp))); if(FAIL(n)) { return n; } if(n == 0) { break; } total += n; } return total; } static void zdb_zone_axfr_input_stream_close(input_stream* is) { zdb_zone_axfr_input_stream_data* data = (zdb_zone_axfr_input_stream_data*)is->data; input_stream_close(&data->filtered); free(data); input_stream_set_void(is); } static input_stream_vtbl zdb_zone_axfr_input_stream_vtbl = { zdb_zone_axfr_input_stream_read, zdb_zone_axfr_input_stream_skip, zdb_zone_axfr_input_stream_close, "zdb_zone_axfr_input_stream" }; ya_result zdb_zone_axfr_input_stream_open_with_path(input_stream *is, zdb_zone *zone, const char *filepath) { ya_result ret; u32 serial; //u32 timestamp; serial = zone->axfr_serial; //timestamp = zone->axfr_timestamp; if(ISOK(ret = file_input_stream_open(is, filepath))) { zdb_zone_axfr_input_stream_data* data; MALLOC_OBJECT_OR_DIE(data, zdb_zone_axfr_input_stream_data, AXFRIS_TAG); data->filtered.data = is->data; data->filtered.vtbl = is->vtbl; data->serial = serial; data->zone = zone; is->data = data; is->vtbl = &zdb_zone_axfr_input_stream_vtbl; } return ret; } ya_result zdb_zone_axfr_input_stream_open(input_stream *is, zdb_zone *zone) { ya_result ret; u32 serial; u32 timestamp; char path[PATH_MAX]; serial = zone->axfr_serial; timestamp = zone->axfr_timestamp; while(timestamp == 0) { /* * being written : try to open the axfr.part file * in the event of a success, a stream waiting for the completion of the file will be returned */ if(ISOK(ret = zdb_zone_path_get_provider()( zone->origin, path, sizeof(path) - 6, ZDB_ZONE_PATH_PROVIDER_AXFR_FILE|ZDB_ZONE_PATH_PROVIDER_MKDIR))) { memcpy(&path[ret], ".part", 6); if(ISOK(ret = file_input_stream_open(is, path))) { zdb_zone_axfr_input_stream_data* data; MALLOC_OBJECT_OR_DIE(data, zdb_zone_axfr_input_stream_data, AXFRIS_TAG); data->filtered.data = is->data; data->filtered.vtbl = is->vtbl; data->serial = serial; data->zone = zone; is->data = data; is->vtbl = &zdb_zone_axfr_input_stream_vtbl; return ret; } } if(dnscore_shuttingdown()) { return STOPPED_BY_APPLICATION_SHUTDOWN; } usleep(10000); serial = zone->axfr_serial; timestamp = zone->axfr_timestamp; } /* * already written : try to open the axfr file * in the event of a success, a simple file input stream will be returned */ if(ISOK(ret = zdb_zone_path_get_provider()( zone->origin, path, sizeof(path) - 6, ZDB_ZONE_PATH_PROVIDER_AXFR_FILE|ZDB_ZONE_PATH_PROVIDER_MKDIR))) { ret = file_input_stream_open(is, path); } return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_zone_label.c0000644000000000000000000000013214505005531022101 xustar000000000000000030 mtime=1695812441.749972263 30 atime=1695812445.802030296 30 ctime=1695812495.130736783 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_zone_label.c0000664000374500037450000003507514505005531022055 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Internal functions for the database: zoned resource records label. * * Internal functions for the database: zoned resource records label. * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include "dnsdb/zdb.h" #include "dnsdb/dictionary.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_error.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger /** * @brief INTERNAL callback, tests for a match between a label and a node. */ static int zdb_zone_label_zlabel_match(const void *label, const dictionary_node * node) { const zdb_zone_label* zone_label = (const zdb_zone_label*)node; return dnslabel_equals(zone_label->name, label); } /** * @brief INTERNAL callback, creates a new node instance */ static dictionary_node * zdb_zone_label_create(const void *data) { zdb_zone_label* zone_label; ZALLOC_OBJECT_OR_DIE(zone_label, zdb_zone_label, ZDB_ZONELABEL_TAG); zone_label->next = NULL; dictionary_init(&zone_label->sub); zone_label->name = dnslabel_zdup(data); zone_label->zone = NULL; return (dictionary_node *)zone_label; } /** * @brief INTERNAL callback, destroys a node instance and its collections. */ static void zdb_zone_label_destroy_callback(dictionary_node * zone_label_node) { if(zone_label_node == NULL) { return; } zdb_zone_label *zone_label = (zdb_zone_label*)zone_label_node; /* detach is made by destroy */ dictionary_destroy(&zone_label->sub, zdb_zone_label_destroy_callback); dnslabel_zfree(zone_label->name); if(zone_label->zone != NULL) { zdb_zone_release(zone_label->zone); zone_label->zone = NULL; } ZFREE_OBJECT(zone_label); } /** * @brief Search for the label of a zone in the database * * Search for the label of a zone in the database * * @param[in] db the database to explore * @param[in] origin the dnsname_vector mapping the label * * @return a pointer to the label or NULL if it does not exists in the database. * */ zdb_zone_label* zdb_zone_label_find(zdb * db, const dnsname_vector* origin) // mutex checked { zdb_zone_label* zone_label; yassert(zdb_ismutexlocked(db)); zone_label = db->root; /* the "." zone */ const_dnslabel_stack_reference sections = origin->labels; s32 index = origin->size; /* look into the sub level */ while(zone_label != NULL && index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); zone_label = (zdb_zone_label*)dictionary_find(&zone_label->sub, hash, label, zdb_zone_label_zlabel_match); index--; } return zone_label; } /** * @brief Search for the label of a zone in the database * * Search for the label of a zone in the database * * @param[in] db the database to explore * @param[in] origin the dnsname_vector mapping the label * * @return a pointer to the label or NULL if it does not exists in the database. * */ zdb_zone_label* zdb_zone_label_find_nolock(zdb * db, const dnsname_vector* origin) { zdb_zone_label* zone_label; zone_label = db->root; /* the "." zone */ const_dnslabel_stack_reference sections = origin->labels; s32 index = origin->size; /* look into the sub level */ while(zone_label != NULL && index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); zone_label = (zdb_zone_label*)dictionary_find(&zone_label->sub, hash, label, zdb_zone_label_zlabel_match); index--; } return zone_label; } zdb_zone_label* zdb_zone_label_find_from_name(zdb* db, const char* name) // mutex checked { dnsname_vector origin; u8 dns_name[MAX_DOMAIN_LENGTH]; if(ISOK(cstr_to_dnsname(dns_name, name))) { dnsname_to_dnsname_vector(dns_name, &origin); zdb_zone_label *label = zdb_zone_label_find(db, &origin); // in zdb_zone_label_find_from_name return label; } return NULL; } zdb_zone_label* zdb_zone_label_find_from_dnsname(zdb* db, const u8* dns_name) // mutex checked { dnsname_vector origin; dnsname_to_dnsname_vector(dns_name, &origin); zdb_zone_label *label = zdb_zone_label_find(db, &origin); // in zdb_zone_label_find_from_dnsname return label; } zdb_zone_label* zdb_zone_label_find_from_dnsname_nolock(zdb* db, const u8* dns_name) { dnsname_vector origin; dnsname_to_dnsname_vector(dns_name, &origin); zdb_zone_label *label = zdb_zone_label_find_nolock(db, &origin); // in zdb_zone_label_find_from_dnsname_nolock return label; } /** * @brief Destroys a label and its collections. * * Destroys a label and its collections. * * @param[in] zone_labelp a pointer to a pointer to the label to destroy. * */ void zdb_zone_label_destroy(zdb_zone_label **zone_labelp) { yassert(zone_labelp != NULL); zdb_zone_label* zone_label = *zone_labelp; if(zone_label != NULL) { #if DEBUG log_debug5("zdb_zone_label_destroy: %{dnslabel}", zone_label->name); #endif dictionary_destroy(&zone_label->sub, zdb_zone_label_destroy_callback); zdb_zone *zone = zone_label->zone; if(zone != NULL) { #if DEBUG log_debug5("zdb_zone_label_destroy: %{dnsname}", zone->origin); #endif mutex_lock(&zone->lock_mutex); alarm_close(zone->alarm_handle); zone->alarm_handle = ALARM_HANDLE_INVALID; mutex_unlock(&zone->lock_mutex); zdb_zone_release(zone); zone_label->zone = NULL; } //zdb_zone_destroy(zone_label->zone); dnslabel_zfree(zone_label->name); ZFREE_OBJECT(zone_label); *zone_labelp = NULL; } } /** * @brief Gets pointers to all the zone labels along the path of a name. * * Gets pointers to all the zone labels along the path of a name. * * @param[in] db a pointer to the database * @param[in] name a pointer to the dns name * @param[in] zone_label_stack a pointer to the stack that will hold the labels pointers * * @return the top of the stack (-1 = empty) */ s32 zdb_zone_label_match(zdb * db, const dnsname_vector* origin, // mutex checked zdb_zone_label_pointer_array zone_label_stack) { zdb_zone_label* zone_label; yassert(zdb_islocked_by(db, ZDB_MUTEX_READER)); zone_label = db->root; /* the "." zone */ const_dnslabel_stack_reference sections = origin->labels; s32 index = origin->size; s32 sp = 0; zone_label_stack[0] = zone_label; /* look into the sub level */ while(index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); zone_label = (zdb_zone_label*)dictionary_find(&zone_label->sub, hash, label, zdb_zone_label_zlabel_match); if(zone_label == NULL) { break; } zone_label_stack[++sp] = zone_label; index--; } return sp; } zdb_zone_label* zdb_zone_label_add_nolock(zdb * db, const dnsname_vector* origin) // mutex checked { zdb_zone_label* zone_label; yassert(zdb_islocked(db)); zone_label = db->root; /* the "." zone */ const_dnslabel_stack_reference sections = origin->labels; s32 index = origin->size; /* look into the sub level */ while(index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); zone_label = (zdb_zone_label*)dictionary_add(&zone_label->sub, hash, label, zdb_zone_label_zlabel_match, zdb_zone_label_create); index--; } return zone_label; } typedef struct zdb_zone_label_delete_process_callback_args zdb_zone_label_delete_process_callback_args; struct zdb_zone_label_delete_process_callback_args { dnslabel_stack_reference sections; s32 top; }; /** * @brief INTERNAL callback */ static ya_result zdb_zone_label_delete_process_callback(void *a, dictionary_node * node) { yassert(node != NULL); zdb_zone_label* zone_label = (zdb_zone_label*)node; zdb_zone_label_delete_process_callback_args *args = (zdb_zone_label_delete_process_callback_args *)a; /* * a points to a kind of dnsname and we are going in * * we go down and down each time calling the dictionnary process for the next level * * at the last level we return the "delete" code * * from there, the dictionnary processor will remove the entry * * at that point the calling dictionnary will know if he has to delete his node or not * * and so on and so forth ... * */ s32 top = args->top; const u8* label = (u8*)args->sections[top]; if(!dnslabel_equals(zone_label->name, label)) { return COLLECTION_PROCESS_NEXT; } /* match */ if(top > 0) { /* go to the next level */ label = args->sections[--args->top]; hashcode hash = hash_dnslabel(label); ya_result err; if((err = dictionary_process(&zone_label->sub, hash, args, zdb_zone_label_delete_process_callback)) == COLLECTION_PROCESS_DELETENODE) { /* check the node for relevance, return "delete" if irrelevant */ if(ZONE_LABEL_IRRELEVANT(zone_label)) { /* Irrelevant means that only the name remains */ dictionary_destroy(&zone_label->sub, zdb_zone_label_destroy_callback); if(zone_label->zone != NULL) { zdb_zone_release(zone_label->zone); zone_label->zone = NULL; } dnslabel_zfree(zone_label->name); ZFREE_OBJECT(zone_label); return COLLECTION_PROCESS_DELETENODE; } return COLLECTION_PROCESS_STOP; } /* or ... stop */ return err; } /* NOTE: the 'detach' is made by destroy : do not touch to the "next" field */ /* NOTE: the freee of the node is made by destroy : do not do it */ /* dictionary destroy will take every item in the dictionary and * iterate through it calling the passed function. */ dictionary_destroy(&zone_label->sub, zdb_zone_label_destroy_callback); if(zone_label->zone != NULL) { zdb_zone_release(zone_label->zone); zone_label->zone = NULL; } dnslabel_zfree(zone_label->name); ZFREE_OBJECT(zone_label); return COLLECTION_PROCESS_DELETENODE; } /** * @brief Destroys a zone label and all its collections * * Destroys a zone label and all its collections * * @parm[in] db a pointer to the database * @parm[in] name a pointer to the name * * @return an error code */ ya_result zdb_zone_label_delete(zdb * db, dnsname_vector* name) // mutex checked { yassert(db != NULL && name != NULL && name->size >= 0); yassert(zdb_islocked(db)); zdb_zone_label* root_label; root_label = db->root; /* the "." zone */ if(root_label == NULL) { /* has already been destroyed */ return ZDB_ERROR_NOSUCHCLASS; } zdb_zone_label_delete_process_callback_args args; args.sections = name->labels; args.top = name->size; hashcode hash = hash_dnslabel(args.sections[args.top]); ya_result err = dictionary_process(&root_label->sub, hash, &args, zdb_zone_label_delete_process_callback); if(err == COLLECTION_PROCESS_DELETENODE) { err = COLLECTION_PROCESS_STOP; } return err; } #if DEBUG /** * DEBUG */ void zdb_zone_label_print_indented(zdb_zone_label* zone_label, output_stream *os, int indented) { if(zone_label == NULL) { osformatln(os, "%tg: NULL", indented); return; } if(zone_label->zone != NULL) { zdb_zone_print_indented(zone_label->zone, os, indented + 1); } if(zone_label->name != NULL) { osformatln(os, "%tg: '%{dnslabel}'", indented, zone_label->name); } else { osformatln(os, "%tg: WRONG", indented); } dictionary_iterator iter; dictionary_iterator_init(&zone_label->sub, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_zone_label* *sub_labelp = (zdb_zone_label**)dictionary_iterator_next(&iter); zdb_zone_label_print_indented(*sub_labelp, os, indented + 1); } } void zdb_zone_label_print(zdb_zone_label* zone_label, output_stream *os) { zdb_zone_label_print_indented(zone_label, os, 0); } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_zone_label_iterator.c0000644000000000000000000000013214505005531024012 xustar000000000000000030 mtime=1695812441.754972335 30 atime=1695812445.802030296 30 ctime=1695812495.132736811 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_zone_label_iterator.c0000664000374500037450000002360414505005531023761 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to iterate through the labels of a zone * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include "dnscore/logger.h" #include "dnsdb/zdb_types.h" #include "dnsdb/zdb_zone_label_iterator.h" #include "dnsdb/zdb_rr_label.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger /** * @brief Initializes a zone label iterator * * Initializes a zone label iterator (iterates zdb_rr_label) * * @param[in] zone The zone to explore * @param[in] iter a pointer to the iterator to initialize * */ #define ZLI_DEBUG 0 void zdb_zone_label_iterator_init(zdb_zone_label_iterator* iter, const zdb_zone* zone) { #if DEBUG memset(iter, 0xff, sizeof(zdb_zone_label_iterator)); #endif s32 top; if(*zone->origin != '\0') { top = dnsname_to_dnslabel_stack(zone->origin, iter->dnslabels); // sets an empty iterator for the labels in the path of the zone for(s32 i = 0; i < top; i++) { dictionary_empty_iterator_init(&iter->stack[i]); } dictionary_iterator_init(&zone->apex->sub, &iter->stack[top]); iter->top = top; iter->current_label = zone->apex; iter->zone = zone; #if ZDB_ZONE_LABEL_ITERATOR_CAN_SKIP_CHILDREN iter->prev_top = -1; // prev_top is used to skip children of the current label #endif iter->current_top = top; } else { dictionary_iterator_init(&zone->apex->sub, &iter->stack[0]); iter->dnslabels[0] = zone->apex->name; iter->top = 0; iter->current_label = zone->apex; iter->zone = zone; #if ZDB_ZONE_LABEL_ITERATOR_CAN_SKIP_CHILDREN iter->prev_top = -1; // prev_top is used to skip children of the current label #endif iter->current_top = 0; } } void zdb_zone_label_iterator_init_from(zdb_zone_label_iterator* iter, const zdb_zone* zone, const u8 *from_name) { #if DEBUG memset(iter, 0xff, sizeof(zdb_zone_label_iterator)); #endif dnslabel_stack from_name_stack; if(from_name == NULL) // from not set : initialise from the start { zdb_zone_label_iterator_init(iter, zone); return; } s32 top = dnsname_to_dnslabel_stack(zone->origin, iter->dnslabels); s32 real_top = dnsname_to_dnslabel_stack(from_name, from_name_stack); if(real_top <= top) { zdb_zone_label_iterator_init(iter, zone); return; } for(s32 i = 0; i < top; i++) { if(!dnslabel_equals(iter->dnslabels[i], from_name_stack[i])) { zdb_zone_label_iterator_init(iter, zone); return; } } // sets an empty iterator for the labels in the path of the zone for(s32 i = 0; i < top; i++) { dictionary_empty_iterator_init(&iter->stack[i]); } // while there are labels in from_name // find if the next level exists // if yes, initialise the iterator from it // initialise an iterator for the next level // note: real_top > top zdb_rr_label *parent = zone->apex; do { zdb_rr_label *child = zdb_rr_label_find_child(parent, from_name_stack[top + 1]); if(child == NULL) { break; } iter->dnslabels[top + 1] = child->name; /* hashcode key = hash_dnslabel(child->name); dictionary_iterator_init_from(&parent->sub, &iter->stack[top], key); */ dictionary_iterator_init_from(&parent->sub, &iter->stack[top], child->name); parent = child; } while( ++top < real_top); dictionary_iterator_init(&parent->sub, &iter->stack[top]); iter->top = top; iter->current_label = parent; iter->zone = zone; #if ZDB_ZONE_LABEL_ITERATOR_CAN_SKIP_CHILDREN iter->prev_top = top - 1; // prev_top is used to skip children of the current label #endif iter->current_top = top; } /** * @brief Checks if there is still data available from an iterator * * Checks if there is still data available from an iterator * * @param[in] iter a pointer to the iterator * * @return TRUE if data is available, FALSE otherwise. * */ bool zdb_zone_label_iterator_hasnext(zdb_zone_label_iterator* iter) { return iter->current_label != NULL; } /** * @brief Copies the full name of the next label returned by the "next" call. * * Copies the full name of the next label returned by the "next" call. * * @param[in] iter a pointer to the iterator * @param[in] buffer256 a pointer to a buffer that will hold the full dns name * * @return the size of the dns name * */ u32 zdb_zone_label_iterator_nextname_to_cstr(zdb_zone_label_iterator* iter, char* buffer256) { u32 ret = dnslabel_stack_to_cstr(iter->dnslabels, iter->top, buffer256); #if ZLI_DEBUG zdb_rr_label *label = iter->current_label; if(label != NULL) { log_debug1("zli: %{dnsname}+%{dnslabel} nextname=%s (%u)", iter->zone->origin, label->name, buffer256, ret); } else { log_debug1("zli: %{dnsname}%NULL nextname=%s (%u)", iter->zone->origin, buffer256, ret); } u32 real_len = strlen(buffer256); if(real_len != ret) { log_err("zli: %d != %d", real_len, ret); } #endif return ret; } u32 zdb_zone_label_iterator_nextname(zdb_zone_label_iterator* iter, u8* buffer256) { /* TOP-DOWN stack */ u32 ret = dnslabel_stack_to_dnsname(iter->dnslabels, iter->top, buffer256); if(*iter->zone->origin == 0) { --ret; } #if ZLI_DEBUG zdb_rr_label *label = iter->current_label; if(label != NULL) { log_debug1("zli: %{dnsname}+%{dnslabel} nextname=%{dnsname} (%u)", iter->zone->origin, label->name, buffer256, ret); } else { log_debug1("zli: %{dnsname}%NULL nextname=%{dnsname} (%u)", iter->zone->origin, buffer256, ret); } u32 real_len = dnsname_len(buffer256); if(real_len != ret) { log_err("zli: %d != %d", real_len, ret); } #endif return ret; } /** * @brief Returns the next data available from an iterator * * Returns the next data available from an iterator * * @param[in] iter a pointer to the iterator * * @return a pointer to the next label * */ zdb_rr_label* zdb_zone_label_iterator_next(zdb_zone_label_iterator* iter) { zdb_rr_label* ret = iter->current_label; #if ZDB_ZONE_LABEL_ITERATOR_CAN_SKIP_CHILDREN iter->prev_top = iter->current_top; #endif iter->current_label = NULL; while(iter->top >= 0) { if(dictionary_iterator_hasnext(&iter->stack[iter->top])) { iter->current_label = *(zdb_rr_label**)dictionary_iterator_next(&iter->stack[iter->top]); iter->current_top = iter->top + 1; dictionary_iterator_init(&iter->current_label->sub, &iter->stack[++iter->top]); iter->dnslabels[iter->top] = iter->current_label->name; break; } #if DEBUG iter->dnslabels[iter->top] = (u8*)(intptr)0xfefefefefefefefeLL; memset(&iter->stack[iter->top], 0xfe, sizeof(iter->stack[iter->top])); #endif iter->top--; } return ret; } #if ZDB_ZONE_LABEL_ITERATOR_CAN_SKIP_CHILDREN /** * @brief Skips the children * * Skips the children * * @return * */ void zdb_zone_label_skip_children(zdb_zone_label_iterator* iter) { /* * If we are on a brother or on a parent there is nothing to do. */ if(iter->prev_top >= iter->current_top) { return; } iter->current_label = NULL; iter->top = iter->current_top - 2; while(iter->top >= 0) { if(dictionary_iterator_hasnext(&iter->stack[iter->top])) { iter->current_label = *(zdb_rr_label**)dictionary_iterator_next(&iter->stack[iter->top]); iter->current_top = iter->top + 1; dictionary_iterator_init(&iter->current_label->sub, &iter->stack[++iter->top]); iter->dnslabels[iter->top] = iter->current_label->name; break; } iter->top--; } } #endif /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_zone_label_iterator_ex.c0000644000000000000000000000013114505005531024505 xustar000000000000000030 mtime=1695812441.717971805 30 atime=1695812445.801030282 29 ctime=1695812495.13473684 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_zone_label_iterator_ex.c0000664000374500037450000001773614505005531024466 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to iterate through the labels of a zone * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include "dnscore/logger.h" #include "dnsdb/zdb_types.h" #include "dnsdb/nsec3_item.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_zone_label_iterator_ex.h" #include "dnsdb/zdb_zone_label_iterator.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger /** * @brief Initializes a zone label iterator * * Initializes a zone label iterator (iterates zdb_rr_label) * * @param[in] zone The zone to explore * @param[in] iter a pointer to the iterator to initialize * */ #define ZLI_DEBUG 0 void zdb_zone_label_iterator_ex_init(zdb_zone_label_iterator_ex* iter, const zdb_zone* zone) { memset(iter, 0, sizeof(zdb_zone_label_iterator_ex)); //iter->mode = ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS; // set by the memset iter->min_ttl = zone->min_ttl; iter->zone = zone; iter->n3 = zone->nsec.nsec3; iter->pool = &iter->pool_buffer[0]; //iter->nsec3_owner = NULL; //iter->nsec3_label.next = NULL; //iter->nsec3_label.sub.count = 0; iter->nsec3_label.resource_record_set = &iter->nsec3_label_nsec3; iter->nsec3_label_nsec3.hash = TYPE_NSEC3; iter->nsec3_label_rrsig.hash = TYPE_RRSIG; zdb_zone_label_iterator_init(&iter->iter.label_iter, zone); } /** * @brief Checks if there is still data available from an iterator * * Checks if there is still data available from an iterator * * @param[in] iter a pointer to the iterator * * @return TRUE if data is available, FALSE otherwise. * */ bool zdb_zone_label_iterator_ex_hasnext(zdb_zone_label_iterator_ex* iter) { bool ret; switch(iter->mode) { case ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS: { ret = zdb_zone_label_iterator_hasnext(&iter->iter.label_iter); if(ret) { return ret; } // end of the labels, prepare the NSEC3 if any if(iter->n3 == NULL) { return FALSE; } nsec3_iterator_init(&iter->n3->items, &iter->iter.nsec3_iter); iter->mode = ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN; // falls through on purpose FALLTHROUGH // fallthrough } case ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN: { ret = nsec3_iterator_hasnext(&iter->iter.nsec3_iter); if(ret) { iter->pool = &iter->pool_buffer[0]; // get the record and convert it to an zdb_rr_label nsec3_node *nsec3_node = nsec3_iterator_next_node(&iter->iter.nsec3_iter); nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm nsec3_parms = { iter->n3, nsec3_node, /// note: in an iterator, if used properly, the returned node cannot be NULL iter->zone->origin, &iter->pool, iter->min_ttl }; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, &iter->nsec3_owner, (zdb_packed_ttlrdata**)&iter->nsec3_label_nsec3.data, (const zdb_packed_ttlrdata**)&iter->nsec3_label_rrsig.data); // craft an zdb_rr_label that suits our needs if(iter->nsec3_label_rrsig.data != NULL) { iter->nsec3_label_nsec3.balance = -1; iter->nsec3_label_nsec3.children.lr.left = &iter->nsec3_label_rrsig; } else { iter->nsec3_label_nsec3.balance = 0; iter->nsec3_label_nsec3.children.lr.left = NULL; } return TRUE; } else { iter->mode = ZDB_ZONE_LABEL_ITERATOR_END_OF_ITERATION; } // FALLTHROUGH // fallthrough break; } } return FALSE; } /** * @brief Copies the full name of the next label returned by the "next" call. * * Copies the full name of the next label returned by the "next" call. * * @param[in] iter a pointer to the iterator * @param[in] buffer256 a pointer to a buffer that will hold the full dns name * * @return the size of the dns name * */ u32 zdb_zone_label_iterator_ex_nextname_to_cstr(zdb_zone_label_iterator_ex* iter, char* buffer256) { u32 ret; switch(iter->mode) { case ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS: { ret = zdb_zone_label_iterator_nextname_to_cstr(&iter->iter.label_iter, buffer256); return ret; } case ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN: { ret = dnsname_to_cstr(buffer256, iter->nsec3_owner); return ret; } } return 0; } u32 zdb_zone_label_iterator_ex_nextname(zdb_zone_label_iterator_ex* iter, u8* buffer256) { /* TOP-DOWN stack */ u32 ret; switch(iter->mode) { case ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS: { ret = zdb_zone_label_iterator_nextname(&iter->iter.label_iter, buffer256); return ret; } case ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN: { ret = dnsname_copy(buffer256, iter->nsec3_owner); return ret; } } return 0; } /** * @brief Returns the next data available from an iterator * * Returns the next data available from an iterator * * @param[in] iter a pointer to the iterator * * @return a pointer to the next label * */ zdb_rr_label* zdb_zone_label_iterator_ex_next(zdb_zone_label_iterator_ex* iter) { zdb_rr_label *ret; switch(iter->mode) { case ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS: { ret = zdb_zone_label_iterator_next(&iter->iter.label_iter); return ret; } case ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN: { ret = &iter->nsec3_label; return ret; } } return NULL; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_zone_load.c0000644000000000000000000000013214505005531021741 xustar000000000000000030 mtime=1695812441.715971776 30 atime=1695812445.801030282 30 ctime=1695812495.136736869 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_zone_load.c0000664000374500037450000012304014505005531021703 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #if ZDB_HAS_DNSSEC_SUPPORT #include #endif #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_icmtl.h" #include "dnsdb/zdb_sanitize.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_zone_write.h" #include "dnsdb/zdb_zone_label_iterator.h" #include "dnsdb/zdb-zone-find.h" #if ZDB_HAS_DNSSEC_SUPPORT #include "dnsdb/dnssec-keystore.h" #include "dnsdb/dnssec.h" #endif #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif #if ZDB_HAS_NSEC_SUPPORT #include "dnsdb/nsec.h" #endif #include "dnsdb/zdb_zone_load.h" extern logger_handle *g_database_logger; #define MODULE_MSG_HANDLE g_database_logger void zdb_zone_load_parms_init(struct zdb_zone_load_parms *parms, zone_reader *zr, const u8 *expected_origin, u16 flags) { ZEROMEMORY(parms, sizeof(struct zdb_zone_load_parms)); parms->zr = zr; parms->expected_origin = expected_origin; parms->dnskey_state = U32_SET_EMPTY; parms->out_zone = NULL; parms->flags = flags; parms->state = 0; } zdb_zone * zdb_zone_load_parms_zone_detach(struct zdb_zone_load_parms *parms) { zdb_zone *zone; zone = parms->out_zone; parms->out_zone = NULL; return zone; } zdb_zone * zdb_zone_load_parms_zone_get(struct zdb_zone_load_parms *parms) { return parms->out_zone; } ya_result zdb_zone_load_parms_result_code(struct zdb_zone_load_parms *parms) { return parms->result_code; } static void zdb_zone_load_parms_finalize_dnskey_state_cb(u32_node *node) { struct zdb_zone_load_dnskey_state_for_key *state = (struct zdb_zone_load_dnskey_state_for_key*)node->value; #if DEBUG union zdb_zone_load_dnskey_id id; id.id = node->key; log_debug("destroying key state: tag=%i alg=%i sig: count=%i from=%T until=%T flags=%x", ntohs(id.fields.tag), id.fields.algorithm, state->rrsig_count, state->signed_from, state->signed_until, state->flags); #endif ZFREE_OBJECT(state); } void zdb_zone_load_parms_finalize(struct zdb_zone_load_parms *parms) { if((parms->state & ZDB_ZONE_LOAD_STATE_SANITIZE_FIELD_AVAIABLE) != 0) { zdb_sanitize_parms_finalize(&parms->sanitize_parms); parms->state &= ~ZDB_ZONE_LOAD_STATE_SANITIZE_FIELD_AVAIABLE; } if(parms->dnskey_state != NULL) { // destroy the collection u32_set_callback_and_destroy(&parms->dnskey_state, zdb_zone_load_parms_finalize_dnskey_state_cb); } if(parms->out_zone != NULL) { // releases the zone zdb_zone_release(parms->out_zone); parms->out_zone = NULL; } } struct zdb_zone_load_dnskey_state_for_key* zdb_zone_load_parms_dnskey_state(struct zdb_zone_load_parms *parms, union zdb_zone_load_dnskey_id id) { u32_node *node = u32_set_insert(&parms->dnskey_state, id.id); struct zdb_zone_load_dnskey_state_for_key *state; if(node->value == NULL) { // new instance ZALLOC_OBJECT_OR_DIE(state, struct zdb_zone_load_dnskey_state_for_key, ZZLDSKEY_TAG); state->signed_from = MAX_U32; state->signed_until = 0; state->rrsig_count = 0; state->key_flags = 0; state->flags = 0; node->value = state; } else { state = (struct zdb_zone_load_dnskey_state_for_key*)node->value; } return state; } void zdb_zone_load_parms_dnskey_add(struct zdb_zone_load_parms *parms, const u8 *dnskey_rdata, u16 dnskey_rdata_size) { if(dnskey_rdata_size < 4) { return; } u16 tag = dnskey_get_tag_from_rdata(dnskey_rdata, dnskey_rdata_size); u8 alg = dnskey_get_algorithm_from_rdata(dnskey_rdata); // insert node union zdb_zone_load_dnskey_id id; id.fields.tag = tag; id.fields.algorithm = alg; id.fields.must_be_zero = 0; struct zdb_zone_load_dnskey_state_for_key *state = zdb_zone_load_parms_dnskey_state(parms, id); state->flags |= ZDB_ZONE_LOAD_DNSKEY_STATE_FLAG_HAS_PUBKEY; state->key_flags = dnskey_get_flags_from_rdata(dnskey_rdata); } u16 zdb_zone_load_parms_get_key_flags_from_rrsig_rdata(struct zdb_zone_load_parms *parms, const u8 *rrsig_rdata, u16 rrsig_rdata_size) { u16 tag = rrsig_get_key_tag_from_rdata(rrsig_rdata, rrsig_rdata_size); u8 alg = rrsig_get_algorithm_from_rdata(rrsig_rdata, rrsig_rdata_size); union zdb_zone_load_dnskey_id id; id.fields.tag = tag; id.fields.algorithm = alg; id.fields.must_be_zero = 0; struct zdb_zone_load_dnskey_state_for_key *state = zdb_zone_load_parms_dnskey_state(parms, id); return state->key_flags; } void zdb_zone_load_parms_rrsig_add(struct zdb_zone_load_parms *parms, const u8 *rrsig_rdata, u16 rrsig_rdata_size) { if(rrsig_rdata_size < RRSIG_RDATA_HEADER_LEN) { return; } u16 tag = rrsig_get_key_tag_from_rdata(rrsig_rdata, rrsig_rdata_size); u8 alg = rrsig_get_algorithm_from_rdata(rrsig_rdata, rrsig_rdata_size); // insert node union zdb_zone_load_dnskey_id id; id.fields.tag = tag; id.fields.algorithm = alg; id.fields.must_be_zero = 0; struct zdb_zone_load_dnskey_state_for_key *state = zdb_zone_load_parms_dnskey_state(parms, id); state->flags |= ZDB_ZONE_LOAD_DNSKEY_STATE_FLAG_HAS_PUBKEY; s64 valid_until = rrsig_get_valid_until_from_rdata(rrsig_rdata, rrsig_rdata_size); s64 valid_from = rrsig_get_valid_from_from_rdata(rrsig_rdata, rrsig_rdata_size); if(state->signed_until < valid_until) { state->signed_until = valid_until; } if(state->signed_from > valid_from) { state->signed_from = valid_from; } ++state->rrsig_count; } ya_result zdb_zone_load_ex(struct zdb_zone_load_parms *parms) { u64 wire_size = 0; u8* rdata; size_t rdata_len; ya_result return_code; resource_record entry; s32 soa_min_ttl = 0; u32 soa_serial = 0; u32 earliest_signature_expiration = MAX_S32; #if ZDB_HAS_DNSSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT u32 has_optout = 0; u32 has_optin = 0; #endif bool nsec3_keys = FALSE; bool nsec_keys = FALSE; bool has_dnskey = FALSE; #endif bool has_nsec3 = FALSE; bool has_nsec = FALSE; bool has_rrsig = FALSE; bool dynupdate_forbidden = FALSE; //bool modified = FALSE; #if ZDB_HAS_NSEC3_SUPPORT nsec3_load_context nsec3_context; #endif char origin_ascii[MAX_DOMAIN_TEXT_LENGTH + 1]; if((parms->zr == NULL) || (parms->out_zone != NULL)) { parms->result_code = INVALID_ARGUMENT_ERROR; return INVALID_ARGUMENT_ERROR; // reader must be set, out_zone must be NULL } /* ------------------------------------------------------------ */ zone_reader *zr = parms->zr; const u8 *expected_origin = parms->expected_origin; const u16 flags = parms->flags; resource_record_init(&entry); if(FAIL(return_code = zone_reader_read_record(zr, &entry))) { resource_record_freecontent(&entry); /* destroys */ const char *message = zone_reader_get_last_error_message(zr); if(expected_origin != NULL) { if(message == NULL) { log_err("zone load: %{dnsname}: reading zone: %r", expected_origin, return_code); } else { log_err("zone load: %{dnsname}: reading zone: %s: %r", expected_origin, message, return_code); } } else { if(message == NULL) { log_err("zone load: reading zone: %r", return_code); } else { log_err("zone load: reading zone: %s: %r", message, return_code); } } parms->result_code = return_code; return return_code; } if(entry.type != TYPE_SOA) { /* bad */ resource_record_freecontent(&entry); /* destroys */ if(expected_origin != NULL) { log_err("zone load: %{dnsname}: first record expected to be an SOA, got %{dnstype} instead", expected_origin, &entry.type); } else { log_err("zone load: first record expected to be an SOA, got %{dnstype} instead", &entry.type); } parms->result_code = ZDB_READER_FIRST_RECORD_NOT_SOA; return ZDB_READER_FIRST_RECORD_NOT_SOA; } if(expected_origin != NULL) { bool char_space_ok = TRUE; bool matched_origin = TRUE; if(!((char_space_ok = dnsname_locase_verify_charspace(entry.name)) && (matched_origin = dnsname_equals(entry.name, expected_origin)))) { if(!char_space_ok) { log_err("zone load: %{dnsname}: invalid character space: %{dnsname}", expected_origin, entry.name); } if(!matched_origin) { log_err("zone load: %{dnsname}: found name outside of zone: %{dnsname}", expected_origin, entry.name); } resource_record_freecontent(&entry); /* destroys, actually no-operation in this version */ parms->result_code = ZDB_READER_WRONGNAMEFORZONE; return ZDB_READER_WRONGNAMEFORZONE; } if(!matched_origin) { resource_record_freecontent(&entry); /* destroys */ log_err("zone load: %{dnsname}: zone file domain do not match the expected one (%{dnsname})", expected_origin, entry.name); parms->result_code = ZDB_READER_ANOTHER_DOMAIN_WAS_EXPECTED; return ZDB_READER_ANOTHER_DOMAIN_WAS_EXPECTED; } } else { bool char_space_ok = dnsname_locase_verify_charspace(entry.name); if(!char_space_ok) { log_err("zone load: invalid character space: %{dnsname}", entry.name); resource_record_freecontent(&entry); /* destroys, actually no-operation in this version */ parms->result_code = ZDB_READER_WRONGNAMEFORZONE; return ZDB_READER_WRONGNAMEFORZONE; } } dnsname_vector name; DEBUG_RESET_dnsname(name); u16 zclass = entry.class; dnsname_to_dnsname_vector(entry.name, &name); rr_soa_get_minimumttl(zone_reader_rdata(entry), zone_reader_rdata_size(entry), &soa_min_ttl); rr_soa_get_serial(zone_reader_rdata(entry), zone_reader_rdata_size(entry), &soa_serial); dnsname_to_cstr(origin_ascii, entry.name); dynupdate_forbidden = FALSE; #if ZDB_HAS_DNSSEC_SUPPORT has_dnskey = FALSE; has_nsec3 = FALSE; has_nsec = FALSE; nsec3_keys = FALSE; nsec_keys = FALSE; #if ZDB_HAS_NSEC3_SUPPORT has_optout = 0; has_optin = 0; #endif #endif zdb_zone* zone; zone = zdb_zone_create(entry.name); // comes with an RC = 1, not locked if(zone == NULL) { log_err("zone load: unable to load zone %{dnsname} %{dnsclass}", entry.name, &zclass); parms->result_code = ZDB_ERROR_NOSUCHCLASS; return ZDB_ERROR_NOSUCHCLASS; } zdb_zone_lock(zone, ZDB_ZONE_MUTEX_LOAD); zone->min_ttl = soa_min_ttl; zone->text_serial = soa_serial; zone->axfr_serial = soa_serial - 1; /* ensure that the axfr on disk is not automatically taken in account later */ if((parms->flags & ZDB_ZONE_NO_MAINTENANCE) == 0) { switch(parms->flags & ZDB_ZONE_DNSSEC_MASK) { case ZDB_ZONE_NSEC: zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC); break; case ZDB_ZONE_NSEC3: zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3); break; case ZDB_ZONE_NSEC3_OPTOUT: zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT); break; } } dnsname_to_dnsname_vector(zone->origin, &name); //dnsname_vector_copy(&name, &zone->origin_vector); #if ZDB_HAS_NSEC3_SUPPORT nsec3_load_init(&nsec3_context, zone); nsec3_load_allowed_to_fix(&nsec3_context, (parms->flags & ZDB_ZONE_IS_SLAVE) == 0); #endif zdb_packed_ttlrdata* ttlrdata; u32 loop_count; for(loop_count = 1;; loop_count++) { /* Add the entry */ if(dnscore_shuttingdown()) { return_code = STOPPED_BY_APPLICATION_SHUTDOWN; break; } dnsname_vector entry_name; DEBUG_RESET_dnsname(entry_name); dnsname_to_dnsname_vector(entry.name, &entry_name); s32 a_i, b_i; if((a_i = name.size) > (b_i = entry_name.size)) { // error return_code = ZDB_READER_WRONGNAMEFORZONE; log_err("zone load: domain name %{dnsnamevector} is too big", &entry_name); break; } /* ZONE ENTRY CHECK */ while(a_i >= 0) { const u8* a = name.labels[a_i--]; const u8* b = entry_name.labels[b_i--]; if(!dnslabel_equals(a, b)) { log_warn("zone load: bad domain name %{dnsnamevector} for zone %{dnsnamevector}", &entry_name, &name); goto zdb_zone_load_loop; } } if(FAIL(return_code)) { break; } rdata_len = zone_reader_rdata_size(entry); rdata = zone_reader_rdata(entry); #if ZDB_HAS_NSEC3_SUPPORT /* * SPECIAL NSEC3 support !!! * * If the record is an RRSIG(NSEC3), an NSEC3, or an NSEC3PARAM then * it cannot be handled the same way as the others. * */ if(entry.type == TYPE_NSEC3PARAM) { if(FAIL(return_code = nsec3_load_add_nsec3param(&nsec3_context, rdata, rdata_len))) { break; } // ALWAYS accept the value of the TTL that's being given. ZDB_RECORD_ZALLOC(ttlrdata, entry.ttl, rdata_len, rdata); zdb_zone_record_add(zone, entry_name.labels, entry_name.size, entry.type, ttlrdata); // verified // has_nsec3 ? has_nsec3 = TRUE; } else if(entry.type == TYPE_NSEC3CHAINSTATE) { if(FAIL(nsec3_load_add_nsec3chainstate(&nsec3_context, rdata, rdata_len))) { break; } ZDB_RECORD_ZALLOC(ttlrdata, /*entry.ttl*/0, rdata_len, rdata); zdb_zone_record_add(zone, entry_name.labels, entry_name.size, entry.type, ttlrdata); // verified } else if(entry.type == TYPE_NSEC3) { bool rdata_optout = NSEC3_RDATA_IS_OPTOUT(rdata); if(rdata_optout) { has_optout++; } else { has_optin++; } if(FAIL(return_code = nsec3_load_add_nsec3(&nsec3_context, entry.name, entry.ttl, rdata, rdata_len))) { break; } has_nsec3 = TRUE; } else if(entry.type == TYPE_RRSIG && ((GET_U16_AT(*rdata)) == TYPE_NSEC3)) /** @note : NATIVETYPE */ { if(FAIL(return_code = nsec3_load_add_rrsig(&nsec3_context, entry.name, /*entry.ttl*/soa_min_ttl, rdata, rdata_len))) { break; } } else { #endif /* * This is the general case * It happen with NSEC3 support if the type is neither NSEC3PARAM, NSEC3 nor RRSIG(NSEC3) */ switch(entry.type) { case TYPE_DNSKEY: { #if ZDB_HAS_DNSSEC_SUPPORT /* * Check if we have access to the private part of the key */ u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_len); u16 key_flags = GET_U16_AT(rdata[0]); u8 algorithm = rdata[3]; switch(algorithm) { case DNSKEY_ALGORITHM_DSASHA1: case DNSKEY_ALGORITHM_RSASHA1: { nsec_keys = TRUE; break; } case DNSKEY_ALGORITHM_DSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: { nsec3_keys = TRUE; break; } case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: case DNSKEY_ALGORITHM_ECDSAP256SHA256: case DNSKEY_ALGORITHM_ECDSAP384SHA384: case DNSKEY_ALGORITHM_ED25519: case DNSKEY_ALGORITHM_ED448: #ifdef DNSKEY_ALGORITHM_DUMMY case DNSKEY_ALGORITHM_DUMMY: #endif { nsec_keys = TRUE; nsec3_keys = TRUE; break; } default: { log_info("zone load: unknown key algorithm for K%{dnsname}+%03d+%05hd", zone->origin, algorithm, tag); break; } } dnssec_key *key = NULL; if((flags & ZDB_ZONE_IS_SLAVE) == 0) { if(ISOK(return_code = dnssec_keystore_load_private_key_from_parameters(algorithm, tag, key_flags, zone->origin, &key))) // converted, key properly released { if(return_code > 0) { log_info("zone load: loaded private key K%{dnsname}+%03d+%05hd", zone->origin, algorithm, tag); } // we are only interested on its existence so it can be released now (the fact the pointer is not NULL is all that matters) dnskey_state_enable(key, DNSKEY_KEY_IS_IN_ZONE); dnskey_release(key); has_dnskey = TRUE; } else { int log_level = zdb_zone_get_rrsig_push_allowed(zone)?MSG_INFO:MSG_WARNING; log_to_level(log_level, "zone load: unable to load the private key K%{dnsname}+%03d+%05hd: %r", zone->origin, algorithm, tag, return_code); } } if(key == NULL) { /* * Either: * * _ The private key is not available (error) * _ The private key should not be loaded (slave) * * Get the public key for signature verifications. */ if(ISOK(return_code = dnssec_keystore_load_public_key_from_rdata(rdata, rdata_len, zone->origin, &key))) // converted { log_info("zone load: loaded public key K%{dnsname}+%03d+%05hd", zone->origin, algorithm, tag); dnskey_state_enable(key, DNSKEY_KEY_IS_IN_ZONE); dnskey_release(key); has_dnskey = TRUE; } else { /* the key is wrong */ log_warn("zone load: unable to load public key K%{dnsname}+%03d+%05hd: %r", zone->origin, algorithm, tag, return_code); } } #else /* DNSKEY not supported */ #endif ZDB_RECORD_ZALLOC(ttlrdata, entry.ttl, rdata_len, rdata); zdb_zone_record_add(zone, entry_name.labels, entry_name.size, entry.type, ttlrdata); // class is implicit, verified break; } #if ZDB_HAS_NSEC_SUPPORT case TYPE_NSEC: { has_nsec = TRUE; ZDB_RECORD_ZALLOC(ttlrdata, entry.ttl, rdata_len, rdata); zdb_zone_record_add(zone, entry_name.labels, entry_name.size, entry.type, ttlrdata); /* class is implicit */ break; } #endif case TYPE_RRSIG: { #if !ZDB_HAS_DNSSEC_SUPPORT if(!has_rrsig) { log_warn("zone load: type %{dnstype} is not supported", &entry.type); } #else has_rrsig = TRUE; #endif u32 rrsig_expiration = rrsig_get_valid_until_from_rdata(rdata, rdata_len); if(rrsig_expiration < earliest_signature_expiration) { earliest_signature_expiration = rrsig_expiration; } } FALLTHROUGH // fall through default: { ZDB_RECORD_ZALLOC(ttlrdata, entry.ttl, rdata_len, rdata); zdb_zone_record_add(zone, entry_name.labels, entry_name.size, entry.type, ttlrdata); // class is implicit, name parameters verified break; } #if !ZDB_HAS_NSEC3_SUPPORT case TYPE_NSEC3PARAM: { if(!has_nsec3param) { log_warn("zone load: type %{dnstype} is not supported", &entry.type); } has_nsec3param = TRUE; break; } case TYPE_NSEC3: { if(!has_nsec3) { log_warn("zone load: type %{dnstype} is not supported", &entry.type); } has_nsec3 = TRUE; break; } #endif #if !ZDB_HAS_NSEC_SUPPORT case TYPE_NSEC: { if(!has_nsec) { log_warn("zone load: type %{dnstype} is not supported", &entry.type); } has_nsec = TRUE; break; } #endif } // switch(entry.type) #if ZDB_HAS_NSEC3_SUPPORT } // else #endif zdb_zone_load_loop: wire_size += resource_record_size(&entry); resource_record_resetcontent(&entry); /* "next" */ /** * Note : Return can be * * OK: got a record * 1: end of zone file * error code: failure */ if(OK != (return_code = zone_reader_read_record(zr, &entry))) { if(FAIL(return_code)) { if(return_code == /**/ ERROR) { return_code = UNEXPECTED_EOF; } const char *message = zone_reader_get_last_error_message(zr); if(message == NULL) { log_err("zone load: reading record #%d of zone %{dnsname}: %r", loop_count, zone->origin, return_code); } else { log_err("zone load: reading record #%d of zone %{dnsname}: %s: %r", loop_count, zone->origin, message, return_code); } } break; } if(!dnsname_locase_verify_charspace(entry.name)) { log_warn("zone load: DNS character space error on '%{dnsname}'", entry.name); } } resource_record_freecontent(&entry); /* destroys, not "next" */ if(ISOK(return_code)) { zdb_sanitize_zone_rrset_flags(zone); } #if ZDB_HAS_DNSSEC_SUPPORT #if ZDB_HAS_NSEC3_SUPPORT if(has_nsec3 && (has_optout > 0)) { zone->_flags |= ZDB_ZONE_HAS_OPTOUT_COVERAGE; } #endif log_debug7("zone load: has_rrsig=%i has_dnskey=%i", has_rrsig, has_dnskey); #endif if(dynupdate_forbidden) { log_info("zone load: freezing zone %{dnsname}", zone->origin); zdb_zone_set_frozen(zone); } #if ZDB_HAS_DNSSEC_SUPPORT if(ISOK(return_code)) { if(has_nsec && has_nsec3) { log_err("zone load: zone %{dnsname} has both NSEC and NSEC3 records!", zone->origin); // return_code = ZDB_READER_MIXED_DNSSEC_VERSIONS; has_nsec = FALSE; } if((flags & ZDB_ZONE_IS_SLAVE) == 0) { if(nsec_keys && nsec3_keys) // after algorithm 7, keys can be used both for NSEC and NSEC3 { if(!(has_nsec3|has_nsec)) { log_warn("zone load: zone %{dnsname} has DNSKEY but there is no NSEC nor NSEC3 coverage", zone->origin); } } else if(nsec3_keys) { if(!has_nsec3) { log_warn("zone load: zone %{dnsname} has NSEC3 DNSKEY but there is no NSEC3 coverage", zone->origin); } } else if(nsec_keys) { if(!has_nsec) { log_warn("zone load: zone %{dnsname} has NSEC DNSKEY but there is no NSEC coverage", zone->origin); } } else { if(has_nsec3) { log_warn("zone load: zone %{dnsname} is NSEC3 but there are no NSEC3 keys available", zone->origin); } if(has_nsec) { log_warn("zone load: zone %{dnsname} is NSEC but there are no NSEC keys available", zone->origin); } } } } if(ISOK(return_code)) { if(!(has_nsec || has_nsec3)) { switch(flags & ZDB_ZONE_DNSSEC_MASK) { case ZDB_ZONE_NSEC: { log_warn("zone load: zone is configured as NSEC but no NSEC records have been found"); if((flags & ZDB_ZONE_IS_SLAVE) == 0) { has_nsec = TRUE; } break; } case ZDB_ZONE_NSEC3: case ZDB_ZONE_NSEC3_OPTOUT: { log_warn("zone load: zone is configured as NSEC3 but no NSEC3 records have been found"); if((flags & ZDB_ZONE_IS_SLAVE) == 0) { has_nsec3 = TRUE; } break; } default: { break; } } } if(has_nsec3) { if((parms->flags & ZDB_ZONE_NO_MAINTENANCE) == 0) { zone->_flags |= ZDB_ZONE_MAINTAIN_NSEC3; if(has_optout > 0) { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT); } else { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3); } } zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_N3OCOVERED|ZDB_RR_LABEL_N3COVERED); #if ZDB_HAS_NSEC3_SUPPORT /** * Check if there is both NSEC & NSEC3. Reject if yes. * compile NSEC if any * compile NSEC3 if any * * I'm only doing NSEC3 here. */ if((flags & ZDB_ZONE_DNSSEC_MASK) == ZDB_ZONE_NSEC) { log_warn("zone load: zone %{dnsname} was set to NSEC but is NSEC3", zone->origin); } if(has_optin > 0) { if(has_optout > 0) { log_warn("zone load: zone %{dnsname} has got both OPT-OUT and OPT-IN records (%u and %u)", zone->origin, has_optout, has_optin); nsec3_context.opt_out = TRUE; } else { nsec3_context.opt_out = FALSE; } if((flags & ZDB_ZONE_DNSSEC_MASK) == ZDB_ZONE_NSEC3_OPTOUT) { log_warn("zone load: zone %{dnsname} was set to OPT-OUT but appears to be OPT-IN", zone->origin); } } else if(has_optout > 0) { /* has_optin is false and has_optout is true */ if((flags & ZDB_ZONE_DNSSEC_MASK) == ZDB_ZONE_NSEC3) { log_warn("zone load: zone %{dnsname} was set to OPT-IN but appears to be OPT-OUT (%u)", zone->origin, has_optout); } nsec3_context.opt_out = TRUE; } else /* use the configuration */ { nsec3_context.opt_out = ((flags & ZDB_ZONE_DNSSEC_MASK) == ZDB_ZONE_NSEC3_OPTOUT)?TRUE:FALSE; } log_info("zone load: zone %{dnsname} is %s", zone->origin, (nsec3_context.opt_out)?"OPT-OUT":"OPT-IN"); /* If there is something in the NSEC3 context ... */ if(!nsec3_load_is_context_empty(&nsec3_context)) { /* ... do it. */ log_debug("zone load: zone %{dnsname}: NSEC3 post-processing.", zone->origin); return_code = nsec3_load_generate(&nsec3_context); if(((flags & ZDB_ZONE_IS_SLAVE) != 0) && (nsec3_context.nsec3_rejected > 0)) { return_code = DNSSEC_ERROR_NSEC3_INVALIDZONESTATE; // the zone is corrupted and as a slave nothing can be done about it. } if(ISOK(return_code)) { /* if(nsec3_context.opt_out) { zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC3 | ZDB_RR_LABEL_NSEC3_OPTOUT); } else { zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC3); } */ if(nsec3_context.fix_applied) { parms->state |= ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_NSEC3_CHAIN_FIXED; zdb_zone_set_status(zone, ZDB_ZONE_STATUS_MODIFIED); } #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT zdb_zone_set_maintained(zone, TRUE); #endif log_debug("zone load: zone %{dnsname}: NSEC3 post-processing done", zone->origin); } else { log_err("zone load: zone %{dnsname}: error %r: NSEC3 post-processing failed", zone->origin, return_code); } } else { log_debug("zone load: zone %{dnsname}: NSEC3 context is empty", zone->origin); has_nsec3 = FALSE; } #else // ZDB_HAS_NSEC3_SUPPORT is 0 log_err("zone load: zone %{dnsname} has NSEC3* record(s) but the server has been compiled without NSEC support", zone->origin); #endif } else if(has_nsec) { zone->_flags |= ZDB_ZONE_MAINTAIN_NSEC; if((flags & ZDB_ZONE_DNSSEC_MASK) >= ZDB_ZONE_NSEC3) { log_warn("zone load: zone %{dnsname} was set to NSEC3 but is NSEC", zone->origin); } #if ZDB_HAS_NSEC_SUPPORT log_debug("zone load: zone %{dnsname}: NSEC post-processing.", zone->origin); if(ISOK(return_code = nsec_update_zone(zone, (flags & ZDB_ZONE_IS_SLAVE) != 0))) {//DNSSEC_ERROR_NSEC_INVALIDZONESTATE zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC); zdb_rr_label_flag_and(zone->apex, ~(ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT)); #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT zdb_zone_set_maintained(zone, (flags & ZDB_ZONE_IS_SLAVE) == 0); #endif } #else log_err("zone load: zone %{dnsname} has NSEC record(s) but the server has been compiled without NSEC support", zone->origin); #endif } } #endif #if ZDB_HAS_NSEC3_SUPPORT nsec3_load_destroy(&nsec3_context); #endif if(ISOK(return_code)) { log_info("zone load: zone %{dnsname} has been loaded (%d record(s) parsed)", zone->origin, loop_count); log_debug("zone load: zone %{dnsname} wire size: %i", zone->origin, wire_size); zone->wire_size = wire_size; zone->progressive_signature_update.earliest_signature_expiration = earliest_signature_expiration; log_debug("zone load: zone %{dnsname} earliest signature expiration at %T in %d seconds", zone->origin, earliest_signature_expiration, (s32)(earliest_signature_expiration - time(NULL))); parms->out_zone = zone; #if defined(ZDB_ZONE_MOUNT_ON_LOAD) if((flags & ZDB_ZONE_MOUNT_ON_LOAD) != 0) { log_info("zone load: zone %{dnsname} has been mounted", zone->origin); zdb_zone *old_zone = zdb_set_zone(db, zone); yassert(old_zone == NULL); (void)old_zone; } #endif } else { log_err("zone load: zone %{dnsname}: error %r (%d record(s) parsed)", zone->origin, return_code, loop_count); } if(ISOK(return_code) && ((flags & ZDB_ZONE_REPLAY_JOURNAL) != 0)) { /* * The zone file has been read. * NSEC structures have been created * * At this point, the incremental journal should be replayed. * */ #if DEBUG log_debug("zone load: replaying changes from journal"); #endif zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_LOAD); return_code = zdb_icmtl_replay(zone); zdb_zone_lock(zone, ZDB_ZONE_MUTEX_LOAD); if(ISOK(return_code)) { if(return_code > 0) { log_info("zone load: replayed %d changes from journal", return_code); } if(!has_nsec3) { if((has_nsec3 = zdb_rr_label_flag_isset(zone->apex, ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT))) { zone->_flags |= ZDB_ZONE_MAINTAIN_NSEC3; if((zone->apex->nsec.nsec3 != NULL) && (has_optout = zone->apex->nsec.nsec3->_self != NULL)) { has_optout = (zone->apex->nsec.nsec3->_self->flags != 0); } } } if(has_nsec3 && (has_optout > 0)) { zone->_flags |= ZDB_ZONE_HAS_OPTOUT_COVERAGE; } if(parms->state & ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_NSEC3_CHAIN_FIXED) { // the zone must look new to the slaves // increment serial // sign serial // delete journal before mount zdb_packed_ttlrdata *soa_rr = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA); yassert(soa_rr != NULL); rr_soa_increase_serial(ZDB_PACKEDRECORD_PTR_RDATAPTR(soa_rr), ZDB_PACKEDRECORD_PTR_RDATASIZE(soa_rr), 1); rrsig_delete_covering(zone->apex, TYPE_SOA); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_MODIFIED); } if((flags & ZDB_ZONE_IS_SLAVE) == 0) { //#if DEBUG log_info("zone load: post-replay sanity check for %{dnsname}", zone->origin); //#endif if(ISOK(return_code = zdb_sanitize_zone_ex(zone, parms))) { log_info("zone load: post-replay sanity check for %{dnsname} done", zone->origin); } else { log_err("zone load: impossible to sanitise %{dnsname}, dropping zone", zone->origin); } log_debug("zone load: post-replay sanity check for %{dnsname} done", zone->origin); } else { log_debug("zone load: no post-replay sanity check for %{dnsname} slave", zone->origin); } if(has_nsec3) { // the chain has just been created, but is probably missing internal links log_debug("journal: %{dnsname}: no journal, updating links", zone->origin); nsec3_zone_update_chain0_links(zone); } } else if(return_code == ZDB_ERROR_ICMTL_NOTFOUND) { if((flags & ZDB_ZONE_IS_SLAVE) == 0) { log_debug("zone load: post-replay sanity check for %{dnsname}", zone->origin); if(ISOK(return_code = zdb_sanitize_zone_ex(zone, parms))) { log_info("zone load: post-replay sanity check for %{dnsname} done", zone->origin); if(has_nsec3) { // the chain has just been created, but is probably missing internal links log_debug("journal: %{dnsname}: no journal, updating links", zone->origin); nsec3_zone_update_chain0_links(zone); } } else { log_err("zone load: impossible to sanitise %{dnsname}, dropping zone", zone->origin); } } else { log_debug("zone load: no post-replay sanity check for %{dnsname} slave", zone->origin); } } else { log_err("zone load: journal replay returned %r", return_code); } /* * End of the incremental replay */ } if(zone != NULL) { zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_LOAD); if(FAIL(return_code)) { zdb_zone_release(zone); parms->out_zone = NULL; } } parms->result_code = return_code; return return_code; } /** * @brief Load a zone in the database. * * Load a zone in the database. * * @note It is not a good idea to scan the zone content in here. ie: getting the earliest signature expiration. (It's counter-productive and pointless) * * @param[in] db_UNUSED a pointer to the database, obsolete, can be set to NULL * @param[in] zr a pointer to an opened zone_reader * @param[in] zone_pointer_out a pointer to the pointer that will be set with the loaded zone * @param[in] expected_origin the expected origin for the loaded file, can be set to NULL * @param[in] flags various flags * * @return an error code. * */ ya_result zdb_zone_load(zdb *db_UNUSED, zone_reader *zr, zdb_zone **zone_pointer_out, const u8 *expected_origin, u16 flags) { (void)db_UNUSED; struct zdb_zone_load_parms parms; zdb_zone_load_parms_init(&parms, zr, expected_origin, flags); ya_result ret = zdb_zone_load_ex(&parms); if(ISOK(ret)) { *zone_pointer_out = zdb_zone_load_parms_zone_detach(&parms); } else { *zone_pointer_out = NULL; } zdb_zone_load_parms_finalize(&parms); return ret; } /** * @brief Load the zone SOA. * * Load the zone SOA record * This is meant mainly for the slave that could choose between, ie: zone file or axfr zone file * The SOA MUST BE the first record * * @param[in] db a pointer to the database * @param[in] zone_data a pointer to an opened zone_reader at its start * @param[out] zone_pointer_out will contains a pointer to the loaded zone if the call is successful * * @return an error code. * */ ya_result zdb_zone_get_soa(zone_reader *zone_data, u16 *rdata_size, u8 *rdata) { ya_result return_value; resource_record entry; resource_record_init(&entry); if(ISOK(return_value = zone_reader_read_record(zone_data, &entry))) { if(entry.type == TYPE_SOA) { s32 soa_rdata_len = zone_reader_rdata_size(entry); u8 *soa_rdata = zone_reader_rdata(entry); if(soa_rdata_len < MAX_SOA_RDATA_LENGTH) { memcpy(rdata, soa_rdata, soa_rdata_len); *rdata_size = soa_rdata_len; } else { return_value = INVALID_RECORD; // too big } } else { return_value = INVALID_STATE_ERROR; } } return return_value; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_zone_process.c0000644000000000000000000000013214505005531022500 xustar000000000000000030 mtime=1695812441.714971762 30 atime=1695812445.800030268 30 ctime=1695812495.138736897 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_zone_process.c0000664000374500037450000001012414505005531022440 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief Functions used to manipulate a zone * * Functions used to manipulate a zone * * @{ */ #include "dnsdb/dnsdb-config.h" #include #include "dnsdb/dictionary.h" #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3_types.h" #include "dnsdb/nsec3_item.h" #endif #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_process.h" static ya_result zdb_zone_process_label_children(zdb_zone_process_label_callback_parms *parms) { ya_result return_code = SUCCESS; dictionary_iterator iter; dictionary_iterator_init(&parms->rr_label->sub, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_rr_label** sub_labelp = (zdb_rr_label**)dictionary_iterator_next(&iter); dnsname_stack_push_label(&parms->fqdn_stack, &(*sub_labelp)->name[0]); parms->rr_label = *sub_labelp; return_code = parms->cb(parms); if((FAIL(return_code) || return_code == ZDB_ZONE_PROCESS_STOP)) { break; } return_code = zdb_zone_process_label_children(parms); if((FAIL(return_code) || return_code == ZDB_ZONE_PROCESS_STOP)) { break; } dnsname_stack_pop_label(&parms->fqdn_stack); } return return_code; } ya_result zdb_zone_process_all_labels_from_zone(zdb_zone *zone, zdb_zone_process_label_callback *cb, void *args) { yassert(zdb_zone_islocked(zone)); ya_result ret; if(zone != NULL) { if(zone->apex != NULL) { zdb_zone_process_label_callback_parms parms; parms.cb = cb; parms.zone = zone; parms.args = args; if(ISOK(ret = dnsname_to_dnsname_stack(zone->origin, &parms.fqdn_stack))) { parms.rr_label = zone->apex; ret = cb(&parms); if(!(FAIL(ret) || ret == ZDB_ZONE_PROCESS_STOP)) { zdb_zone_process_label_children(&parms); } } } else { ret = INVALID_STATE_ERROR; } } else { ret = UNEXPECTED_NULL_ARGUMENT_ERROR; } return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_zone_store_axfr.c0000644000000000000000000000013214505005531023176 xustar000000000000000030 mtime=1695812441.748972248 30 atime=1695812445.802030296 30 ctime=1695812495.140736926 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_zone_store_axfr.c0000664000374500037450000002461614505005531023151 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include "dnsdb/zdb_types.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_zone_label_iterator.h" #include "dnsdb/zdb_record.h" #include #include #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif #include #include #include "dnsdb/zdb_utils.h" #include // With this set to 1, AXFR storage on disk will be extremely slow. // Meant to debug network faster than disk speeds. // The value is expressed in ms // // Keep this to 0 except if you need it to be slow #define DEBUG_SLOW_STORAGE_MS 0 // 100 #if !DEBUG #undef DEBUG_SLOW_STORAGE_MS #define DEBUG_SLOW_STORAGE_MS 0 #endif /* * */ struct type_class_ttl_size { u16 rtype; u16 rclass; u32 rttl; u16 rsize; }; #define TCTS_SIZE 10 //static const u8 wild_wire[2] = {1, '*'}; ya_result zdb_zone_store_axfr(zdb_zone* zone, output_stream* os) { zdb_rr_label* label; u32 fqdn_len; ya_result err = SUCCESS; u8 fqdn[MAX_DOMAIN_LENGTH]; zdb_zone_label_iterator iter; btree_iterator type_iter; struct type_class_ttl_size rec; yassert((((u8*) & rec.rtype - (u8*) & rec) == 0) && (((u8*) & rec.rclass - (u8*) & rec) == 2) && (((u8*) & rec.rttl - (u8*) & rec) == 4) && (((u8*) & rec.rsize - (u8*) & rec) == 8) ); /* Else the struct is "aligned" ... and broken */ yassert(zdb_zone_islocked(zone)); rec.rclass = zdb_zone_getclass(zone); /** @note: NATIVECLASS */ zdb_packed_ttlrdata* soa = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA); if(soa == NULL) { return ZDB_ERROR_GENERAL; } s32 minimum_ttl; zdb_zone_getminttl(zone, &minimum_ttl); rec.rtype = (TYPE_SOA); /** @note: NATIVETYPE */ rec.rttl = htonl(soa->ttl); rec.rsize = htons(soa->rdata_size); output_stream_write(os, zone->origin, dnsname_len(zone->origin)); output_stream_write(os, (u8*) & rec, TCTS_SIZE); output_stream_write(os, soa->rdata_start, soa->rdata_size); zdb_zone_label_iterator_init(&iter, zone); while(zdb_zone_label_iterator_hasnext(&iter)) { #if DEBUG_SLOW_STORAGE_MS > 0 usleep(DEBUG_SLOW_STORAGE_MS * 1000); #endif fqdn_len = zdb_zone_label_iterator_nextname(&iter, fqdn); label = zdb_zone_label_iterator_next(&iter); btree_iterator_init(label->resource_record_set, &type_iter); while(btree_iterator_hasnext(&type_iter)) { btree_node* type_node = btree_iterator_next_node(&type_iter); if(type_node->hash == TYPE_SOA) { continue; } rec.rtype = ((u16)type_node->hash); /** @note: NATIVETYPE */ zdb_packed_ttlrdata* rr_sll = (zdb_packed_ttlrdata*)type_node->data; do { rec.rttl = htonl(rr_sll->ttl); rec.rsize = htons(rr_sll->rdata_size); if(FAIL(err = output_stream_write(os, fqdn, fqdn_len))) { return err; } if(FAIL(err = output_stream_write(os, (u8*) & rec, TCTS_SIZE))) { return err; } if(FAIL(err = output_stream_write(os, rr_sll->rdata_start, rr_sll->rdata_size))) { return err; } rr_sll = rr_sll->next; } while(rr_sll != NULL); } } #if ZDB_HAS_NSEC3_SUPPORT /* * NSEC3 part of the DB */ u32 origin_len = dnsname_len(zone->origin); /* * For each NSEC3PARAM struct ... * * Note that from the 'transaction' update, the dnssec zone collections have to be read without checking for the NSEC3 flag */ nsec3_zone* n3 = zone->nsec.nsec3; while(n3 != NULL) { /* * Iterate the NSEC3 nodes */ nsec3_iterator nsec3_items_iter; nsec3_iterator_init(&n3->items, &nsec3_items_iter); if(nsec3_iterator_hasnext(&nsec3_items_iter)) { nsec3_zone_item *first = nsec3_iterator_next_node(&nsec3_items_iter); nsec3_zone_item *item = first; nsec3_zone_item *next_item; u8 digest_len = NSEC3_NODE_DIGEST_SIZE(first); u32 rdata_hash_offset = NSEC3_ZONE_RDATA_SIZE(n3); u32 encoded_digest_len = BASE32HEX_ENCODED_LEN(digest_len); do { if(nsec3_iterator_hasnext(&nsec3_items_iter)) { next_item = nsec3_iterator_next_node(&nsec3_items_iter); } else { next_item = first; } /* Writes the nsec3 item, wire format, to an output stream */ u32 rdata_size = rdata_hash_offset + digest_len + 1 + item->type_bit_maps_size; if(rdata_size > RDATA_MAX_LENGTH) { return ZDB_ERROR_GENERAL; } /* FQDN */ fqdn[0] = encoded_digest_len; base32hex_lc_encode(NSEC3_NODE_DIGEST_PTR(item), digest_len, (char*)&fqdn[1]); if(FAIL(err = output_stream_write(os, fqdn, encoded_digest_len + 1))) { return err; } if(FAIL(err = output_stream_write(os, zone->origin, origin_len))) { return err; } if(FAIL(err = output_stream_write_u16(os, TYPE_NSEC3))) /** @note NATIVETYPE */ { return err; } if(FAIL(err = output_stream_write_u16(os, CLASS_IN))) /** @note NATIVECLASS */ { return err; } if(FAIL(err = output_stream_write_nu32(os, minimum_ttl))) { return err; } /* Write the data */ if(FAIL(err = output_stream_write_nu16(os, rdata_size))) { return err; } if(FAIL(err = output_stream_write_u8(os, n3->rdata[0]))) { return err; } if(FAIL(err = output_stream_write_u8(os, item->flags))) { return err; } if(FAIL(err = output_stream_write(os, &n3->rdata[2], rdata_hash_offset - 2))) { return err; } if(FAIL(err = output_stream_write(os, next_item->digest, digest_len + 1))) { return err; } if(FAIL(err = output_stream_write(os, item->type_bit_maps, item->type_bit_maps_size))) { return err; } zdb_packed_ttlrdata* rrsig = item->rrsig; while(rrsig != NULL) { output_stream_write(os, fqdn, encoded_digest_len + 1); output_stream_write(os, zone->origin, origin_len); output_stream_write_u16(os, TYPE_RRSIG); /** @note NATIVETYPE */ output_stream_write_u16(os, CLASS_IN); /** @note NATIVECLASS */ output_stream_write_nu32(os, rrsig->ttl); output_stream_write_nu16(os, rrsig->rdata_size); output_stream_write(os, rrsig->rdata_start, rrsig->rdata_size); rrsig = rrsig->next; } /* * nsec3 item written with its signatures * * Wire format * */ item = next_item; } while(next_item != first); } /* If there is a first item*/ n3 = n3-> next; } #endif rec.rtype = (TYPE_SOA); /** @note: NATIVETYPE */ rec.rttl = htonl(soa->ttl); rec.rsize = htons(soa->rdata_size); output_stream_write(os, zone->origin, dnsname_len(zone->origin)); output_stream_write(os, (u8*) & rec, TCTS_SIZE); output_stream_write(os, soa->rdata_start, soa->rdata_size); return err; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-image.c0000644000000000000000000000013214505005531021740 xustar000000000000000030 mtime=1695812441.693971461 30 atime=1695812445.799030253 30 ctime=1695812495.142736955 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-image.c0000664000374500037450000004773514505005531021722 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include "dnsdb/zdb_types.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_label.h" #include "dnsdb/zdb_record.h" #include #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif #include #include #include "dnsdb/zdb_utils.h" #include "dnscore/zone_reader.h" #include #define ZNIRDATA_TAG 0x4154414452494e5a // With this set to 1, AXFR storage on disk will be extremely slow. // Meant to debug network faster than disk speeds. // The value is expressed in ms // // Keep this to 0 except if you need it to be slow #define ZDB_ZONE_IMAGE_FLAG_FULLY_WRITTEN 1 #define IMAGE_MAGIC0 MAGIC4(0xff,'Z','O','N') #define IMAGE_MAGIC1 MAGIC4('E',13,10,26) #define CHAIN_MAGIC MAGIC4('N','S','C',3) #define END_MAGIC MAGIC4('E','N','D', 0) /* * */ struct zdb_zone_image_store_header { u32 magic0; u32 magic1; u64 epoch; u64 size; u64 estimated_wire_size; u16 version; u8 flags; u8 chains; u32 serial; u16 zclass; u8 reserved; u8 origin_size; }; struct zdb_zone_image_store_record_set { u16 type; u16 count; }; struct zdb_zone_image_store_record { u32 ttl; u16 rdata_size; u8 rdata[]; }; struct zdb_zone_image_reader_data { file_pool_file_t file; input_stream is; resource_record *unread_next; struct zdb_zone_image_store_header hdr; struct zdb_zone_image_store_record_set rrset_hdr; s8 depth; u8 fqdn_size; u8 label_len[128]; u8 fqdn[MAX_DOMAIN_LENGTH]; }; typedef struct zdb_zone_image_reader_data zdb_zone_image_reader_data; // 1: down // -1: up #define TCTS_SIZE 10 //static const u8 wild_wire[2] = {1, '*'}; static ya_result zdb_zone_image_store_record_set_innerloop(output_stream *os, zdb_packed_ttlrdata *rrset) { ya_result ret; u32 wire_size = 0; while(rrset != NULL) { if(FAIL(ret = output_stream_write_u32(os, rrset->ttl))) { return ret; } if(FAIL(ret = output_stream_write_u16(os, ZDB_PACKEDRECORD_PTR_RDATASIZE(rrset)))) { return ret; } if(FAIL(ret = output_stream_write(os, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrset), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrset)))) { return ret; } wire_size += ZDB_PACKEDRECORD_PTR_RDATASIZE(rrset); rrset = rrset->next; } return wire_size; } static ya_result zdb_zone_image_store_record_set(output_stream *os, u16 rtype, zdb_packed_ttlrdata *rrset) { ya_result ret; int count = zdb_packed_ttlrdata_count(rrset); if(count == 0) { return 0; } if(count > MAX_U16) { return ERROR; } struct zdb_zone_image_store_record_set rrset_hdr = { rtype, count }; if(FAIL(ret = output_stream_write(os, &rrset_hdr, sizeof(rrset_hdr)))) { return ret; } if(FAIL(ret = zdb_zone_image_store_record_set_innerloop(os, rrset))) { return ret; } return ret + count * TCTS_SIZE; } static ya_result zdb_zone_image_store_record_sets(output_stream *os, zdb_rr_collection rrsets) { ya_result ret; u32 wire_size = 0; btree_iterator iter; btree_iterator_init(rrsets, &iter); while(btree_iterator_hasnext(&iter)) { btree_node *rr_node = btree_iterator_next_node(&iter); u16 rtype = (u16)rr_node->hash; if(FAIL(ret = zdb_zone_image_store_record_set(os, rtype, rr_node->data))) { return ret; } wire_size += ret; } output_stream_write_u16(os, TYPE_ANY); return wire_size; } static ya_result zdb_zone_image_store_record_sets_but_SOA(output_stream *os, zdb_rr_collection rrsets) { ya_result ret; u32 wire_size = 0; btree_iterator iter; btree_iterator_init(rrsets, &iter); while(btree_iterator_hasnext(&iter)) { btree_node *rr_node = btree_iterator_next_node(&iter); u16 rtype = (u16)rr_node->hash; if(rtype == TYPE_SOA) { continue; } if(FAIL(ret = zdb_zone_image_store_record_set(os, rtype, rr_node->data))) { return ret; } wire_size += ret; } output_stream_write_u16(os, TYPE_ANY); return wire_size; } static s64 zdb_zone_image_store_label_children_recursively(output_stream *os, zdb_rr_label_set *labels, u32 name_len) { s64 ret; s64 wire_size = 0; if(!dictionary_isempty(labels)) { dictionary_iterator iter; dictionary_iterator_init(labels, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_rr_label *sub_label = *(zdb_rr_label**)dictionary_iterator_next(&iter); for(;;) { output_stream_write_u8(os, 1); output_stream_write(os, sub_label->name, sub_label->name[0] + 1); if(FAIL(ret = zdb_zone_image_store_record_sets(os, sub_label->resource_record_set))) { return ret; } wire_size += ret + name_len + sub_label->name[0]; if(FAIL(ret = zdb_zone_image_store_label_children_recursively(os, &sub_label->sub, name_len + sub_label->name[0]))) { return ret; } wire_size += ret; output_stream_write_u8(os, 255); if(sub_label->next == NULL) { break; } sub_label = sub_label->next; } } } return wire_size; } s64 zdb_zone_image_store(zdb_zone* zone, const char *filename, file_pool_t fp, mode_t mode) { struct zdb_zone_image_store_header hdr; output_stream os; ya_result ret; u32 soa_serial; u32 origin_len = dnsname_len(zone->origin); if(origin_len > 255) { return ERROR; } zdb_packed_ttlrdata* soa = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA); if(soa == NULL) { return ZDB_ERROR_GENERAL; } rr_soa_get_serial(ZDB_PACKEDRECORD_PTR_RDATAPTR(soa), ZDB_PACKEDRECORD_PTR_RDATASIZE(soa), &soa_serial); file_pool_unlink_from_pool_and_filename(fp, filename); file_pool_file_t f = file_pool_create_excl(fp, filename, mode); if(f == NULL) { return ERROR; } hdr.magic0 = IMAGE_MAGIC0; hdr.magic1 = IMAGE_MAGIC1; hdr.epoch = 0; hdr.size = 0; hdr.estimated_wire_size = 0; hdr.flags = 0; hdr.version = 0; hdr.serial = soa_serial; hdr.zclass = zdb_zone_getclass(zone); hdr.reserved = 0; hdr.origin_size = origin_len; file_pool_file_output_stream_init(&os, f); file_pool_file_output_stream_set_full_writes(&os, TRUE); if(FAIL(ret = output_stream_write(&os, &hdr, sizeof(hdr)))) { file_pool_unlink(f); output_stream_close(&os); //file_close(f); return ret; } if(FAIL(ret = output_stream_write(&os, zone->origin, origin_len))) { file_pool_unlink(f); output_stream_close(&os); //file_close(f); return ret; } // now write from the apex zdb_zone_image_store_record_set(&os, TYPE_SOA, soa); zdb_zone_image_store_record_sets_but_SOA(&os, zone->apex->resource_record_set); s64 wire_size = zdb_zone_image_store_label_children_recursively(&os, &zone->apex->sub, origin_len); #if ZDB_HAS_NSEC3_SUPPORT /* * For each NSEC3PARAM struct ... * * Note that from the 'transaction' update, the dnssec zone collections have to be read without checking for the NSEC3 flag */ nsec3_zone *n3 = zone->nsec.nsec3; while(n3 != NULL) { ++hdr.chains; /* * Iterate the NSEC3 nodes */ output_stream_write_u32(&os, CHAIN_MAGIC); output_stream_write_u8(&os, NSEC3_ZONE_ALGORITHM(n3)); output_stream_write_u8(&os, NSEC3_ZONE_FLAGS(n3)); output_stream_write_u16(&os, NSEC3_ZONE_ITERATIONS(n3)); output_stream_write_u8(&os, NSEC3_ZONE_SALT_LEN(n3)); output_stream_write(&os, NSEC3_ZONE_SALT(n3), NSEC3_ZONE_SALT_LEN(n3)); u32 common = 5 + NSEC3_ZONE_SALT_LEN(n3); nsec3_iterator nsec3_items_iter; nsec3_iterator_init(&n3->items, &nsec3_items_iter); while(nsec3_iterator_hasnext(&nsec3_items_iter)) { nsec3_zone_item *item = nsec3_iterator_next_node(&nsec3_items_iter); u8 digest_len = NSEC3_NODE_DIGEST_SIZE(item); if(FAIL(ret = output_stream_write_u8(&os, digest_len))) { break; } if(FAIL(ret = output_stream_write(&os, NSEC3_NODE_DIGEST_PTR(item), digest_len))) { break; } if(FAIL(ret = output_stream_write_u8(&os, item->flags))) { break; } if(FAIL(ret = output_stream_write_u16(&os, item->type_bit_maps_size))) { break; } if(FAIL(ret = output_stream_write(&os, item->type_bit_maps, item->type_bit_maps_size))) { break; } wire_size += common + item->type_bit_maps_size; int rrsig_count = zdb_packed_ttlrdata_count(item->rrsig); if(FAIL(ret = output_stream_write_u16(&os, rrsig_count))) { break; } if(rrsig_count > 0) { if(FAIL(ret = zdb_zone_image_store_record_set_innerloop(&os, item->rrsig))) { return ret; } wire_size += ret + TCTS_SIZE * rrsig_count; } } if(FAIL(ret)) { file_pool_unlink(f); output_stream_close(&os); //file_close(f); return ret; } n3 = n3->next; } #endif if(FAIL(ret = output_stream_write_u32(&os, END_MAGIC))) { file_pool_unlink(f); output_stream_close(&os); //file_close(f); return ret; } output_stream_flush(&os); file_pool_file_output_stream_detach(&os); size_t position; if(FAIL(ret = file_pool_tell(f, &position))) { file_pool_unlink(f); file_pool_close(f); return ret; } hdr.epoch = timeus(); hdr.size = position; hdr.estimated_wire_size = wire_size; hdr.flags |= ZDB_ZONE_IMAGE_FLAG_FULLY_WRITTEN; if(FAIL(ret = file_pool_seek(f, 0, SEEK_SET))) { file_pool_unlink(f); file_pool_close(f); return ret; } if(FAIL(ret = file_pool_write(f, &hdr, sizeof(hdr)))) { file_pool_unlink(f); file_pool_close(f); return ret; } return SUCCESS; } static ya_result zdb_zone_image_reader_read_record(zone_reader *zr, resource_record *rr) { zdb_zone_image_reader_data *data = (zdb_zone_image_reader_data*)zr->data; if(data->unread_next != NULL) { resource_record *tmp = data->unread_next; resource_record_copy(rr, tmp); data->unread_next = tmp->next; free(tmp); return SUCCESS; } ya_result ret; for(;;) { if(data->rrset_hdr.count == 0) { // next RRSET if(FAIL(ret = input_stream_read_u16(&data->is, &data->rrset_hdr.type))) { return ret; } if(data->rrset_hdr.type != TYPE_ANY) { if(FAIL(ret = input_stream_read_u16(&data->is, &data->rrset_hdr.count))) { return ret; } if(data->rrset_hdr.count == 0) { return ERROR; } // fallback on the "read record, decrement count" code } else { // done for this label data->rrset_hdr.count = 0; for(;;) { s8 up_down = 0; u8 label_len = 0; if(FAIL(ret = input_stream_read_s8(&data->is, &up_down))) { return ret; } if(up_down == 1) { // read the next label and append it to the fqdn if(FAIL(ret = input_stream_read_u8(&data->is, &label_len))) { return ret; } if(data->fqdn_size + label_len > 255) { return ERROR; } data->fqdn[data->fqdn_size] = label_len; if(FAIL(ret = input_stream_read(&data->is, &data->fqdn[data->fqdn_size + 1], label_len))) { return ret; } data->label_len[data->depth++] = label_len; data->fqdn_size += label_len; // now go back at the beginning of the function break; } else if(up_down == -1) { if(data->depth == 0) { return ERROR; } data->fqdn_size -= data->label_len[data->depth--]; // after a -1 you can get either a 1 or a -1 } else { return ERROR; } } // for up down // reached by breaking for a 1 continue; // will go back trying to read records } } // we know what type is being read // we know there is at least one to read // we know its fqdn // rr input_stream_read_s32(&data->is, &rr->ttl); rr->type = data->rrset_hdr.type; rr->class = data->hdr.zclass; memcpy(rr->name, data->fqdn, data->fqdn_size); input_stream_read_u16(&data->is, &rr->rdata_size); input_stream_read(&data->is, rr->rdata, rr->rdata_size); return SUCCESS; } // for loop } static ya_result zdb_zone_image_reader_unread_record(zone_reader *zr, resource_record *rr) { zdb_zone_image_reader_data *data = (zdb_zone_image_reader_data*)zr->data; resource_record *clone; MALLOC_OBJECT_OR_DIE(clone, resource_record, DNSRR_TAG); clone->next = data->unread_next; data->unread_next = clone; return SUCCESS; } static ya_result zdb_zone_image_reader_free_record(zone_reader *zr, resource_record *rr) { zdb_zone_image_reader_data *data = (zdb_zone_image_reader_data*)zr->data; (void)zr; (void)rr; (void)data; return SUCCESS; } static void zdb_zone_image_reader_close(zone_reader *zr) { zdb_zone_image_reader_data *data = (zdb_zone_image_reader_data*)zr->data; resource_record *rr = data->unread_next; while(rr != NULL) { resource_record *tmp = rr; rr = rr->next; free(tmp); } data->unread_next = NULL; input_stream_close(&data->is); data->file = NULL; ZFREE_OBJECT(data); } static void zdb_zone_image_reader_handle_error(zone_reader *zr, ya_result error_code) // used for cleaning up after an error (AXFR feedback) { zdb_zone_image_reader_data *data = (zdb_zone_image_reader_data*)zr->data; (void)data; (void)error_code; } static const char* zdb_zone_image_reader_get_last_error_message(zone_reader *zr) { zdb_zone_image_reader_data *data = (zdb_zone_image_reader_data*)zr->data; (void)data; return "?"; } static bool zdb_zone_image_reader_canwriteback(zone_reader *zr) { (void)zr; return FALSE; } static const zone_reader_vtbl zdb_zone_image_reader_vtbl = { zdb_zone_image_reader_read_record, zdb_zone_image_reader_unread_record, zdb_zone_image_reader_free_record, zdb_zone_image_reader_close, zdb_zone_image_reader_handle_error, zdb_zone_image_reader_canwriteback, zdb_zone_image_reader_get_last_error_message, "zdb_zone_image_reader" }; ya_result zdb_zone_image_reader_open(zone_reader *zr, const char *filename, file_pool_t fp) { file_pool_file_t f = file_pool_open(fp, filename); ya_result ret; if(f == NULL) { return ERROR; } zdb_zone_image_reader_data *data; ZALLOC_OBJECT_OR_DIE(data, zdb_zone_image_reader_data, ZNIRDATA_TAG); data->file = f; file_pool_file_input_stream_init(&data->is, f); file_pool_file_input_stream_set_full_reads(&data->is, TRUE); data->unread_next = NULL; if(FAIL(ret = input_stream_read(&data->is, &data->hdr, sizeof(data->hdr)))) { file_pool_close(f); ZFREE_OBJECT(data); return ret; } if((data->hdr.magic0 != IMAGE_MAGIC0) || (data->hdr.magic0 != IMAGE_MAGIC1)) { file_pool_close(f); ZFREE_OBJECT(data); return ret; } if(FAIL(ret = input_stream_read(&data->is, data->fqdn, data->hdr.origin_size))) { file_pool_close(f); ZFREE_OBJECT(data); return ret; } data->fqdn_size = data->hdr.origin_size; data->rrset_hdr.type = 0; data->rrset_hdr.count = 0; zr->data = data; zr->vtbl = &zdb_zone_image_reader_vtbl; return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_zone_write_text.c0000644000000000000000000000013114505005531023217 xustar000000000000000029 mtime=1695812441.73997212 30 atime=1695812445.802030296 30 ctime=1695812495.144736983 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_zone_write_text.c0000664000374500037450000006550514505005531023175 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dnsdb/zdb_zone_write.h" #include "dnsdb/zdb_error.h" #include "dnsdb/zdb_zone_label_iterator.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_zone.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define ZDB_ZONE_WRITE_TEXT_USE_TTL_VAR 1 #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif #define OUTPUT_BUFFER_SIZE 4096 #define DEFAULT_TTL 86400 #define FILE_RIGHTS 0644 #define TAB_SIZE 8 #define TTL_SIZE 8 #define INDENT_SPACES 40 #define INDENT_TABS (INDENT_SPACES/TAB_SIZE) // escapes '@' and '$' symbols of fqdn in rdata #define ZDB_ZONE_WRITE_TEXT_FILE_ESCAPE_RDATA 1 /* * 0 1 * 1 1 * 2 1 * 3 1 * 4 2 */ static const char __TAB__[1] = {'\t'}; #if !DEBUG static const char __LF__[1] = {'\n'}; #endif static const char __ESCAPE__[1] = {'\\'}; static u32 zdb_zone_write_text_output_stream_write_escaped(output_stream *os, const char *str, u32 len) { u32 additional_len = 0; for(u32 i = 0; i < len; ++i) { switch(str[i]) { case '@': case '$': case '\r': case '\n': case '\t': case '\\': ++additional_len; output_stream_write(os, __ESCAPE__, 1); FALLTHROUGH // fall through default: output_stream_write(os, &str[i], 1); } } return len + additional_len; } static void zdb_zone_write_text_fqdn_print(output_stream *os, char *str, u32 len, s32 tabs) { if(str != NULL) { #if 1 // handle escapes #if _GNU_SOURCE char *str_limit = &str[len]; *str_limit = '@'; char *chrpos = rawmemchr(str, '@'); if(chrpos == str_limit) // not found { *str_limit = '$'; chrpos = rawmemchr(str, '$'); if(chrpos == str_limit) // not found { output_stream_write(os, (u8*)str, len); } else { // write escaped len = zdb_zone_write_text_output_stream_write_escaped(os, str, len); } } else { // write escaped len = zdb_zone_write_text_output_stream_write_escaped(os, str, len); } #else char *chrpos = memchr(str, '@', len); if(chrpos == NULL) // not found { chrpos = memchr(str, '$', len); if(chrpos == NULL) // not found { output_stream_write(os, (u8*)str, len); } else { // write escaped len = zdb_zone_write_text_output_stream_write_escaped(os, str, len); } } else { // write escaped len = zdb_zone_write_text_output_stream_write_escaped(os, str, len); } #endif #else // do not handle escapes output_stream_write(os, (u8*)str, len); #endif } tabs -= (len / TAB_SIZE) + 1; while(tabs-- > 0) { output_stream_write(os, (u8*)__TAB__, 1); } } #if DEBUG static void zdb_zone_write_text_rr_label_flags_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u32 flags = *((u16*)value); if((flags & ZDB_RR_LABEL_APEX) != 0) { output_stream_write(os, "A", 1); } #if ZDB_HAS_NSEC_SUPPORT if((flags & ZDB_RR_LABEL_NSEC) != 0) { output_stream_write(os, "1", 1); } #endif #if ZDB_HAS_NSEC3_SUPPORT if((flags & ZDB_RR_LABEL_NSEC3) != 0) { output_stream_write(os, "3", 1); } if((flags & ZDB_RR_LABEL_NSEC3_OPTOUT) != 0) { output_stream_write(os, "O", 1); } #endif if((flags & ZDB_RR_LABEL_GOT_WILD) != 0) { output_stream_write(os, "*", 1); } if((flags & ZDB_RR_LABEL_DELEGATION) != 0) { output_stream_write(os, "D", 1); } if((flags & ZDB_RR_LABEL_UNDERDELEGATION) != 0) { output_stream_write(os, "d", 1); } if((flags & ZDB_RR_LABEL_HASCNAME) != 0) { output_stream_write(os, "C", 1); } if((flags & ZDB_RR_LABEL_DROPCNAME) != 0) { output_stream_write(os, "c", 1); } if((flags & ZDB_RR_LABEL_N3COVERED) != 0) { output_stream_write(os, "S", 1); } if((flags & ZDB_RR_LABEL_N3OCOVERED) != 0) { output_stream_write(os, "s", 1); } } #endif ya_result zdb_zone_write_text_ex(zdb_zone *zone, output_stream *fos, bool force_label, bool allow_shutdown) { ya_result ret; s32 current_ttl = DEFAULT_TTL; #if ZDB_HAS_NSEC3_SUPPORT s32 soa_nttl = zone->min_ttl; #endif u32 label_len; u32 origin_len; #if ZDB_HAS_NSEC3_SUPPORT u32 dot_origin_len; #endif u32 stored_serial = 0; if((zone == NULL) || (fos == NULL)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } yassert(zdb_zone_islocked_weak(zone)); s64 wire_size = 0; #if DEBUG format_writer status_flags_fw = {zdb_zone_write_text_rr_label_flags_format, NULL}; osprintln(fos, "; A=apex 1=NSEC 3=NSEC3 O=NSEC3-OPTOUT *=wildcard present D=at-delegation d=under-delegation C=has-CNAME c=no-CNAME-allowed S=NSEC3-covered s=NSEC3-optout-covered"); #endif char label_cstr[2 + MAX_DOMAIN_LENGTH + 1]; origin_len = dnsname_len(zone->origin); { zdb_packed_ttlrdata* soa_ttlrdata = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA); if(soa_ttlrdata != NULL) { current_ttl = soa_ttlrdata->ttl; rr_soa_get_serial(ZDB_PACKEDRECORD_PTR_RDATAPTR(soa_ttlrdata), ZDB_PACKEDRECORD_PTR_RDATASIZE(soa_ttlrdata), &stored_serial); } else { log_err("%{dnsname}: no SOA record found at apex.", zone->origin); } } #if ZDB_HAS_NSEC3_SUPPORT char dot_origin[1 + MAX_DOMAIN_LENGTH + 1]; dot_origin[0] = '.'; dot_origin_len = dnsname_to_cstr(&dot_origin[1], zone->origin) + 1; #endif osformat(fos, "$ORIGIN %{dnsname}\n", zone->origin); #if ZDB_ZONE_WRITE_TEXT_USE_TTL_VAR osformat(fos, "$TTL %u\n", current_ttl); #endif zdb_zone_label_iterator iter; btree_iterator records_iter; checked_output_stream_data_t chkosd; output_stream chkos; checked_output_stream_init(&chkos, fos, &chkosd); fos = &chkos; zdb_zone_label_iterator_init(&iter, zone); /* * Save each label, and its records. */ while(zdb_zone_label_iterator_hasnext(&iter)) { if(checked_output_stream_failed(fos)) { return checked_output_stream_error(fos); } u32 len = zdb_zone_label_iterator_nextname_to_cstr(&iter, label_cstr); if(len != dot_origin_len) { u32 n = len - origin_len; label_cstr[n] = '\0'; label_len = n; if((n > 0) && (label_cstr[n - 1] == '.')) { label_cstr[n - 1] = '\0'; label_len--; } } else { label_len = dnsname_to_cstr(label_cstr, zone->origin); } zdb_rr_label* label = zdb_zone_label_iterator_next(&iter); #if DEBUG if(zdb_rr_label_flag_isset(label, (ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT))) { nsec3_label_extension *n3e = label->nsec.nsec3; while(n3e != NULL) { osformat(fos, ";; NSEC3:"); if(n3e->_self != NULL) { osformat(fos, " SELF: %{digest32h}", n3e->_self->digest); } else { osformat(fos, " SELF: ERROR"); } if(n3e->_star != NULL) { osformat(fos, " STAR: %{digest32h}", n3e->_star->digest); } else { osformat(fos, " STAR: ERROR"); } osprintln(fos, ""); n3e = n3e->_next; } } else if(zdb_rr_label_flag_isset(label, ZDB_RR_LABEL_NSEC)) { osformat(fos, ";; NSEC:"); nsec_node *nsec = label->nsec.nsec.node; if(nsec != NULL) { osformat(fos, " SELF: %{dnsname}", nsec->inverse_relative_name); } else { osformat(fos, " SELF: ERROR"); } osprintln(fos, ""); } #endif // DEBUG bool print_label = TRUE; zdb_packed_ttlrdata* soa_ttlrdata = zdb_record_find(&label->resource_record_set, TYPE_SOA); if(soa_ttlrdata != NULL) { wire_size += origin_len + label_len + 10 + ZDB_PACKEDRECORD_PTR_RDATASIZE(soa_ttlrdata); if(print_label) { zdb_zone_write_text_fqdn_print(fos, label_cstr, label_len, INDENT_TABS); u16 zclass = zdb_zone_getclass(zone); osformat(fos, "\t%{dnsclass}%tSOA%t", &zclass, (TTL_SIZE/TAB_SIZE) + 1, TTL_SIZE/TAB_SIZE); } else { zdb_zone_write_text_fqdn_print(fos, NULL, 0, INDENT_TABS); } #if !ZDB_ZONE_WRITE_TEXT_FILE_ESCAPE_RDATA ret = osprint_rdata(fos, TYPE_SOA, ZDB_PACKEDRECORD_PTR_RDATAPTR(soa_ttlrdata), ZDB_PACKEDRECORD_PTR_RDATASIZE(soa_ttlrdata)); #else ret = osprint_rdata_escaped(fos, TYPE_SOA, ZDB_PACKEDRECORD_PTR_RDATAPTR(soa_ttlrdata), ZDB_PACKEDRECORD_PTR_RDATASIZE(soa_ttlrdata)); #endif #if DEBUG status_flags_fw.value = &label->_flags; osformatln(fos, " ; flags=%w (label@%p)", &status_flags_fw, label); #else output_stream_write(fos, (const u8*)__LF__, 1); #endif if(FAIL(ret)) { osprintln(fos, ";; ABOVE RECORD IS CORRUPTED"); } print_label = force_label; } if(allow_shutdown && dnscore_shuttingdown()) { output_stream_close(fos); return STOPPED_BY_APPLICATION_SHUTDOWN; } btree_iterator_init(label->resource_record_set, &records_iter); while(btree_iterator_hasnext(&records_iter)) { btree_node* node = btree_iterator_next_node(&records_iter); u16 type = (u16)node->hash; if(type == TYPE_SOA) { continue; } zdb_packed_ttlrdata* ttlrdata_sll = (zdb_packed_ttlrdata*)node->data; s32 rrset_ttl; while(ttlrdata_sll != NULL) { wire_size += origin_len + label_len + 10 + ZDB_PACKEDRECORD_PTR_RDATASIZE(ttlrdata_sll); if(print_label) { zdb_zone_write_text_fqdn_print(fos, label_cstr, label_len, INDENT_TABS); } else { zdb_zone_write_text_fqdn_print(fos, NULL, 0, INDENT_TABS); } if(type != TYPE_RRSIG) { rrset_ttl = ttlrdata_sll->ttl; } else { rrset_ttl = rrsig_get_original_ttl_from_rdata(ZDB_PACKEDRECORD_PTR_RDATAPTR(ttlrdata_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(ttlrdata_sll)); } if(current_ttl != rrset_ttl) { #if !ZDB_ZONE_WRITE_TEXT_FILE_ESCAPE_RDATA current_ttl = rrset_ttl; #endif osformat(fos, "\t%-" TOSTRING(TTL_SIZE) "u\t", rrset_ttl); } else { osformat(fos, "%t", 1 + (TTL_SIZE/TAB_SIZE) + 1); } osformat(fos, "%{dnstype}%t", &type, (TTL_SIZE/TAB_SIZE)); #if !ZDB_ZONE_WRITE_TEXT_FILE_ESCAPE_RDATA ret = osprint_rdata(fos, type, ZDB_PACKEDRECORD_PTR_RDATAPTR(ttlrdata_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(ttlrdata_sll)); #else ret = osprint_rdata_escaped(fos, type, ZDB_PACKEDRECORD_PTR_RDATAPTR(ttlrdata_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(ttlrdata_sll)); #endif if(type == TYPE_DNSKEY) { u16 tag = dnskey_get_tag_from_rdata(ZDB_PACKEDRECORD_PTR_RDATAPTR(ttlrdata_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(ttlrdata_sll)); osformat(fos, " ; tag = %05u", tag); } #if DEBUG status_flags_fw.value = &label->_flags; osformatln(fos, " ; flags=%w (label@%p)", &status_flags_fw, label); #else output_stream_write(fos, (const u8*)__LF__, 1); #endif if(FAIL(ret)) { osprintln(fos, ";; ABOVE RECORD IS CORRUPTED"); } print_label = force_label; ttlrdata_sll = ttlrdata_sll->next; } } #if DEBUG if(btree_isempty(label->resource_record_set)) { osprint(fos, ";; "); output_stream_write(fos, label_cstr, label_len); status_flags_fw.value = &label->_flags; if(label->sub.count == 0) { osformatln(fos, " is empty terminal ; flags=%w (label@%p)", &status_flags_fw, label); } else { osformatln(fos, " is empty non-terminal ; flags=%w (label@%p)", &status_flags_fw, label); } } #endif } #if ZDB_HAS_NSEC3_SUPPORT /* * If the zone is NSEC3, print the nsec3 data */ const nsec3_zone* n3 = zone->nsec.nsec3; while(n3 != NULL) { u8 rdata[TYPE_BIT_MAPS_MAX_RDATA_SIZE]; if(checked_output_stream_failed(fos)) { return checked_output_stream_error(fos); } u32 rdata_hash_offset = NSEC3_ZONE_RDATA_SIZE(n3); MEMCOPY(rdata, &n3->rdata[0], NSEC3_ZONE_RDATA_SIZE(n3)); nsec3_iterator nsec3_items_iter; nsec3_iterator_init(&n3->items, &nsec3_items_iter); if(nsec3_iterator_hasnext(&nsec3_items_iter)) { nsec3_zone_item* first = nsec3_iterator_next_node(&nsec3_items_iter); nsec3_zone_item* item = first; nsec3_zone_item* next_item; u8 digest_len = NSEC3_NODE_DIGEST_SIZE(first); do { if(allow_shutdown && dnscore_shuttingdown()) { output_stream_close(fos); return STOPPED_BY_APPLICATION_SHUTDOWN; } if(nsec3_iterator_hasnext(&nsec3_items_iter)) { next_item = nsec3_iterator_next_node(&nsec3_items_iter); } else { next_item = first; } rdata[1] = item->flags; #if DEBUG if(nsec3_owner_count(item) == 1) { if(nsec3_owner_count(item) != 0) { if(item->label.owner->name[0] != 0) { osformatln(fos, ";; Owner: %{dnslabel}", item->label.owner->name); } else { osformatln(fos, ";; Owner: %{dnslabel} (the apex)", zone->origin); } } else { osprintln(fos, ";; Owner: ERROR : RC=0"); } } else { if(nsec3_owner_count(item) > 0) { s32 i = nsec3_owner_count(item) - 1; do { if(item->label.owners[i]->name[0] != 0) { osformatln(fos, ";; Owner: %{dnslabel}", item->label.owners[i]->name); } else { osformatln(fos, ";; Owner: %{dnslabel} (the apex)", zone->origin); } } while(i-- > 0); } else { osprintln(fos, ";; NO OWNER"); } } if(item->sc <= 1) { if(item->sc != 0) { if(item->star_label.owner->name[0] != 0) { osformatln(fos, ";; Star: %{dnslabel}", item->star_label.owner->name); } else { osformatln(fos, ";; Star: %{dnslabel} (the apex)", zone->origin); } } } else { s32 i = item->sc - 1; do { if(item->star_label.owners[i]->name[0] != 0) { osformatln(fos, ";; Star: %{dnslabel}", item->star_label.owners[i]->name); } else { osformatln(fos, ";; Star: %{dnslabel} (the apex)", zone->origin); } } while(i-- > 0); } #endif u32 rdata_size = rdata_hash_offset; MEMCOPY(&rdata[rdata_size], next_item->digest, digest_len + 1); rdata_size += digest_len + 1; MEMCOPY(&rdata[rdata_size], item->type_bit_maps, item->type_bit_maps_size); rdata_size += item->type_bit_maps_size; ya_result hex32_len; if(FAIL(hex32_len = output_stream_write_base32hex(fos, NSEC3_NODE_DIGEST_PTR(item), digest_len))) { return hex32_len; } wire_size += origin_len + hex32_len + 10 + rdata_size; output_stream_write(fos, (const u8*)dot_origin, dot_origin_len); output_stream_write_u8(fos, (u8)'\t'); osformat(fos, "%-" TOSTRING(TTL_SIZE) "u\tNSEC3\t", soa_nttl); osprint_rdata(fos, TYPE_NSEC3, rdata, rdata_size); osprintln(fos, ""); zdb_packed_ttlrdata* rrsig = item->rrsig; while(rrsig != NULL) { u32 tabs = ((hex32_len+ dot_origin_len) / TAB_SIZE) + 1; s32 rrsig_ttl = rrsig_get_original_ttl_from_rdata(ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig)); wire_size += origin_len + hex32_len + 10 + ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig); #if ZDB_ZONE_WRITE_TEXT_FILE_ESCAPE_RDATA if(rrsig_ttl != current_ttl) { osformat(fos, "%t%-" TOSTRING(TTL_SIZE) "u\tRRSIG\t", tabs, rrsig_ttl); } else { tabs += (TTL_SIZE/TAB_SIZE) + 1; osformat(fos, "%tRRSIG\t", tabs); /* ${} requires a pointer to the data */ } #else if(rrsig_ttl != soa_nttl) { osformat(fos, "%t%-" TOSTRING(TTL_SIZE) "u\tRRSIG\t", tabs, rrsig_ttl); } else { tabs += (TTL_SIZE/TAB_SIZE) + 1; osformat(fos, "%tRRSIG\t", tabs); /* ${} requires a pointer to the data */ } #endif #if !ZDB_ZONE_WRITE_TEXT_FILE_ESCAPE_RDATA osprint_rdata(fos, TYPE_RRSIG, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig)); #else osprint_rdata_escaped(fos, TYPE_RRSIG, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig)); #endif osprintln(fos, ""); rrsig = rrsig->next; } item = next_item; } while(next_item != first); } /* If there is a first item*/ n3 = n3->next; } /* while n3 != NULL */ #endif if(checked_output_stream_failed(fos)) { return checked_output_stream_error(fos); } zone->text_serial = stored_serial; zone->wire_size = wire_size; return SUCCESS; } /* * Without buffering: * * zdb_zone_write_text: 1245933248000 -> 1245933499739 (251739) * * With buffering: * * zdb_zone_write_text: 1245933590000 -> 1245933597877 (7877) * */ /** * * Zone MUST be locked * Note that the one caller locks the zone. * * @param zone * @param output_file * @param force_label * @return */ /** * * Zone MUST be locked * Note that the one caller locks the zone. * * @param zone * @param output_file * @param force_label * @return */ ya_result zdb_zone_write_text_file(zdb_zone* zone, const char* output_file, u8 flags) { output_stream fos; ya_result ret; random_ctx rnd = thread_pool_get_random_ctx(); if(rnd == NULL) { thread_pool_setup_random_ctx(); rnd = thread_pool_get_random_ctx(); } bool force_label = flags & ZDB_ZONE_WRITE_TEXT_FILE_FORCE_LABEL; bool allow_shutdown = flags & ZDB_ZONE_WRITE_TEXT_FILE_IGNORE_SHUTDOWN; char tmp[PATH_MAX]; size_t output_file_len = strlen(output_file); if(output_file_len >= PATH_MAX) { return ERROR; } if(PATH_MAX - output_file_len >= 8) { do { u32 rndval = random_next(rnd); if(FAIL(ret = snformat(tmp, sizeof(tmp), "%s%08x", output_file, rndval))) { return ret; } } while(file_exists(tmp) && !dnscore_shuttingdown()); } else if(PATH_MAX - output_file_len >= 4) { do { u32 rndval = random_next(rnd); #if DEBUG ret = #endif snformat(tmp, sizeof(tmp), "%s%04x", output_file, rndval & 0xffffU); #if DEBUG yassert(ISOK(ret)); #endif } while(file_exists(tmp) && !dnscore_shuttingdown()); } else { log_warn("%{dnsname}: path '%s' is too long to allow temporary random suffix, shutdown not allowed while saving the file", zone->origin, output_file); allow_shutdown = FALSE; } if(ISOK(ret = file_output_stream_create(&fos, tmp, FILE_RIGHTS))) { if(ISOK(ret = buffer_output_stream_init(&fos, &fos, OUTPUT_BUFFER_SIZE))) { ret = zdb_zone_write_text_ex(zone, &fos, force_label, allow_shutdown); output_stream_close(&fos); if(ISOK(ret)) // zone is locked { if(file_is_link(output_file) > 0) { if(unlink(output_file) < 0) { log_warn("%{dnsname}: could not delete symbolic link '%s': %r", zone->origin, output_file, ERRNO_ERROR); } } if(rename(tmp, output_file) >= 0) { log_info("%{dnsname}: saved as '%s'", zone->origin, output_file); zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_MODIFIED); return SUCCESS; } else { log_err("%{dnsname}: could not move temporary file '%s' to overwrite '%s': %r", zone->origin, tmp, output_file, ERRNO_ERROR); return ERROR; } } else { log_warn("%{dnsname}: could not write '%s', cleaning up: %r", zone->origin, tmp, ret); unlink(tmp); } } else { log_warn("%{dnsname}: could not bufferize '%s', cleaning up: %r", zone->origin, tmp, ret); output_stream_close(&fos); unlink(tmp); } } else { log_err("%{dnsname}: could not create '%s': %r", zone->origin, tmp, ret); } return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb_zone_write_unbound.c0000644000000000000000000000013214505005531023706 xustar000000000000000030 mtime=1695812441.752972306 30 atime=1695812445.802030296 30 ctime=1695812495.146737012 yadifa-2.6.5-11201/lib/dnsdb/src/zdb_zone_write_unbound.c0000664000374500037450000002036414505005531023655 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbzone Zone related functions * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #include #include "dnsdb/zdb_error.h" #include "dnsdb/zdb_zone_label_iterator.h" #include "dnsdb/zdb_zone_write.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_zone.h" #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #include "dnsdb/dnsrdata.h" #endif /* * Without buffering: * * zdb_write_zone_text: 1245933248000 -> 1245933499739 (251739) * * With buffering: * * zdb_write_zone_text: 1245933590000 -> 1245933597877 (7877) * */ ya_result zdb_zone_write_unbound(const zdb_zone* zone, const char* output_file) { output_stream bos; output_stream fos; ya_result ret; if(FAIL(ret = file_output_stream_create(&fos, output_file, 0644))) { return ret; } if(FAIL(ret = buffer_output_stream_init(&bos, &fos, 4096))) { return ret; } char label_cstr[MAX_DOMAIN_LENGTH]; osformat(&bos, "local-zone: \"%{dnsname}\" static\n", zone->origin); zdb_packed_ttlrdata* soa_ttlrdata = NULL; zdb_zone_label_iterator iter; btree_iterator records_iter; zdb_zone_label_iterator_init(&iter, zone); /* * Save each label, and its records. */ while(zdb_zone_label_iterator_hasnext(&iter)) { zdb_zone_label_iterator_nextname_to_cstr(&iter, label_cstr); zdb_rr_label* label = zdb_zone_label_iterator_next(&iter); soa_ttlrdata = zdb_record_find(&label->resource_record_set, TYPE_SOA); if(soa_ttlrdata != NULL) { u16 zclass = zdb_zone_getclass(zone); osformat(&bos, "local-data: \"%s %u %{dnsclass} SOA ", label_cstr, soa_ttlrdata->ttl, &zclass); ret = osprint_rdata(&bos, TYPE_SOA, ZDB_PACKEDRECORD_PTR_RDATAPTR(soa_ttlrdata), ZDB_PACKEDRECORD_PTR_RDATASIZE(soa_ttlrdata)); osprintln(&bos, "\""); if(FAIL(ret)) { osprintln(&bos, ";; ABOVE RECORD IS CORRUPTED"); } } btree_iterator_init(label->resource_record_set, &records_iter); while(btree_iterator_hasnext(&records_iter)) { btree_node* node = btree_iterator_next_node(&records_iter); u16 type = (u16)node->hash; if(type == TYPE_SOA) { continue; } zdb_packed_ttlrdata* ttlrdata_sll = (zdb_packed_ttlrdata*)node->data; while(ttlrdata_sll != NULL) { osformat(&bos, "local-data: \"%s %u %{dnstype} ", label_cstr, ttlrdata_sll->ttl, &type); ret = osprint_rdata(&bos, type, ZDB_PACKEDRECORD_PTR_RDATAPTR(ttlrdata_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(ttlrdata_sll)); osprintln(&bos, "\""); if(FAIL(ret)) { osprintln(&bos, ";; ABOVE RECORD IS CORRUPTED"); } ttlrdata_sll = ttlrdata_sll->next; } } } if(soa_ttlrdata == NULL) { return ZDB_ERROR_NOSOAATAPEX; } #if ZDB_HAS_NSEC3_SUPPORT /* * If the zone is NSEC3, print the nsec3 data */ if(zdb_record_find(&zone->apex->resource_record_set, TYPE_NSEC3PARAM) != NULL) { soa_rdata soa; zdb_record_getsoa(soa_ttlrdata, &soa); nsec3_zone* n3 = zone->nsec.nsec3; while(n3 != NULL) { u8 rdata[TYPE_BIT_MAPS_MAX_RDATA_SIZE]; u32 rdata_hash_offset = NSEC3_ZONE_RDATA_SIZE(n3); MEMCOPY(rdata, &n3->rdata[0], NSEC3_ZONE_RDATA_SIZE(n3)); nsec3_iterator nsec3_items_iter; nsec3_iterator_init(&n3->items, &nsec3_items_iter); if(nsec3_iterator_hasnext(&nsec3_items_iter)) { nsec3_zone_item* first = nsec3_iterator_next_node(&nsec3_items_iter); nsec3_zone_item* item = first; nsec3_zone_item* next_item; u8 digest_len = NSEC3_NODE_DIGEST_SIZE(first); do { if(nsec3_iterator_hasnext(&nsec3_items_iter)) { next_item = nsec3_iterator_next_node(&nsec3_items_iter); } else { next_item = first; } rdata[1] = item->flags; u32 rdata_size = rdata_hash_offset; MEMCOPY(&rdata[rdata_size], next_item->digest, digest_len + 1); rdata_size += digest_len + 1; MEMCOPY(&rdata[rdata_size], item->type_bit_maps, item->type_bit_maps_size); rdata_size += item->type_bit_maps_size; osprint(&bos, "local-data: \""); if(FAIL(ret = output_stream_write_base32hex(&bos, NSEC3_NODE_DIGEST_PTR(item), digest_len))) { return ret; } osformat(&bos, ".%{dnsname} %u NSEC3 ", zone->origin, soa.minimum); osprint_rdata(&bos, TYPE_NSEC3, rdata, rdata_size); osprintln(&bos, "\""); zdb_packed_ttlrdata* rrsig = item->rrsig; while(rrsig != NULL) { /*osformatln(&bos, ";; rrsig@%p", rrsig);*/ u16 type = TYPE_RRSIG; osformat(&bos, "local-data: \"%{dnsname} %u %{dnstype} ", zone->origin, rrsig->ttl, &type); /* ${} requires a pointer to the data */ osprint_rdata(&bos, type, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig)); osprintln(&bos, "\""); rrsig = rrsig->next; } item = next_item; } while(next_item != first); } /* If there is a first item*/ n3 = n3->next; } /* while n3 != NULL */ } #endif /* The filter closes the filtered */ output_stream_close(&bos); return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dynupdate_check_prerequisites.c0000644000000000000000000000013214505005531025246 xustar000000000000000030 mtime=1695812441.701971575 30 atime=1695812445.800030268 30 ctime=1695812495.149737055 yadifa-2.6.5-11201/lib/dnsdb/src/dynupdate_check_prerequisites.c0000664000374500037450000002545514505005531025223 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbupdate Dynamic update functions * @ingroup dnsdb * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include "dnsdb/dynupdate.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_zone.h" /* * */ #define ZDB_DYNUPDATE_TAG 0x1111111111111111 typedef struct name_type_rdata name_type_rdata; struct name_type_rdata { u8* rname; u8* rdata; u16 rtype; u16 rdata_size; }; static int name_type_rdata_compare(const void* a, const void* b) { int cmp; name_type_rdata* ia = (name_type_rdata*)a; name_type_rdata* ib = (name_type_rdata*)b; /* strcmp is adequate for this test */ if((cmp = strcmp((char*)ia->rname, (char*)ib->rname)) != 0) { return cmp; } cmp = ia->rtype; cmp -= ib->rtype; return cmp; } static void name_type_rdata_free(void* a) { free(a); } static void free_rrsets(ptr_vector* rrsetsp) { ptr_vector_callback_and_clear(rrsetsp, name_type_rdata_free); ptr_vector_destroy(rrsetsp); } /* * Input stream here is not a good idea because * * A) Like Gery said, the buffer is 64K max. * B) Using an input stream would require me to copy & allocate memory, * this way only requires it for the last case, and only a "token", * never a string. */ ya_result dynupdate_check_prerequisites(zdb_zone* zone, packet_unpack_reader_data *reader, u16 count) { if(zdb_zone_invalid(zone)) { return ZDB_ERROR_ZONE_INVALID; } if(count == 0) { return SUCCESS; } dnsname_vector *origin_path; dnsname_vector name_path; ptr_vector rrsets; u8* rname; u8* rdata; u32 rname_size; u16 rtype; u16 rclass; u16 rdata_size; u8 wire[MAX_DOMAIN_LENGTH + 10 + 65536]; origin_path = &zone->origin_vector; ptr_vector_init(&rrsets); while(count-- > 0) { ya_result return_value; if(FAIL(return_value = packet_reader_read_record(reader, wire, sizeof(wire)))) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_FORMERR); } rname = wire; rname_size = dnsname_len(wire); rtype = GET_U16_AT(wire[rname_size]); rclass = GET_U16_AT(wire[rname_size + 2]); rdata_size = ntohs(GET_U16_AT(wire[rname_size + 8])); rdata = &wire[rname_size + 10]; dnsname_to_dnsname_vector(rname, &name_path); s32 idx; for(idx = 0; idx < origin_path->size; idx++) { if(!dnslabel_equals(origin_path->labels[origin_path->size - idx], name_path.labels[name_path.size - idx])) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_NOTZONE); } } if(rclass == CLASS_ANY) { if(rdata_size != 0) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_FORMERR); } zdb_rr_label* label = zdb_rr_label_find_exact(zone->apex, name_path.labels, (name_path.size - origin_path->size) - 1); if(rtype == TYPE_ANY) { if(label == NULL) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_NXDOMAIN); } } else { if(label == NULL) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_NXRRSET); } if(zdb_record_find(&label->resource_record_set, rtype) == NULL) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_NXRRSET); } } } else if(rclass == CLASS_NONE) { if(rdata_size != 0) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_FORMERR); } zdb_rr_label* label = zdb_rr_label_find_exact(zone->apex, name_path.labels, (name_path.size - origin_path->size) - 1); if(rtype == TYPE_ANY) { if(label != NULL) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_YXDOMAIN); } } else { if(label != NULL) { if(zdb_record_find(&label->resource_record_set, rtype) != NULL) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_YXRRSET); } } // else label is NULL } } else if(rclass == zdb_zone_getclass(zone)) { name_type_rdata* item; MALLOC_OBJECT_OR_DIE(item, name_type_rdata, ZDB_DYNUPDATE_TAG); item->rname = rname; item->rdata = rdata; item->rtype = rtype; item->rdata_size = rdata_size; ptr_vector_append(&rrsets, item); } else { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_FORMERR); } } ptr_vector_qsort(&rrsets, name_type_rdata_compare); /* * Get the first name. * While the next records have this name ... * Get the first type * while the next records have this type ... * Test that the record has a match * Decrement the match count (dual record queries are an error) * */ if(ptr_vector_size(&rrsets) > 0) { zdb_rr_label* label = NULL; zdb_packed_ttlrdata* rr_sll = NULL; u8* last_name = (u8*)"\0377"; u16 last_type = 0; s32 required_matches = 0; name_type_rdata** itemp; s32 record_count = ptr_vector_last_index(&rrsets); // record_count >= 0 itemp = (name_type_rdata**)rrsets.data; while(record_count-- >= 0) { name_type_rdata* item = *itemp++; if(!dnsname_equals(item->rname, last_name)) { if(required_matches != 0) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_NXRRSET); } last_name = item->rname; /* * It's a new name: get the rr_label */ dnsname_to_dnsname_vector(item->rname, &name_path); label = zdb_rr_label_find_exact(zone->apex, name_path.labels, (name_path.size - origin_path->size) - 1); if(label == NULL) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_NXRRSET); } last_type = 0; // forces the next test } if(last_type != item->rtype) { if(required_matches != 0) { free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_NXRRSET); } last_type = item->rtype; /* * get the type's rr list * compute the size of the list */ if(label != NULL) { rr_sll = zdb_record_find(&label->resource_record_set, last_type); } else { rr_sll = NULL; } required_matches = 0; zdb_packed_ttlrdata* rr = rr_sll; while(rr != NULL) { required_matches++; rr = rr->next; } } /* * check that the rdata exists * * if not: break * * if yes: decrement the counter */ zdb_packed_ttlrdata* rr = rr_sll; while(rr != NULL) { if(rr->rdata_size == item->rdata_size) { /* * the records are read canonised to lower-case */ if(memcmp(&rr->rdata_start[0], item->rdata, item->rdata_size) == 0) { /* * match */ required_matches--; break; } } rr = rr->next; } if(rr == NULL) { /* * no match */ free_rrsets(&rrsets); return RCODE_ERROR_CODE(RCODE_NXRRSET); } } } free_rrsets(&rrsets); return reader->offset; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dynupdate-diff.c0000644000000000000000000000013114505005531022032 xustar000000000000000029 mtime=1695812441.74697222 30 atime=1695812445.802030296 30 ctime=1695812495.151737083 yadifa-2.6.5-11201/lib/dnsdb/src/dynupdate-diff.c0000664000374500037450000076262114505005531022013 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbupdate Dynamic update functions * @ingroup dnsdb * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #include "dnsdb/zdb_types.h" #include "dnsdb/nsec.h" #include "dnsdb/nsec3.h" #include #include #include #include #include #include "dnsdb/dnssec.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/dnssec-keystore.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/dynupdate-diff.h" #include "dnsdb/zdb-zone-path-provider.h" #include "dnsdb/zdb_icmtl.h" #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif #define ZDB_JOURNAL_CODE 1 #include "dnsdb/journal.h" #define MODULE_MSG_HANDLE g_database_logger extern logger_handle *g_database_logger; // Disable detailed diff log even in debug builds #define DYNUPDATE_DIFF_DO_NOT_ADD_NSEC3_ON_NON_NSEC3_ZONE 0 #define DYNUPDATE_DIFF_DETAILED_LOG 0 #ifndef DYNUPDATE_DIFF_DETAILED_LOG #if DEBUG #define DYNUPDATE_DIFF_DETAILED_LOG 1 #else #define DYNUPDATE_DIFF_DETAILED_LOG 0 #endif #endif #if DYNUPDATE_DIFF_DETAILED_LOG #pragma message("WARNING: DYNUPDATE_DIFF_DETAILED_LOG is not set to 0") #endif #define DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG 0 #ifndef DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG #if DEBUG #define DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG 1 #else #define DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG 0 #endif #endif #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG #pragma message("WARNING: DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG is not set to 0") #endif /////////////////////////////////////////////////////////////////////////////// static char zone_diff_record_state_format_letters[6] = {'+','-','O','V','E','A'}; void zone_diff_record_state_format(const void* data, output_stream* os, s32 a, char b , bool c, void* reserved_for_method_parameters) { (void)a; (void)b; (void)c; (void)reserved_for_method_parameters; u8 state = *((u8*)data); for(u32 i = 0; i < sizeof(zone_diff_record_state_format_letters); ++i) { char c = ((state & (1 << i)) != 0)?zone_diff_record_state_format_letters[i]:'_'; output_stream_write(os, &c, 1); } } #if DEBUG static char zone_diff_chain_state_format_letters[8] = {'+','-',' ','r','E','{','}','!'}; static void zone_diff_chain_state_format(const void* data, output_stream* os, s32 a, char b , bool c, void* reserved_for_method_parameters) { (void)a; (void)b; (void)c; (void)reserved_for_method_parameters; u8 state = *((u8*)data); for(u32 i = 0; i < sizeof(zone_diff_chain_state_format_letters); ++i) { char c = ((state & (1 << i)) != 0)?zone_diff_chain_state_format_letters[i]:'_'; output_stream_write(os, &c, 1); } } #endif static void zone_diff_fqdn_changes_format(const void* data, output_stream* os, s32 a, char b , bool c, void* reserved_for_method_parameters) { (void)a; (void)b; (void)c; (void)reserved_for_method_parameters; zone_diff_fqdn *diff = (zone_diff_fqdn*)data; if(diff->type_map_changed) output_stream_write(os, "MAP ", 4); if(diff->all_rrset_added) output_stream_write(os, "+ALL ", 5); if(diff->all_rrset_removed) output_stream_write(os, "-ALL ", 5); if(diff->is_apex) output_stream_write(os, "APEX ", 5); output_stream_write(os, "AT(", 3); output_stream_write_u8(os, diff->was_at_delegation?'1':'0'); output_stream_write(os, "->", 2); output_stream_write_u8(os, diff->at_delegation?'1':'0'); output_stream_write(os, ") ", 2); output_stream_write(os, "UNDER(", 6); output_stream_write_u8(os, diff->was_under_delegation?'1':'0'); output_stream_write(os, "->", 2); output_stream_write_u8(os, diff->under_delegation?'1':'0'); output_stream_write(os, ") ", 2); output_stream_write(os, "DS(", 3); output_stream_write_u8(os, diff->had_ds?'1':'0'); output_stream_write(os, "->", 2); output_stream_write_u8(os, diff->will_have_ds?'1':'0'); output_stream_write(os, ") ", 2); output_stream_write(os, "CHILDREN(", 9); output_stream_write_u8(os, diff->had_children?'1':'0'); output_stream_write(os, "->", 2); output_stream_write_u8(os, diff->will_have_children?'1':'0'); output_stream_write(os, ") ", 2); output_stream_write(os, "RECORDS(", 8); output_stream_write_u8(os, diff->was_non_empty?'1':'0'); output_stream_write(os, "->", 2); output_stream_write_u8(os, diff->will_be_non_empty?'1':'0'); output_stream_write(os, ") ", 2); } static const u8 * zone_diff_label_rr_rrv_get_fqdn(void *data, const void* p) { (void)data; zone_diff_label_rr *rr = (zone_diff_label_rr*)p; return rr->fqdn; } static u16 zone_diff_label_rr_rrv_get_type(void *data, const void* p) { /* zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)data; (void)p; return rrset->rtype; */ (void)data; zone_diff_label_rr *rr = (zone_diff_label_rr*)p; return rr->rtype; } static u16 zone_diff_label_rr_rrv_get_class(void *data, const void* p) { /* zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)data; (void)p; return rrset->rclass; */ (void)data; zone_diff_label_rr *rr = (zone_diff_label_rr*)p; return rr->rclass; } static s32 zone_diff_label_rr_rrv_get_ttl(void *data, const void* p) { /* zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)data; (void)p; return rrset->new_ttl; */ (void)data; zone_diff_label_rr *rr = (zone_diff_label_rr*)p; return rr->ttl; } static u16 zone_diff_label_rr_rrv_get_rdata_size(void *data, const void* p) { (void)data; zone_diff_label_rr *rr = (zone_diff_label_rr*)p; return rr->rdata_size; } static const u8 * zone_diff_label_rr_rrv_get_rdata(void *data, const void* p) { (void)data; zone_diff_label_rr *rr = (zone_diff_label_rr*)p; return (const u8*)rr->rdata; } static void * zone_diff_label_rr_rrv_new_instance(void *data, const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size, const u8 *rdata) { (void)data; zone_diff_label_rr *rr = zone_diff_label_rr_new(fqdn, rtype, rclass, ttl, (void*)rdata, rdata_size, TRUE); return rr; } static const struct resource_record_view_vtbl zone_diff_label_rr_rrv_vtbl = { zone_diff_label_rr_rrv_get_fqdn, zone_diff_label_rr_rrv_get_type, zone_diff_label_rr_rrv_get_class, zone_diff_label_rr_rrv_get_ttl, zone_diff_label_rr_rrv_get_rdata_size, zone_diff_label_rr_rrv_get_rdata, zone_diff_label_rr_rrv_new_instance }; /////////////////////////////////////////////////////////////////////////////// /** * Initialises a dnssec chain (editor). * NSEC and NSEC3 chains cannot be mixed. * The actual chain must be set using dnssec_chain_add_chain * * @param dc * @param chain_functions */ void dnssec_chain_init(dnssec_chain *dc, const dnssec_chain_node_vtbl *chain_functions, zone_diff *diff) { dc->diff = diff; dc->chain = chain_functions; dc->chains_count = 0; } /** * Adds a chain to the chain editor. * * NSEC3: every nsec3_zone* of the zone (one at a time). * NSEC: the nsec_zone of the zone. * * @param dc * @param chain */ void dnssec_chain_add_chain(dnssec_chain *dc, dnssec_chain_head_t chain, bool being_deleted) { if(dc->chains_count < DNSSEC_CHAIN_SUPPORTED_MAX) { ptr_set_init(&dc->chain_diff[dc->chains_count]); dc->chain_diff[dc->chains_count].compare = dc->chain->compare; dc->chains[dc->chains_count] = chain; dc->chain_being_deleted[dc->chains_count] = being_deleted; ++dc->chains_count; } } static void dnssec_chain_add_node(dnssec_chain *dc, const u8 *fqdn, u16 rtype, u8 asked_or_mask) { // compute the hash // find the prev & next in the current set // store a node with "prev new next" // store a node with "prev" marked as begin (if !E) // store a node with "next" marked as end (if !E) (void)rtype; for(int chain_index = 0; chain_index < dc->chains_count; ++chain_index) { void *chain = dc->chains[chain_index]; // need to know if it's under delegation // #if DEBUG log_debug("NEW NODE %{dnsname} (0)", fqdn); #endif void *chain_node = dc->chain->node_new(fqdn, chain); ptr_node *node = ptr_set_insert(&dc->chain_diff[chain_index], chain_node); // if chain is not empty, edit it, else create it with one node if(!dc->chain->isempty(chain)) { u8 or_mask = (!dc->chain_being_deleted[chain_index])?asked_or_mask:DNSSEC_CHAIN_DELETE; if(node->value == NULL) { node->value = chain_node; // create a node for the prev & next void *chain_begin = dc->chain->node_prev(chain_node); // zone_diff_add_fqdn(dc->diff, node->fqdn, rr_label); yassert(chain_begin != NULL); ptr_node *node_prev = ptr_set_insert(&dc->chain_diff[chain_index], chain_begin); if(node_prev->value == NULL) { node_prev->value = chain_begin; } else { dc->chain->node_merge(node_prev->value, chain_begin); } void *chain_end = dc->chain->node_next(chain_node); yassert(chain_end != NULL); ptr_node *node_next = ptr_set_insert(&dc->chain_diff[chain_index], chain_end); if(node_next->value == NULL) { node_next->value = chain_end; } else { dc->chain->node_merge(node_next->value, chain_end); } } else { // node exists already ... dc->chain->state_set(node->value, dc->chain->state_get(node->value) & ~(DNSSEC_CHAIN_BEGIN|DNSSEC_CHAIN_END)); dc->chain->node_delete(chain_node); } if(or_mask != 0) { dc->chain->state_set(node->value, dc->chain->state_get(node->value) | or_mask); } } else { // instead of the doing diff computations the chain will be fully created node->value = chain_node; } } } static void dnssec_chain_add_node_neighbours(dnssec_chain *dc, const zone_diff_fqdn *diff_fqdn, void *chain_node, int chain_index) { (void)diff_fqdn; void *chain_begin = dc->chain->node_prev(chain_node); yassert(chain_begin != NULL); #if DEBUG format_writer chain_node_prev_fw; dc->chain->format_writer_init(chain_begin, &chain_node_prev_fw); #endif ptr_node *node_prev = ptr_set_insert(&dc->chain_diff[chain_index], chain_begin); if(node_prev->value == NULL) { node_prev->value = chain_begin; #if DEBUG log_debug2("dnssec-chain: %{dnsname}: chain[%i]: previous node is %w", diff_fqdn->fqdn, chain_index, &chain_node_prev_fw); #endif } else { #if DEBUG log_debug2("dnssec-chain: %{dnsname}: chain[%i]: previous node %w already in chain, merging", diff_fqdn->fqdn, chain_index, &chain_node_prev_fw); #endif dc->chain->node_merge(node_prev->value, chain_begin); #if DEBUG dc->chain->format_writer_init(node_prev->value, &chain_node_prev_fw); log_debug2("dnssec-chain: %{dnsname}: chain[%i]: previous node %w merged", diff_fqdn->fqdn, chain_index, &chain_node_prev_fw); #endif } void *chain_end = dc->chain->node_next(chain_node); yassert(chain_end != NULL); #if DEBUG format_writer chain_node_next_fw; dc->chain->format_writer_init(chain_end, &chain_node_next_fw); #endif ptr_node *node_next = ptr_set_insert(&dc->chain_diff[chain_index], chain_end); if(node_next->value == NULL) { #if DEBUG log_debug2("dnssec-chain: %{dnsname}: chain[%i]: next node is %w", diff_fqdn->fqdn, chain_index, &chain_node_next_fw); #endif node_next->value = chain_end; } else { #if DEBUG log_debug2("dnssec-chain: %{dnsname}: chain[%i]: next node %w already in chain, merging", diff_fqdn->fqdn, chain_index, &chain_node_next_fw); #endif dc->chain->node_merge(node_next->value, chain_end); #if DEBUG dc->chain->format_writer_init(node_next->value, &chain_node_next_fw); log_debug2("dnssec-chain: %{dnsname}: chain[%i]: next node %w merged", diff_fqdn->fqdn, chain_index, &chain_node_next_fw); #endif } } static int dnssec_chain_add_node_from_diff_fqdn(dnssec_chain *dc, zone_diff_fqdn *diff_fqdn, u16 rtype, u8 asked_or_mask) { int ret = 0; // compute the hash // find the prev & next in the current set // store a node with "prev new next" // store a node with "prev" marked as begin (if !E) // store a node with "next" marked as end (if !E) (void)rtype; for(int chain_index = 0; chain_index < dc->chains_count; ++chain_index) { void *chain = dc->chains[chain_index]; // need to know if it's under delegation if(asked_or_mask & DNSSEC_CHAIN_DELETE) { // IT HAD TO EXIST FIRST! if(!dc->chain->fqdn_was_covered(diff_fqdn)) { #if DEBUG log_debug2("dnssec-chain: %{dnsname}: chain[%i]: did not cover", diff_fqdn->fqdn, chain_index); #endif continue; } } else { if(!dc->chain->fqdn_is_covered(diff_fqdn)) { #if DEBUG log_debug2("dnssec-chain: %{dnsname}: chain[%i]: does not covers", diff_fqdn->fqdn, chain_index); #endif continue; } } #if DEBUG log_debug2("dnssec-chain: %{dnsname}: chain[%i]: covers", diff_fqdn->fqdn, chain_index); #endif // #if DEBUG log_debug3("NEW NODE %{dnsname} (1)", diff_fqdn->fqdn); #endif void *chain_node = dc->chain->node_new(diff_fqdn->fqdn, chain); #if DEBUG format_writer chain_node_fw; dc->chain->format_writer_init(chain_node, &chain_node_fw); log_debug2("dnssec-chain: %{dnsname}: chain[%i]: node is %w", diff_fqdn->fqdn, chain_index, &chain_node_fw); #endif ptr_node *node = ptr_set_insert(&dc->chain_diff[chain_index], chain_node); if(!dc->chain->isempty(chain)) { u8 or_mask = (!dc->chain_being_deleted[chain_index])?asked_or_mask:DNSSEC_CHAIN_DELETE; if(node->value == NULL) { #if DEBUG log_debug2("dnssec-chain: %{dnsname}: chain[%i]: node %w is new, getting both neighbours", diff_fqdn->fqdn, chain_index, &chain_node_fw); #endif diff_fqdn->will_have_new_nsec = 1; node->value = chain_node; // create a node for the prev & next dnssec_chain_add_node_neighbours(dc, diff_fqdn, chain_node, chain_index); } else { #if DEBUG log_debug2("dnssec-chain: %{dnsname}: chain[%i]: node %w already exists", diff_fqdn->fqdn, chain_index, &chain_node_fw); #endif // node exists already ... dnssec_chain_add_node_neighbours(dc, diff_fqdn, chain_node, chain_index); dc->chain->node_merge(node->value, chain_node); dc->chain->state_set(node->value, dc->chain->state_get(node->value) & ~(DNSSEC_CHAIN_BEGIN|DNSSEC_CHAIN_END)); } // check if any of the RRSET of the label have been added or removed // u8 prev_state = dc->chain->state_get(node->value); if(prev_state & DNSSEC_CHAIN_EXISTS) { bool type_map_changed = zone_diff_fqdn_type_map_changed(diff_fqdn); if(type_map_changed) { or_mask |= DNSSEC_CHAIN_REMAP; } } if(or_mask != 0) { dc->chain->state_set(node->value, prev_state | or_mask); } if(((prev_state & DNSSEC_CHAIN_EXISTS) == 0) || ((or_mask & (DNSSEC_CHAIN_DELETE|DNSSEC_CHAIN_REMAP)) != 0)) { ++ret; } } else { #if DEBUG log_debug("dnssec-chain: %{dnsname}: chain[%i] was empty", diff_fqdn->fqdn, chain_index); #endif // instead of the doing diff computations the chain will be fully created if(node->value != NULL) { #if DEBUG log_debug("dnssec-chain: %{dnsname}: chain[%i]: node %w already exists", diff_fqdn->fqdn, chain_index, &chain_node_fw); #endif // node exists already ... assert(dc->chain->compare(node->value, chain_node) == 0); dc->chain->node_merge(node->value, chain_node); dc->chain->state_set(node->value, dc->chain->state_get(node->value) & ~(DNSSEC_CHAIN_BEGIN|DNSSEC_CHAIN_END)); } else { diff_fqdn->will_have_new_nsec = 1; node->value = chain_node; } ++ret; } } return ret; } /** * Adds a node to the chain. * * @param dc * @param fqdn * @param rtype */ void dnssec_chain_add(dnssec_chain *dc, const u8 *fqdn, u16 rtype) { dnssec_chain_add_node(dc, fqdn, rtype, DNSSEC_CHAIN_ADD); // It used to be : // dnssec_chain_add_node(dc, fqdn, rtype, 0); } int dnssec_chain_add_from_diff_fqdn(dnssec_chain *dc, zone_diff_fqdn* diff_fqdn, u16 rtype) { int ret = dnssec_chain_add_node_from_diff_fqdn(dc, diff_fqdn, rtype, DNSSEC_CHAIN_ADD); return ret; } /** * Removes a node from the chain. * * @param dc * @param fqdn * @param rtype */ void dnssec_chain_del(dnssec_chain *dc, const u8 *fqdn, u16 rtype) { dnssec_chain_add_node(dc, fqdn, rtype, DNSSEC_CHAIN_DELETE); } int dnssec_chain_del_from_diff_fqdn(dnssec_chain *dc, zone_diff_fqdn* diff_fqdn, u16 rtype) { int ret = dnssec_chain_add_node_from_diff_fqdn(dc, diff_fqdn, rtype, DNSSEC_CHAIN_DELETE); return ret; } static void dnssec_chain_store_diff_publish_chain_node(dnssec_chain *dc, zone_diff *diff, ptr_vector *keys, void *chain, void *prev, void *prev_next, ptr_vector *add) { ya_result ret; s32 from_offset = ptr_vector_size(add); dc->chain->publish_add(chain, prev, prev_next, diff, add); // and its signature(s) s32 to_offset = ptr_vector_size(add); // make a ptr_vector that's a view of the last added records ptr_vector rrset = {&add->data[from_offset], 0, to_offset - from_offset}; struct resource_record_view rrv = {NULL, &zone_diff_label_rr_rrv_vtbl}; u16 rrset_type = TYPE_NONE; for(int i = 0; i <= ptr_vector_last_index(&rrset); ++i) { void* data = ptr_vector_get(&rrset, i); const void *fqdn = rrv.vtbl->get_fqdn(rrv.data, data); u16 rtype = rrv.vtbl->get_type(rrv.data, data); u16 rclass = rrv.vtbl->get_class(rrv.data, data); s32 ttl = rrv.vtbl->get_ttl(rrv.data, data); u16 rdata_size = rrv.vtbl->get_rdata_size(rrv.data, data); const void *rdata = rrv.vtbl->get_rdata(rrv.data, data); rrset_type = rtype; rdata_desc rdt = {rtype, rdata_size, rdata}; log_debug("update: %{dnsname}: will sign chain record #%i: %{dnsname} %i %{dnsclass} %{typerdatadesc}", diff->origin, i, fqdn, ttl, &rclass, &rdt); } bool canonize = TRUE; for(int j = 0; j <= ptr_vector_last_index(keys); ++j) { const dnssec_key *key = (dnssec_key*)ptr_vector_get(keys, j); zone_diff_label_rr *rrsig_rr = NULL; s32 maxinterval = diff_generate_signature_interval(diff); // rrset_to_sign; if(ISOK(ret = dnskey_sign_rrset_with_maxinterval(key, &rrset, canonize, &rrv, maxinterval, (void **) &rrsig_rr))) { canonize = FALSE; // add the key to the add set rdata_desc rdt = {rrsig_rr->rtype, rrsig_rr->rdata_size, rrsig_rr->rdata}; log_debug("update: %{dnsname}: signed chain rrset %{dnstype} with key %03d %05d: %{dnsname} %i %{dnsclass} %{typerdatadesc}", diff->origin, &rrset_type, dnskey_get_algorithm(key), dnskey_get_tag_const(key), rrsig_rr->fqdn, rrsig_rr->ttl, &rrsig_rr->rclass, &rdt ); rrsig_rr->state |= ZONE_DIFF_RR_VOLATILE; ptr_vector_append(add, rrsig_rr); // since we are mapping inside the array and the array could have been replaced by a bigger one ... rrset.data = &add->data[from_offset]; } #if DEBUG else { log_debug("update: %{dnsname}: did not sign rrset %{dnstype} with key %03d %05d: %r", diff->origin, &rrset_type, dnskey_get_algorithm(key), dnskey_get_tag_const(key), ret); } #endif } } /** * Computes the changes of the chain into a del and an add records vector. * * @param diff * @param origin * @param nttl */ void dnssec_chain_store_diff(dnssec_chain *dc, zone_diff *diff, ptr_vector *keys, ptr_vector *del, ptr_vector *add) { // simplify then apply the changes // put all the nodes in an array ptr_vector nodes; ptr_vector_init(&nodes); // for every chain for(int chain_index = 0; chain_index < dc->chains_count; ++chain_index) { void *chain = dc->chains[chain_index]; // clear the nodes (from a previous chain) ptr_vector_clear(&nodes); // gather all the nodes in the chain in an array // they are inserted in sorted order (ptr_set_iterator does this) ptr_set_iterator iter; ptr_set_iterator_init(&dc->chain_diff[chain_index], &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); yassert(node->value != NULL); ptr_vector_append(&nodes, node->value); } // "nodes" is the list of all the nodes // look in a circular pattern for all the nodes that have the "delete" status log_debug("update: %{dnsname}: %i nodes in dnssec chain #%i", diff->origin, ptr_vector_size(&nodes), chain_index); if(ptr_vector_size(&nodes) == 0) { continue; } #if DEBUG for(int i = 0; i <= ptr_vector_last_index(&nodes); ++i) { void *node = ptr_vector_get_mod(&nodes, i); void *next = (i < ptr_vector_last_index(&nodes))?ptr_vector_get_mod(&nodes, i + 1) : NULL; u8 state = dc->chain->state_get(node); format_writer temp_fw_0 = {zone_diff_chain_state_format, &state}; log_debug1("update: %{dnsname}: %3i: %02x %w", diff->origin, i, state, &temp_fw_0); dc->chain->publish_log(node, next); } #endif int first_begin = -1; // the first chain node at the begin of a change int last_end; bool whole_chain = FALSE; // does the operation covers the whole chain // if the chain isn't empty if(!dc->chain->isempty(chain)) { // chain is not empty but may be too small (1 item) if(ptr_vector_last_index(&nodes) > 0) // if true, then it has more than one item { // the chain has more than one item int exists = 0; int begin = 0; int end = 0; int both = 0; bool prev_does_not_alter_the_chain = FALSE; // note: this block is the initial step of the loop that follows // check if the last node of the chain exists already { void *node = ptr_vector_last(&nodes); u8 state = dc->chain->state_get(node); if(state & DNSSEC_CHAIN_EXISTS) { ++exists; // if the node exists and is not deleted // 00 != 01 = 1 // 01 = 0 // 10 = 1 // 11 = 1 // only false if the node exists, hasn't been added and is being deleted prev_does_not_alter_the_chain = ((state & (DNSSEC_CHAIN_ADD|DNSSEC_CHAIN_DELETE)) != DNSSEC_CHAIN_DELETE); } else // the node did not exist (and thus will be added, as there is no other reason being here) { prev_does_not_alter_the_chain = FALSE; // the chain will be altered } } // this loop marks nodes with the next field changed for(int i = 0; i <= ptr_vector_last_index(&nodes); ++i) { void *node = ptr_vector_get(&nodes, i); u8 state = dc->chain->state_get(node); if(state & DNSSEC_CHAIN_BEGIN) // the node exists already in the chain and is the start of an update { first_begin = i; ++begin; } if(state & DNSSEC_CHAIN_END) // the node exists already in the chain and is the end of an update { ++end; if(state & DNSSEC_CHAIN_BEGIN) // if it's also the start of an update, some merging will happen { ++both; } } bool does_not_alter_the_chain; // as in : the label is not new and is not deleted if(state & DNSSEC_CHAIN_EXISTS) { ++exists; // if the node exists and is not deleted // only false if the node exists, hasn't been added and is being deleted (same as on the previous block) does_not_alter_the_chain = ((state & (DNSSEC_CHAIN_ADD|DNSSEC_CHAIN_DELETE)) != DNSSEC_CHAIN_DELETE); } else // the node did not exist (and thus will be added, as there is no other reason being here) { does_not_alter_the_chain = FALSE; // the chain will be altered } // if the current node alters the chain but not the previous one if(!does_not_alter_the_chain && prev_does_not_alter_the_chain) // since this one is added and not the previous one, the previous one has to be updated { void *prev_node = ptr_vector_get_mod(&nodes, i - 1); u8 prev_state = dc->chain->state_get(prev_node); dc->chain->state_set(prev_node, prev_state | (DNSSEC_CHAIN_ADD|DNSSEC_CHAIN_DELETE)); // means "updated" } prev_does_not_alter_the_chain = does_not_alter_the_chain; } int chain_loops = 0; if(begin + end == 0) // there are no blocks marked as "begin" nor "end" { // the chain is looping on itself, take the first exist and mark it as begin & end int delete = 0; for(int i = 0; i <= ptr_vector_last_index(&nodes); ++i) { void *node = ptr_vector_get(&nodes, i); u8 state = dc->chain->state_get(node); u8 masked_state = state & (DNSSEC_CHAIN_EXISTS|DNSSEC_CHAIN_ADD|DNSSEC_CHAIN_DELETE); // if the node exists, exists and is added or exists and is updated if((masked_state == DNSSEC_CHAIN_EXISTS) || (masked_state == (DNSSEC_CHAIN_EXISTS | DNSSEC_CHAIN_ADD)) || (masked_state == (DNSSEC_CHAIN_EXISTS | DNSSEC_CHAIN_ADD | DNSSEC_CHAIN_DELETE))) { // then mark it as the "begin" and the "end" as well dc->chain->state_set(node, state | (DNSSEC_CHAIN_BEGIN|DNSSEC_CHAIN_END)); first_begin = i; // this node is the first (and last) "begin" node chain_loops = 1; // one loop on this whole chain break; } if(masked_state == (DNSSEC_CHAIN_EXISTS | DNSSEC_CHAIN_DELETE)) { ++delete; } } // are all nodes deleted? if(delete == ptr_vector_size(&nodes)) { void *node = ptr_vector_get(&nodes, 0); u8 state = dc->chain->state_get(node); dc->chain->state_set(node, state | (DNSSEC_CHAIN_BEGIN|DNSSEC_CHAIN_END)); first_begin = 0; chain_loops = 1; } } else if((begin == 1) && (end == 1) && (both == 1)) // there is exactly one "begin", one "end" and one that's both { whole_chain = TRUE; } yassert(first_begin >= 0); // chain_loops is 1 iff one node was set as begin & end manually // the last "end" is at (modulo) the first "begin" + the number of nodes last_end = first_begin + ptr_vector_last_index(&nodes) + chain_loops; } else // there is only one item in the chain update { log_debug("update: %{dnsname}: chain #%i update has only one item", diff->origin, chain_index); first_begin = 0; last_end = ptr_vector_last_index(&nodes); // should be 0 } } else // chain is empty, we add everything { log_debug("update: %{dnsname}: chain #%i is empty", diff->origin, chain_index); first_begin = 0; last_end = ptr_vector_last_index(&nodes); } //yassert(dc->chain->isempty(chain) || (first_begin >= 0) || ((first_begin == 0) && (last_end == 0))); #if DEBUG for(int i = first_begin; i <= last_end; ++i) { void *node = ptr_vector_get_mod(&nodes, i); u8 state = dc->chain->state_get(node); void *next = ((state & (DNSSEC_CHAIN_BEGIN|DNSSEC_CHAIN_END)) != DNSSEC_CHAIN_END) ? ptr_vector_get_mod(&nodes, i + 1) : NULL; format_writer temp_fw_0 = {zone_diff_chain_state_format, &state}; log_debug1("update: %{dnsname}: %3i: %02x %w: %p -> %p", diff->origin, i, state, &temp_fw_0, node, next); dc->chain->publish_log(node, next); } #endif if(dc->chain->isempty(chain) || whole_chain || ((first_begin == 0) && (last_end == 0))) { // we are processing a new/whole chain, or the chain is made of one record // for all nodes from the first to the last (modulo) for(int i = first_begin; i <= last_end; ++i) { int j = i + 1; // get the node and its follower void *node = ptr_vector_get_mod(&nodes, i); void *node_next = ptr_vector_get_mod(&nodes, j); u8 state = dc->chain->state_get(node); // if the node exists if(state & DNSSEC_CHAIN_EXISTS) { // if the node is remapped (bitmask change) or the node is updated if((state & DNSSEC_CHAIN_REMAP) || ((state & (DNSSEC_CHAIN_DELETE|DNSSEC_CHAIN_ADD)) == (DNSSEC_CHAIN_DELETE|DNSSEC_CHAIN_ADD))) { #if DEBUG log_debug3("update: %{dnsname}: chain %i state (%02x) del/add", diff->origin, chain_index, state); #endif // delete then add the node dc->chain->publish_delete(chain, node, node_next, diff, del); dnssec_chain_store_diff_publish_chain_node(dc, diff, keys, chain, node, node_next, add); } // if the node is deleted else if(state & DNSSEC_CHAIN_DELETE) { #if DEBUG log_debug3("update: %{dnsname}: chain %i state (%02x) del", diff->origin, chain_index, state); #endif // delete the node dc->chain->publish_delete(chain, node, node_next, diff, del); } } else // if the node doesn't exists { if((state & DNSSEC_CHAIN_EXISTS) == 0) // always true at this point { // remove any delete mark state &= ~DNSSEC_CHAIN_DELETE; // cannot delete what does not exists // if the node was marked as a remap (bitmap change) if(state & DNSSEC_CHAIN_REMAP) { state &= ~DNSSEC_CHAIN_REMAP; // do not remap, create state |= DNSSEC_CHAIN_ADD; } dc->chain->state_set(node, state); } // if the node is being added if(state & DNSSEC_CHAIN_ADD) { #if DEBUG log_debug3("update: %{dnsname}: chain %i state (%02x) add", diff->origin, chain_index, state); #endif // publish the node dnssec_chain_store_diff_publish_chain_node(dc, diff, keys, chain, node, node_next, add); } } } continue; } yassert(first_begin != last_end); void *next_did_exist_node = NULL; void *next_will_exist_node = NULL; int next_did_exist_index = -1; int next_will_exist_index = -1; // for all nodes from the first to the last (modulo) for(int i = first_begin; i < last_end; ++i) { void *node = ptr_vector_get_mod(&nodes, i); u8 state = dc->chain->state_get(node); #if DEBUG { format_writer chain_node_fw; dc->chain->format_writer_init(node, &chain_node_fw); format_writer temp_fw_0 = {zone_diff_chain_state_format, &state}; log_debug1("dnssec-chain: %{dnsname}: chain %i node %w with state %w", diff->origin, chain_index, &chain_node_fw, &temp_fw_0); } #endif // if the node doesn't exists if((state & DNSSEC_CHAIN_EXISTS) == 0) { // remove any delete mark state &= ~DNSSEC_CHAIN_DELETE; // cannot delete what does not exists // if the is marked as remap if(state & DNSSEC_CHAIN_REMAP) { // remove the remap mark and add it instead state &= ~DNSSEC_CHAIN_REMAP; // do not remap, create state |= DNSSEC_CHAIN_ADD; } dc->chain->state_set(node, state); } // if the node is marked as deleted or remapped (note: the node must be marked as "exists" too) if(state & (DNSSEC_CHAIN_DELETE|DNSSEC_CHAIN_REMAP)) { #if DEBUG if((state & DNSSEC_CHAIN_EXISTS) == 0) // impossible, given the previous block { format_writer chain_node_fw; dc->chain->format_writer_init(node, &chain_node_fw); format_writer temp_fw_0 = {zone_diff_chain_state_format, &state}; log_err("dnssec-chain: %{dnsname}: chain %i node %w with state %w should be remapped or deleted but does not exist?", diff->origin, chain_index, &chain_node_fw, &temp_fw_0); logger_flush(); } #endif yassert(state & DNSSEC_CHAIN_EXISTS); // trips on an empty terminal : the node to delete does not exists. if(next_did_exist_index <= i) // always true on the first iteration { // for all nodes following this one (modulo) for(int j = i + 1; j <= last_end; ++j) { void *next_node = ptr_vector_get_mod(&nodes, j); u8 next_state = dc->chain->state_get(next_node); #if DEBUG { format_writer chain_node_fw; dc->chain->format_writer_init(next_node, &chain_node_fw); format_writer temp_fw_0 = {zone_diff_chain_state_format, &next_state}; log_debug1("dnssec-chain: %{dnsname}: chain %i next-node [%i] %w with state %w (delete/remap loop)", diff->origin, chain_index, j, &chain_node_fw, &temp_fw_0); } #endif // if the following node exists, then keep it aside if(next_state & DNSSEC_CHAIN_EXISTS) { next_did_exist_node = next_node; next_did_exist_index = j; break; } } } #if DEBUG logger_flush(); #endif yassert(next_did_exist_index > i); // publish that interval being deleted ... dc->chain->publish_delete(chain, node, next_did_exist_node, diff, del); } // if the node is ... switch(state & (DNSSEC_CHAIN_DELETE|DNSSEC_CHAIN_ADD|DNSSEC_CHAIN_EXISTS|DNSSEC_CHAIN_REMAP)) { // added // added with a remapped // updated // existing and added with a remap // existing, updated with a remap case DNSSEC_CHAIN_ADD: case DNSSEC_CHAIN_ADD|DNSSEC_CHAIN_REMAP: case DNSSEC_CHAIN_DELETE|DNSSEC_CHAIN_ADD|DNSSEC_CHAIN_EXISTS: case DNSSEC_CHAIN_ADD|DNSSEC_CHAIN_EXISTS|DNSSEC_CHAIN_REMAP: case DNSSEC_CHAIN_DELETE|DNSSEC_CHAIN_ADD|DNSSEC_CHAIN_EXISTS|DNSSEC_CHAIN_REMAP: { if(next_will_exist_index <= i) // always true on the first iteration { // for all nodes following this one (modulo) for(int j = i + 1; j <= last_end; ++j) { void *next_node = ptr_vector_get_mod(&nodes, j); u8 next_state = dc->chain->state_get(next_node); #if DEBUG { format_writer chain_node_fw; dc->chain->format_writer_init(next_node, &chain_node_fw); format_writer temp_fw_0 = {zone_diff_chain_state_format, &next_state}; log_debug1("dnssec-chain: %{dnsname}: chain %i next-node [%i] %w with state %w (add/update/remap loop)", diff->origin, chain_index, j, &chain_node_fw, &temp_fw_0); } #endif // if the node is added, or exist (and will keep existing) // a.k.a // if the node will exist after this operation ... // // then keep it aside if((next_state & DNSSEC_CHAIN_ADD) || ((next_state & (DNSSEC_CHAIN_DELETE | DNSSEC_CHAIN_EXISTS)) == DNSSEC_CHAIN_EXISTS)) { next_will_exist_node = next_node; next_will_exist_index = j; break; } } } #if DEBUG logger_flush(); #endif yassert(next_will_exist_index > i); #if DEBUG log_debug3("update: %{dnsname}: chain %i state (%02x) publish chain node", diff->origin, chain_index, state); #endif // publish that interval dnssec_chain_store_diff_publish_chain_node(dc, diff, keys, chain, node, next_will_exist_node, add); break; } default: { break; } } } // for all items in [begin;end[ } // for all chains ptr_vector_destroy(&nodes); } /** * Releases the memory used by a chain */ void dnssec_chain_finalize(dnssec_chain *dc) { for(int chain_index = 0; chain_index < dc->chains_count; ++chain_index) { ptr_set_callback_and_destroy(&dc->chain_diff[chain_index], dc->chain->ptr_set_node_delete_callback); } } static int zone_diff_label_rr_compare(const void *node_a, const void *node_b) { const zone_diff_label_rr *a = (const zone_diff_label_rr*)node_a; const zone_diff_label_rr *b = (const zone_diff_label_rr*)node_b; int d; d = a->rclass; d -= b->rclass; if(d == 0) { d = a->rtype; d -= b->rtype; if(d == 0) { d = dnsname_getdepth(a->fqdn); d -= dnsname_getdepth(b->fqdn); if(d == 0) { d = dnsname_compare(a->fqdn, b->fqdn); if(d == 0) { u16 len = MIN(a->rdata_size, b->rdata_size); d = memcmp(a->rdata, b->rdata, len); if(d == 0) { d = a->rdata_size; d -= b->rdata_size; } } } } else { // SOA have to be first if(a->rtype == TYPE_SOA) { d = -1; } else { d = 1; } } } return d; } zone_diff_label_rr * zone_diff_label_rr_new(const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, void *rdata, u16 rdata_size, bool copy) { zone_diff_label_rr *rr; ZALLOC_OBJECT_OR_DIE(rr, zone_diff_label_rr, ZDFFLABL_TAG); rr->fqdn = dnsname_zdup(fqdn); rr->ttl = ttl; rr->rtype = rtype; rr->rclass = rclass; rr->rdata_size = rdata_size; if(copy) { ZALLOC_ARRAY_OR_DIE(u8*, rr->rdata, rdata_size, ZDFFLBRR_TAG); memcpy(rr->rdata, rdata, rdata_size); rr->state = ZONE_DIFF_RR_RDATA_OWNED; } else { rr->rdata = rdata; rr->state = 0; } return rr; } void zone_diff_label_rr_init_tmp(zone_diff_label_rr *rr, const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, void *rdata, u16 rdata_size) { rr->fqdn = (u8*)fqdn; rr->ttl = ttl; rr->rtype = rtype; rr->rclass = rclass; rr->rdata_size = rdata_size; rr->rdata = rdata; rr->state = 0; } zone_diff_label_rr * zone_diff_label_rr_new_nordata(const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size) { zone_diff_label_rr *rr; ZALLOC_OBJECT_OR_DIE(rr, zone_diff_label_rr, ZDFFLABL_TAG); rr->fqdn = dnsname_zdup(fqdn); rr->ttl = ttl; rr->rtype = rtype; rr->rclass = rclass; rr->rdata_size = rdata_size; ZALLOC_ARRAY_OR_DIE(u8*, rr->rdata, rdata_size, ZDFFLBRR_TAG); rr->state = ZONE_DIFF_RR_RDATA_OWNED; return rr; } static void zone_diff_label_rr_delete(zone_diff_label_rr *rr) { dnsname_zfree(rr->fqdn); if(rr->state & ZONE_DIFF_RR_RDATA_OWNED) { #if DEBUG memset(rr->rdata, 0xff, rr->rdata_size); #endif ZFREE_ARRAY(rr->rdata, rr->rdata_size); } #if DEBUG memset(rr, 0xff, sizeof(zone_diff_label_rr)); #endif ZFREE_OBJECT(rr); } static void zone_diff_label_rr_vector_clear(ptr_vector *records) { for(int i = 0; i <= ptr_vector_last_index(records); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(records, i); if((rr->state & ZONE_DIFF_RR_VOLATILE) != 0) { zone_diff_label_rr_delete(rr); } } ptr_vector_clear(records); } zone_diff_fqdn_rr_set *zone_diff_fqdn_rr_set_new(u16 rtype) { zone_diff_fqdn_rr_set *rr_set; ZALLOC_OBJECT_OR_DIE(rr_set, zone_diff_fqdn_rr_set, ZDFFRRST_TAG); ptr_set_init(&rr_set->rr); rr_set->rr.compare = zone_diff_label_rr_compare; rr_set->key_mask = 0; rr_set->org_ttl = -1; rr_set->new_ttl = -1; rr_set->rtype = rtype; rr_set->rclass = CLASS_IN; return rr_set; } static void zone_diff_fqdn_rr_set_delete_cb(ptr_node *node) { zone_diff_label_rr *rr = (zone_diff_label_rr*)node->value; #if DEBUG log_debug7("update: %{dnsname}: deleting %{dnstype} structure", rr->fqdn, &rr->rtype); #endif zone_diff_label_rr_delete(rr); } static void zone_diff_fqdn_rr_set_delete(zone_diff_fqdn_rr_set *rr_set) { if(rr_set != NULL) { ptr_set_callback_and_destroy(&rr_set->rr, zone_diff_fqdn_rr_set_delete_cb); ZFREE_OBJECT(rr_set); } } void zone_diff_fqdn_rr_set_rr_add_replace(zone_diff_fqdn_rr_set *rr_set, zone_diff_label_rr *rr) { ptr_node *node = ptr_set_insert(&rr_set->rr, rr); if(node->value == NULL) { node->value = rr; } else { zone_diff_label_rr_delete((zone_diff_label_rr*)node->value); node->key = rr; node->value = rr; } } zone_diff_label_rr* zone_diff_fqdn_rr_set_rr_add_get(zone_diff_fqdn_rr_set *rr_set, zone_diff_label_rr *rr) { ptr_node *node = ptr_set_insert(&rr_set->rr, rr); if(node->value == NULL) { node->value = rr; } else { zone_diff_label_rr_delete(rr); rr = (zone_diff_label_rr*)node->value; } return rr; } static zone_diff_label_rr * zone_diff_fqdn_rr_set_get_existing_rr(zone_diff_fqdn_rr_set *rr_set, const zone_diff_label_rr *rr) { ptr_node *node = ptr_set_find(&rr_set->rr, rr); if(node != NULL) { return (zone_diff_label_rr*)node->value; } return NULL; } // static zone_diff_fqdn *zone_diff_fqdn_new(const u8 *fqdn) { zone_diff_fqdn *diff_fqdn; ZALLOC_OBJECT_OR_DIE(diff_fqdn, zone_diff_fqdn, ZDFFFQDN_TAG); memset(diff_fqdn, 0, sizeof(zone_diff_fqdn)); u32_set_init(&diff_fqdn->rrset); diff_fqdn->fqdn = dnsname_zdup(fqdn); //diff_fqdn->type_map_changed = FALSE; return diff_fqdn; } static void zone_diff_fqdn_delete_cb(u32_node *node) { zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)node->value; #if DEBUG if(rrset == NULL) { u16 rtype = (u16)node->key; log_debug1("zone_diff_fqdn_delete_cb empty set for type %{dnstype}", &rtype); } #endif zone_diff_fqdn_rr_set_delete(rrset); } static void zone_diff_fqdn_delete(zone_diff_fqdn *diff_fqdn) { u32_set_callback_and_destroy(&diff_fqdn->rrset, zone_diff_fqdn_delete_cb); #if DEBUG log_debug1("update: %{dnsname}: deleting diff fqdn", diff_fqdn->fqdn); #endif dnsname_zfree(diff_fqdn->fqdn); ZFREE_OBJECT(diff_fqdn); } zone_diff_fqdn_rr_set* zone_diff_fqdn_rr_set_add(zone_diff_fqdn *diff_fqdn, u16 rtype) { u32_node *node = u32_set_insert(&diff_fqdn->rrset, rtype); if(node->value == NULL) { node->value = zone_diff_fqdn_rr_set_new(rtype); } return (zone_diff_fqdn_rr_set*)node->value; } /** * Returns the local copy of the specified RRSET * Creates an emtpy set if it does not exist. * * @param diff_fqdn * @param rtype * @return */ zone_diff_fqdn_rr_set * zone_diff_fqdn_rr_set_get(const zone_diff_fqdn *diff_fqdn, u16 rtype) { u32_node *node = u32_set_find(&diff_fqdn->rrset, rtype); if(node != NULL) { return (zone_diff_fqdn_rr_set*)node->value; } return NULL; } /** * Returns the local copy of the specified RRSET * * @param diff_fqdn * @param rtype * @return */ const zone_diff_fqdn_rr_set *zone_diff_fqdn_rr_get_const(const zone_diff_fqdn *diff_fqdn, u16 rtype) { u32_node *node = u32_set_find(&diff_fqdn->rrset, rtype); if(node != NULL) { return (zone_diff_fqdn_rr_set*)node->value; } return NULL; } s32 zone_diff_fqdn_rr_set_get_ttl(zone_diff_fqdn_rr_set *rrset) { // @note 20170228 edf -- issue detection // If this aborts, it's likely somebody called zone_diff_fqdn_rr_get without // the intent of putting records in it. // Find it and call zone_diff_will_have_rrset_type instead. yassert(rrset != NULL); ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & ZONE_DIFF_RR_REMOVE) == 0) { // this record was present or is being added return rr->ttl; } } return -1; } s32 zone_diff_fqdn_rr_get_ttl(const zone_diff_fqdn *diff_fqdn, u16 rtype) { s32 ttl = -1; u32_node *rrset_node = u32_set_find(&diff_fqdn->rrset, rtype); if(rrset_node != NULL) { zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)rrset_node->value; ttl = zone_diff_fqdn_rr_set_get_ttl(rrset); } return ttl; // TTL is signed, 32 bits and >= 0 } /** * Deletes an RRSET if it's empty. * * @param diff_fqdn * @param rtype */ void zone_diff_fqdn_rr_clear(zone_diff_fqdn *diff_fqdn, u16 rtype) { u32_node *node = u32_set_insert(&diff_fqdn->rrset, rtype); if(node != NULL) { if(node->value == NULL) { u32_set_delete(&diff_fqdn->rrset, rtype); } } } /** * Returns TRUE iff an rrset as been added or removed from the label. * Stressing out this concerns RRSET as a whole. * * @param diff_fqdn * @return */ bool zone_diff_fqdn_type_map_changed(const zone_diff_fqdn *diff_fqdn) { if(diff_fqdn->rrsig_kept == 0) { if(diff_fqdn->rrsig_added || diff_fqdn->rrsig_removed || diff_fqdn->rrsig_expect_new_rrsig) { return TRUE; // RRSIG type bitmap has changed; } } u32_set_iterator iter; ptr_set_iterator rr_iter; u32_set_iterator_init(&diff_fqdn->rrset, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)node->value; if(rrset != NULL) { ptr_set_iterator_init(&rrset->rr, &rr_iter); u8 rr_state = 0; while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)rr_node->key; if(rr->state == 0) { // previously existing record : no change on this set rr_state = 0; break; } rr_state |= rr->state & (ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_ADD); } if((rr_state != 0) && ((rr_state & (ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_ADD)) != (ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_ADD))) { // this set is completely added or completely removed if(rrset->rtype != TYPE_RRSIG) // exceptional test { return TRUE; } else { if(!diff_fqdn->is_apex) { if(diff_fqdn->has_active_zsk) { rr_state |= ZONE_DIFF_RR_ADD; if((rr_state != 0) && ((rr_state & (ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_ADD)) != (ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_ADD))) { return TRUE; } } } else { if(diff_fqdn->has_active_zsk||diff_fqdn->has_active_ksk) { rr_state |= ZONE_DIFF_RR_ADD; if((rr_state != 0) && ((rr_state & (ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_ADD)) != (ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_ADD))) { return TRUE; } } } } } } } return FALSE; } /** * Initialises a zone diff * * @param diff * @param origin * @param nttl */ void zone_diff_init(zone_diff *diff, zdb_zone *zone, bool rrsig_update_allowed) { log_debug1("update: %{dnsname}: initialising diff @%p", zone->origin, diff); ptr_set_init(&diff->fqdn); ptr_set_init(&diff->root.sub); diff->root.sub.compare = ptr_set_dnslabel_node_compare; diff->fqdn.compare = ptr_set_fqdn_node_compare; diff->origin = zone->origin; diff->rrsig_validity_interval = MAX(zone->sig_validity_interval_seconds, 0); diff->rrsig_validity_regeneration = MAX(zone->sig_validity_regeneration_seconds, 0); diff->rrsig_validity_jitter = MAX( zone->sig_validity_jitter_seconds, 0); diff->nttl = zone->min_ttl; diff->rrsig_update_allowed = rrsig_update_allowed; diff->has_active_zsk = FALSE; diff->has_active_ksk = FALSE; u8 maintain_mode = zone_get_maintain_mode(zone); switch(maintain_mode) { case ZDB_ZONE_MAINTAIN_NSEC3: case ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT: { diff->maintain_nsec = FALSE; diff->maintain_nsec3 = TRUE; break; } case ZDB_ZONE_MAINTAIN_NSEC: { diff->maintain_nsec = TRUE; diff->maintain_nsec3 = FALSE; break; } default: { diff->maintain_nsec = FALSE; diff->maintain_nsec3 = FALSE; break; } } // NOTE: set the apex at the end of the function diff->apex = zone_diff_fqdn_add(diff, zone->origin, zone->apex); } static zone_diff_label_tree* zone_diff_label_tree_add_fqdn(zone_diff *diff, const u8 *fqdn) { #if DEBUG log_debug2("zone-diff: %{dnsname}: label tree add %{dnsname}", diff->origin, fqdn); #endif if(fqdn[0] != 0) { zone_diff_label_tree *label_node; ptr_node *label_tree_node; const u8 *parent_fqdn = fqdn + fqdn[0] + 1; zone_diff_label_tree *parent = zone_diff_label_tree_add_fqdn(diff, parent_fqdn); label_tree_node = ptr_set_insert(&parent->sub, (u8*)fqdn); if(label_tree_node->value != NULL) { label_node = (zone_diff_label_tree*)label_tree_node->value; } else { ZALLOC_OBJECT_OR_DIE(label_node, zone_diff_label_tree, ZDLABELT_TAG); label_node->label = fqdn; label_node->diff_fqdn = zone_diff_fqdn_get(diff, fqdn); ptr_set_init(&label_node->sub); label_node->sub.compare = ptr_set_dnslabel_node_compare; label_tree_node->value = label_node; } return label_node; } else { return &diff->root; } } static void zone_diff_label_tree_destroy_cb(ptr_node* node) { zone_diff_label_tree* dlt = (zone_diff_label_tree*)node->value; if(dlt != NULL) { if(!ptr_set_isempty(&dlt->sub)) { ptr_set_callback_and_destroy(&dlt->sub, zone_diff_label_tree_destroy_cb); } ZFREE_OBJECT(dlt); } } static void zone_diff_label_tree_destroy(zone_diff *diff) { ptr_set_callback_and_destroy(&diff->root.sub, zone_diff_label_tree_destroy_cb); } static zone_diff_label_tree* zone_diff_fqdn_label_find(zone_diff_label_tree* parent, const u8 *fqdn) { if(fqdn[0] != 0) { parent = zone_diff_fqdn_label_find(parent, fqdn + fqdn[0] + 1); if(parent != NULL) { ptr_node *node = ptr_set_find(&parent->sub, fqdn); parent = (zone_diff_label_tree*)node->value; } } return parent; } bool zone_diff_fqdn_has_children(zone_diff *diff, const u8 *fqdn) { zone_diff_label_tree* parent = &diff->root; parent = zone_diff_fqdn_label_find(parent, fqdn); return parent != NULL; } //#define ZONE_DIFF_FQDN_LABEL_STATE_RECORDS_EXISTED 1 //#define ZONE_DIFF_FQDN_LABEL_STATE_RECORDS_ADDED 2 //#define ZONE_DIFF_FQDN_LABEL_STATE_RECORDS_EXISTS 3 #define ZONE_DIFF_FQDN_LABEL_STATE_NONEMPTY 2 #define ZONE_DIFF_FQDN_LABEL_STATE_CHILDREN 1 static u8 zone_diff_fqdn_children_state_find(zone_diff_label_tree* parent) { u8 ret; if(parent->diff_fqdn != NULL) { ret = parent->diff_fqdn->is_apex; if(parent->diff_fqdn->children_flags_set) { ret |= parent->diff_fqdn->will_be_non_empty | parent->diff_fqdn->will_have_children; #if DYNUPDATE_DIFF_DETAILED_LOG log_debug3("zone_diff_fqdn_children_state_find(%{dnsname}) = %x (already known)", parent->diff_fqdn->fqdn, ret); #endif return ret; } } else { ret = 0; } ptr_set_iterator iter; ptr_set_iterator_init(&parent->sub, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node* node = ptr_set_iterator_next_node(&iter); zone_diff_label_tree* fqdn_node = (zone_diff_label_tree*)node->value; if(fqdn_node->diff_fqdn != NULL) { if(!fqdn_node->diff_fqdn->children_flags_set) { if(!ptr_set_isempty(&fqdn_node->sub)) { if(zone_diff_fqdn_children_state_find(fqdn_node) != 0) { // ret |= ZONE_DIFF_FQDN_LABEL_STATE_CHILDREN; fqdn_node->diff_fqdn->will_have_children = 1; } } fqdn_node->diff_fqdn->children_flags_set = 1; } ret |= fqdn_node->diff_fqdn->will_be_non_empty | fqdn_node->diff_fqdn->will_have_children; } else { if(!ptr_set_isempty(&fqdn_node->sub)) { if(zone_diff_fqdn_children_state_find(fqdn_node) != 0) { ret |= ZONE_DIFF_FQDN_LABEL_STATE_CHILDREN; } } } } #if DYNUPDATE_DIFF_DETAILED_LOG log_debug3("zone_diff_fqdn_children_state_find(%{dnsname}) = %x", parent->diff_fqdn->fqdn, ret); #endif return ret; } u8 zone_diff_fqdn_children_state(zone_diff *diff, const u8 *fqdn) { zone_diff_label_tree* fqdn_node = zone_diff_fqdn_label_find(&diff->root, fqdn); if(fqdn_node != NULL) { /* zone_diff_fqdn_children_state_parm parms; int fqdn_len = dnsname_len(fqdn); parms.fqdn = &parms.fqdn_storage[256 - fqdn_len]; memcpy(parms.fqdn, fqdn, fqdn_len); */ // if node has sub, set it // for all sub // if sub has all records removed, set it // if sub has records added, set it // if +- are both set, stop seeking (all needed answers are ready) // if sub has sub, go deeper zone_diff_fqdn_children_state_find(fqdn_node); } return 0; } /** * Finalises a zone diff * * @param diff */ static void zone_diff_finalize_cb(ptr_node *node) { zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)node->value; zone_diff_fqdn_delete(diff_fqdn); } void zone_diff_finalize(zone_diff *diff) { log_debug1("update: %{dnsname}: deleting diff @%p", diff->origin, diff); zone_diff_label_tree_destroy(diff); ptr_set_callback_and_destroy(&diff->fqdn, zone_diff_finalize_cb); } zone_diff_fqdn* zone_diff_fqdn_add_empty(zone_diff *diff, const u8 *fqdn) { ptr_node *node = ptr_set_insert(&diff->fqdn, (u8*)fqdn); if(node->value == NULL) { #if DEBUG log_debug2("update: %{dnsname} ...", fqdn); #endif zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_new(fqdn); node->key = diff_fqdn->fqdn; // to guarantee the const node->value = diff_fqdn; } return (zone_diff_fqdn*)node->value; } /** * label will be replaced ... * * @param diff * @param fqdn * @param label * @return */ zone_diff_fqdn* zone_diff_fqdn_add(zone_diff *diff, const u8 *fqdn, zdb_rr_label *label) { ptr_node *node = ptr_set_insert(&diff->fqdn, (u8*)fqdn); if(node->value == NULL) { #if DEBUG log_debug2("update: %{dnsname} (%p) ...", fqdn, label); #endif zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_new(fqdn); node->key = diff_fqdn->fqdn; // to guarantee the const node->value = diff_fqdn; zone_diff_label_tree *diff_fqdn_label = zone_diff_label_tree_add_fqdn(diff, diff_fqdn->fqdn); diff_fqdn_label->diff_fqdn = diff_fqdn; // copy all records if(label != NULL) { diff_fqdn->is_apex = zdb_rr_label_is_apex(label); diff_fqdn->at_delegation = ZDB_LABEL_ATDELEGATION(label); diff_fqdn->under_delegation = ZDB_LABEL_UNDERDELEGATION(label); diff_fqdn->had_ds = zdb_rr_label_has_rrset(label, TYPE_DS); diff_fqdn->was_at_delegation = diff_fqdn->at_delegation; diff_fqdn->was_under_delegation = diff_fqdn->under_delegation; diff_fqdn->was_non_empty = btree_notempty(label->resource_record_set); diff_fqdn->had_children = dictionary_notempty(&label->sub); //diff_fqdn->will_be_non_empty = diff_fqdn->was_non_empty; diff_fqdn->will_have_children = diff_fqdn->is_apex; diff_fqdn->will_have_ds = diff_fqdn->had_ds; diff_fqdn->children_added = 0; diff_fqdn->has_active_zsk = diff->has_active_zsk; diff_fqdn->has_active_ksk = diff->has_active_ksk; diff_fqdn->is_in_database = 1; btree_iterator iter; btree_iterator_init(label->resource_record_set, &iter); while(btree_iterator_hasnext(&iter)) { btree_node *rr_node = btree_iterator_next_node(&iter); u16 type = (u16)rr_node->hash; #if DEBUG log_debug2("update: %{dnsname} (%p) copying %{dnstype} RRSET", fqdn, label, &type); #endif zone_diff_fqdn_rr_set *rr_set = zone_diff_fqdn_rr_set_add(diff_fqdn, type); zdb_packed_ttlrdata *rr_sll = (zdb_packed_ttlrdata*)rr_node->data; yassert(rr_sll != NULL); if(rr_set->org_ttl == -1) { rr_set->org_ttl = rr_sll->ttl; } rr_set->new_ttl = rr_sll->ttl; do { zone_diff_label_rr *rr = zone_diff_label_rr_new(fqdn, type, CLASS_IN, rr_sll->ttl, ZDB_PACKEDRECORD_PTR_RDATAPTR(rr_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(rr_sll), FALSE); rr->state |= ZONE_DIFF_RR_IN_ZONE; /** rr = */ zone_diff_fqdn_rr_set_rr_add_replace(rr_set, rr); /// NOTE: there should not be any collision here rr_sll = rr_sll->next; } while(rr_sll != NULL); } } else { #if DEBUG log_debug2("update: %{dnsname} (%p) label is not in the zone", fqdn, label); #endif /* diff_fqdn->is_apex = FALSE; diff_fqdn->at_delegation = FALSE; diff_fqdn->under_delegation = FALSE; diff_fqdn->will_have_ds = FALSE; diff_fqdn->was_at_delegation = FALSE; diff_fqdn->was_under_delegation = FALSE; diff_fqdn->had_ds = FALSE; diff_fqdn->was_non_empty = FALSE; */ } } #if DEBUG else { log_debug2("update: %{dnsname} (%p) already known (add)", fqdn, label); } #endif return (zone_diff_fqdn*)node->value; } #if ZDB_HAS_NSEC3_SUPPORT zone_diff_fqdn* zone_diff_add_nsec3(zone_diff *diff, const nsec3_zone* n3, const nsec3_node *item, s32 ttl, zone_diff_fqdn_rr_set **out_nsec3_rrset) { u8 digest_len = NSEC3_NODE_DIGEST_SIZE(item); u8 fqdn[MAX_DOMAIN_LENGTH]; fqdn[0] = base32hex_lc_encode(NSEC3_NODE_DIGEST_PTR(item), digest_len, (char*)&fqdn[1]); dnsname_copy(&fqdn[fqdn[0] + 1], diff->origin); ptr_node *node = ptr_set_insert(&diff->fqdn, fqdn); if(node->value == NULL) { #if DEBUG log_debug2("update: %{dnsname} (%p) ...", fqdn, item); #endif zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_new(fqdn); node->key = diff_fqdn->fqdn; // to guarantee the const node->value = diff_fqdn; zone_diff_label_tree *diff_fqdn_label = zone_diff_label_tree_add_fqdn(diff, diff_fqdn->fqdn); diff_fqdn_label->diff_fqdn = diff_fqdn; // copy all records //diff_fqdn->is_apex = 0; //diff_fqdn->at_delegation = 0; //diff_fqdn->under_delegation = 0; //diff_fqdn->will_have_ds = 0; //diff_fqdn->was_at_delegation = 0; //diff_fqdn->was_under_delegation = 0; //diff_fqdn->had_ds = 0; diff_fqdn->was_non_empty = 1; //diff_fqdn->had_children = 0; //diff_fqdn->will_have_children = 0; //diff_fqdn->children_added = 0; diff_fqdn->is_nsec3 = 1; diff_fqdn->has_active_zsk = diff->has_active_zsk; diff_fqdn->has_active_ksk = diff->has_active_ksk; #if DEBUG log_debug2("update: %{dnsname} (%p) copying NSEC3 record", fqdn, item); #endif u32 param_rdata_size = NSEC3_ZONE_RDATA_SIZE(n3); u8 hash_len = NSEC3_NODE_DIGEST_SIZE(item); u32 type_bit_maps_size = item->type_bit_maps_size; /* Whatever the editor says: rdata_size is used. */ u32 rdata_size = param_rdata_size + 1 + hash_len + type_bit_maps_size; zone_diff_fqdn_rr_set *nsec3_rr_set = zone_diff_fqdn_rr_set_add(diff_fqdn, TYPE_NSEC3); zone_diff_label_rr *rr = zone_diff_label_rr_new_nordata(fqdn, TYPE_NSEC3, CLASS_IN, ttl, rdata_size); nsec3_zone_item_to_rdata(n3, item, rr->rdata, rdata_size); rr->state |= ZONE_DIFF_RR_IN_ZONE; zone_diff_fqdn_rr_set_rr_add_replace(nsec3_rr_set, rr); /// NOTE: there should not be any collision here if(out_nsec3_rrset != NULL) { *out_nsec3_rrset = nsec3_rr_set; } zdb_packed_ttlrdata *nsec3_rrsig_rr_sll = (zdb_packed_ttlrdata*)item->rrsig; if(nsec3_rrsig_rr_sll != NULL) { zone_diff_fqdn_rr_set *nsec3_rrsig_rr_set = zone_diff_fqdn_rr_set_add(diff_fqdn, TYPE_RRSIG); nsec3_rrsig_rr_set->org_ttl = ttl; nsec3_rrsig_rr_set->new_ttl = ttl; while(nsec3_rrsig_rr_sll != NULL) { zone_diff_label_rr *new_rr = zone_diff_label_rr_new(fqdn, TYPE_RRSIG, CLASS_IN, ttl, ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec3_rrsig_rr_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(nsec3_rrsig_rr_sll), FALSE); new_rr->state |= ZONE_DIFF_RR_IN_ZONE; /** rr = */ zone_diff_fqdn_rr_set_rr_add_replace(nsec3_rrsig_rr_set, new_rr); /// NOTE: there should not be any collision here nsec3_rrsig_rr_sll = nsec3_rrsig_rr_sll->next; } } } #if DEBUG else { log_debug2("update: %{dnsname} (%p) already known (add nsec3)", fqdn, item); } #endif return (zone_diff_fqdn*)node->value; } zone_diff_fqdn* zone_diff_add_nsec3_ex(zone_diff *diff, const ptr_vector *zsk_keys, const nsec3_zone* n3, const nsec3_node *item, s32 ttl, zone_diff_fqdn_rr_set **out_nsec3_rrset, s32 now, s32 regeneration) { u8 digest_len = NSEC3_NODE_DIGEST_SIZE(item); u8 fqdn[MAX_DOMAIN_LENGTH]; fqdn[0] = base32hex_lc_encode(NSEC3_NODE_DIGEST_PTR(item), digest_len, (char*)&fqdn[1]); dnsname_copy(&fqdn[fqdn[0] + 1], diff->origin); ptr_node *node = ptr_set_insert(&diff->fqdn, fqdn); if(node->value == NULL) { #if DEBUG log_debug2("update: %{dnsname} (%p) ...", fqdn, item); #endif zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_new(fqdn); node->key = diff_fqdn->fqdn; // to guarantee the const node->value = diff_fqdn; zone_diff_label_tree *diff_fqdn_label = zone_diff_label_tree_add_fqdn(diff, diff_fqdn->fqdn); diff_fqdn_label->diff_fqdn = diff_fqdn; // copy all records //diff_fqdn->is_apex = 0; //diff_fqdn->at_delegation = 0; //diff_fqdn->under_delegation = 0; //diff_fqdn->will_have_ds = 0; //diff_fqdn->was_at_delegation = 0; //diff_fqdn->was_under_delegation = 0; //diff_fqdn->had_ds = 0; diff_fqdn->was_non_empty = 1; //diff_fqdn->had_children = 0; //diff_fqdn->will_have_children = 0; //diff_fqdn->children_added = 0; diff_fqdn->is_nsec3 = 1; diff_fqdn->has_active_zsk = diff->has_active_zsk; diff_fqdn->has_active_ksk = diff->has_active_ksk; #if DEBUG log_debug2("update: %{dnsname} (%p) copying NSEC3 record", fqdn, item); #endif u32 param_rdata_size = NSEC3_ZONE_RDATA_SIZE(n3); u8 hash_len = NSEC3_NODE_DIGEST_SIZE(item); u32 type_bit_maps_size = item->type_bit_maps_size; /* Whatever the editor says: rdata_size is used. */ u32 rdata_size = param_rdata_size + 1 + hash_len + type_bit_maps_size; zone_diff_fqdn_rr_set *nsec3_rr_set = zone_diff_fqdn_rr_set_add(diff_fqdn, TYPE_NSEC3); zone_diff_label_rr *rr = zone_diff_label_rr_new_nordata(fqdn, TYPE_NSEC3, CLASS_IN, ttl, rdata_size); nsec3_zone_item_to_rdata(n3, item, rr->rdata, rdata_size); rr->state |= ZONE_DIFF_RR_IN_ZONE; zone_diff_fqdn_rr_set_rr_add_replace(nsec3_rr_set, rr); /// NOTE: there should not be any collision here if(out_nsec3_rrset != NULL) { *out_nsec3_rrset = nsec3_rr_set; } zdb_packed_ttlrdata *nsec3_rrsig_rr_sll = (zdb_packed_ttlrdata*)item->rrsig; if(nsec3_rrsig_rr_sll != NULL) { zone_diff_fqdn_rr_set *nsec3_rrsig_rr_set = zone_diff_fqdn_rr_set_add(diff_fqdn, TYPE_RRSIG); nsec3_rrsig_rr_set->org_ttl = ttl; nsec3_rrsig_rr_set->new_ttl = ttl; while(nsec3_rrsig_rr_sll != NULL) { zone_diff_label_rr *new_rr = zone_diff_label_rr_new(fqdn, TYPE_RRSIG, CLASS_IN, ttl, ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec3_rrsig_rr_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(nsec3_rrsig_rr_sll), FALSE); new_rr->state |= ZONE_DIFF_RR_IN_ZONE; s32 matching_key_index = -2; if(rrsig_should_remove_signature_from_rdata( ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec3_rrsig_rr_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(nsec3_rrsig_rr_sll), zsk_keys, now, regeneration, &matching_key_index) /* unnecessary: || (matching_key_index == -1)*/) { new_rr->state |= ZONE_DIFF_RR_REMOVE; } /** rr = */ zone_diff_fqdn_rr_set_rr_add_replace(nsec3_rrsig_rr_set, new_rr); /// NOTE: there should not be any collision here nsec3_rrsig_rr_sll = nsec3_rrsig_rr_sll->next; } } } #if DEBUG else { log_debug2("update: %{dnsname} (%p) already known (add nsec3 ex)", fqdn, item); } #endif return (zone_diff_fqdn*)node->value; } #endif // HAS_NSEC3_SUPPORT zone_diff_fqdn* zone_diff_add_static_fqdn(zone_diff *diff, const u8 *fqdn, zdb_rr_label *label) { zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_add(diff, fqdn, label); diff_fqdn->will_be_non_empty = diff_fqdn->was_non_empty; diff_fqdn->will_have_children = diff_fqdn->had_children; diff_fqdn->will_have_ds = diff_fqdn->had_ds && diff_fqdn->at_delegation; if(diff_fqdn->will_have_ds != diff_fqdn->had_ds) { // may be looking at a broken zone // it it only contains DS records (and RRSIG records) then it should be marked empty btree_iterator iter; btree_iterator_init(label->resource_record_set, &iter); while(btree_iterator_hasnext(&iter)) { btree_node *rr_node = btree_iterator_next_node(&iter); u16 type = (u16)rr_node->hash; if((type != TYPE_RRSIG) && (type != TYPE_DS)) { return diff_fqdn; } } // the label will be emptied by validation later, the the NSEC3 chain doesn't know that yet. log_warn("update: %{dnsname}: %{dnsname} label only contained DS and RRSIG resource record sets: they will be removed", diff->origin, fqdn); diff_fqdn->will_be_non_empty = 0; } return diff_fqdn; } void zone_diff_add_fqdn_children(zone_diff *diff, const u8 *fqdn, zdb_rr_label *label) { dictionary_iterator iter; u8 sub_fqdn[MAX_DOMAIN_LENGTH]; dictionary_iterator_init(&label->sub, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_rr_label *sub_label = *(zdb_rr_label**)dictionary_iterator_next(&iter); dnsname_copy(&sub_fqdn[dnslabel_copy(sub_fqdn, sub_label->name)], fqdn); zone_diff_fqdn *parent = zone_diff_fqdn_add(diff, sub_fqdn, sub_label); parent->children_added = 1; if(dictionary_notempty(&sub_label->sub)) { zone_diff_add_fqdn_children(diff, sub_fqdn, sub_label); } } } void zone_diff_add_fqdn_parents_up_to_below_apex(zone_diff *diff, const u8 *fqdn, zdb_zone *zone) { size_t origin_len = dnsname_len(diff->origin); fqdn += fqdn[0] + 1; while(dnsname_len(fqdn) > origin_len) { zdb_rr_label *fqdn_label = zdb_rr_label_find_from_name(zone, fqdn); zone_diff_fqdn *parent = zone_diff_fqdn_add(diff, fqdn, fqdn_label); parent->children_added = 1; fqdn += fqdn[0] + 1; } } /** * Enables the or_state flags in every record of the set. * * @param rrset * @param or_state */ void zone_diff_fqdn_rr_set_set_state(zone_diff_fqdn_rr_set *rrset, u8 or_state) { ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; rr->state |= or_state; } } /** * Returns true iff an rrset of the given type will be present after applying * the diff. * * @param diff_fqdn * @param rtype * @return */ bool zone_diff_will_have_rrset_type(const zone_diff_fqdn *diff_fqdn, u16 rtype) { u32_node *rrset_node = u32_set_find(&diff_fqdn->rrset, rtype); if(rrset_node != NULL) { zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)rrset_node->value; // @note 20170228 edf -- issue detection // If this aborts, it's likely somebody called zone_diff_fqdn_rr_get without // the intent of putting records in it. // Find it and call zone_diff_will_have_rrset_type instead. yassert(rrset != NULL); ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & ZONE_DIFF_RR_REMOVE) == 0) { // this record was present or is being added return TRUE; } } } return FALSE; } bool zone_diff_remove_rrsig_covering_type(zone_diff_fqdn *diff_fqdn, u16 rtype) { u32_node *rrsig_rrset_node = u32_set_find(&diff_fqdn->rrset, TYPE_RRSIG); if(rrsig_rrset_node != NULL) { zone_diff_fqdn_rr_set *rrsig_rrset = (zone_diff_fqdn_rr_set*)rrsig_rrset_node->value; // @note 20170228 edf -- issue detection // If this aborts, it's likely somebody called zone_diff_fqdn_rr_get without // the intent of putting records in it. // Find it and call zone_diff_will_have_rrset_type instead. yassert(rrsig_rrset != NULL); ptr_vector to_remove = PTR_VECTOR_EMPTY; ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrsig_rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)node->key; if(rrsig_get_type_covered_from_rdata(rr->rdata, rr->rdata_size) == rtype) { if((rr->state & ZONE_DIFF_RR_IN_ZONE) != 0) // did exist ? { // remove rr->state |= ZONE_DIFF_RR_REMOVE; log_debug2("update: %{dnsname} RRSIG covering %{dnstype} record will be removed from zone", rr->fqdn, &rtype); } else if((rr->state & ZONE_DIFF_RR_ADD) != 0) // was being added ? { // remove the entry instead (postponed) ptr_vector_append(&to_remove, rr); log_debug2("update: %{dnsname} RRSIG covering %{dnstype} record will not be added to zone", rr->fqdn, &rtype); } else { // log_warn("update: %{dnsname} RRSIG covering %{dnstype} record has state %02x, which is not expected", rr->fqdn, &rtype, rr->state); } } } for(int i = 0; i <= ptr_vector_last_index(&to_remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&to_remove, i); ptr_set_delete(&rrsig_rrset->rr, rr); zone_diff_label_rr_delete(rr); } if(ptr_set_isempty(&rrsig_rrset->rr)) { u32_set_delete(&diff_fqdn->rrset, TYPE_RRSIG); } ptr_vector_destroy(&to_remove); } return FALSE; } /** * * Removes existing records as well as cancels additions of new ones. * * This is called by zone_diff_validate. * This means there is no rrset_to_sign collection yet. * */ bool zone_diff_remove_rrset_type(zone_diff_fqdn *diff_fqdn, u16 rtype) { u32_node *rrset_node = u32_set_find(&diff_fqdn->rrset, rtype); if(rrset_node != NULL) { zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)rrset_node->value; // @note 20170228 edf -- issue detection // If this aborts, it's likely somebody called zone_diff_fqdn_rr_get without // the intent of putting records in it. // Find it and call zone_diff_will_have_rrset_type instead. yassert(rrset != NULL); ptr_vector to_remove = PTR_VECTOR_EMPTY; ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)node->key; if((rr->state & ZONE_DIFF_RR_IN_ZONE) != 0) // did exist ? { // remove rr->state |= ZONE_DIFF_RR_REMOVE; log_debug2("update: %{dnsname} %{dnstype} record will be removed from zone", rr->fqdn, &rtype); } else if((rr->state & ZONE_DIFF_RR_ADD) != 0) // was being added ? { // remove the entry instead (postponed) ptr_vector_append(&to_remove, rr); log_debug2("update: %{dnsname} %{dnstype} record will not be added to zone", rr->fqdn, &rtype); } else { // log_warn("update: %{dnsname} %{dnstype} record has state %02x, which is not expected", rr->fqdn, &rtype, rr->state); } } for(int i = 0; i <= ptr_vector_last_index(&to_remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&to_remove, i); ptr_set_delete(&rrset->rr, rr); zone_diff_label_rr_delete(rr); } if(ptr_vector_last_index(&to_remove) >= 0) { if(ptr_set_isempty(&rrset->rr)) { u32_set_delete(&diff_fqdn->rrset, rtype); } zone_diff_remove_rrsig_covering_type(diff_fqdn, rtype); } ptr_vector_destroy(&to_remove); } return FALSE; } /** * Returns true iff a DNSKEY with these exact parameters will be present in the zone after the diff. * * @param diff_fqdn * @param algorithm * @param flags * @param tag * @return */ bool zone_diff_will_have_dnskey_with_algorithm_flags_tag(const zone_diff_fqdn *diff_fqdn, u8 algorithm, u16 flags, u16 tag) { u32_node *rrset_node = u32_set_find(&diff_fqdn->rrset, TYPE_DNSKEY); if(rrset_node != NULL) { zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)rrset_node->value; // @note 20170228 edf -- issue detection // If this aborts, it's likely somebody called zone_diff_fqdn_rr_get without // the intent of putting records in it. // Find it and call zone_diff_will_have_rrset_type instead. yassert(rrset != NULL); ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & ZONE_DIFF_RR_REMOVE) == 0) { // this record was present or is being added if(rr->rdata_size > 3) { if(dnskey_get_algorithm_from_rdata(rr->rdata) == algorithm) { if(dnskey_get_flags_from_rdata(rr->rdata) == flags) { if(dnskey_get_tag_from_rdata(rr->rdata, rr->rdata_size) == tag) { return TRUE; } } } } } } } return FALSE; } /** * Returns true iff a DNSKEY with these exact parameters will be present in the zone after the diff. * * @param diff_fqdn * @param algorithm * @param flags * @param tag * @return */ bool zone_diff_will_have_dnskey_with_algorithm_tag(const zone_diff_fqdn *diff_fqdn, u8 algorithm, u16 tag) { u32_node *rrset_node = u32_set_find(&diff_fqdn->rrset, TYPE_DNSKEY); if(rrset_node != NULL) { zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)rrset_node->value; // @note 20170228 edf -- issue detection // If this aborts, it's likely somebody called zone_diff_fqdn_rr_get without // the intent of putting records in it. // Find it and call zone_diff_will_have_rrset_type instead. yassert(rrset != NULL); ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & ZONE_DIFF_RR_REMOVE) == 0) { // this record was present or is being added if(rr->rdata_size > 3) { if(dnskey_get_algorithm_from_rdata(rr->rdata) == algorithm) { if(dnskey_get_tag_from_rdata(rr->rdata, rr->rdata_size) == tag) { return TRUE; } } } } } } return FALSE; } /** * Releases keys that will not be in the apex after the diff is applied. * * @param diff * @param keys */ void zone_diff_filter_out_keys(const zone_diff *diff, ptr_vector *keys) { const zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_get_const(diff, diff->origin); if(diff_fqdn != NULL) { for(int i = 0; i <= ptr_vector_last_index(keys); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(keys, i); #if !DEBUG if(!dnskey_is_private(key) || !zone_diff_will_have_dnskey_with_algorithm_flags_tag(diff_fqdn, dnskey_get_algorithm( key), dnskey_get_flags(key), dnskey_get_tag(key))) { ptr_vector_end_swap(keys, i); ptr_vector_pop(keys); dnskey_release(key); } #else /*if(!dnskey_is_private(key)) { log_debug3("zone_diff_filter_out_keys: 'K%{dnsname}+%03d+%05hd' is not private", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); ptr_vector_end_swap(keys, i); ptr_vector_pop(keys); dnskey_release(key); } else*/ if(!zone_diff_will_have_dnskey_with_algorithm_flags_tag(diff_fqdn, dnskey_get_algorithm(key), dnskey_get_flags(key), dnskey_get_tag(key))) { log_debug3("zone_diff_filter_out_keys: 'K%{dnsname}+%03d+%05hd' will not be in the zone", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); ptr_vector_end_swap(keys, i); ptr_vector_pop(keys); dnskey_release(key); } #endif } } } /** * find label for fqdn ... * * @param diff * @param fqdn * @param label * @return */ const zone_diff_fqdn* zone_diff_fqdn_get_const(const zone_diff *diff, const u8 *fqdn) { zone_diff_fqdn *ret = NULL; ptr_node *node = ptr_set_find(&diff->fqdn, (u8*)fqdn); if(node != NULL) { ret = (zone_diff_fqdn*)node->value; } return ret; } zone_diff_fqdn* zone_diff_fqdn_get(const zone_diff *diff, const u8 *fqdn) { zone_diff_fqdn *ret = NULL; ptr_node *node = ptr_set_find(&diff->fqdn, (u8*)fqdn); if(node != NULL) { ret = (zone_diff_fqdn*)node->value; } return ret; } /** * Generates a type bit map based on the diff including records matching: * * (status & mask) == masked * * mask,masked * all pre records : ZONE_DIFF_REMOVE|ZONE_DIFF_ADD == 0 * all post records: ZONE_DIFF_REMOVE = 0 * * Note: it ignores A and AAAA records at or under a delegation * * @param diff * @param fqdn * @param bitmap * @param mask * @param masked * @return */ u16 zone_diff_type_bit_map_generate(const zone_diff *diff, const u8 *fqdn, type_bit_maps_context *bitmap, u8 mask, u8 masked, const u8 *chain_node_fqdn, bool append_existing_signatures) { type_bit_maps_init(bitmap); const zone_diff_fqdn* zdf = zone_diff_fqdn_get_const(diff, fqdn); if(zdf != NULL) { if(zdf->at_delegation || zdf->under_delegation) { ptr_set_iterator rr_iter; u32_set_iterator iter; u32_set_iterator_init(&zdf->rrset, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); u16 rtype = (u16)node->key; if((rtype == TYPE_A) || (rtype == TYPE_AAAA)) { continue; } zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)node->value; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & mask) == masked) { log_debug1("update: %{dnsname}: %{dnsname}: %x: %{dnstype}", diff->origin, chain_node_fqdn, mask, &rtype); type_bit_maps_set_type(bitmap, rtype); break; } } } } else { ptr_set_iterator rr_iter; u32_set_iterator iter; u32_set_iterator_init(&zdf->rrset, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); u16 rtype = (u16)node->key; zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)node->value; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & mask) == masked) { log_debug1("update: %{dnsname}: %{dnsname}: %x: %{dnstype}", diff->origin, chain_node_fqdn, mask, &rtype); type_bit_maps_set_type(bitmap, rtype); break; } } } } if(append_existing_signatures) { if((zdf->rrsig_kept == 0) && zdf->rrsig_added) { type_bit_maps_set_type(bitmap, TYPE_RRSIG); } } } else { log_debug1("update: %{dnsname}: %{dnsname}: %x: no matching fqdn in the diff", diff->origin, chain_node_fqdn, mask); } u16 bitmap_size = type_bit_maps_update_size(bitmap); return bitmap_size; } /** * Adds a record on a diff * * * @param diff * @param rr_label * @param fqdn * @param rtype * @param rttl * @param rdata_size * @param rdata */ zone_diff_label_rr* zone_diff_record_add(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn, u16 rtype, s32 rttl, u16 rdata_size, void *rdata) { zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_add(diff, fqdn, rr_label); zone_diff_fqdn_rr_set *rr_set = zone_diff_fqdn_rr_set_add(diff_fqdn, rtype); zone_diff_label_rr *rr = zone_diff_label_rr_new(fqdn, rtype, CLASS_IN, rttl, rdata, rdata_size, TRUE); rr = zone_diff_fqdn_rr_set_rr_add_get(rr_set, rr); #if DEBUG rdata_desc rd = {rtype, rdata_size, rdata}; log_debug2("update: %{dnsname}: will add [%02x] %{dnsname} %5i %{typerdatadesc}", diff->origin, rr->state, fqdn, rttl, &rd); #endif if( ((rr->state & ZONE_DIFF_RR_IN_ZONE) != 0) && ((rr->state & ZONE_DIFF_RR_REMOVE) != 0) ) { //rr->state |= ZONE_DIFF_RR_ADD; rr->state &= ~ZONE_DIFF_RR_REMOVE; #if DEBUG log_debug2("update: %{dnsname}: will add [%02x] %{dnsname} %5i %{typerdatadesc} (no add needed, cleared del)", diff->origin, rr->state, fqdn, rttl, &rd); #endif } else if( ((rr->state & ZONE_DIFF_RR_IN_ZONE) == 0) || ((rr->state & ZONE_DIFF_RR_REMOVE) != 0) ) { rr->state |= ZONE_DIFF_RR_ADD; #if DEBUG log_debug2("update: %{dnsname}: will add [%02x] %{dnsname} %5i %{typerdatadesc} (set add)", diff->origin, rr->state, fqdn, rttl, &rd); #endif } return rr; } /** * * Adds the removal of a specific record on a diff * * @param diff * @param rr_label * @param fqdn * @param rtype * @param rttl * @param rdata_size * @param rdata */ void zone_diff_record_remove(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn, u16 rtype, s32 rttl, u16 rdata_size, void *rdata) { #if DEBUG rdata_desc rd = {rtype, rdata_size, rdata}; log_debug2("update: %{dnsname}: will del %{dnsname} %5i %{typerdatadesc}", diff->origin, fqdn, rttl, &rd); #endif (void)rttl; zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_add(diff, fqdn, rr_label); zone_diff_fqdn_rr_set *rr_set = zone_diff_fqdn_rr_set_add(diff_fqdn, rtype); zone_diff_label_rr *rr = zone_diff_label_rr_new(fqdn, rtype, CLASS_IN, 0, rdata, rdata_size, TRUE); rr = zone_diff_fqdn_rr_set_rr_add_get(rr_set, rr); rr->state |= ZONE_DIFF_RR_REMOVE; } bool zone_diff_record_remove_existing(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn, u16 rtype, s32 rttl, u16 rdata_size, void *rdata) { #if DEBUG rdata_desc rd = {rtype, rdata_size, rdata}; log_debug2("update: %{dnsname}: will del %{dnsname} %5i %{typerdatadesc}", diff->origin, fqdn, rttl, &rd); #endif (void)rttl; zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_add(diff, fqdn, rr_label); zone_diff_fqdn_rr_set *rr_set = zone_diff_fqdn_rr_set_get(diff_fqdn, rtype); if(rr_set != NULL) { zone_diff_label_rr tmp_rr; zone_diff_label_rr_init_tmp(&tmp_rr, fqdn, rtype, CLASS_IN, 0, rdata, rdata_size); zone_diff_label_rr *rr = zone_diff_fqdn_rr_set_get_existing_rr(rr_set, &tmp_rr); if(rr != NULL) { rr->state |= ZONE_DIFF_RR_REMOVE; return TRUE; } } return FALSE; } void zone_diff_record_remove_automated(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn, u16 rtype, s32 rttl, u16 rdata_size, void *rdata) { #if DEBUG rdata_desc rd = {rtype, rdata_size, rdata}; log_debug2("update: %{dnsname}: will del %{dnsname} %5i %{typerdatadesc}", diff->origin, fqdn, rttl, &rd); #endif (void)rttl; zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_add(diff, fqdn, rr_label); zone_diff_fqdn_rr_set *rr_set = zone_diff_fqdn_rr_set_add(diff_fqdn, rtype); zone_diff_label_rr *rr = zone_diff_label_rr_new(fqdn, rtype, CLASS_IN, 0, rdata, rdata_size, TRUE); rr = zone_diff_fqdn_rr_set_rr_add_get(rr_set, rr); rr->state |= ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_AUTOMATED; } /** * Adds the removal of a record set on a diff * * @param diff * @param rr_label * @param fqdn * @param rtype */ void zone_diff_record_remove_all(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn, u16 rtype) { zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_add(diff, fqdn, rr_label); zone_diff_fqdn_rr_set *rr_set = zone_diff_fqdn_rr_set_add(diff_fqdn, rtype); ptr_set_iterator iter; ptr_set_iterator_init(&rr_set->rr, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; rr->state |= ZONE_DIFF_RR_REMOVE; } } /** * Adds the removal all record sets on a diff * * @param diff * @param rr_label * @param fqdn * @param rtype */ void zone_diff_record_remove_all_sets(zone_diff *diff, zdb_rr_label *rr_label, const u8 *fqdn) { zone_diff_fqdn *diff_fqdn = zone_diff_fqdn_add(diff, fqdn, rr_label); u32_set_iterator typeiter; u32_set_iterator_init(&diff_fqdn->rrset, &typeiter); while(u32_set_iterator_hasnext(&typeiter)) { u32_node* node = u32_set_iterator_next_node(&typeiter); yassert((node != NULL) && (node->value != NULL)); zone_diff_fqdn_rr_set *rr_set = (zone_diff_fqdn_rr_set*)node->value; ptr_set_iterator iter; ptr_set_iterator_init(&rr_set->rr, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; rr->state |= ZONE_DIFF_RR_REMOVE; } } } /** * Adds the SOA records for the incremental update. * * @param diff * @return */ ya_result zone_diff_set_soa(zone_diff *diff, zdb_rr_label *label) { /************************************************************************** * SOA HANDLING **************************************************************************/ // check the SOA // expects 1 record, "removed", then add 1 added with incremented serial // else one and only one should be seen as "added" (and not removed), then do nothing // else still add 1 added incremented serial // if one (and only one, more being an error) SOA is marked as added, then do nothing // else add one with incremented serial based on the highest found serial zone_diff_fqdn *apex = zone_diff_fqdn_add(diff, diff->origin, label); zone_diff_fqdn_rr_set *soa_rrset = zone_diff_fqdn_rr_set_add(apex, TYPE_SOA); //ptr_set_iterator fqdn_iter; ptr_set_iterator rr_iter; zone_diff_label_rr *rr_soa_removed = NULL; zone_diff_label_rr *rr_soa_added = NULL; u32 soa_latest_serial; ya_result ret; ptr_set_iterator_init(&soa_rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; #if DEBUG rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug1("update: %{dnsname}: SOA[%x] %{dnsname} %9i %{typerdatadesc}", diff->origin, rr->state, rr->fqdn, rr->ttl, &rd); #endif if(rr->state & ZONE_DIFF_RR_REMOVE) { u32 soa_serial; if(FAIL(ret = rr_soa_get_serial(rr->rdata, rr->rdata_size, &soa_serial))) { // error return ret; } if(rr_soa_removed == NULL) { soa_latest_serial = soa_serial; rr_soa_removed = rr; } else { soa_latest_serial = serial_max(soa_latest_serial, soa_serial); // soa_latest_serial is initialized if(serial_lt(soa_latest_serial, soa_serial)) { rr_soa_removed = rr; } } } if((rr->state & (ZONE_DIFF_RR_ADD | ZONE_DIFF_RR_REMOVE)) == ZONE_DIFF_RR_ADD) // VS false positive: rr is a key and can't be NULL { if(rr_soa_added != NULL) { return INVALID_STATE_ERROR; // two SOA added ... } rr_soa_added = rr; } } if(rr_soa_removed == NULL) { return INVALID_STATE_ERROR; } if(rr_soa_added != NULL) { u32 soa_serial; if(FAIL(ret = rr_soa_get_serial(rr_soa_added->rdata, rr_soa_added->rdata_size, &soa_serial))) { // error return ret; } if(serial_le(soa_serial, soa_latest_serial)) // soa_latest_serial is initialized { // error return INVALID_STATE_ERROR; } } else { // add the SOA add record #if C11_VLA_AVAILABLE u8 tmp_rdata[rr_soa_removed->rdata_size]; #else u8* const tmp_rdata = (u8* const)stack_alloc(rr_soa_removed->rdata_size); #endif memcpy(tmp_rdata, rr_soa_removed->rdata, rr_soa_removed->rdata_size); rr_soa_increase_serial(tmp_rdata, rr_soa_removed->rdata_size, 1); rr_soa_added = zone_diff_label_rr_new(rr_soa_removed->fqdn, TYPE_SOA, CLASS_IN, rr_soa_removed->ttl, tmp_rdata, rr_soa_removed->rdata_size, TRUE); rr_soa_added = zone_diff_fqdn_rr_set_rr_add_get(soa_rrset, rr_soa_added); // add_get rr_soa_added->state |= ZONE_DIFF_RR_ADD | ZONE_DIFF_RR_AUTOMATED; } return SUCCESS; } /** * Updates status and validates a diff. * * @param diff * @return */ ya_result zone_diff_validate(zone_diff *diff) { ptr_set_iterator fqdn_iter; ptr_vector diff_fqdn_to_remove = EMPTY_PTR_VECTOR; ptr_set_iterator_init(&diff->fqdn, &fqdn_iter); while(ptr_set_iterator_hasnext(&fqdn_iter)) { ptr_node *diff_fqdn_node = ptr_set_iterator_next_node(&fqdn_iter); const u8 *diff_fqdn_name = (const u8*)diff_fqdn_node->key; zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; // update status flags // do validation tests log_debug2("update: %{dnsname}: validating %{dnsname}", diff->origin, diff_fqdn_name); if(diff_fqdn->is_apex) { // only check for CNAME if(zone_diff_will_have_rrset_type(diff_fqdn, TYPE_CNAME)) { log_err("update: %{dnsname}: update would add CNAME on apex", diff->origin); //dnssec_chain_finalize(&dc); return INVALID_STATE_ERROR; } } else { // check for CNAME // update under-delegation // // for all labels above, look in the diff if they are present and if their delegation status will be changed bool under_delegation = FALSE; const u8 *above_fqdn = diff_fqdn->fqdn; bool is_right_above = TRUE; while(*above_fqdn != 0) { above_fqdn += *above_fqdn + 1; const zone_diff_fqdn *parent = zone_diff_fqdn_get_const(diff, above_fqdn); if(parent != NULL) { if(parent->is_apex) { break; } if(is_right_above) { if((parent->was_at_delegation || parent->was_under_delegation) && !diff_fqdn->was_under_delegation) { // then we are at delegation #if DEBUG if(diff_fqdn->is_in_database) { log_warn("update: %{dnsname}: %{dnsname} expected to be marked as being under delegation in the database as %{dnsname} at=%i under=%i (fixing)", diff->origin, diff_fqdn->fqdn, parent->fqdn, parent->was_at_delegation, parent->was_under_delegation); } #endif diff_fqdn->was_under_delegation = TRUE; } else if(!((parent->was_at_delegation || parent->was_under_delegation)) && diff_fqdn->was_under_delegation) { // then we are at delegation #if DEBUG if(diff_fqdn->is_in_database) { log_warn("update: %{dnsname}: %{dnsname} not expected to be marked as being under delegation in the database as %{dnsname} at=%i under=%i (fixing)", diff->origin, diff_fqdn->fqdn, parent->fqdn, parent->was_at_delegation, parent->was_under_delegation); } #endif diff_fqdn->was_under_delegation = FALSE; } is_right_above = FALSE; } if(parent->under_delegation) { if(!diff_fqdn->under_delegation) { log_debug("update: %{dnsname}: %{dnsname} under under delegation %{dnsname}", diff->origin, diff_fqdn->fqdn, parent->fqdn); } under_delegation = TRUE; break; } if(parent->at_delegation) { if(!diff_fqdn->under_delegation) { log_debug1("update: %{dnsname}: %{dnsname} under delegation %{dnsname}", diff->origin, diff_fqdn->fqdn, parent->fqdn); } under_delegation = TRUE; break; } } /*else { under_delegation = diff_fqdn->under_delegation; }*/ } if(diff_fqdn->under_delegation && !under_delegation) { log_debug1("update: %{dnsname}: %{dnsname} not under delegation anymore", diff->origin, diff_fqdn->fqdn); } diff_fqdn->under_delegation = under_delegation; // update delegation // // if(zone_diff_will_have_rrset_type(diff_fqdn, TYPE_NS)) { diff_fqdn->at_delegation = TRUE; // check there will be only glue records under this level } else { diff_fqdn->at_delegation = FALSE; } diff_fqdn->will_have_ds = zone_diff_will_have_rrset_type(diff_fqdn, TYPE_DS); if(diff_fqdn->will_have_ds && !diff_fqdn->at_delegation) { log_debug1("update: %{dnsname}: %{dnsname} will have a DS but no NS : removing all DS", diff->origin, diff_fqdn->fqdn); zone_diff_remove_rrset_type(diff_fqdn, TYPE_DS); diff_fqdn->will_have_ds = 0; if(u32_set_isempty(&diff_fqdn->rrset)) { ptr_vector_append(&diff_fqdn_to_remove, diff_fqdn_node); } } } log_debug2("update: %{dnsname}: validating %{dnsname}: apex=%i at=%i under=%i ds=%i was-at=%i was-under=%i had-ds=%i", diff->origin, diff_fqdn_name, diff_fqdn->is_apex, diff_fqdn->at_delegation, diff_fqdn->under_delegation, diff_fqdn->will_have_ds, diff_fqdn->was_at_delegation, diff_fqdn->was_under_delegation, diff_fqdn->had_ds ); } for(int i = 0; i <= ptr_vector_last_index(&diff_fqdn_to_remove); ++i) { ptr_node *diff_fqdn_node = (ptr_node*)ptr_vector_get(&diff_fqdn_to_remove, i); //const u8 *diff_fqdn_name = (const u8*)diff_fqdn_node->key; zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; ptr_set_delete(&diff->fqdn, diff_fqdn->fqdn); // remove the node // if diff_fqdn is not in the database // from diff->root, remove the fqdn with attention to empty terminal not in the database // and // zone_diff_fqdn_delete(diff_fqdn); // delete the data } ptr_vector_destroy(&diff_fqdn_to_remove); return SUCCESS; } struct zone_diff_get_changes_update_rr_parm { u8 changes; bool rrset_removed; bool rrset_new; bool all_rrset_added; bool all_rrset_removed; bool non_empty; }; static void zone_diff_get_changes_update_rrsig_rr(zone_diff_fqdn_rr_set *rr_set, struct zone_diff_get_changes_update_rr_parm *parm, ptr_vector *remove, ptr_vector *add) { u8 changes = parm->changes; bool rrset_removed = parm->rrset_removed; bool all_rrset_added = parm->all_rrset_added; bool all_rrset_removed = parm->all_rrset_removed; bool rrset_new = TRUE; ptr_set_iterator rr_iter; // for all marked rr ptr_set_iterator_init(&rr_set->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)rr_node->value; yassert(rr->rtype == TYPE_RRSIG); if((rr->state & (ZONE_DIFF_RR_IN_ZONE|ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_ADDED)) == ZONE_DIFF_RR_ADD) { // add #if DEBUG rdata_desc rrsig_rr_rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug1("update: add %w %{dnsname} %9i %{typerdatadesc} (zone_diff_get_changes_update_rrsig_rr %p)", &temp_fw_0, rr->fqdn, rr->ttl, &rrsig_rr_rd, rr); #endif ptr_vector_append(add, rr); rr->state |= ZONE_DIFF_RR_ADDED; // proceed with the chain if needed changes |= ZONE_DIFF_CHANGES_ADD; rrset_removed = FALSE; all_rrset_removed = FALSE; } else if((rr->state & (ZONE_DIFF_RR_IN_ZONE|ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_REMOVED)) == (ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_IN_ZONE)) { // remove #if DEBUG rdata_desc rrsig_rr_rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug1("update: del %w %{dnsname} %9i %{typerdatadesc} (zone_diff_get_changes_update_rrsig_rr %p)", &temp_fw_0, rr->fqdn, rr->ttl, &rrsig_rr_rd, rr); #endif ptr_vector_append(remove, rr); rr->state |= ZONE_DIFF_RR_REMOVED; // proceed with the chain if needed changes |= ZONE_DIFF_CHANGES_REMOVE; all_rrset_added = FALSE; } else if((rr->state & (ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE)) == 0) { // stays #if DEBUG rdata_desc rrsig_rr_rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug1("update: nop %w %{dnsname} %9i %{typerdatadesc} (zone_diff_get_changes_update_rrsig_rr %p)", &temp_fw_0, rr->fqdn, rr->ttl, &rrsig_rr_rd, rr); #endif changes |= ZONE_DIFF_CHANGES_KEPT; rrset_removed = FALSE; all_rrset_removed = FALSE; all_rrset_added = FALSE; rrset_new = TRUE; } else { #if DEBUG rdata_desc rrsig_rr_rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug1("update: ign %w %{dnsname} %9i %{typerdatadesc} (zone_diff_get_changes_update_rrsig_rr %p)", &temp_fw_0, rr->fqdn, rr->ttl, &rrsig_rr_rd, rr); #endif } } parm->changes = changes; parm->rrset_removed = rrset_removed; parm->rrset_new = rrset_new; parm->all_rrset_added = all_rrset_added; parm->all_rrset_removed = all_rrset_removed; } static void zone_diff_get_changes_update_rr(zone_diff_fqdn_rr_set *rr_set, struct zone_diff_get_changes_update_rr_parm *parm, ptr_vector *remove, ptr_vector *add) { u8 changes = parm->changes; bool rrset_removed = parm->rrset_removed; bool all_rrset_added = parm->all_rrset_added; bool all_rrset_removed = parm->all_rrset_removed; bool non_empty = parm->non_empty; ptr_set_iterator rr_iter; // for all marked rr ptr_set_iterator_init(&rr_set->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)rr_node->value; if((rr->state & (ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_ADDED)) == ZONE_DIFF_RR_ADD) { // add #if DEBUG rdata_desc rrsig_rr_rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug1("update: add %w %{dnsname} %9i %{typerdatadesc} (zone_diff_get_changes_update_rr %p)", &temp_fw_0, rr->fqdn, rr->ttl, &rrsig_rr_rd, rr); #endif ptr_vector_append(add, rr); rr->state |= ZONE_DIFF_RR_ADDED; if(rr->rtype == TYPE_SOA) { ptr_vector_end_swap(add, 0); } // proceed with the chain if needed changes |= ZONE_DIFF_CHANGES_ADD; rrset_removed = FALSE; all_rrset_removed = FALSE; non_empty = TRUE; } else if((rr->state & (ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_REMOVED)) == ZONE_DIFF_RR_REMOVE) { // remove #if DEBUG rdata_desc rrsig_rr_rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug1("update: del %w %{dnsname} %9i %{typerdatadesc} (zone_diff_get_changes_update_rr %p)", &temp_fw_0, rr->fqdn, rr->ttl, &rrsig_rr_rd, rr); #endif ptr_vector_append(remove, rr); rr->state |= ZONE_DIFF_RR_REMOVED; if(rr->rtype == TYPE_SOA) { ptr_vector_end_swap(remove, 0); } // proceed with the chain if needed changes |= ZONE_DIFF_CHANGES_REMOVE; all_rrset_added = FALSE; } else if((rr->state & (ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE)) == 0) { #if DEBUG rdata_desc rrsig_rr_rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug1("update: nop %w %{dnsname} %9i %{typerdatadesc} (zone_diff_get_changes_update_rr %p)", &temp_fw_0, rr->fqdn, rr->ttl, &rrsig_rr_rd, rr); #endif // stays changes |= ZONE_DIFF_CHANGES_KEPT; rrset_removed = FALSE; all_rrset_removed = FALSE; all_rrset_added = FALSE; non_empty = TRUE; } } parm->changes = changes; parm->rrset_removed = rrset_removed; parm->all_rrset_added = all_rrset_added; parm->all_rrset_removed = all_rrset_removed; parm->non_empty = non_empty; } u64 zone_diff_key_vector_get_mask(ptr_vector *keys, time_t now, u32 regeneration_seconds) { u64 mask = 0; for(int i = 0; i <= ptr_vector_last_index(keys); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(keys, i); bool is_private = dnskey_is_private(key); if((is_private && dnskey_is_activated_lenient(key, now, regeneration_seconds)) || !is_private) { mask |= 1ULL << i; } } return mask; } /** * Stores changes of a diff into two vectors. * Optionally keep track of record sets that need to be signed. * Optionally notify a chain about changes. * * @param diff * @param dc can be NULL * @param rrset_to_sign_vector can be NULL * @param remove * @param add * @return TRUE iff there is a DNSKEY rrset in the diff */ s32 zone_diff_get_changes(zone_diff *diff, ptr_vector *rrset_to_sign_vector, ptr_vector *ksks, ptr_vector *zsks, ptr_vector *remove, ptr_vector *add, s32 regeneration_seconds) { s32 mandatory_changes = 0; ya_result err = SUCCESS; // first fill the arrays with the relevant keys zone_diff_store_diff_dnskey_get_keys(diff, ksks, zsks, regeneration_seconds); ptr_set_iterator fqdn_iter; ptr_set_iterator rr_iter; time_t now = time(NULL); u64 ksks_mask = zone_diff_key_vector_get_mask(ksks, now, regeneration_seconds); u64 zsks_mask = zone_diff_key_vector_get_mask(zsks, now, regeneration_seconds); //bool may_have_empty_terminals = FALSE; // for all fqdn ptr_set_iterator_init(&diff->fqdn, &fqdn_iter); while(ptr_set_iterator_hasnext(&fqdn_iter)) { ptr_node *diff_fqdn_node = ptr_set_iterator_next_node(&fqdn_iter); #if DYNUPDATE_DIFF_DETAILED_LOG const u8 *diff_fqdn_name = (const u8*)diff_fqdn_node->key; #endif zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; if(diff_fqdn->will_have_new_nsec) { ++mandatory_changes; } // for all rrset bool type_map_changed = FALSE; bool all_rrset_added = TRUE; bool all_rrset_removed = TRUE; bool non_empty = FALSE; zone_diff_fqdn_rr_set *rrsig_rr_set = NULL; u32_node *rrset_node = u32_set_find(&diff_fqdn->rrset, TYPE_RRSIG); if(rrset_node != NULL) { rrsig_rr_set = (zone_diff_fqdn_rr_set*)rrset_node->value; } type_map_changed = (rrsig_rr_set == NULL); // for all records if(!u32_set_isempty(&diff_fqdn->rrset)) { u32_set_iterator rrset_iter; u32_set_iterator_init(&diff_fqdn->rrset, &rrset_iter); while(u32_set_iterator_hasnext(&rrset_iter)) { u32_node *rrset_node = u32_set_iterator_next_node(&rrset_iter); zone_diff_fqdn_rr_set *rr_set = (zone_diff_fqdn_rr_set*)rrset_node->value; if(rr_set == NULL) { continue; } #if DYNUPDATE_DIFF_DETAILED_LOG { // enumerate records ptr_set_iterator rr_iter; ptr_set_iterator_init(&rr_set->rr, &rr_iter); rdata_desc rdatadesc = {rr_set->rtype, 0, NULL}; while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)rr_node->key; rdatadesc.len = rr->rdata_size; rdatadesc.rdata = rr->rdata; log_debug("update: %02x [%llx] %{dnsname} %i %{typerdatadesc}", rr->state, rr_set->key_mask, rr->fqdn, rr->ttl, &rdatadesc); } } #endif if(rr_set->rtype == TYPE_RRSIG) { // if allowed ... if(diff->rrsig_update_allowed) { ptr_set_iterator_init(&rr_set->rr, &rr_iter); bool rrsig_added = FALSE; bool rrsig_kept = FALSE; bool rrsig_removed = FALSE; bool key_will_be_present = FALSE; bool key_will_be_present_DNSKEY = FALSE; bool key_will_be_present_not_DNSKEY = FALSE; while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)rr_node->value; if((rr->state & (ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE)) == ZONE_DIFF_RR_ADD) { rdata_desc rdt = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("update: %{dnsname}: checking for signing key of RRSIG record %{dnsname} %i %{dnsclass} %{typerdatadesc}", diff->origin, rr->fqdn, rr->ttl, &rr->rclass, &rdt); u8 algorithm = rrsig_get_algorithm_from_rdata(rr->rdata, rr->rdata_size); u16 tag = rrsig_get_key_tag_from_rdata(rr->rdata, rr->rdata_size); rrsig_added = TRUE; if(zone_diff_will_have_dnskey_with_algorithm_tag(diff_fqdn, algorithm, tag)) { key_will_be_present = TRUE; if(rrsig_get_type_covered_from_rdata(rr->rdata, rr->rdata_size) == TYPE_DNSKEY) { key_will_be_present_DNSKEY = TRUE; } else { key_will_be_present_not_DNSKEY = TRUE; } break; } } else if((rr->state & (ZONE_DIFF_RR_IN_ZONE|ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE)) == ZONE_DIFF_RR_REMOVE) { rrsig_removed = TRUE; } else if((rr->state & (ZONE_DIFF_RR_IN_ZONE/*|ZONE_DIFF_RR_ADD*/|ZONE_DIFF_RR_REMOVE)) == ZONE_DIFF_RR_IN_ZONE) { rrsig_kept = TRUE; // if it's added but already in zone, it does not count does it ... } } diff_fqdn->rrsig_added = rrsig_added; diff_fqdn->rrsig_kept = rrsig_kept; diff_fqdn->rrsig_removed = rrsig_removed; if(!rrsig_added || (rrsig_added && key_will_be_present)) { u8 changes = ZONE_DIFF_CHANGES_NONE; bool rrset_removed = TRUE; struct zone_diff_get_changes_update_rr_parm parms = {changes, rrset_removed, FALSE, all_rrset_added, all_rrset_removed, non_empty}; zone_diff_get_changes_update_rrsig_rr(rr_set, &parms, remove, add); diff_fqdn->rrsig_kept = !parms.rrset_new; } else { if(!key_will_be_present_DNSKEY) { log_info("update: %{dnsname}: DNSKEY RRSIG without signing DNSKEY present (probably on purpose)", diff_fqdn->fqdn); } if(!key_will_be_present_not_DNSKEY) { log_err("update: %{dnsname}: RRSIG without signing DNSKEY present (probably bad)", diff_fqdn->fqdn); } err = INVALID_STATE_ERROR; } } #if DEBUG else { log_debug1("update: %{dnsname}: not updating RRSIG rr_set at this point (rrsig_update_allowed is false)", diff_fqdn->fqdn); ptr_set_iterator_init(&rr_set->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)rr_node->value; if((rr->state & (ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE)) == ZONE_DIFF_RR_ADD) { rdata_desc rdt = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("update: %{dnsname}: (ignoring) [%02x] %{dnsname} %i %{dnsclass} %{typerdatadesc}", diff->origin, rr->state, rr->fqdn, rr->ttl, &rr->rclass, &rdt); } } } #endif continue; } u8 changes = ZONE_DIFF_CHANGES_NONE; bool rrset_removed = TRUE; struct zone_diff_get_changes_update_rr_parm parms = {changes, FALSE, rrset_removed, all_rrset_added, all_rrset_removed, non_empty}; zone_diff_get_changes_update_rr(rr_set, &parms, remove, add); changes = parms.changes; rrset_removed = parms.rrset_removed; if(rr_set->rtype != TYPE_NSEC) { all_rrset_added = parms.all_rrset_added; all_rrset_removed = parms.all_rrset_removed; non_empty = parms.non_empty; } /* * If the status is 0, then all the added records that have been added have also been removed => no map change, and no signature change * If the status is 1, then the rrset has completely been removed => map change and remove all signatures * If the status is 2, then the rrset has completely been added => map change, and add (new) signatures * If the status is 4, then the rrset existed and still exists => no map change, and no signature change * * Any other combination having 1 or 2 on will make no map change but update the signature * */ if((changes == ZONE_DIFF_CHANGES_ADD) || (changes == ZONE_DIFF_CHANGES_REMOVE)) { type_map_changed = TRUE; } ptr_vector *keys = zsks; u64 keys_mask = zsks_mask; if(rr_set->rtype == TYPE_DNSKEY) { if(!ptr_vector_isempty(ksks)) { keys = ksks; keys_mask = ksks_mask; } } if(rrset_node->key == TYPE_RRSIG) { continue; } bool rrset_updated = (changes & (ZONE_DIFF_CHANGES_ADD|ZONE_DIFF_CHANGES_REMOVE)); // || type_map_changed ? if((rr_set->rtype != TYPE_SOA) && rrset_updated) { ++mandatory_changes; } bool rrset_expected_to_be_covered = !(diff_fqdn->at_delegation || diff_fqdn->under_delegation) || (!diff_fqdn->under_delegation && (diff_fqdn->at_delegation && ((rr_set->rtype == TYPE_DS) || (rr_set->rtype == TYPE_NSEC))) ); bool rrset_rrsig_covered_with_chain_rules = (!rrset_removed && rrset_expected_to_be_covered); bool came_under_delegation = (!diff_fqdn->was_under_delegation && diff_fqdn->under_delegation); //bool came_out_of_delegation = (diff_fqdn->was_under_delegation && !diff_fqdn->under_delegation); // blanket bombing if((rrsig_rr_set != NULL) && (rrset_updated || all_rrset_removed || came_under_delegation || !rrset_rrsig_covered_with_chain_rules ) ) { ptr_set_iterator_init(&rrsig_rr_set->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rrsig_rr = (zone_diff_label_rr *)rr_node->key; if(rrsig_get_type_covered_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size) != rr_set->rtype) { continue; } if(rrsig_rr->state & ZONE_DIFF_RR_ADD) { // manually added continue; } if((rrsig_rr->state & ZONE_DIFF_RR_REMOVED) == 0) // the signature is not marked for removal (e.g.: expired) { rrsig_rr->state |= ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_AUTOMATED; #if DEBUG { rdata_desc rrsig_rr_rd = {rrsig_rr->rtype, rrsig_rr->rdata_size, rrsig_rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rrsig_rr->state}; log_debug1("update: del %w %{dnsname} %9i %{typerdatadesc} (rrsig A zone_diff_get_changes %p)", &temp_fw_0, rrsig_rr->fqdn, rrsig_rr->ttl, &rrsig_rr_rd, rrsig_rr); } #endif ptr_vector_append(remove, rrsig_rr); rrsig_rr->state |= ZONE_DIFF_RR_REMOVED; } } } // for all rrsig, enumerate properly covered types //bool rrset_already_covered = FALSE; if(!all_rrset_removed && rrset_rrsig_covered_with_chain_rules ) // else this would be pointless { if(rrsig_rr_set != NULL) { u64 coverage = 0; ptr_set_iterator_init(&rrsig_rr_set->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rrsig_rr = (zone_diff_label_rr *)rr_node->key; if(rrsig_get_type_covered_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size) != rr_set->rtype) { continue; } if((rrsig_rr->state & (ZONE_DIFF_RR_ADDED|ZONE_DIFF_RR_RDATA_OWNED)) == (ZONE_DIFF_RR_ADDED|ZONE_DIFF_RR_RDATA_OWNED)) { continue; } if((rrsig_rr->state & ZONE_DIFF_RR_REMOVED) != 0) // the signature is not marked for removal (e.g.: expired) { continue; } // check if the signature is with a valid key and is in its validity period // if it's not valid yet, keep it // if its expired, remove it // if no valid signatures are available, may mark the record for signing s32 key_index = -2; if(rrsig_should_remove_signature_from_rdata( rrsig_rr->rdata, rrsig_rr->rdata_size, keys, now, diff->rrsig_validity_regeneration, &key_index) || (key_index == -1)) { rrsig_rr->state |= ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_AUTOMATED; #if DEBUG { rdata_desc rrsig_rr_rd = {rrsig_rr->rtype, rrsig_rr->rdata_size, rrsig_rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rrsig_rr->state}; log_debug1("update: del %w %{dnsname} %9i %{typerdatadesc} (rrsig B zone_diff_get_changes %p)", &temp_fw_0, rrsig_rr->fqdn, rrsig_rr->ttl, &rrsig_rr_rd, rrsig_rr); } #endif ptr_vector_append(remove, rrsig_rr); rrsig_rr->state |= ZONE_DIFF_RR_REMOVED; ++mandatory_changes; continue; } // the signature will be kept coverage |= (1ULL << key_index); } rr_set->key_mask = keys_mask ^ coverage; } else { rr_set->key_mask = keys_mask; } } // If the chain believes it has to handle the fqdn, add the rrset to the "to sign" // This does not work with mixed chains (NSEC & NSEC3) if((rr_set->key_mask != 0) && (rrset_to_sign_vector != NULL)) { if(rr_set->rtype != TYPE_SOA) { ++mandatory_changes; } // will generate new signatures for the rrset (postponed) // verify that signatures are not already present #if DYNUPDATE_DIFF_DETAILED_LOG log_debug("update: %{dnsname}: dnssec: %{dnsname} %{dnstype} rrset @%p should be signed (%08llx/%08llx)", diff->origin, diff_fqdn_name, &rr_set->rtype, rr_set, rr_set->key_mask, keys_mask); #endif ptr_vector_append(rrset_to_sign_vector, rr_set); } } } else { #if DYNUPDATE_DIFF_DETAILED_LOG { // empty log_debug("update: ?? [?] %{dnsname} has no records", diff_fqdn->fqdn); } #endif type_map_changed = FALSE; all_rrset_added = FALSE; all_rrset_removed = FALSE; non_empty = FALSE; //may_have_empty_terminals = TRUE; } // if type_map_changes, the type map has to be updated and the signature too, obviously diff_fqdn->type_map_changed = type_map_changed || (!diff_fqdn->rrsig_kept && (diff_fqdn->rrsig_added != diff_fqdn->rrsig_removed)); diff_fqdn->all_rrset_added = all_rrset_added; diff_fqdn->all_rrset_removed = all_rrset_removed; diff_fqdn->will_be_non_empty = non_empty; /**/ diff_fqdn->type_map_changed &= non_empty; diff_fqdn->all_rrset_added &= non_empty; /**/ diff_fqdn->records_flags_set = 1; #if DYNUPDATE_DIFF_DETAILED_LOG { // empty log_debug("update: -- --- %{dnsname} remap=%i +all=%i -all=%i !empty=%i mandatory = %i + %i + %i", diff_fqdn->fqdn, type_map_changed, all_rrset_added, all_rrset_removed, non_empty, mandatory_changes, diff->nsec_change_count, diff->nsec3_change_count); } #endif } if(ISOK(err)) { // mandatory_changes += diff->nsec_change_count + diff->nsec3_change_count; return mandatory_changes; } else { return err; } } #if 0 && DYNUPDATE_DIFF_DETAILED_LOG if(may_have_empty_terminals) { ptr_set_iterator_init(&diff->fqdn, &fqdn_iter); while(ptr_set_iterator_hasnext(&fqdn_iter)) { ptr_node *diff_fqdn_node = ptr_set_iterator_next_node(&fqdn_iter); const u8 *diff_fqdn_name = (const u8*)diff_fqdn_node->key; zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; } } #endif bool zone_diff_adds_nsec3param(zone_diff *diff) { ptr_set_iterator fqdn_iter; ptr_set_iterator_init(&diff->fqdn, &fqdn_iter); while(ptr_set_iterator_hasnext(&fqdn_iter)) { ptr_node *diff_fqdn_node = ptr_set_iterator_next_node(&fqdn_iter); zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; if(!dnsname_equals(diff->origin, diff_fqdn->fqdn)) { continue; } u32_node *rrset_node = u32_set_find(&diff_fqdn->rrset, /*TYPE_NSEC3PARAM*/TYPE_NSEC3PARAMQUEUED); if(rrset_node != NULL) { zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)rrset_node->value; ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & ZONE_DIFF_RR_ADDED) != 0) { return TRUE; } } } } return FALSE; } bool zone_diff_has_or_adds_nsec3param(zone_diff *diff) { ptr_set_iterator fqdn_iter; ptr_set_iterator_init(&diff->fqdn, &fqdn_iter); while(ptr_set_iterator_hasnext(&fqdn_iter)) { ptr_node *diff_fqdn_node = ptr_set_iterator_next_node(&fqdn_iter); zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; if(!dnsname_equals(diff->origin, diff_fqdn->fqdn)) { continue; } u32_node *rrset_node; rrset_node = u32_set_find(&diff_fqdn->rrset, TYPE_NSEC3PARAM); if(rrset_node != NULL) { zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)rrset_node->value; ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & (ZONE_DIFF_RR_IN_ZONE|ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_ADDED)) != 0) { return TRUE; } } } rrset_node = u32_set_find(&diff_fqdn->rrset, TYPE_NSEC3PARAMQUEUED); if(rrset_node != NULL) { zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)rrset_node->value; ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & (ZONE_DIFF_RR_IN_ZONE|ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_ADDED)) != 0) { return TRUE; } } } } return FALSE; } bool zone_diff_has_zsk(zone_diff *diff) { ptr_set_iterator fqdn_iter; ptr_set_iterator_init(&diff->fqdn, &fqdn_iter); while(ptr_set_iterator_hasnext(&fqdn_iter)) { ptr_node *diff_fqdn_node = ptr_set_iterator_next_node(&fqdn_iter); zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; if(!dnsname_equals(diff->origin, diff_fqdn->fqdn)) { continue; } u32_node *rrset_node = u32_set_find(&diff_fqdn->rrset, TYPE_DNSKEY); if(rrset_node != NULL) { zone_diff_fqdn_rr_set *rrset = (zone_diff_fqdn_rr_set*)rrset_node->value; ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & ZONE_DIFF_RR_ADDED) != 0) { if((rr->rdata_size >= 2) && DNSKEY_FLAGS_FROM_RDATA(rr->rdata) == DNSKEY_FLAGS_ZSK) { return TRUE; } } } } } return FALSE; } void zone_diff_get_chain_changes(zone_diff *diff, dnssec_chain* dc/*, ptr_vector *rrset_to_sign_vector, ptr_vector *ksks, ptr_vector *zsks, ptr_vector *remove, ptr_vector *add*/) { ptr_set_iterator fqdn_iter; if(dc != NULL) { ptr_set_iterator_init(&diff->fqdn, &fqdn_iter); while(ptr_set_iterator_hasnext(&fqdn_iter)) { ptr_node *diff_fqdn_node = ptr_set_iterator_next_node(&fqdn_iter); const u8 *diff_fqdn_name = (const u8*)diff_fqdn_node->key; zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; zone_diff_fqdn_children_state(diff, diff_fqdn->fqdn); // calling dnssec_chain_del_from_diff_fqdn and dnssec_chain_add_from_diff_fqdn respectively // tell to remove or to add a chain node (NSEC/NSEC3) for the given fqdn in the zone. // Note the "was" or "is" covered means "IF the fqdn existed, was the past state covering it, is the new state covering it." // This table gives the del/add for a node given the various states // (+-R => sumrises to "has changed") // Was covered | Is covered | +ALL | -ALL | REMAP | NODE // -----------------------------------------------+------ // 0 0 1 0 ? | // 0 0 0 1 ? | // 0 0 0 0 0 | // 0 0 0 0 1 | // -----------------------------------------------+------ // 0 1 1 0 ? | + // 0 1 0 1 ? | There is nothing anymore (empty non-terminal ? => +) // 0 1 0 0 0 | + // 0 1 0 0 1 | + // -----------------------------------------------+------ // 1 0 1 0 ? | There was nothing before // 1 0 0 1 ? | - // 1 0 0 0 0 | - // 1 0 0 0 1 | - // -----------------------------------------------+------ // 1 1 1 0 ? | + There was nothing before // 1 1 0 1 ? | - (empty non-terminal ? => -+) // 1 1 0 0 0 | There is no changed of state on this regard // 1 1 0 0 1 | -+ // -----------------------------------------------+------ #define CHAIN_NODE_NOP 0 #define CHAIN_NODE_DEL 1 #define CHAIN_NODE_ADD 2 bool is_covered = dc->chain->fqdn_is_covered(diff_fqdn); bool was_covered = dc->chain->fqdn_was_covered(diff_fqdn); #if DYNUPDATE_DIFF_DETAILED_LOG log_debug("update: %{dnsname}: dnssec: %{dnsname}: +ALL(%i) -ALL(%i) RECORDS(%i->%i) COVERED(%i->%i) CHILDREN(%i->%i) AT(%i->%i) UNDER(%i->%i) MAP(%i)", diff->origin, diff_fqdn_name, diff_fqdn->all_rrset_added, diff_fqdn->all_rrset_removed, diff_fqdn->was_non_empty, diff_fqdn->will_be_non_empty, was_covered, is_covered, diff_fqdn->had_children, diff_fqdn->will_have_children, diff_fqdn->was_at_delegation, diff_fqdn->at_delegation, diff_fqdn->was_under_delegation, diff_fqdn->under_delegation, diff_fqdn->type_map_changed); #endif if(was_covered || is_covered) // quickly cull the first 4 states of the table { bool did_exist = diff_fqdn->had_children || diff_fqdn->was_non_empty; bool will_exist = diff_fqdn->will_have_children || diff_fqdn->will_be_non_empty; u8 ops = 0; if( (diff_fqdn->had_children != diff_fqdn->will_have_children) || (diff_fqdn->all_rrset_added) || (diff_fqdn->all_rrset_removed) || (diff_fqdn->type_map_changed) || (is_covered != was_covered) ) { //ops_index = 3; // means change if(was_covered && did_exist) { //ops_index |= 8; ops |= CHAIN_NODE_DEL; } if(is_covered && will_exist) { //ops_index |= 4; ops |= CHAIN_NODE_ADD; } } #if DEBUG log_debug2("update: %{dnsname}: dnssec: %{dnsname}: operation %x", diff->origin, diff_fqdn_name, ops); #endif if(ops & CHAIN_NODE_DEL) { log_debug2("update: %{dnsname}: dnssec: %{dnsname}: removing chain node", diff->origin, diff_fqdn_name); dnssec_chain_del_from_diff_fqdn(dc, diff_fqdn, 0); } if(ops & CHAIN_NODE_ADD) { log_debug2("update: %{dnsname}: dnssec: %{dnsname}: adding chain node", diff->origin, diff_fqdn_name); dnssec_chain_add_from_diff_fqdn(dc, diff_fqdn, 0); } } } // while fqdn names } } /** * Returns TRUE iff there are changes in the diff * * @param diff * @param dc can be NULL * @param rrset_to_sign_vector can be NULL * * @return TRUE iff there are changes in the diff */ bool zone_diff_has_changes(zone_diff *diff, ptr_vector *rrset_to_sign_vector) { if(ptr_vector_last_index(rrset_to_sign_vector) >= 0) { #if DEBUG for(s32 i = 0; i <= ptr_vector_last_index(rrset_to_sign_vector); ++i) { zone_diff_fqdn_rr_set *rr_set = (zone_diff_fqdn_rr_set*)ptr_vector_get(rrset_to_sign_vector, i); ptr_set_iterator rr_iter; // for all marked rr ptr_set_iterator_init(&rr_set->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)rr_node->value; rdata_desc rdatadesc = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug1("zone-diff: changes: %{dnsname}: %02x: %w: %{dnsname} %i %{typerdatadesc}", diff->origin, rr->state, &temp_fw_0, rr->fqdn, rr->ttl, &rdatadesc); } } #endif return TRUE; } ptr_set_iterator fqdn_iter; ptr_set_iterator rr_iter; // for all fqdn ptr_set_iterator_init(&diff->fqdn, &fqdn_iter); while(ptr_set_iterator_hasnext(&fqdn_iter)) { ptr_node *diff_fqdn_node = ptr_set_iterator_next_node(&fqdn_iter); zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; // for all records u32_set_iterator rrset_iter; u32_set_iterator_init(&diff_fqdn->rrset, &rrset_iter); while(u32_set_iterator_hasnext(&rrset_iter)) { u32_node *rrset_node = u32_set_iterator_next_node(&rrset_iter); zone_diff_fqdn_rr_set *rr_set = (zone_diff_fqdn_rr_set*)rrset_node->value; // for all marked rr ptr_set_iterator_init(&rr_set->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)rr_node->value; #if DEBUG rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug1("update: %{dnsname}: has-changes: state %02x: %{dnsname} %9i %{typerdatadesc}", diff->origin, rr->state, rr->fqdn, rr->ttl, &rd); #endif if((rr->state & (ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE)) == ZONE_DIFF_RR_ADD) { // add return TRUE; } else if((rr->state & (ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE)) == ZONE_DIFF_RR_REMOVE) { // remove return TRUE; } } } } return FALSE; } void zone_diff_fqdn_rr_set_log(const zone_diff_fqdn_rr_set *rr_set, const u8* origin, logger_handle *handle, int level) { ptr_set_iterator rr_iter; // for all marked rr ptr_set_iterator_init(&rr_set->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)rr_node->value; rdata_desc rdatadesc = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; logger_handle_msg_nocull(handle, level, LOG_TEXT_PREFIX "zone-diff: %{dnsname}: %{dnsname}: %02x: %w: %{dnsname} %i %{typerdatadesc}", origin, rr->fqdn, rr->state, &temp_fw_0, rr->fqdn, rr->ttl, &rdatadesc); } } void zone_diff_fqdn_log(const zone_diff_fqdn* diff_fqdn, const u8 *origin, logger_handle *handle, int level) { if(!log_is_set(handle, level)) { return; } // for all rrset const u8 *diff_fqdn_name = diff_fqdn->fqdn; if(origin == NULL) { origin = (const u8 *)"\004NULL"; } format_writer temp_fw_1 = {zone_diff_fqdn_changes_format, diff_fqdn}; logger_handle_msg_nocull(handle, level, LOG_TEXT_PREFIX "zone-diff: %{dnsname}: %{dnsname}: %w", origin, diff_fqdn_name, &temp_fw_1); // for all records u32_set_iterator rrset_iter; u32_set_iterator_init(&diff_fqdn->rrset, &rrset_iter); while(u32_set_iterator_hasnext(&rrset_iter)) { u32_node *rrset_node = u32_set_iterator_next_node(&rrset_iter); zone_diff_fqdn_rr_set *rr_set = (zone_diff_fqdn_rr_set*)rrset_node->value; if(rr_set == NULL) { log_debug("zone-diff: %{dnsname}: %{dnsname} has no record set", origin, diff_fqdn_name); continue; } format_writer temp_fw_1 = {zone_diff_fqdn_changes_format, diff_fqdn}; logger_handle_msg_nocull(handle, level, LOG_TEXT_PREFIX "zone-diff: %{dnsname}: %{dnsname}: %w", origin, diff_fqdn_name, &temp_fw_1); zone_diff_fqdn_rr_set_log(rr_set, origin, handle, level); } } void zone_diff_log(const zone_diff *diff, logger_handle *handle, int level) { if(!log_is_set(handle, level)) { return; } ptr_set_iterator fqdn_iter; // for all fqdn ptr_set_iterator_init(&diff->fqdn, &fqdn_iter); while(ptr_set_iterator_hasnext(&fqdn_iter)) { ptr_node *diff_fqdn_node = ptr_set_iterator_next_node(&fqdn_iter); zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; zone_diff_fqdn_log(diff_fqdn, diff->origin, handle, level); } } int zone_diff_check_changes(const zone_diff *diff, logger_handle *handle, int level) { ptr_set_iterator fqdn_iter; int changes = 0; ptr_set_iterator_init(&diff->fqdn, &fqdn_iter); while(ptr_set_iterator_hasnext(&fqdn_iter)) { ptr_node *diff_fqdn_node = ptr_set_iterator_next_node(&fqdn_iter); zone_diff_fqdn *diff_fqdn = (zone_diff_fqdn*)diff_fqdn_node->value; u32_set_iterator rrset_iter; u32_set_iterator_init(&diff_fqdn->rrset, &rrset_iter); while(u32_set_iterator_hasnext(&rrset_iter)) { u32_node *rrset_node = u32_set_iterator_next_node(&rrset_iter); zone_diff_fqdn_rr_set *rr_set = (zone_diff_fqdn_rr_set*)rrset_node->value; ptr_set_iterator rr_iter; ptr_set_iterator_init(&rr_set->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)rr_node->value; if(!(rr->state & ZONE_DIFF_RR_AUTOMATED)) { if(rr->state & (ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE)) { ++changes; } } } } } if(changes == 0) { zone_diff_log(diff, handle, level); } return changes; } /** * Signs RRSET with all active keys found in keys. * Doesn't do any pertinence tests. * It's only use now is to add RRSIG records to NSEC3 rrsets that have no valid signatures * */ void zone_diff_sign_rrset(zone_diff *diff, zdb_zone *zone, ptr_vector *keys, ptr_vector *add, zone_diff_fqdn_rr_set *rr_set, zone_diff_fqdn_rr_set *rrsig_rr_set) { ptr_vector rrset = PTR_VECTOR_EMPTY; dnskey_signature ds; dnskey_signature_init(&ds); // setup the view for the RRSET (RRSET abstraction for the part that generates signatures) struct resource_record_view rrv = {NULL, &zone_diff_label_rr_rrv_vtbl}; rrv.data = rr_set; ptr_vector_clear(&rrset); //const u8* rr_fqdn = NULL; u8 rrsig_state_mask = ZONE_DIFF_RR_AUTOMATED; // accumulate records FOREACH_PTR_SET(void*,value, &rr_set->rr) { zone_diff_label_rr* rr = (zone_diff_label_rr*)value; //rr_fqdn = rr->fqdn; // if the RR will exist in the zone (A.K.A: not removed), add it to the collection to sign if((rr->state & ZONE_DIFF_RR_REMOVE) == 0) { #if DEBUG rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug2("update: %{dnsname}: covers %w %{dnsname} %9i %{typerdatadesc}%s", diff->origin, &temp_fw_0, rr->fqdn, rr->ttl, &rd, ((rr->state & ZONE_DIFF_RR_AUTOMATED)!=0)?"":""); #endif rrsig_state_mask &= rr->state; ptr_vector_append(&rrset, value); } else { #if DEBUG rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug2("update: %{dnsname}: ignore %w %{dnsname} %9i %{typerdatadesc}", diff->origin, &temp_fw_0, rr->fqdn, rr->ttl, &rd); #endif } } for(int j = 0; j <= ptr_vector_last_index(keys); ++j) { const dnssec_key *key = (dnssec_key*)ptr_vector_get(keys, j); // check if the key has private components if(!dnskey_is_private(key)) { log_debug("update: %{dnsname}: key K%{dnsname}+%03d+%05d is not private", diff->origin, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key)); continue; } zone_diff_label_rr *rrsig_rr = NULL; ya_result ret; s32 maxinterval = diff_generate_signature_interval(diff); // rrset_to_sign; if(ISOK(ret = dnskey_sign_rrset_with_maxinterval(key, &rrset, TRUE, &rrv, maxinterval, (void **) &rrsig_rr))) { // add the key to the add set log_debug2("update: %{dnsname}: signed %{dnsname} %{dnstype} rrset with key %03d %05d",diff->origin, rrsig_rr->fqdn, &rr_set->rtype, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); s32 signature_valid_until = rrsig_get_valid_until_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); // if the signature expires in this time if(signature_valid_until > 0) { if(signature_valid_until < dnskey_get_inactive_epoch(key)) { s32 signature_regeneration_time = signature_valid_until - diff->rrsig_validity_regeneration; if(zone->progressive_signature_update.earliest_signature_expiration > signature_regeneration_time) { zone->progressive_signature_update.earliest_signature_expiration = signature_regeneration_time; } } else { if(zone->progressive_signature_update.earliest_signature_expiration > signature_valid_until) { zone->progressive_signature_update.earliest_signature_expiration = signature_valid_until; } } } rrsig_rr->state |= rrsig_state_mask; zone_diff_label_rr *final_rrsig_rr = zone_diff_fqdn_rr_set_rr_add_get(rrsig_rr_set, rrsig_rr); if((final_rrsig_rr->state & ZONE_DIFF_RR_IN_ZONE) == 0) { ptr_vector_append(add, final_rrsig_rr); } } else { log_warn("update: %{dnsname}: failed to sign with key %03d %05d: %r", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key), ret); // ... } } // for each key } /** * Appends RRSIGs to remove/add vector, following the the need-to-be-signed RR set, using keys from KSK and ZSK vectors. * * @param diff * @param rrset_to_sign_vector * @param ksks * @param zsks * @param remove * @param add */ ya_result zone_diff_sign(zone_diff *diff, zdb_zone *zone, ptr_vector* rrset_to_sign_vector, ptr_vector *ksks, ptr_vector *zsks, ptr_vector *remove, ptr_vector* add) { /************************************************************************** * SIGNATURES HANDLING **************************************************************************/ (void)remove; // if there are no rrset to be signed, don't bother going further if(ptr_vector_last_index(rrset_to_sign_vector) < 0) { return SUCCESS; } // eliminate potential duplicates (rare case) { ptr_vector_qsort(rrset_to_sign_vector, ptr_vector_compare_pointers_callback); void *prev = ptr_vector_get(rrset_to_sign_vector, 0); for(s32 i = 1; i <= ptr_vector_last_index(rrset_to_sign_vector);) { void *item = ptr_vector_get(rrset_to_sign_vector, i); if(item == prev) { ptr_vector_remove_at(rrset_to_sign_vector, i); continue; } prev = item; ++i; } } /* * for each rrset in rrset_to_sign * for each valid zsk in the keyring * start new signature * add each record * generate signature */ log_debug("update: %{dnsname}: signing differences", diff->origin); #if DEBUG zone_diff_log(diff, MODULE_MSG_HANDLE, MSG_DEBUG2); #endif // if there is a chain, proceed with the changes ptr_vector rrset = PTR_VECTOR_EMPTY; dnskey_signature ds; dnskey_signature_init(&ds); // setup the view for the RRSET (RRSET abstraction for the part that generates signatures) struct resource_record_view rrv = {NULL, &zone_diff_label_rr_rrv_vtbl}; // for each RRSET for(int i = 0; i <= ptr_vector_last_index(rrset_to_sign_vector); ++i) { zone_diff_fqdn_rr_set *rr_set = (zone_diff_fqdn_rr_set*)ptr_vector_get(rrset_to_sign_vector, i); log_debug1("update: %{dnsname}: signing (trying) %{dnstype} rrset @%p", diff->origin, &rr_set->rtype, rr_set); rrv.data = rr_set; ptr_vector_clear(&rrset); u8 rrsig_state_mask = ZONE_DIFF_RR_AUTOMATED; // for each record in the RRSET const u8* rr_fqdn = NULL; // accumulate records FOREACH_PTR_SET(void*,value, &rr_set->rr) { zone_diff_label_rr* rr = (zone_diff_label_rr*)value; rr_fqdn = rr->fqdn; // keep the fqdn from the first match #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG if(rr_set->rtype == TYPE_DNSKEY) { rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_info("update: %{dnsname}: [%02x] %{dnsname} %9i %{typerdatadesc}", diff->origin, rr->state, rr->fqdn, rr->ttl, &rd); } #endif // if the RR will exist in the zone (A.K.A: not removed), add it to the collection to sign if((rr->state & ZONE_DIFF_RR_REMOVE) == 0) { #if DEBUG rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug2("update: %{dnsname}: covers %w %{dnsname} %9i %{typerdatadesc}%s", diff->origin, &temp_fw_0, rr->fqdn, rr->ttl, &rd, ((rr->state & ZONE_DIFF_RR_AUTOMATED)!=0)?"":""); #endif rrsig_state_mask &= rr->state; ptr_vector_append(&rrset, value); } else { #if DEBUG rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rr->state}; log_debug2("update: %{dnsname}: ignore %w %{dnsname} %9i %{typerdatadesc}", diff->origin, &temp_fw_0, rr->fqdn, rr->ttl, &rd); #endif } } if(rr_fqdn == NULL) { continue; } #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG if(rr_set->rtype == TYPE_DNSKEY) { log_info("update: %{dnsname}: DNSKEY records may be updated", diff->origin); } #endif // if the collection is empty, nothing more to do for this RRSET zone_diff_fqdn *rrsig_label = zone_diff_fqdn_add(diff, rr_fqdn, NULL); if(ptr_vector_last_index(&rrset) < 0) { // except removing all signatures associated with it ... if(rrsig_label != NULL) { #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG if(rr_set->rtype == TYPE_DNSKEY) { log_info("update: %{dnsname}: DNSKEY rrset empty, all its signatures will be removed", diff->origin); } #endif zone_diff_fqdn_rr_set *rrsig_label_rrset = zone_diff_fqdn_rr_set_add(rrsig_label, TYPE_RRSIG); FOREACH_PTR_SET(void*,value, &rrsig_label_rrset->rr) { zone_diff_label_rr* rrsig_rr = (zone_diff_label_rr*)value; if(rrsig_get_type_covered_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size) == rr_set->rtype) { #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG if(rr_set->rtype == TYPE_DNSKEY) { rdata_desc rd = {rrsig_rr->rtype, rrsig_rr->rdata_size, rrsig_rr->rdata}; log_info("update: %{dnsname}: will remove %{dnsname} %9i %{typerdatadesc}", diff->origin, rrsig_rr->fqdn, rrsig_rr->ttl, &rd); } #endif if((rrsig_rr->state & ZONE_DIFF_RR_REMOVED) == 0) { rrsig_rr->state &= ~ZONE_DIFF_RR_ADD; rrsig_rr->state |= ZONE_DIFF_RR_REMOVE; #if DEBUG rdata_desc rd = {rrsig_rr->rtype, rrsig_rr->rdata_size, rrsig_rr->rdata}; log_debug("update: %{dnsname}: will remove %{dnsname} %9i %{typerdatadesc}", diff->origin, rrsig_rr->fqdn, rrsig_rr->ttl, &rd); #endif ptr_vector_append(remove, rrsig_rr); rrsig_rr->state |= ZONE_DIFF_RR_REMOVED; } } } } continue; } yassert(rrsig_label != NULL); zone_diff_fqdn_rr_set *rrsig_label_rrset = zone_diff_fqdn_rr_set_add(rrsig_label, TYPE_RRSIG); yassert(rrsig_label_rrset != NULL); // take note that some RRSIG records will be added rrsig_state_mask |= ZONE_DIFF_RR_ADD; bool canonize = TRUE; ptr_vector *keys; yassert(rr_set->rtype != TYPE_RRSIG); // use the adequate DNSKEY collection if(rr_set->rtype != TYPE_DNSKEY) { keys = zsks; } else { if(!ptr_vector_isempty(ksks)) { keys = ksks; } else { keys = zsks; } } // for all keys from said collection for(int j = 0; j <= ptr_vector_last_index(keys); ++j) { const dnssec_key *key = (dnssec_key*)ptr_vector_get(keys, j); #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG log_debug("update: considering key %{dnsname} %03d %05d", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); #endif #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG if(rr_set->rtype == TYPE_DNSKEY) { log_info("update: %{dnsname} DNSKEY cannot use key %03d %05d as it is not private", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); } #endif // check if the key is to be used (using the key_mask) if((rr_set->key_mask & (1ULL << j)) == 0) { #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG if(rr_set->rtype == TYPE_DNSKEY) { log_info("update: %{dnsname} DNSKEY will not use key %03d %05d as the signature doesn't need an update", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); } #endif #if DEBUG zone_diff_label_rr* rr = ptr_vector_get(&rrset, 0); log_debug2("update: %{dnsname}: %{dnsname} %{dnstype} does not need a signature update for key %03d %05d", diff->origin, rr->fqdn, &rr->rtype, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); #endif continue; // skip } // check if the key has private components if(!dnskey_is_private(key)) { #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG if(rr_set->rtype == TYPE_DNSKEY) { log_info("update: %{dnsname} DNSKEY cannot use key %03d %05d as it is not private", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); } #endif log_debug("update: %{dnsname}: key K%{dnsname}+%03d+%05d is not private", diff->origin, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key)); continue; } if(dnskey_is_deactivated(key, time(NULL) - 5)) // don't generate it if it's about to expire { #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG if(rr_set->rtype == TYPE_DNSKEY) { log_info("update: %{dnsname} DNSKEY cannot use key %03d %05d as its deactivated", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); } #endif log_debug("update: %{dnsname}: key K%{dnsname}+%03d+%05d is about to be deactivated", diff->origin, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key)); continue; } zone_diff_label_rr *rrsig_rr = NULL; ya_result ret; s32 maxinterval = diff_generate_signature_interval(diff); // rrset_to_sign; if(ISOK(ret = dnskey_sign_rrset_with_maxinterval(key, &rrset, canonize, &rrv, maxinterval, (void **)&rrsig_rr))) { canonize = FALSE; // add the key to the add set #if DYNUPDATE_DIFF_DETAILED_DNSKEY_LOG if(rr_set->rtype == TYPE_DNSKEY) { log_info("update: %{dnsname} DNSKEY has been signed with key %03d %05d", diff->origin, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key)); } #endif log_debug2("update: %{dnsname}: signed %{dnsname} %{dnstype} rrset with key %03d %05d",diff->origin, rrsig_rr->fqdn, &rr_set->rtype, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); s32 signature_valid_until = rrsig_get_valid_until_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); // if the signature expires in this time if(signature_valid_until > 0) { if(signature_valid_until < dnskey_get_inactive_epoch(key)) { s32 signature_regeneration_time = signature_valid_until - diff->rrsig_validity_regeneration; if(zone->progressive_signature_update.earliest_signature_expiration > signature_regeneration_time) { zone->progressive_signature_update.earliest_signature_expiration = signature_regeneration_time; } } else { if(zone->progressive_signature_update.earliest_signature_expiration > signature_valid_until) { zone->progressive_signature_update.earliest_signature_expiration = signature_valid_until; } } } rrsig_rr->state |= rrsig_state_mask; #if DEBUG { rdata_desc rrsig_rr_desc = {rrsig_rr->rtype, rrsig_rr->rdata_size, rrsig_rr->rdata}; log_debug6("update: %{dnsname}: signature <= %p [%02x] %{dnsname} %i %{typerdatadesc}", diff->origin, rrsig_rr, rrsig_rr->state, rrsig_rr->fqdn, rrsig_rr->ttl, &rrsig_rr_desc); } #endif zone_diff_label_rr *final_rrsig_rr = zone_diff_fqdn_rr_set_rr_add_get(rrsig_label_rrset, rrsig_rr); // replace is right (should be unique) #if DEBUG { rdata_desc rrsig_rr_desc = {final_rrsig_rr->rtype, final_rrsig_rr->rdata_size, final_rrsig_rr->rdata}; log_debug6("update: %{dnsname}: signature => %p [%02x] %{dnsname} %i %{typerdatadesc}", diff->origin, final_rrsig_rr, final_rrsig_rr->state, final_rrsig_rr->fqdn, final_rrsig_rr->ttl, &rrsig_rr_desc); } #endif if((final_rrsig_rr->state & ZONE_DIFF_RR_IN_ZONE) == 0) { ptr_vector_append(add, final_rrsig_rr); if(rrsig_label != NULL) { // int rrsig_count = 0; FOREACH_PTR_SET(void*,value, &rrsig_label_rrset->rr) { zone_diff_label_rr* rrsig_rr = (zone_diff_label_rr*)value; if((rrsig_rr->state & (ZONE_DIFF_RR_IN_ZONE|ZONE_DIFF_RR_REMOVE|ZONE_DIFF_RR_REMOVED)) == ZONE_DIFF_RR_IN_ZONE) // if the key is marked as being removed, no need to remove it twice { // key is kept or added u16 ctype = rrsig_get_type_covered_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); // type covered by the signature if(ctype == rr_set->rtype) { u16 keytag = rrsig_get_key_tag_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); if(keytag == dnskey_get_tag_const(key)) { u8 keyalg = rrsig_get_algorithm_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); if(keyalg == dnskey_get_algorithm(key)) { #if DEBUG rdata_desc rrsig_rr_desc = {rrsig_rr->rtype, rrsig_rr->rdata_size, rrsig_rr->rdata}; log_debug6("update: %{dnsname}: [%02x] %{dnsname} %i %{typerdatadesc} is obsolete", diff->origin, rrsig_rr->state, rrsig_rr->fqdn, rrsig_rr->ttl, &rrsig_rr_desc); #endif rrsig_rr->state |= ZONE_DIFF_RR_REMOVE; ptr_vector_append(remove, rrsig_rr); rrsig_rr->state |= ZONE_DIFF_RR_REMOVED; } } } } } } } //(void)rrsig_rr_set; } else { log_warn("update: %{dnsname}: failed to sign with key %03d %05d: %r", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key), ret); // ... } } // for each key // remove signatures not covered by an active key if(rrsig_label != NULL) { int rrsig_count = 0; int rrsig_known = 0; int rrsig_ignored = 0; FOREACH_PTR_SET(void*,value, &rrsig_label_rrset->rr) { ++rrsig_known; zone_diff_label_rr* rrsig_rr = (zone_diff_label_rr*)value; #if DEBUG rdata_desc rrsig_rr_desc = {rrsig_rr->rtype, rrsig_rr->rdata_size, rrsig_rr->rdata}; log_debug6("update: %{dnsname}: [%02x] %{dnsname} %i %{typerdatadesc}", diff->origin, rrsig_rr->state, rrsig_rr->fqdn, rrsig_rr->ttl, &rrsig_rr_desc); #endif if(rrsig_rr->state & ZONE_DIFF_RR_REMOVE) // if the key is marked as being removed, no need to remove it twice { rrsig_label->rrsig_removed = 1; continue; } // key is kept or added u16 ctype = rrsig_get_type_covered_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); // type covered by the signature if(ctype == rr_set->rtype) { u16 keytag = rrsig_get_key_tag_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); u8 keyalg = rrsig_get_algorithm_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); bool keep = FALSE; ++rrsig_ignored; for(int j = 0; j <= ptr_vector_last_index(keys); ++j) { const dnssec_key *key = (dnssec_key*)ptr_vector_get(keys, j); if((dnskey_get_algorithm(key) == keyalg) && (dnskey_get_tag_const(key) == keytag)) { --rrsig_ignored; ++rrsig_count; keep = TRUE; break; } } if(keep) { if(rrsig_rr->state & ZONE_DIFF_RR_ADD) { rrsig_label->rrsig_added = 1; // new } else { rrsig_label->rrsig_kept = 1; // already in zone } } else { #if DEBUG rdata_desc rd = {rrsig_rr->rtype, rrsig_rr->rdata_size, rrsig_rr->rdata}; log_debug("update: %{dnsname}: will remove %{dnsname} %9i %{typerdatadesc}", diff->origin, rrsig_rr->fqdn, rrsig_rr->ttl, &rd); #endif rrsig_rr->state |= ZONE_DIFF_RR_REMOVE; ptr_vector_append(remove, rrsig_rr); rrsig_rr->state |= ZONE_DIFF_RR_REMOVED; } } } // for all RRSIG in the RRSIG rrset if(rrsig_count == 0) { // record set cannot be properly signed log_warn("update: %{dnsname}: %{dnsname} %{dnstype} not covered by a signature (%i signatures in the set, %i ignored for the type)", diff->origin, rr_fqdn, &rr_set->rtype, rrsig_known, rrsig_ignored); if(rrsig_label != NULL) { int rrsig_index = 0; FOREACH_PTR_SET(void*,value, &rrsig_label_rrset->rr) { zone_diff_label_rr* rrsig_rr = (zone_diff_label_rr*)value; rdata_desc rrsig_record = {TYPE_RRSIG, rrsig_rr->rdata_size, rrsig_rr->rdata}; log_warn("update: %{dnsname}: %02i [%02x] %{dnsname} %5i %{typerdatadesc}", diff->origin, rrsig_index, rrsig_rr->state, rrsig_rr->fqdn, rrsig_rr->ttl, &rrsig_record); ++rrsig_index; } } dnskey_signature_finalize(&ds); ptr_vector_destroy(&rrset); return DNSSEC_ERROR_RRSIG_NOUSABLEKEYS; } else { // record set cannot be properly signed and has no valid signatures #if DEBUG log_debug1("update: %{dnsname}: %{dnsname} %{dnstype} is covered by a signature", diff->origin, rr_fqdn, &rr_set->rtype); #endif } } // if(rrsig_label != NULL) } // for(int i = 0; i <= ptr_vector_last_index(rrset_to_sign_vector); ++i) // FOR EACH RRSET dnskey_signature_finalize(&ds); ptr_vector_destroy(&rrset); return SUCCESS; } void zone_diff_label_state_flags_long_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; static char separator[1] = {','}; if(value == NULL) { return; } u8 state = *(u8*)value; int separator_size = 0; if(state & ZONE_DIFF_RR_ADD) { output_stream_write(os, "add", 3); separator_size = 1; } if(state & ZONE_DIFF_RR_REMOVE) { output_stream_write(os, separator, separator_size); output_stream_write(os, "remove", 6); separator_size = 1; } if(state & ZONE_DIFF_RR_RDATA_OWNED) { output_stream_write(os, separator, separator_size); output_stream_write(os, "owned", 5); separator_size = 1; } if(state & ZONE_DIFF_RR_VOLATILE) { output_stream_write(os, separator, separator_size); output_stream_write(os, "volatile", 8); separator_size = 1; } if(state & ZONE_DIFF_RR_IN_ZONE) { output_stream_write(os, separator, separator_size); output_stream_write(os, "inzone", 6); separator_size = 1; } if(state & ZONE_DIFF_RR_AUTOMATED) { output_stream_write(os, separator, separator_size); output_stream_write(os, "auto", 4); separator_size = 1; } if(state & ZONE_DIFF_RR_ADDED) { output_stream_write(os, separator, separator_size); output_stream_write(os, "added", 5); separator_size = 1; } if(state & ZONE_DIFF_RR_REMOVED) { output_stream_write(os, separator, separator_size); output_stream_write(os, "removed", 7); } } void zone_diff_store_diff_dnskey_get_keys(zone_diff *diff, ptr_vector *ksks, ptr_vector *zsks, s32 regeneration_seconds) { // remove all signing keys that are about to be removed // add all activated signing keys that are being added const zone_diff_fqdn *apex = diff->apex; const zone_diff_fqdn_rr_set *dnskey_rrset = zone_diff_fqdn_rr_get_const(apex, TYPE_DNSKEY); if(dnskey_rrset != NULL) { // for all keys, handle added and removed ones time_t now = time(NULL); dnssec_key *key; ptr_set_iterator rr_iter; ptr_set_iterator_init(&dnskey_rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; #if DEBUG format_writer state_flags = {zone_diff_label_state_flags_long_format, &rr->state}; log_debug("maintenance: DNSKEY: 'K%{dnsname}+%03d+%05hd': key listed (%w)", diff->origin, dnskey_get_algorithm_from_rdata(rr->rdata), dnskey_get_tag_from_rdata(rr->rdata, rr->rdata_size), &state_flags); #endif if((rr->state & ZONE_DIFF_RR_REMOVE) == 0) // exists or is being added { key = NULL; ya_result ret = dnssec_keystore_load_private_key_from_rdata(rr->rdata, rr->rdata_size, rr->fqdn, &key); if(ISOK(ret)) { ptr_vector *keys = NULL; if(dnskey_get_flags(key) == DNSKEY_FLAGS_KSK) { keys = ksks; } else if(dnskey_get_flags(key) == DNSKEY_FLAGS_ZSK) { keys = zsks; } else { log_err("maintenance: DNSKEY: 'K%{dnsname}+%03d+%05hd': unexpected flags: %u", diff->origin, dnskey_get_algorithm_from_rdata(rr->rdata), dnskey_get_tag_from_rdata(rr->rdata, rr->rdata_size), htons(dnskey_get_flags(key))); dnskey_release(key); continue; } // if key is activated, and not already in the (signing) set, add it #if DEBUG log_debug("maintenance: DNSKEY: 'K%{dnsname}+%03d+%05hd': key found, exists or is about to be added", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); #endif if(dnskey_is_activated_lenient(key, now, regeneration_seconds)) { #if DEBUG log_debug("maintenance: DNSKEY: 'K%{dnsname}+%03d+%05hd': private key is active (or will soon be) (%T)", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key), (u32)dnskey_get_activate_epoch(key)); #endif #if DEBUG log_debug("maintenance: DNSKEY: 'K%{dnsname}+%03d+%05hd': private key added in signers", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); #endif ptr_vector_append(keys, key); } else { #if DEBUG log_debug("maintenance: DNSKEY: 'K%{dnsname}+%03d+%05hd': private key is not active (%T)", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key), (u32)dnskey_get_activate_epoch(key)); #endif } } else // key is being removed { ya_result ret = dnssec_keystore_load_public_key_from_rdata(rr->rdata, rr->rdata_size, rr->fqdn, &key); if(ISOK(ret)) { #if DEBUG log_debug("maintenance: DNSKEY: 'K%{dnsname}+%03d+%05hd': key found, private key not available", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); #endif ptr_vector *keys = NULL; if(dnskey_get_flags(key) == DNSKEY_FLAGS_KSK) { keys = ksks; } else if(dnskey_get_flags(key) == DNSKEY_FLAGS_ZSK) { keys = zsks; } else { log_err("maintenance: DNSKEY: 'K%{dnsname}+%03d+%05hd': unexpected flags: %u", diff->origin, dnskey_get_algorithm_from_rdata(rr->rdata), dnskey_get_tag_from_rdata(rr->rdata, rr->rdata_size), htons(dnskey_get_flags(key))); dnskey_release(key); continue; } #if DEBUG log_debug("maintenance: DNSKEY: 'K%{dnsname}+%03d+%05hd': private key not loaded: %r", diff->origin, dnskey_get_algorithm_from_rdata(rr->rdata), dnskey_get_tag_from_rdata(rr->rdata, rr->rdata_size), ret); #endif ptr_vector_append(keys, key); } else // no private key and public record could not be loaded { log_err("maintenance: DNSKEY: 'K%{dnsname}+%03d+%05hd': public key not loaded: %r", diff->origin, dnskey_get_algorithm_from_rdata(rr->rdata), dnskey_get_tag_from_rdata(rr->rdata, rr->rdata_size), ret); // if the zone is handled by policies, this key should be removed #if 0 // note: don't cleanup keys here if(ret != DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM) { rr->state |= ZONE_DIFF_RR_REMOVE; } #endif } } } // else key is being removed } } // else would be surprising #if DEBUG for(int i = 0; i <= ptr_vector_last_index(ksks); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(ksks, i); log_debug3("maintenance: DNSKEY: KSK: 'K%{dnsname}+%03d+%05hd': final state", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); } for(int i = 0; i <= ptr_vector_last_index(zsks); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(zsks, i); log_debug3("maintenance: DNSKEY: ZSK: 'K%{dnsname}+%03d+%05hd': final state", diff->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); } #endif } static ya_result zone_diff_verify_dnskey_presence(zone_diff *diff, zdb_zone *zone, ptr_vector *rrset_to_sign, ptr_vector *ksks, ptr_vector *zsks) { ya_result ret = SUCCESS; u8 maintain_mode = zone_get_maintain_mode(zone); if(maintain_mode > ZDB_ZONE_MAINTAIN_NOSEC) { for(int i = 0; i <= ptr_vector_last_index(ksks); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(ksks, i); log_debug3("update: DNSKEY: KSK: 'K%{dnsname}+%03d+%05hd': key visible", zone->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); } for(int i = 0; i <= ptr_vector_last_index(zsks); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(zsks, i); log_debug3("update: DNSKEY: ZSK: 'K%{dnsname}+%03d+%05hd': key visible", zone->origin, dnskey_get_algorithm(key), dnskey_get_tag_const(key)); } zone_diff_fqdn *apex = zone_diff_fqdn_get(diff, diff->origin); if(!zone_diff_will_have_rrset_type(apex, TYPE_DNSKEY)) { log_err("update: %{dnsname}: there are no DNSKEY in the zone", zone->origin); ret = ZDB_ERROR_ZONE_NO_ACTIVE_DNSKEY_FOUND; } for(int i = 0; i <= ptr_vector_last_index(rrset_to_sign); ++i) { zone_diff_fqdn_rr_set *rr_set = (zone_diff_fqdn_rr_set*)ptr_vector_get(rrset_to_sign, i); if(!diff->rrsig_update_allowed) { if(rr_set->rtype != TYPE_DNSKEY) { if(ptr_vector_last_index(zsks) < 0) { log_warn("update: %{dnsname}: %{dnstype} record set is being modified but no ZSK can sign it", zone->origin, &rr_set->rtype); } } else { if(ptr_vector_last_index(ksks) < 0) { log_warn("update: %{dnsname} DNSKEY record set is being modified but no KSK can sign it", zone->origin); } } } } } return ret; } static ya_result zone_diff_store_diff(zone_diff *diff, zdb_zone *zone, ptr_vector *remove, ptr_vector *add) { // for all fqdn // for all rrset // for all marked rr (add or remove) // put the rr(s) in the relevant vector // proceed with dnssec on the side // if changed and the rr must be signed // put all signatures rr in the remove set // generate relevant signatures and add them to the add set // add the dnssec changes, including signatures // then, because it's Y2 and not Y3, apply the changes into the DB with the journal ready to write // so .. ya_result ret; if(FAIL(ret = zone_diff_set_soa(diff, NULL))) { return ret; } /************************************************************************** * DIFF COMPUTATIONS **************************************************************************/ // initialise the chain(s) dnssec_chain dc; u8 maintain_mode = zone_get_maintain_mode(zone); switch(maintain_mode) { case ZDB_ZONE_MAINTAIN_NSEC3: case ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT: { dnssec_chain_init(&dc, (maintain_mode == ZDB_ZONE_MAINTAIN_NSEC3)?dynupdate_nsec3_chain_get_vtbl():dynupdate_nsec3_optout_chain_get_vtbl(), diff); nsec3_zone *n3 = zone->nsec.nsec3; while(n3 != NULL) { const u8 *nsec3param_rdata = n3->rdata; u8 nsec3_chain_status = 0; nsec3_zone_get_status_from_rdata(zone, nsec3param_rdata, NSEC3_ZONE_RDATA_SIZE(n3), &nsec3_chain_status); dnssec_chain_add_chain(&dc, (dnssec_chain_head_t)n3, (nsec3_chain_status & NSEC3_ZONE_REMOVING) != 0); n3 = n3->next; } break; } case ZDB_ZONE_MAINTAIN_NSEC: { u8 nsec_chain_status = 0; nsec_zone_get_status(zone, &nsec_chain_status); dnssec_chain_init(&dc, dynupdate_nsec_chain_get_vtbl(), diff); dnssec_chain_add_chain(&dc, (dnssec_chain_head_t)zone->nsec.nsec, (nsec_chain_status & NSEC_ZONE_REMOVING) != 0); break; } default: { dnssec_chain_init(&dc, dynupdate_nosec_chain_get_vtbl(), diff); break; } } // update statuses, validates if(ISOK(ret = zone_diff_validate(diff))) { ptr_vector ksks = PTR_VECTOR_EMPTY; ptr_vector zsks = PTR_VECTOR_EMPTY; ptr_vector rrset_to_sign = PTR_VECTOR_EMPTY; // store changes in vectors and get the RR sets to sign s32 mandatory_changes = zone_diff_get_changes(diff, &rrset_to_sign, &ksks, &zsks, remove, add, zone->sig_validity_regeneration_seconds); #if DYNUPDATE_DIFF_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug3("update: changes: %{dnsname}: - %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug3("update: changes: %{dnsname}: + %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); } #endif #if DEBUG log_debug1("update: %{dnsname}: diff changes edited", zone->origin); zone_diff_log(diff, MODULE_MSG_HANDLE, MSG_DEBUG2); #endif const bool changes_happened = (mandatory_changes > 0); if(changes_happened) { ret = zone_diff_verify_dnskey_presence(diff, zone, &rrset_to_sign, &ksks, &zsks); if(ISOK(ret)) { // sign the records, store the changes in vectors ret = zone_diff_sign(diff, zone, &rrset_to_sign, &ksks, &zsks, remove, add); #if DYNUPDATE_DIFF_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug3("update: sign: %{dnsname}: - %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug3("update: sign: %{dnsname}: + %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); } #endif ptr_vector_destroy(&rrset_to_sign); if(ISOK(ret)) { zone_diff_get_chain_changes(diff, &dc); // chain deletes should use the existing maps if possible (speed) or generate from the local state (all 'exists') // chain adds should use the local state (all exists not removed + all adds) #if DEBUG zone_diff_log(diff, MODULE_MSG_HANDLE, MSG_DEBUG2); #endif dnssec_chain_store_diff(&dc, diff, &zsks, remove, add); #if DYNUPDATE_DIFF_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug3("update: store: %{dnsname}: - %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug3("update: store: %{dnsname}: + %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); } #endif } } else { zone_diff_label_rr_vector_clear(remove); zone_diff_label_rr_vector_clear(add); ptr_vector_destroy(&rrset_to_sign); } } else { zone_diff_label_rr_vector_clear(remove); zone_diff_label_rr_vector_clear(add); ptr_vector_destroy(&rrset_to_sign); if(FAIL(mandatory_changes)) { log_warn("update: %{dnsname} update rejected: %r", zone->origin, mandatory_changes); } } dnssec_keystore_release_keys_from_vector(&zsks); dnssec_keystore_release_keys_from_vector(&ksks); ptr_vector_destroy(&zsks); ptr_vector_destroy(&ksks); } dnssec_chain_finalize(&dc); return ret; } #if ZDB_HAS_DNSSEC_SUPPORT /** * Get all DNSKEY records from the zone. * Load the private keys of these DNSKEY records in the keystore. * * @param zone * @return */ ya_result dynupdate_diff_load_private_keys(zdb_zone *zone) { ya_result return_code = SUCCESS; // ensure all the private keys are available or servfail const zdb_packed_ttlrdata *dnskey_rrset = zdb_zone_get_dnskey_rrset(zone); // zone is locked int ksk_count = 0; int zsk_count = 0; if(dnskey_rrset != NULL) { do { u16 flags = DNSKEY_FLAGS(*dnskey_rrset); u8 algorithm = DNSKEY_ALGORITHM(*dnskey_rrset); u16 tag = DNSKEY_TAG(*dnskey_rrset); // note: expensive dnssec_key *key = NULL; if(!((flags == DNSKEY_FLAGS_KSK) && zdb_zone_get_rrsig_push_allowed(zone))) { if(ISOK(return_code = dnssec_keystore_load_private_key_from_parameters(algorithm, tag, flags, zone->origin, &key))) // key properly released { dnskey_release(key); } else { log_warn("update: unable to load the private key 'K%{dnsname}+%03d+%05hd': %r", zone->origin, algorithm, tag, return_code); } } else { // on an RRSIG-push-allowed zone, don't try to load a KSK } if(flags == DNSKEY_FLAGS_KSK) { ++ksk_count; } else if(flags == DNSKEY_FLAGS_ZSK) { ++zsk_count; } dnskey_rrset = dnskey_rrset->next; } while(dnskey_rrset != NULL); return_code = ksk_count + zsk_count; } else { log_warn("update: there are no private keys in the zone %{dnsname}", zone->origin); return_code = DNSSEC_ERROR_RRSIG_NOZONEKEYS; } return return_code; } #endif /** * Writes the del then add records to the journal, * deletes the records marked as volatile, * exchanges the locks of the zone, * replays the journal * exchanges the locks back. * * Returns the result of the replay or SUCCESS if there was nothing to replay. * * @param zone * @param secondary_lock * @param del_vector * @param add_vector * @return */ ya_result dynupdate_diff_write_to_journal_and_replay(zdb_zone *zone, u8 secondary_lock, ptr_vector *del_vector, ptr_vector *add_vector) { ya_result ret = 0; bool changes_occurred = (ptr_vector_size(add_vector) + ptr_vector_size(del_vector)) > 2; if(changes_occurred) { // instead of storing to a buffer and back, could write an inputstream // translating the ptr_vector content on the fly s32 total_size_in_bytes = 0; for(int i = 0; i <= ptr_vector_last_index(del_vector); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(del_vector, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug2("update: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); total_size_in_bytes += dnsname_len(rr->fqdn); total_size_in_bytes += 10; total_size_in_bytes += rr->rdata_size; } for(int i = 0; i <= ptr_vector_last_index(add_vector); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add_vector, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug2("update: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); #if DEBUG switch(rr->rtype) { case TYPE_NSEC: { const u8 *fqdn = rr->rdata; const u8 *tbm = &fqdn[dnsname_len(fqdn)]; if((tbm - fqdn) == 0) { log_err("NSEC record has no type bitmap"); abort(); } break; } default: { break; } } #endif total_size_in_bytes += dnsname_len(rr->fqdn); total_size_in_bytes += 10; total_size_in_bytes += rr->rdata_size; } log_debug("update: %{dnsname}: writing message", zone->origin); output_stream baos; bytearray_output_stream_init(&baos, NULL, total_size_in_bytes); for(int i = 0; i <= ptr_vector_last_index(del_vector); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(del_vector, i); output_stream_write_dnsname(&baos, rr->fqdn); output_stream_write_u16(&baos, rr->rtype); output_stream_write_u16(&baos, rr->rclass); output_stream_write_nu32(&baos, rr->ttl); output_stream_write_nu16(&baos, rr->rdata_size); output_stream_write(&baos, rr->rdata, rr->rdata_size); if((rr->state & ZONE_DIFF_RR_VOLATILE) != 0) { zone_diff_label_rr_delete(rr); } } for(int i = 0; i <= ptr_vector_last_index(add_vector); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add_vector, i); output_stream_write_dnsname(&baos, rr->fqdn); output_stream_write_u16(&baos, rr->rtype); output_stream_write_u16(&baos, rr->rclass); output_stream_write_nu32(&baos, rr->ttl); output_stream_write_nu16(&baos, rr->rdata_size); output_stream_write(&baos, rr->rdata, rr->rdata_size); if((rr->state & ZONE_DIFF_RR_VOLATILE) != 0) { zone_diff_label_rr_delete(rr); } } log_debug1("update: %{dnsname}: message ready", zone->origin); input_stream bais; bytearray_input_stream_init(&bais, bytearray_output_stream_buffer(&baos), bytearray_output_stream_size(&baos), FALSE); log_debug("update: %{dnsname}: acquiring journal", zone->origin); journal* jnl = NULL; if(ISOK(ret = journal_acquire_from_zone_ex(&jnl, zone, TRUE))) { jnl->vtbl->minimum_serial_update(jnl, zone->text_serial); u32 journal_max_size = zone->wire_size / 3; zdb_zone_info_get_zone_max_journal_size(zone->origin, &journal_max_size); jnl->vtbl->maximum_size_update(jnl, journal_max_size); if(ISOK(ret = journal_append_ixfr_stream(jnl, &bais))) // writes a single page { log_debug("update: %{dnsname}: wrote %i bytes to the journal", zone->origin, total_size_in_bytes); bytearray_input_stream_reset(&bais); u32 current_serial = 0; if(secondary_lock != 0) { zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, secondary_lock); } ret = zdb_icmtl_replay_commit(zone, &bais, ¤t_serial); if(secondary_lock != 0) { zdb_zone_exchange_locks(zone, secondary_lock, ZDB_ZONE_MUTEX_SIMPLEREADER); } if(ISOK(ret)) { log_info("update: %{dnsname}: applied %u changes (%u bytes), serial=%u", zone->origin, ret, total_size_in_bytes, current_serial); ret = total_size_in_bytes; } else { log_err("update: %{dnsname}: could not apply changes: %r", zone->origin, ret); } } else if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { log_info("update: %{dnsname}: could not write %i bytes to the journal as it is full and the zone needs to be locally stored first", zone->origin, total_size_in_bytes); } else { log_err("update: %{dnsname}: could not write %i bytes to the journal: %r", zone->origin, total_size_in_bytes, ret); } journal_release(jnl); } else { log_err("update: %{dnsname}: could not acquire journal: %r", zone->origin, ret); } input_stream_close(&bais); output_stream_close(&baos); } return ret; } /** * * Computes the diff of an update. * * @param zone * @param reader * @param count * @param dryrun * @return */ ya_result dynupdate_diff(zdb_zone *zone, packet_unpack_reader_data *reader, u16 count, u8 secondary_lock, u32 flags) { yassert(zdb_zone_islocked(zone)); const bool dryrun = (flags & DYNUPDATE_DIFF_DRYRUN) != 0; const bool external = (flags & DYNUPDATE_DIFF_EXTERNAL) != 0; #if DEBUG log_debug("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i)", zone->origin, zone, reader, count, secondary_lock, dryrun); #endif if(zdb_zone_invalid(zone)) { #if DEBUG log_debug("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with ZDB_ERROR_ZONE_INVALID", zone->origin, zone, reader, count, secondary_lock, dryrun); #endif return ZDB_ERROR_ZONE_INVALID; } if(count == 0) { #if DEBUG log_debug("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) success with count == 0", zone->origin, zone, reader, count, secondary_lock, dryrun); #endif return SUCCESS; } if(packet_reader_opcode(reader) != (OPCODE_UPDATE >> OPCODE_SHIFT)) { #if DEBUG log_debug("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) not an update message", zone->origin, zone, reader, count, secondary_lock, dryrun); #endif return INVALID_STATE_ERROR; } // if the status was already set, stop if((zdb_zone_set_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF) & ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF) != 0) { return INVALID_STATE_ERROR; // already } zdb_packed_ttlrdata* soa = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA); if(soa == NULL) { #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with ZDB_ERROR_NOSOAATAPEX", zone->origin, zone, reader, count, secondary_lock, dryrun); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return ZDB_ERROR_NOSOAATAPEX; } #if DEBUG { u32 soa_serial = 0; rr_soa_get_serial(ZDB_PACKEDRECORD_PTR_RDATAPTR(soa), ZDB_PACKEDRECORD_PTR_RDATASIZE(soa), &soa_serial); log_debug("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) from serial %u", zone->origin, zone, reader, count, secondary_lock, dryrun, soa_serial); } #endif zone_diff diff; zone_diff_init(&diff, zone, zdb_zone_get_rrsig_push_allowed(zone)); dnsname_vector name_path; #if DEBUG memset(&name_path, 0xff, sizeof(name_path)); #endif u8 *rname; u8 *rdata; //u32 rname_size; u32 rttl; ya_result ret; // = SUCCESS; ya_result ret_status = 0; //s32 zsk_key_update_mask = 0; u16 rtype; u16 rclass; u16 rdata_size; s8 has_valid_ksk = -1; // unknown (don't care yet) u8 wire[MAX_DOMAIN_LENGTH + 10 + 65535]; #if DEBUG //rdata = (u8*)~0; // DEBUG //rname_size = ~0; // DEBUG //rttl = ~0; // DEBUG rtype = ~0; // DEBUG rclass = ~0; // DEBUG //rdata_size = ~0; // DEBUG #endif bool changes_occurred = FALSE; #if ZDB_HAS_DNSSEC_SUPPORT // zone load private keys bool dnssec_zone = zdb_zone_is_maintained(zone); bool check_for_last_nsec3param_removal = FALSE; if(dnssec_zone) { dynupdate_diff_load_private_keys(zone); } #endif log_debug1("update: %{dnsname}: reading message", zone->origin); // marks the SOA as being automatically removed (as the serial will increase) zone_diff_record_remove_automated(&diff, zone->apex, zone->origin, TYPE_SOA, soa->ttl, ZDB_PACKEDRECORD_PTR_RDATASIZE(soa), ZDB_PACKEDRECORD_PTR_RDATAPTR(soa)); int record_index = 0; do { u8 *p = wire; int s = sizeof(wire); if(FAIL(ret = packet_reader_read_fqdn(reader, p, s))) { log_err("update: %{dnsname}: failed reading next record fqdn: %r", zone->origin, ret); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed at fqdn with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_FORMERR)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_FORMERR); } rname = p; //rname_size = ret; p += ret; s -= ret; if(!dnsname_locase_verify_charspace(rname)) { log_err("update: %{dnsname}: fqdn contains illegal characters", zone->origin); log_memdump(MODULE_MSG_HANDLE,MSG_ERR, rname, dnsname_len(rname), 32); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_FORMERR)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_FORMERR); } if(!dnsname_is_subdomain(rname, zone->origin)) { log_err("update: %{dnsname}: %{dnsname} is not a sub-domain", zone->origin, rname); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_NOTZONE)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_NOTZONE); } if((ret = packet_reader_read(reader, p, 10)) != 10) { ret = UNEXPECTED_EOF; log_err("update: %{dnsname}: failed reading next record fields: %r", zone->origin, ret); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_FORMERR)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_FORMERR); } rtype = GET_U16_AT(p[0]); rclass = GET_U16_AT(p[2]); rttl = ntohl(GET_U32_AT(p[4])); rdata_size = ntohs(GET_U16_AT(p[8])); /** * Some records are used internally by yadifad to track chain creation states. * They shouldn't be received externally (e.g. DNS dynamic update) as it could wreak havoc with the logic. * This change avoids having to handle a legion of pitfalls. * * In the future, we may give the option to change the value of these 3 records at build time. * It may be useful for some specific use cases. * Alternatively, we may document how to change their value manually. */ if(external) { switch(rtype) { case TYPE_NSECCHAINSTATE: case TYPE_NSEC3CHAINSTATE: case TYPE_NSEC3PARAMQUEUED: { log_err("update: %{dnsname}: reserved record found in update message: %r", zone->origin, ret); zone_diff_finalize(&diff); zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_REFUSED); } } } if((rdata_size > 0) && (rclass == CLASS_ANY)) { log_err("update: %{dnsname}: next record has non-empty rdata with class ANY: %r", zone->origin, RCODE_ERROR_CODE(RCODE_FORMERR)); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_FORMERR)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_FORMERR); } /* * Simple consistency test: */ if((rdata_size == 0) && (rclass != CLASS_ANY)) { log_err("update: %{dnsname}: next record has empty rdata with non-ANY class: %r", zone->origin, RCODE_ERROR_CODE(RCODE_FORMERR)); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_FORMERR)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_FORMERR); } if(rdata_size > 0) { if(FAIL(ret = packet_reader_read_rdata(reader, rtype, rdata_size, p, s))) { log_err("update: %{dnsname}: failed reading next record rdata: %r", zone->origin, ret); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_FORMERR)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_FORMERR); } rdata = p; rdata_size = ret; rdata_desc wire_rdatadesc = {rtype, rdata_size, rdata}; log_debug1("update: %{dnsname}: record [%2i]: %{dnsname} %i %{dnsclass} %{dnstype} %{rdatadesc}", zone->origin, record_index, rname, rttl, &rclass, &rtype, &wire_rdatadesc); } else { rdata = NULL; log_debug1("update: %{dnsname}: record [%2i]: %{dnsname} %i %{dnsclass} %{dnstype}", zone->origin, record_index, rname, rttl, &rclass, &rtype); } ++record_index; dnsname_to_dnsname_vector(rname, &name_path); s32 idx; for(idx = 0; idx < zone->origin_vector.size; idx++) { if(!dnslabel_equals(zone->origin_vector.labels[zone->origin_vector.size - idx], name_path.labels[name_path.size - idx])) { log_err("update: %{dnsname}: %{dnsname} manual add/del of %{dnstype} records refused", zone->origin, rname, &rtype); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_NOTZONE)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_NOTZONE); } } if((rtype == TYPE_NSEC) || (rtype == TYPE_NSEC3)) { // reject any dynupdate operation on a dnssec-maintained record. log_err("update: %{dnsname}: %{dnsname} manual add/del of %{dnstype} records refused", zone->origin, rname, &rtype); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_REFUSED)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_REFUSED); } #if ZDB_HAS_NSEC3_SUPPORT // sanity checks // If the record is an NSEC3PARAM at the APEX if(rtype == TYPE_NSEC3PARAM) { if(!dnsname_equals_ignorecase(zone->origin, rname)) { // reject adding NSEC3PARAM anywhere else than in the apex log_err("update: %{dnsname}: %{dnsname} NSEC3PARAM : type is only allowed in the apex", zone->origin, rname); zone_diff_finalize(&diff); zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_REFUSED); } if(/*!ZONE_HAS_NSEC3PARAM(zone) &&*/ zdb_zone_has_nsec_chain(zone)) { // don't add/del NSEC3PARAM on a zone that is not already NSEC3 (it works if the zone is not secure but only if the zone has keys already. So for now : disabled) log_err("update: %{dnsname}: %{dnsname} NSEC3PARAM add/del refused on an non-dnssec3 zone", zone->origin, rname); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_REFUSED)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_REFUSED); } else { if((rdata != NULL) && (NSEC3_RDATA_ALGORITHM(rdata) != NSEC3_DIGEST_ALGORITHM_SHA1)) { // don't touch an unsupported digest log_err("update: %{dnsname}: %{dnsname} NSEC3PARAM with unsupported digest algorithm %d", zone->origin, rname, NSEC3_RDATA_ALGORITHM(rdata)); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_NOTIMP)); #endif zone_diff_finalize(&diff); zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_NOTIMP); } if(rclass == CLASS_ANY) // remove all { // don't remove all NSEC3PARAMs from an NSEC3 zone log_err("update: %{dnsname}: %{dnsname} cannot remove all NSEC3PARAM of an NSEC3 zone", zone->origin, rname); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_REFUSED)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_REFUSED); } else if(rclass == CLASS_NONE) // remove one { /// @note important: don't remove the first NSEC3PARAM from an NSEC3 zone if no other is available /// also note that given the new mechanisms, an NSEC3PARAM being added will not count as one until /// the whole chain has been created /// This condition is tested later. check_for_last_nsec3param_removal = TRUE; ret_status |= DYNUPDATE_DIFF_RETURN_NSEC3PARAM; zdb_zone_set_status(zone, ZDB_ZONE_STATUS_GENERATE_CHAIN); } else // add one { // scan-build false positive : assumes rdata_size < 0 => impossible // or ((rdata_size == 0) & (rclass == CLASS_ANY)) => this would branch in the first "if" a few lines above /* ret = nsec3_zone_set_status(zone, ZDB_ZONE_MUTEX_DYNUPDATE, NSEC3PARAM_RDATA_ALGORITHM(rdata), 0, NSEC3PARAM_RDATA_ITERATIONS(rdata), NSEC3PARAM_RDATA_SALT(rdata), NSEC3PARAM_RDATA_SALT_LEN(rdata), NSEC3_ZONE_ENABLED|NSEC3_ZONE_GENERATING); */ #if DYNUPDATE_DIFF_DO_NOT_ADD_NSEC3_ON_NON_NSEC3_ZONE ret = 0; // nsec3_zone_set_status recursively calls to dynupdate_diff : don't do it here. continue; #else rtype = TYPE_NSEC3PARAMQUEUED; ret_status |= DYNUPDATE_DIFF_RETURN_NSEC3PARAM; zdb_zone_set_status(zone, ZDB_ZONE_STATUS_GENERATE_CHAIN); #endif } } } // type == TYPE_NSEC3PARAM else if(((rtype == TYPE_NSEC3PARAMQUEUED) || (rtype == TYPE_NSEC3CHAINSTATE)) && (rdata != NULL)) { u16 expected_rdata_size = NSEC3PARAM_RDATA_SIZE_FROM_SALT(NSEC3PARAM_RDATA_SALT_LEN(rdata)); if(rtype == TYPE_NSEC3CHAINSTATE) { ++expected_rdata_size; /// @todo 20211202 edf -- check the status byte (last one in the rdata) makes sense } if(rdata_size != expected_rdata_size) { log_warn("update: %{dnsname}: %{dnsname} %{dnstype} has as a size of %d when it should be %d", zone->origin, rname, &rtype, rdata_size, expected_rdata_size); zone_diff_finalize(&diff); zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_NOTIMP); } // check the content is looking like an NSEC3PARAM if(NSEC3PARAM_RDATA_ALGORITHM(rdata) != NSEC3_DIGEST_ALGORITHM_SHA1) { log_warn("update: %{dnsname}: %{dnsname} %{dnstype} with unsupported digest algorithm %d", zone->origin, rname, &rtype, NSEC3PARAM_RDATA_ALGORITHM(rdata)); zone_diff_finalize(&diff); zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_NOTIMP); } if(NSEC3PARAM_RDATA_FLAGS(rdata) > 1) { log_warn("update: %{dnsname}: %{dnsname} %{dnstype} with unsupported flags %d", zone->origin, rname, &rtype, NSEC3PARAM_RDATA_FLAGS(rdata)); zone_diff_finalize(&diff); zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_NOTIMP); } /// @todo 20211202 edf -- check if there are operations about this record going on and maybe reject this update because of it } #endif // ZDB_HAS_NSEC3_SUPPORT if(rclass == CLASS_NONE) { assert(rdata != NULL); // delete from an rrset if(rttl != 0) { zone_diff_finalize(&diff); log_err("update: %{dnsname}: %{dnsname} record delete expected a TTL set to 0", zone->origin, rname); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_FORMERR)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_FORMERR); } if(name_path.size <= zone->origin_vector.size) { if((rtype == TYPE_SOA) || (rtype == TYPE_ANY)) { // refused log_err("update: %{dnsname}: refused", zone->origin); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_REFUSED)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_REFUSED); } if(rtype == TYPE_DNSKEY) { u16 key_flags = DNSKEY_FLAGS_FROM_RDATA(rdata); // scan-build false positive // (rdata == NULL) && (rdata_size == 0) can only occur if (rclass == CLASS_ANY) // the condition is tested and exited for a FORMERR around line 5557 if(key_flags == DNSKEY_FLAGS_ZSK) { ret_status |= DYNUPDATE_DIFF_RETURN_DNSKEY_REMOVED; } if(has_valid_ksk < 0) { has_valid_ksk = dnssec_keystore_has_usable_ksk(zone->origin, time(NULL))?1:0; } } } #if DEBUG log_debug("update: %{dnsname}: delete %{dnsname} %{dnstype} any", zone->origin, rname, &rtype); #endif zdb_rr_label* rr_label = zdb_rr_label_find_exact(zone->apex, name_path.labels, (name_path.size - zone->origin_vector.size) - 1); if(rr_label != NULL) { #if DEBUG if(RR_LABEL_IRRELEVANT(rr_label)) // debug { log_debug("update: %{dnsname}: %{dnsname} is irrelevant (0)", zone->origin, rname); } #endif zdb_packed_ttlrdata *rr; if((rr = zdb_record_find(&rr_label->resource_record_set, rtype)) != NULL) { bool exists = FALSE; do { if(ZDB_PACKEDRECORD_PTR_RDATASIZE(rr) == rdata_size) { // scan-build false positive : rdata cannot be NULL // (rdata == NULL) && (rdata_size == 0) can only occur if (rclass == CLASS_ANY) // the condition is tested and exited for a FORMERR around line 5557 if(memcmp(ZDB_PACKEDRECORD_PTR_RDATAPTR(rr), rdata, rdata_size) == 0) { exists = TRUE; break; } } rr = rr->next; } while(rr != NULL); if(exists) { if(rr_label != zone->apex) { zone_diff_add_fqdn_children(&diff, rname, rr_label); zone_diff_add_fqdn_parents_up_to_below_apex(&diff, rname, zone); } if(!zone_diff_record_remove_existing(&diff, rr_label, rname, rtype, rttl, rdata_size, rdata)) { rdata_desc rd = {rtype, rdata_size, rdata}; log_warn("update: %{dnsname}: delete %{dnsname} %{typerdatadesc} not in zone", zone->origin, rname, &rd); } } else { log_debug("update: %{dnsname}: delete %{dnsname} NONE %{dnstype}: no record match", zone->origin, rname, &rtype); } } else { log_debug("update: %{dnsname}: delete %{dnsname} NONE %{dnstype}: no type match", zone->origin, rname, &rtype); } } else { log_debug("update: %{dnsname}: delete %{dnsname} NONE %{dnstype}: no label match", zone->origin, rname, &rtype); } } else if(rclass == CLASS_ANY) // delete all RRSETs { if((rttl != 0) || (rdata_size != 0)) { log_err("update: %{dnsname}: format error", zone->origin); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_FORMERR)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_FORMERR); } if(name_path.size <= zone->origin_vector.size) { if((rtype == TYPE_SOA) || (rtype == TYPE_ANY)) { // refused log_err("update: %{dnsname}: refused", zone->origin); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_REFUSED)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_REFUSED); } if(rtype == TYPE_DNSKEY) { // get all keys from the zone_diff // if one of these keys is a ZSK, set the ret_status flag accordingly const zone_diff_fqdn *apex = zone_diff_fqdn_get_const(&diff, zone->origin); const zone_diff_fqdn_rr_set *dnskey_rrset = zone_diff_fqdn_rr_get_const(apex, TYPE_DNSKEY); if(dnskey_rrset != NULL) { ptr_set_iterator rr_iter; ptr_set_iterator_init(&dnskey_rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)rr_node->value; if((rr->state & ZONE_DIFF_RR_IN_ZONE) != 0) { u16 key_flags = DNSKEY_FLAGS_FROM_RDATA(rr->rdata); if(key_flags == DNSKEY_FLAGS_ZSK) { ret_status |= DYNUPDATE_DIFF_RETURN_DNSKEY_REMOVED; } if(has_valid_ksk < 0) { has_valid_ksk = dnssec_keystore_has_usable_ksk(zone->origin, time(NULL))?1:0; } diff.may_add_dnskey = TRUE; break; } } diff.may_remove_dnskey = TRUE; if(has_valid_ksk < 0) { has_valid_ksk = dnssec_keystore_has_usable_ksk(zone->origin, time(NULL))?1:0; } } else { diff.may_remove_dnskey = FALSE; has_valid_ksk = FALSE; } } } if(rtype != TYPE_ANY) { // delete an rrset #if DEBUG log_debug2("update: %{dnsname}: delete %{dnsname} %{dnstype} ...", zone->origin, rname, &rtype); #endif zdb_rr_label *rr_label = zdb_rr_label_find_exact(zone->apex, name_path.labels, (name_path.size - zone->origin_vector.size) - 1); if(rr_label != NULL) { #if DEBUG if(RR_LABEL_IRRELEVANT(rr_label)) // debug { log_debug2("update: %{dnsname}: %{dnsname} is irrelevant (1)", zone->origin, rname); } #endif if(zdb_record_find(&rr_label->resource_record_set, rtype) != NULL) { if(rr_label != zone->apex) { zone_diff_add_fqdn_children(&diff, rname, rr_label); zone_diff_add_fqdn_parents_up_to_below_apex(&diff, rname, zone); } zone_diff_record_remove_all(&diff, rr_label, rname, rtype); } else { log_debug("update: %{dnsname}: delete %{dnsname} %{dnstype} ANY: no type match", zone->origin, rname, &rtype); } } else { log_debug("update: %{dnsname}: delete %{dnsname} %{dnstype} ANY: no label match", zone->origin, rname, &rtype); } } else { // delete all rrsets #if DEBUG log_debug2("update: %{dnsname}: delete %{dnsname} %{dnstype} ...", zone->origin, rname, &rtype); #endif zdb_rr_label* rr_label = zdb_rr_label_find_exact(zone->apex, name_path.labels, (name_path.size - zone->origin_vector.size) - 1); if(rr_label != NULL) { #if DEBUG if(RR_LABEL_IRRELEVANT(rr_label)) // debug { log_debug2("update: %{dnsname}: %{dnsname} is irrelevant (2)", zone->origin, rname); } if(RR_LABEL_EMPTY_TERMINAL(rr_label)) { log_debug2("update: %{dnsname}: %{dnsname} is an empty terminal (2)", zone->origin, rname); } #endif if(rr_label != zone->apex) { zone_diff_add_fqdn_children(&diff, rname, rr_label); zone_diff_add_fqdn_parents_up_to_below_apex(&diff, rname, zone); zone_diff_record_remove_all_sets(&diff, rr_label, rname); } else { // apex log_err("update: %{dnsname}: removing all records from the apex is forbidden", zone->origin); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_REFUSED)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_REFUSED); } } else { log_debug("update: %{dnsname}: delete %{dnsname} %{dnstype} ANY: no label match", zone->origin, rname, &rtype); } } } else { // add record to an rrset assert(rdata != NULL); // to help scan-build // scan-build false positive : rdata cannot be NULL // (rdata == NULL) && (rdata_size == 0) can only occur if (rclass == CLASS_ANY) // the condition is tested and exited for a FORMERR around line 5557 zdb_rr_label* rr_label = zdb_rr_label_find_exact(zone->apex, name_path.labels, (name_path.size - zone->origin_vector.size) - 1); zone_diff_record_add(&diff, rr_label, rname, rtype, rttl, rdata_size, rdata); const u8 *above_fqdn = rname; for(int index = 1; index < name_path.size; ++index) { zdb_rr_label* above_rr_label = zdb_rr_label_find_exact(zone->apex, name_path.labels + index, (name_path.size - index - zone->origin_vector.size) - 1); above_fqdn += above_fqdn[0] + 1; zone_diff_fqdn_add(&diff, above_fqdn, above_rr_label); } if(rr_label != NULL) { if(rr_label != zone->apex) { zone_diff_add_fqdn_children(&diff, rname, rr_label); zone_diff_add_fqdn_parents_up_to_below_apex(&diff, rname, zone); } else { if(rtype == TYPE_DNSKEY) { u16 key_flags = DNSKEY_FLAGS_FROM_RDATA(rdata); if(key_flags == DNSKEY_FLAGS_ZSK) { ret_status |= DYNUPDATE_DIFF_RETURN_DNSKEY_ADDED; } diff.may_add_dnskey = TRUE; } } } } } while(--count > 0); if(check_for_last_nsec3param_removal) { bool at_least_one_nsec3param_remains = FALSE; // look if there is any NSEC3PARAM remaining in the zone const zone_diff_fqdn *apex = zone_diff_fqdn_get_const(&diff, zone->origin); const zone_diff_fqdn_rr_set *nsec3param_rrset = zone_diff_fqdn_rr_get_const(apex, TYPE_NSEC3PARAM); if(nsec3param_rrset != NULL) { ptr_set_iterator rr_iter; ptr_set_iterator_init(&nsec3param_rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *rr_node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr*)rr_node->value; if((rr->state & (ZONE_DIFF_RR_ADD|ZONE_DIFF_RR_REMOVE)) != ZONE_DIFF_RR_REMOVE) { at_least_one_nsec3param_remains = TRUE; break; } } if(!at_least_one_nsec3param_remains) { log_err("update: %{dnsname}: %{dnsname} cannot remove the last NSEC3PARAM of an NSEC3 zone", zone->origin, rname); zone_diff_finalize(&diff); #if DEBUG log_err("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) failed with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, RCODE_ERROR_CODE(RCODE_REFUSED)); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return RCODE_ERROR_CODE(RCODE_REFUSED); } // remove the record, create the removal placeholder } // else there was no NSEC3PARAM to begin with } if(ISOK(ret) && !dryrun) { ptr_vector add = PTR_VECTOR_EMPTY; ptr_vector del = PTR_VECTOR_EMPTY; #if DEBUG log_debug1("update: %{dnsname}: storing diff", zone->origin); zone_diff_log(&diff, MODULE_MSG_HANDLE, MSG_DEBUG2); #endif if(ISOK(ret = zone_diff_store_diff(&diff, zone, &del, &add))) { zdb_zone_error_status_clear(zone, ZDB_ZONE_ERROR_STATUS_DIFF_FAILEDNOUSABLE_KEYS); #if DEBUG log_debug1("update: %{dnsname}: stored diff", zone->origin); for(int i = 0; i <= ptr_vector_last_index(&del); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&del, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug1("update: %{dnsname}: - %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(&add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug1("update: %{dnsname}: + %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); } #endif changes_occurred = (ptr_vector_size(&add) + ptr_vector_size(&del)) > 2; #if DEBUG log_debug1("update: %{dnsname}: changes: %i", zone->origin, changes_occurred); #endif if(changes_occurred) { // instead of storing to a buffer and back, could write an inputstream // translating the ptr_vector content on the fly s32 total = 0; for(int i = 0; i <= ptr_vector_last_index(&del); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&del, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug2("update: %{dnsname}: - %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); total += dnsname_len(rr->fqdn); total += 10; total += rr->rdata_size; } for(int i = 0; i <= ptr_vector_last_index(&add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug2("update: %{dnsname}: + %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); total += dnsname_len(rr->fqdn); total += 10; total += rr->rdata_size; } output_stream baos; bytearray_output_stream_init(&baos, NULL, total); for(int i = 0; i <= ptr_vector_last_index(&del); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&del, i); /* rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("update: %{dnsname}: - %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); */ output_stream_write_dnsname(&baos, rr->fqdn); output_stream_write_u16(&baos, rr->rtype); output_stream_write_u16(&baos, rr->rclass); output_stream_write_nu32(&baos, rr->ttl); output_stream_write_nu16(&baos, rr->rdata_size); output_stream_write(&baos, rr->rdata, rr->rdata_size); } for(int i = 0; i <= ptr_vector_last_index(&add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&add, i); /* rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("update: %{dnsname}: + %{dnsname} %9i %{typerdatadesc}", zone->origin, rr->fqdn, rr->ttl, &rd); */ output_stream_write_dnsname(&baos, rr->fqdn); output_stream_write_u16(&baos, rr->rtype); output_stream_write_u16(&baos, rr->rclass); output_stream_write_nu32(&baos, rr->ttl); output_stream_write_nu16(&baos, rr->rdata_size); output_stream_write(&baos, rr->rdata, rr->rdata_size); } input_stream bais; bytearray_input_stream_init(&bais, bytearray_output_stream_buffer(&baos), bytearray_output_stream_size(&baos), FALSE); journal* jnl = NULL; if(ISOK(ret = journal_acquire_from_zone_ex(&jnl, zone, TRUE))) { jnl->vtbl->minimum_serial_update(jnl, zone->text_serial); u32 journal_max_size = zone->wire_size / 3; zdb_zone_info_get_zone_max_journal_size(zone->origin, &journal_max_size); jnl->vtbl->maximum_size_update(jnl, journal_max_size); if(ISOK(ret = journal_append_ixfr_stream(jnl, &bais))) // writes a single page { log_debug("update: %{dnsname}: wrote %i bytes to the journal", zone->origin, total); bytearray_input_stream_reset(&bais); u32 current_serial = 0; if(secondary_lock != 0) { zdb_zone_exchange_locks(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, secondary_lock); } ret = zdb_icmtl_replay_commit(zone, &bais, ¤t_serial); if(secondary_lock != 0) { zdb_zone_exchange_locks(zone, secondary_lock, ZDB_ZONE_MUTEX_SIMPLEREADER); } if(ISOK(ret)) { log_debug("update: %{dnsname}: applied journal changes", zone->origin); if(ret_status & (DYNUPDATE_DIFF_RETURN_DNSKEY_ADDED|DYNUPDATE_DIFF_RETURN_DNSKEY_REMOVED)) { ret_status |= DYNUPDATE_DIFF_RETURN_DNSKEY_UPDATED; } } else { log_err("update: %{dnsname}: could not apply journal changes: %r", zone->origin, ret); } } else { if(ret == ZDB_JOURNAL_SERIAL_RANGE_LOCKED) { log_notice("update: %{dnsname}: could not write %i bytes to the journal as it is full and busy", zone->origin, total); } else if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { log_info("update: %{dnsname}: could not write %i bytes to the journal as it is full and the zone needs to be locally stored first", zone->origin, total); } else { log_err("update: %{dnsname}: could not write %i bytes to the journal: %r", zone->origin, total, ret); } } journal_release(jnl); } input_stream_close(&bais); output_stream_close(&baos); #if 0 if(!zdb_zone_is_maintained(zone) && (zone_get_maintain_mode(zone) == ZDB_ZONE_MAINTAIN_NOSEC)) { if(zone_diff_adds_nsec3param(&diff)) { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_GENERATE_CHAIN); } else if(zone_diff_has_zsk(&diff)) { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_GENERATE_CHAIN); } } #else if(!zdb_zone_is_maintained(zone)) { u8 maintain_mode = zone_get_maintain_mode(zone); switch(maintain_mode) { case ZDB_ZONE_MAINTAIN_NOSEC: { if(zone_diff_adds_nsec3param(&diff) || zone_diff_has_or_adds_nsec3param(&diff)) { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_GENERATE_CHAIN); } else if(zone_diff_has_zsk(&diff)) { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_GENERATE_CHAIN); } break; } case ZDB_ZONE_MAINTAIN_NSEC: { if(zone_diff_adds_nsec3param(&diff)) { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_GENERATE_CHAIN); } else if(zone_diff_has_zsk(&diff)) { //zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_GENERATE_CHAIN); } break; } case ZDB_ZONE_MAINTAIN_NSEC3: case ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT: { if(zone_diff_adds_nsec3param(&diff) || zone_diff_has_or_adds_nsec3param(&diff)) { //zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_GENERATE_CHAIN); } else if(zone_diff_has_zsk(&diff)) { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_GENERATE_CHAIN); } break; } default: { break; } } } #endif } } // storediff succeeded else { if(zdb_zone_error_status_getnot_set(zone, ZDB_ZONE_ERROR_STATUS_DIFF_FAILEDNOUSABLE_KEYS)) { log_err("update: %{dnsname}: diff failed: %r", zone->origin, ret); } } zone_diff_label_rr_vector_clear(&del); zone_diff_label_rr_vector_clear(&add); ptr_vector_destroy(&add); ptr_vector_destroy(&del); } #if DEBUG { zdb_packed_ttlrdata *soa = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA); if(soa != NULL) { u32 soa_serial = 0; rr_soa_get_serial(ZDB_PACKEDRECORD_PTR_RDATAPTR(soa), ZDB_PACKEDRECORD_PTR_RDATASIZE(soa), &soa_serial); log_debug("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) to serial %u", zone->origin, zone, reader, count, secondary_lock, dryrun, soa_serial); } else { log_debug("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) has no SOA anymore", zone->origin, zone, reader, count, secondary_lock, dryrun); } } #endif log_debug("update: %{dnsname}: done", zone->origin); zone_diff_finalize(&diff); if(ISOK(ret)) { ret = ret_status; } #if DEBUG log_debug("dynupdate_diff(%{dnsname}@%p, %p, %i, %x, %i) returned with %r", zone->origin, zone, reader, count, secondary_lock, dryrun, ret); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_IN_DYNUPDATE_DIFF); return ret; } yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dynupdate-message.c0000644000000000000000000000013214505005531022547 xustar000000000000000030 mtime=1695812441.752972306 30 atime=1695812445.802030296 30 ctime=1695812495.153737112 yadifa-2.6.5-11201/lib/dnsdb/src/dynupdate-message.c0000664000374500037450000002163514505005531022520 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbupdate Dynamic update functions * @ingroup dnsdb * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include "dnsdb/dynupdate-message.h" #define DMSGPCKT_TAG 0x544b435047534d44 // Disable detailled diff log even in debug builds #define DYNUPDATE_DIFF_DETAILLED_LOG 0 #ifndef DYNUPDATE_DIFF_DETAILLED_LOG #if DEBUG #define DYNUPDATE_DIFF_DETAILLED_LOG 1 #else #define DYNUPDATE_DIFF_DETAILLED_LOG 0 #endif #endif /////////////////////////////////////////////////////////////////////////////// /** * Initialises a simple update buffer * * @param dmsg */ void dynupdate_message_init(dynupdate_message *dmsg, const u8 *origin, u16 rclass) { dmsg->size = MAX_U16; MALLOC_OR_DIE(u8*, dmsg->packet, dmsg->size, DMSGPCKT_TAG); // packet_writer_init is for valid messages. For writing a new message use: packet_writer_create(&dmsg->pw, dmsg->packet, dmsg->size); dmsg->rclass = rclass; message_header *hdr = (message_header*)dmsg->packet; #if DEBUG memset(dmsg->packet, 0xcc, dmsg->size); #endif ZEROMEMORY(hdr, DNS_HEADER_LENGTH); hdr->opcode = OPCODE_UPDATE; packet_writer_add_fqdn(&dmsg->pw, origin); packet_writer_add_u16(&dmsg->pw, TYPE_SOA); packet_writer_add_u16(&dmsg->pw, rclass); hdr->qdcount = NU16(1); } void dynupdate_message_reset(dynupdate_message *dmsg, const u8 *origin, u16 rclass) { // packet_writer_init is for valid messages. For writing a new message use: packet_writer_create(&dmsg->pw, dmsg->packet, dmsg->size); dmsg->rclass = rclass; message_header *hdr = (message_header*)dmsg->packet; #if DEBUG memset(dmsg->packet, 0xcc, dmsg->size); #endif ZEROMEMORY(hdr, DNS_HEADER_LENGTH); hdr->opcode = OPCODE_UPDATE; packet_writer_add_fqdn(&dmsg->pw, origin); packet_writer_add_u16(&dmsg->pw, TYPE_SOA); packet_writer_add_u16(&dmsg->pw, rclass); hdr->qdcount = NU16(1); } /** * Releases resources. * * @param dmsg */ void dynupdate_message_finalize(dynupdate_message *dmsg) { //packet_writer_finalize(&dmsg->pw); free(dmsg->packet); } /** * Sets a reader up for the buffer. * * @param dmsg * @param purd */ void dynupdate_message_set_reader(dynupdate_message *dmsg, packet_unpack_reader_data *purd) { yassert(dmsg->pw.packet_offset >= DNS_HEADER_LENGTH); packet_reader_init(purd, dmsg->packet, dmsg->pw.packet_offset); } /** * Return the number of update records. * * @param dmsg * @return */ u16 dynupdate_message_get_count(dynupdate_message *dmsg) { message_header *hdr = (message_header*)dmsg->packet; u16 count = ntohs(hdr->nscount); return count; } /** * Adds a dnskey record to the buffer * * @param dmsg * @param ttl * @param key * @return */ ya_result dynupdate_message_add_dnskey(dynupdate_message *dmsg, s32 ttl, const dnssec_key *key) { u32 rdata_size = key->vtbl->dnssec_key_rdatasize(key); u32 remaining = packet_writer_get_remaining_capacity(&dmsg->pw); ya_result ret = BUFFER_WOULD_OVERFLOW; // the first 2 is assuming compression will take place // which is as it should be since the messages are initialised with the fqdn of the zone if(remaining >= 2 + 2 + 2 + 4 + 2 + rdata_size) { if(ISOK(ret = packet_writer_add_fqdn(&dmsg->pw, &dmsg->packet[DNS_HEADER_LENGTH]))) { packet_writer_add_u16(&dmsg->pw, TYPE_DNSKEY); packet_writer_add_u16(&dmsg->pw, dmsg->rclass); packet_writer_add_u32(&dmsg->pw, htonl(ttl)); packet_writer_add_u16(&dmsg->pw, htons(rdata_size)); key->vtbl->dnssec_key_writerdata(key, packet_writer_get_next_u8_ptr(&dmsg->pw), rdata_size); packet_writer_forward(&dmsg->pw, rdata_size); message_header *hdr = (message_header*)dmsg->packet; hdr->nscount = htons(ntohs(hdr->nscount) + 1); } } return ret; } /** * Deletes a dnskey record to the buffer * * @param dmsg * @param ttl * @param key * @return */ ya_result dynupdate_message_del_dnskey(dynupdate_message *dmsg, const dnssec_key *key) { u32 rdata_size = key->vtbl->dnssec_key_rdatasize(key); u32 remaining = packet_writer_get_remaining_capacity(&dmsg->pw); ya_result ret = BUFFER_WOULD_OVERFLOW; if(remaining >= 2 + 2 + 2 + 4 + 2 + rdata_size) { if(ISOK(ret = packet_writer_add_fqdn(&dmsg->pw, &dmsg->packet[DNS_HEADER_LENGTH]))) { packet_writer_add_u16(&dmsg->pw, TYPE_DNSKEY); packet_writer_add_u16(&dmsg->pw, CLASS_NONE); packet_writer_add_u32(&dmsg->pw, 0); packet_writer_add_u16(&dmsg->pw, htons(rdata_size)); key->vtbl->dnssec_key_writerdata(key, packet_writer_get_next_u8_ptr(&dmsg->pw), rdata_size); packet_writer_forward(&dmsg->pw, rdata_size); message_header *hdr = (message_header*)dmsg->packet; hdr->nscount = htons(ntohs(hdr->nscount) + 1); } } return ret; } /** * Appends a "add RR" command to the buffer. * * @param dmsg * @param fqdn * @param rtype * @param ttl * @param rdata_size * @param rdata * @return */ ya_result dynupdate_message_add_record(dynupdate_message *dmsg, const u8 *fqdn, u16 rtype, s32 ttl, u16 rdata_size, const void *rdata) { ya_result ret; if(ISOK(ret = packet_writer_add_record(&dmsg->pw, fqdn, rtype, dmsg->rclass, ttl, rdata, rdata_size))) { message_header *hdr = (message_header*)dmsg->packet; hdr->nscount = htons(ntohs(hdr->nscount) + 1); } return ret; } /** * Appends a "delete RR" command to the buffer. * * @param dmsg * @param fqdn * @param rtype * @param ttl * @param rdata_size * @param rdata * @return */ ya_result dynupdate_message_del_record(dynupdate_message *dmsg, const u8 *fqdn, u16 rtype, s32 ttl, u16 rdata_size, const void *rdata) { ya_result ret; if(ISOK(ret = packet_writer_add_record(&dmsg->pw, fqdn, rtype, TYPE_NONE, ttl, rdata, rdata_size))) { message_header *hdr = (message_header*)dmsg->packet; hdr->nscount = htons(ntohs(hdr->nscount) + 1); } return ret; } /** * * Appends a "delete RRSET" command to the buffer. * * @param dmsg * @param fqdn * @param rtype * @return */ ya_result dynupdate_message_del_record_set(dynupdate_message *dmsg, const u8 *fqdn, u16 rtype) { ya_result ret; if(ISOK(ret = packet_writer_add_record(&dmsg->pw, fqdn, rtype, TYPE_ANY, 0, NULL, 0))) { message_header *hdr = (message_header*)dmsg->packet; hdr->nscount = htons(ntohs(hdr->nscount) + 1); } return ret; } /** * Appends a "delete fqdn" command to the buffer. * * @param dmsg * @param fqdn * @return */ ya_result dynupdate_message_del_fqdn(dynupdate_message *dmsg, const u8 *fqdn) { ya_result ret; if(ISOK(ret = packet_writer_add_record(&dmsg->pw, fqdn, TYPE_ANY, TYPE_ANY, 0, NULL, 0))) { message_header *hdr = (message_header*)dmsg->packet; hdr->nscount = htons(ntohs(hdr->nscount) + 1); } return ret; } yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dynupdate-diff-nochain.c0000644000000000000000000000013214505005531023450 xustar000000000000000030 mtime=1695812441.732972019 30 atime=1695812445.801030282 30 ctime=1695812495.155737141 yadifa-2.6.5-11201/lib/dnsdb/src/dynupdate-diff-nochain.c0000664000374500037450000001261414505005531023416 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbupdate Dynamic update functions * @ingroup dnsdb * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include "dnsdb/dynupdate-diff.h" static bool dnssec_chain_node_nochain_fqdn_is_covered(const zone_diff_fqdn *diff_fqdn) { (void)diff_fqdn; return FALSE; } static bool dnssec_chain_node_nochain_fqdn_was_covered(const zone_diff_fqdn *diff_fqdn) { (void)diff_fqdn; return FALSE; } static dnssec_chain_node_t dnssec_chain_node_nochain_new(const u8 *fqdn, dnssec_chain_head_t chain) { (void)fqdn; (void)chain; return NULL; } static void dnssec_chain_node_nochain_delete(dnssec_chain_node_t node_) { (void)node_; } static int dnssec_chain_node_nochain_compare(const void *a_, const void *b_) { (void)a_; (void)b_; return 0; } static dnssec_chain_node_t dnssec_chain_node_nochain_prev(const dnssec_chain_node_t node_) { (void)node_; return NULL; } static dnssec_chain_node_t dnssec_chain_node_nochain_next(const dnssec_chain_node_t node_) { (void)node_; return NULL; } static u8 dnssec_chain_node_nochain_state_get(const dnssec_chain_node_t node_) { (void)node_; return 0; } static void dnssec_chain_node_nochain_state_set(dnssec_chain_node_t node_, u8 value) { (void)node_; (void)value; } static void dnssec_chain_node_nochain_merge(dnssec_chain_node_t node_, dnssec_chain_node_t with_) { (void)node_; (void)with_; } static void dnssec_chain_node_nochain_publish_log(dnssec_chain_node_t from_, dnssec_chain_node_t to_) { (void)from_; (void)to_; } static void dnssec_chain_node_nochain_publish_add(dnssec_chain_head_t chain_, dnssec_chain_node_t from_, dnssec_chain_node_t to_, zone_diff *diff, ptr_vector *collection) { (void)chain_; (void)from_; (void)to_; (void)diff; (void)collection; } static void dnssec_chain_node_nochain_publish_delete(dnssec_chain_head_t chain_, dnssec_chain_node_t from_, dnssec_chain_node_t to_, zone_diff *diff, ptr_vector *collection) { (void)chain_; (void)from_; (void)to_; (void)diff; (void)collection; } static bool dnssec_chain_nochain_isempty(dnssec_chain_head_t chain_) { (void)chain_; return TRUE; } static void dnssec_chain_nochain_finalize_delete_callback(ptr_node *node) { (void)node; } static void dnssec_chain_node_nochain_format_writer_init(dnssec_chain_node_t node_, format_writer *outfw) { (void)node_; (void)outfw; } static bool dnssec_chain_node_rrset_should_be_signed(const zone_diff_fqdn *diff_fqdn, const zone_diff_fqdn_rr_set *rr_set) { (void)diff_fqdn; (void)rr_set; return FALSE; } static dnssec_chain_node_vtbl dnssec_chain_node_nochain_vtbl = { dnssec_chain_node_nochain_fqdn_is_covered, dnssec_chain_node_nochain_fqdn_was_covered, dnssec_chain_node_nochain_new, dnssec_chain_node_nochain_prev, dnssec_chain_node_nochain_merge, dnssec_chain_node_nochain_next, dnssec_chain_node_nochain_state_set, dnssec_chain_node_nochain_state_get, dnssec_chain_node_nochain_delete, dnssec_chain_node_nochain_publish_delete, dnssec_chain_node_nochain_publish_add, dnssec_chain_node_nochain_publish_log, dnssec_chain_node_nochain_compare, dnssec_chain_nochain_finalize_delete_callback, dnssec_chain_nochain_isempty, dnssec_chain_node_nochain_format_writer_init, dnssec_chain_node_rrset_should_be_signed, "nosec" }; const dnssec_chain_node_vtbl * dynupdate_nosec_chain_get_vtbl() { return &dnssec_chain_node_nochain_vtbl; } yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dynupdate-diff-nsec.c0000644000000000000000000000013214505005531022761 xustar000000000000000030 mtime=1695812441.742972162 30 atime=1695812445.802030296 30 ctime=1695812495.157737169 yadifa-2.6.5-11201/lib/dnsdb/src/dynupdate-diff-nsec.c0000664000374500037450000004236214505005531022732 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbupdate Dynamic update functions * @ingroup dnsdb * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #include #include #include "dnsdb/zdb_types.h" #include "dnsdb/nsec.h" #include #include #include "dnsdb/dnssec.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/dnssec-keystore.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/dynupdate-diff.h" #define MODULE_MSG_HANDLE g_database_logger extern logger_handle *g_database_logger; #define NSECNODE_TAG 0x45444f4e4345534e struct dnssec_chain_node_nsec { nsec_node *prev; nsec_node *self; nsec_node *next; u8 *fqdn; u8 state; u8 inverse_relative_name[MAX_DOMAIN_LENGTH]; }; typedef struct dnssec_chain_node_nsec dnssec_chain_node_nsec; static const u8* dnssec_chain_node_nsec_get_inverse_fqdn(const dnssec_chain_node_nsec *node) { return (node->self != NULL)?node->self->inverse_relative_name:node->inverse_relative_name; } static bool dnssec_chain_node_nsec_fqdn_is_covered(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (!diff_fqdn->under_delegation && (diff_fqdn->will_be_non_empty /*|| diff_fqdn->will_have_children*/)); } static bool dnssec_chain_node_nsec_fqdn_was_covered(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (!diff_fqdn->was_under_delegation && (diff_fqdn->was_non_empty /*|| diff_fqdn->will_have_children*/)); } static dnssec_chain_node_t dnssec_chain_node_nsec_new(const u8 *fqdn, dnssec_chain_head_t chain) { // compute the inverse of the fqdn for the chain // find if the node already exists // return the appropriate node nsec_zone* nsec_chain = (nsec_zone*)chain; u8 inverse_name[MAX_DOMAIN_LENGTH]; nsec_inverse_name(inverse_name, fqdn); nsec_zone_item *self = NULL; nsec_zone_item *prev; nsec_zone_item *next; bool empty = nsec_isempty(&nsec_chain); // true if there is not a single node in the NSEC chain if(!empty) { prev = nsec_find_interval_prev_mod(&nsec_chain, (const u8*)inverse_name); next = nsec_node_mod_next(prev); if(dnsname_compare(next->inverse_relative_name, inverse_name) == 0) { // exists self = next; next = nsec_node_mod_next(self); } } else { prev = NULL; next = NULL; } dnssec_chain_node_nsec *node; ZALLOC_OBJECT_OR_DIE(node, dnssec_chain_node_nsec, NSECNODE_TAG); node->prev = prev; node->self = self; node->next = next; node->fqdn = dnsname_zdup(fqdn); if(!empty) { if(self != NULL) { node->state = DNSSEC_CHAIN_EXISTS; } else { node->state = DNSSEC_CHAIN_ADD; dnsname_copy(node->inverse_relative_name, inverse_name); } if(node->prev != NULL) { if(node->next != NULL) { log_debug1("update: nsec: %{dnsname} has node %{dnsname} [ %{dnsname} ; %{dnsname} ] (%02x)", fqdn, dnssec_chain_node_nsec_get_inverse_fqdn(node), node->prev->inverse_relative_name, node->next->inverse_relative_name, node->state); } else { log_debug1("update: nsec: %{dnsname} has node %{dnsname} [ %{dnsname} ; ? [ (%02x)", fqdn, dnssec_chain_node_nsec_get_inverse_fqdn(node), node->prev->inverse_relative_name, node->state); } } else { log_debug1("update: nsec: %{dnsname} has node %{dnsname} [ ? ; %{dnsname} [ (%02x)", fqdn, dnssec_chain_node_nsec_get_inverse_fqdn(node), node->next->inverse_relative_name, node->state); } } else { node->state = DNSSEC_CHAIN_ADD; dnsname_copy(node->inverse_relative_name, inverse_name); } return (dnssec_chain_node_t)node; } static void dnssec_chain_node_nsec_delete(dnssec_chain_node_t node_) { dnssec_chain_node_nsec *nsec_node = (dnssec_chain_node_nsec*)node_; if(nsec_node->fqdn != NULL) { dnsname_zfree(nsec_node->fqdn); } ZFREE_OBJECT(nsec_node); } static bool dnssec_chain_node_nsec_has_bits_map(const dnssec_chain_node_nsec *node) { return (node->self != NULL) && (node->self->label != NULL) && (zdb_record_find(&node->self->label->resource_record_set, TYPE_NSEC) != NULL); } static int dnssec_chain_node_nsec_compare(const void *a_, const void *b_) { const dnssec_chain_node_nsec *a = (const dnssec_chain_node_nsec*)a_; const dnssec_chain_node_nsec *b = (const dnssec_chain_node_nsec*)b_; const u8 *a_inverse_fqdn = dnssec_chain_node_nsec_get_inverse_fqdn(a); const u8 *b_inverse_fqdn = dnssec_chain_node_nsec_get_inverse_fqdn(b); int ret = dnsname_compare(a_inverse_fqdn, b_inverse_fqdn); return ret; } static dnssec_chain_node_t dnssec_chain_node_nsec_prev(const dnssec_chain_node_t node_) { dnssec_chain_node_nsec *self = (dnssec_chain_node_nsec*)node_; dnssec_chain_node_nsec *node; u8 fqdn[MAX_DOMAIN_LENGTH]; ZALLOC_OBJECT_OR_DIE(node, dnssec_chain_node_nsec, NSECNODE_TAG); node->prev = NULL; node->self = self->prev; node->next = self->next; nsec_inverse_name(fqdn, self->prev->inverse_relative_name); node->fqdn = dnsname_zdup(fqdn); node->state = DNSSEC_CHAIN_EXISTS|DNSSEC_CHAIN_BEGIN; log_debug1("update: prev is %{dnsname} (%02x)", node->self->inverse_relative_name, node->state); return (dnssec_chain_node_t)node; } static dnssec_chain_node_t dnssec_chain_node_nsec_next(const dnssec_chain_node_t node_) { dnssec_chain_node_nsec *self = (dnssec_chain_node_nsec*)node_; dnssec_chain_node_nsec *node; u8 fqdn[MAX_DOMAIN_LENGTH]; ZALLOC_OBJECT_OR_DIE(node, dnssec_chain_node_nsec, NSECNODE_TAG); node->prev = self->prev; node->self = self->next; node->next = NULL; nsec_inverse_name(fqdn, self->next->inverse_relative_name); node->fqdn = dnsname_zdup(fqdn); node->state = DNSSEC_CHAIN_EXISTS|DNSSEC_CHAIN_END; log_debug1("update: next is %{dnsname} (%02x)", node->self->inverse_relative_name, node->state); return (dnssec_chain_node_t)node; } static u8 dnssec_chain_node_nsec_state_get(const dnssec_chain_node_t node_) { const dnssec_chain_node_nsec *self = (const dnssec_chain_node_nsec*)node_; return self->state; } static void dnssec_chain_node_nsec_state_set(dnssec_chain_node_t node_, u8 value) { dnssec_chain_node_nsec *self = (dnssec_chain_node_nsec*)node_; log_debug1("update: status %{dnsname} from %02x to %02x", dnssec_chain_node_nsec_get_inverse_fqdn(self), self->state, value); self->state = value; } static void dnssec_chain_node_nsec_merge(dnssec_chain_node_t node, dnssec_chain_node_t with) { u8 node_state = dnssec_chain_node_nsec_state_get(node); u8 with_state = dnssec_chain_node_nsec_state_get(with); if((node_state & DNSSEC_CHAIN_END) && (with_state & DNSSEC_CHAIN_BEGIN)) { dnssec_chain_node_nsec_state_set(node, dnssec_chain_node_nsec_state_get(node) & ~DNSSEC_CHAIN_END); } if((node_state & DNSSEC_CHAIN_BEGIN) && (with_state & DNSSEC_CHAIN_END)) { dnssec_chain_node_nsec_state_set(node, dnssec_chain_node_nsec_state_get(node) & ~DNSSEC_CHAIN_BEGIN); } dnssec_chain_node_nsec_delete(with); } /** * * * * @param nsec_chain * @param from * @param to * @param diff * @param collection * @param mask ZONE_DIFF_REMOVE: get the new state, ZONE_DIFF_ADD: get the old state * @param append_signatures append the signature (used so they can be removed) */ static void dnssec_chain_node_nsec_publish_record(nsec_zone *nsec_chain, dnssec_chain_node_nsec *from, dnssec_chain_node_nsec *to, zone_diff *diff, ptr_vector *collection, u8 mask, bool append_signatures) { (void)nsec_chain; const u8 *inverse_fqdn = dnssec_chain_node_nsec_get_inverse_fqdn(from); const u8 *next_inverse_fqdn = dnssec_chain_node_nsec_get_inverse_fqdn(to); log_debug1("update: %{dnsname}: %{dnsname}: %x: %{dnsname} -> %{dnsname}", diff->origin, inverse_fqdn, mask, inverse_fqdn, next_inverse_fqdn); // generate the label // previous and future bitmaps can be computed from zone_diff // generate the type map if(!dnssec_chain_node_nsec_has_bits_map(from) || ((mask & ZONE_DIFF_RR_REMOVE) && (from->state & DNSSEC_CHAIN_REMAP))) { type_bit_maps_context bitmap; u16 bitmap_size = zone_diff_type_bit_map_generate(diff, from->fqdn, &bitmap, mask | ZONE_DIFF_RR_REMOVE, 0, from->fqdn, append_signatures); if(mask & ZONE_DIFF_RR_REMOVE) { type_bit_maps_set_type(&bitmap, TYPE_NSEC); type_bit_maps_set_type(&bitmap, TYPE_RRSIG); bitmap_size = type_bit_maps_update_size(&bitmap); } yassert(bitmap_size != 0); int to_fqdn_len = dnsname_len(to->fqdn); u16 rdata_size = to_fqdn_len + bitmap_size; #if C11_VLA_AVAILABLE u8 rdata[rdata_size]; #else u8* const rdata = (u8* const)stack_alloc(rdata_size); #endif memcpy(&rdata, to->fqdn, to_fqdn_len); type_bit_maps_write(&bitmap, &rdata[to_fqdn_len]); type_bit_maps_finalize(&bitmap); // the record can be created zone_diff_label_rr *nsec_rr = zone_diff_label_rr_new( from->fqdn, TYPE_NSEC, CLASS_IN, diff->nttl, rdata, rdata_size, TRUE); nsec_rr->state |= ZONE_DIFF_RR_VOLATILE; ptr_vector_append(collection, nsec_rr); } else // bitmap already present { // get existing NSEC record const zdb_rr_label *label = from->self->label; const zdb_packed_ttlrdata* nsec_sll = zdb_record_find(&label->resource_record_set, TYPE_NSEC); yassert(nsec_sll != NULL); // get its type bitmap const u8 *nsec_rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec_sll); u16 nsec_rdata_size = ZDB_PACKEDRECORD_PTR_RDATASIZE(nsec_sll); s32 next_fqdn_len = dnsname_len(nsec_rdata); yassert(nsec_rdata_size >= next_fqdn_len); u16 bitmap_size = nsec_rdata_size - next_fqdn_len; // dnssec_chain_node_nsec_get_bits_map_size(from) int to_fqdn_len = dnsname_len(to->fqdn); u16 rdata_size = to_fqdn_len + bitmap_size; #if C11_VLA_AVAILABLE u8 rdata[rdata_size]; #else u8* const rdata = (u8* const)stack_alloc(rdata_size); #endif memcpy(&rdata, to->fqdn, to_fqdn_len); memcpy(&rdata[to_fqdn_len], &nsec_rdata[next_fqdn_len], bitmap_size); zone_diff_label_rr *nsec_rr = zone_diff_label_rr_new(from->fqdn, TYPE_NSEC, CLASS_IN, diff->nttl, rdata, rdata_size, TRUE); nsec_rr->state |= ZONE_DIFF_RR_VOLATILE; ptr_vector_append(collection, nsec_rr); if(append_signatures) { zdb_packed_ttlrdata* rrsig_sll = zdb_record_find(&label->resource_record_set, TYPE_RRSIG); while(rrsig_sll != NULL) { if(RRSIG_TYPE_COVERED(rrsig_sll) == TYPE_NSEC) { zone_diff_label_rr *new_nsec_rr = zone_diff_label_rr_new( from->fqdn, TYPE_RRSIG, CLASS_IN, rrsig_sll->ttl, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig_sll), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig_sll), TRUE); new_nsec_rr->state |= ZONE_DIFF_RR_VOLATILE; ptr_vector_append(collection, new_nsec_rr); } rrsig_sll = rrsig_sll->next; } } } } static void dnssec_chain_node_nsec_publish_log(dnssec_chain_node_t from_, dnssec_chain_node_t to_) { dnssec_chain_node_nsec *from = (dnssec_chain_node_nsec*)from_; dnssec_chain_node_nsec *to = (dnssec_chain_node_nsec*)to_; const u8 *inverse_fqdn = dnssec_chain_node_nsec_get_inverse_fqdn(from); if(to != NULL) { const u8 *next_inverse_fqdn = dnssec_chain_node_nsec_get_inverse_fqdn(to); log_debug1("update: %{dnsname} -> %{dnsname}", inverse_fqdn, next_inverse_fqdn); } else { log_debug1("update: %{dnsname} -> ?", inverse_fqdn); } } static void dnssec_chain_node_nsec_publish_add(dnssec_chain_head_t chain_, dnssec_chain_node_t from_, dnssec_chain_node_t to_, zone_diff *diff, ptr_vector *collection) { dnssec_chain_node_nsec *from = (dnssec_chain_node_nsec*)from_; dnssec_chain_node_nsec *to = (dnssec_chain_node_nsec*)to_; nsec_zone *nsec_chain = (nsec_zone*)chain_; dnssec_chain_node_nsec_publish_record(nsec_chain, from, to, diff, collection, ZONE_DIFF_RR_REMOVE, FALSE); } static void dnssec_chain_node_nsec_publish_delete(dnssec_chain_head_t chain_, dnssec_chain_node_t from_, dnssec_chain_node_t to_, zone_diff *diff, ptr_vector *collection) { dnssec_chain_node_nsec *from = (dnssec_chain_node_nsec*)from_; dnssec_chain_node_nsec *to = (dnssec_chain_node_nsec*)to_; nsec_zone *nsec_chain = (nsec_zone*)chain_; dnssec_chain_node_nsec_publish_record(nsec_chain, from, to, diff, collection, ZONE_DIFF_RR_ADD, TRUE); } static bool dnssec_chain_nsec_isempty(dnssec_chain_head_t chain_) { nsec_zone *nsec_chain = (nsec_zone*)chain_; bool ret = (nsec_chain != NULL)?nsec_isempty(&nsec_chain):TRUE; return ret; } static void dnssec_chain_nsec_finalize_delete_callback(ptr_node *node) { dnssec_chain_node_nsec_delete(node->value); } static void dnssec_chain_node_nsec_format_writer_init(dnssec_chain_node_t node_, format_writer *outfw) { dnssec_chain_node_nsec *node = (dnssec_chain_node_nsec*)node_; outfw->callback = dnsname_format_handler_method; outfw->value = node->fqdn; } static bool dnssec_chain_node_nsec_rrset_should_be_signed(const zone_diff_fqdn *diff_fqdn, const zone_diff_fqdn_rr_set *rr_set) { if(diff_fqdn->at_delegation || diff_fqdn->under_delegation) { return (rr_set->rtype == TYPE_DS) || (rr_set->rtype == TYPE_NSEC); } else { return TRUE; } } static dnssec_chain_node_vtbl dnssec_chain_node_nsec_vtbl = { dnssec_chain_node_nsec_fqdn_is_covered, dnssec_chain_node_nsec_fqdn_was_covered, dnssec_chain_node_nsec_new, dnssec_chain_node_nsec_prev, dnssec_chain_node_nsec_merge, dnssec_chain_node_nsec_next, dnssec_chain_node_nsec_state_set, dnssec_chain_node_nsec_state_get, dnssec_chain_node_nsec_delete, dnssec_chain_node_nsec_publish_delete, dnssec_chain_node_nsec_publish_add, dnssec_chain_node_nsec_publish_log, dnssec_chain_node_nsec_compare, dnssec_chain_nsec_finalize_delete_callback, dnssec_chain_nsec_isempty, dnssec_chain_node_nsec_format_writer_init, dnssec_chain_node_nsec_rrset_should_be_signed, "nsec" }; const dnssec_chain_node_vtbl * dynupdate_nsec_chain_get_vtbl() { return &dnssec_chain_node_nsec_vtbl; } yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dynupdate-diff-nsec3.c0000644000000000000000000000013214505005531023044 xustar000000000000000030 mtime=1695812441.699971547 30 atime=1695812445.800030268 30 ctime=1695812495.159737198 yadifa-2.6.5-11201/lib/dnsdb/src/dynupdate-diff-nsec3.c0000664000374500037450000005717514505005531023025 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbupdate Dynamic update functions * @ingroup dnsdb * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #include #include #include #include "dnsdb/zdb_types.h" #include "dnsdb/nsec.h" #include "dnsdb/nsec3.h" #include #include #include #include "dnsdb/dnssec.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/dnssec-keystore.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/dynupdate-diff.h" #define MODULE_MSG_HANDLE g_database_logger extern logger_handle *g_database_logger; #define NSC3NODE_TAG 0x45444f4e3343534e static const u8 UNKNOWN_FQDN[] = "\007UNKNOWN"; struct dnssec_chain_node_nsec3 { nsec3_node *prev; nsec3_node *self; nsec3_node *next; u8 *fqdn; u8 state; u8 reserved[sizeof(void*)-2]; u8 digest[1 + SHA_DIGEST_LENGTH]; }; typedef struct dnssec_chain_node_nsec3 dnssec_chain_node_nsec3; static void dnssec_chain_node_nsec3_set_fqdn(dnssec_chain_node_nsec3 *node, const u8 *fqdn) { yassert(node->fqdn == NULL); node->fqdn = dnsname_zdup(fqdn); } static const u8* dnssec_chain_node_nsec3_get_digest(const dnssec_chain_node_nsec3 *node) { return (node->self != NULL)?node->self->digest:node->digest; } static void dnssec_chain_node_nsec3_format_handler_method(const void *val, output_stream *stream, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; dnssec_chain_node_nsec3 *node = (dnssec_chain_node_nsec3*)val; const u8* digest = dnssec_chain_node_nsec3_get_digest(node); output_stream_write_base32hex(stream, &digest[1], *digest); output_stream_write_u8(stream, '('); if(node->fqdn != NULL) { dnsname_format_handler_method(node->fqdn, stream, 0, 0, FALSE, NULL); } else { output_stream_write_u8(stream, '?'); } output_stream_write_u8(stream, ')'); } static void dnssec_chain_node_nsec3_format_writer_init(dnssec_chain_node_t node_, format_writer *outfw) { dnssec_chain_node_nsec3 *node = (dnssec_chain_node_nsec3*)node_; outfw->callback = dnssec_chain_node_nsec3_format_handler_method; outfw->value = node; } //#define NSEC3_HANDLE_SUBDELEGATION 1 static bool dnssec_chain_node_nsec3_fqdn_is_covered(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (diff_fqdn->at_delegation && !diff_fqdn->under_delegation)|| // has NS records (but is not below NS records) (!(diff_fqdn->at_delegation || diff_fqdn->under_delegation) && (diff_fqdn->will_be_non_empty || diff_fqdn->will_have_children)) // else it's under a delegation ; } static bool dnssec_chain_node_nsec3_fqdn_was_covered(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (diff_fqdn->was_at_delegation && !diff_fqdn->was_under_delegation) || // had NS records (but is not below NS records) (!(diff_fqdn->was_at_delegation || diff_fqdn->was_under_delegation) && (diff_fqdn->was_non_empty || diff_fqdn->had_children)) // else it was under a delegation ; } static bool dnssec_chain_node_nsec3_optout_fqdn_is_covered(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (diff_fqdn->at_delegation && !diff_fqdn->under_delegation && diff_fqdn->will_have_ds) || // has DS record(s) (!(diff_fqdn->at_delegation || diff_fqdn->under_delegation) && (diff_fqdn->will_be_non_empty || diff_fqdn->will_have_children)) // else it's under a delegation ; } static bool dnssec_chain_node_nsec3_optout_fqdn_was_covered(const zone_diff_fqdn *diff_fqdn) { return diff_fqdn->is_apex || (diff_fqdn->was_at_delegation && !diff_fqdn->was_under_delegation && diff_fqdn->had_ds) || // had DS record(s) (!(diff_fqdn->was_at_delegation || diff_fqdn->was_under_delegation) && (diff_fqdn->was_non_empty || diff_fqdn->had_children)) // else it was under a delegation ; } /** * Creates a new entry with its pred/next from the zone nsec3 database * * @param digest * @param chain nsec3_zone * @return */ static dnssec_chain_node_nsec3 * dnssec_chain_node_nsec3_new_from_digest(const u8 *digest, const nsec3_zone *n3) { // compute the digest of the fqdn for the chain // find if the node already exists // return the appropriate node nsec3_zone_item *self = NULL; nsec3_zone_item *prev; nsec3_zone_item *next; bool empty = (n3->items == NULL); if(!empty) { prev = nsec3_find_interval_prev_mod(&n3->items, (u8*)digest); next = nsec3_node_mod_next(prev); if(memcmp(&next->digest[1], &digest[1], digest[0]) == 0) { // exists self = next; next = nsec3_node_mod_next(self); } } else { prev = NULL; next = NULL; } dnssec_chain_node_nsec3 *node; ZALLOC_OBJECT_OR_DIE(node, dnssec_chain_node_nsec3, NSC3NODE_TAG); node->prev = prev; node->self = self; node->next = next; node->fqdn = NULL; if(self != NULL) { node->state = DNSSEC_CHAIN_EXISTS; } else { node->state = DNSSEC_CHAIN_ADD; memcpy(node->digest, digest, digest[0] + 1); } return node; } static dnssec_chain_node_t dnssec_chain_node_nsec3_new(const u8 *fqdn, dnssec_chain_head_t chain) { // compute the digest of the fqdn for the chain // find if the node already exists // return the appropriate node const nsec3_zone* n3 = (nsec3_zone*)chain; u8 digest[1 + SHA_DIGEST_LENGTH]; nsec3_compute_digest_from_fqdn_with_len(n3, fqdn, dnsname_len(fqdn), digest, FALSE); dnssec_chain_node_nsec3 *node = dnssec_chain_node_nsec3_new_from_digest(digest, n3); dnssec_chain_node_nsec3_set_fqdn(node, fqdn); if(node->prev != NULL) { if(node->next != NULL) { log_debug1("update: nsec3: %{dnsname} has node %{digest32h} [ %{digest32h} ; %{digest32h} ] (%02x)", fqdn, dnssec_chain_node_nsec3_get_digest(node), node->prev->digest, node->next->digest, node->state); } else { log_debug1("update: nsec3: %{dnsname} has node %{digest32h} [ %{digest32h} ; ? [ (%02x)", fqdn, dnssec_chain_node_nsec3_get_digest(node), node->prev->digest, node->state); } } else { log_debug1("update: nsec3: %{dnsname} has node %{digest32h} [ ? ; ? [ (%02x)", fqdn, dnssec_chain_node_nsec3_get_digest(node), node->state); } return (dnssec_chain_node_t)node; } static void dnssec_chain_node_nsec3_delete(dnssec_chain_node_t node_) { dnssec_chain_node_nsec3 *nsec3_node = (dnssec_chain_node_nsec3*)node_; if((nsec3_node->fqdn != NULL) && (nsec3_node->fqdn != UNKNOWN_FQDN)) { dnsname_zfree(nsec3_node->fqdn); } ZFREE(nsec3_node, dnssec_chain_node_nsec3); } static bool dnssec_chain_node_nsec3_has_bits_map(const dnssec_chain_node_nsec3 *node) { return node->self != NULL; } static const u8 *dnssec_chain_node_nsec3_get_bits_map(const dnssec_chain_node_nsec3 *node) { return node->self->type_bit_maps; } static u16 dnssec_chain_node_nsec3_get_bits_map_size(const dnssec_chain_node_nsec3 *node) { return node->self->type_bit_maps_size; } static int dnssec_chain_node_nsec3_compare(const void *a_, const void *b_) { const dnssec_chain_node_nsec3 *a = (const dnssec_chain_node_nsec3*)a_; const dnssec_chain_node_nsec3 *b = (const dnssec_chain_node_nsec3*)b_; const u8 *a_digest = dnssec_chain_node_nsec3_get_digest(a); const u8 *b_digest = dnssec_chain_node_nsec3_get_digest(b); yassert(a_digest[0] == SHA_DIGEST_LENGTH && b_digest[0] == SHA_DIGEST_LENGTH); int ret = memcmp(&a_digest[1], &b_digest[1], a_digest[0]); return ret; } static dnssec_chain_node_t dnssec_chain_node_nsec3_prev(const dnssec_chain_node_t node_) { dnssec_chain_node_nsec3 *self = (dnssec_chain_node_nsec3*)node_; dnssec_chain_node_nsec3 *node; ZALLOC_OBJECT_OR_DIE(node, dnssec_chain_node_nsec3, NSC3NODE_TAG); node->prev = NULL; node->self = self->prev; node->next = self->next; // ? node->fqdn = (u8*)UNKNOWN_FQDN; node->state = DNSSEC_CHAIN_EXISTS|DNSSEC_CHAIN_BEGIN; node->digest[0] = 0; log_debug1("update: prev is %{digest32h} (%02x) '%{dnsname}'", node->self->digest, node->state, node->fqdn); return (dnssec_chain_node_t)node; } static dnssec_chain_node_t dnssec_chain_node_nsec3_next(const dnssec_chain_node_t node_) { dnssec_chain_node_nsec3 *self = (dnssec_chain_node_nsec3*)node_; dnssec_chain_node_nsec3 *node; ZALLOC_OBJECT_OR_DIE(node, dnssec_chain_node_nsec3, NSC3NODE_TAG); node->prev = self->prev; // ? node->self = self->next; node->next = NULL; node->fqdn = (u8*)UNKNOWN_FQDN; node->state = DNSSEC_CHAIN_EXISTS|DNSSEC_CHAIN_END; log_debug1("update: next is %{digest32h} (%02x) '%{dnsname}'", node->self->digest, node->state, node->fqdn); return (dnssec_chain_node_t)node; } static u8 dnssec_chain_node_nsec3_state_get(const dnssec_chain_node_t node_) { const dnssec_chain_node_nsec3 *self = (const dnssec_chain_node_nsec3*)node_; return self->state; } static void dnssec_chain_node_nsec3_state_set(dnssec_chain_node_t node_, u8 value) { dnssec_chain_node_nsec3 *self = (dnssec_chain_node_nsec3*)node_; log_debug1("update: status %{digest32h} from %02x to %02x", dnssec_chain_node_nsec3_get_digest(self), self->state, value); self->state = value; } static void dnssec_chain_node_nsec3_merge(dnssec_chain_node_t chain_node, dnssec_chain_node_t chain_with) { dnssec_chain_node_nsec3 *node = (dnssec_chain_node_nsec3*)chain_node; dnssec_chain_node_nsec3 *with = (dnssec_chain_node_nsec3*)chain_with; u8 node_state = dnssec_chain_node_nsec3_state_get(chain_node); u8 with_state = dnssec_chain_node_nsec3_state_get(chain_with); #if DEBUG format_writer node_writer; dnssec_chain_node_nsec3_format_writer_init(chain_node, &node_writer); format_writer with_writer; dnssec_chain_node_nsec3_format_writer_init(chain_with, &with_writer); log_debug2("nsec3_merge: %w (%02x) with %w(%02x)", &node_writer, node_state, &with_writer, with_state); #endif if((node_state & DNSSEC_CHAIN_END) && (with_state & DNSSEC_CHAIN_BEGIN)) { #if DEBUG log_debug("dnssec_chain_node_nsec3_merge(%{digest32h},%{digest32h}) end<->begin (%08x %08x)", dnssec_chain_node_nsec3_get_digest(node), dnssec_chain_node_nsec3_get_digest(with), node_state, with_state); #endif dnssec_chain_node_nsec3_state_set(chain_node, dnssec_chain_node_nsec3_state_get(chain_node) & ~DNSSEC_CHAIN_END); } if((node_state & DNSSEC_CHAIN_BEGIN) && (with_state & DNSSEC_CHAIN_END)) { #if DEBUG log_debug("dnssec_chain_node_nsec3_merge(%{digest32h},%{digest32h}) begin<->end (%08x %08x)", dnssec_chain_node_nsec3_get_digest(node), dnssec_chain_node_nsec3_get_digest(with), node_state, with_state); #endif dnssec_chain_node_nsec3_state_set(chain_node, dnssec_chain_node_nsec3_state_get(chain_node) & ~DNSSEC_CHAIN_BEGIN); } // properly handle merging of the FQDN if(node->fqdn == UNKNOWN_FQDN) { if(with->fqdn != UNKNOWN_FQDN) { node->fqdn = with->fqdn; with->fqdn = (u8*)UNKNOWN_FQDN; } } dnssec_chain_node_nsec3_delete(chain_with); } /** * * @param n3 * @param from * @param to * @param diff * @param collection * @param mask ZONE_DIFF_REMOVE: get the new state, ZONE_DIFF_ADD: get the old state * @param append_existing_signatures adds the existing signature to the collection (e.g.: to remove them) * @param optout */ static void dnssec_chain_node_nsec3_publish_record(nsec3_zone *n3, dnssec_chain_node_nsec3 *from, dnssec_chain_node_nsec3 *to, zone_diff *diff, ptr_vector *collection, u8 mask, bool append_existing_signatures, u8 optout) { const u8 *digest = dnssec_chain_node_nsec3_get_digest(from); const u8 *next_digest = dnssec_chain_node_nsec3_get_digest(to); u32 b32_len; u32 fqdn_len; u8 hash_len; u8 digest_fqdn[512]; log_debug1("update: %{dnsname}: %{digest32h}: %x: %{dnsname} -> %{digest32h}", diff->origin, digest, mask, from->fqdn, next_digest); // generate the label hash_len = digest[0]; b32_len = base32hex_lc_encode(&digest[1], hash_len, (char*)&digest_fqdn[1]); digest_fqdn[0] = b32_len; fqdn_len = dnsname_len(diff->origin); memcpy(&digest_fqdn[b32_len + 1], diff->origin, fqdn_len ); u32 nsec3param_rdata_size = NSEC3PARAM_RDATA_SIZE_FROM_RDATA(n3->rdata); if(!dnssec_chain_node_nsec3_has_bits_map(from) || ((mask & ZONE_DIFF_RR_REMOVE) && (from->state & DNSSEC_CHAIN_REMAP)) /* * can only modify if (mask & ZONE_DIFF_RR_REMOVE) || ((from->state & (DNSSEC_CHAIN_DELETE|DNSSEC_CHAIN_REMAP|DNSSEC_CHAIN_EXISTS)) == (DNSSEC_CHAIN_DELETE|DNSSEC_CHAIN_REMAP|DNSSEC_CHAIN_EXISTS)) */ ) { // generate the type map #if DEBUG log_debug2("update: %{dnsname}: %{digest32h}: %x: %{dnsname} -> %{digest32h} regenerating bitmap (%i || (%i && %i [%02x])", diff->origin, digest, mask, from->fqdn, next_digest, !dnssec_chain_node_nsec3_has_bits_map(from), (mask & ZONE_DIFF_RR_REMOVE), (from->state & DNSSEC_CHAIN_REMAP), from->state); #endif type_bit_maps_context bitmap; u16 bitmap_size = zone_diff_type_bit_map_generate(diff, from->fqdn, &bitmap, mask | ZONE_DIFF_RR_REMOVE, 0, digest_fqdn, append_existing_signatures); u16 rdata_size = nsec3param_rdata_size + 1 + next_digest[0] + bitmap_size; #if C11_VLA_AVAILABLE u8 rdata[rdata_size]; #else u8* const rdata = (u8* const)stack_alloc(rdata_size); #endif memcpy(rdata, n3->rdata, nsec3param_rdata_size); rdata[1] = optout; memcpy(&rdata[nsec3param_rdata_size], next_digest, 1 + next_digest[0]); type_bit_maps_write(&bitmap, &rdata[nsec3param_rdata_size + 1 + next_digest[0]]); type_bit_maps_finalize(&bitmap); // the record can be created zone_diff_label_rr *nsec3_rr = zone_diff_label_rr_new(digest_fqdn, TYPE_NSEC3, CLASS_IN, diff->nttl, rdata, rdata_size, TRUE); nsec3_rr->state |= ZONE_DIFF_RR_VOLATILE; ptr_vector_append(collection, nsec3_rr); } else // bitmap already present { #if DEBUG log_debug2("update: %{dnsname}: %{digest32h}: %x: %{dnsname} -> %{digest32h} keeping bitmap (%i || (%i && %i [%02x])", diff->origin, digest, mask, from->fqdn, next_digest, !dnssec_chain_node_nsec3_has_bits_map(from), (mask & ZONE_DIFF_RR_REMOVE), (from->state & DNSSEC_CHAIN_REMAP), from->state); #endif u16 bitmap_size = dnssec_chain_node_nsec3_get_bits_map_size(from); u16 rdata_size = nsec3param_rdata_size + 1 + next_digest[0] + bitmap_size; #if C11_VLA_AVAILABLE u8 rdata[rdata_size]; #else u8* const rdata = (u8* const)stack_alloc(rdata_size); #endif memcpy(rdata, n3->rdata, nsec3param_rdata_size); rdata[1] = optout; memcpy(&rdata[nsec3param_rdata_size], next_digest, 1 + next_digest[0]); memcpy(&rdata[nsec3param_rdata_size + 1 + next_digest[0]], dnssec_chain_node_nsec3_get_bits_map(from), bitmap_size); // the record can be created zone_diff_label_rr *nsec3_rr = zone_diff_label_rr_new( digest_fqdn, TYPE_NSEC3, CLASS_IN, diff->nttl, rdata, rdata_size, TRUE); nsec3_rr->state |= ZONE_DIFF_RR_VOLATILE | (from->state & DNSSEC_CHAIN_EXISTS); ptr_vector_append(collection, nsec3_rr); } if(append_existing_signatures && (from->self != NULL)) { zdb_packed_ttlrdata *rrsig = from->self->rrsig; while(rrsig != NULL) { zone_diff_label_rr *rrsig_rr = zone_diff_label_rr_new(digest_fqdn, TYPE_RRSIG, CLASS_IN, diff->nttl, ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig), TRUE); rrsig_rr->state |= ZONE_DIFF_RR_VOLATILE; ptr_vector_append(collection, rrsig_rr); rrsig = rrsig->next; } } } static void dnssec_chain_node_nsec3_publish_log(dnssec_chain_node_t from_, dnssec_chain_node_t to_) { dnssec_chain_node_nsec3 *from = (dnssec_chain_node_nsec3*)from_; dnssec_chain_node_nsec3 *to = (dnssec_chain_node_nsec3*)to_; const u8 *digest = dnssec_chain_node_nsec3_get_digest(from); if(to != NULL) { const u8 *next_digest = dnssec_chain_node_nsec3_get_digest(to); log_debug1("update: %{digest32h} -> %{digest32h}", digest, next_digest); } else { log_debug1("update: %{digest32h} -> ?", digest); } } static void dnssec_chain_node_nsec3_publish_add(dnssec_chain_head_t chain_, dnssec_chain_node_t from_, dnssec_chain_node_t to_, zone_diff *diff, ptr_vector *collection) { dnssec_chain_node_nsec3 *from = (dnssec_chain_node_nsec3*)from_; dnssec_chain_node_nsec3 *to = (dnssec_chain_node_nsec3*)to_; nsec3_zone *n3 = (nsec3_zone*)chain_; dnssec_chain_node_nsec3_publish_record(n3, from, to, diff, collection, ZONE_DIFF_RR_REMOVE, FALSE, 0); } static void dnssec_chain_node_nsec3_publish_delete(dnssec_chain_head_t chain_, dnssec_chain_node_t from_, dnssec_chain_node_t to_, zone_diff *diff, ptr_vector *collection) { dnssec_chain_node_nsec3 *from = (dnssec_chain_node_nsec3*)from_; dnssec_chain_node_nsec3 *to = (dnssec_chain_node_nsec3*)to_; nsec3_zone *n3 = (nsec3_zone*)chain_; dnssec_chain_node_nsec3_publish_record(n3, from, to, diff, collection, ZONE_DIFF_RR_ADD, TRUE, 0); } static void dnssec_chain_node_nsec3_publish_add_optout(dnssec_chain_head_t chain_, dnssec_chain_node_t from_, dnssec_chain_node_t to_, zone_diff *diff, ptr_vector *collection) { dnssec_chain_node_nsec3 *from = (dnssec_chain_node_nsec3*)from_; dnssec_chain_node_nsec3 *to = (dnssec_chain_node_nsec3*)to_; nsec3_zone *n3 = (nsec3_zone*)chain_; dnssec_chain_node_nsec3_publish_record(n3, from, to, diff, collection, ZONE_DIFF_RR_REMOVE, FALSE, 1); } static void dnssec_chain_node_nsec3_publish_delete_optout(dnssec_chain_head_t chain_, dnssec_chain_node_t from_, dnssec_chain_node_t to_, zone_diff *diff, ptr_vector *collection) { dnssec_chain_node_nsec3 *from = (dnssec_chain_node_nsec3*)from_; dnssec_chain_node_nsec3 *to = (dnssec_chain_node_nsec3*)to_; nsec3_zone *n3 = (nsec3_zone*)chain_; dnssec_chain_node_nsec3_publish_record(n3, from, to, diff, collection, ZONE_DIFF_RR_ADD, TRUE, 1); } static bool dnssec_chain_nsec3_isempty(dnssec_chain_head_t chain_) { nsec3_zone *nsec3_chain = (nsec3_zone*)chain_; bool ret = (nsec3_chain != NULL)?nsec3_isempty(&nsec3_chain->items):TRUE; return ret; } static void dnssec_chain_nsec3_finalize_delete_callback(ptr_node *node) { dnssec_chain_node_nsec3_delete(node->value); } static bool dnssec_chain_node_nsec3_rrset_should_be_signed(const zone_diff_fqdn *diff_fqdn, const zone_diff_fqdn_rr_set *rr_set) { if(diff_fqdn->at_delegation || diff_fqdn->under_delegation) { return (rr_set->rtype == TYPE_NS) || (rr_set->rtype == TYPE_DS); } else { return TRUE; } } static bool dnssec_chain_node_nsec3_optout_rrset_should_be_signed(const zone_diff_fqdn *diff_fqdn, const zone_diff_fqdn_rr_set *rr_set) { if(diff_fqdn->at_delegation || diff_fqdn->under_delegation) { return (rr_set->rtype == TYPE_DS); } else { return TRUE; } } static dnssec_chain_node_vtbl dnssec_chain_node_nsec3_vtbl = { dnssec_chain_node_nsec3_fqdn_is_covered, dnssec_chain_node_nsec3_fqdn_was_covered, dnssec_chain_node_nsec3_new, dnssec_chain_node_nsec3_prev, dnssec_chain_node_nsec3_merge, dnssec_chain_node_nsec3_next, dnssec_chain_node_nsec3_state_set, dnssec_chain_node_nsec3_state_get, dnssec_chain_node_nsec3_delete, dnssec_chain_node_nsec3_publish_delete, dnssec_chain_node_nsec3_publish_add, dnssec_chain_node_nsec3_publish_log, dnssec_chain_node_nsec3_compare, dnssec_chain_nsec3_finalize_delete_callback, dnssec_chain_nsec3_isempty, dnssec_chain_node_nsec3_format_writer_init, dnssec_chain_node_nsec3_rrset_should_be_signed, "nsec3" }; const dnssec_chain_node_vtbl * dynupdate_nsec3_chain_get_vtbl() { return &dnssec_chain_node_nsec3_vtbl; } static dnssec_chain_node_vtbl dnssec_chain_node_nsec3_optout_vtbl = { dnssec_chain_node_nsec3_optout_fqdn_is_covered, dnssec_chain_node_nsec3_optout_fqdn_was_covered, dnssec_chain_node_nsec3_new, dnssec_chain_node_nsec3_prev, dnssec_chain_node_nsec3_merge, dnssec_chain_node_nsec3_next, dnssec_chain_node_nsec3_state_set, dnssec_chain_node_nsec3_state_get, dnssec_chain_node_nsec3_delete, dnssec_chain_node_nsec3_publish_delete_optout, dnssec_chain_node_nsec3_publish_add_optout, dnssec_chain_node_nsec3_publish_log, dnssec_chain_node_nsec3_compare, dnssec_chain_nsec3_finalize_delete_callback, dnssec_chain_nsec3_isempty, dnssec_chain_node_nsec3_format_writer_init, dnssec_chain_node_nsec3_optout_rrset_should_be_signed, "nsec3-optout" }; const dnssec_chain_node_vtbl * dynupdate_nsec3_optout_chain_get_vtbl() { return &dnssec_chain_node_nsec3_optout_vtbl; } yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-maintenance.c0000644000000000000000000000013214505005531023140 xustar000000000000000030 mtime=1695812441.694971475 30 atime=1695812445.799030253 30 ctime=1695812495.161737227 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-maintenance.c0000664000374500037450000015035014505005531023106 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include "dnsdb/zdb_types.h" #include "dnsdb/zdb_icmtl.h" #include "dnsdb/zdb-packed-ttlrdata.h" #include "dnsdb/dnssec.h" #include "dnsdb/zdb_record.h" #include "dnsdb/dnssec-keystore.h" #include #include #include "dnsdb/zdb_zone_label_iterator.h" #include "dnsdb/zdb-zone-maintenance.h" #include "dnsdb/zdb_zone_load.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define ZDB_ZONE_MAINTENANCE_DETAILED_LOG 0 /// @note 20180615 edf -- heavy, use with care #define ZDB_ZONE_MAINTENANCE_IGNORE_TIME_QUOTA 0 #define DEBUG_SIGNATURE_REFRESH 0 #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG #pragma message("WARNING: ZDB_ZONE_MAINTENANCE_DETAILED_LOG is not set to 0") #endif #if ZDB_ZONE_MAINTENANCE_IGNORE_TIME_QUOTA #pragma message("WARNING: ZDB_ZONE_MAINTENANCE_IGNORE_TIME_QUOTA is not set to 0") #endif #define ZDB_ZONE_MAINTENANCE_SAME_PASS_CLOSE 1 #define ZDB_ZONE_MAINTENANCE_RRSIG_COUNT_THRESHOLD 256 // after that many signatures, stop processing labels #define ZDB_MAINTENANCE_BATCH_TIME_US_MAX 20000 // 10ms #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG #pragma message("WARNING: ZDB_ZONE_MAINTENANCE_DETAILED_LOG IS NOT SET TO 0. SET IT BACK TO 0 IT IF YOU DON'T NEED IT!") #pragma message("WARNING: ZDB_ZONE_MAINTENANCE_DETAILED_LOG IS NOT SET TO 0. SET IT BACK TO 0 IT IF YOU DON'T NEED IT!") #pragma message("WARNING: ZDB_ZONE_MAINTENANCE_DETAILED_LOG IS NOT SET TO 0. SET IT BACK TO 0 IT IF YOU DON'T NEED IT!") #endif static bool zdb_zone_maintenance_validate_sign_chain_store(zdb_zone_maintenance_ctx *mctx, zone_diff *diff, zdb_zone *zone, ptr_vector *rrset_to_sign, ptr_vector *remove, ptr_vector *add) { ya_result ret; log_debug("maintenance: validate-sign-chain-store: %{dnsname}", zone->origin); #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-validate: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-validate: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } #endif if(ISOK(ret = zone_diff_validate(diff))) { #if DEBUG log_debug("maintenance: %{dnsname}: diff validated", diff->origin); #endif // store changes in vectors and get the RR sets to sign #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-get-changes: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-get-changes: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } #endif ptr_vector ksks = PTR_VECTOR_EMPTY; ptr_vector zsks = PTR_VECTOR_EMPTY; s32 mandatory_changes = zone_diff_get_changes(diff, rrset_to_sign, &ksks, &zsks, remove, add, zone->sig_validity_regeneration_seconds); // sign the records, store the changes in vectors #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-diff-sign: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-diff-sign: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } log_debug("maintenance: mandatory-changes: %i", mandatory_changes); #endif bool relevant_update = (mandatory_changes > 0); if(relevant_update) { /* * Signs the RRSETs using the ksk & zsk, applies the changes in remove and add vectors */ dnssec_chain_store_diff(&mctx->nsec_chain_updater, diff, &zsks, remove, add); zone_diff_sign(diff, zone, rrset_to_sign, &ksks, &zsks, remove, add); #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-nsec3-chain-store-diff: %{dnsname}: - [%02x] %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->state, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-nsec3-chain-store-diff: %{dnsname}: + [%02x] %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->state, rr->fqdn, rr->ttl, &rd); } #endif // zone_diff_get_chain_changes(diff, &dc); dnssec_chain_store_diff(&mctx->nsec3_chains_updater, diff, &zsks, remove, add); #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("when-all-is-said-and-done: %{dnsname}: - [%02x] %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->state, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("when-all-is-said-and-done: %{dnsname}: + [%02x] %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->state, rr->fqdn, rr->ttl, &rd); } #endif } dnssec_keystore_release_keys_from_vector(&zsks); dnssec_keystore_release_keys_from_vector(&ksks); ptr_vector_destroy(&zsks); ptr_vector_destroy(&ksks); return relevant_update; } else { log_err("maintenance: %{dnsname}: could not validate the diff", diff->origin); return FALSE; } } static void zdb_zone_maintenance_ctx_init(zdb_zone_maintenance_ctx *mctx, zdb_zone *zone) { log_debug("maintenance: %{dnsname}: context init", zone->origin); ZEROMEMORY(mctx, sizeof(zdb_zone_maintenance_ctx)); mctx->zone = zone; } static void zdb_zone_maintenance_ctx_finalize(zdb_zone_maintenance_ctx *mctx) { log_debug("maintenance: %{dnsname}: context finalize", mctx->zone->origin); log_debug("maintenance: %{dnsname}: context finalize: clearing KSK", mctx->zone->origin); dnssec_keystore_release_keys_from_vector(&mctx->ksks); log_debug("maintenance: %{dnsname}: context finalize: clearing ZSK", mctx->zone->origin); dnssec_keystore_release_keys_from_vector(&mctx->zsks); ptr_vector_destroy(&mctx->ksks); ptr_vector_destroy(&mctx->zsks); log_debug("maintenance: %{dnsname}: context finalize: finalising NSEC chain", mctx->zone->origin); dnssec_chain_finalize(&mctx->nsec_chain_updater); log_debug("maintenance: %{dnsname}: context finalize: finalising NSEC3 chain", mctx->zone->origin); dnssec_chain_finalize(&mctx->nsec3_chains_updater); log_debug("maintenance: %{dnsname}: context finalize: releasing active keys", mctx->zone->origin); zdb_zone_release_active_keys(mctx->keys); mctx->keys = NULL; log_debug("maintenance: %{dnsname}: context finalize done", mctx->zone->origin); } /** * Updates the signatures of a zone incrementally. * Each call goes a bit further. * * @param zone * @param signature_count_loose_limit * @param present_signatures_are_verified * @return */ static ya_result zdb_zone_maintenance_from(zdb_zone* zone, u8 *from_fqdn, size_t from_fqdn_size, s64 maxus, s32 rrsigcountmax) { yassert(((from_fqdn != NULL) && (from_fqdn_size > 0)) || ((from_fqdn == NULL) && (from_fqdn_size == 0))); //bool from_fqdn_is_binary_digest = FALSE; if(!zdb_zone_is_maintained(zone)) { log_debug("maintenance: %{dnsname}: not maintained", zone->origin); return ZDB_ERROR_ZONE_NOT_MAINTAINED; } u8 current_owner; u8 current_reserved_owner; while(!zdb_zone_try_double_lock_ex(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_RRSIG_UPDATER, ¤t_owner, ¤t_reserved_owner)) { log_debug("maintenance: %{dnsname}: cannot double-lock the zone for maintenance (%02x, %04x, %02x, %02x)", zone->origin, zone->_flags, zone->_status, current_owner, current_reserved_owner); if((current_owner == ZDB_ZONE_MUTEX_RRSIG_UPDATER) || (current_reserved_owner == ZDB_ZONE_MUTEX_RRSIG_UPDATER)) { // the zone is already being signed return ZDB_ERROR_ZONE_IS_ALREADY_BEING_SIGNED; } else { // wait for the condition mutex_lock(&zone->lock_mutex); cond_timedwait(&zone->lock_cond, &zone->lock_mutex, 1000); mutex_unlock(&zone->lock_mutex); } } if((from_fqdn != NULL) && (from_fqdn[0] != 0)) { log_debug("maintenance: %{dnsname}: starting from %{dnsname}", zone->origin, from_fqdn); } else { log_debug("maintenance: %{dnsname}: starting from the apex", zone->origin); zdb_zone_clear_maintenance_queued(zone); } s64 start_time = timeus(); int maintenance_rrsig_count = 0; int maintenance_nsec_count = 0; int maintenance_nsec3_count = 0; int maintenance_generate_nsec3_rrsig_count = 0; int maintenance_generate_nsec3param_rrsig_count = 0; bool nsecchainstate_changed = FALSE; zdb_zone_maintenance_ctx mctx; zdb_zone_maintenance_ctx_init(&mctx, zone); u8 maintain_mode = zone_get_maintain_mode(zone); zone_diff diff; zone_diff_init(&diff, zone, TRUE); switch(maintain_mode) { case ZDB_ZONE_MAINTAIN_NSEC3: case ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT: { diff.maintain_nsec3 = TRUE; break; } case ZDB_ZONE_MAINTAIN_NSEC: { diff.maintain_nsec = TRUE; break; } default: { break; } } dnssec_chain_init(&mctx.nsec_chain_updater, dynupdate_nsec_chain_get_vtbl(), &diff); if((maintain_mode & ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT) != ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT) { dnssec_chain_init(&mctx.nsec3_chains_updater, dynupdate_nsec3_chain_get_vtbl(), &diff); } else { dnssec_chain_init(&mctx.nsec3_chains_updater, dynupdate_nsec3_optout_chain_get_vtbl(), &diff); } // load all the active keys from the keyring of the zone // compute a mask for all the keys that are private (usable) log_debug("maintenance: %{dnsname}: fetching keys", zone->origin); ptr_vector_init(&mctx.ksks); ptr_vector_init(&mctx.zsks); zone_diff_store_diff_dnskey_get_keys(&diff, &mctx.ksks, &mctx.zsks, zone->sig_validity_regeneration_seconds); u64 ksk_mask = 0; u64 zsk_mask = 0; mctx.now = time(NULL); for(int i = 0; i <= ptr_vector_last_index(&mctx.ksks); ++i) { const dnssec_key *key = (const dnssec_key*)ptr_vector_get(&mctx.ksks, i); if(!dnskey_is_private(key)) { log_debug("maintenance: DNSKEY: %{dnsname}+%03d+%05d/%d is not a private KSK", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); continue; } if(dnskey_is_activated_lenient(key, mctx.now, zone->sig_validity_regeneration_seconds)) { ksk_mask |= 1ULL << i; log_debug("maintenance: DNSKEY: %{dnsname}+%03d+%05d/%d will be used for KSK signatures", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); } } for(int i = 0; i <= ptr_vector_last_index(&mctx.zsks); ++i) { const dnssec_key *key = (const dnssec_key*)ptr_vector_get(&mctx.zsks, i); if(!dnskey_is_private(key)) { log_debug("maintenance: DNSKEY: %{dnsname}+%03d+%05d/%d is not a private ZSK", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); continue; } if(dnskey_is_activated_lenient(key, mctx.now, zone->sig_validity_regeneration_seconds)) { zsk_mask |= 1ULL << i; log_debug("maintenance: DNSKEY: %{dnsname}+%03d+%05d/%d will be used for ZSK signatures", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); } } mctx.ksk_mask = ksk_mask; mctx.zsk_mask = zsk_mask; mctx.ksk_count = ptr_vector_size(&mctx.ksks); mctx.zsk_count = ptr_vector_size(&mctx.zsks); log_debug("maintenance: DNSKEY: %{dnsname}: ksk mask=%p, count=%llx, zsk mask=%p, count = %i", mctx.zone->origin, mctx.ksk_mask, mctx.ksk_count, mctx.zsk_mask, mctx.zsk_count); if(mctx.zsk_mask == 0) { zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_RRSIG_UPDATER); zone_diff_finalize(&diff); zdb_zone_maintenance_ctx_finalize(&mctx); return ZDB_ERROR_ZONE_NO_ZSK_PRIVATE_KEY_FILE; } ptr_vector remove = PTR_VECTOR_EMPTY; ptr_vector add = PTR_VECTOR_EMPTY; int loop_iterations = 0; // prevents loops to break in first iteration when the system is too slow (forever retrying) bool diff_has_changes = FALSE; bool actions_happened = FALSE; bool last_label_of_zone_reached = FALSE; //bool soa_updated = FALSE; diff.has_active_ksk = ksk_mask != 0; diff.has_active_zsk = zsk_mask != 0; // the maximum number of labels we are allowed to process in one pass int labels_at_once = mctx.zone->progressive_signature_update.labels_at_once; ya_result ret; log_debug("maintenance: %{dnsname}: has %i KSKs and %i ZSKs"/* (%i and %i)"*/, zone->origin, mctx.ksk_count, mctx.zsk_count/*, mctx_ksk_count, mctx_zsk_count*/); // no rrset to sign, for now ptr_vector rrset_to_sign = PTR_VECTOR_EMPTY; // get a copy of the APEX zone_diff_fqdn *apex = zone_diff_add_static_fqdn(&diff, diff.origin, zone->apex); zdb_zone_label_iterator iter; // initialises the "start-from" iterator if(zone->progressive_signature_update.chain_index < 0) { if((from_fqdn == NULL) || (*from_fqdn == 0)) { zdb_zone_label_iterator_init(&iter, zone); // also reset the earliest resignature mctx.zone->progressive_signature_update.earliest_signature_expiration = MAX_S32; mctx.zone->progressive_signature_update.labels_at_once = ZDB_ZONE_MAINTENANCE_LABELS_AT_ONCE_DEFAULT; } else { zdb_zone_label_iterator_init_from(&iter, zone, from_fqdn); } } nsec_zone_get_status(zone, &mctx.nsec_chain_status); dnssec_chain_add_chain(&mctx.nsec_chain_updater, (dnssec_chain_head_t)zone->nsec.nsec, (mctx.nsec_chain_status & NSEC_ZONE_REMOVING) != 0); // get all nsec3 statuses mctx.nsec3_chain_count = MIN(nsec3_zone_get_chain_count(zone), ZDB_ZONE_MAINTENANCE_NSEC3CHAIN_MAX); nsec3_zone_get_chains(zone, mctx.nsec3_chain, mctx.nsec3_chain_count); for(u8 nsec3_chain_index = 0; nsec3_chain_index < mctx.nsec3_chain_count; ++nsec3_chain_index) { const u8 *nsec3param_rdata = mctx.nsec3_chain[nsec3_chain_index]->rdata; nsec3_zone_get_status_from_rdata(zone, nsec3param_rdata, NSEC3_ZONE_RDATA_SIZE(mctx.nsec3_chain[nsec3_chain_index]), &mctx.nsec3_chain_status[nsec3_chain_index]); dnssec_chain_add_chain(&mctx.nsec3_chains_updater, (dnssec_chain_head_t)mctx.nsec3_chain[nsec3_chain_index], (mctx.nsec3_chain_status[nsec3_chain_index] & NSEC3_ZONE_REMOVING) != 0); } /************************************************************************************************************** * * "Normal" database (chain_index < 0) * **************************************************************************************************************/ ptr_vector rrset_vector = PTR_VECTOR_EMPTY; ptr_vector candidates = PTR_VECTOR_EMPTY; ptr_vector chain_candidates = PTR_VECTOR_EMPTY; int labels_to_process_count = labels_at_once; u8 from_digest[256]; if(zone->progressive_signature_update.chain_index < 0) { for(;;) { if(zdb_zone_label_iterator_hasnext(&iter)) { memcpy(&mctx.fqdn_stack.labels[0], &iter.dnslabels[0], (iter.top + 1) * sizeof(u8*)); mctx.fqdn_stack.size = iter.top; // MUST be called before zdb_zone_label_iterator_next(&iter) zdb_rr_label *rr_label = zdb_zone_label_iterator_next(&iter); // if we are under delegation : don't stop (resuming from under a delegation would require to fetch more data bool under_delegation = ZDB_LABEL_UNDERDELEGATION(rr_label); dnsname_stack_to_dnsname(&mctx.fqdn_stack, mctx.fqdn); // if too many iterations : break s64 now = timeus(); --labels_to_process_count; if(!under_delegation) { if(labels_to_process_count < 0) { #if DEBUG double dt = now - start_time; dt /= ONE_SECOND_US_F; log_debug("maintenance: %{dnsname}: time elapsed (%fs): fqdn quota spent: next one will be %{dnsnamestack}", zone->origin, dt, &mctx.fqdn_stack); #endif break; } #if !ZDB_ZONE_MAINTENANCE_IGNORE_TIME_QUOTA if((loop_iterations > 0) && (now - start_time >= maxus)) { // too much time taken already #if DEBUG double dt = now - start_time; dt /= ONE_SECOND_US_F; log_debug("maintenance: %{dnsname}: time elapsed (%fs): time spent: next one will be %{dnsnamestack}", zone->origin, dt, &mctx.fqdn_stack); #endif break; } #endif } ++loop_iterations; #if DEBUG log_debug2("maintenance: %{dnsname}: at %{dnsnamestack}", zone->origin, &mctx.fqdn_stack); #endif mctx.label = rr_label; zone_diff_fqdn *diff_fqdn = zone_diff_add_static_fqdn(&diff, mctx.fqdn, rr_label); maintenance_rrsig_count += zdb_zone_maintenance_rrsig(&mctx, diff_fqdn, &rrset_to_sign); maintenance_nsec_count += zdb_zone_maintenance_nsec(&mctx, diff_fqdn, &rrset_to_sign); maintenance_nsec3_count += zdb_zone_maintenance_nsec3(&mctx, diff_fqdn); // only affects the chain structure, hence the lack of "rrset_to_sign" #if DEBUG log_debug2("maintenance: %{dnsname}: at %{dnsnamestack} %i + %i + %i = %i", zone->origin, &mctx.fqdn_stack, maintenance_rrsig_count, maintenance_nsec_count, maintenance_nsec3_count, maintenance_rrsig_count + maintenance_nsec_count + maintenance_nsec3_count); #endif if(maintenance_rrsig_count + maintenance_nsec_count + maintenance_nsec3_count > 0) { // ++labels_to_process_count; actions_happened = TRUE; // if too many signatures are already to be generated, don't process more labels if(maintenance_rrsig_count > rrsigcountmax) { labels_at_once = loop_iterations; // update the amount of labels projected in this update labels_to_process_count = 0; // prevents doing more labels } } } else { #if DEBUG log_debug("maintenance: %{dnsname}: reached the last label", zone->origin); #endif if(mctx.nsec3_chain_count > 0) { // if the chain is not empty in the zone if(mctx.zone->nsec.nsec3->items != NULL) { log_debug("maintenance: %{dnsname}: will process NSEC3 chain(s)", zone->origin); zone->progressive_signature_update.chain_index = 0; nsec3_node *first = nsec3_get_first(&mctx.zone->nsec.nsec3->items); memcpy(from_digest, first->digest, first->digest[0] + 1); from_digest[first->digest[0] + 1] = 0; //from_fqdn_is_binary_digest = TRUE; log_debug("maintenance: %{dnsname}: starting work on NSEC3 chain %i", zone->origin, zone->progressive_signature_update.chain_index); } else { #if DEBUG log_debug("maintenance: %{dnsname}: no chain to process after the last label", zone->origin); #endif last_label_of_zone_reached = TRUE; } } else { #if DEBUG log_debug("maintenance: %{dnsname}: no chain in the zone to be processed after the last label", zone->origin); #endif last_label_of_zone_reached = TRUE; } break; } } // while has labels .. } else { // if we are working in the NSEC3 chains, the index is >= 0 // then we also want to decode the base32hex encoding to work on the binary digest from_digest[0] = base32hex_decode((const char*)&from_fqdn[1], from_fqdn[0], &from_digest[1]); //from_fqdn_is_binary_digest = TRUE; log_debug("maintenance: %{dnsname}: starting work on NSEC3 chain %i", zone->origin, zone->progressive_signature_update.chain_index); } // while no more normal labels are to be processed but NSEC3 chains are remaining /************************************************************************************************************** * * "NSEC3" database * **************************************************************************************************************/ while(zone->progressive_signature_update.chain_index >= 0) { loop_iterations = 0; //yassert(from_fqdn_is_binary_digest); nsec3_zone *n3e = zdb_zone_get_nsec3chain(mctx.zone, zone->progressive_signature_update.chain_index); nsec3_iterator iter; nsec3_iterator_init_from(&n3e->items, &iter, from_digest); // binary form for(;;) { if(nsec3_iterator_hasnext(&iter)) { nsec3_zone_item *item = nsec3_iterator_next_node(&iter); //u8 digest_len = NSEC3_NODE_DIGEST_SIZE(item); // check signature // mark signature for update // actions_happened = TRUE; s64 now = timeus(); if(item->rc <= 0) { double dt = now - start_time; dt /= ONE_SECOND_US_F; log_debug("maintenance: %{dnsname}: time elapsed (%fs): %{digest32h}.%{dnsname} has no owner (rc=%i, sc=%i)", zone->origin, dt, item->digest, zone->origin, item->rc, item->sc); } --labels_to_process_count; if(labels_to_process_count < 0) { #if DEBUG double dt = now - start_time; dt /= ONE_SECOND_US_F; log_debug("maintenance: %{dnsname}: time elapsed (%fs): fqdn quota spent: next one will be %{digest32h}.%{dnsname}", zone->origin, dt, item->digest, zone->origin); #endif u8 digest_len = NSEC3_NODE_DIGEST_SIZE(item); mctx.fqdn[0] = base32hex_lc_encode(NSEC3_NODE_DIGEST_PTR(item), digest_len, (char*)&mctx.fqdn[1]); dnsname_copy(&mctx.fqdn[mctx.fqdn[0] + 1], zone->origin); /************************************ * GOTO, breaking two loops at once.* ************************************/ goto zdb_zone_maintenance_from_chain_iteration_loop_break; } #if !ZDB_ZONE_MAINTENANCE_IGNORE_TIME_QUOTA if((loop_iterations > 0) && (now - start_time >= maxus)) { // too much time taken already #if DEBUG double dt = now - start_time; dt /= ONE_SECOND_US_F; log_debug("maintenance: %{dnsname}: time elapsed (%fs): time spent: next one will be %{digest32h}.%{dnsname}", zone->origin, dt, item->digest, zone->origin); #endif u8 digest_len = NSEC3_NODE_DIGEST_SIZE(item); mctx.fqdn[0] = base32hex_lc_encode(NSEC3_NODE_DIGEST_PTR(item), digest_len, (char*)&mctx.fqdn[1]); dnsname_copy(&mctx.fqdn[mctx.fqdn[0] + 1], zone->origin); /************************************ * GOTO, breaking two loops at once.* ************************************/ goto zdb_zone_maintenance_from_chain_iteration_loop_break; } #endif intptr nsec3_key_mask; zdb_packed_ttlrdata *rrsig = item->rrsig; bool delete_nsec3_rrsig = FALSE; if(rrsig != NULL) { nsec3_key_mask = 0; u32 key_matched = 0; do { s32 key_index = -2; // returns TRUE iff the signature needs to be removed, that covers "key not found" bool rrsig_should_remove_signature_from_rdata_result = rrsig_should_remove_signature_from_rdata( ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig), ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig), &mctx.zsks, mctx.now, zone->sig_validity_regeneration_seconds, &key_index); #if DEBUG_SIGNATURE_REFRESH rdata_desc nsec3_rrsig_desc = {TYPE_RRSIG, ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig), ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig)}; log_debug("maintenance: %{dnsname}: should-remove: %{digest32h}.%{dnsname} %{typerdatadesc}: %s (%i)", zone->origin, item->digest, zone->origin, &nsec3_rrsig_desc, (rrsig_should_remove_signature_from_rdata_result?"yes":"no"), key_index); #endif if(rrsig_should_remove_signature_from_rdata_result) { if(key_index >= 0) { // RRSIG will be removed, use the key_index to update the mask nsec3_key_mask |= 1LL << key_index; } else { // the key was not found: remove the RRSIG delete_nsec3_rrsig = TRUE; // this enables a "filter out" } } else { key_matched |= 1LL << key_index; } rrsig = rrsig->next; } while(rrsig != NULL); // keys whose signatures have not been found are added now nsec3_key_mask |= key_matched ^ mctx.zsk_mask; } else { nsec3_key_mask = mctx.zsk_mask; } #if DEBUG || DEBUG_SIGNATURE_REFRESH log_debug("maintenance: %{dnsname}: at %{digest32h}.%{dnsname} NSEC3: mask=%p/%p (has signature: %i, key-not-found: %i)", zone->origin, item->digest, zone->origin, nsec3_key_mask, mctx.zsk_mask, (rrsig != NULL), delete_nsec3_rrsig); if(rrsig != NULL) { for(zdb_packed_ttlrdata *rr = rrsig; rr != NULL; rr = rr->next) { const void *rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(rr); u16 rdata_size = ZDB_PACKEDRECORD_PTR_RDATASIZE(rr); log_debug("maintenance: %{dnsname}: at %{digest32h}.%{dnsname} RRSIG: %5i %T -> %T", zone->origin, item->digest, zone->origin, rrsig_get_key_tag_from_rdata(rdata, rdata_size), rrsig_get_valid_from_from_rdata(rdata, rdata_size), rrsig_get_valid_until_from_rdata(rdata, rdata_size)); } } #endif if((nsec3_key_mask != 0) || delete_nsec3_rrsig) { // generate signature or delete signatures zone_diff_fqdn_rr_set *nsec3_diff_rrset = NULL; #if DEBUG zone_diff_fqdn* nsec3_diff_fqdn = #endif zone_diff_add_nsec3_ex(&diff, &mctx.zsks, mctx.zone->nsec.nsec3, item, mctx.zone->min_ttl, &nsec3_diff_rrset, mctx.now, zone->sig_validity_regeneration_seconds); if(nsec3_diff_rrset != NULL) { #if DEBUG log_debug("maintenance: %{dnsname}: %{dnsname}: NSEC3 should be signed", zone->origin, nsec3_diff_fqdn->fqdn); #endif nsec3_diff_rrset->key_mask = nsec3_key_mask; ptr_vector_append(&rrset_to_sign, nsec3_diff_rrset); ++maintenance_generate_nsec3_rrsig_count; actions_happened = TRUE; } } ++loop_iterations; } else // end of iteration { // if there is another chain, take its first digest (binary form) if(++zone->progressive_signature_update.chain_index < mctx.nsec3_chain_count) { n3e = n3e->next; if(n3e != NULL) { log_debug("maintenance: %{dnsname}: starting work on NSEC3 chain %i", zone->origin, zone->progressive_signature_update.chain_index); nsec3_node *first = nsec3_get_first(&mctx.zone->nsec.nsec3->items); memcpy(from_digest, first->digest, first->digest[0] + 1); from_digest[first->digest[0] + 1] = 0; //from_fqdn_is_binary_digest = TRUE; break; } else { log_err("maintenance: %{dnsname}: NSEC3 chain smaller than expected", zone->origin); #if DEBUG log_debug("maintenance: %{dnsname}: no more chain after last label", zone->origin); #endif zone->progressive_signature_update.chain_index = -1; last_label_of_zone_reached = TRUE; mctx.fqdn[0] = 0; /************************************ * GOTO, breaking two loops at once.* ************************************/ goto zdb_zone_maintenance_from_chain_iteration_loop_break; // nothing else } } else { zone->progressive_signature_update.chain_index = -1; #if DEBUG log_debug("maintenance: %{dnsname}: nothing to do after last label (NSEC3 rrsig to do: %i)", zone->origin, maintenance_generate_nsec3_rrsig_count); #endif last_label_of_zone_reached = TRUE; mctx.fqdn[0] = 0; /************************************ * GOTO, breaking two loops at once.* ************************************/ goto zdb_zone_maintenance_from_chain_iteration_loop_break; // nothing else } } } // for } // while zdb_zone_maintenance_from_chain_iteration_loop_break: #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG log_debug("maintenance: %{dnsname}: last_label_of_zone_reached: %i, rrset_to_sign contains %i items", zone->origin, last_label_of_zone_reached, ptr_vector_size(&rrset_to_sign)); #endif diff.nsec_change_count = maintenance_nsec_count; diff.nsec3_change_count = maintenance_nsec3_count; diff_has_changes |= maintenance_nsec_count > 0; diff_has_changes |= zone_diff_has_changes(&diff, &rrset_to_sign); #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG log_debug("maintenance: %{dnsname}: diff_has_changes: %i, last_label_of_zone_reached: %i, rrset_to_sign contains %i items", zone->origin, diff_has_changes, last_label_of_zone_reached, ptr_vector_size(&rrset_to_sign)); #endif if(diff_has_changes && !last_label_of_zone_reached) { #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(&remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-validate-sign: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(&add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-validate-sign: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } #endif } else // not diff_has_changes { log_debug("maintenance: %{dnsname}: no changes", zone->origin); } if(last_label_of_zone_reached) { log_debug("maintenance: %{dnsname}: closing edited chains", zone->origin); // add missing NSEC3PARAM // remove TYPE65282 // update NSEC3 // update signatures bool updated = FALSE; if(zone_diff_will_have_rrset_type(apex, TYPE_NSEC3CHAINSTATE)) { #if DEBUG log_debug("maintenance: %{dnsname}: NSEC3CHAINSTATE will be present", zone->origin); #endif // NSEC3PARAM zdb_packed_ttlrdata* nsec3chainstate = zdb_record_find(&zone->apex->resource_record_set, TYPE_NSEC3CHAINSTATE); if(nsec3chainstate != NULL) { do { // find the nsec3param matching nsec3chainstate in nsec3param_rrset // if no match has been found, add a new nsec3param zone_diff_label_rr *rr = zone_diff_record_add(&diff, zone->apex, zone->origin, TYPE_NSEC3PARAM, 0 /* TTL value enforced to 0 */, ZDB_PACKEDRECORD_PTR_RDATASIZE(nsec3chainstate) - 1, ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec3chainstate) ); // clears the opt-out flag that exists in the NSEC3CHAINSTATE record u8* flagsp = &((u8*)rr->rdata)[1]; *flagsp = 0; nsec3chainstate = nsec3chainstate->next; } while(nsec3chainstate != NULL); yassert(apex != NULL); zone_diff_fqdn_rr_set *nsec3chainstate_rrset = zone_diff_fqdn_rr_set_get(apex, TYPE_NSEC3CHAINSTATE); yassert(nsec3chainstate_rrset != NULL); zone_diff_fqdn_rr_set_set_state(nsec3chainstate_rrset, ZONE_DIFF_RR_REMOVE); ptr_vector_append(&rrset_to_sign, nsec3chainstate_rrset); zone_diff_fqdn_rr_set *nsec3paramqueued_rrset = zone_diff_fqdn_rr_set_get(apex, TYPE_NSEC3PARAMQUEUED); if(nsec3paramqueued_rrset != NULL) { yassert(nsec3paramqueued_rrset != NULL); zone_diff_fqdn_rr_set_set_state(nsec3paramqueued_rrset, ZONE_DIFF_RR_REMOVE); ptr_vector_append(&rrset_to_sign, nsec3paramqueued_rrset); } zone_diff_fqdn_rr_set *nsec3param_rrset = zone_diff_fqdn_rr_set_get(apex, TYPE_NSEC3PARAM); if(nsec3param_rrset != NULL) { yassert(nsec3param_rrset != NULL); nsec3param_rrset->key_mask = zsk_mask; ptr_vector_append(&rrset_to_sign, nsec3param_rrset); } ++maintenance_generate_nsec3param_rrsig_count; updated = TRUE; actions_happened = TRUE; } } if(zone_diff_will_have_rrset_type(apex, TYPE_NSECCHAINSTATE)) { yassert(apex != NULL); zone_diff_fqdn_rr_set *nsecchainstate_rrset = zone_diff_fqdn_rr_set_get(apex, TYPE_NSECCHAINSTATE); yassert(nsecchainstate_rrset != NULL); zone_diff_fqdn_rr_set_set_state(nsecchainstate_rrset, ZONE_DIFF_RR_REMOVE); updated = TRUE; nsecchainstate_changed = TRUE; actions_happened = TRUE; } if(updated) { diff_has_changes = TRUE; zdb_zone_maintenance_nsec(&mctx, apex, NULL); zdb_zone_maintenance_nsec3(&mctx, apex); } } // if remove contains more than +- SOA and +- SOA RRSIG ... if(actions_happened) { u32 soa_serial = 0; zdb_packed_ttlrdata* soa = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA); if(soa != NULL) { //zone_diff_record_remove(&diff, zone->apex, zone->origin, TYPE_SOA, soa->ttl, ZDB_PACKEDRECORD_PTR_RDATASIZE(soa), ZDB_PACKEDRECORD_PTR_RDATAPTR(soa)); zone_diff_record_remove_automated(&diff, zone->apex, zone->origin, TYPE_SOA, soa->ttl, ZDB_PACKEDRECORD_PTR_RDATASIZE(soa), ZDB_PACKEDRECORD_PTR_RDATAPTR(soa)); rr_soa_get_serial(ZDB_PACKEDRECORD_PTR_RDATAPTR(soa), ZDB_PACKEDRECORD_PTR_RDATASIZE(soa), &soa_serial); } log_debug("maintenance: %{dnsname}: serial=%u actions: rrsig=%i nsec=%i nsec3=%i nsec3-rrsig=%i nsec3param=%i chain-state=%i", zone->origin, soa_serial, maintenance_rrsig_count, maintenance_nsec_count, maintenance_nsec3_count, maintenance_generate_nsec3_rrsig_count, maintenance_generate_nsec3param_rrsig_count, nsecchainstate_changed); if(ISOK(zone_diff_set_soa(&diff, zone->apex))) { #if DEBUG log_debug1("maintenance: %{dnsname}: SOA should be signed", zone->origin); #endif yassert(apex != NULL); zone_diff_fqdn_rr_set *soa_rrset = zone_diff_fqdn_rr_set_get(apex, TYPE_SOA); soa_rrset->key_mask = zsk_mask; yassert(soa_rrset != NULL); ptr_vector_append(&rrset_to_sign, soa_rrset); } #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(&remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-validate-sign: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(&add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("before-validate-sign: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } #endif /* * Does validation checks on the update. * Generates signatures for the specified RRSETs. */ diff_has_changes = zdb_zone_maintenance_validate_sign_chain_store(&mctx, &diff, zone, &rrset_to_sign, &remove, &add); if(!diff_has_changes) { log_debug("maintenance: %{dnsname}: update contains nothing", zone->origin); } #if ZDB_ZONE_MAINTENANCE_DETAILED_LOG for(int i = 0; i <= ptr_vector_last_index(&remove); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&remove, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("after-validate-sign: %{dnsname}: - %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } for(int i = 0; i <= ptr_vector_last_index(&add); ++i) { zone_diff_label_rr *rr = (zone_diff_label_rr*)ptr_vector_get(&add, i); rdata_desc rd = {rr->rtype, rr->rdata_size, rr->rdata}; log_debug("after-validate-sign: %{dnsname}: + %{dnsname} %9i %{typerdatadesc} ; (W+R)", zone->origin, rr->fqdn, rr->ttl, &rd); } #endif } ptr_vector_destroy(&rrset_to_sign); ptr_vector_destroy(&chain_candidates); ptr_vector_destroy(&candidates); ptr_vector_destroy(&rrset_vector); if(diff_has_changes) { log_debug("maintenance: %{dnsname}: writing and playing transaction", zone->origin); ret = dynupdate_diff_write_to_journal_and_replay(zone, ZDB_ZONE_MUTEX_RRSIG_UPDATER, &remove, &add); } else { ret = 0; } ptr_vector_destroy(&remove); ptr_vector_destroy(&add); if(ISOK(ret)) { if(ret < 32768) { if(ret > 0) { double r = 32768.0; r /= ret; r *= labels_at_once; if(r > 65535.0) { r = 65535; } mctx.zone->progressive_signature_update.labels_at_once = (u16)r; } else { mctx.zone->progressive_signature_update.labels_at_once = MAX_U16; } log_debug("maintenance: %{dnsname}: adjusting up batch size to %i", zone->origin, mctx.zone->progressive_signature_update.labels_at_once); } else { if(mctx.zone->progressive_signature_update.labels_at_once > 1) { mctx.zone->progressive_signature_update.labels_at_once /= 2; log_debug("maintenance: %{dnsname}: adjusting down batch size to %i", zone->origin, mctx.zone->progressive_signature_update.labels_at_once); } } } log_debug("maintenance: %{dnsname}: releasing resources", zone->origin); zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_RRSIG_UPDATER); zdb_zone_maintenance_ctx_finalize(&mctx); zone_diff_finalize(&diff); if(last_label_of_zone_reached) { if(ISOK(ret)) { #if ZDB_ZONE_MAINTENANCE_SAME_PASS_CLOSE log_info("maintenance: %{dnsname}: done", zone->origin); ret = 0; // so the caller do not try to call again right away. mctx.fqdn[0] = '\0'; #else if(!diff_has_changes) // the end and no changes : closure must have happened { log_debug("maintenance: %{dnsname}: done, for now", zone->origin); ret = 0; // so the caller do not try to call again right away. mctx.fqdn[0] = '\0'; } else { log_debug("maintenance: %{dnsname}: done, but will allow for one last pass", zone->origin); ret = 1; // else the potential closing of the chain will not happen } #endif } else { if(ret != ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { log_warn("maintenance: %{dnsname}: reached the end, but with an error code: %r", zone->origin, ret); } else { log_debug("maintenance: %{dnsname}: reached the end, but zone must be stored", zone->origin); } } } else { if(ret == 0) { log_debug("maintenance: %{dnsname}: another pass will follow from %{dnsname}", zone->origin, mctx.fqdn); ret = 1; // else the remaining will be postponed for a while } } if(ISOK(ret)) { size_t fqdn_len = dnsname_len(mctx.fqdn); if((fqdn_len <= from_fqdn_size) && (from_fqdn != NULL)) { log_debug("maintenance: %{dnsname}: saving the next node (%{dnsname})", zone->origin, mctx.fqdn); memcpy(from_fqdn, mctx.fqdn, fqdn_len); // if from_fqdn == 0, fqdl_len == 0 //from_fqdn_is_binary_digest = FALSE; } else { log_debug("maintenance: %{dnsname}: cannot save the next node (%{dnsname}) as buffer size is too small (%llu < %llu)", zone->origin, mctx.fqdn, from_fqdn_size, fqdn_len); } } else { log_debug("maintenance: %{dnsname}: an error state occurred (%r), keeping previous state (%{dnsname}), ignoring next state (%{dnsname})", zone->origin, ret, from_fqdn, mctx.fqdn); } /* if(from_fqdn_is_binary_digest) { log_err("maintenance: %{dnsname}: next fqdn is binary digest %{digest32h}", zone->origin, from_fqdn); } yassert(!from_fqdn_is_binary_digest); */ s64 stop_time = timeus(); double dt = stop_time - start_time; if(dt < 0) dt = 0; dt /= ONE_SECOND_US_F; log_debug("rrsig: %{dnsname}: %r (%.3fs)", zone->origin, ret, dt); return ret; } /** * Will double-lock for reader & rrsig-updater * * @param zone * @param signature_count_loose_limit * @param present_signatures_are_verified * @return 0 : all done, >0 : some done (some could be 0), <0 error */ ya_result zdb_zone_maintenance(zdb_zone* zone) { ya_result ret; u8 *prev_fqdn; s8 prev_chain_index; u8 in_out_fqdn[MAX_DOMAIN_LENGTH]; if(zone->progressive_signature_update.current_fqdn != NULL) { log_debug("maintenance: %{dnsname}: resuming from %{dnsname}", zone->origin, zone->progressive_signature_update.current_fqdn); dnsname_copy(in_out_fqdn, zone->progressive_signature_update.current_fqdn); prev_fqdn = zone->progressive_signature_update.current_fqdn; prev_chain_index = zone->progressive_signature_update.chain_index; //dnsname_zfree(zone->progressive_signature_update.current_fqdn); zone->progressive_signature_update.current_fqdn = NULL; } else { prev_fqdn = NULL; prev_chain_index = -1; log_info("maintenance: %{dnsname}: zone maintenance started", zone->origin); in_out_fqdn[0] = 0; #if DEBUG memset(in_out_fqdn, 0, sizeof(in_out_fqdn)); #endif zone->progressive_signature_update.current_fqdn = NULL; zone->progressive_signature_update.chain_index = -1; #if DEBUG log_debug("maintenance: %{dnsname}: interval=%is jitter=%is regeneration=%is (DEBUG)", zone->origin, zone->sig_validity_interval_seconds, zone->sig_validity_jitter_seconds, zone->sig_validity_regeneration_seconds); #endif } ret = zdb_zone_maintenance_from(zone, in_out_fqdn, sizeof(in_out_fqdn), ZDB_MAINTENANCE_BATCH_TIME_US_MAX, ZDB_ZONE_MAINTENANCE_RRSIG_COUNT_THRESHOLD); if(in_out_fqdn[0] != 0) { if(ISOK(ret)) { zone->progressive_signature_update.current_fqdn = dnsname_zdup(in_out_fqdn); if(prev_fqdn != NULL) { dnsname_zfree(prev_fqdn); prev_fqdn = NULL; } log_debug("maintenance: %{dnsname}: pausing at %{dnsname} (%r)", zone->origin, zone->progressive_signature_update.current_fqdn, ret); } else { if(prev_fqdn != NULL) { zone->progressive_signature_update.current_fqdn = prev_fqdn; zone->progressive_signature_update.chain_index = prev_chain_index; prev_fqdn = NULL; // prev_chain_index = -1; log_debug("maintenance: %{dnsname}: pausing at %{dnsname} (%r) (may try again)", zone->origin, zone->progressive_signature_update.current_fqdn, ret); } else { log_debug("maintenance: %{dnsname}: pausing (%r) (may try again)", zone->origin, ret); } } } else { if(prev_fqdn != NULL) { dnsname_zfree(prev_fqdn); prev_fqdn = NULL; } log_debug("maintenance: %{dnsname}: done (%r)", zone->origin, ret); } if(ret == 0) { log_info("maintenance: %{dnsname}: zone maintenance finished", zone->origin); } return ret; } ya_result zdb_zone_sign(zdb_zone* zone) { ya_result ret = zdb_zone_maintenance_from(zone, NULL, 0, ZDB_MAINTENANCE_BATCH_TIME_US_MAX, ZDB_ZONE_MAINTENANCE_RRSIG_COUNT_THRESHOLD); return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-maintenance-rrsig.c0000644000000000000000000000013214505005531024264 xustar000000000000000030 mtime=1695812441.743972177 30 atime=1695812445.802030296 30 ctime=1695812495.163737255 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-maintenance-rrsig.c0000664000374500037450000004010614505005531024227 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include "dnsdb/zdb-zone-maintenance.h" #include "dnsdb/rrsig.h" #include "dnsdb/zdb_zone.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger #define DEBUG_RRSIG_PASS_STATES 0 #if DEBUG_RRSIG_PASS_STATES #pragma message("WARNING: DEBUG_RRSIG_PASS_STATES IS NOT SET TO 0. SET IT BACK TO 0 IT IF YOU DON'T NEED IT!") #endif /** * Adds a node (type,0) in a u32_set for each rrset in the label pointed out by mctx. * * @param mctx * @param type_coverage */ static void zdb_zone_maintenance_rrsig_coverage_init(zdb_zone_maintenance_ctx* mctx, u32_set *type_coverage) { btree_iterator iter; btree_iterator_init(mctx->label->resource_record_set, &iter); while(btree_iterator_hasnext(&iter)) { btree_node *rr_node = btree_iterator_next_node(&iter); u16 type = (u16)rr_node->hash; if(/*(type != TYPE_NSEC) && */(type != TYPE_RRSIG)) { u32_set_insert(type_coverage, type); } } } static int zdb_zone_maintenance_rrsig_coverage_finalize(zdb_zone_maintenance_ctx* mctx, zone_diff_fqdn *diff_fqdn, ptr_vector *rrset_to_sign, u32_set *type_coverage) { int signatures_to_generate = 0; intptr ksk_mask = mctx->ksk_mask; intptr zsk_mask = mctx->zsk_mask; bool at_or_underdelegation = ZDB_LABEL_ATORUNDERDELEGATION(mctx->label); //u8 maintain_mode = zone_get_maintain_mode(mctx->zone); if(!at_or_underdelegation) { u32_set_iterator iter; u32_set_iterator_init(type_coverage, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); intptr mask = (intptr)node->value; // what is really covering intptr key_mask = (node->key != TYPE_DNSKEY)?zsk_mask:ksk_mask; // what it should be covered by if((key_mask & mask) != key_mask) { // there are holes : set has to be updated // give the rrset from the diff zone_diff_fqdn_rr_set *rrset = zone_diff_fqdn_rr_set_get(diff_fqdn, node->key); rrset->key_mask = (key_mask & mask) ^ key_mask; // get the needed coverage into rrset->key_mask #if DEBUG u16 rtype = (u16)node->key; log_debug1("maintenance: %{dnsname}: %{dnsname} %{dnstype} will have its RRSIGs updated", mctx->zone->origin, diff_fqdn->fqdn, &rtype); #endif ptr_vector_append(rrset_to_sign, rrset); ++signatures_to_generate; } } } else { if(zone_diff_will_have_rrset_type(diff_fqdn, TYPE_DS)) { zone_diff_fqdn_rr_set *ds_rrset = zone_diff_fqdn_rr_set_get(diff_fqdn, TYPE_DS); if(ds_rrset != NULL) { u32_node *node = u32_set_find(type_coverage, TYPE_DS); intptr mask = (node != NULL)?(intptr)node->value:0; intptr key_mask = zsk_mask; if((key_mask & mask) != key_mask) { ds_rrset->key_mask = (key_mask & mask) ^ key_mask; #if DEBUG log_debug1("maintenance: %{dnsname}: %{dnsname} DS will have its RRSIGs updated", mctx->zone->origin, diff_fqdn->fqdn); #endif ptr_vector_append(rrset_to_sign, ds_rrset); ++signatures_to_generate; } else { #if DEBUG log_debug1("maintenance: %{dnsname}: %{dnsname} properly signed already", mctx->zone->origin, diff_fqdn->fqdn); #endif } } } /* if(maintain_mode == ZDB_ZONE_MAINTAIN_NSEC) { } */ } zone_diff_fqdn_rr_clear(diff_fqdn, TYPE_RRSIG); // only deletes the set if it is empty u32_set_destroy(type_coverage); return signatures_to_generate; } /** * Updates the signatures of a zone incrementally. * Each call goes a bit further. * * @param zone * @param signature_count_loose_limit * @param present_signatures_are_verified * @return the number of actions made by the call */ int zdb_zone_maintenance_rrsig(zdb_zone_maintenance_ctx* mctx, zone_diff_fqdn *diff_fqdn, ptr_vector *rrset_to_sign) { ya_result signatures_to_add_or_remove = 0; #if DEBUG_RRSIG_PASS_STATES log_debug("maintenance: rrsig: %{dnsname}: %{dnsname}", mctx->zone->origin, diff_fqdn->fqdn); #endif // for all RRSIG: remove expired ones if(rrsig_should_label_be_signed(mctx->zone, mctx->fqdn, mctx->label)) { #if DEBUG log_debug2("zdb_zone_maintenance_rrsig: %{dnsname}", diff_fqdn->fqdn); zone_diff_fqdn_log(diff_fqdn, mctx->zone->origin, MODULE_MSG_HANDLE, MSG_DEBUG1); #endif // generate a set of all the (relevant) types in the label, and list a node by key // they are meant to be signed with // first, remove the expired or unknown signatures bool create_signatures = TRUE; bool at_delegation = ZDB_LABEL_ATDELEGATION(mctx->label); bool above_delegation = !ZDB_LABEL_ATORUNDERDELEGATION(mctx->label); bool will_have_ds = zone_diff_will_have_rrset_type(diff_fqdn, TYPE_DS); bool will_have_nsec = zone_diff_will_have_rrset_type(diff_fqdn, TYPE_NSEC); switch(zone_get_maintain_mode(mctx->zone)) { case ZDB_ZONE_MAINTAIN_NSEC: create_signatures = above_delegation || (at_delegation && (will_have_nsec || will_have_ds)); break; case ZDB_ZONE_MAINTAIN_NSEC3: create_signatures = above_delegation || (at_delegation && will_have_ds); break; case ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT: create_signatures = above_delegation || (at_delegation && will_have_ds); break; } u32_set type_coverage = U32_SET_EMPTY; zdb_zone_maintenance_rrsig_coverage_init(mctx, &type_coverage); // look if there are expired signatures (time, key, ...) // mark them for removal, mark the covered rrset for signature zone_diff_fqdn_rr_set *rrsig_set = zone_diff_fqdn_rr_set_get(diff_fqdn, TYPE_RRSIG); if(rrsig_set != NULL) { #if DEBUG_RRSIG_PASS_STATES log_debug("maintenance: rrsig: %{dnsname}: %{dnsname}: contains signatures", mctx->zone->origin, diff_fqdn->fqdn); #endif zone_diff_fqdn_rr_set* rrsig_covered_rrset_cached = NULL; u16 rrsig_ctype_cached = MAX_U16; s32 rrsig_ctype_ttl = -1; // for all RRSIG records ... ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrsig_set->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rrsig_rr = (zone_diff_label_rr *)node->key; #if DEBUG_RRSIG_PASS_STATES u16 tmp_type = rrsig_get_type_covered_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); rdata_desc rrsig_rr_rd = {rrsig_rr->rtype, rrsig_rr->rdata_size, rrsig_rr->rdata}; format_writer temp_fw_0 = {zone_diff_record_state_format, &rrsig_rr->state}; log_debug("maintenance: rrsig: %{dnsname}: has %w %{dnsname} %9i %{typerdatadesc}", mctx->zone->origin, &temp_fw_0, rrsig_rr->fqdn, rrsig_rr->ttl, &rrsig_rr_rd); #endif if((rrsig_rr->state & ZONE_DIFF_RR_REMOVE) != 0) { #if DEBUG_RRSIG_PASS_STATES log_debug("maintenance: rrsig: %{dnsname}: %{dnsname}: RRSIG %02x %{dnstype} %T %T (already being removed)", mctx->zone->origin, diff_fqdn->fqdn, rrsig_rr->state, &tmp_type, rrsig_get_valid_until_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size), rrsig_get_valid_from_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size)); #endif continue; // signature is being removed already: ignore } s32 valid_until = rrsig_get_valid_until_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); s32 valid_from = rrsig_get_valid_from_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); u16 type_covered = rrsig_get_type_covered_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); if(valid_from > valid_until) { log_warn("maintenance: rrsig: %{dnsname}: %{dnsname}: %{dnstype}: bad timings (%T > %T)", mctx->zone->origin, diff_fqdn->fqdn, &type_covered, valid_from, valid_until); rrsig_rr->state |= ZONE_DIFF_RR_REMOVE; ++signatures_to_add_or_remove; continue; } ptr_vector *keys = (type_covered!= TYPE_DNSKEY)?&mctx->zsks:&mctx->ksks; s32 key_index = -2; if(rrsig_should_remove_signature_from_rdata( rrsig_rr->rdata, rrsig_rr->rdata_size, keys, mctx->now, mctx->zone->sig_validity_regeneration_seconds, &key_index) || (key_index == -1)) { #if DEBUG_RRSIG_PASS_STATES log_debug("maintenance: rrsig: %{dnsname}: will replace %{dnsname} %9i %{typerdatadesc}", mctx->zone->origin, /*valid_until, mctx->zone->sig_validity_regeneration_seconds, mctx->now,*/ rrsig_rr->fqdn, rrsig_rr->ttl, &rrsig_rr_rd); #endif rrsig_rr->state |= ZONE_DIFF_RR_REMOVE; ++signatures_to_add_or_remove; continue; } // if valid_until is earlier than the current earliest for the zone, update the latter if(mctx->zone->progressive_signature_update.earliest_signature_expiration > valid_until) { mctx->zone->progressive_signature_update.earliest_signature_expiration = valid_until; } if(type_covered != rrsig_ctype_cached) { rrsig_ctype_cached = type_covered; rrsig_covered_rrset_cached = zone_diff_fqdn_rr_set_get(diff_fqdn, type_covered); if(rrsig_covered_rrset_cached != NULL) { rrsig_ctype_ttl = zone_diff_fqdn_rr_set_get_ttl(rrsig_covered_rrset_cached); } else { rrsig_ctype_ttl = -1; } } if(rrsig_ctype_ttl >= 0) { yassert(key_index >= 0); dnssec_key *key = (dnssec_key*)ptr_vector_get(keys, key_index); // only fix the TTL if the key is able to sign if(dnskey_is_private(key)) { s32 rrsig_original_ttl = rrsig_get_original_ttl_from_rdata(rrsig_rr->rdata, rrsig_rr->rdata_size); if(rrsig_original_ttl != rrsig_ctype_ttl) { // TTL does not match: redo rrsig_rr->state |= ZONE_DIFF_RR_REMOVE; ++signatures_to_add_or_remove; continue; } } } else { // no such type: remove rrsig_rr->state |= ZONE_DIFF_RR_REMOVE; ++signatures_to_add_or_remove; continue; } rrsig_covered_rrset_cached->key_mask |= 1ULL << key_index; u32_node *type_node = u32_set_find(&type_coverage, type_covered); if(type_node != NULL) { // update the key coverage mask intptr mask = (intptr)type_node->value; mask |= 1ULL << key_index; type_node->value = (void*)mask; } } // while RR in RRSET } else { #if DEBUG log_debug2("maintenance: rrsig: %{dnsname}: %{dnsname}: contains no signatures", mctx->zone->origin, diff_fqdn->fqdn); #endif } #if DEBUG_RRSIG_PASS_STATES log_debug2("zdb_zone_maintenance_rrsig: %{dnsname} after RRSIG pass", diff_fqdn->fqdn); zone_diff_fqdn_log(diff_fqdn, mctx->zone->origin, MODULE_MSG_HANDLE, MSG_DEBUG1); #endif // masks have been set if(create_signatures) { #if DEBUG log_debug2("maintenance: rrsig: %{dnsname}: %{dnsname}: will create signatures", mctx->zone->origin, diff_fqdn->fqdn); #endif int modified_rrset = zdb_zone_maintenance_rrsig_coverage_finalize(mctx, diff_fqdn, rrset_to_sign, &type_coverage); signatures_to_add_or_remove += modified_rrset; if(modified_rrset > 0) { diff_fqdn->rrsig_expect_new_rrsig = (rrsig_set == NULL); } } else // opt-out zone and not apex nor delegation with a DS record { #if DEBUG log_debug2("maintenance: rrsig: %{dnsname}: %{dnsname}: removing emtpy signatures rrset", mctx->zone->origin, diff_fqdn->fqdn); #endif zone_diff_fqdn_rr_clear(diff_fqdn, TYPE_RRSIG); // removes the empty RRSIG rrset (or do nothing) u32_set_destroy(&type_coverage); } #if DEBUG_RRSIG_PASS_STATES log_debug2("zdb_zone_maintenance_rrsig: %{dnsname} after create pass", diff_fqdn->fqdn); zone_diff_fqdn_log(diff_fqdn, mctx->zone->origin, MODULE_MSG_HANDLE, MSG_DEBUG1); #endif } #if DEBUG else { log_debug("zdb_zone_maintenance_rrsig: %{dnsname} should not be signed (REMOVE EXISTING)", diff_fqdn->fqdn); } #endif return signatures_to_add_or_remove; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-maintenance-nsec.c0000644000000000000000000000013214505005531024066 xustar000000000000000030 mtime=1695812441.707971661 30 atime=1695812445.800030268 30 ctime=1695812495.165737284 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-maintenance-nsec.c0000664000374500037450000002112414505005531024030 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include "dnsdb/zdb-zone-maintenance.h" #include "dnsdb/rrsig.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger /** * Updates the signatures of a zone incrementally. * Each call goes a bit further. * * @param zone * @param signature_count_loose_limit * @param present_signatures_are_verified * @return the number of actions counted */ int zdb_zone_maintenance_nsec(zdb_zone_maintenance_ctx* mctx, zone_diff_fqdn *diff_fqdn, ptr_vector *rrset_to_sign) { // if NSEC created : // _ add the NSEC record & signature if missing // _ update the NSEC RRSIG // _ add the NSEC node to the collection // if NSEC removal : // _ remove the NSEC record & signature // _ remove the NSEC node from the collection // NSEC signatures should be handled with the general signatures int ret = 0; if((mctx->nsec_chain_status & (NSEC_ZONE_GENERATING|NSEC_ZONE_REMOVING)) == NSEC_ZONE_GENERATING) { // add zdb_packed_ttlrdata *nsec_rrset = zdb_record_find(&mctx->label->resource_record_set, TYPE_NSEC); if(nsec_rrset == NULL) { // need to add the NSEC record and its signature // difficult as the next record has to be known ret = dnssec_chain_add_from_diff_fqdn(&mctx->nsec_chain_updater, diff_fqdn, 0); } } else if((mctx->nsec_chain_status & (NSEC_ZONE_GENERATING|NSEC_ZONE_REMOVING)) == NSEC_ZONE_REMOVING) { // del zdb_packed_ttlrdata *nsec_rrset = zdb_record_find(&mctx->label->resource_record_set, TYPE_NSEC); if(nsec_rrset != NULL) { // need to remove the NSEC record(s) and its signature(s) // simple to do ret = dnssec_chain_del_from_diff_fqdn(&mctx->nsec_chain_updater, diff_fqdn, 0); } } else { if(rrset_to_sign != NULL) { #if DEBUG log_debug1("maintenance: %{dnsname}: looking at NSEC RRSIG coverage", mctx->zone->origin); #endif if(zone_diff_will_have_rrset_type(diff_fqdn, TYPE_NSEC)) { zone_diff_fqdn_rr_set *nsec_rrset = zone_diff_fqdn_rr_set_get((zone_diff_fqdn *) diff_fqdn, TYPE_NSEC); if(nsec_rrset != NULL) { #if DEBUG log_debug1("maintenance: %{dnsname}: NSEC RRSET exists", mctx->zone->origin); #endif #if 0 zone_diff_fqdn_rr_set *rrsig_rrset = zone_diff_fqdn_rr_set_get((zone_diff_fqdn *) diff_fqdn, TYPE_RRSIG); #endif bool sign_nsec_rrset = TRUE; #if 0 if(rrsig_rrset != NULL) { bool has_one_valid_signature = FALSE; sign_nsec_rrset = FALSE; ptr_set_iterator rr_iter; ptr_set_iterator_init(&rrsig_rrset->rr, &rr_iter); while(ptr_set_iterator_hasnext(&rr_iter)) { ptr_node *node = ptr_set_iterator_next_node(&rr_iter); zone_diff_label_rr *rr = (zone_diff_label_rr *)node->key; if((rr->state & ZONE_DIFF_RR_REMOVE) != 0) { continue; // signature is being removed already: ignore } u16 covered_type = rrsig_get_type_covered_from_rdata(rr->rdata, rr->rdata_size); if(covered_type == TYPE_NSEC) { s32 key_index = -2; if(rrsig_should_remove_signature_from_rdata( rr->rdata, rr->rdata_size, &mctx->zsks, mctx->now, mctx->zone->sig_validity_regeneration_seconds, &key_index) && (key_index != -1)) { #if DEBUG log_debug1("maintenance: %{dnsname}: NSEC RRSET signature should be removed", mctx->zone->origin); #endif sign_nsec_rrset = TRUE; break; } else { #if DEBUG log_debug1("maintenance: %{dnsname}: NSEC RRSET is covered by at least one signature", mctx->zone->origin); #endif has_one_valid_signature = TRUE; } } } sign_nsec_rrset |= has_one_valid_signature; } else { #if DEBUG log_debug1("maintenance: %{dnsname}: NSEC RRSET and there are no signatures at all on the label", mctx->zone->origin); #endif sign_nsec_rrset = TRUE; } #endif if(sign_nsec_rrset) // always true ... { for(int i = 0; i <= ptr_vector_last_index(rrset_to_sign); ++i) { if(ptr_vector_get(rrset_to_sign, i) == nsec_rrset) { sign_nsec_rrset = FALSE; break; } } if(sign_nsec_rrset) { #if DEBUG u16 rtype = TYPE_NSEC; log_debug1("maintenance: %{dnsname}: %{dnsname} %{dnstype} will have its RRSIGs updated", mctx->zone->origin, diff_fqdn->fqdn, &rtype); #endif ptr_vector_append(rrset_to_sign, nsec_rrset); ++ret; } else { log_debug1("maintenance: %{dnsname}: NSEC RRSET is already marked for signature", mctx->zone->origin); } } else { #if DEBUG log_debug1("maintenance: %{dnsname}: NSEC RRSET does not need to be signed again", mctx->zone->origin); #endif } } } } } return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-zone-maintenance-nsec3.c0000644000000000000000000000013114505005531024150 xustar000000000000000029 mtime=1695812441.75397232 30 atime=1695812445.802030296 30 ctime=1695812495.167737313 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-zone-maintenance-nsec3.c0000664000374500037450000000525214505005531024117 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup dnsdb * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include "dnsdb/zdb-zone-maintenance.h" #include "dnsdb/dynupdate-diff.h" extern logger_handle* g_database_logger; #define MODULE_MSG_HANDLE g_database_logger /** * Updates the signatures of a zone incrementally. * Each call goes a bit further. * * @param zone * @param signature_count_loose_limit * @param present_signatures_are_verified * * @return the number of actions counted */ int zdb_zone_maintenance_nsec3(zdb_zone_maintenance_ctx* mctx, zone_diff_fqdn *diff_fqdn) { int ret = dnssec_chain_add_from_diff_fqdn(&mctx->nsec3_chains_updater, diff_fqdn, 0); return ret; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dnssec.c0000644000000000000000000000013214505005531020407 xustar000000000000000030 mtime=1695812441.731972005 30 atime=1695812445.801030282 30 ctime=1695812495.170737356 yadifa-2.6.5-11201/lib/dnsdb/src/dnssec.c0000664000374500037450000001062714505005531020357 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnsdbdnssec DNSSEC functions * @ingroup dnsdb * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #define _DNSSEC_C #include "dnsdb/dnsdb-config.h" #include #include #include #include //#include #include #include #include "dnsdb/dnssec.h" #include "dnsdb/dnsrdata.h" #include "dnsdb/zdb_utils.h" #include "dnsdb/zdb_error.h" #include #define MODULE_MSG_HANDLE g_dnssec_logger logger_handle *g_dnssec_logger = LOGGER_HANDLE_SINK; /* * NOTE: strtok_r CRASHES if the first parameter is on non-writable memory (ie: "openssl" instead of strdup("openssl") ) * In order to avoid this, I dup the string before processing it. */ ENGINE* dnssec_loadengine(const char *engine_name_const) { ENGINE *engine; char *token_pointer = NULL; char *engine_name = strdup(engine_name_const); char *token = strtok_r(engine_name, ENGINE_COMMAND_DELIMITER, &token_pointer); if(token == NULL) { engine = ENGINE_by_id(engine_name); } else { engine = ENGINE_by_id(token); token = strtok_r(NULL, ENGINE_COMMAND_DELIMITER, &token_pointer); } if(engine == NULL) { log_err("ENGINE %s not available", engine_name); DIE(DNSSEC_ERROR_NOENGINE); } while(token != NULL) { char *command_pointer; char *command = strtok_r(token, "=", &command_pointer); if(command == NULL) { log_err("bad command %s", command); DIE(DNSSEC_ERROR_INVALIDENGINE); } char *command_value = strtok_r(NULL, "=", &command_pointer); if(command_value == NULL) { log_err("bad command value %s", command_value); DIE(DNSSEC_ERROR_INVALIDENGINE); } // command_value is not NULL because DIE stops the program. ENGINE_ctrl_cmd((ENGINE*)engine, command, atoi(command_value), NULL, NULL, 0); token = strtok_r(NULL, ENGINE_COMMAND_DELIMITER, &token_pointer); } if(ENGINE_init((ENGINE*)engine) == 0) { log_err("ENGINE_init failed"); ENGINE_free((ENGINE*)engine); /* cfr: http://www.openssl.org/docs/crypto/engine.html */ DIE(DNSSEC_ERROR_INVALIDENGINE); } free(engine_name); return engine; } void dnssec_unloadengine(ENGINE *engine) { ENGINE_finish((ENGINE*)engine); ENGINE_free((ENGINE*)engine); } /* ------------------------------------------------------------ */ /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/dnssec-keystore.c0000644000000000000000000000013214505005531022252 xustar000000000000000030 mtime=1695812441.719971833 30 atime=1695812445.801030282 30 ctime=1695812495.172737384 yadifa-2.6.5-11201/lib/dnsdb/src/dnssec-keystore.c0000664000374500037450000017633114505005531022227 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup dnskey DNSSEC keys functions * @ingroup dnsdbdnssec * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dnsdb/zdb_error.h" #include "dnsdb/zdb_record.h" #include "dnsdb/dnssec.h" #include "dnsdb/dnssec_config.h" #include "dnsdb/dnssec-keystore.h" #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; #ifndef PATH_MAX #define PATH_MAX 4096 #endif #define ZDB_KEYSTORE_ORIGIN_TAG 0x4e494749524f534b #define DNSKEY_FILE_FORMAT "K%s+%03d+%05d" // if the key is irrelevant and yadifad is self-managing, then a deactivated key can be removed after this time elapsed #define AUTOMATIC_DEACTIVATED_DNSKEY_UNPUBLISH_DELAY 86400 static int dnssec_keystore_keys_node_compare(const void *, const void *); #define DNSSEC_KEYSTORE_EMPTY {PTR_SET_CUSTOM(ptr_set_nullable_asciizp_node_compare), PTR_SET_CUSTOM(dnssec_keystore_keys_node_compare), PTR_SET_CUSTOM(ptr_set_nullable_dnsname_node_compare)/*, NULL*/, MUTEX_INITIALIZER} //typedef btree dnssec_keystore; /** * After carefully weighting the advantages and disadvantages, * the maintenance of the keys will go through a new keystore * * The keystore will contain all the paths it is supposed to scan and how many times a path has been added * ie: once for the "global" setting, once for each zone it is specifically set on * These paths are mandatory to avoid doing a lot of IOs when a simple scan can answer all our questions * * The keystore will contain all the keys by their name alg and tag. * Probably something like tag + ( alg << 16 ), the idea being to use unassigned bits [9;14] of the flags * Actually the name + tag should be enough. * * The keystore will contain a list of the keys for each zone, by their name */ #define KSDOMAIN_TAG 0x4e49414d4f44534b struct dnssec_keystore_domain_s { u8* fqdn; // domain name u64 keys_scan_epoch; // last time the keys have been refreshed const char *keys_path; // path where to find the keys of the domain dnssec_key *key_chain; // list of keys for the domain }; typedef struct dnssec_keystore_domain_s dnssec_keystore_domain_s; struct dnssec_keystore { ptr_set paths; // path -> count : each path of the keystore and the number of domains using it ptr_set keys; // name+alg+tag -> key ptr_set domains; // name -> dnssec_keystore_domain_s //const char *default_path; mutex_t lock; // mutex }; typedef struct dnssec_keystore dnssec_keystore; static const char* g_keystore_path = DNSSEC_DEFAULT_KEYSTORE_PATH; static dnssec_keystore g_keystore = DNSSEC_KEYSTORE_EMPTY; #define KEY_HASH(key) ((((hashcode)key->tag)<<16)|key->flags|(key->algorithm<<1)) #define TAG_FLAGS_ALGORITHM_HASH(t_,f_,a_) ((((hashcode)t_)<<16)|(f_)|((a_)<<1)) static int dnssec_keystore_keys_node_compare(const void *node_a, const void *node_b) { dnssec_key *k_a = (dnssec_key*)node_a; dnssec_key *k_b = (dnssec_key*)node_b; ya_result ret; ret = dnskey_get_algorithm(k_a) - dnskey_get_algorithm(k_b); if(ret == 0) { ret = dnskey_get_tag(k_a) - dnskey_get_tag(k_b); if(ret == 0) { ret = dnsname_compare(dnskey_get_domain(k_a), dnskey_get_domain(k_b)); } } return ret; } /** * * Initialises the keystore * * @param ks */ void dnssec_keystore_init(/*dnssec_keystore *ks*/) { /* dnssec_keystore *ks = &g_keystore; ks->paths.root = NULL; ks->paths.compare = ptr_set_nullable_asciizp_node_compare; ks->keys.root = NULL; ks->keys.compare = dnssec_keystore_keys_node_compare; ks->domains.root = NULL; ks->domains.compare = ptr_set_nullable_dnsname_node_compare; mutex_init(&ks->lock); */ } static dnssec_keystore_domain_s* dnssec_keystore_get_domain_nolock(dnssec_keystore *ks, const u8 *domain) { ptr_node *d_node = ptr_set_find(&ks->domains, domain); return (dnssec_keystore_domain_s*)((d_node != NULL)?d_node->value:NULL); } static dnssec_keystore_domain_s* dnssec_keystore_get_domain(dnssec_keystore *ks, const u8 *domain) { mutex_lock(&ks->lock); dnssec_keystore_domain_s *ret = dnssec_keystore_get_domain_nolock(ks, domain); // locked mutex_unlock(&ks->lock); return ret; } static ya_result dnssec_keystore_get_key_path_with_parameters_and_domain(const char *fqdn, u8 algorithm, u16 tag, char *buffer, size_t buffer_size, dnssec_keystore_domain_s *domain, bool private) { ya_result ret; if((fqdn == NULL) || (buffer == NULL)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } if(buffer_size > PATH_MAX) { buffer_size = PATH_MAX; } const char *path = ((domain != NULL) && (domain->keys_path != NULL))?domain->keys_path:g_keystore_path; if(path != NULL) { if((ret = snprintf(buffer, buffer_size, "%s/" DNSKEY_FILE_FORMAT ".%s", path, fqdn, algorithm, tag, private?"private":"key")) >= (ya_result)buffer_size) { /* Path bigger than PATH_MAX */ return DNSSEC_ERROR_KEYSTOREPATHISTOOLONG; } } else { ret = INVALID_STATE_ERROR; // the keystore path or the domain paths are supposed to be set } return ret; } static ya_result dnssec_keystore_get_key_path_with_domain(dnssec_key* key, char *buffer, size_t buffer_size, dnssec_keystore_domain_s *domain, bool private) { ya_result ret; if(key == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } dnskey_get_tag(key); // updates the tag field if needed ret = dnssec_keystore_get_key_path_with_parameters_and_domain(key->origin, key->algorithm, key->tag, buffer, buffer_size, domain, private); return ret; } ya_result dnssec_keystore_get_key_path_with_parameters(const char *fqdn_text, u8 algorithm, u16 tag, char *buffer, size_t buffer_size, bool private) { ya_result ret; u8 fqdn[MAX_DOMAIN_LENGTH]; if(ISOK(ret = cstr_to_dnsname(fqdn, fqdn_text))) { dnssec_keystore_domain_s *domain = dnssec_keystore_get_domain(&g_keystore, fqdn); ret = dnssec_keystore_get_key_path_with_parameters_and_domain(fqdn_text, algorithm, tag, buffer, buffer_size, domain, private); } return ret; } ya_result dnssec_keystore_get_key_path(dnssec_key *key, char *buffer, size_t buffer_size, bool private) { dnssec_keystore_domain_s *domain = dnssec_keystore_get_domain(&g_keystore, key->owner_name); ya_result ret = dnssec_keystore_get_key_path_with_domain(key, buffer, buffer_size, domain, private); return ret; } ya_result dnssec_keystore_delete_key_files(dnssec_key *key) { ya_result ret0, ret1; char path[PATH_MAX]; if(ISOK(ret0 = dnssec_keystore_get_key_path(key, path, sizeof(path), TRUE))) { unlink(path); } if(ISOK(ret1 = dnssec_keystore_get_key_path(key, path, sizeof(path), TRUE))) { unlink(path); } if(FAIL(ret0)) { return ret0; } return ret1; } /** * Adds the knowledge of domain<->path * Set path to NULL to use the default value * * Can overwrite a previous value * * @param ks * @param domain * @param path */ static dnssec_keystore_domain_s* dnssec_keystore_add_domain_nolock(dnssec_keystore *ks, const u8 *domain, const char *path) { // insert or get the domain in the collection ptr_node *d_node = ptr_set_insert(&ks->domains, (u8*)domain); dnssec_keystore_domain_s *d; if(d_node->value == NULL) { // insert : setup ZALLOC_OBJECT_OR_DIE(d, dnssec_keystore_domain_s, KSDOMAIN_TAG); d->fqdn = dnsname_zdup(domain); d_node->key = d->fqdn; d->keys_scan_epoch = 0; d->keys_path = NULL; d->key_chain = NULL; d_node->value = d; } else { // get : has the keys path changed ? d = (dnssec_keystore_domain_s*)d_node->value; if(d->keys_path != NULL) { // tests for NULL or equality if((path == d->keys_path) || ((path != NULL) && (strcmp(path, d->keys_path) == 0))) { // it has not changed : nothing to do return d; } // it has changed : reduce previous count ptr_node *node = ptr_set_find(&ks->paths, (char*)d->keys_path); yassert(node != NULL); node->value = (void*)(((intptr)node->value) - 1); if(node->value == NULL) { char *key = (char*)node->key; ptr_set_delete(&ks->paths, path); free(key); } // the previous path is fully removed, the new value will be assigned, if needs to be, at the next step d->keys_path = NULL; d->keys_scan_epoch = 0; } } if(path != NULL) { ptr_node *p_node = ptr_set_insert(&ks->paths, (char*)path); if(p_node->value == NULL) { p_node->key = strdup(path); } p_node->value = (void*)(((intptr)p_node->value) + 1); d->keys_path = (const char*)p_node->key; d->keys_scan_epoch = 0; } return d; } void dnssec_keystore_add_domain(/*dnssec_keystore *ks, */const u8 *domain, const char *path) { dnssec_keystore *ks = &g_keystore; mutex_lock(&ks->lock); dnssec_keystore_add_domain_nolock(ks, domain, path); mutex_unlock(&ks->lock); } /** * Remove the knowledge of domain<->path * * @param ks * @param domain * @param path */ void dnssec_keystore_remove_domain_nolock(/*dnssec_keystore *ks, */const u8 *domain, const char *path) { (void)domain; dnssec_keystore *ks = &g_keystore; ptr_node *node = ptr_set_find(&ks->paths, path); if(node != NULL) { node->value = (void*)(((intptr)node->value) - 1); if(node->value == NULL) { char *key = (char*)node->key; ptr_set_delete(&ks->paths, path); free(key); } } } void dnssec_keystore_remove_domain(/*dnssec_keystore *ks, */const u8 *domain, const char *path) { (void)domain; dnssec_keystore *ks = &g_keystore; mutex_lock(&ks->lock); dnssec_keystore_remove_domain_nolock(domain, path); mutex_unlock(&ks->lock); } /** * * Add a key to the keystore, do nothing if the key is already known * * RC ok * * @param ks * @param key */ static bool dnssec_keystore_add_key_nolock(dnssec_keystore *ks, dnssec_key *key) { const u8 *domain = dnskey_get_domain(key); dnssec_keystore_domain_s *kd; kd = dnssec_keystore_get_domain_nolock(ks, domain); // caller nolock if(kd == NULL) { kd = dnssec_keystore_add_domain_nolock(ks, domain, NULL); yassert(kd != NULL); } // Add a reference in the keys collection ptr_node *key_node = ptr_set_insert(&ks->keys, key); if(key_node->value == NULL) { // new one key_node->value = key; dnskey_acquire(key); // RC // Add a reference in the domain keys collection // insert, sorted by tag value dnskey_add_to_chain(key, &kd->key_chain); // RC return TRUE; } // else already known return FALSE; } /** * * Replace a key from the keystore, release the replaced key * * RC ok * * @param ks * @param key */ static bool dnssec_keystore_replace_key_nolock(dnssec_keystore *ks, dnssec_key *key) { const u8 *domain = dnskey_get_domain(key); dnssec_keystore_domain_s *kd; kd = dnssec_keystore_get_domain_nolock(ks, domain); // caller nolock if(kd == NULL) { kd = dnssec_keystore_add_domain_nolock(ks, domain, NULL); yassert(kd != NULL); } // Add a reference in the keys collection ptr_node *key_node = ptr_set_insert(&ks->keys, key); dnssec_key *old_key = (dnssec_key*)key_node->value; if(old_key != key) { if(old_key != NULL) { dnskey_remove_from_chain(old_key, &kd->key_chain); dnskey_release(old_key); } dnskey_acquire(key); key_node->value = key; // Add a reference in the domain keys collection // insert, sorted by tag value dnskey_add_to_chain(key, &kd->key_chain); // RC return TRUE; } // else already known return FALSE; } /** * * Add a key to the keystore, do nothing if a key with the same tag and algorithm is * in the keystore for that domain already * * RC ok * * @param ks * @param key * * @return TRUE iff the key was added */ bool dnssec_keystore_add_key(dnssec_key *key) { dnssec_keystore *ks = &g_keystore; mutex_lock(&ks->lock); bool ret = dnssec_keystore_add_key_nolock(ks, key); // RC // locked mutex_unlock(&ks->lock); return ret; } /** * * Replace a key from the keystore, release the replaced key * * RC ok * * @param ks * @param key * * @return TRUE iff the key was added */ bool dnssec_keystore_replace_key(dnssec_key *key) { dnssec_keystore *ks = &g_keystore; mutex_lock(&ks->lock); bool ret = dnssec_keystore_replace_key_nolock(ks, key); // RC // locked mutex_unlock(&ks->lock); return ret; } /** * * Removes a key from the keystore * If the key is found, it is returned acquired (still has to be released) * * RC ok * * @param ks * @param key * @return the instance of the key from the keystore, or NULL if the key was not found */ static dnssec_key* dnssec_keystore_remove_key_nolock(dnssec_keystore *ks, dnssec_key *key) { dnssec_key *ret_key = NULL; ptr_node *key_node = ptr_set_find(&ks->keys, key); if(key_node != NULL) { ret_key = (dnssec_key*)key_node->value; ptr_set_delete(&ks->keys, key); // no not release as it will be returned const u8 *domain = dnskey_get_domain(key); dnssec_keystore_domain_s *kd = dnssec_keystore_get_domain_nolock(ks, domain); // caller nolock if(kd != NULL) { // remove, sorted by tag value dnskey_remove_from_chain(key, &kd->key_chain); // RC } } // else already known return ret_key; } /** * * Removes a key from the keystore * If the key is found, it is returned acquired (still requires release) * * RC ok * * @param ks * @param key * * @return the instance of the key from the keystore, or NULL if the key was not found */ dnssec_key* dnssec_keystore_remove_key(dnssec_key *key) { dnssec_keystore *ks = &g_keystore; mutex_lock(&ks->lock); dnssec_key *ret_key = dnssec_keystore_remove_key_nolock(ks, key); // RC // locked mutex_unlock(&ks->lock); return ret_key; } /** * Removes a key from the keystore, if possible. * Renames both key files adding suffix of the creation time plus bak * Does not return any error code as it's a best effort kind of thing. * * @param key */ void dnssec_keystore_delete_key(dnssec_key *key) { dnssec_keystore_domain_s *domain; char clean_origin[MAX_DOMAIN_LENGTH]; const u8 *fqdn = key->owner_name; const u8 algorithm = key->algorithm; const u16 tag = key->tag; /* Load from the disk, add to the keystore */ domain = dnssec_keystore_get_domain(&g_keystore, fqdn); dnsname_to_cstr(clean_origin, fqdn); format_writer epoch_writer = {packedepoch_format_handler_method, (void*)(intptr)key->epoch_created}; char path[PATH_MAX]; char path_new[PATH_MAX]; // PRIVATE ya_result ret; ret = dnssec_keystore_get_key_path_with_domain(key, path, sizeof(path), domain, TRUE); if(ISOK(ret) && (snformat(path_new, sizeof(path_new), "%s.%w.bak", path, &epoch_writer) < PATH_MAX)) { log_debug("dnskey-keystore: %{dnsname}: delete: private key file is '%s'", fqdn, path); if(file_exists(path)) { dnssec_key *key_from_file = NULL; ret = dnskey_new_private_key_from_file(path, &key_from_file); // RC if(ISOK(ret)) { if(dnskey_equals(key, key_from_file)) { log_info("dnskey-keystore: %{dnsname}: delete: private key file content matches key: renaming file '%s' to '%s'", fqdn, path, path_new); if(rename(path, path_new) < 0) { ret = ERRNO_ERROR; log_err("dnskey-keystore: %{dnsname}: delete: could not rename file '%s' to '%s': %r", fqdn, path, path_new, ret); } } else { log_info("dnskey-keystore: %{dnsname}: delete: private key file content does not matches key: renaming file '%s' to '%s'", fqdn, path, path_new); } dnskey_release(key_from_file); key_from_file = NULL; } else { log_err("dnskey-keystore: %{dnsname}: delete: could not read key from private key file '%s': %r", fqdn, path, ret); } } else { log_info("dnskey-keystore: %{dnsname}: delete: private key file '%s' does not exists", fqdn, path); } } else { log_err("dnskey-keystore: %{dnsname}: delete: K%s+%03d+%05d private key file path size would be too big", fqdn, clean_origin, algorithm, tag); } // PUBLIC ret = dnssec_keystore_get_key_path_with_domain(key, path, sizeof(path), domain, FALSE); if(ISOK(ret) && (snformat(path_new, sizeof(path_new), "%s.%w.bak", path, &epoch_writer) < PATH_MAX)) { log_debug("dnskey-keystore: %{dnsname}: delete: public key file is '%s'", fqdn, path); if(file_exists(path)) { dnssec_key *key_from_file = NULL; ret = dnskey_new_public_key_from_file(path, &key_from_file); // RC if(ISOK(ret)) { if(dnskey_public_equals(key, key_from_file)) { log_info("dnskey-keystore: %{dnsname}: delete: public key file content matches key: renaming file '%s' to '%s'", fqdn, path, path_new); if(rename(path, path_new) < 0) { ret = ERRNO_ERROR; log_err("dnskey-keystore: %{dnsname}: delete: could not rename file '%s' to '%s': %r", fqdn, path, path_new, ret); } } else { log_info("dnskey-keystore: %{dnsname}: delete: public key file content does not matches key: renaming file '%s' to '%s'", fqdn, path, path_new); } dnskey_release(key_from_file); key_from_file = NULL; } else { log_err("dnskey-keystore: %{dnsname}: delete: could not read key from public key file '%s': %r", fqdn, path, ret); } } else { log_info("dnskey-keystore: %{dnsname}: delete: public key file '%s' does not exists", fqdn, path); } } else { log_err("dnskey-keystore: %{dnsname}: delete: K%s+%03d+%05d public key file path size would be too big", fqdn, clean_origin, algorithm, tag); } dnssec_key *keystore_key = dnssec_keystore_remove_key(key); if(keystore_key != NULL) { dnskey_release(keystore_key); keystore_key = NULL; } } /** * * Retrieves a key from the keystore * * RC ok * * @param ks * @param domain * @param tag * @return */ static dnssec_key* dnssec_keystore_acquire_key_from_fqdn_nolock(dnssec_keystore *ks, const u8 *domain, u16 tag) { dnssec_key *key = NULL; dnssec_keystore_domain_s* kd = dnssec_keystore_get_domain_nolock(ks, domain); // caller nolock if(kd != NULL) { key = kd->key_chain; while(key != NULL) { u16 key_tag = dnskey_get_tag(key); if(key_tag == tag) { break; } key = key->next; } if(key != NULL) { dnskey_acquire(key); } } return key; } /** * * Retrieves a key from the keystore * * RC ok * * @param ks * @param domain * @param tag * @return */ dnssec_key* dnssec_keystore_acquire_key_from_fqdn_with_tag(const u8 *domain, u16 tag) { dnssec_keystore *ks = &g_keystore; mutex_lock(&ks->lock); dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_nolock(ks, domain, tag); // RC // locked mutex_unlock(&ks->lock); return key; } /** * * Retrieves a key from the keystore * * RC ok * * @param ks * @param domain * @param tag * @return */ dnssec_key* dnssec_keystore_acquire_key_from_rdata(const u8 *domain, const u8 *rdata, u16 rdata_size) { dnssec_keystore *ks = &g_keystore; u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size); mutex_lock(&ks->lock); dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_nolock(ks, domain, tag); // RC // locked mutex_unlock(&ks->lock); return key; } /** * Returns the nth key from the domain or NULL if no such key exist * * RC ok * * @return a dnskey */ dnssec_key* dnssec_keystore_acquire_key_from_fqdn_by_index(const u8 *domain, int idx) { dnssec_keystore *ks = &g_keystore; dnssec_key *key = NULL; mutex_lock(&ks->lock); dnssec_keystore_domain_s* kd = dnssec_keystore_get_domain_nolock(ks, domain); // locked if(kd != NULL) { key = kd->key_chain; while(idx > 0 && key != NULL) { --idx; key = key->next; } if(key != NULL) { dnskey_acquire(key); } } mutex_unlock(&ks->lock); return key; } dnssec_key * dnssec_keystore_acquire_key_from_fqdn_at_index(const u8 *domain, int index) { dnssec_key *key = NULL; dnssec_keystore *ks = &g_keystore; mutex_lock(&ks->lock); dnssec_keystore_domain_s *ks_domain = dnssec_keystore_get_domain_nolock(ks, domain); // locked if(ks_domain != NULL) { key = ks_domain->key_chain; while(index > 0 && key != NULL) { key = key->next; --index; } if(key != NULL) { dnskey_acquire(key); } } mutex_unlock(&ks->lock); return key; } bool dnssec_keystore_has_any_ksk(const u8 *domain) { dnssec_keystore *ks = &g_keystore; dnssec_key *key = NULL; bool ret = FALSE; mutex_lock(&ks->lock); dnssec_keystore_domain_s* kd = dnssec_keystore_get_domain_nolock(ks, domain); // locked if(kd != NULL) { key = kd->key_chain; while(key != NULL) { if(dnskey_get_flags(key) == (DNSKEY_FLAG_ZONEKEY | DNSKEY_FLAG_KEYSIGNINGKEY)) { ret = TRUE; } key = key->next; } } mutex_unlock(&ks->lock); return ret; } bool dnssec_keystore_has_activated_ksk(const u8 *domain, time_t attime) { dnssec_keystore *ks = &g_keystore; dnssec_key *key = NULL; bool ret = FALSE; mutex_lock(&ks->lock); dnssec_keystore_domain_s* kd = dnssec_keystore_get_domain_nolock(ks, domain); // locked if(kd != NULL) { key = kd->key_chain; while(key != NULL) { if(dnskey_get_flags(key) == (DNSKEY_FLAG_ZONEKEY | DNSKEY_FLAG_KEYSIGNINGKEY)) { if(dnskey_is_activated(key, attime)) { ret = TRUE; break; } } key = key->next; } } mutex_unlock(&ks->lock); return ret; } bool dnssec_keystore_has_activated_zsk(const u8 *domain, time_t attime) { dnssec_keystore *ks = &g_keystore; dnssec_key *key = NULL; bool ret = FALSE; mutex_lock(&ks->lock); dnssec_keystore_domain_s* kd = dnssec_keystore_get_domain_nolock(ks, domain); // locked if(kd != NULL) { key = kd->key_chain; while(key != NULL) { if(dnskey_get_flags(key) == DNSKEY_FLAG_ZONEKEY) { if(dnskey_is_activated(key, attime)) { ret = TRUE; break; } } key = key->next; } } mutex_unlock(&ks->lock); return ret; } bool dnssec_keystore_has_usable_ksk(const u8 *domain, time_t attime) { dnssec_keystore *ks = &g_keystore; dnssec_key *key = NULL; bool ret = FALSE; mutex_lock(&ks->lock); dnssec_keystore_domain_s* kd = dnssec_keystore_get_domain_nolock(ks, domain); // locked if(kd != NULL) { key = kd->key_chain; while(key != NULL) { if(dnskey_is_private(key) && (dnskey_get_flags(key) == (DNSKEY_FLAG_ZONEKEY | DNSKEY_FLAG_KEYSIGNINGKEY))) { if(dnskey_is_activated(key, attime)) { ret = TRUE; break; } } key = key->next; } } mutex_unlock(&ks->lock); return ret; } bool dnssec_keystore_has_usable_zsk(const u8 *domain, time_t attime) { dnssec_keystore *ks = &g_keystore; dnssec_key *key = NULL; bool ret = FALSE; mutex_lock(&ks->lock); dnssec_keystore_domain_s* kd = dnssec_keystore_get_domain_nolock(ks, domain); // locked if(kd != NULL) { key = kd->key_chain; while(key != NULL) { if(dnskey_is_private(key) && (dnskey_get_flags(key) == DNSKEY_FLAG_ZONEKEY)) { if(dnskey_is_activated(key, attime)) { ret = TRUE; break; } } key = key->next; } } mutex_unlock(&ks->lock); return ret; } int dnssec_keystore_acquire_publish_delete_keys_from_fqdn_to_vectors(const u8 *domain, ptr_vector *publish_keys, ptr_vector *delete_keys) { time_t now = time(NULL); for(int i = 0; ;++i) { dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_by_index(domain, i); if(key == NULL) { log_debug1("dnskey-keystore: acquiring activated key %{dnsname}: no other key available", domain); break; } if((key->status & DNSKEY_KEY_IS_IN_ZONE) == 0) { if(dnskey_has_explicit_publish_or_delete(key)) { if(dnskey_is_published(key, now)) { if((publish_keys != NULL) && (ptr_vector_search_ptr_index(publish_keys, key) < 0)) { ptr_vector_append(publish_keys, key); } else { dnskey_release(key); } continue; } if(dnskey_is_unpublished(key, now)) { if((delete_keys != NULL) && (ptr_vector_search_ptr_index(delete_keys, key) < 0)) { ptr_vector_append(delete_keys, key); } else { dnskey_release(key); } continue; } } else if(dnskey_has_activate_or_deactivate(key)) { if(dnskey_is_activated(key, now)) { if((publish_keys != NULL) && (ptr_vector_search_ptr_index(publish_keys, key) < 0)) { ptr_vector_append(publish_keys, key); } else { dnskey_release(key); } continue; } if(dnskey_is_deactivated(key, MAX((s64)now - AUTOMATIC_DEACTIVATED_DNSKEY_UNPUBLISH_DELAY, 0))) { if((delete_keys != NULL) && (ptr_vector_search_ptr_index(delete_keys, key) < 0)) { ptr_vector_append(delete_keys, key); } else { dnskey_release(key); } continue; } } } dnskey_release(key); } int ret = 0; if(publish_keys != NULL) { ret += ptr_vector_size(publish_keys); } if(delete_keys != NULL) { ret += ptr_vector_size(delete_keys); } return ret; } /** * Releases all the keys from a vector. * * @param keys */ void dnssec_keystore_release_keys_from_vector(ptr_vector *keys) { for(int i = 0; i <= ptr_vector_last_index(keys); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(keys, i); log_debug("dnskey-keystore: releasing key %{dnsname}", dnskey_get_domain(key)); dnskey_release(key); } } /** * * Retrieves a key from the keystore * * RC ok * * @param ks * @param domain * @param tag * @return */ static dnssec_key* dnssec_keystore_acquire_key_from_name_nolock(dnssec_keystore *ks, const char *domain, u16 tag) { dnssec_key *key = NULL; u8 fqdn[MAX_DOMAIN_LENGTH]; if(ISOK(cstr_to_dnsname(fqdn, domain))) { key = dnssec_keystore_acquire_key_from_fqdn_nolock(ks, fqdn, tag); // RC // caller nolock } return key; } /** * * Retrieves a key from the keystore * * RC ok * * @param ks * @param domain * @param tag * @return */ dnssec_key* dnssec_keystore_acquire_key_from_name(const char *domain, u16 tag) { dnssec_key *key = NULL; u8 fqdn[MAX_DOMAIN_LENGTH]; if(ISOK(cstr_to_dnsname(fqdn, domain))) { key = dnssec_keystore_acquire_key_from_fqdn_with_tag(fqdn, tag); // RC } return key; } /** * Returns the nth key from the domain or NULL if no such key exist * * RC ok * * @return a dnskey */ dnssec_key * dnssec_keystore_acquire_key_from_name_by_index(const char *domain, int idx) { dnssec_key *key = NULL; u8 fqdn[MAX_DOMAIN_LENGTH]; if(ISOK(cstr_to_dnsname(fqdn, domain))) { key = dnssec_keystore_acquire_key_from_fqdn_by_index(fqdn, idx); // RC } return key; } struct dnssec_keystore_reload_readdir_callback_s { dnssec_keystore *ks; const char *domain; int private_update; }; typedef struct dnssec_keystore_reload_readdir_callback_s dnssec_keystore_reload_readdir_callback_s; static ya_result dnssec_keystore_reload_readdir_callback_nolock(const char *basedir, const char *filename, u8 filetype, void *args_) { if((filetype == DT_REG) && (filename[0] != 'K')) { return SUCCESS; } dnssec_keystore_reload_readdir_callback_s *args = (dnssec_keystore_reload_readdir_callback_s*)args_; dnssec_keystore *ks = args->ks; int algorithm; int tag; char extension[16]; char domain[256]; char file[PATH_MAX + 1]; size_t dlen = strlen(basedir); size_t flen = strlen(filename); if(dlen + flen >= sizeof(file)) { log_err("path too long for '%s'/'%s'", basedir, filename); return INVALID_PATH; } memset(extension, 0, sizeof(extension)); // to shut-up valgrind memcpy(file, basedir, dlen); if(file[dlen - 1] != '/') { file[dlen++] = '/'; } memcpy(&file[dlen], filename, flen + 1); if(sscanf(filename, "K%255[^+]+%03d+%05d.%15s", domain, &algorithm, &tag, extension) == 4) { domain[255] = '\0'; // ensure the 256th char is '\0' if((args->domain == NULL) || (strcmp(domain, args->domain) == 0)) { if(memcmp(extension, "private", 8) == 0) { log_debug("found private key file for domain '%s' with tag %i and algorithm %i", domain, tag, algorithm); s64 ts; if(ISOK(file_mtime(file, &ts))) { // get the key with that domain/tag // @note 20150907 edf -- work in progress dnssec_key *current_key = dnssec_keystore_acquire_key_from_name_nolock(ks, domain, tag); // RC // caller nolock if(current_key != NULL) { // check if it has to be reloaded if(current_key->timestamp >= ts) { // ignore this file (already got it) dnskey_release(current_key); return SUCCESS; } log_info("DNSKEY from file '%s' was modified (expected %lT, got %lT)", filename, current_key->timestamp, ts); } dnssec_key *key; // remove the key from the keystore, load the key from disk log_debug("dnssec_keystore_reload_readdir_callback: opening file '%s'", file); ya_result ret; if(ISOK(ret = dnskey_new_private_key_from_file(file, &key))) { bool is_missing_any_smart_field = !dnskey_has_explicit_publish_and_delete(key) || !dnskey_has_explicit_activate(key) || !dnskey_has_explicit_deactivate(key); bool has_no_smart_field = dnskey_has_explicit_publish_or_delete(key) && dnskey_has_explicit_activate(key) && dnskey_has_explicit_deactivate(key); if(has_no_smart_field) { log_info("key from '%s' has no smart fields", file); } else if(is_missing_any_smart_field) { log_info("key from '%s' is missing some smart fields", file); } #if DEBUG log_debug1("dnssec_keystore_reload_readdir_callback: private key generated from file '%s'", file); #endif // compare the cryptographic parts of the key (the public key is enough) and // overwrite the timestamps iff they are the same, else ... refuse to break security if(current_key != NULL) { if(dnskey_equals(current_key, key)) { #if DEBUG log_debug1("dnssec_keystore_reload_readdir_callback: file '%s' has already been loaded", file); #endif current_key->epoch_created = key->epoch_created; current_key->epoch_publish = key->epoch_publish; current_key->epoch_activate = key->epoch_activate; current_key->epoch_inactive = key->epoch_inactive; current_key->epoch_delete = key->epoch_delete; current_key->timestamp = key->timestamp; current_key->status &= ~(DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE); current_key->status |= key->status & (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE); } else { // update #if DEBUG log_debug1("dnssec_keystore_reload_readdir_callback: file '%s' updated a key", file); #endif current_key->epoch_created = key->epoch_created; current_key->epoch_publish = key->epoch_publish; current_key->epoch_activate = key->epoch_activate; current_key->epoch_inactive = key->epoch_inactive; current_key->epoch_delete = key->epoch_delete; current_key->timestamp = key->timestamp; current_key->status &= ~(DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE); current_key->status |= key->status & (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE); // update key re-signature scheduling } dnskey_release(current_key); } else { // add the new key #if DEBUG log_debug1("dnssec_keystore_reload_readdir_callback: file '%s' generated a new key", file); #endif dnssec_keystore_add_key_nolock(ks, key); // RC // caller nolock // also : the key should be put in the zone and signature should be scheduled } dnskey_release(key); ++args->private_update; // one key was modified (it's timings at the very least) #if DEBUG log_debug1("dnssec_keystore_reload_readdir_callback: file '%s' successfully read", file); #endif } else { log_debug("could not read '%s': %r (missing public .key file ?)", file, ret); } } else { log_err("could not access '%s': %r", file, ERRNO_ERROR); } } // else this is not a private key file } else { log_debug("ignoring key file %s (%s != %s)", filename, domain, args->domain); } } else { log_debug("ignoring file %s", filename); } return SUCCESS; // invalid file name, but it's irrelevant for this } /** * * (Re)loads keys found in the paths of the keystore * * @return */ ya_result dnssec_keystore_reload() { // scan all directories // for each key found, load and propose it to the domain // if the key has changed ... // timings: remove the previous alarms (?) // removed: ? // added: update alarms (?) dnssec_keystore *ks = &g_keystore; ya_result ret; dnssec_keystore_reload_readdir_callback_s args = {ks, NULL, 0}; mutex_lock(&ks->lock); ptr_set_iterator iter; ptr_set_iterator_init(&ks->paths, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *path_node = ptr_set_iterator_next_node(&iter); const char *path = (const char*)path_node->key; if(FAIL(ret = readdir_forall(path, dnssec_keystore_reload_readdir_callback_nolock, &args))) { log_err("dnssec keystore reload: an error occurred reading key directory '%s': %r", path, ret); } } if(FAIL(ret = readdir_forall(g_keystore_path, dnssec_keystore_reload_readdir_callback_nolock, &args))) { log_err("dnssec keystore reload: an error occurred reading key directory '%s': %r", g_keystore_path, ret); } mutex_unlock(&ks->lock); if(ISOK(ret)) { ret = args.private_update; } return ret; } /** * * (Re)loads keys found in the path of the keystore for the specified domain * * @param fqdn * @return */ ya_result dnssec_keystore_reload_domain(const u8 *fqdn) { // scan all directories // for each key found, load and propose it to the domain // if the key has changed ... // timings: remove the previous alarms (?) // removed: ? // added: update alarms (?) log_debug("dnskey-keystore: %{dnsname}: reload domain: scanning for keys", fqdn); dnssec_keystore *ks = &g_keystore; ya_result ret = SUCCESS; mutex_lock(&ks->lock); dnssec_keystore_domain_s *keystore_domain = dnssec_keystore_get_domain_nolock(ks, fqdn); // locked ret = DNSSEC_ERROR_NO_KEY_FOR_DOMAIN; // no key for domain if(keystore_domain != NULL) { char domain[MAX_DOMAIN_LENGTH]; dnsname_to_cstr(domain, fqdn); dnssec_keystore_reload_readdir_callback_s args = {ks, domain, 0}; const char *path = keystore_domain->keys_path; if(path == NULL) { path = g_keystore_path; } struct stat st; stat(path, &st); #if defined WIN32 s64 mod_time = st.st_mtime; #elif IS_DARWIN_OS s64 mod_time = st.st_mtimespec.tv_sec; mod_time *= 1000000000LL; mod_time += st.st_mtimespec.tv_nsec; #else s64 mod_time = st.st_mtim.tv_sec; mod_time *= 1000000000LL; mod_time += st.st_mtim.tv_nsec; #endif if((u64)mod_time > keystore_domain->keys_scan_epoch) { if(ISOK(ret = readdir_forall(path, dnssec_keystore_reload_readdir_callback_nolock, &args))) { ret = args.private_update; keystore_domain->keys_scan_epoch = mod_time; } else { log_err("dnssec keystore: %{dnsname} reload domain: an error occurred reading key directory '%s': %r", fqdn, path, ret); if(keystore_domain->key_chain != NULL) { ret = 0; } } } else { log_debug("dnssec keystore: %{dnsname} reload domain: no need to scan key directory '%s' again", fqdn, path); ret = 0; } } mutex_unlock(&ks->lock); return ret; } // sanitises an origin static void dnssec_keystore_origin_copy_sanitize(char* target, const char* origin) { if(origin == NULL) { target[0] = '.'; target[1] = '\0'; return; } int origin_len = strlen(origin); if(origin_len == 0) { target[0] = '.'; target[1] = '\0'; return; } if(origin[origin_len - 1] == '.') { origin_len++; MEMCOPY(target, origin, origin_len); } else { MEMCOPY(target, origin, origin_len); target[origin_len++] = '.'; target[origin_len] = '\0'; } } const char* dnssec_keystore_getpath() { return g_keystore_path; } static const char* dnssec_default_keystore_path = DNSSEC_DEFAULT_KEYSTORE_PATH; void dnssec_keystore_resetpath() { /* * cast to void to avoid the -Wstring-compare warning */ if(((void*)g_keystore_path) != ((void*)dnssec_default_keystore_path)) { free((void*)g_keystore_path); g_keystore_path = dnssec_default_keystore_path; } } void dnssec_keystore_setpath(const char* path) { dnssec_keystore_resetpath(); if(path != NULL) { g_keystore_path = strdup(path); } } /* void dnssec_keystore_destroy_paths_cb(ptr_node *node) { free(node->key); } */ static void dnssec_keystore_destroy_domains_cb(ptr_node *node) { dnssec_keystore_domain_s *d = (dnssec_keystore_domain_s*)node->value; dnsname_zfree(d->fqdn); d->fqdn = NULL; ZFREE_OBJECT(d); //d->keys_path is a pointer to a key in g_keystore.paths //d->key_chain should have been emptied by now } void dnssec_keystore_destroy() { log_debug("dnskey-keystore: clearing-up"); mutex_lock(&g_keystore.lock); while(!ptr_set_isempty(&g_keystore.keys)) { ptr_node *key_node = g_keystore.keys.root; dnssec_key *key = (dnssec_key *)key_node->key; if(key != NULL) { log_debug("dnskey-keystore: %{dnsname} +%03d+%05d/%d status=%x rc=%i (%p)", dnskey_get_domain(key), key->algorithm, key->tag, ntohs(key->flags), key->status, key->rc, key); dnssec_key *ret_key = dnssec_keystore_remove_key_nolock(&g_keystore, key); // locked dnskey_release(ret_key); } else { break; } } ptr_set_callback_and_destroy(&g_keystore.domains, dnssec_keystore_destroy_domains_cb); mutex_unlock(&g_keystore.lock); } /** * Generates a private key, store in the keystore * The caller is expected to create a resource record with this key and add * it to the owner. * * @param algorithm the DNSKEY algorithm * @param size the size of the key. Not all algoritms are taking it into account. * @param flags the DNSKEY flags * @param origin the domain of the key * @param smart_fields all the smart fields to set, don't forget to set the "fields" field to tell which fields are valid * @param out_key the generated key * @returns an error code * */ ya_result dnssec_keystore_new_key(u8 algorithm, u32 size, u16 flags, const char *origin, dnskey_smart_fields_t *smart_fields, dnssec_key **out_key) { ya_result ret; dnssec_key* key = NULL; char clean_origin[MAX_DOMAIN_LENGTH]; u8 fqdn[MAX_DOMAIN_LENGTH]; /* sanitise the origin name */ dnssec_keystore_origin_copy_sanitize(clean_origin, origin); cstr_to_dnsname(fqdn, clean_origin); /** * @note if 65536 keys exist then this function will loop forever */ for(;;) { switch(algorithm) { case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: { if(FAIL(ret = dnskey_rsa_newinstance(size, algorithm, flags, clean_origin, &key))) { return ret; } break; } case DNSKEY_ALGORITHM_DSASHA1: case DNSKEY_ALGORITHM_DSASHA1_NSEC3: { if(FAIL(ret = dnskey_dsa_newinstance(size, algorithm, flags, clean_origin, &key))) { return ret; } break; } #if DNSCORE_HAS_ECDSA_SUPPORT case DNSKEY_ALGORITHM_ECDSAP256SHA256: case DNSKEY_ALGORITHM_ECDSAP384SHA384: { if(FAIL(ret = dnskey_ecdsa_newinstance(size, algorithm, flags, clean_origin, &key))) { return ret; } break; } #endif #if DNSCORE_HAS_EDDSA_SUPPORT case DNSKEY_ALGORITHM_ED25519: case DNSKEY_ALGORITHM_ED448: { if(FAIL(ret = dnskey_eddsa_newinstance(size, algorithm, flags, clean_origin, &key))) { return ret; } break; } #endif #ifdef DNSKEY_ALGORITHM_DUMMY case DNSKEY_ALGORITHM_DUMMY: { if(FAIL(return_value = dnskey_dummy_newinstance(size, algorithm, flags, clean_origin, &key))) { return return_value; } } #endif default: { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } } if(smart_fields != NULL) { if(smart_fields->fields & DNSKEY_KEY_HAS_SMART_FIELD_CREATED) { dnskey_set_created_epoch(key, smart_fields->created_epoch); } if(smart_fields->fields & DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH) { dnskey_set_publish_epoch(key, smart_fields->publish_epoch); } if(smart_fields->fields & DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE) { dnskey_set_activate_epoch(key, smart_fields->activate_epoch); } if(smart_fields->fields & DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE) { dnskey_set_inactive_epoch(key, smart_fields->deactivate_epoch); } if(smart_fields->fields & DNSKEY_KEY_HAS_SMART_FIELD_DELETE) { dnskey_set_delete_epoch(key, smart_fields->unpublish_epoch); } } dnssec_key *same_tag_key = NULL; dnskey_get_tag(key); // updates the tag field if needed if(ISOK(ret = dnssec_keystore_load_private_key_from_parameters(algorithm, key->tag, flags, fqdn, &same_tag_key))) // key properly released { dnskey_release(same_tag_key); // the key already exists in the keystore : tag collision if(dnscore_shuttingdown()) // else it may loop forever { return STOPPED_BY_APPLICATION_SHUTDOWN; } } else { // the key already exists in the keystore if(ISOK(ret = dnssec_keystore_store_private_key(key))) { if(ISOK(ret = dnssec_keystore_store_public_key(key))) { dnssec_keystore_add_key(key); } else { dnssec_keystore_delete_key_files(key); } } if(FAIL(ret)) { dnssec_keystore_remove_key(key); dnskey_release(key); key = NULL; } break; } dnskey_release(key); } *out_key = key; return ret; } /** * Loads a public key from the rdata, store in the keystore, then sets out_key to point to it * * RC ok * * @param rdata * @param rdata_size * @param origin * @param out_key * @return */ ya_result dnssec_keystore_load_public_key_from_rdata(const u8 *rdata, u16 rdata_size, const u8 *fqdn, dnssec_key **out_key) { //u16 flags = DNSKEY_FLAGS_FROM_RDATA(rdata); //u8 algorithm = rdata[3]; u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size); ya_result ret = SUCCESS; dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_with_tag(fqdn, tag); if(key == NULL) { if(ISOK(ret = dnskey_new_from_rdata(rdata, rdata_size, fqdn, &key))) // RC { if(!dnssec_keystore_add_key(key)) // RC { dnskey_release(key); key = dnssec_keystore_acquire_key_from_fqdn_with_tag(fqdn, tag); if(key == NULL) // should not happen { ret = ERROR; } } } } *out_key = key; // already RCed at instantiation return ret; } /** * Loads a private key from the disk or the keystore, then returns it. * NOTE: If the key already existed as a public-only key, the public version is released. * * RC ok * * @param algorithm * @param tag * @param flags * @param origin * @param out_key * @return the number of keys loaded by the call (1 or 0) or an error code */ ya_result dnssec_keystore_load_private_key_from_rdata(const u8 *rdata, u16 rdata_size, const u8 *fqdn, dnssec_key **out_key) { if(rdata_size < 4) { return INVALID_ARGUMENT_ERROR; } u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size); u16 flags = GET_U16_AT_P(rdata); u8 algorithm = rdata[3]; ya_result ret = dnssec_keystore_load_private_key_from_parameters(algorithm, tag, flags, fqdn, out_key); return ret; } /** * Loads a private key from the disk or the keystore, then returns it. * NOTE: If the key already existed as a public-only key, the public version is released. * * RC ok * * @param algorithm * @param tag * @param flags * @param origin * @param out_key * @return SUCCESS if a key is loaded, 1 if the key was already loaded, or an error code */ ya_result dnssec_keystore_load_private_key_from_parameters(u8 algorithm, u16 tag, u16 flags, const u8* fqdn, dnssec_key **out_key) { dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_with_tag(fqdn, tag); ya_result ret; bool has_public_key = FALSE; *out_key = NULL; if(key != NULL && !dnskey_is_private(key)) { log_debug("dnssec_key_load_private: %{dnsname} +%03d+%05d/%d is not private", fqdn, algorithm, tag, ntohs(flags)); has_public_key = TRUE; dnskey_release(key); key = NULL; } if(key == NULL) { // the key is not loaded already /* Load from the disk, add to the keystore */ char fqdn_text[MAX_DOMAIN_TEXT_LENGTH]; dnsname_to_cstr(fqdn_text, fqdn); char path[PATH_MAX]; path[0] = '\0'; if(FAIL(ret = dnssec_keystore_get_key_path_with_parameters(fqdn_text, algorithm, tag, path, sizeof(path), TRUE))) { /* Path bigger than PATH_MAX */ return ret; } log_debug("dnssec_key_load_private: %{dnsname} +%03d+%05d/%d: opening file '%s'", fqdn, algorithm, tag, ntohs(flags), path); ret = dnskey_new_private_key_from_file(path, &key); // RC if(ISOK(ret)) { if(has_public_key) { /* * remove the old (public) version */ log_debug("dnssec_key_load_private: %{dnsname} +%03d+%05hd/%hd: replacing previous version with loaded key", fqdn, algorithm, tag, ntohs(flags)); dnssec_keystore_replace_key(key); // RC } else { log_debug("dnssec_key_load_private: %{dnsname} +%03d+%05hd/%hd: adding loaded key", fqdn, algorithm, tag, ntohs(flags)); dnssec_keystore_add_key(key); // RC } log_info("dnssec: loaded private key: %{dnsname} +%03d+%05hd/%hd from '%s'", fqdn, algorithm, tag, ntohs(flags), path); *out_key = key; ret = 1; // newly loaded } else { log_debug("dnssec_key_load_private: %{dnsname} +%03d+%05hd/%hd: could not load the key: %r", fqdn, algorithm, tag, ntohs(flags), ret); } } else { *out_key = key; ret = 0; // already loaded } return ret; } ya_result dnssec_keystore_store_private_key(dnssec_key* key) { ya_result ret; char path[PATH_MAX]; if(key == NULL || key->key.any == NULL || key->origin == NULL || !dnskey_is_private(key)) { return DNSSEC_ERROR_INCOMPLETEKEY; } if(FAIL(ret = dnssec_keystore_get_key_path(key, path, sizeof(path), TRUE))) { return ret; } switch(key->algorithm) { case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: case DNSKEY_ALGORITHM_DSASHA1: case DNSKEY_ALGORITHM_DSASHA1_NSEC3: case DNSKEY_ALGORITHM_ECDSAP256SHA256: case DNSKEY_ALGORITHM_ECDSAP384SHA384: case DNSKEY_ALGORITHM_ED25519: case DNSKEY_ALGORITHM_ED448: #ifdef DNSKEY_ALGORITHM_DUMMY case DNSKEY_ALGORITHM_DUMMY: #endif { break; } default: { return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } } ret = dnskey_store_private_key_to_file(key, path); return ret; } ya_result dnssec_keystore_store_public_key(dnssec_key* key) { ya_result ret; char path[PATH_MAX]; dnskey_get_tag(key); // updates the tag field if needed if(FAIL(ret = dnssec_keystore_get_key_path(key, path, sizeof(path), FALSE))) { /* Path bigger than PATH_MAX */ return ret; } FILE* f; if((f = fopen(path, "w+b")) == NULL) { return DNSSEC_ERROR_UNABLETOCREATEKEYFILES; } u32 lc = 1; const char* p = key->origin; char c; while((c = *p) != '\0') { if(c == '.') { lc++; } p++; } fprintf(f, "%s IN DNSKEY %u %u %u ", key->origin, ntohs(key->flags), lc, key->algorithm); u8* rdata; u32 rdata_size = key->vtbl->dnssec_key_rdatasize(key); MALLOC_OR_DIE(u8*, rdata, rdata_size, DNSKEY_RDATA_TAG); /* store the RDATA */ key->vtbl->dnssec_key_writerdata(key, rdata, rdata_size); char b64[BASE64_ENCODED_SIZE(4096)]; u8* ptr = rdata + 4; rdata_size -= 4; u32 n = base64_encode(ptr, rdata_size, b64); if(fwrite(b64, n, 1, f) == 1) { ret = SUCCESS; } else { ret = DNSSEC_ERROR_KEYWRITEERROR; } fprintf(f, "\n"); free(rdata); fclose(f); if(FAIL(ret)) { unlink(path); } return ret; } /** * Adds all the valid keys of the domain in the keyring * * @param fqdn the domain name * @param at_time the epoch at which the test is done ie: time(NULL) * @param kr the target keyring */ u32 dnssec_keystore_add_valid_keys_from_fqdn(const u8 *fqdn, time_t at_time, struct dnskey_keyring *kr) { dnssec_keystore *ks = &g_keystore; u32 count = 0; mutex_lock(&ks->lock); dnssec_keystore_domain_s *ks_domain = dnssec_keystore_get_domain_nolock(ks, fqdn); // locked if(ks_domain != NULL) { dnssec_key *key = ks_domain->key_chain; while(key != NULL) { time_t from = (key->epoch_activate == 0)?1:key->epoch_activate; time_t to = (key->epoch_inactive == 0)?MAX_S32:key->epoch_inactive; if(from <= at_time && to >= at_time) { if(ISOK(dnskey_keyring_add(kr, key))) { ++count; } } key = key->next; } } mutex_unlock(&ks->lock); return count; } /** * Returns all the active keys, chained in a single linked list whose nodes need to be freed, * * @param zone * @param out_keys * @param out_ksk_count * @param out_zsk_count * @return */ ya_result zdb_zone_get_active_keys(zdb_zone *zone, dnssec_key_sll **out_keys, int *out_ksk_count, int *out_zsk_count) { ya_result ret = SUCCESS; int ksk_count = 0; int zsk_count = 0; zdb_packed_ttlrdata* dnskey_rrset = zdb_record_find(&zone->apex->resource_record_set, TYPE_DNSKEY); // zone is locked if(dnskey_rrset == NULL) { if(out_ksk_count != NULL) { *out_ksk_count = 0; } if(out_zsk_count != NULL) { *out_zsk_count = 0; } if(out_keys != NULL) { *out_keys = NULL; } return DNSSEC_ERROR_RRSIG_NOZONEKEYS; } dnssec_key_sll *keys = NULL; for(zdb_packed_ttlrdata* key = dnskey_rrset ;key != NULL ;key = key->next) { u8 algorithm = DNSKEY_ALGORITHM(*key); u16 tag = DNSKEY_TAG(*key); u16 flags = DNSKEY_FLAGS(*key); if((flags != DNSKEY_FLAGS_KSK) && (flags != DNSKEY_FLAGS_ZSK)) { // ignore the key log_debug("rrsig: %{dnsname}: key with private key algorithm=%d tag=%05d flags=%3d is ignored (flags)", zone->origin, algorithm, tag, ntohs(flags)); continue; } dnssec_key* priv_key; // from disk or from global keyring ret = dnssec_keystore_load_private_key_from_parameters(algorithm, tag, flags, zone->origin, &priv_key); // converted, key put in a collection or released if(ISOK(ret)) { yassert(priv_key != NULL); if(dnskey_is_activated(priv_key, time(NULL))) { log_debug("rrsig: %{dnsname}: private key algorithm=%d tag=%05d flags=%3d is active", zone->origin, algorithm, tag, ntohs(flags)); /* * We can sign with this key : chain it */ if(flags == DNSKEY_FLAGS_KSK) { ++ksk_count; } else if(flags == DNSKEY_FLAGS_ZSK) { ++zsk_count; } else { // not a KSK nor a ZSK } if(out_keys != NULL) { dnssec_key_sll *key_node; ZALLOC_OBJECT_OR_DIE(key_node, dnssec_key_sll, DNSSEC_KEY_SLL_TAG); key_node->next = keys; key_node->key = priv_key; keys = key_node; } else { dnskey_release(priv_key); } } else { log_debug("rrsig: %{dnsname}: private key algorithm=%d tag=%05d flags=%3d is not active", zone->origin, algorithm, tag, ntohs(flags)); dnskey_release(priv_key); } } else { yassert(priv_key == NULL); } } if(out_ksk_count != NULL) { *out_ksk_count = ksk_count; } if(out_zsk_count != NULL) { *out_zsk_count = zsk_count; } if(out_keys != NULL) { *out_keys = keys; } ret = ksk_count + zsk_count; return ret; } /** * * @param keys */ void zdb_zone_release_active_keys(dnssec_key_sll *keys) { while(keys != NULL) { dnskey_release(keys->key); dnssec_key_sll *tmp = keys; keys = keys->next; ZFREE_OBJECT(tmp); } } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec_common.c0000644000000000000000000000013214505005531021430 xustar000000000000000030 mtime=1695812441.725971919 30 atime=1695812445.801030282 30 ctime=1695812495.174737413 yadifa-2.6.5-11201/lib/dnsdb/src/nsec_common.c0000664000374500037450000001321214505005531021371 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec NSEC functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include "dnsdb/btree.h" #include "dnsdb/zdb_record.h" #include "dnsdb/nsec_common.h" #if ZDB_HAS_NSEC3_SUPPORT #include "dnsdb/nsec3.h" #endif /* * Force RRSIG: because the signatures could not be available yet. * Force NSEC: because the NSEC record is not available at first init. * */ u32 nsec_type_bit_maps_initialise_from_label(type_bit_maps_context *context, zdb_rr_label *label, bool force_nsec, bool force_rrsig) { u8 *type_bitmap_field = context->type_bitmap_field; u8 *window_size = context->window_size; ZEROMEMORY(window_size, sizeof(context->window_size)); context->last_type_window = -1; bool has_records = !zdb_record_isempty(&label->resource_record_set); /* If there are no records, nor forced ones ... */ if(!(force_nsec||force_rrsig||has_records)) { return 0; } ZEROMEMORY(type_bitmap_field, sizeof(context->type_bitmap_field)); btree_iterator types_iter; btree_iterator_init(label->resource_record_set, &types_iter); while(btree_iterator_hasnext(&types_iter)) { btree_node *node = btree_iterator_next_node(&types_iter); u16 type = node->hash; /** @note : NATIVETYPE */ #if ZDB_HAS_NSEC3_SUPPORT && defined(TYPE_NSEC3PARAMADD) if(type == TYPE_NSEC3PARAMADD) type = TYPE_NSEC3PARAM; // we are generating an NSEC3 chain : let's get the real types right #endif /** * domain.tld. NS domain.tld. * A domain.tld. * NSEC further.tld. NS RRSIG NSEC * RRSIG ... * * Because this is possible, I have to filter out (I should maybe filter in instead) */ if(zdb_rr_label_flag_isset(label, (ZDB_RR_LABEL_DELEGATION|ZDB_RR_LABEL_UNDERDELEGATION))) { if(type == TYPE_A || type == TYPE_AAAA) { continue; } } type = (u16)ntohs(type); /* Network bit order */ type_bitmap_field[type >> 3] |= 1 << (7 - (type & 7)); window_size[type >> 8] = ((type & 0xf8) >> 3) + 1; context->last_type_window = MAX(type >> 8, context->last_type_window); } /* * Add the forced types : NSEC, RRSIG * They all are on window 0 */ /* * HHHHHHHH LLLLLlll * * TBF[ HHHHHHHH LLLLL ] |= 1 << 7 - (lll) * * => * * * LLLLLlll HHHHHHHH * * TBF[ HHHHHHHH LLLLL ] |= 1 << ((0x700 - (lll00000000)) >> 8) * * * Given that I can't get rid of the >> 8 in the above statement, a swap will work better * */ if(force_rrsig) { type_bitmap_field[(NU16(TYPE_RRSIG) >> 3)] |= 1 << (7 - (NU16(TYPE_RRSIG) & 7)); /** @note : NATIVETYPE */ window_size[0] = MAX(((NU16(TYPE_RRSIG) & 0xf8) >> 3) + 1, window_size[0]); /** @note : NATIVETYPE */ context->last_type_window = MAX(0, context->last_type_window); } if(force_nsec) { type_bitmap_field[(NU16(TYPE_NSEC) >> 3)] |= 1 << (7 - (NU16(TYPE_NSEC) & 7)); /** @note : NATIVETYPE */ window_size[0] = MAX(((NU16(TYPE_NSEC) & 0xf8) >> 3) + 1, window_size[0]); /** @note : NATIVETYPE */ context->last_type_window = MAX(0, context->last_type_window); } u32 type_bit_maps_size = 0; for(s32 i = 0; i <= context->last_type_window; i++) { u8 ws = window_size[i]; if(ws > 0) { type_bit_maps_size += 1 + 1 + ws; } } context->type_bit_maps_size = type_bit_maps_size; return type_bit_maps_size; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/rrsig.c0000644000000000000000000000013214505005531020256 xustar000000000000000030 mtime=1695812441.738972105 30 atime=1695812445.802030296 30 ctime=1695812495.176737441 yadifa-2.6.5-11201/lib/dnsdb/src/rrsig.c0000664000374500037450000003234714505005531020231 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup rrsig RRSIG functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include #include #include #include #include "dnsdb/dnsrdata.h" #include "dnsdb/dnssec.h" #include "dnsdb/rrsig.h" #include "dnsdb/zdb_record.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb-zone-dnssec.h" #include "dnsdb/zdb-packed-ttlrdata.h" #include "dnsdb/nsec.h" #define MODULE_MSG_HANDLE g_dnssec_logger /* * 0 : no dump * 1 : dump * 2 : more dump ... */ #define RRSIG_DUMP 0 // 5 #define RRSIG_AUTOMATIC_ALARM_REFRESH 0 #define DEBUG_SIGNATURE_REMOVAL_TEST 0 /** * * Returns the first RRSIG record that applies to the give type. * * @param label the label where to do the search * @param covered_type the type covered by the RRSIG * * @return the first RRSIG covering the type or NULL */ zdb_packed_ttlrdata* rrsig_find_first(const zdb_rr_label* label, u16 type) { zdb_packed_ttlrdata* rrsig = zdb_record_find(&label->resource_record_set, TYPE_RRSIG); while(rrsig != NULL) { if(RRSIG_TYPE_COVERED(rrsig) == type) { return rrsig; } rrsig = rrsig->next; } return NULL; } /** * * Returns the next RRSIG record that applies to the give type. * * @param rrsig the previous RRSIG covering the type * @param covered_type the type covered by the RRSIG * * @return covered_type the next RRSIG covering the type or NULL */ zdb_packed_ttlrdata* rrsig_find_next(const zdb_packed_ttlrdata* rrsig, u16 type) { rrsig = rrsig->next; while(rrsig != NULL) { if(RRSIG_TYPE_COVERED(rrsig) == type) { return (zdb_packed_ttlrdata*)rrsig; } rrsig = rrsig->next; } return NULL; } /** * Deletes all RRSIG covering the given type. */ void rrsig_delete_covering(const zdb_rr_label* label, u16 type) { zdb_packed_ttlrdata** rrsigp = zdb_record_findp(&label->resource_record_set, TYPE_RRSIG); // pointer to a pointer to the record if(rrsigp != NULL) { zdb_packed_ttlrdata *rrsig; // will point to the record while((rrsig = *rrsigp) != NULL) { if(RRSIG_TYPE_COVERED(rrsig) != type) { rrsigp = &(*rrsigp)->next; } else { *rrsigp = (*rrsigp)->next; ZDB_RECORD_ZFREE(rrsig); } } } } /** * * Removes all the RRSIG covering the type * * @param dname the fqdn of the label * @param label the label * @param covered_type the type covered by the RRSIG */ void rrsig_delete(const zdb_zone *zone, const u8 *dname, zdb_rr_label* label, u16 type) { /* * zdb_packed_ttlrdata** prev = zdb_record_findp(&label->resource_record_set, TYPE_RRSIG); * * => * */ (void)zone; (void)dname; zdb_packed_ttlrdata** first = (zdb_packed_ttlrdata**)btree_findp(&label->resource_record_set, TYPE_RRSIG); if(first == NULL) { return; } zdb_packed_ttlrdata** prev = first; zdb_packed_ttlrdata* rrsig = *prev; while(rrsig != NULL) { if(RRSIG_TYPE_COVERED(rrsig) == type) { if(prev == first && rrsig->next == NULL) /* Only one RRSIG: proper removal and delete */ { zdb_record_delete(&label->resource_record_set, TYPE_RRSIG); break; } else { *prev = rrsig->next; /* More than one RRSIG: unchain and delete */ ZDB_RECORD_ZFREE(rrsig); rrsig = *prev; if(rrsig == NULL) { break; } } } prev = &(*prev)->next; rrsig = rrsig->next; } } void rrsig_delete_by_tag(const zdb_zone *zone, u16 tag) { /* * zdb_packed_ttlrdata** prev = zdb_record_findp(&label->resource_record_set, TYPE_RRSIG); * * => * */ zdb_packed_ttlrdata** first = (zdb_packed_ttlrdata**)btree_findp(&zone->apex->resource_record_set, TYPE_RRSIG); if(first == NULL) { return; } zdb_packed_ttlrdata** prev = first; zdb_packed_ttlrdata* rrsig = *prev; while(rrsig != NULL) { if(RRSIG_KEY_TAG(rrsig) == tag) { if(prev == first && rrsig->next == NULL) /* Only one RRSIG: proper removal and delete */ { zdb_record_delete(&zone->apex->resource_record_set, TYPE_RRSIG); break; } else { *prev = rrsig->next; /* More than one RRSIG: unchain and delete */ ZDB_RECORD_ZFREE(rrsig); rrsig = *prev; if(rrsig == NULL) { break; } } } prev = &(*prev)->next; rrsig = rrsig->next; } } /** * Use label position state (apex, at delegation, under delegation, ...) to decide if a label should be signed. * Optout is not taken into account. */ bool rrsig_should_label_be_signed(zdb_zone *zone, const u8 *fqdn, zdb_rr_label *rr_label) { (void)zone; (void)fqdn; if(LABEL_HAS_RECORDS(rr_label)) { if(zdb_rr_label_is_apex(rr_label)) { return TRUE; } else { if(ZDB_LABEL_ATDELEGATION(rr_label)) { return TRUE; } else { // not under a delegation: sign if(!ZDB_LABEL_UNDERDELEGATION(rr_label)) { return TRUE; } else { return FALSE; } } } } else { return FALSE; } } /** * regeneration is the time before expiration of the signature to regenerate it * but it should not be taken into account if the key will expire in that amount of time * */ bool rrsig_should_remove_signature_from_rdata(const void *rdata, u16 rdata_size, const ptr_vector *zsks, s32 now, s32 regeneration, s32 *key_indexp) { s64 inception = rrsig_get_valid_from_from_rdata(rdata, rdata_size); s64 expiration = rrsig_get_valid_until_from_rdata(rdata, rdata_size); #if DEBUG_SIGNATURE_REMOVAL_TEST rdata_desc rrsig_rr_rd = {TYPE_RRSIG, rdata_size, rdata}; #endif if(inception > expiration) { expiration += MAX_U32; } // signature date mismatched (time will be handled as 64 bits integers at a later date) if(expiration < inception) { #if DEBUG_SIGNATURE_REMOVAL_TEST log_info("rrsig_should_remove_signature_from_rdata: mismatched times %T < %T (DEBUG_SIGNATURE_REMOVAL_TEST)", expiration, inception); #endif return TRUE; } // signature expired if(now >= expiration) { #if DEBUG_SIGNATURE_REMOVAL_TEST log_info("rrsig_should_remove_signature_from_rdata: now >= expiration %T >= %T (DEBUG_SIGNATURE_REMOVAL_TEST) %{rdatadesc}", now, expiration, &rrsig_rr_rd); #endif return TRUE; } // find the key u16 key_tag = rrsig_get_key_tag_from_rdata(rdata, rdata_size); #if DEBUG_SIGNATURE_REMOVAL_TEST log_info("rrsig_should_remove_signature_from_rdata: tag=%hd", key_tag); #endif dnssec_key *key = NULL; for(int i = 0; i <= ptr_vector_last_index(zsks); ++i) { key = (dnssec_key*)ptr_vector_get(zsks, i); if(key == NULL) // invalid key { log_err("rrsig_should_remove_signature_from_rdata: tag=%hd: got NULL key", key_tag); break; } if(dnskey_get_tag(key) == key_tag) { *key_indexp = i; // key found if(!dnskey_is_deactivated(key, expiration)) { // key will not be deactivated at expiration of this signature (else there is no point regenerating it) // if the key is not private, regeneration is impossible if(dnskey_is_private(key)) { if(now >= (expiration - regeneration)) // signature needs to be regenerated (maybe) { if(now < expiration) { if(expiration < dnskey_get_inactive_epoch(key)) { #if DEBUG_SIGNATURE_REMOVAL_TEST log_info("rrsig_should_remove_signature_from_rdata: tag=%hd: expiration < inactive_epoch(key) times %T < %T (DEBUG_SIGNATURE_REMOVAL_TEST) %{rdatadesc}", key_tag, now, expiration, &rrsig_rr_rd); #endif return TRUE; // remove it for replacement } else { return FALSE; // no point re-doing it, it would only move the goal post } } else { #if DEBUG_SIGNATURE_REMOVAL_TEST log_info("rrsig_should_remove_signature_from_rdata: tag=%hd: now >= expiration %T >= %T (DEBUG_SIGNATURE_REMOVAL_TEST) %{rdatadesc}", key_tag, now, expiration, &rrsig_rr_rd); #endif return TRUE; // remove it for replacement } } else { return FALSE; } // return now >= (expiration - regeneration); // signature needs to be regenerated } else { #if DEBUG_SIGNATURE_REMOVAL_TEST if(now >= expiration) { log_info("rrsig_should_remove_signature_from_rdata: tag=%hd: now >= expiration %T >= %T (DEBUG_SIGNATURE_REMOVAL_TEST 2) %{rdatadesc}", key_tag, now, expiration, &rrsig_rr_rd); } #endif return now >= expiration; } } else // key is deactivated with its signature { #if DEBUG_SIGNATURE_REMOVAL_TEST if(now >= dnskey_get_inactive_epoch(key)) { log_info("rrsig_should_remove_signature_from_rdata: tag=%hd: now >= inactive_epoch(key) %T >= %T (DEBUG_SIGNATURE_REMOVAL_TEST 2) %{rdatadesc}", key_tag, now, dnskey_get_inactive_epoch(key), &rrsig_rr_rd); } #endif return (now >= dnskey_get_inactive_epoch(key)); } } } #if DEBUG_SIGNATURE_REMOVAL_TEST if(key != NULL) { if(now >= dnskey_get_inactive_epoch(key)) { log_info("rrsig_should_remove_signature_from_rdata: tag=%hd: key is inactive (DEBUG_SIGNATURE_REMOVAL_TEST) %{rdatadesc}", key_tag, now, dnskey_get_inactive_epoch(key), &rrsig_rr_rd); } } else { log_info("rrsig_should_remove_signature_from_rdata: tag=%hd : no such key (DEBUG_SIGNATURE_REMOVAL_TEST) %{rdatadesc}", key_tag, &rrsig_rr_rd); } #endif *key_indexp = -1; // key is unknown return TRUE; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/zdb-packed-ttlrdata.c0000644000000000000000000000013114505005531022750 xustar000000000000000030 mtime=1695812441.734972048 30 atime=1695812445.801030282 29 ctime=1695812495.17873747 yadifa-2.6.5-11201/lib/dnsdb/src/zdb-packed-ttlrdata.c0000664000374500037450000001402614505005531022716 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnsdb/zdb-packed-ttlrdata.h" static const u8 * zdb_packed_ttlrdata_record_view_get_fqdn(void *data, const void *rr) { zdb_packed_ttlrdata_record_view_data *rrv = (zdb_packed_ttlrdata_record_view_data*)data; (void)rr; return rrv->fqdn; } static u16 zdb_packed_ttlrdata_record_view_get_type(void *data, const void *rr) { zdb_packed_ttlrdata_record_view_data *rrv = (zdb_packed_ttlrdata_record_view_data*)data; (void)rr; return rrv->rtype; } static u16 zdb_packed_ttlrdata_record_view_get_class(void *data, const void *rr) { zdb_packed_ttlrdata_record_view_data *rrv = (zdb_packed_ttlrdata_record_view_data*)data; (void)rr; return rrv->rclass; } static s32 zdb_packed_ttlrdata_record_view_get_ttl(void *data, const void *rr) { zdb_packed_ttlrdata_record_view_data *rrv = (zdb_packed_ttlrdata_record_view_data*)data; (void)rr; return rrv->rttl; } static u16 zdb_packed_ttlrdata_record_view_get_rdata_size(void *data, const void *rr) { (void)data; zdb_packed_ttlrdata *ttlrdata = (zdb_packed_ttlrdata*)rr; return ZDB_PACKEDRECORD_PTR_RDATASIZE(ttlrdata); } static const u8 * zdb_packed_ttlrdata_record_view_get_rdata(void *data, const void *rr) { (void)data; zdb_packed_ttlrdata *ttlrdata = (zdb_packed_ttlrdata*)rr; return ZDB_PACKEDRECORD_PTR_RDATAPTR(ttlrdata); } static void * zdb_packed_ttlrdata_record_view_new_instance(void *data, const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size, const u8 *rdata) { (void)data; (void)fqdn; (void)rtype; (void)rclass; zdb_packed_ttlrdata *ttlrdata; ZDB_RECORD_ZALLOC(ttlrdata, ttl, rdata_size, rdata); ttlrdata->next = NULL; return ttlrdata; } static const struct resource_record_view_vtbl zdb_packed_ttlrdata_record_view_vtbl = { zdb_packed_ttlrdata_record_view_get_fqdn, zdb_packed_ttlrdata_record_view_get_type, zdb_packed_ttlrdata_record_view_get_class, zdb_packed_ttlrdata_record_view_get_ttl, zdb_packed_ttlrdata_record_view_get_rdata_size, zdb_packed_ttlrdata_record_view_get_rdata, zdb_packed_ttlrdata_record_view_new_instance }; void zdb_packed_ttlrdata_resource_record_view_init(struct resource_record_view *rrv) { zdb_packed_ttlrdata_record_view_data *data; ZALLOC_OBJECT_OR_DIE(data, zdb_packed_ttlrdata_record_view_data, ZDBPTRVD_TAG); rrv->data = data; rrv->vtbl = &zdb_packed_ttlrdata_record_view_vtbl; } void zdb_packed_ttlrdata_resource_record_view_set_fqdn(struct resource_record_view *rrv, const u8 *fqdn) { zdb_packed_ttlrdata_record_view_data *data = (zdb_packed_ttlrdata_record_view_data*)rrv->data; data->fqdn = fqdn; } void zdb_packed_ttlrdata_resource_record_view_set_type(struct resource_record_view *rrv, u16 rtype) { zdb_packed_ttlrdata_record_view_data *data = (zdb_packed_ttlrdata_record_view_data*)rrv->data; data->rtype = rtype; } void zdb_packed_ttlrdata_resource_record_view_set_class(struct resource_record_view *rrv, u16 rclass) { zdb_packed_ttlrdata_record_view_data *data = (zdb_packed_ttlrdata_record_view_data*)rrv->data; data->rclass = rclass; } void zdb_packed_ttlrdata_resource_record_view_set_ttl(struct resource_record_view *rrv, s32 rttl) { zdb_packed_ttlrdata_record_view_data *data = (zdb_packed_ttlrdata_record_view_data*)rrv->data; data->rttl = rttl; } void zdb_packed_ttlrdata_resource_record_view_finalize(struct resource_record_view *rrv) { zdb_packed_ttlrdata_record_view_data *data = (zdb_packed_ttlrdata_record_view_data*)rrv->data; ZFREE_OBJECT(data); rrv->data = NULL; } zdb_packed_ttlrdata* zdb_packed_ttlrdata_clone(zdb_packed_ttlrdata *record) { zdb_packed_ttlrdata* clone; ZDB_RECORD_ZALLOC(clone, record->ttl, ZDB_PACKEDRECORD_PTR_RDATASIZE(record), ZDB_PACKEDRECORD_PTR_RDATAPTR(record)); clone->next = NULL; return clone; } void zdb_packed_ttlrdata_insert_clone(zdb_packed_ttlrdata **list_head, zdb_packed_ttlrdata *record) { zdb_packed_ttlrdata *new_head = zdb_packed_ttlrdata_clone(record); new_head->next = *list_head; *list_head = new_head; } void zdb_packed_ttlrdata_insert(zdb_packed_ttlrdata **list_head, zdb_packed_ttlrdata *new_head) { assert(new_head->next == NULL); new_head->next = *list_head; *list_head = new_head; } yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec3.c0000644000000000000000000000013214505005531020143 xustar000000000000000030 mtime=1695812441.751972291 30 atime=1695812445.802030296 30 ctime=1695812495.180737499 yadifa-2.6.5-11201/lib/dnsdb/src/nsec3.c0000664000374500037450000014671414505005531020122 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include /* * RFC 5155 * * Server Response to a Run-Time Collision * * If the hash of a non-existing QNAME collides with the owner name of * an existing NSEC3 RR, then the server will be unable to return a * response that proves that QNAME does not exist. In this case, the * server MUST return a response with an RCODE of 2 (server failure). * * Note that with the hash algorithm specified in this document, SHA-1, * such collisions are highly unlikely. * */ #include "dnsdb/zdb_types.h" #if !ZDB_HAS_NSEC3_SUPPORT #error nsec3.c should not be compiled when ZDB_HAS_NSEC3_SUPPORT == 0 #endif #include #include #include #include #include #include #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb_zone_label_iterator.h" #include "dnsdb/zdb_record.h" #include "dnsdb/nsec3.h" #include "dnsdb/nsec_common.h" #include "dnsdb/nsec3_owner.h" #include "dnsdb/rrsig.h" #include "dnsdb/dynupdate-diff.h" #include "dnsdb/dynupdate-message.h" #include "dnsdb/zdb-zone-path-provider.h" #define NSEC3_ZONE_LABEL_UPDATE_CHAIN_LINKS_DEBUG 0 #if NSEC3_UPDATE_ZONE_DEBUG #pragma message("NSEC3_UPDATE_ZONE_DEBUG enabled, disable this for release builds") #endif #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; #define N3IRRVDT_TAG 0x544456525249334e #define RRVDATA_TAG 0x41544144565252 /** * used by nsec3_label_link * * It will find if the label has got a matching NSEC3 record (by digest) * If so, it will link to it. */ static nsec3_zone_item * nsec3_label_link_seeknode(nsec3_zone* n3, const u8 *fqdn, s32 fqdn_len, u8 *digest) { nsec3_compute_digest_from_fqdn_with_len(n3, fqdn, fqdn_len, digest, FALSE); #if NSEC3_UPDATE_ZONE_DEBUG log_debug("nsec3: seeking node for %{dnsname} with %{digest32h}", fqdn, digest); #endif nsec3_zone_item *self = nsec3_find(&n3->items, digest); return self; } /** * used by nsec3_label_link * * It will find if the *.label has got a matching NSEC3 record (by digest) * If so, it will link to it. */ static nsec3_zone_item * nsec3_label_link_seekstar(nsec3_zone* n3, const u8 *fqdn, s32 fqdn_len, u8 *digest) { nsec3_compute_digest_from_fqdn_with_len(n3, fqdn, fqdn_len, digest, TRUE); #if NSEC3_UPDATE_ZONE_DEBUG log_debug("nsec3: seeking star for %{dnsname} with %{digest32h}", fqdn, digest); #endif nsec3_zone_item* star = nsec3_find_interval_start(&n3->items, digest); return star; } /* * This destroy all the NSEC3 structures from the zone, starting from the NSEC3PARAM. * The zdb_rr_label are also affected by the call. */ void nsec3_destroy_zone(zdb_zone *zone) { // Note that from the 'transaction' update, the dnssec zone collections have to be read without checking for the NSEC3 flag while(zone->nsec.nsec3 != NULL) { #if DEBUG nsec3_zone *n3 = zone->nsec.nsec3; #endif nsec3_zone_destroy(zone, zone->nsec.nsec3); #if DEBUG yassert(n3 != zone->nsec.nsec3); #endif } } /****************************************************************************** * * NSEC3 - queries * *****************************************************************************/ /** * @brief Finds the provable resource record label matching a path of labels starting from another rr label * * Finds the resource record label matching a path of labels starting from another rr label * Typically the starting label is a zone cut. * The starting point MUST be provable (ie: the apex in NSEC and in NSEC3 zones) * * @param[in] apex the starting label * @param[in] path a stack of labels * @param[in] path_index the index of the top of the stack * * @return the matching label or NULL if it has not been found */ /* NSEC3: Zone possible */ static int nsec3_get_closest_provable_encloser_match(const void *label, const dictionary_node *node) { zdb_rr_label* rr_label = (zdb_rr_label*) node; return dnslabel_equals(rr_label->name, label); } /** * * Finds what is the closest provable encloser for a label in a zone * * @param apex * @param sections * @param sections_topp * @return */ const zdb_rr_label* nsec3_get_closest_provable_encloser_optin(const zdb_rr_label *apex, const_dnslabel_vector_reference sections, s32 *sections_topp) { yassert((apex != NULL) && (sections != NULL) && (sections_topp != NULL)); s32 index = *sections_topp; const zdb_rr_label* rr_label = apex; /* the zone cut */ const zdb_rr_label* provable = apex; /* * the apex is already known, so we don't loop for it */ index--; /* look into the sub level*/ while(index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); rr_label = (zdb_rr_label*) dictionary_find(&rr_label->sub, hash, label, nsec3_get_closest_provable_encloser_match); if(rr_label == NULL) { index++; break; } if(zdb_rr_label_flag_matches(rr_label, ZDB_RR_LABEL_N3COVERED)) { provable = rr_label; *sections_topp = index; } index--; } return provable; } const zdb_rr_label* nsec3_get_closest_provable_encloser_optout(const zdb_rr_label *apex, const_dnslabel_vector_reference sections, s32 *sections_topp) { yassert(apex != NULL && sections != NULL && sections_topp != NULL); s32 index = *sections_topp; const zdb_rr_label* rr_label = apex; /* the zone cut */ const zdb_rr_label* provable = apex; /* * the apex is already known, so we don't loop for it */ index--; /* look into the sub level*/ while(index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); rr_label = (zdb_rr_label*) dictionary_find(&rr_label->sub, hash, label, nsec3_get_closest_provable_encloser_match); if(rr_label == NULL) { index++; break; } if(zdb_rr_label_flag_matches(rr_label, ZDB_RR_LABEL_N3OCOVERED)) { provable = rr_label; *sections_topp = index; } /* else if(zdb_rr_label_flag_matches(rr_label, ZDB_RR_LABEL_GOT_WILD)) { dictionary_iterator iter; dictionary_iterator_init(&rr_label->sub, &iter); if(dictionary_iterator_hasnext(&iter)) { provable = *(zdb_rr_label**)dictionary_iterator_next(&iter); *sections_topp = index - 1; break; } } */ index--; } return provable; } static int zdb_label_wild_match(const void *label, const dictionary_node *node) { (void)label; zdb_rr_label* rr_label = (zdb_rr_label*) node; return IS_WILD_LABEL(rr_label->name); } void nsec3_get_wild_match_and_closest_provable_encloser_optin(const zdb_rr_label *apex, const_dnslabel_vector_reference sections, s32 sections_top, const zdb_rr_label** wild_matchp, s32 *wild_topp, const zdb_rr_label** provable_matchp, s32 *provable_topp) { yassert(apex != NULL && sections != NULL && wild_matchp != NULL && wild_topp != NULL && provable_matchp != NULL && provable_topp != NULL); s32 index = sections_top; const zdb_rr_label* rr_label = apex; /* the zone cut */ *wild_matchp = NULL; *provable_matchp = apex; *provable_topp = sections_top; /* * the apex is already known, so we don't loop for it */ index--; /* look into the sub level*/ while(index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); const zdb_rr_label* sub_rr_label = (zdb_rr_label*)dictionary_find(&rr_label->sub, hash, label, nsec3_get_closest_provable_encloser_match); if(sub_rr_label == NULL) { if(rr_label == apex) { zdb_rr_label *rr_label_sub_wild = (zdb_rr_label*)dictionary_find(&rr_label->sub, WILD_LABEL_HASH, NULL, zdb_label_wild_match); *wild_matchp = rr_label_sub_wild; *wild_topp = sections_top - 1; if(zdb_rr_label_flag_matches(rr_label, ZDB_RR_LABEL_N3COVERED)) { *provable_matchp = rr_label; *provable_topp = index; } } break; } rr_label = sub_rr_label; if(zdb_rr_label_flag_matches(rr_label, ZDB_RR_LABEL_GOT_WILD)) { zdb_rr_label *rr_label_sub_wild = (zdb_rr_label*)dictionary_find(&rr_label->sub, WILD_LABEL_HASH, NULL, zdb_label_wild_match); *wild_matchp = rr_label_sub_wild; *wild_topp = index - 1; } if(zdb_rr_label_flag_matches(rr_label, ZDB_RR_LABEL_N3COVERED)) { *provable_matchp = rr_label; *provable_topp = index; } index--; } } void nsec3_get_wild_match_and_closest_provable_encloser_optout(const zdb_rr_label *apex, const_dnslabel_vector_reference sections, s32 sections_top, const zdb_rr_label** wild_matchp, s32 *wild_topp, const zdb_rr_label** provable_matchp, s32 *provable_topp ) { yassert(apex != NULL && sections != NULL && wild_matchp != NULL && wild_topp != NULL && provable_matchp != NULL && provable_topp != NULL); s32 index = sections_top; const zdb_rr_label* rr_label = apex; /* the zone cut */ *wild_matchp = NULL; *provable_matchp = apex; *provable_topp = sections_top; --index; /* look into the sub level*/ while(index >= 0) { const u8* label = sections[index]; hashcode hash = hash_dnslabel(label); const zdb_rr_label* sub_rr_label = (zdb_rr_label*)dictionary_find(&rr_label->sub, hash, label, nsec3_get_closest_provable_encloser_match); if(sub_rr_label == NULL) { if(rr_label == apex) { zdb_rr_label *rr_label_sub_wild = (zdb_rr_label*)dictionary_find(&rr_label->sub, WILD_LABEL_HASH, NULL, zdb_label_wild_match); *wild_matchp = rr_label_sub_wild; *wild_topp = sections_top - 1; if(zdb_rr_label_flag_matches(rr_label, ZDB_RR_LABEL_N3OCOVERED)) { *provable_matchp = rr_label; *provable_topp = index; } } break; } rr_label = sub_rr_label; if(zdb_rr_label_flag_matches(rr_label, ZDB_RR_LABEL_GOT_WILD)) { zdb_rr_label *rr_label_sub_wild = (zdb_rr_label*)dictionary_find(&rr_label->sub, WILD_LABEL_HASH, NULL, zdb_label_wild_match); *wild_matchp = rr_label_sub_wild; *wild_topp = index - 1; } if(zdb_rr_label_flag_matches(rr_label, ZDB_RR_LABEL_N3OCOVERED)) { *provable_matchp = rr_label; *provable_topp = index; } index--; } } /** * Computes the closest closer proof for a name in a zone * Results are returned in 3 pointers * The last one of them can be set NULL if the information is not needed. * * @param zone * @param qname the fqdn of the query * @param apex_index the index of the apex in qname * @param encloser_nsec3p will point to the encloser * @param closest_provable_encloser_nsec3p will point to the closest provable encloser * @param wild_closest_provable_encloser_nsec3p will point to the *.closest provable encloser * * * https://www.ietf.org/rfc/rfc7129.txt */ void nsec3_wild_closest_encloser_proof( const zdb_zone *zone, const dnsname_vector *qname, s32 apex_index, const nsec3_zone_item **wild_encloser_nsec3p, const nsec3_zone_item **closest_provable_encloser_nsec3p, const nsec3_zone_item **qname_encloser_nsec3p ) { u8 tmp_fqdn[MAX_DOMAIN_LENGTH + 1]; u8 digest[64 + 1]; digest[0] = SHA_DIGEST_LENGTH; // wild_closest_provable_encloser_nsec3p can be NULL const_dnslabel_vector_reference qname_sections = qname->labels; s32 closest_encloser_index_limit = qname->size - apex_index + 1; /* not "+1'" because it starts at the apex */ const nsec3_zone* n3 = zone->nsec.nsec3; #if DEBUG if((n3 == NULL) || (n3->items == NULL)) { log_err("zone %{dnsname} has invalid NSEC3 data", zone->origin); return; } #endif if(closest_encloser_index_limit > 0) { const zdb_rr_label* wild_match; const zdb_rr_label* provable_match; s32 wild_top; s32 provable_top; if((zdb_zone_get_flags(zone) & ZDB_ZONE_HAS_OPTOUT_COVERAGE) != 0) { nsec3_get_wild_match_and_closest_provable_encloser_optout(zone->apex, qname_sections, closest_encloser_index_limit, &wild_match, &wild_top, &provable_match, &provable_top); } else { nsec3_get_wild_match_and_closest_provable_encloser_optin(zone->apex, qname_sections, closest_encloser_index_limit, &wild_match, &wild_top, &provable_match, &provable_top); } /* Get ZONE NSEC3PARAM */ u16 iterations = nsec3_zone_get_iterations(n3); u8 salt_len = NSEC3_ZONE_SALT_LEN(n3); const u8* salt = NSEC3_ZONE_SALT(n3); nsec3_hash_function* const digestname = nsec3_hash_get_function(NSEC3_ZONE_ALGORITHM(n3)); /// @note 20150917 edf -- do not use nsec3_compute_digest_from_fqdn_with_len /** @note log_* cannot be used here (except yassert because if that one logs it will abort anyway ...) */ //dnsname_vector_sub_to_dnsname(qname, closest_encloser_index_limit , ); const nsec3_zone_item *wild_closest_provable_encloser_nsec3 = NULL; const nsec3_zone_item *qname_encloser_nsec3 = NULL; if((wild_match != NULL) && zdb_rr_label_nsec3_linked(wild_match)) { wild_closest_provable_encloser_nsec3 = nsec3_label_extension_self(wild_match->nsec.nsec3); // add the interval for the fqdn at the * level dnsname_vector_sub_to_dnsname(qname, wild_top, tmp_fqdn); // wild top here must be 0 digestname(tmp_fqdn, dnsname_len(tmp_fqdn), salt, salt_len, iterations, &digest[1], FALSE); qname_encloser_nsec3 = nsec3_find_interval_start(&n3->items, digest); if(qname_encloser_nsec3 != wild_closest_provable_encloser_nsec3) { *qname_encloser_nsec3p = qname_encloser_nsec3; } } *wild_encloser_nsec3p = wild_closest_provable_encloser_nsec3; const nsec3_zone_item *closest_provable_encloser_nsec3; if(zdb_rr_label_nsec3_linked(provable_match)) { closest_provable_encloser_nsec3 = nsec3_label_extension_self(provable_match->nsec.nsec3); } else { digestname(tmp_fqdn, dnsname_len(tmp_fqdn), salt, salt_len, iterations, &digest[1], FALSE); closest_provable_encloser_nsec3 = nsec3_find_interval_start(&n3->items, digest); } if((closest_provable_encloser_nsec3 != wild_closest_provable_encloser_nsec3) && (closest_provable_encloser_nsec3 != qname_encloser_nsec3)) { *closest_provable_encloser_nsec3p = closest_provable_encloser_nsec3; } else { *closest_provable_encloser_nsec3p = NULL; } } else // the closest is the item itself ... { *wild_encloser_nsec3p = nsec3_label_extension_self(zone->apex->nsec.nsec3); *closest_provable_encloser_nsec3p = NULL; } } /** * Computes the closest closer proof for a name in a zone * Results are returned in 3 pointers * The last one of them can be set NULL if the information is not needed. * * @param zone * @param qname the fqdn of the query * @param apex_index the index of the apex in qname * @param encloser_nsec3p will point to the encloser * @param closest_provable_encloser_nsec3p will point to the closest provable encloser * @param wild_closest_provable_encloser_nsec3p will point to the *.closest provable encloser * */ void nsec3_closest_encloser_proof( const zdb_zone *zone, const dnsname_vector *qname, s32 apex_index, const nsec3_zone_item **encloser_nsec3p, const nsec3_zone_item **closest_provable_encloser_nsec3p, const nsec3_zone_item **wild_closest_provable_encloser_nsec3p ) { u8 closest_provable_encloser[MAX_DOMAIN_LENGTH+1]; u8 encloser[MAX_DOMAIN_LENGTH+1]; u8 digest[64 + 1]; digest[0] = SHA_DIGEST_LENGTH; yassert(encloser_nsec3p != NULL); yassert(closest_provable_encloser_nsec3p != NULL); // wild_closest_provable_encloser_nsec3p can be NULL const_dnslabel_vector_reference qname_sections = qname->labels; s32 closest_encloser_index_limit = qname->size - apex_index + 1; /* not "+1'" because it starts at the apex */ const nsec3_zone* n3 = zone->nsec.nsec3; #if DEBUG if((n3 == NULL) || (n3->items == NULL)) { log_err("zone %{dnsname} has invalid NSEC3 data", zone->origin); return; } #endif if(closest_encloser_index_limit > 0) { const zdb_rr_label* closest_provable_encloser_label = ((zdb_zone_get_flags(zone) & ZDB_ZONE_HAS_OPTOUT_COVERAGE) != 0)? nsec3_get_closest_provable_encloser_optout(zone->apex, qname_sections, &closest_encloser_index_limit): nsec3_get_closest_provable_encloser_optin(zone->apex, qname_sections, &closest_encloser_index_limit); //log_debug("closest_provable_encloser_label: %{dnslabel}: %{digest32h}", closest_provable_encloser_label->name, closest_provable_encloser_label->nsec.nsec3->self->digest); //log_debug("*.closest_provable_encloser_label: %{dnslabel}: %{digest32h}", closest_provable_encloser_label->name, closest_provable_encloser_label->nsec.nsec3->star->digest); /* * Convert from closest_encloser_label_bottom to name.size into a dnslabel */ /* Get ZONE NSEC3PARAM */ u16 iterations = nsec3_zone_get_iterations(n3); u8 salt_len = NSEC3_ZONE_SALT_LEN(n3); const u8* salt = NSEC3_ZONE_SALT(n3); const nsec3_zone_item* encloser_nsec3 = NULL; nsec3_hash_function* const digestname = nsec3_hash_get_function(NSEC3_ZONE_ALGORITHM(n3)); /// @note 20150917 edf -- do not use nsec3_compute_digest_from_fqdn_with_len /** @note log_* cannot be used here (except yassert because if that one logs it will abort anyway ...) */ // encloser_nsec3p if(closest_encloser_index_limit > 0) // if the closest encloser is itself, we should not be here { yassert(closest_provable_encloser_label != NULL); dnsname_vector_sub_to_dnsname(qname, closest_encloser_index_limit - 1, encloser); digestname(encloser, dnsname_len(encloser), salt, salt_len, iterations, &digest[1], FALSE); encloser_nsec3 = nsec3_zone_item_find_encloser_start(n3, digest); *encloser_nsec3p = encloser_nsec3; } else { *encloser_nsec3p = NULL; // the closest is itself (ie: missing type) } // closest_provable_encloser_nsec3p dnsname_vector_sub_to_dnsname(qname, closest_encloser_index_limit , closest_provable_encloser); const nsec3_zone_item* closest_provable_encloser_nsec3; if(!zdb_rr_label_nsec3_linked(closest_provable_encloser_label)) { digestname(closest_provable_encloser, dnsname_len(closest_provable_encloser), salt, salt_len, iterations, &digest[1], FALSE); closest_provable_encloser_nsec3 = nsec3_find(&n3->items, digest); } else { closest_provable_encloser_nsec3 = nsec3_label_extension_self(closest_provable_encloser_label->nsec.nsec3); } if(closest_provable_encloser_nsec3 == encloser_nsec3) { closest_provable_encloser_nsec3 = NULL; } *closest_provable_encloser_nsec3p = closest_provable_encloser_nsec3; if(wild_closest_provable_encloser_nsec3p != NULL) { if(closest_provable_encloser_nsec3 == NULL) { dnsname_vector_sub_to_dnsname(qname, closest_encloser_index_limit , closest_provable_encloser); } const nsec3_zone_item *wild_closest_provable_encloser_nsec3; if(!zdb_rr_label_nsec3_linked(closest_provable_encloser_label)) { digestname(closest_provable_encloser, dnsname_len(closest_provable_encloser), salt, salt_len, iterations, &digest[1], TRUE); wild_closest_provable_encloser_nsec3 = nsec3_find_interval_start(&n3->items, digest); } else { wild_closest_provable_encloser_nsec3 = nsec3_label_extension_star(closest_provable_encloser_label->nsec.nsec3); } if(wild_closest_provable_encloser_nsec3 == encloser_nsec3) { wild_closest_provable_encloser_nsec3 = NULL; } else if(wild_closest_provable_encloser_nsec3 == closest_provable_encloser_nsec3) { wild_closest_provable_encloser_nsec3 = NULL; } *wild_closest_provable_encloser_nsec3p = wild_closest_provable_encloser_nsec3; } } else // the closest is the item itself ... { *encloser_nsec3p = nsec3_label_extension_self(zone->apex->nsec.nsec3); *closest_provable_encloser_nsec3p = nsec3_label_extension_self(zone->apex->nsec.nsec3); if(wild_closest_provable_encloser_nsec3p != NULL) { *wild_closest_provable_encloser_nsec3p = nsec3_label_extension_self(zone->apex->nsec.nsec3); } } } #if NSEC3_UPDATE_ZONE_DEBUG /** * This is an internal integrity check * * For all owners of the NSEC3 record (aka nsec3_zone_item aka nsec3_node) * Check the label is not under a delegation (log debug only) * Check the label points back to the NSEC3 record * * @param item the NSEC3 record * @param param_index_base the index of the chain of the NSEC3 record */ void nsec3_check_item(nsec3_zone_item *item, u32 param_index_base) { yassert(item != NULL); u16 n = nsec3_owner_count(item); if(n == 0) { log_err("nsec3_check: %{digest32h} has no owner", item->digest); logger_flush(); abort(); } for(u16 i = 0; i < n; i++) { zdb_rr_label *label = nsec3_item_owner_get(item, i); yassert(label != NULL && label->nsec.nsec3 != NULL); if(ZDB_LABEL_UNDERDELEGATION(label)) { log_err("nsec3_check: %{digest32h} label nsec3 reference under a delegation (%{dnslabel})", item->digest, label); } nsec3_label_extension *n3le = label->nsec.nsec3; u32 param_index = param_index_base; while(param_index > 0) { yassert(n3le != NULL); n3le = nsec3_label_extension_next(n3le); param_index--; } yassert(n3le != NULL); // the nsec3 structure reference to the item linked to the label does not links back to the item yassert(n3le->_self == item); } n = nsec3_star_count(item); for(u16 i = 0; i < n; i++) { zdb_rr_label *label = nsec3_item_star_get(item, i); if(!((label != NULL) && (label->nsec.nsec3 != NULL))) { log_err("nsec3_check: %{digest32h} (#self=%d/#star=%d) corrupted", item->digest, item->rc, item->sc); } yassert(label != NULL && label->nsec.nsec3 != NULL); if(ZDB_LABEL_UNDERDELEGATION(label)) { log_err("nsec3_check: %{digest32h} *.label nsec3 reference under a delegation (%{dnslabel})", item->digest, label); } nsec3_label_extension *n3le = label->nsec.nsec3; u32 param_index = param_index_base; while(param_index > 0) { yassert(n3le != NULL); n3le = nsec3_label_extension_next(n3le); param_index--; } yassert(n3le != NULL); if(nsec3_label_extension_star(n3le) != item) { if(nsec3_label_extension_star(n3le) != NULL) { log_err("nsec3_check: %{digest32h} (#self=%d/#star=%d) failing %{dnslabel} expected %{digest32h}", item->digest, item->rc, item->sc, label->name, nsec3_label_extension_star(n3le)->digest); } else { log_err("nsec3_check: %{digest32h} (#self=%d/#star=%d) *.%{dnslabel} is NULL", item->digest, item->rc, item->sc, label->name, nsec3_label_extension_star(n3le)->digest); } } if(nsec3_label_extension_self(n3le) == NULL) { log_err("nsec3_check: %{digest32h} (#self=%d/#star=%d) failing %{dnslabel}: no self", item->digest, item->rc, item->sc, label->name); } if(nsec3_label_extension_star(n3le) != item) { log_err("nsec3_check: %{digest32h} *.label nsec3 reference does not point back to the nsec3 item (%{dnslabel})", item->digest, label); } if(nsec3_label_extension_self(n3le) == NULL) { log_err("nsec3_check: %{digest32h} *.label nsec3 reference self is NULL (%{dnslabel})", item->digest, label); } } } /** * This is an internal integrity check * * Checks all NSEC3 links to their owners back and forth. * * @param zone */ void nsec3_check(zdb_zone *zone) { log_debug("nsec3_check: %{dnsname}, from the NSEC3's reference", zone->origin); const nsec3_zone *n3 = zone->nsec.nsec3; if(n3 == NULL) { log_debug("nsec3_check: %{dnsname}: no NSEC3", zone->origin); return; } /* * For each node, check if the owners and stars are coherent */ u32 param_index = 0; while(n3 != NULL) { nsec3_iterator n3iter; nsec3_iterator_init(&n3->items, &n3iter); while(nsec3_iterator_hasnext(&n3iter)) { nsec3_zone_item* item = nsec3_iterator_next_node(&n3iter); nsec3_check_item(item, param_index); } param_index++; n3 = n3->next; } log_debug("nsec3_check: %{dnsname}: from the label's reference", zone->origin); zdb_zone_label_iterator label_iterator; u8 fqdn[MAX_DOMAIN_LENGTH + 1]; zdb_zone_label_iterator_init(&label_iterator, zone); while(zdb_zone_label_iterator_hasnext(&label_iterator)) { zdb_zone_label_iterator_nextname(&label_iterator, fqdn); zdb_rr_label* label = zdb_zone_label_iterator_next(&label_iterator); nsec3_label_extension *n3le = label->nsec.nsec3; while(n3le != NULL) { if(n3le->_self != NULL) { int found = 0; for(s32 i = 0; i < n3le->_self->rc; ++i) { zdb_rr_label* self = nsec3_item_owner_get(n3le->_self, i); if(self == label) { ++found; } } if(found == 0) { log_err("nsec3_check: %{dnsname}: %{dnsname} => %{digest32h} is one way", zone->origin, fqdn, n3le->_self->digest); } else if(found > 1) { log_err("nsec3_check: %{dnsname}: %{dnsname} => %{digest32h} is referenced back multiple times", zone->origin, fqdn, n3le->_self->digest); } } if(n3le->_star != NULL) { int found = 0; for(s32 i = 0; i < n3le->_star->sc; ++i) { zdb_rr_label* star = nsec3_item_star_get(n3le->_star, i); if(star == label) { ++found; } } if(found == 0) { log_err("nsec3_check: %{dnsname}: *.%{dnsname} => %{digest32h} is one way", zone->origin, fqdn, n3le->_star->digest); } else if(found > 1) { log_err("nsec3_check: %{dnsname}: *.%{dnsname} => %{digest32h} is referenced back multiple times", zone->origin, fqdn, n3le->_star->digest); } } n3le = n3le->_next; } } log_debug("nsec3_check: %{dnsname} : done", zone->origin); } #endif void nsec3_compute_digest_from_fqdn_with_len(const nsec3_zone *n3, const u8 *fqdn, u32 fqdn_len, u8 *digest, bool isstar) { digest[0] = nsec3_hash_len(NSEC3_ZONE_ALGORITHM(n3)); nsec3_hash_get_function(NSEC3_ZONE_ALGORITHM(n3))( fqdn, fqdn_len, NSEC3_ZONE_SALT(n3), NSEC3_ZONE_SALT_LEN(n3), nsec3_zone_get_iterations(n3), &digest[1], isstar); } void nsec3_zone_label_detach(zdb_rr_label *label) { yassert((label != NULL) && zdb_rr_label_flag_isset(label, (ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT))); nsec3_label_extension *n3le = label->nsec.nsec3; while(n3le != NULL) { // remove if(nsec3_label_extension_self(n3le) != NULL) { #if DEBUG nsec3_node *node_self = nsec3_label_extension_self(n3le); #endif nsec3_item_remove_owner(nsec3_label_extension_self(n3le), label); #if DEBUG log_debug1("nsec3_zone_label_detach(%{dnslabel}@%p) : nsec3 rc = %i", nsec3_owner_count(node_self)); #endif } if(nsec3_label_extension_star(n3le) != NULL) { nsec3_item_remove_star(nsec3_label_extension_star(n3le), label); } zdb_rr_label_flag_and(label, ~(ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT)); label->nsec.nsec3 = NULL; nsec3_label_extension *tmp = n3le; n3le = nsec3_label_extension_next(n3le); nsec3_label_extension_free(tmp); } label->nsec.nsec3 = NULL; } ya_result nsec3_get_next_digest_from_rdata(const u8 *rdata, u32 rdata_size, u8 *digest, u32 digest_size) { if((NSEC3_RDATA_ALGORITHM(rdata) == NSEC3_DIGEST_ALGORITHM_SHA1) && (rdata_size > 5 + 21)) { u32 salt_size = rdata[4]; u32 hash_size = rdata[5 + salt_size]; if((hash_size < digest_size) && (hash_size + salt_size + 5 < rdata_size)) { memcpy(digest, &rdata[5 + salt_size], hash_size + 1); return hash_size + 1; } } return ERROR; } // frees from back to front static inline void nsec3_zone_label_extension_remove(zdb_rr_label *label, nsec3_label_extension *n3le) { if(nsec3_label_extension_next(n3le) != NULL) { nsec3_zone_label_extension_remove(label, nsec3_label_extension_next(n3le)); nsec3_label_extension_set_next(n3le, NULL); } // remove if(nsec3_label_extension_self(n3le) != NULL) { nsec3_item_remove_owner(nsec3_label_extension_self(n3le), label); } if(nsec3_label_extension_star(n3le) != NULL) { nsec3_item_remove_star(nsec3_label_extension_star(n3le), label); } nsec3_label_extension_free(n3le); } void nsec3_zone_label_update_chain_links(nsec3_zone *n3, zdb_rr_label* label, int count, u16 coverage_mask, const u8 *fqdn) { nsec3_label_extension *n3le = label->nsec.nsec3; u8 digest[1 + MAX_DIGEST_LENGTH]; #if NSEC3_ZONE_LABEL_UPDATE_CHAIN_LINKS_DEBUG log_info("link: %{dnsname} (DEBUG)", fqdn); #endif // coverage_mask tells what coverage is expected in the zone. It has only one bit set. bool should_be_covered = zdb_rr_label_flag_isset(label, coverage_mask); u8 expected_optout_flag_value = (coverage_mask & ZDB_RR_LABEL_N3OCOVERED)?1:0; if(should_be_covered) // should be covered { #if NSEC3_ZONE_LABEL_UPDATE_CHAIN_LINKS_DEBUG log_info("link: %{dnsname}: should be covered (DEBUG)", fqdn); #endif if(n3le == NULL) // has no extension { // add the extension list n3le = nsec3_label_extension_alloc_list(count); label->nsec.nsec3 = n3le; if(zdb_rr_label_flag_isset(label, ZDB_RR_LABEL_N3OCOVERED)) { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT); } else { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_NSEC3); } } do { // are links missing ? if((nsec3_label_extension_self(n3le) == NULL) || (nsec3_label_extension_star(n3le) == NULL)) { // compute the digest(s) and link s32 fqdn_len = dnsname_len(fqdn); if(nsec3_label_extension_self(n3le) == NULL) { nsec3_zone_item *self = nsec3_label_link_seeknode(n3, fqdn, fqdn_len, digest); if(self != NULL) { if(self->flags != expected_optout_flag_value) { log_warn("%{dnsname} NSEC3 coverage flag doesn't match expected value", fqdn); } nsec3_item_add_owner(self, label); nsec3_label_extension_set_self(n3le, self); #if NSEC3_ZONE_LABEL_UPDATE_CHAIN_LINKS_DEBUG log_info("link: %{dnsname}: self node %{digest32h} bound (DEBUG)", fqdn, digest); #endif #if HAS_SUPERDUMP nsec3_superdump_integrity_check_label_nsec3_self_points_back(label,0); nsec3_superdump_integrity_check_nsec3_owner_self_points_back(self,0); #endif } #if NSEC3_ZONE_LABEL_UPDATE_CHAIN_LINKS_DEBUG else { log_info("link: %{dnsname}: self node %{digest32h} not found (DEBUG)", fqdn, digest); } #endif } if(nsec3_label_extension_star(n3le) == NULL) { nsec3_zone_item *star = nsec3_label_link_seekstar(n3, fqdn, fqdn_len, digest); if(star != NULL) { //nsec3_superdump_integrity_check_label_nsec3_star_points_back(label,0); nsec3_item_add_star(star, label); nsec3_label_extension_set_star(n3le, star); #if NSEC3_ZONE_LABEL_UPDATE_CHAIN_LINKS_DEBUG log_info("link: %{dnsname}: star node %{digest32h} bound (DEBUG)", fqdn, digest); #endif #if HAS_SUPERDUMP nsec3_superdump_integrity_check_label_nsec3_star_points_back(label,0); nsec3_superdump_integrity_check_nsec3_owner_star_points_back(star,0); #endif } #if NSEC3_ZONE_LABEL_UPDATE_CHAIN_LINKS_DEBUG else { log_info("link: %{dnsname}: star node %{digest32h} not found (DEBUG)", fqdn, digest); } #endif } } n3 = n3->next; nsec3_label_extension *next = nsec3_label_extension_next(n3le); if((next == NULL) && (n3 != NULL)) { // add nsec3_label_extension_set_next(n3le, nsec3_label_extension_alloc_list(1)); } else if((next != NULL) && (n3 == NULL)) { // extensions beyond the chain nsec3_label_extension_set_next(n3le, NULL); nsec3_zone_label_extension_remove(label, next); next = NULL; } n3le = next; } while(n3le != NULL); } else // should not be covered { #if NSEC3_ZONE_LABEL_UPDATE_CHAIN_LINKS_DEBUG log_info("link: %{dnsname}: should not be covered (DEBUG)", fqdn); #endif if(n3le != NULL) { nsec3_zone_label_extension_remove(label, n3le); zdb_rr_label_flag_and(label, ~(ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT)); label->nsec.nsec3 = NULL; } } } /** * Updates links for the first NSEC3 chain of the zone * Only links to existing NSEC3 records. * Only links label with an extension and self/wild set to NULL * * @param zone */ void nsec3_zone_update_chain0_links(zdb_zone *zone) { nsec3_zone *n3 = zone->nsec.nsec3; if(n3 == NULL) { return; } u16 coverage_mask; u8 maintain_mode = zone_get_maintain_mode(zone); if(maintain_mode & ZDB_ZONE_HAS_OPTOUT_COVERAGE) { coverage_mask = ZDB_RR_LABEL_N3OCOVERED; } else { coverage_mask = ZDB_RR_LABEL_N3COVERED; } log_debug("nsec3_zone_update_chain0_links(%{dnsname}) maintain_mode=%x", zone->origin, maintain_mode); int n3_count = 1; //u16 structure_mask = (maintain_mode == ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT)?ZDB_RR_LABEL_NSEC3_OPTOUT:((maintain_mode == ZDB_ZONE_MAINTAIN_NSEC3)?ZDB_RR_LABEL_NSEC3:0); { const nsec3_zone *n3 = zone->nsec.nsec3->next; while(n3 != NULL) { ++n3_count; n3 = n3->next; } } zdb_zone_label_iterator label_iterator; u8 fqdn[MAX_DOMAIN_LENGTH + 1]; zdb_zone_label_iterator_init(&label_iterator, zone); while(zdb_zone_label_iterator_hasnext(&label_iterator)) { zdb_zone_label_iterator_nextname(&label_iterator, fqdn); zdb_rr_label* label = zdb_zone_label_iterator_next(&label_iterator); nsec3_zone_label_update_chain_links(zone->nsec.nsec3, label, n3_count, coverage_mask, fqdn); } } #if ZDB_HAS_MASTER_SUPPORT /** * Sets the NSEC3 maintenance status for a specific chain. * Marks the zone using private records. * * The zone must be double-locked. * * @param zone * @param secondary_lock the secondary lock owner * @param algorithm * @param optout * @param salt * @param salt_len * @param iterations * @param status * @return */ ya_result nsec3_zone_set_status(zdb_zone *zone, u8 secondary_lock, u8 algorithm, u8 optout, u16 iterations, const u8 *salt, u8 salt_len, u8 status) { dynupdate_message dmsg; packet_unpack_reader_data reader; dynupdate_message_init(&dmsg, zone->origin, CLASS_IN); u8 prev_status = 0; #ifndef WIN32 u8 nsec3paramadd_rdata[5 + salt_len + 1]; #else u8 nsec3paramadd_rdata[5 + 255 + 1]; #endif nsec3paramadd_rdata[0] = algorithm; nsec3paramadd_rdata[1] = optout; SET_U16_AT(nsec3paramadd_rdata[2], htons(iterations)); nsec3paramadd_rdata[4] = salt_len; memcpy(&nsec3paramadd_rdata[5], salt, salt_len); nsec3paramadd_rdata[5 + salt_len] = status; // look for the matching record if(nsec3_zone_get_status(zone, algorithm, optout, iterations, salt, salt_len, &prev_status) == 1) { // if the record exists, remove it and add it nsec3paramadd_rdata[5 + salt_len] = prev_status; if(prev_status == status) { dynupdate_message_finalize(&dmsg); // already set return SUCCESS; } dynupdate_message_del_record(&dmsg, zone->origin, TYPE_NSEC3CHAINSTATE, 0, 6 + salt_len, nsec3paramadd_rdata); nsec3paramadd_rdata[5 + salt_len] = status; } dynupdate_message_add_record(&dmsg, zone->origin, TYPE_NSEC3CHAINSTATE, 0, 6 + salt_len, nsec3paramadd_rdata); dynupdate_message_set_reader(&dmsg, &reader); u16 count = dynupdate_message_get_count(&dmsg); packet_reader_skip(&reader, DNS_HEADER_LENGTH); // checked below packet_reader_skip_fqdn(&reader); // checked below packet_reader_skip(&reader, 4); // checked below ya_result ret; if(!packet_reader_eof(&reader)) { #if ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT if(zone_get_maintain_mode(zone) == 0) { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT); } #endif ret = dynupdate_diff(zone, &reader, count, secondary_lock, DYNUPDATE_DIFF_RUN); if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { // trigger a background store of the zone zdb_zone_info_background_store_zone(zone->origin); } } else { ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } dynupdate_message_finalize(&dmsg); return ret; } #endif /** * Gets the NSEC3 maintenance status for a specific chain. * Get the information from the zone using private records. * * The zone must be locked. * * @param zone * @param algorithm * @param optout * @param salt * @param salt_len * @param iterations * @param status * @return */ ya_result nsec3_zone_get_status(zdb_zone *zone, u8 algorithm, u8 optout, u16 iterations, const u8 *salt, u8 salt_len, u8 *statusp) { // get the TYPE_NSEC3PARAMADD record set // search for a record matching the chain zdb_packed_ttlrdata *rrset = zdb_record_find(&zone->apex->resource_record_set, TYPE_NSEC3CHAINSTATE); while(rrset != NULL) { if(rrset->rdata_size == 6 + salt_len) { if(rrset->rdata_start[0] == algorithm) { if(rrset->rdata_start[1] == optout) { if(GET_U16_AT(rrset->rdata_start[2]) == htons(iterations)) { if(rrset->rdata_start[4] == salt_len) { if((salt == NULL) || (memcmp(&rrset->rdata_start[5], salt, salt_len) == 0)) { *statusp = rrset->rdata_start[5 + salt_len]; return 1; } } } } } } rrset = rrset->next; } return 0; } /** * Gets a copy of the salt bytes from the first matching NSEC3PARAM record. * * The zone must be locked. * * @param zone * @param algorithm * @param optout * @param salt_len * @param iterations * @param salt_buffer * @return */ ya_result nsec3_zone_get_first_salt_matching(zdb_zone *zone, u8 algorithm, u8 optout, u16 iterations, u8 salt_len, u8 *salt_buffer) { // get the TYPE_NSEC3PARAMADD record set // search for a record matching the chain zdb_packed_ttlrdata *rrset = zdb_record_find(&zone->apex->resource_record_set, TYPE_NSEC3CHAINSTATE); while(rrset != NULL) { if(rrset->rdata_size == 6 + salt_len) { if(rrset->rdata_start[0] == algorithm) { if(rrset->rdata_start[1] == optout) { if(GET_U16_AT(rrset->rdata_start[2]) == htons(iterations)) { if(rrset->rdata_start[4] == salt_len) { if(salt_buffer != NULL) { memcpy(salt_buffer, &rrset->rdata_start[5], salt_len); } return 1; } } } } rrset = rrset->next; } } return 0; } /** * Gets the NSEC3 maintenance status for a specific chain. * Get the information from the zone using private records. * * The zone must be locked. * * @param zone * @param rdata * @param rdata_size * @param statusp * @return */ ya_result nsec3_zone_get_status_from_rdata(zdb_zone *zone, const u8* rdata, u16 rdata_size, u8 *statusp) { // get the TYPE_NSEC3PARAMADD record set // search for a record matching the chain zdb_packed_ttlrdata *rrset = zdb_record_find(&zone->apex->resource_record_set, TYPE_NSEC3CHAINSTATE); while(rrset != NULL) { if(rrset->rdata_size == rdata_size + 1) { if(rrset->rdata_start[0] == rdata[0]) { if(GET_U16_AT(rrset->rdata_start[2]) == GET_U16_AT(rdata[2])) { if(rrset->rdata_start[4] == rdata[4]) { if(memcmp(&rrset->rdata_start[5], &rdata[5], rdata[4]) == 0) { *statusp = rrset->rdata_start[5 + rdata[4]]; return 1; } } } } rrset = rrset->next; } } return 0; } /** * Returns the number of known chains in the zone. * Inactive chains are also counted. * Zone must be locked. * * @param zone * @return */ int nsec3_zone_get_chain_count(zdb_zone *zone) { int ret = 0; nsec3_zone *n3 = zone->nsec.nsec3; while(n3 != NULL) { ++ret; n3 = n3->next; } return ret; } /** * Returns pointers to the chains from the zone. * Inactive chains are also counted. * Zone must be locked. * * @param zone * @param n3p * @param max_count * @return */ int nsec3_zone_get_chains(zdb_zone *zone, nsec3_zone **n3p, int max_count) { int ret = 0; nsec3_zone *n3 = zone->nsec.nsec3; while(n3 != NULL) { *n3p++ = n3; if(++ret == max_count) { break; } n3 = n3->next; } return ret; } struct nsec3_item_rrv_data_s { nsec3_zone *n3; nsec3_node *item; const u8 *origin; u8 *rdata; u16 rdata_size; u16 rdata_buffer_size; s32 ttl; u8 fqdn[256]; }; typedef struct nsec3_item_rrv_data_s nsec3_item_rrv_data_t; static void nsec3_item_resource_record_view_data_item_set(nsec3_item_rrv_data_t *rrv_data, nsec3_node *item) { u32 required_size = nsec3_zone_item_rdata_size(rrv_data->n3, item); if(rrv_data->rdata_buffer_size < required_size) { free(rrv_data->rdata); rrv_data->rdata_buffer_size = (required_size + 128) & ~127; MALLOC_OBJECT_ARRAY_OR_DIE(rrv_data->rdata, u8, rrv_data->rdata_buffer_size, RRVDATA_TAG); } rrv_data->rdata_size = nsec3_zone_item_to_rdata(rrv_data->n3, item, rrv_data->rdata, rrv_data->rdata_buffer_size); u32 b32_len = base32hex_lc_encode(NSEC3_NODE_DIGEST_PTR(item), NSEC3_NODE_DIGEST_SIZE(item), (char*)&rrv_data->fqdn[1]); rrv_data->fqdn[0] = b32_len; dnsname_copy(&rrv_data->fqdn[b32_len + 1], rrv_data->origin); rrv_data->item = item; } static const u8 * nsec3_item_rrv_get_fqdn(void *data, const void* p) { nsec3_item_rrv_data_t *rrv_data = (nsec3_item_rrv_data_t*)data; if(rrv_data->item != (nsec3_node*)p) nsec3_item_resource_record_view_data_item_set(rrv_data, (nsec3_node*)p); return rrv_data->fqdn; } static u16 nsec3_item_rrv_get_type(void *data, const void* p) { (void)data; (void)p; return TYPE_NSEC3; } static u16 nsec3_item_rrv_get_class(void *data, const void* p) { (void)data; (void)p; return CLASS_IN; } static s32 nsec3_item_rrv_get_ttl(void *data, const void* p) { (void)p; nsec3_item_rrv_data_t *rrv_data = (nsec3_item_rrv_data_t*)data; return rrv_data->ttl; } static u16 nsec3_item_rrv_get_rdata_size(void *data, const void* p) { nsec3_item_rrv_data_t *rrv_data = (nsec3_item_rrv_data_t*)data; if(rrv_data->item != (nsec3_node*)p) nsec3_item_resource_record_view_data_item_set(rrv_data, (nsec3_node*)p); return rrv_data->rdata_size; } static const u8 * nsec3_item_rrv_get_rdata(void *data, const void* p) { nsec3_item_rrv_data_t *rrv_data = (nsec3_item_rrv_data_t*)data; if(rrv_data->item != (nsec3_node*)p) nsec3_item_resource_record_view_data_item_set(rrv_data, (nsec3_node*)p); return rrv_data->rdata; } static void * nsec3_item_rrv_new_instance(void *data, const u8 *fqdn, u16 rtype, u16 rclass, s32 ttl, u16 rdata_size, const u8 *rdata) { (void)data; (void)fqdn; (void)rtype; (void)rclass; yassert(rtype == TYPE_RRSIG); struct zdb_packed_ttlrdata *ttlrdata; ZDB_RECORD_ZALLOC(ttlrdata, ttl, rdata_size, rdata); return ttlrdata; } static const struct resource_record_view_vtbl nsec3_item_rrv_vtbl = { nsec3_item_rrv_get_fqdn, nsec3_item_rrv_get_type, nsec3_item_rrv_get_class, nsec3_item_rrv_get_ttl, nsec3_item_rrv_get_rdata_size, nsec3_item_rrv_get_rdata, nsec3_item_rrv_new_instance }; void nsec3_item_resource_record_view_init(resource_record_view *rrv) { ZALLOC_OBJECT_OR_DIE(rrv->data, nsec3_item_rrv_data_t, N3IRRVDT_TAG); ZEROMEMORY(rrv->data, sizeof(nsec3_item_rrv_data_t)); rrv->vtbl = &nsec3_item_rrv_vtbl; } void nsec3_item_resource_record_view_origin_set(struct resource_record_view *rrv, const u8 *origin) { yassert(rrv->vtbl == &nsec3_item_rrv_vtbl); nsec3_item_rrv_data_t *rrv_data = (nsec3_item_rrv_data_t*)rrv->data; rrv_data->origin = origin; } void nsec3_item_resource_record_view_nsec3_zone_set(struct resource_record_view *rrv, nsec3_zone *n3) { yassert(rrv->vtbl == &nsec3_item_rrv_vtbl); nsec3_item_rrv_data_t *rrv_data = (nsec3_item_rrv_data_t*)rrv->data; rrv_data->n3 = n3; } void nsec3_item_resource_record_view_ttl_set(resource_record_view *rrv, s32 ttl) { yassert(rrv->vtbl == &nsec3_item_rrv_vtbl); nsec3_item_rrv_data_t *rrv_data = (nsec3_item_rrv_data_t*)rrv->data; rrv_data->ttl = ttl; } void nsec3_item_resource_record_finalize(resource_record_view *rrv) { yassert(rrv->vtbl == &nsec3_item_rrv_vtbl); ZFREE_OBJECT_OF_TYPE(rrv->data, nsec3_item_rrv_data_t); rrv->vtbl = NULL; } void nsec3_superdump(zdb_zone *zone) { (void)zone; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec3_collection.c0000644000000000000000000000013214505005531022356 xustar000000000000000030 mtime=1695812441.705971632 30 atime=1695812445.800030268 30 ctime=1695812495.182737528 yadifa-2.6.5-11201/lib/dnsdb/src/nsec3_collection.c0000664000374500037450000002645014505005531022327 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #define _NSEC3_COLLECTION_C #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; #define DUMPER_FUNCTION(...) logger_handle_msg(MODULE_MSG_HANDLE,MSG_DEBUG,__VA_ARGS__) //#define DEBUG_LEVEL 9 //#define DEBUG_DUMP #include #include "dnsdb/nsec3_collection.h" /* * The following macros are defining relevant fields in the node */ /* * Access to the field that points to the left child * */ #define AVL_LEFT_CHILD(node) ((node)->children.lr.left) /* * Access to the field that points to the right child */ #define AVL_RIGHT_CHILD(node) ((node)->children.lr.right) /* * Access to the field that points to one of the children (0: left, 1: right) */ #define AVL_CHILD(node,id) ((node)->children.child[(id)]) /* * OPTIONAL : Access to the field that points the parent of the node. * * This field is optional but is mandatory if AVL_HAS_PARENT_POINTER is not 0 */ #define AVL_PARENT(node) ((node)->parent) /* * Access to the field that keeps the balance (a signed byte) */ #define AVL_BALANCE(node) ((node)->balance) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u8* /* * */ #define AVL_REFERENCE_FORMAT_STRING "%{digest32h}" #define AVL_REFERENCE_FORMAT(reference) reference /* * Two helpers macro, nothing to do with AVL */ #define NODE_SIZE(node) (sizeof(AVL_NODE_TYPE) + (node)->digest[0]) #define NODE_PAYLOAD_SIZE(node) (NODE_SIZE(node)-sizeof(nsec3_children_union)-1) /* * A macro to initialize a node and setting the reference */ #define AVL_INIT_NODE(node,reference) MEMCOPY((node)->digest,&(reference)[0],(reference)[0]+1) /* * A macro to allocate a new node */ #define AVL_ALLOC_NODE(node,reference) \ yassert((reference)[0]!=0); \ ZALLOC_ARRAY_OR_DIE(AVL_NODE_TYPE*, node, (sizeof(AVL_NODE_TYPE)+(reference)[0]), N3NODE_TAG); \ ZEROMEMORY(node,sizeof(AVL_NODE_TYPE)+(reference)[0]) /* * A macro to free a node allocated by ALLOC_NODE */ static void nsec3_free_node(nsec3_zone_item* node) { /* * This assert is wrong because this is actually the payload that has just overwritten our node * assert(node->rc == 0 && node->sc == 0 && node->label.owners == NULL && node->star_label.owners == NULL & node->type_bit_maps == NULL); */ if((node->rc | node->sc) != 0) { log_err("NSEC3 node %{digest32h} being deleted has RC,SC={%i,%i}, should be {0, 0}", node->digest, node->rc, node->sc); } if(node->rrsig != NULL) { log_warn("NSEC3 node %{digest32h} being deleted is still signed", node->digest); zdb_packed_ttlrdata *rrsig = node->rrsig; do { rdata_desc rrsig_record = {TYPE_RRSIG, ZDB_PACKEDRECORD_PTR_RDATASIZE(rrsig), ZDB_PACKEDRECORD_PTR_RDATAPTR(rrsig)}; log_debug("NSEC3 node %{digest32h} has %{typerdatadesc}", node->digest, &rrsig_record); zdb_packed_ttlrdata *tmp = rrsig; rrsig = rrsig->next; ZDB_RECORD_ZFREE(tmp); } while(rrsig != NULL); } ZFREE_ARRAY(node->type_bit_maps, node->type_bit_maps_size); node->type_bit_maps = NULL; node->type_bit_maps_size = 0; u32 node_size = NSEC3_NODE_SIZE(node); ZFREE_ARRAY(node, node_size); } #define AVL_FREE_NODE(node) nsec3_free_node(node) /* * A macro to print the node */ #define AVL_DUMP_NODE(node) format("node@%p",(node)); /* * A macro that returns the reference field of the node. * It must be of type REFERENCE_TYPE */ #define AVL_REFERENCE(node) (node)->digest #define AVL_TERNARYCMP 1 #if !AVL_TERNARYCMP /* * A macro to compare two references * Returns TRUE if and only if the references are equal. */ #define AVL_ISEQUAL(reference_a,reference_b) (memcmp(&(reference_a)[1],&(reference_b)[1],(reference_a)[0])==0) /* * A macro to compare two references * Returns TRUE if and only if the first one is bigger than the second one. */ #define AVL_ISBIGGER(reference_a,reference_b) (memcmp(&(reference_a)[1],&(reference_b)[1],(reference_a)[0])>0) #else #define AVL_COMPARE(reference_a,reference_b) (memcmp(&(reference_a)[1],&(reference_b)[1],(reference_a)[0])) #endif /* * Copies the payload of a node * It MUST NOT copy the "proprietary" node fields : children, parent, balance */ #define AVL_COPY_PAYLOAD(node_trg,node_src) MEMCOPY(&(node_trg)->flags,&(node_src)->flags,NODE_PAYLOAD_SIZE(node)) /* * A macro to preprocess a node before it is preprocessed for a delete (detach) * If there was anything to do BEFORE deleting a node, we would do it here * After this macro is exectuted, the node * _ is detached, then deleted with FREE_NODE * _ has got its content overwritten by the one of another node, then the other * node is deleted with FREE_NODE */ #define AVL_NODE_DELETE_CALLBACK(node) #include AVL_NODE_TYPE* AVL_PREFIXED(find_interval_start)(AVL_CONST_TREE_TYPE* root, const AVL_REFERENCE_TYPE obj_hash) { AVL_NODE_TYPE* node = *root; AVL_NODE_TYPE* lower_bound = NULL; AVL_REFERENCE_TYPE h; //yassert(node != NULL); /* This is one of the parts I could try to optimize * I've checked the assembly, and it sucks ... */ /* Both the double-test while/ternary and the current one * are producing the same assembly code. */ /** * Get a key that */ while(node != NULL) { h = AVL_REFERENCE(node); /* * [0] is the length of the obj_hash * * The obj_hashs starts at [1] * */ #if DEBUG if(h[0] != obj_hash[0]) { DIE_MSG("NSEC3 corrupted NSEC3 node"); } #endif int cmp = memcmp(&obj_hash[1], &h[1], h[0]); /* equals */ if(cmp == 0) { return node; } /* bigger */ if(cmp > 0) { lower_bound = node; node = AVL_CHILD(node, DIR_RIGHT); } else { node = AVL_CHILD(node, DIR_LEFT); } } if(lower_bound == NULL) { lower_bound = *root; if(lower_bound != NULL) { while((node = AVL_CHILD(lower_bound, DIR_RIGHT)) != NULL) { lower_bound = node; } } } return lower_bound; } AVL_NODE_TYPE* AVL_PREFIXED(find_interval_prev_mod)(AVL_CONST_TREE_TYPE* root, const AVL_REFERENCE_TYPE obj_hash) { AVL_NODE_TYPE* node = *root; AVL_NODE_TYPE* lower_bound = NULL; AVL_REFERENCE_TYPE h; yassert(node != NULL); /* Both the double-test while/ternary and the current one * are producing the same assembly code. */ /** * Get a key that */ while(node != NULL) { h = AVL_REFERENCE(node); /* * [0] is the length of the obj_hash * * The obj_hashs starts at [1] * */ #if DEBUG if(h[0] != obj_hash[0]) { DIE_MSG("NSEC3 corrupted NSEC3 node"); } #endif int cmp = memcmp(&obj_hash[1], &h[1], h[0]); /* equals */ if(cmp == 0) { return nsec3_node_mod_prev(node); } /* bigger */ if(cmp > 0) { lower_bound = node; node = AVL_CHILD(node, DIR_RIGHT); } else { node = AVL_CHILD(node, DIR_LEFT); } } if(lower_bound == NULL) { lower_bound = *root; yassert(lower_bound != NULL); while((node = AVL_CHILD(lower_bound, DIR_RIGHT)) != NULL) // VS false positive: an assert says this can't happen { lower_bound = node; } } return lower_bound; } AVL_NODE_TYPE* AVL_PREFIXED(find_prev_mod)(AVL_CONST_TREE_TYPE* root, const AVL_REFERENCE_TYPE obj_hash) { AVL_NODE_TYPE* node = *root; AVL_NODE_TYPE* lower_bound = NULL; AVL_REFERENCE_TYPE h; yassert(node != NULL); /* This is one of the parts I could try to optimize * I've checked the assembly, and it sucks ... */ /* Both the double-test while/ternary and the current one * are producing the same assembly code. */ /** * Get a key that */ while(node != NULL) { h = AVL_REFERENCE(node); /* * [0] is the length of the obj_hash * * The obj_hashs starts at [1] * */ #if DEBUG if(h[0] != obj_hash[0]) { DIE_MSG("NSEC3 corrupted NSEC3 node"); } #endif int cmp = memcmp(&obj_hash[1], &h[1], h[0]); /* equals */ if(cmp == 0) { // want the prev mod return nsec3_node_mod_prev(node); } /* bigger */ if(cmp > 0) { lower_bound = node; node = AVL_CHILD(node, DIR_RIGHT); } else { node = AVL_CHILD(node, DIR_LEFT); } } if(lower_bound == NULL) { lower_bound = *root; yassert(lower_bound != NULL); while((node = AVL_CHILD(lower_bound, DIR_RIGHT)) != NULL) // VS false positive: an assert says this can't happen { lower_bound = node; } } return lower_bound; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec3_item.c0000644000000000000000000000013214505005531021161 xustar000000000000000030 mtime=1695812441.759972406 30 atime=1695812445.803030311 30 ctime=1695812495.184737556 yadifa-2.6.5-11201/lib/dnsdb/src/nsec3_item.c0000664000374500037450000005310414505005531021126 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include "dnsdb/zdb_record.h" #include "dnsdb/nsec3_item.h" #include "dnsdb/nsec3_owner.h" #include "dnsdb/nsec3_zone.h" #include "dnsdb/rrsig.h" #include #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; /** * Finds the nsec3 record starting the interval based on the binary digest * * @param n3 * @param digest * @return */ nsec3_zone_item* nsec3_zone_item_find_encloser_start(const nsec3_zone* n3, const u8* digest) { return nsec3_find_interval_start(&n3->items, (u8*)digest); } nsec3_zone_item* nsec3_zone_item_find(const nsec3_zone* n3, const u8* digest) { return nsec3_find(&n3->items, (u8*)digest); } /** * Finds an nsec3 record matching the label * * @param n3 * @param digest * @return */ nsec3_zone_item* nsec3_zone_item_find_by_name(const nsec3_zone* n3, const u8* nsec3_label) { u8 digest[256]; ya_result digest_len = base32hex_decode((char*)&nsec3_label[1], nsec3_label[0], &digest[1]); if(ISOK(digest_len)) { digest[0] = digest_len; return nsec3_find(&n3->items, digest); } else { return NULL; } } nsec3_zone_item* nsec3_zone_item_find_by_name_ext(const zdb_zone *zone, const u8 *fqdn, nsec3_zone **out_n3) { nsec3_zone *n3 = zone->nsec.nsec3; nsec3_zone_item *n3zi = NULL; while(n3 != NULL) { if((n3zi = nsec3_zone_item_find_by_name(n3, fqdn)) != NULL) { break; } n3 = n3->next; } if(out_n3 != NULL) { *out_n3 = n3; } return n3zi; } nsec3_zone_item* nsec3_zone_item_find_by_record(const zdb_zone *zone, const u8 *fqdn, u16 rdata_size, const u8 *rdata) { const nsec3_zone *n3 = nsec3_zone_get_from_rdata(zone, rdata_size, rdata); nsec3_zone_item *n3zi = NULL; if(n3 != NULL) { n3zi = nsec3_zone_item_find_by_name(n3, fqdn); } return n3zi; } bool nsec3_zone_item_equals_rdata(const nsec3_zone* n3, const nsec3_zone_item *item, u16 rdata_size, const u8* rdata) { u32 param_rdata_size = NSEC3_ZONE_RDATA_SIZE(n3); u8 hash_len = NSEC3_NODE_DIGEST_SIZE(item); u32 type_bit_maps_size = item->type_bit_maps_size; u32 item_rdata_size = param_rdata_size + 1 + hash_len + type_bit_maps_size; if(item_rdata_size != rdata_size) { return FALSE; } /* Do not check the flags */ if(nsec3param_compare_by_rdata(rdata, n3->rdata) != 0) { return FALSE; } const u8 *p = &rdata[param_rdata_size]; nsec3_zone_item* next = nsec3_node_mod_next(item); if(memcmp(p, next->digest, hash_len + 1) != 0) { #if DEBUG_LEVEL >= 9 //nsec3_find_debug(&n3->items, item->digest); //nsec3_find_debug(&n3->items, next->digest); //bool exists = nsec3_find_debug(&n3->items, p) != NULL; log_debug("nsec3_zone_item_equals_rdata: REJECT: %{digest32h} NSEC3 ... %{digest32h} was expected to be followed by %{digest32h}", item->digest, next->digest, p); #endif return FALSE; } p += hash_len + 1; return memcmp(p, item->type_bit_maps, item->type_bit_maps_size) == 0; } bool nsec3_zone_item_equals_rdata_lenient(const nsec3_zone* n3, const nsec3_zone_item *item, u16 rdata_size, const u8* rdata) { u32 param_rdata_size = NSEC3_ZONE_RDATA_SIZE(n3); u8 hash_len = NSEC3_NODE_DIGEST_SIZE(item); //u32 type_bit_maps_size = item->type_bit_maps_size; u32 item_rdata_size = param_rdata_size + 1 + hash_len /*+ type_bit_maps_size*/; if(item_rdata_size > rdata_size) { return FALSE; } /* Do not check the flags */ if(nsec3param_compare_by_rdata(rdata, n3->rdata) != 0) { return FALSE; } const u8 *p = &rdata[param_rdata_size]; nsec3_zone_item* next = nsec3_node_mod_next(item); if(memcmp(p, next->digest, hash_len + 1) != 0) { #if DEBUG_LEVEL >= 9 //nsec3_find_debug(&n3->items, item->digest); //nsec3_find_debug(&n3->items, next->digest); //bool exists = nsec3_find_debug(&n3->items, p) != NULL; log_debug("nsec3_zone_item_equals_rdata: REJECT: %{digest32h} NSEC3 ... %{digest32h} was expected to be followed by %{digest32h}", item->digest, next->digest, p); #endif return FALSE; } // p += hash_len + 1; // memcmp(p, item->type_bit_maps, item->type_bit_maps_size) == 0 return TRUE; } /** * * @param n3 * @param item * @param origin * @param out_owner * @param nsec3 output buffer * @param nsec3_max_size output_buffer rdata size * @param out_nsec3_rrsig return value, if not NULL, it's a reference into the DB */ ya_result nsec3_zone_item_to_zdb_packed_ttlrdata(const nsec3_zone* n3, const nsec3_zone_item* item, const u8* origin, u8* out_owner, /* dnsname */ u32 ttl, zdb_packed_ttlrdata* nsec3, u32 nsec3_max_size) { u32 param_rdata_size = NSEC3_ZONE_RDATA_SIZE(n3); u8 hash_len = NSEC3_NODE_DIGEST_SIZE(item); u32 type_bit_maps_size = item->type_bit_maps_size; /* Whatever the editor says: rdata_size is used. */ u32 rdata_size = param_rdata_size + 1 + hash_len + type_bit_maps_size; if(nsec3_max_size < rdata_size) { return BUFFER_WOULD_OVERFLOW; } /* * NOTE: ZALLOC SHOULD NEVER BE USED IN MT * */ nsec3->ttl = ttl; nsec3->rdata_size = rdata_size; nsec3->next = NULL; u8* p = &nsec3->rdata_start[0]; MEMCOPY(p, &n3->rdata[0], param_rdata_size); p += param_rdata_size; nsec3_zone_item* next = nsec3_node_mod_next(item); MEMCOPY(p, next->digest, hash_len + 1); p += hash_len + 1; MEMCOPY(p, item->type_bit_maps, item->type_bit_maps_size); u32 b32_len = base32hex_lc_encode(NSEC3_NODE_DIGEST_PTR(item), hash_len, (char*)& out_owner[1]); out_owner[0] = b32_len; u32 origin_len = dnsname_len(origin); MEMCOPY(&out_owner[1 + b32_len], origin, origin_len); nsec3->rdata_start[1] = item->flags & 1; /* Opt-Out or Opt-In */ return rdata_size; } /** * * @param n3 * @param item * @param origin * @param out_owner * @param out_nsec3 return value, if not NULL, it is allocated by a malloc * @param out_nsec3_rrsig return value, if not NULL, it's a reference into the DB */ void nsec3_zone_item_to_new_zdb_packed_ttlrdata( nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm *nsec3_parms, u8** out_owner_p, /* dnsname */ zdb_packed_ttlrdata** out_nsec3, const zdb_packed_ttlrdata** out_nsec3_rrsig) { const nsec3_zone* n3 = nsec3_parms->n3; #if DEBUG if(n3 == NULL) { log_err("%{dnsname}: missing NSEC3 chain", nsec3_parms->origin); if(out_owner_p != NULL) { *out_owner_p = NULL; } if(out_nsec3 != NULL) { *out_nsec3 = NULL; } if(out_nsec3_rrsig != NULL) { *out_nsec3_rrsig = NULL; } return; } #endif u32 param_rdata_size = NSEC3_ZONE_RDATA_SIZE(n3); const nsec3_zone_item* item = nsec3_parms->item; #if DEBUG if(n3 == NULL) { log_err("%{dnsname}: missing NSEC3 record", nsec3_parms->origin); if(out_owner_p != NULL) { *out_owner_p = NULL; } if(out_nsec3 != NULL) { *out_nsec3 = NULL; } if(out_nsec3_rrsig != NULL) { *out_nsec3_rrsig = NULL; } return; } #endif u8 hash_len = NSEC3_NODE_DIGEST_SIZE(nsec3_parms->item); u32 type_bit_maps_size = item->type_bit_maps_size; /* Whatever the editor says: rdata_size is used. */ u32 rdata_size = param_rdata_size + 1 + hash_len + type_bit_maps_size; zdb_packed_ttlrdata* nsec3; u8 * restrict * pool = nsec3_parms->pool; nsec3 = (zdb_packed_ttlrdata*)*pool; *pool += ALIGN16(ZDB_RECORD_SIZE_FROM_RDATASIZE(rdata_size)); nsec3->next = NULL; nsec3->ttl = nsec3_parms->ttl; nsec3->rdata_size = rdata_size; u8* p = &nsec3->rdata_start[0]; MEMCOPY(p, &n3->rdata[0], param_rdata_size); p += param_rdata_size; nsec3_zone_item* next = nsec3_node_mod_next(item); MEMCOPY(p, next->digest, hash_len + 1); p += hash_len + 1; MEMCOPY(p, item->type_bit_maps, item->type_bit_maps_size); u8 *out_owner = *pool; *out_owner_p = out_owner; u32 b32_len = base32hex_lc_encode(NSEC3_NODE_DIGEST_PTR(item), hash_len, (char*)&out_owner[1]); out_owner[0] = b32_len; const u8 *origin = nsec3_parms->origin; u32 origin_len = dnsname_len(origin); MEMCOPY(&out_owner[1 + b32_len], origin, origin_len); *pool += ALIGN16(1 + b32_len + origin_len); nsec3->rdata_start[1] = item->flags & 1; /* Opt-Out or Opt-In */ *out_nsec3 = nsec3; *out_nsec3_rrsig = item->rrsig; } u32 nsec3_zone_item_rdata_size(const nsec3_zone* n3, const nsec3_zone_item *item) { u32 param_rdata_size = NSEC3_ZONE_RDATA_SIZE(n3); u8 hash_len = NSEC3_NODE_DIGEST_SIZE(item); u32 type_bit_maps_size = item->type_bit_maps_size; /* Whatever the editor says: rdata_size is used. */ u32 rdata_size = param_rdata_size + 1 + hash_len + type_bit_maps_size; return rdata_size; } u16 nsec3_zone_item_to_rdata( const nsec3_zone* n3, const nsec3_zone_item *item, u8 *out_rdata, u16 out_rdata_size) { u32 param_rdata_size = NSEC3_ZONE_RDATA_SIZE(n3); u8 hash_len = NSEC3_NODE_DIGEST_SIZE(item); u32 type_bit_maps_size = item->type_bit_maps_size; /* Whatever the editor says: rdata_size is used. */ u32 rdata_size = param_rdata_size + 1 + hash_len + type_bit_maps_size; yassert(out_rdata_size >= rdata_size); if(out_rdata_size < rdata_size) { log_err("nsec3_zone_item_to_rdata: buffer would overflow"); return 0; } u8* p = out_rdata; MEMCOPY(p, &n3->rdata[0], param_rdata_size); p[1] = item->flags & 1; /* Opt-Out or Opt-In */ p += param_rdata_size; nsec3_zone_item* next = nsec3_node_mod_next(item); MEMCOPY(p, next->digest, hash_len + 1); p += hash_len + 1; MEMCOPY(p, item->type_bit_maps, item->type_bit_maps_size); return rdata_size; } u32 nsec3_zone_item_get_label(const nsec3_zone_item* item, u8* output_buffer, u32 buffer_size ) { yassert(buffer_size >= 128); (void)buffer_size; u8 hash_len = NSEC3_NODE_DIGEST_SIZE(item); u32 b32_len = base32hex_lc_encode(NSEC3_NODE_DIGEST_PTR(item), hash_len, (char*)&output_buffer[1]); output_buffer[0] = b32_len; return b32_len + 1; } void nsec3_zone_item_write_owner(output_stream* os, const nsec3_zone_item* item, const u8* origin ) { u8 tmp[128]; /* enough to get a 64 bit digest printed as base32hex */ u32 label_len = nsec3_zone_item_get_label(item, tmp, sizeof(tmp)); output_stream_write(os, tmp, label_len); u32 origin_len = dnsname_len(origin); output_stream_write(os, origin, origin_len); } void nsec3_item_format_writer_callback(const void *args_, output_stream *os, s32 padding, char pad_char, bool left_justified, void *reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; nsec3_item_format_writer_args *args = (nsec3_item_format_writer_args*)args_; output_stream nsec3_wire_os; bytearray_output_stream_context nsec3_wire_os_context; u8 *wire; u8 nsec3_wire_tmp[512]; /* enough for most cases */ bytearray_output_stream_init_ex_static(&nsec3_wire_os, (u8*)nsec3_wire_tmp, sizeof(nsec3_wire_tmp), 0, &nsec3_wire_os_context); nsec3_zone_item_to_output_stream(&nsec3_wire_os, args->n3, args->item, args->origin, args->ttl); wire = bytearray_output_stream_buffer(&nsec3_wire_os); osformat(os, "%{recordwire}", wire); } void nsec3_zone_item_to_output_stream(output_stream* os, const nsec3_zone* n3, const nsec3_zone_item* item, const u8* origin, u32 ttl) { u32 param_rdata_size; u32 type_bit_maps_size; u32 rdata_size; u32 b32_len; u32 origin_len; u8 hash_len; u8 tmp[128]; /* enough to get a 64 bit digest printed as base32hex */ param_rdata_size = NSEC3_ZONE_RDATA_SIZE(n3); hash_len = NSEC3_NODE_DIGEST_SIZE(item); type_bit_maps_size = item->type_bit_maps_size; /* Whatever the editor says: rdata_size is used. */ rdata_size = param_rdata_size + 1 + hash_len + type_bit_maps_size; b32_len = base32hex_lc_encode(NSEC3_NODE_DIGEST_PTR(item), hash_len, (char*)&tmp[1]); tmp[0] = b32_len; /* NAME */ output_stream_write(os, tmp, b32_len + 1); origin_len = dnsname_len(origin); output_stream_write(os, origin, origin_len); /* TYPE */ output_stream_write_u16(os, TYPE_NSEC3); /** @note NATIVETYPE */ /* CLASS */ output_stream_write_u16(os, CLASS_IN); /** @note NATIVECLASS */ /* TTL */ output_stream_write_nu32(os, ttl); /* RDATA SIZE */ output_stream_write_nu16(os, rdata_size); /* RDATA */ output_stream_write_u8(os, n3->rdata[0]); output_stream_write_u8(os, item->flags); output_stream_write(os, &n3->rdata[2], param_rdata_size - 2); nsec3_zone_item* next = nsec3_node_mod_next(item); output_stream_write(os, next->digest, hash_len + 1); output_stream_write(os, item->type_bit_maps, item->type_bit_maps_size); } void nsec3_zone_item_rrsig_del_by_keytag(nsec3_zone_item *item, u16 native_key_tag) { if(item->rrsig != NULL) { zdb_packed_ttlrdata **rrsigp = &item->rrsig; do { zdb_packed_ttlrdata *rrsig = *rrsigp; if(RRSIG_KEY_NATIVETAG(rrsig) == native_key_tag) { /* Remove from the list */ *rrsigp = rrsig->next; ZDB_RECORD_ZFREE(rrsig); break; } rrsigp = &rrsig->next; } while(*rrsigp != NULL); } } void nsec3_zone_item_rrsig_del(nsec3_zone_item *item, const zdb_ttlrdata *nsec3_rrsig) { if(item->rrsig != NULL) { while(nsec3_rrsig != NULL) { zdb_packed_ttlrdata** rrsigp = &item->rrsig; // look for a match zdb_packed_ttlrdata* rrsig; while((rrsig = *rrsigp) != NULL) { if(zdb_record_equals_unpacked(rrsig, nsec3_rrsig)) { /* Remove from the list */ *rrsigp = rrsig->next; ZDB_RECORD_ZFREE(rrsig); break; } rrsigp = &rrsig->next; } nsec3_rrsig = nsec3_rrsig->next; } } } void nsec3_zone_item_rrsig_add(nsec3_zone_item *item, zdb_packed_ttlrdata *nsec3_rrsig) { if(item->rrsig == NULL) { item->rrsig = nsec3_rrsig; } else { zdb_packed_ttlrdata *good = NULL; zdb_packed_ttlrdata *rrsig; while(nsec3_rrsig != NULL) { /* look for the first item on the list */ rrsig = item->rrsig; bool add = TRUE; do { /* Replaces another signature ? */ if(zdb_record_equals(rrsig, nsec3_rrsig)) { add = FALSE; break; } rrsig = rrsig->next; } while(rrsig != NULL); zdb_packed_ttlrdata *tmp = nsec3_rrsig->next; if(add) { nsec3_rrsig->next = good; good = nsec3_rrsig; } else { ZDB_RECORD_ZFREE(nsec3_rrsig); } nsec3_rrsig = tmp; } if(good != NULL) { rrsig = item->rrsig; while(rrsig->next != NULL) { rrsig = rrsig->next; } rrsig->next = good; } } } void nsec3_zone_item_rrsig_delete_all(nsec3_zone_item *item) { zdb_packed_ttlrdata *rrsig_sll = item->rrsig; item->rrsig = NULL; while(rrsig_sll != NULL) { zdb_packed_ttlrdata *tmp = rrsig_sll; rrsig_sll = rrsig_sll->next; ZDB_RECORD_ZFREE(tmp); } } /* * Empties an nsec3_zone_item * * Only frees the payload : owners, stars, bitmap, rrsig * Does not change the other nodes of the structure * * This should be followed by the destruction of the item */ void nsec3_zone_item_empties(nsec3_zone_item *item) { nsec3_item_remove_all_star(item); nsec3_item_remove_all_owners(item); yassert(item->rc == 0 && item->sc == 0); ZFREE_ARRAY(item->type_bit_maps, item->type_bit_maps_size); item->type_bit_maps = NULL; item->type_bit_maps_size = 0; nsec3_zone_item_rrsig_delete_all(item); item->flags = NSEC3_FLAGS_MARKED_FOR_ICMTL_DEL; } /** * Sets the type bitmap of the nsec3 item to match the one in the rdata * Does nothing if the bitmap is already ok * * NOTE: Remember that the item does not contain * * _ hash_algorithm * _ iterations * _ salt_length * _ salt * _ hash_length * _ next_hashed_owner_name */ ya_result nsec3_zone_item_update_bitmap(nsec3_zone_item* nsec3_item, const u8 *rdata, u16 rdata_size) { /* * Skip the irrelevant bytes */ if(rdata_size < 8) { return BUFFER_WOULD_OVERFLOW; } const u8 *bitmap = rdata; u16 type_bit_maps_size = rdata_size; // skip hash + flags + iterations bitmap += 4; type_bit_maps_size -= 4; // skip salt length + salt (and checks) if(type_bit_maps_size < *bitmap + 1) { return INCORRECT_RDATA; } type_bit_maps_size -= *bitmap + 1; bitmap += *bitmap + 1; // skip hash length + hash (and checks) if(type_bit_maps_size < *bitmap + 1) { return INCORRECT_RDATA; } type_bit_maps_size -= *bitmap + 1; bitmap += *bitmap + 1; /* * If it does not match, replace. */ if((nsec3_item->type_bit_maps_size != type_bit_maps_size) || (memcmp(nsec3_item->type_bit_maps, bitmap, type_bit_maps_size) != 0)) { /* If the (bloc) size differs : free and alloc */ if(zalloc_memory_block_size(nsec3_item->type_bit_maps_size) != zalloc_memory_block_size(type_bit_maps_size)) { ZFREE_ARRAY(nsec3_item->type_bit_maps, nsec3_item->type_bit_maps_size); ZALLOC_ARRAY_OR_DIE(u8*, nsec3_item->type_bit_maps, type_bit_maps_size, NSEC3_TYPEBITMAPS_TAG); } memcpy(nsec3_item->type_bit_maps, bitmap, type_bit_maps_size); nsec3_item->type_bit_maps_size = type_bit_maps_size; } return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec3-chain-replay.c0000644000000000000000000000013214505005531022515 xustar000000000000000030 mtime=1695812441.756972363 30 atime=1695812445.803030311 30 ctime=1695812495.186737585 yadifa-2.6.5-11201/lib/dnsdb/src/nsec3-chain-replay.c0000664000374500037450000011226714505005531022470 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include #include "dnsdb/zdb_types.h" #include "dnsdb/nsec3-chain-replay.h" #include "dnsdb/nsec3_types.h" #include "dnsdb/rrsig.h" #include "dnsdb/zdb-zone-arc.h" #include "dnsdb/zdb_zone.h" #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; void nsec3_zone_label_detach(zdb_rr_label *label); #define NSEC3_CHAIN_REPLAY_DEBUG 0 #if NSEC3_CHAIN_REPLAY_DEBUG #pragma message("WARNING: NSEC3_CHAIN_REPLAY_DEBUG is not set to 0") #endif #define NSEC3CNR_TAG 0x524e43334345534e #define NSEC3RPL_TAG 0x4c5052334345534e #define NSEC3_CHAIN_REPLAY_STATUS_UPDATED 1 struct nsec3_chain_replay_record { s32 ttl; u16 rdata_size; #if NSEC3_CHAIN_REPLAY_DEBUG u16 rtype; u16 _padding_; #endif u8 fqdn_len; u8 status; u8 fqdn_rdata[]; }; typedef struct nsec3_chain_replay_record nsec3_chain_replay_record; static nsec3_chain_replay_record * nsec3_chain_replay_record_new(const u8 *fqdn, u16 rtype, s32 ttl, const u8 *rdata, u16 rdata_size) { nsec3_chain_replay_record *record; int fqdn_len = dnsname_len(fqdn); ZALLOC_ARRAY_OR_DIE(nsec3_chain_replay_record*, record, sizeof(nsec3_chain_replay_record) + fqdn_len + rdata_size, NSEC3CNR_TAG); record->ttl = ttl; record->rdata_size = rdata_size; #if NSEC3_CHAIN_REPLAY_DEBUG record->rtype = rtype; #endif record->fqdn_len = fqdn_len; record->status = 0; memcpy(record->fqdn_rdata, fqdn, fqdn_len); memcpy(&record->fqdn_rdata[fqdn_len], rdata, rdata_size); #if NSEC3_CHAIN_REPLAY_DEBUG rdata_desc nsec3_desc = {rtype, rdata_size, rdata}; log_debug("nsec3-chain: record new %{dnsname} %i %{typerdatadesc}", fqdn, ttl, &nsec3_desc); #else (void)rtype; #endif return record; } static const u8 * nsec3_chain_replay_record_fqdn(nsec3_chain_replay_record *record) { return record->fqdn_rdata; } static const u8 * nsec3_chain_replay_record_rdata(nsec3_chain_replay_record *record) { return &record->fqdn_rdata[record->fqdn_len]; } static const u8 * nsec3_chain_replay_record_next_digest(nsec3_chain_replay_record *record) { const u8 *rdata = nsec3_chain_replay_record_rdata(record); return &rdata[rdata[4] + 5]; } #if NSEC3_CHAIN_REPLAY_DEBUG static void nsec3_chain_replay_record_format(const void* r, output_stream* os, s32 a, char b, bool c, void* d) { nsec3_chain_replay_record *rr = (nsec3_chain_replay_record*)r; (void)a; (void)b; (void)c; (void)d; rdata_desc typerdata = {rr->rtype, rr->rdata_size, nsec3_chain_replay_record_rdata(rr)}; osformat(os, "%{dnsname} %i %{typerdatadesc}", nsec3_chain_replay_record_fqdn(rr), rr->ttl, &typerdata); } #endif static void nsec3_chain_replay_record_delete(nsec3_chain_replay_record *record) { #if NSEC3_CHAIN_REPLAY_DEBUG rdata_desc nsec3_desc = {record->rtype, record->rdata_size, nsec3_chain_replay_record_rdata(record)}; log_debug("nsec3-chain: record free %{dnsname} %i %{typerdatadesc}", nsec3_chain_replay_record_fqdn(record), record->ttl, &nsec3_desc); #endif ZFREE_ARRAY(record, sizeof(nsec3_chain_replay_record) + record->fqdn_len + record->rdata_size); } static void nsec3_chain_replay_record_delete_cb(void *record) { nsec3_chain_replay_record_delete((nsec3_chain_replay_record*)record); } static nsec3_zone * nsec3_chain_replay_record_find_chain(zdb_zone *zone, nsec3_chain_replay_record *record) { nsec3_zone *n3 = zone->nsec.nsec3; while(n3 != NULL) { const u8 *record_rdata = nsec3_chain_replay_record_rdata(record); u16 record_rdata_size = NSEC3PARAM_RDATA_SIZE_FROM_RDATA(record_rdata); u16 n3_rdata_size = NSEC3PARAM_RDATA_SIZE_FROM_RDATA(n3->rdata); if(n3_rdata_size <= record_rdata_size) { if(record_rdata[0] == n3->rdata[0]) { if(memcmp(&record_rdata[3], &n3->rdata[3], n3_rdata_size - 3) == 0) { break; } } } n3 = n3->next; } return n3; } static nsec3_zone * nsec3_chain_replay_record_add_chain(zdb_zone *zone, nsec3_chain_replay_record *record) { nsec3_zone **n3p = &zone->nsec.nsec3; while(*n3p != NULL) { n3p = &(*n3p)->next; } nsec3_zone *n3 = nsec3_zone_new(nsec3_chain_replay_record_rdata(record), record->rdata_size); *n3p = n3; return n3; } static nsec3_zone_item * nsec3_chain_replay_record_find_item_by_name(zdb_zone *zone, nsec3_chain_replay_record *record) { nsec3_zone *n3 = zone->nsec.nsec3; while(n3 != NULL) { nsec3_zone_item *item = nsec3_zone_item_find_by_name(n3, nsec3_chain_replay_record_fqdn(record)); if(item != NULL) { return item; } n3 = n3->next; } return NULL; } static int nsec3_chain_replay_record_nsec3_compare(const void *a, const void *b) { nsec3_chain_replay_record *ra = (nsec3_chain_replay_record*)a; nsec3_chain_replay_record *rb = (nsec3_chain_replay_record*)b; const u8 *ra_rdata = nsec3_chain_replay_record_rdata(ra); const u8 *rb_rdata = nsec3_chain_replay_record_rdata(rb); int ra_chain_size = NSEC3PARAM_RDATA_SIZE_FROM_RDATA(ra_rdata); int rb_chain_size = NSEC3PARAM_RDATA_SIZE_FROM_RDATA(rb_rdata); int d = ra_chain_size - rb_chain_size; if(d == 0) { d = memcmp(ra_rdata, rb_rdata, ra_chain_size); if(d == 0) { d = dnsname_compare(nsec3_chain_replay_record_fqdn(ra), nsec3_chain_replay_record_fqdn(rb)); } } return d; } static void nsec3_chain_replay_fqdn_key_delete(ptr_node *node) { dnsname_zfree((u8*)node->key); } struct nsec3_chain_replay_data { zdb_zone *zone; ptr_set fqdns; ptr_vector del_nsec3_records; ptr_vector add_nsec3_records; ptr_vector del_nsec3_rrsig_records; ptr_vector add_nsec3_rrsig_records; ptr_vector del_nsec3param_records; ptr_vector add_nsec3param_records; }; typedef struct nsec3_chain_replay_data nsec3_chain_replay_data; static void nsec3_chain_replay_record_add_fqdn(nsec3_chain_replay_data *crd, const u8 *fqdn) { ptr_node *node = ptr_set_insert(&crd->fqdns, (u8*)fqdn); if(node->value == NULL) { node->key = dnsname_zdup(fqdn); node->value = node->key; } } static ya_result nsec3_chain_replay_record_del(chain_replay *cr, const u8 *fqdn, u16 rtype, const zdb_ttlrdata *ttlrdata) { yassert((ttlrdata != NULL) || ((ttlrdata == NULL) && (rtype == TYPE_NONE))); nsec3_chain_replay_data *crd = (nsec3_chain_replay_data*)cr->data; #if NSEC3_CHAIN_REPLAY_DEBUG if(ttlrdata != NULL) { rdata_desc type_len_rdata = {rtype, ZDB_RECORD_PTR_RDATASIZE(ttlrdata), ZDB_RECORD_PTR_RDATAPTR(ttlrdata)}; log_debug("nsec3-chain: del %{dnsname} %{typerdatadesc}", fqdn, &type_len_rdata); } else { log_debug("nsec3-chain: del %{dnsname} (fqdn)", fqdn); } #endif switch(rtype) { case TYPE_NSEC3: { ptr_vector_append(&crd->del_nsec3_records, nsec3_chain_replay_record_new(fqdn, TYPE_NSEC3, ttlrdata->ttl, ZDB_RECORD_PTR_RDATAPTR(ttlrdata), ZDB_RECORD_PTR_RDATASIZE(ttlrdata))); return 1; } case TYPE_NSEC3PARAM: { ptr_vector_append(&crd->del_nsec3param_records, nsec3_chain_replay_record_new(fqdn, TYPE_NSEC3PARAM, ttlrdata->ttl, ZDB_RECORD_PTR_RDATAPTR(ttlrdata), ZDB_RECORD_PTR_RDATASIZE(ttlrdata))); nsec3_chain_replay_record_add_fqdn(crd, fqdn); return 0; } case TYPE_RRSIG: { u16 covered_type = GET_U16_AT_P(ZDB_RECORD_PTR_RDATAPTR(ttlrdata)); if(covered_type == TYPE_NSEC3) { ptr_vector_append(&crd->del_nsec3_rrsig_records, nsec3_chain_replay_record_new(fqdn, TYPE_RRSIG, ttlrdata->ttl, ZDB_RECORD_PTR_RDATAPTR(ttlrdata), ZDB_RECORD_PTR_RDATASIZE(ttlrdata))); return 1; } else { nsec3_chain_replay_record_add_fqdn(crd, fqdn); return 0; } } default: { nsec3_chain_replay_record_add_fqdn(crd, fqdn); // this allows to compute links between labels/fqdns and their associated NSEC3 record return 0; } } } static ya_result nsec3_chain_replay_record_add(chain_replay *cr, const u8 *fqdn, u16 rtype, const zdb_ttlrdata *ttlrdata) { yassert((ttlrdata != NULL) || ((ttlrdata == NULL) && (rtype == TYPE_NONE))); nsec3_chain_replay_data *crd = (nsec3_chain_replay_data*)cr->data; #if NSEC3_CHAIN_REPLAY_DEBUG if(ttlrdata != NULL) { rdata_desc type_len_rdata = {rtype, ZDB_RECORD_PTR_RDATASIZE(ttlrdata), ZDB_RECORD_PTR_RDATAPTR(ttlrdata)}; log_debug("nsec3-chain: add %{dnsname} %{typerdatadesc}", fqdn, &type_len_rdata); } else { log_debug("nsec3-chain: add %{dnsname} (fqdn)", fqdn); } #endif switch(rtype) { case TYPE_NSEC3: { ptr_vector_append(&crd->add_nsec3_records, nsec3_chain_replay_record_new(fqdn, TYPE_NSEC3, ttlrdata->ttl, ZDB_RECORD_PTR_RDATAPTR(ttlrdata), ZDB_RECORD_PTR_RDATASIZE(ttlrdata))); return 1; } case TYPE_NSEC3PARAM: { ptr_vector_append(&crd->add_nsec3param_records, nsec3_chain_replay_record_new(fqdn, TYPE_NSEC3PARAM, ttlrdata->ttl, ZDB_RECORD_PTR_RDATAPTR(ttlrdata), ZDB_RECORD_PTR_RDATASIZE(ttlrdata))); nsec3_chain_replay_record_add_fqdn(crd, fqdn); return 0; } case TYPE_RRSIG: { u16 covered_type = GET_U16_AT_P(ZDB_RECORD_PTR_RDATAPTR(ttlrdata)); if(covered_type == TYPE_NSEC3) { ptr_vector_append(&crd->add_nsec3_rrsig_records, nsec3_chain_replay_record_new(fqdn, TYPE_RRSIG, ttlrdata->ttl, ZDB_RECORD_PTR_RDATAPTR(ttlrdata), ZDB_RECORD_PTR_RDATASIZE(ttlrdata))); return 1; } else { nsec3_chain_replay_record_add_fqdn(crd, fqdn); return 0; } } default: { nsec3_chain_replay_record_add_fqdn(crd, fqdn); return 0; } } } static ya_result nsec3_chain_replay_execute(chain_replay *cr) { // sort NSEC3 records by chain,fqdn // verify chains are making sense // remove signatures from the relevant nsec3_zone // remove nodes from the relevant nsec3_zone // add nodes to the relevant nsec3_zone // add signatures to the relevant nsec3_zone // if an nsec3param was removed, choose the new best chain // (start) unlink old chain and add new chain nsec3_chain_replay_data *crd = (nsec3_chain_replay_data*)cr->data; ptr_set del_nsec3_set = PTR_SET_DNSNAME_EMPTY; ptr_set_iterator iter; ya_result ret = SUCCESS; int n; u8 expected_mode = ZDB_ZONE_MAINTAIN_NSEC3; u8 tmp_digest[MAX_DIGEST_LENGTH + 1]; ptr_vector_qsort(&crd->del_nsec3_records, nsec3_chain_replay_record_nsec3_compare); ptr_vector_qsort(&crd->add_nsec3_records, nsec3_chain_replay_record_nsec3_compare); #if NSEC3_CHAIN_REPLAY_DEBUG { log_debug("nsec3-chain: %{dnsname}: replaying:", crd->zone->origin); for(int i = 0; i < ptr_vector_size(&crd->add_nsec3param_records); ++i) { nsec3_chain_replay_record *rr = (nsec3_chain_replay_record*)ptr_vector_get(&crd->add_nsec3param_records, i); format_writer temp_fw_0 = {nsec3_chain_replay_record_format, rr}; log_debug("nsec3-chain: %{dnsname}: NSEC3PARAM-ADD: %w", crd->zone->origin, &temp_fw_0); } for(int i = 0; i < ptr_vector_size(&crd->del_nsec3param_records); ++i) { nsec3_chain_replay_record *rr = (nsec3_chain_replay_record*)ptr_vector_get(&crd->del_nsec3param_records, i); format_writer temp_fw_0 = {nsec3_chain_replay_record_format, rr}; log_debug("nsec3-chain: %{dnsname}: NSEC3PARAM-DEL: %w", crd->zone->origin, &temp_fw_0); } for(int i = 0; i < ptr_vector_size(&crd->del_nsec3_rrsig_records); ++i) { nsec3_chain_replay_record *rr = (nsec3_chain_replay_record*)ptr_vector_get(&crd->del_nsec3_rrsig_records, i); format_writer temp_fw_0 = {nsec3_chain_replay_record_format, rr}; log_debug("nsec3-chain: %{dnsname}: NSEC3-RRSIG-DEL: %w", crd->zone->origin, &temp_fw_0); } for(int i = 0; i < ptr_vector_size(&crd->del_nsec3_records); ++i) { nsec3_chain_replay_record *rr = (nsec3_chain_replay_record*)ptr_vector_get(&crd->del_nsec3_records, i); format_writer temp_fw_0 = {nsec3_chain_replay_record_format, rr}; log_debug("nsec3-chain: %{dnsname}: NSEC3-DEL: %w", crd->zone->origin, &temp_fw_0); } for(int i = 0; i < ptr_vector_size(&crd->add_nsec3_records); ++i) { nsec3_chain_replay_record *rr = (nsec3_chain_replay_record*)ptr_vector_get(&crd->add_nsec3_records, i); format_writer temp_fw_0 = {nsec3_chain_replay_record_format, rr}; log_debug("nsec3-chain: %{dnsname}: NSEC3-ADD: %w", crd->zone->origin, &temp_fw_0); } for(int i = 0; i < ptr_vector_size(&crd->add_nsec3_rrsig_records); ++i) { nsec3_chain_replay_record *rr = (nsec3_chain_replay_record*)ptr_vector_get(&crd->add_nsec3_rrsig_records, i); format_writer temp_fw_0 = {nsec3_chain_replay_record_format, rr}; log_debug("nsec3-chain: %{dnsname}: NSEC3-RRSIG-ADD: %w", crd->zone->origin, &temp_fw_0); } ptr_set_iterator_init(&crd->fqdns, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); log_debug("nsec3-chain: %{dnsname}: FQDN: %{dnsname}", crd->zone->origin, node->value); } } logger_flush(); #endif n = ptr_vector_size(&crd->del_nsec3_records); for(int i = 0; i < n; ++i) { nsec3_chain_replay_record *record = (nsec3_chain_replay_record*)ptr_vector_get(&crd->del_nsec3_records, i); // check the record exists // find the chain // find the record // keep a quick access on the record ptr_node *node = ptr_set_insert(&del_nsec3_set, (u8*)nsec3_chain_replay_record_fqdn(record)); if(node->value == NULL) { node->value = record; #if NSEC3_CHAIN_REPLAY_DEBUG format_writer temp_fw_0 = {nsec3_chain_replay_record_format, record}; #endif nsec3_zone_item *item = nsec3_chain_replay_record_find_item_by_name(crd->zone, record); if(item != NULL) { nsec3_zone_item *next = nsec3_node_mod_next(item); if(memcmp(next->digest, nsec3_chain_replay_record_next_digest(record), next->digest[0] + 1) == 0) { #if NSEC3_CHAIN_REPLAY_DEBUG // match log_debug("nsec3-chain: %{dnsname}: del %w checks out", crd->zone->origin, &temp_fw_0); #endif } else { // nsec3_zone_item *next = nsec3_chain_replay_record_find_item_by_digest(crd->zone, nsec3_chain_replay_record_next_digest(record)); #if NSEC3_CHAIN_REPLAY_DEBUG log_err("nsec3-chain: %{dnsname}: %w is not in the zone: current next is %{digest32h} but expected next is %{digest32h}", crd->zone->origin, &temp_fw_0, next->digest, nsec3_chain_replay_record_next_digest(record)); logger_flush(); #endif ret = DNSSEC_ERROR_NSEC3_INVALIDZONESTATE; // replay delete NSEC3 record does not match current chain } } else { #if NSEC3_CHAIN_REPLAY_DEBUG log_err("nsec3-chain: %{dnsname}: %w is not in the zone: no label", crd->zone->origin, &temp_fw_0); #endif ret = DNSSEC_ERROR_NSEC3_LABELNOTFOUND; // replay delete NSEC3 record of a label not in zone #if NSEC3_CHAIN_REPLAY_DEBUG logger_flush(); #endif } } else { // duplicate : something is wrong log_err("nsec3-chain: %{dnsname}: replay delete %{dnsname} is a duplicate entry in this run", crd->zone->origin, nsec3_chain_replay_record_fqdn(record)); } } n = ptr_vector_size(&crd->add_nsec3_records); for(int i = 0; i < n; ++i) { nsec3_chain_replay_record *record = (nsec3_chain_replay_record*)ptr_vector_get(&crd->add_nsec3_records, i); // find the start of a sub-chain // find the end of the sub-chain // if the sub-chain is not looping, the head must exist (and is being removed/added) // check for updates ptr_node *node = ptr_set_find(&del_nsec3_set, nsec3_chain_replay_record_fqdn(record)); if(node != NULL) { // the record is updated nsec3_chain_replay_record *old_record = (nsec3_chain_replay_record*)node->value; record->status = NSEC3_CHAIN_REPLAY_STATUS_UPDATED; old_record->status = NSEC3_CHAIN_REPLAY_STATUS_UPDATED; } } #if DEBUG // n = ptr_vector_size(&crd->add_nsec3_records); // already done for(int i = 0; i < n; ++i) { nsec3_chain_replay_record *record = (nsec3_chain_replay_record*)ptr_vector_get(&crd->add_nsec3_records, i); nsec3_chain_replay_record *deleted = NULL; // check the next record exist // find the chain // find the record // it must not be deleted ptr_node *node = ptr_set_find(&del_nsec3_set, nsec3_chain_replay_record_fqdn(record)); if(node != NULL) { deleted = (nsec3_chain_replay_record*)node->value; if(deleted->status != NSEC3_CHAIN_REPLAY_STATUS_UPDATED) { // will be deleted } } } #endif // everything checks out : lock the zone for writing n = ptr_vector_size(&crd->del_nsec3_rrsig_records); for(int i = 0; i < n; ++i) { nsec3_chain_replay_record *record = (nsec3_chain_replay_record*)ptr_vector_get(&crd->del_nsec3_rrsig_records, i); nsec3_zone_item *item = nsec3_chain_replay_record_find_item_by_name(crd->zone, record); if(item != NULL) { // remove RRSIG const zdb_ttlrdata nsec3_rrsig = { NULL, record->ttl, record->rdata_size, 0, (u8*)nsec3_chain_replay_record_rdata(record) }; nsec3_zone_item_rrsig_del(item, &nsec3_rrsig); continue; } #if NSEC3_CHAIN_REPLAY_DEBUG yassert(record->rtype == TYPE_RRSIG); #endif rdata_desc type_len_rdata = {TYPE_RRSIG, record->rdata_size, nsec3_chain_replay_record_rdata(record)}; log_warn("nsec3-chain: - %{dnsname} %{typerdatadesc} failed", nsec3_chain_replay_record_fqdn(record), &type_len_rdata); } n = ptr_vector_size(&crd->del_nsec3_records); for(int i = 0; i < n; ++i) { nsec3_chain_replay_record *record = (nsec3_chain_replay_record*)ptr_vector_get(&crd->del_nsec3_records, i); if(record->status == 0) { // nsec3_zone *n3 = nsec3_chain_replay_record_find_chain(crd->zone, record); // remove the record from n3 #if NSEC3_CHAIN_REPLAY_DEBUG const rdata_desc type_len_rdata = { TYPE_NSEC3, record->rdata_size, nsec3_chain_replay_record_rdata(record) }; log_debug("nsec3-chain: - %{dnsname} %{typerdatadesc}", nsec3_chain_replay_record_fqdn(record), &type_len_rdata); #endif nsec3_zone *n3 = nsec3_chain_replay_record_find_chain(crd->zone, record); if(n3 != NULL) { const u8 *record_fqdn = nsec3_chain_replay_record_fqdn(record); yassert(record_fqdn != NULL); ya_result digest_len = base32hex_decode( (char*)&record_fqdn[1], (u32)record_fqdn[0], &tmp_digest[1]); yassert((digest_len >= 0) && ((u32)digest_len < sizeof(tmp_digest) - 1)); tmp_digest[0] = digest_len; nsec3_zone_item *item = nsec3_find(&n3->items, tmp_digest); if(item != NULL) { // detach all RC and SC // RC ... nsec3_item_remove_all_owners(item); // SC ... // all the removed stars should be moved to the pred nsec3_node *prev = nsec3_node_mod_prev(item); if((prev != NULL) && (prev != item)) { nsec3_item_move_all_star_to_nsec3_item(item, prev); } else // if the chain is one node long or something is wrong, just drop the stars { nsec3_item_remove_all_star(item); } nsec3_delete(&n3->items, tmp_digest); if(n3->items == NULL) { // remove the chain log_info("%{dnsname} NSEC3 chain emptied", crd->zone->origin); if(n3->next != NULL) { nsec3_zone_detach(crd->zone, n3); nsec3_zone_free(n3); } } } else { log_warn("nsec3-chain: - %{dnsname} NSEC3 not found", record_fqdn); } } } else // else the record is being updated { // this means that potentially all "stars" will be wrong } } n = ptr_vector_size(&crd->add_nsec3_records); for(int i = 0; i < n; ++i) { nsec3_chain_replay_record *record = (nsec3_chain_replay_record*)ptr_vector_get(&crd->add_nsec3_records, i); nsec3_zone *n3 = nsec3_chain_replay_record_find_chain(crd->zone, record); if(n3 == NULL) { // create the new chain n3 = nsec3_chain_replay_record_add_chain(crd->zone, record); } if(record->status == 0) { // insert the new record #if NSEC3_CHAIN_REPLAY_DEBUG const rdata_desc type_len_rdata = { TYPE_NSEC3, record->rdata_size, (u8*)nsec3_chain_replay_record_rdata(record) }; log_debug("nsec3-chain: + %{dnsname} %{typerdatadesc}", nsec3_chain_replay_record_fqdn(record), &type_len_rdata); #endif const u8 *record_fqdn = nsec3_chain_replay_record_fqdn(record); ya_result digest_len = base32hex_decode( (char*)&record_fqdn[1], (u32)record_fqdn[0], &tmp_digest[1]); if(FAIL(digest_len)) { log_err("nsec3-chain: %{dnsname}: failed to decode base32hex: %r", crd->zone->origin, digest_len); log_err("nsec3-chain: %{dnsname}: there may be a corruption somewhere (file, disk, ram, network, master, ...)", crd->zone->origin); ret = DNSSEC_ERROR_NSEC3_LABELTODIGESTFAILED; // replay NSEC3 fqdn base32hex cannot be decoded logger_flush(); goto nsec3_chain_replay_execute_exit; // goto, that's how bad it is } yassert((digest_len >= 0) && ((u32)digest_len < sizeof(tmp_digest) - 1)); const u8 *rdata = nsec3_chain_replay_record_rdata(record); if(rdata[1] != 0) { expected_mode |= ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT; } tmp_digest[0] = digest_len; nsec3_zone_item *item = nsec3_insert(&n3->items, tmp_digest); //item-> nsec3_zone_item_update_bitmap(item, nsec3_chain_replay_record_rdata(record), record->rdata_size); item->flags = rdata[1]; // for all fqdns, find the one(s) matching this and link its label // look for the pred of item, and move relevant *.fqdn to item // // This is done later (fqdn iteration) } else { const u8 *rdata = nsec3_chain_replay_record_rdata(record); #if NSEC3_CHAIN_REPLAY_DEBUG rdata_desc type_len_rdata = { TYPE_NSEC3, record->rdata_size, rdata }; log_debug("nsec3-chain: ~ %{dnsname} %{typerdatadesc}", nsec3_chain_replay_record_fqdn(record), &type_len_rdata); #endif // update the old record : this doesn't update the links nsec3_zone_item *item = nsec3_zone_item_find_by_name(n3, nsec3_chain_replay_record_fqdn(record)); if(item != NULL) { nsec3_zone_item_update_bitmap(item, nsec3_chain_replay_record_rdata(record), record->rdata_size); item->flags = rdata[1]; nsec3_item_remove_all_star(item); } else { rdata_desc type_len_rdata = { TYPE_NSEC3, record->rdata_size, rdata }; log_warn("nsec3-chain: ~ %{dnsname} %{typerdatadesc} cannot be edited as it's not in the database.", nsec3_chain_replay_record_fqdn(record), &type_len_rdata); } } } n = ptr_vector_size(&crd->add_nsec3_rrsig_records); for(int i = 0; i < n; ++i) { nsec3_chain_replay_record *record = (nsec3_chain_replay_record*)ptr_vector_get(&crd->add_nsec3_rrsig_records, i); nsec3_zone_item *item = nsec3_chain_replay_record_find_item_by_name(crd->zone, record); if(item != NULL) { // remove RRSIG zdb_packed_ttlrdata* nsec3_rrsig; ZDB_RECORD_ZALLOC(nsec3_rrsig,record->ttl,record->rdata_size,nsec3_chain_replay_record_rdata(record)); nsec3_rrsig->next = NULL; nsec3_zone_item_rrsig_add(item, nsec3_rrsig); continue; } const rdata_desc type_len_rdata = {TYPE_RRSIG, record->rdata_size, nsec3_chain_replay_record_rdata(record)}; log_warn("nsec3-chain: + %{dnsname} %{typerdatadesc} failed", nsec3_chain_replay_record_fqdn(record), &type_len_rdata); } // if an nsec3param just appeared, generate the chain if it's the first/only one // check if the addition of the chain needs to be triggered if(ptr_vector_last_index(&crd->add_nsec3param_records) >= 0) { // this triggers addition of the chain log_debug("nsec3-chain: %{dnsname}: NSEC3PARAM added", crd->zone->origin); } // if there is an active chain, and crd->fqdns is not empty : link the chain nsec3_zone *n3 = crd->zone->nsec.nsec3; if(n3 != NULL) { ptr_set_iterator_init(&crd->fqdns, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); const u8 *fqdn = (const u8*)node->key; // this FQDN link can be updated (void)fqdn; // get the label zdb_rr_label_find_from_name_delete_empty_terminal(crd->zone, fqdn); } } nsec3_chain_replay_execute_exit: if(crd->zone->nsec.nsec3 != NULL) { zdb_rr_label_flag_or(crd->zone->apex, ZDB_RR_LABEL_N3OCOVERED|ZDB_RR_LABEL_N3COVERED); u8 maintain_mode = zone_get_maintain_mode(crd->zone) | expected_mode; u16 coverage_mask = (maintain_mode == ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT)?ZDB_RR_LABEL_N3OCOVERED:((maintain_mode == ZDB_ZONE_MAINTAIN_NSEC3)?ZDB_RR_LABEL_N3COVERED:0); int n3_count = 1; { const nsec3_zone *n3 = crd->zone->nsec.nsec3->next; while(n3 != NULL) { ++n3_count; n3 = n3->next; } } nsec3_zone_label_update_chain_links(crd->zone->nsec.nsec3, crd->zone->apex, n3_count, coverage_mask, crd->zone->origin); ptr_set_iterator_init(&crd->fqdns, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); const u8 *fqdn = (const u8*)node->key; zdb_rr_label *labels[64]; const u8 *sub_fqdn[64]; int n = zdb_rr_label_find_path_from_name(crd->zone, fqdn, labels); if(n > 0) { { const u8 *p = fqdn; for(int i = n - 1; i >= 0; --i) { sub_fqdn[i] = p; p += *p + 1; } } #if DEBUG log_debug("nsec3-chain: %{dnsname}: %{dnsname} will have %i label(s) updated", crd->zone->origin, fqdn, n); #endif for(int i = 0; i < n; ++i) { zdb_rr_label *label = labels[i]; #if DEBUG log_debug("nsec3-chain: %{dnsname}: %{dnsname} label %i %{dnslabel} starts with %04x", crd->zone->origin, fqdn, i, label->name, zdb_rr_label_flag_get(label)); #endif if(!RR_LABEL_EMPTY_TERMINAL(label)) { // evaluate N3COVERED and N3OCOVERED if(ZDB_LABEL_ATORUNDERDELEGATION(label)) { if(!ZDB_LABEL_UNDERDELEGATION(label)) { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED); if(zdb_rr_label_has_rrset(label, TYPE_DS)) { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3OCOVERED); // at opt-out delegation } else { zdb_rr_label_flag_and(label, ~ZDB_RR_LABEL_N3OCOVERED); // not at opt-out delegation (anymore) } } else { zdb_rr_label_flag_and(label, ~(ZDB_RR_LABEL_N3COVERED|ZDB_RR_LABEL_N3OCOVERED)); // under delegation /* zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED); // under delegation zdb_rr_label_flag_and(label->flags, ~ZDB_RR_LABEL_N3OCOVERED); // under delegation */ } } else { zdb_rr_label_flag_or(label, ZDB_RR_LABEL_N3COVERED|ZDB_RR_LABEL_N3OCOVERED); // above delegation } #if DEBUG log_debug("nsec3-chain: %{dnsname}: %{dnsname} label %i %{dnslabel} stalls at %04x before doing the linking", crd->zone->origin, fqdn, i, label->name, zdb_rr_label_flag_get(label)); #endif if((maintain_mode == ZDB_ZONE_MAINTAIN_NSEC3) || (maintain_mode == ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT)) { nsec3_zone_label_update_chain_links(crd->zone->nsec.nsec3, label, n3_count, coverage_mask, sub_fqdn[i]); } #if DEBUG log_debug("nsec3-chain: %{dnsname}: %{dnsname} label %i %{dnslabel} ends with %04x", crd->zone->origin, fqdn, i, label->name, zdb_rr_label_flag_get(label)); #endif } else // something very wrong happened { log_debug("nsec3-chain: %{dnsname}: something wrong happened deleting %{dnsname}", crd->zone->origin, fqdn); } } } else { nsec3_zone_label_update_chain_links(crd->zone->nsec.nsec3, crd->zone->apex, n3_count, coverage_mask, fqdn); } } } if(ptr_vector_last_index(&crd->add_nsec3param_records) >= 0) { nsec3_zone_update_chain0_links(crd->zone); } // unlock the zone for writing ptr_set_destroy(&del_nsec3_set); ptr_vector_callback_and_clear(&crd->del_nsec3_records, nsec3_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->add_nsec3_records, nsec3_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->del_nsec3_rrsig_records, nsec3_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->add_nsec3_rrsig_records, nsec3_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->del_nsec3param_records, nsec3_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->add_nsec3param_records, nsec3_chain_replay_record_delete_cb); ptr_set_callback_and_destroy(&crd->fqdns, nsec3_chain_replay_fqdn_key_delete); return ret; } static void nsec3_chain_replay_finalize(chain_replay *cr) { nsec3_chain_replay_data *crd = (nsec3_chain_replay_data*)cr->data; ptr_vector_callback_and_clear(&crd->del_nsec3_records, nsec3_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->add_nsec3_records, nsec3_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->del_nsec3_rrsig_records, nsec3_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->add_nsec3_rrsig_records, nsec3_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->del_nsec3param_records, nsec3_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->add_nsec3param_records, nsec3_chain_replay_record_delete_cb); ptr_vector_destroy(&crd->del_nsec3_records); ptr_vector_destroy(&crd->add_nsec3_records); ptr_vector_destroy(&crd->del_nsec3_rrsig_records); ptr_vector_destroy(&crd->add_nsec3_rrsig_records); ptr_vector_destroy(&crd->del_nsec3param_records); ptr_vector_destroy(&crd->add_nsec3param_records); ptr_set_callback_and_destroy(&crd->fqdns, nsec3_chain_replay_fqdn_key_delete); zdb_zone_release(crd->zone); crd->zone = NULL; // release memory ZFREE_OBJECT(crd); cr->data = NULL; } static const struct chain_replay_vtbl nsec3_chain_replay_vtbl = { nsec3_chain_replay_record_add, nsec3_chain_replay_record_del, nsec3_chain_replay_execute, nsec3_chain_replay_finalize, "nsec3_chain_replay" }; ya_result nsec3_chain_replay_init(chain_replay *cr, zdb_zone *zone) { nsec3_chain_replay_data *data; ZALLOC_OBJECT_OR_DIE(data, nsec3_chain_replay_data, NSEC3RPL_TAG); data->fqdns.root = NULL; data->fqdns.compare = ptr_set_dnsname_node_compare; ptr_vector_init(&data->del_nsec3_records); ptr_vector_init(&data->add_nsec3_records); ptr_vector_init(&data->del_nsec3_rrsig_records); ptr_vector_init(&data->add_nsec3_rrsig_records); ptr_vector_init(&data->del_nsec3param_records); ptr_vector_init(&data->add_nsec3param_records); zdb_zone_acquire(zone); data->zone = zone; cr->vtbl = &nsec3_chain_replay_vtbl; cr->data = data; return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec3_load.c0000644000000000000000000000013114505005531021141 xustar000000000000000029 mtime=1695812441.69597149 30 atime=1695812445.800030268 30 ctime=1695812495.188737613 yadifa-2.6.5-11201/lib/dnsdb/src/nsec3_load.c0000664000374500037450000013103714505005531021111 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #define DEBUG_LEVEL 0 #include #include #include #include "dnsdb/dnssec.h" #include "dnsdb/nsec3_load.h" #include "dnsdb/nsec3_zone.h" #include "dnsdb/zdb_zone_label_iterator.h" #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; #define N3CHNCTX_TAG 0x5854434e4843334e #define N3PRDATA_TAG 0x415441445250334e #define N3LCTXRR_TAG 0x52525854434c334e #define N3LCTXCN_TAG 0x434e5854434c334e #define N3LKEYDG_TAG 0x474459454b4c334e /* ;; Owner: mejnertsen 4Q9DAPPUSCM8987DU4UL56CF2O5S0CNO.eu. 600 NSEC3 1 1 1 5ca1ab1e 4Q9DE8JTV8EA3H4IP8KC33F1RJK45SD1 RRSIG NSEC3 8 2 600 20181020080859 20180919080849 37080 eu. urzQ7qjZ5L+F0pEykY/IN5XHuwb5+iwqxz */ /****************************************************************************** * * NSEC3 - load (ie: from zone file / axfr / ...) * *****************************************************************************/ struct nsec3_context_record { zdb_packed_ttlrdata *rrsig; s32 ttl; u16 rdata_size; u8 digest_then_rdata[]; }; typedef struct nsec3_context_record nsec3_context_record; struct nsec3_load_context_chain { ptr_vector nsec3_added; // array of full of records u16 nsec3param_rdata_size; bool has_nsec3param; u8 nsec3param_rdata[]; }; typedef struct nsec3_load_context_chain nsec3_load_context_chain; static void nsec3_load_context_record_delete_rrsig(nsec3_context_record *r) { zdb_packed_ttlrdata *rrsig = r->rrsig; while(rrsig != NULL) { zdb_packed_ttlrdata *next = rrsig->next; ZDB_RECORD_ZFREE(rrsig); rrsig = next; } r->rrsig = NULL; } static void nsec3_load_context_record_delete(nsec3_context_record *r) { zdb_packed_ttlrdata *rrsig = r->rrsig; while(rrsig != NULL) { zdb_packed_ttlrdata *next = rrsig->next; ZDB_RECORD_ZFREE(rrsig); rrsig = next; } size_t nsec3_context_record_size = sizeof(nsec3_context_record) + 1 + r->digest_then_rdata[0] + r->rdata_size; #if DEBUG memset(r, 0xfe, nsec3_context_record_size); #endif ZFREE_ARRAY(r, nsec3_context_record_size); } static nsec3_context_record* nsec3_load_context_record_new(const u8 *base32hex_digest, s32 ttl, const u8 *rdata, u16 rdata_size) { u8 digest_len = BASE32HEX_DECODED_LEN(base32hex_digest[0]); nsec3_context_record *record; ZALLOC_ARRAY_OR_DIE(nsec3_context_record*, record, sizeof(nsec3_context_record) + 1 + digest_len + rdata_size, N3LCTXRR_TAG); record->rrsig = NULL; record->ttl = ttl; record->rdata_size = rdata_size; // memcpy(&record->digest_then_rdata[0], digest, digest_len); record->digest_then_rdata[0] = digest_len; if(ISOK(base32hex_decode((const char*)&base32hex_digest[1], base32hex_digest[0], &record->digest_then_rdata[1]))) { memcpy(&record->digest_then_rdata[digest_len + 1], rdata, rdata_size); return record; } else { nsec3_load_context_record_delete(record); return NULL; } } static nsec3_context_record* nsec3_load_context_record_new_binary(const u8 *binary_digest, s32 ttl, u16 rdata_size) { u8 digest_len = binary_digest[0]; nsec3_context_record *record; ZALLOC_ARRAY_OR_DIE(nsec3_context_record*, record, sizeof(nsec3_context_record) + 1 + digest_len + rdata_size, N3LCTXRR_TAG); record->rrsig = NULL; record->ttl = ttl; record->rdata_size = rdata_size; record->digest_then_rdata[0] = digest_len; memcpy(record->digest_then_rdata, binary_digest, digest_len + 1); #if DEBUG memset(&record->digest_then_rdata[digest_len + 1], 0xff, rdata_size); #endif return record; } static void nsec3_load_context_record_delete_void(void *r) { nsec3_load_context_record_delete((nsec3_context_record*)r); } static const u8* nsec3_load_context_record_rdata(const nsec3_context_record *r) { size_t digest_len = 1 + r->digest_then_rdata[0]; return &r->digest_then_rdata[digest_len]; } static const u8* nsec3_load_context_record_next_digest(const nsec3_context_record *r) { const u8 *rdata = nsec3_load_context_record_rdata(r); size_t nsec3param_size = NSEC3PARAM_RDATA_SIZE_FROM_RDATA(rdata); return &rdata[nsec3param_size]; } static int nsec3_load_context_record_qsort_callback(const void *a, const void *b) { const nsec3_context_record *ra = (nsec3_context_record*)a; const nsec3_context_record *rb = (nsec3_context_record*)b; int ra_size = ra->digest_then_rdata[0]; int rb_size = rb->digest_then_rdata[0]; int d = ra_size - rb_size; if(d == 0) { d = memcmp(ra->digest_then_rdata, rb->digest_then_rdata, ra_size + 1); } return d; } static bool nsec3_load_context_record_linked(const nsec3_context_record *ra, const nsec3_context_record *rb) { const u8 *next_digest = nsec3_load_context_record_next_digest(ra); int next_size = next_digest[0]; int size = rb->digest_then_rdata[0]; if(next_size == size) { return memcmp(&next_digest[1], &rb->digest_then_rdata[1], size) == 0; } return FALSE; } static nsec3_load_context_chain* nsec3_load_context_chain_new(nsec3_context_record *r) { nsec3_load_context_chain *chain; const u8 *nsec3param_rdata = nsec3_load_context_record_rdata(r); size_t nsec3param_size = NSEC3PARAM_RDATA_SIZE_FROM_RDATA(nsec3param_rdata); ZALLOC_ARRAY_OR_DIE(nsec3_load_context_chain*, chain, sizeof(nsec3_load_context_chain) + nsec3param_size, N3LCTXCN_TAG); ZEROMEMORY(chain, sizeof(nsec3_load_context_chain)); ptr_vector_init_ex(&chain->nsec3_added, 65536); chain->nsec3param_rdata_size = nsec3param_size; memcpy(chain->nsec3param_rdata, nsec3param_rdata, nsec3param_size); #if DEBUG log_debug("nsec3_load_context_chain_new(%p) -> (%p, %p)", r, chain, chain->nsec3_added.data); #endif return chain; } static void nsec3_load_context_chain_delete(nsec3_load_context_chain *chain) { #if DEBUG log_debug("nsec3_load_context_chain_delete(%p) -> (%p)", chain, chain->nsec3_added.data); #endif ptr_vector_callback_and_destroy(&chain->nsec3_added, nsec3_load_context_record_delete_void); ZFREE_ARRAY(chain, sizeof(nsec3_load_context_chain) + chain->nsec3param_rdata_size); } static void nsec3_load_context_chain_add_nsec3(nsec3_load_context_chain *chain, nsec3_context_record *r) { ptr_vector_append(&chain->nsec3_added, r); } static int nsec3_load_context_chain_qsort_callback(const void *a, const void *b) { const nsec3_load_context_chain *ca = (nsec3_load_context_chain*)a; const nsec3_load_context_chain *cb = (nsec3_load_context_chain*)b; int d = (ca->has_nsec3param?1:0) - (cb->has_nsec3param?1:0); if(d == 0) { d = ca->nsec3param_rdata_size - cb->nsec3param_rdata_size; if(d == 0) { d = memcmp(ca->nsec3param_rdata, cb->nsec3param_rdata, ca->nsec3param_rdata_size); } } return d; } static bool nsec3_load_context_chain_matches(nsec3_load_context_chain *chain, const u8 *rdata, u16 rdata_size) { if((chain->nsec3param_rdata_size <= rdata_size) && (chain->nsec3param_rdata[0] == rdata[0])) { if(memcmp(&chain->nsec3param_rdata[2], &rdata[2], chain->nsec3param_rdata_size - 2) == 0) { return TRUE; } } return FALSE; } static nsec3_load_context_chain* nsec3_load_context_get_chain(nsec3_load_context *context, nsec3_context_record *r) { // ptr_node *r_node = ptr_set_insert(&context->nsec3chain, r); for(int i = 0; i <= ptr_vector_last_index(&context->nsec3chain); ++i) { nsec3_load_context_chain *chain = (nsec3_load_context_chain*)ptr_vector_get(&context->nsec3chain, i); if(nsec3_load_context_chain_matches(chain, nsec3_load_context_record_rdata(r), r->rdata_size)) { return chain; } } nsec3_load_context_chain *chain = nsec3_load_context_chain_new(r); ptr_vector_append(&context->nsec3chain, chain); return chain; } static int nsec3_load_postponed_rrsig_node_compare(const void *node_a, const void *node_b) { const u8 *key_a = (const u8*)node_a; const u8 *key_b = (const u8*)node_b; int d = key_a[0]; d -= key_b[0]; if(d == 0) { d = memcmp(&key_a[1], &key_b[1], key_a[0]); } return d; } ya_result nsec3_load_init(nsec3_load_context *context, zdb_zone* zone) { ZEROMEMORY(context, sizeof(nsec3_load_context)); ptr_vector_init_ex(&context->nsec3chain, 2); ptr_set_init(&context->postponed_rrsig); context->postponed_rrsig.compare = nsec3_load_postponed_rrsig_node_compare; context->zone = zone; context->opt_out = TRUE; return SUCCESS; } void nsec3_load_destroy_nsec3chain_cb(void *ptr) { nsec3_load_context_chain *chain = (nsec3_load_context_chain*)ptr; nsec3_load_context_chain_delete(chain); } void nsec3_load_destroy(nsec3_load_context *context) { ptr_vector_callback_and_destroy(&context->nsec3chain, nsec3_load_destroy_nsec3chain_cb); if(!ptr_set_isempty(&context->postponed_rrsig)) { ptr_set_iterator iter; ptr_set_iterator_init(&context->postponed_rrsig, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *rrsig_node = ptr_set_iterator_next_node(&iter); if(rrsig_node->key != NULL) { u8 *key = (u8*)rrsig_node->key; ZFREE_ARRAY(rrsig_node->key, key[0] + 1); (void)key; // silence warning in some build settings } rrsig_node->key = NULL; rrsig_node->value = NULL; } ptr_set_destroy(&context->postponed_rrsig); } context->zone = NULL; } ya_result nsec3_load_add_nsec3param(nsec3_load_context *context, const u8 *rdata, u16 rdata_size) { if((rdata_size < 5) || (NSEC3_RDATA_ALGORITHM(rdata) != NSEC3_DIGEST_ALGORITHM_SHA1)) { return DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM; } nsec3_context_record* nsec3param_r = nsec3_load_context_record_new((const u8*)"", 0, rdata, rdata_size); nsec3_load_context_chain* chain = nsec3_load_context_get_chain(context, nsec3param_r); nsec3_load_context_record_delete(nsec3param_r); chain->has_nsec3param = TRUE; return SUCCESS; } // TYPE_NSEC3CHAINSTATE ya_result nsec3_load_add_nsec3chainstate(nsec3_load_context *context, const u8 *rdata, u16 rdata_size) { if((rdata_size < 5) || (NSEC3_RDATA_ALGORITHM(rdata) != NSEC3_DIGEST_ALGORITHM_SHA1)) { return DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM; } nsec3_context_record* nsec3param_r = nsec3_load_context_record_new((const u8*)"", 0, rdata, rdata_size); nsec3_load_context_chain* chain = nsec3_load_context_get_chain(context, nsec3param_r); nsec3_load_context_record_delete(nsec3param_r); chain->has_nsec3param = FALSE; return SUCCESS; } ya_result nsec3_load_add_nsec3(nsec3_load_context *context, const u8 *base32hex_digest, s32 ttl, const u8 *rdata, u16 rdata_size) { /* * Get the right chain from the rdata * Add the record to the chain */ if((rdata_size < 5) || (NSEC3_RDATA_ALGORITHM(rdata) != NSEC3_DIGEST_ALGORITHM_SHA1)) { return DNSSEC_ERROR_UNSUPPORTEDDIGESTALGORITHM; } nsec3_context_record* nsec3_r = nsec3_load_context_record_new(base32hex_digest, ttl, rdata, rdata_size); if(nsec3_r != NULL) { nsec3_load_context_chain* chain = nsec3_load_context_get_chain(context, nsec3_r); nsec3_load_context_chain_add_nsec3(chain, nsec3_r); context->last_inserted_nsec3 = nsec3_r; if(!ptr_set_isempty(&context->postponed_rrsig)) { ptr_node *node = ptr_set_find(&context->postponed_rrsig, nsec3_r->digest_then_rdata); if(node != NULL) { u8 *key = node->key; nsec3_r->rrsig = (zdb_packed_ttlrdata*)node->value; ptr_set_delete(&context->postponed_rrsig, nsec3_r->digest_then_rdata); ZFREE_ARRAY(key, key[0] + 1); } } return SUCCESS; } else { context->last_inserted_nsec3 = NULL; return DNSSEC_ERROR_NSEC3_LABELTODIGESTFAILED; } } ya_result nsec3_load_add_rrsig(nsec3_load_context *context, const u8 *digest_label, s32 ttl, const u8 *rdata, u16 rdata_size) { u8 digest_len = BASE32HEX_DECODED_LEN(digest_label[0]); #if C11_VLA_AVAILABLE u8 digest[digest_len + 1]; #else u8 * const digest = (u8*const)stack_alloc(digest_len + 1); #endif digest[0] = digest_len; if(ISOK(base32hex_decode((const char*)&digest_label[1], digest_label[0], &digest[1]))) { zdb_packed_ttlrdata *rrsig; ZDB_RECORD_ZALLOC(rrsig,ttl,rdata_size,rdata); if(context->last_inserted_nsec3 != NULL) { nsec3_context_record* nsec3_r = (nsec3_context_record*)context->last_inserted_nsec3; if(memcmp(nsec3_r->digest_then_rdata, digest, 1 + digest[0]) == 0) { rrsig->next = nsec3_r->rrsig; nsec3_r->rrsig = rrsig; return SUCCESS; } } // the records are not nicely ordered : need to postpone the insertion of this record. ptr_node *node = ptr_set_insert(&context->postponed_rrsig, digest); if(node->value == NULL) { u8 *key; ZALLOC_ARRAY_OR_DIE(u8*, key, digest_len + 1, N3LKEYDG_TAG); memcpy(key, digest, digest_len + 1); node->key = key; } rrsig->next = (zdb_packed_ttlrdata*)node->value; node->value = rrsig; return SUCCESS; } else { return DNSSEC_ERROR_NSEC3_LABELTODIGESTFAILED; } } static int nsec3_load_fix_chain_search_cb(const void *key, const void *item) { const u8 *digest = (const u8*)key; nsec3_context_record *nsec3_record = (nsec3_context_record*)item; int ret = memcmp(digest, nsec3_record->digest_then_rdata, digest[0] + 1); return ret; } bool nsec3_load_is_label_covered(zdb_rr_label *label) { return !ZDB_LABEL_UNDERDELEGATION(label); } bool nsec3_load_is_label_covered_optout(zdb_rr_label *label) { if(!ZDB_LABEL_ATORUNDERDELEGATION(label)) // includes APEX { return TRUE; } if(ZDB_LABEL_ATDELEGATION(label)) { return zdb_rr_label_get_rrset(label, TYPE_DS) != NULL; } return FALSE; } /** * Fixes extraneous NSEC3 records in chain. * * @returns TRUE iff the chain had no extraneous records; */ static bool nsec3_load_find_extranous_records_in_chain(nsec3_load_context *context, nsec3_load_context_chain *chain) { // for all labels // check if the label should be covered by an NSEC3 // compute the digest // seek for the digest // if not missing // mark the entry to tell it's covering something // // for all digests // if the entry is not used, remove it nsec3_hash_function *hash_function; u8 *salt; nsec3_load_is_label_covered_function *is_covered; s32 min_ttl = context->zone->min_ttl; u32 nsec3_correction_count = 0; u16 hash_iterations; u16 nsec3param_rdata_size; u8 salt_len; u8 digest_len; bool fix_required; zdb_zone_label_iterator iter; u8 digest[64]; u8 fqdn[MAX_DOMAIN_LENGTH + 1]; u8 optout_byte; digest_len = digest[0] = nsec3_hash_len(NSEC3PARAM_RDATA_ALGORITHM(chain->nsec3param_rdata)); hash_function = nsec3_hash_get_function(NSEC3PARAM_RDATA_ALGORITHM(chain->nsec3param_rdata)); salt = NSEC3PARAM_RDATA_SALT(chain->nsec3param_rdata); salt_len = NSEC3PARAM_RDATA_SALT_LEN(chain->nsec3param_rdata); hash_iterations = NSEC3PARAM_RDATA_ITERATIONS(chain->nsec3param_rdata); nsec3param_rdata_size = NSEC3PARAM_MINIMUM_LENGTH + salt_len; fix_required = FALSE; if(context->opt_out) { is_covered = nsec3_load_is_label_covered_optout; optout_byte = 1; } else { is_covered = nsec3_load_is_label_covered; optout_byte = 0; } // find and mark all covered labels, the non-marked ones will be removed zdb_zone_label_iterator_init(&iter, context->zone); while(zdb_zone_label_iterator_hasnext(&iter)) { u32 fqdn_len = zdb_zone_label_iterator_nextname(&iter, fqdn); zdb_rr_label* label = zdb_zone_label_iterator_next(&iter); if(is_covered(label)) // note: is_covered is a local variable pointing to the relevant function { // should be covered hash_function( fqdn, fqdn_len, salt, salt_len, hash_iterations, &digest[1], FALSE); // digest exists ? // nsec3 missing: generate the type bitmap and make an rdata with an nsec3 digest type_bit_maps_context bitmap; u16 bitmap_size = zdb_rr_label_bitmap_type_init(label, &bitmap); u16 rdata_size_pre_bitmap = nsec3param_rdata_size + 1 + digest_len; u16 rdata_size = rdata_size_pre_bitmap + bitmap_size; nsec3_context_record* expected_nsec3_record = nsec3_load_context_record_new_binary(digest, min_ttl, rdata_size); u8 *rdata = &expected_nsec3_record->digest_then_rdata[digest_len + 1]; memcpy(rdata, chain->nsec3param_rdata, nsec3param_rdata_size); rdata[1] = optout_byte; type_bit_maps_write(&bitmap, &rdata[nsec3param_rdata_size + 1 + digest_len]); type_bit_maps_finalize(&bitmap); s32 match_index = ptr_vector_search_index(&chain->nsec3_added, digest, nsec3_load_fix_chain_search_cb); void *match; if((match_index >= 0) && ((match = ptr_vector_get(&chain->nsec3_added, match_index)) != NULL)) { // found /*nsec3_context_record *nsec3_record = (nsec3_context_record*)match; assert(nsec3_record->ttl >= 0); nsec3_record->ttl = -nsec3_record->ttl; */ bool nsec3_matches = FALSE; nsec3_context_record *nsec3_record = (nsec3_context_record*)match; if(nsec3_record->rdata_size == expected_nsec3_record->rdata_size) { if(memcmp(&nsec3_record->digest_then_rdata[digest_len + 1 + rdata_size_pre_bitmap], &expected_nsec3_record->digest_then_rdata[digest_len + 1 + rdata_size_pre_bitmap], bitmap_size) == 0) { nsec3_matches = TRUE; } } if(nsec3_matches) { nsec3_load_context_record_delete(expected_nsec3_record); nsec3_record->ttl = - nsec3_record->ttl; } else { ++nsec3_correction_count; #if !DEBUG log_debug("zone load: %{dnsname}: nsec3: %{digest32h}.%{dnsname} has mismatched bitmap: fixed (%{dnsname})", context->zone->origin, nsec3_record->digest_then_rdata, context->zone->origin, fqdn); #else log_warn("zone load: %{dnsname}: nsec3: %{digest32h}.%{dnsname} has mismatched bitmap: fixed (%{dnsname})", context->zone->origin, nsec3_record->digest_then_rdata, context->zone->origin, fqdn); log_warn("zone load: %{dnsname}: nsec3: %{digest32h}.%{dnsname} expected: (DEBUG)", context->zone->origin, nsec3_record->digest_then_rdata, context->zone->origin); log_memdump(MODULE_MSG_HANDLE, MSG_WARNING, &expected_nsec3_record->digest_then_rdata[digest_len + 1 + rdata_size_pre_bitmap], bitmap_size, 32); log_warn("zone load: %{dnsname}: nsec3: %{digest32h}.%{dnsname} got: (DEBUG)", context->zone->origin, nsec3_record->digest_then_rdata, context->zone->origin); log_memdump(MODULE_MSG_HANDLE, MSG_WARNING, &nsec3_record->digest_then_rdata[digest_len + 1 + rdata_size_pre_bitmap], bitmap_size, 32); #endif memcpy(&expected_nsec3_record->digest_then_rdata[digest_len + 1 + nsec3param_rdata_size], &nsec3_record->digest_then_rdata[digest_len + 1 + nsec3param_rdata_size], digest_len + 1); nsec3_load_context_record_delete_rrsig(expected_nsec3_record); ptr_vector_set(&chain->nsec3_added, match_index, expected_nsec3_record); nsec3_load_context_record_delete(nsec3_record); expected_nsec3_record->ttl = - expected_nsec3_record->ttl; fix_required = TRUE; } } else { // will be trashed log_warn("zone load: %{dnsname}: nsec3: %{digest32h}.%{dnsname} covering %{dnsname} not found in chain", context->zone->origin, digest, context->zone->origin, fqdn); #if DEBUG log_warn("zone load: %{dnsname}: nsec3: %{digest32h}.%{dnsname} covering %{dnsname}: label flags=%04x, is_covered=%i at_or_under_delegation=%i, at_delegation=%i (DEBUG)", context->zone->origin, digest, context->zone->origin, fqdn, zdb_rr_label_flag_get(label), (int)is_covered(label), (int)ZDB_LABEL_ATORUNDERDELEGATION(label), (int)ZDB_LABEL_ATDELEGATION(label)); #endif nsec3_load_context_record_delete(expected_nsec3_record); } } } int warning_quota = 1000; // remove unused and replace them by missing (if any) int last_good = -1; for(int i = 0; i <= ptr_vector_last_index(&chain->nsec3_added); ++i) { nsec3_context_record *nsec3_record = (nsec3_context_record*)ptr_vector_get(&chain->nsec3_added, i); if(nsec3_record->ttl < 0) { nsec3_record->ttl = -nsec3_record->ttl; ++last_good; ptr_vector_set(&chain->nsec3_added, last_good, ptr_vector_get(&chain->nsec3_added, i)); } else { // unused if(warning_quota > 0) { log_warn("zone load: %{dnsname}: nsec3: unused %{digest32h}.%{dnsname} removed", context->zone->origin, nsec3_record->digest_then_rdata, context->zone->origin); if(--warning_quota == 0) { log_warn("zone load: %{dnsname}: nsec3: too many warnings, silently removing unused links remaining in the chain", context->zone->origin); } } fix_required = TRUE; } } if(nsec3_correction_count > 0) { log_warn("zone load: %{dnsname}: nsec3: %u bitmap corrections made", context->zone->origin, nsec3_correction_count); } ptr_vector_remove_after(&chain->nsec3_added, last_good); ptr_vector_resize(&chain->nsec3_added, last_good + 1); if(fix_required && context->can_fix) { // fix next digest nsec3_context_record *prev_nsec3_record = (nsec3_context_record*)ptr_vector_last(&chain->nsec3_added); size_t next_digest_offset = digest_len + 1 + nsec3param_rdata_size; if(ptr_vector_last_index(&chain->nsec3_added) > 0) { for(int i = 0; i <= ptr_vector_last_index(&chain->nsec3_added); ) { nsec3_context_record *nsec3_record = (nsec3_context_record*)ptr_vector_get(&chain->nsec3_added, i); if(memcmp(prev_nsec3_record->digest_then_rdata, nsec3_record->digest_then_rdata, digest_len + 1) == 0) { // unlikely case of hash collision : delete record, shrink ptr_vector (should also merge bitmap) /// @todo edf 20180905 -- merge type bitmaps (this is a very unlikely case) log_notice("zone load: %{dnsname}: nsec3: multiple %{digest32h}.%{dnsname} coverage. " "This is highly unexpected as it requires an hash collision. You should probably change the salt value.", context->zone->origin, nsec3_record->digest_then_rdata, context->zone->origin); nsec3_load_context_record_delete(nsec3_record); ptr_vector_remove_at(&chain->nsec3_added, i); continue; } // if next-hash != next hash ... if(memcmp(&prev_nsec3_record->digest_then_rdata[next_digest_offset], nsec3_record->digest_then_rdata, digest_len + 1) != 0) { // overwrite next-hash value memcpy(&prev_nsec3_record->digest_then_rdata[next_digest_offset], nsec3_record->digest_then_rdata, digest_len + 1); // clear all signatures nsec3_load_context_record_delete_rrsig(prev_nsec3_record); } // proceed with the next record prev_nsec3_record = nsec3_record; ++i; } } else { for(int i = 0; i <= ptr_vector_last_index(&chain->nsec3_added); ++i) { nsec3_context_record *nsec3_record = (nsec3_context_record*)ptr_vector_get(&chain->nsec3_added, i); // if next-hash != next hash ... if(memcmp(&prev_nsec3_record->digest_then_rdata[next_digest_offset], nsec3_record->digest_then_rdata, digest_len + 1) != 0) { // overwrite next-hash value memcpy(&prev_nsec3_record->digest_then_rdata[next_digest_offset], nsec3_record->digest_then_rdata, digest_len + 1); // clear all signatures nsec3_load_context_record_delete_rrsig(prev_nsec3_record); } // proceed with the next record prev_nsec3_record = nsec3_record; } } // chain is fixed zdb_zone_set_status(context->zone, ZDB_ZONE_STATUS_MODIFIED); } return !fix_required; } /** * There are two choices for fixing the chain. * Either all digests are computed, associated with their fqdn and then matched with what exists in the context : this way costs (a lot of) memory (say 100 bytes per covered label.) * Either for all fqdn the digest is computed, then sought in the context : this way costs about log2(#labels) seek/compare per covered label. * * This fix for extreme cases has more chances to succeed if it does not go out of memory so the second, slower, way has been chosen. * */ static void nsec3_load_fix_chain(nsec3_load_context *context, nsec3_load_context_chain *chain) { // for all labels // check if the label should be covered by an NSEC3 // compute the digest // seek for the digest // if missing // it will need to be added: keep it on the side for the next pass (with an uninitialised next) // else // mark the entry to tell it's covering something // // for all digests // if the entry is not used, remove it // // add all new entries // // for all digests // verify and fix the next fields // nsec3_hash_function *hash_function; u8 *salt; nsec3_load_is_label_covered_function *is_covered; ptr_vector added_nsec3 = PTR_VECTOR_EMPTY; s32 min_ttl = context->zone->min_ttl; u16 hash_iterations; u16 nsec3param_rdata_size; u8 salt_len; u8 optout_byte; u8 digest_len; bool dirty = FALSE; zdb_zone_label_iterator iter; u8 digest[64]; u8 fqdn[MAX_DOMAIN_LENGTH + 1]; digest_len = digest[0] = nsec3_hash_len(NSEC3PARAM_RDATA_ALGORITHM(chain->nsec3param_rdata)); hash_function = nsec3_hash_get_function(NSEC3PARAM_RDATA_ALGORITHM(chain->nsec3param_rdata)); salt = NSEC3PARAM_RDATA_SALT(chain->nsec3param_rdata); salt_len = NSEC3PARAM_RDATA_SALT_LEN(chain->nsec3param_rdata); hash_iterations = NSEC3PARAM_RDATA_ITERATIONS(chain->nsec3param_rdata); nsec3param_rdata_size = NSEC3PARAM_MINIMUM_LENGTH + salt_len; if(context->opt_out) { is_covered = nsec3_load_is_label_covered_optout; optout_byte = 1; } else { is_covered = nsec3_load_is_label_covered; optout_byte = 0; } zdb_zone_label_iterator_init(&iter, context->zone); while(zdb_zone_label_iterator_hasnext(&iter)) { u32 fqdn_len = zdb_zone_label_iterator_nextname(&iter, fqdn); zdb_rr_label* label = zdb_zone_label_iterator_next(&iter); if(is_covered(label)) { // should be covered hash_function( fqdn, fqdn_len, salt, salt_len, hash_iterations, &digest[1], FALSE); // digest exists ? // nsec3 missing: generate the type bitmap and make an rdata with an nsec3 digest type_bit_maps_context bitmap; u16 bitmap_size = zdb_rr_label_bitmap_type_init(label, &bitmap); u16 rdata_size_pre_bitmap = nsec3param_rdata_size + 1 + digest_len; u16 rdata_size = rdata_size_pre_bitmap + bitmap_size; nsec3_context_record *expected_nsec3_record = nsec3_load_context_record_new_binary(digest, min_ttl, rdata_size); u8 *rdata = &expected_nsec3_record->digest_then_rdata[digest_len + 1]; memcpy(rdata, chain->nsec3param_rdata, nsec3param_rdata_size); rdata[1] = optout_byte; type_bit_maps_write(&bitmap, &rdata[nsec3param_rdata_size + 1 + digest_len]); type_bit_maps_finalize(&bitmap); s32 match_index = ptr_vector_search_index(&chain->nsec3_added, digest, nsec3_load_fix_chain_search_cb); void *match = (match_index >= 0)?ptr_vector_get(&chain->nsec3_added, match_index):NULL; if(match == NULL) { #if DEBUG rdata[nsec3param_rdata_size] = digest_len; rdata_desc nsec3_rdata = {TYPE_NSEC3, rdata_size, rdata}; log_debug("zone load: %{dnsname}: missing %{digest32h}.%{dnsname} %{typerdatadesc}", context->zone->origin, expected_nsec3_record->digest_then_rdata, context->zone->origin, &nsec3_rdata); #endif ptr_vector_append(&added_nsec3, expected_nsec3_record); log_warn("zone load: %{dnsname}: nsec3: missing %{digest32h}.%{dnsname} covering %{dnsname} added", context->zone->origin, digest, context->zone->origin, fqdn); } else { // found bool nsec3_matches = FALSE; nsec3_context_record *nsec3_record = (nsec3_context_record*)match; if(nsec3_record->rdata_size == expected_nsec3_record->rdata_size) { if(memcmp(&nsec3_record->digest_then_rdata[digest_len + 1 + rdata_size_pre_bitmap], &expected_nsec3_record->digest_then_rdata[digest_len + 1 + rdata_size_pre_bitmap], bitmap_size) == 0) { nsec3_matches = TRUE; } } if(nsec3_matches) { nsec3_load_context_record_delete(expected_nsec3_record); nsec3_record->ttl = - nsec3_record->ttl; } else { log_warn("zone load: %{dnsname}: nsec3: %{digest32h}.%{dnsname} has mismatched bitmap: fixed (%{dnsname})", context->zone->origin, nsec3_record->digest_then_rdata, context->zone->origin, fqdn); ptr_vector_set(&chain->nsec3_added, match_index, expected_nsec3_record); nsec3_load_context_record_delete(nsec3_record); expected_nsec3_record->ttl = - expected_nsec3_record->ttl; dirty = TRUE; } } } } int j = 0; // remove unused and replace them by missing (if any) for(int i = 0; i <= ptr_vector_last_index(&chain->nsec3_added); ++i) { nsec3_context_record *nsec3_record = (nsec3_context_record*)ptr_vector_get(&chain->nsec3_added, i); if(nsec3_record->ttl < 0) { nsec3_record->ttl = - nsec3_record->ttl; } else { // unused log_warn("zone load: %{dnsname}: nsec3: unused %{digest32h}.%{dnsname} removed", context->zone->origin, nsec3_record->digest_then_rdata, context->zone->origin); nsec3_load_context_record_delete(nsec3_record); if(j <= ptr_vector_last_index(&added_nsec3)) { ptr_vector_set(&chain->nsec3_added, i, ptr_vector_get(&added_nsec3, j)); ++j; } else { ptr_vector_set(&chain->nsec3_added, i, NULL); } dirty = TRUE; } } // add missing not added in previous pass if(j <= ptr_vector_last_index(&added_nsec3)) { int reserve = ptr_vector_last_index(&added_nsec3) - j + 1; ptr_vector_ensures(&chain->nsec3_added, ptr_vector_size(&chain->nsec3_added) + reserve); for(; j <= ptr_vector_last_index(&added_nsec3); ++j) { ptr_vector_append(&chain->nsec3_added, ptr_vector_get(&added_nsec3, j)); } } ptr_vector_destroy(&added_nsec3); ptr_vector_qsort(&chain->nsec3_added, nsec3_load_context_record_qsort_callback); // sort the records in the chain // fix next digest nsec3_context_record *prev_nsec3_record = (nsec3_context_record*)ptr_vector_last(&chain->nsec3_added); size_t next_digest_offset = digest_len + 1 + nsec3param_rdata_size; for(int i = 0; i <= ptr_vector_last_index(&chain->nsec3_added); ++i) { nsec3_context_record *nsec3_record = (nsec3_context_record*)ptr_vector_get(&chain->nsec3_added, i); // check for duplicates (don't change the comparison order) // the first test is mandatory to find an error // the second test is cheap but pointless on all but duplicate cases if(memcmp(prev_nsec3_record->digest_then_rdata, nsec3_record->digest_then_rdata, digest_len + 1) == 0) { if(ptr_vector_last_index(&chain->nsec3_added) > 0) { // unlikely case of hash collision : delete record, shrink ptr_vector (should also merge bitmap) /// @todo edf 20180905 -- merge type bitmaps (this is a very unlikely case) log_notice("zone load: %{dnsname}: nsec3: multiple %{digest32h}.%{dnsname} coverage. This is highly unexpected as it requires an hash collision. You should probably change the salt value.", context->zone->origin, nsec3_record->digest_then_rdata, context->zone->origin); dirty = TRUE; nsec3_load_context_record_delete(nsec3_record); ptr_vector_remove_at(&chain->nsec3_added, i); --i; continue; } } if(memcmp(&prev_nsec3_record->digest_then_rdata[next_digest_offset], nsec3_record->digest_then_rdata, digest_len + 1) != 0) { if(ptr_vector_last_index(&chain->nsec3_added) > 0) { memcpy(&prev_nsec3_record->digest_then_rdata[next_digest_offset], nsec3_record->digest_then_rdata, digest_len + 1); nsec3_load_context_record_delete_rrsig(prev_nsec3_record); dirty = TRUE; } } prev_nsec3_record = nsec3_record; } // chain is fixed if(dirty) { zdb_zone_set_status(context->zone, ZDB_ZONE_STATUS_MODIFIED); } } /* * Use this to add the NSEC3 information from the context to the zone. * yadifad used to be more strict about the NSEC3 chain * Now it only requires the chain to loop. * * If an error is found, and the context allows fixing the zone then: * The function will correct it and mark the context to tell the zone has been modified. * The caller should then increment the serial, destroy the journal, and save the fixed zone. */ ya_result nsec3_load_generate(nsec3_load_context *context) { // for all chains // sort the records // ensure the records are following (modulo) // create the nsec3 chain collection // add the collection to the zone (enabled or not) for(int i = 0; i <= ptr_vector_last_index(&context->nsec3chain); ++i) { nsec3_load_context_chain *chain = (nsec3_load_context_chain*)ptr_vector_get(&context->nsec3chain, i); if(ptr_vector_last_index(&chain->nsec3_added) >= 0) { ptr_vector_qsort(&chain->nsec3_added, nsec3_load_context_record_qsort_callback); // sort the records in the chain // slaves cannot fix their content if(context->can_fix) { if(!nsec3_load_find_extranous_records_in_chain(context, chain)) { context->fix_applied = TRUE; --i; continue; } } const nsec3_context_record *p = (const nsec3_context_record*)ptr_vector_last(&chain->nsec3_added); for(int j = 0; j <= ptr_vector_last_index(&chain->nsec3_added); ++j) { const nsec3_context_record *r = (const nsec3_context_record*)ptr_vector_get(&chain->nsec3_added, j); // the digest in the rdata of p has to be the digest of r if(!nsec3_load_context_record_linked(p, r)) { // the chain is broken log_err("zone load: %{dnsname}: nsec3: %{digest32h}.%{dnsname} should be followed by %{digest32h}.%{dnsname} but was by %{digest32h}.%{dnsname} instead", context->zone->origin, p->digest_then_rdata, context->zone->origin, nsec3_load_context_record_next_digest(p), context->zone->origin, r->digest_then_rdata, context->zone->origin); if(!context->can_fix) { // even with a more lenient yadifad, a broken chain is just not usable by a slave // the minimum requirement now is coherence return DNSSEC_ERROR_NSEC3_INVALIDZONESTATE; } nsec3_load_fix_chain(context, chain); context->fix_applied = TRUE; // --i; break; } p = r; } if(!context->fix_applied) { const nsec3_context_record *s = (const nsec3_context_record*)ptr_vector_get(&chain->nsec3_added, 0); if(!nsec3_load_context_record_linked(p, s)) { // the chain is broken log_err("zone load: %{dnsname}: nsec3: %{digest32h}.%{dnsname} should be followed by %{digest32h}.%{dnsname} but was by %{digest32h}.%{dnsname} instead (back to front)", context->zone->origin, p->digest_then_rdata, context->zone->origin, nsec3_load_context_record_next_digest(p), context->zone->origin, s->digest_then_rdata, context->zone->origin); if(!context->can_fix) { return DNSSEC_ERROR_NSEC3_INVALIDZONESTATE; } nsec3_load_fix_chain(context, chain); context->fix_applied = TRUE; //--i; break; } } } else { log_err("zone load: %{dnsname}: nsec3: empty chain %i", context->zone->origin, i); // slaves cannot fix their content if(context->can_fix) { nsec3_load_fix_chain(context, chain); context->fix_applied = TRUE; } } } nsec3_zone **n3p = &context->zone->nsec.nsec3; // the chain are valid : create the collections // but first sort the collections to put the ones with NSEC3PARAM with smallest digest/iterations ptr_vector_qsort(&context->nsec3chain, nsec3_load_context_chain_qsort_callback); // sort the chains for(int i = 0; i <= ptr_vector_last_index(&context->nsec3chain); ++i) { nsec3_load_context_chain *chain = (nsec3_load_context_chain*)ptr_vector_get(&context->nsec3chain, i); nsec3_zone *n3 = nsec3_zone_new(chain->nsec3param_rdata, chain->nsec3param_rdata_size); for(int j = 0; j <= ptr_vector_last_index(&chain->nsec3_added); ++j) { nsec3_context_record *r = (nsec3_context_record*)ptr_vector_get(&chain->nsec3_added, j); const u8 *rdata = nsec3_load_context_record_rdata(r); nsec3_node *node = nsec3_insert(&n3->items, r->digest_then_rdata); node->flags = rdata[1]; nsec3_zone_item_update_bitmap(node, rdata, r->rdata_size); node->rrsig = r->rrsig; r->rrsig = NULL; } // the chain is complete *n3p = n3; n3p = &n3->next; // if the first chain has an nsec3param, it is visible if(i == 0 && chain->has_nsec3param) { // link the labels nsec3_zone_update_chain0_links(context->zone); } } // finally: add the postponed rrsig records ptr_set_iterator iter; ptr_set_iterator_init(&context->postponed_rrsig, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *rrsig_node = ptr_set_iterator_next_node(&iter); bool useless = TRUE; for(nsec3_zone *n3 = context->zone->nsec.nsec3; n3 != NULL; n3 = n3->next) { nsec3_node *nsec3_node = nsec3_find(&n3->items, rrsig_node->key); if(nsec3_node != NULL) { zdb_packed_ttlrdata *rrsig = (zdb_packed_ttlrdata*)rrsig_node->value; nsec3_node->rrsig = rrsig; u8 *key = (u8*)rrsig_node->key; ZFREE_ARRAY(rrsig_node->key, key[0] + 1); // VS false positive: a key cannot be NULL rrsig_node->key = NULL; rrsig_node->value = NULL; useless = FALSE; break; } } if(useless) { // complain log_warn("nsec3: %{dnsname}: %{digest32h}: RRSIG does not covers any known NSEC3 record", context->zone->origin, rrsig_node->key); } } return SUCCESS; } bool nsec3_load_is_context_empty(nsec3_load_context* context) { return (context->zone == NULL) || (ptr_vector_last_index(&context->nsec3chain) < 0); } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec3_name_error.c0000644000000000000000000000013214505005531022354 xustar000000000000000030 mtime=1695812441.736972077 30 atime=1695812445.802030296 30 ctime=1695812495.190737642 yadifa-2.6.5-11201/lib/dnsdb/src/nsec3_name_error.c0000664000374500037450000002573114505005531022326 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include "dnsdb/nsec3_types.h" #include "dnsdb/nsec3_item.h" #include "dnsdb/nsec3_name_error.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/rrsig.h" #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; /** */ void nsec3_closest_encloser_from_fqdn(const zdb_zone* zone, const dnsname_vector *qname, u32 apex_index, u8 * restrict * pool, u8 **out_next_closer_nsec3_owner_p, zdb_packed_ttlrdata** out_encloser_nsec3, const zdb_packed_ttlrdata** out_encloser_nsec3_rrsig) { const struct nsec3_node *encloser_nsec3; nsec3_closest_encloser_proof(zone, qname, apex_index, &encloser_nsec3,NULL,NULL); if(encloser_nsec3 != NULL) { nsec3_zone* n3 = zone->nsec.nsec3; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm nsec3_parms = { n3, encloser_nsec3, zone->origin, pool, min_ttl }; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_next_closer_nsec3_owner_p, out_encloser_nsec3, out_encloser_nsec3_rrsig); } } void nsec3_wild_closest_encloser(const zdb_zone* zone, const dnsname_vector *qname, u32 apex_index, u8 * restrict * pool, u8 **out_wild_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_wild_encloser_nsec3, const zdb_packed_ttlrdata** out_wild_encloser_nsec3_rrsig, u8 **out_wild_closest_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_wild_closest_encloser_nsec3, const zdb_packed_ttlrdata** out_wild_closest_encloser_nsec3_rrsig, u8 **out_qname_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_qname_encloser_nsec3, const zdb_packed_ttlrdata** out_qname_encloser_nsec3_rrsig ) { const nsec3_zone_item *wild_encloser_nsec3; const nsec3_zone_item *closest_provable_encloser_nsec3; const nsec3_zone_item *qname_encloser_nsec3; nsec3_wild_closest_encloser_proof(zone, qname, apex_index, &wild_encloser_nsec3, &closest_provable_encloser_nsec3, &qname_encloser_nsec3); nsec3_zone* n3 = zone->nsec.nsec3; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm nsec3_parms = { n3, wild_encloser_nsec3, zone->origin, pool, min_ttl }; if(wild_encloser_nsec3 != NULL) { nsec3_parms.item = wild_encloser_nsec3; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_wild_encloser_nsec3_owner_p, out_wild_encloser_nsec3, out_wild_encloser_nsec3_rrsig); } if((closest_provable_encloser_nsec3 != wild_encloser_nsec3) && (closest_provable_encloser_nsec3 != NULL)) { nsec3_parms.item = closest_provable_encloser_nsec3; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_wild_closest_encloser_nsec3_owner_p, out_wild_closest_encloser_nsec3, out_wild_closest_encloser_nsec3_rrsig); } if((qname_encloser_nsec3 != wild_encloser_nsec3) && (qname_encloser_nsec3 != closest_provable_encloser_nsec3) && (qname_encloser_nsec3 != NULL)) { nsec3_parms.item = qname_encloser_nsec3; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_qname_encloser_nsec3_owner_p, out_qname_encloser_nsec3, out_qname_encloser_nsec3_rrsig); } } /** * @note Name Error Responses * * Retrieve NSEC3 name error records * * To prove the nonexistence of QNAME, a closest encloser proof and an * NSEC3 RR covering the (nonexistent) wildcard RR at the closest * encloser MUST be included in the response. This collection of (up * to) three NSEC3 RRs proves both that QNAME does not exist and that a * wildcard that could have matched QNAME also does not exist. * * For example, if "gamma.example." is the closest provable encloser to * QNAME, then an NSEC3 RR covering "*.gamma.example." is included in * the authority section of the response. * * * * Z-Allocates and creates an NSEC3 record from an nsec3_zone_item * * This record is temporary. * * The function is supposed to be called by nsec3_name_error & nsec3_nodata_error * Said functions are called by the query function * * The record is supposed to be destroyed after usage (ie: at destroy query answer) * * @param zone * @param qname * @param apex_index * @param pool * @param out_next_closer_nsec3_owner_p * @param out_encloser_nsec3 * @param out_encloser_nsec3_rrsig * @param out_closest_encloser_nsec3_owner_p * @param out_closest_encloser_nsec3 * @param out_closest_encloser_nsec3_rrsig * @param out_wild_closest_encloser_nsec3_owner_p * @param out_wild_closest_encloser_nsec3 * @param out_wild_closest_encloser_nsec3_rrsig */ void nsec3_name_error(const zdb_zone* zone, const dnsname_vector *qname, u32 apex_index, u8 * restrict * pool, u8 **out_next_closer_nsec3_owner_p, zdb_packed_ttlrdata** out_encloser_nsec3, const zdb_packed_ttlrdata** out_encloser_nsec3_rrsig, u8 **out_closest_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_closest_encloser_nsec3, const zdb_packed_ttlrdata** out_closest_encloser_nsec3_rrsig, u8 **out_wild_closest_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_wild_closest_encloser_nsec3, const zdb_packed_ttlrdata** out_wild_closest_encloser_nsec3_rrsig ) { const nsec3_zone_item *encloser_nsec3; const nsec3_zone_item *closest_provable_encloser_nsec3; const nsec3_zone_item *wild_closest_provable_encloser_nsec3; yassert(out_next_closer_nsec3_owner_p != NULL && out_encloser_nsec3 != NULL && out_encloser_nsec3_rrsig != NULL); yassert(out_closest_encloser_nsec3_owner_p != NULL && out_closest_encloser_nsec3 != NULL && out_closest_encloser_nsec3_rrsig != NULL); yassert(out_wild_closest_encloser_nsec3_owner_p != NULL && out_wild_closest_encloser_nsec3 != NULL && out_wild_closest_encloser_nsec3_rrsig != NULL); *out_next_closer_nsec3_owner_p = NULL; *out_encloser_nsec3 = NULL; *out_encloser_nsec3_rrsig = NULL; *out_closest_encloser_nsec3_owner_p = NULL; *out_closest_encloser_nsec3 = NULL; *out_closest_encloser_nsec3_rrsig = NULL; *out_wild_closest_encloser_nsec3_owner_p = NULL; *out_wild_closest_encloser_nsec3 = NULL; *out_wild_closest_encloser_nsec3_rrsig = NULL; nsec3_closest_encloser_proof(zone, qname, apex_index, &encloser_nsec3, &closest_provable_encloser_nsec3, &wild_closest_provable_encloser_nsec3 ); /* Append all items + sig to the authority * Don't do dups */ nsec3_zone* n3 = zone->nsec.nsec3; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm nsec3_parms = { n3, encloser_nsec3, zone->origin, pool, min_ttl }; if(encloser_nsec3 != NULL) { nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_next_closer_nsec3_owner_p, out_encloser_nsec3, out_encloser_nsec3_rrsig); } *out_closest_encloser_nsec3 = NULL; if((closest_provable_encloser_nsec3 != encloser_nsec3) && (closest_provable_encloser_nsec3 != NULL)) { nsec3_parms.item = closest_provable_encloser_nsec3; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_closest_encloser_nsec3_owner_p, out_closest_encloser_nsec3, out_closest_encloser_nsec3_rrsig); } *out_wild_closest_encloser_nsec3 = NULL; if((wild_closest_provable_encloser_nsec3 != encloser_nsec3) && (wild_closest_provable_encloser_nsec3 != closest_provable_encloser_nsec3) && (wild_closest_provable_encloser_nsec3 != NULL)) { nsec3_parms.item = wild_closest_provable_encloser_nsec3; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_wild_closest_encloser_nsec3_owner_p, out_wild_closest_encloser_nsec3, out_wild_closest_encloser_nsec3_rrsig); } } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec3_nodata_error.c0000644000000000000000000000013214505005531022702 xustar000000000000000030 mtime=1695812441.730971991 30 atime=1695812445.801030282 30 ctime=1695812495.193737685 yadifa-2.6.5-11201/lib/dnsdb/src/nsec3_nodata_error.c0000664000374500037450000002252114505005531022646 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include "dnsdb/zdb_zone.h" #include "dnsdb/nsec3_types.h" #include "dnsdb/nsec3_item.h" #include "dnsdb/nsec3_name_error.h" #include "dnsdb/rrsig.h" #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; /* * It is assumed that zone is NSEC3. * The caller must ensure this is the case. */ /** * @note No Data Responses, QTYPE is not DS * * The server MUST include the NSEC3 RR that matches QNAME. This NSEC3 * RR MUST NOT have the bits corresponding to either the QTYPE or CNAME * set in its Type Bit Maps field. */ void nsec3_nodata_error(const zdb_zone *zone, const zdb_rr_label* owner, const dnsname_vector *qname, s32 apex_index, u8 * restrict * pool, u8 **out_owner_nsec3_owner, zdb_packed_ttlrdata** out_owner_nsec3, const zdb_packed_ttlrdata** out_owner_nsec3_rrsig, u8 **out_closest_encloser_nsec3_owner, zdb_packed_ttlrdata** out_closest_encloser_nsec3, const zdb_packed_ttlrdata** out_closest_encloser_nsec3_rrsig) { yassert(out_owner_nsec3_owner != NULL && out_owner_nsec3 != NULL && out_owner_nsec3_rrsig != NULL); yassert(out_closest_encloser_nsec3_owner != NULL && out_closest_encloser_nsec3 != NULL && out_closest_encloser_nsec3_rrsig != NULL); const nsec3_zone_item *owner_nsec3; nsec3_zone* n3 = zone->nsec.nsec3; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm nsec3_parms = { n3, NULL, zone->origin, pool, min_ttl }; if((owner->nsec.dnssec == NULL) || (nsec3_label_extension_self(owner->nsec.nsec3) == NULL)) // scan-build false positive: owner->nsec.dnssec == owner->nsec.nsec3 => owner->nsec.nsec3 can't ben NULL for nsec3_label_extension_self { nsec3_closest_encloser_proof(zone, qname, apex_index, &owner_nsec3, &nsec3_parms.item, // closest_provable_encloser_nsec3 NULL ); if(nsec3_parms.item != NULL) { nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_closest_encloser_nsec3_owner, out_closest_encloser_nsec3, out_closest_encloser_nsec3_rrsig); } else { *out_closest_encloser_nsec3_owner = NULL; *out_closest_encloser_nsec3 = NULL; *out_closest_encloser_nsec3_rrsig = NULL; #if DEBUG log_debug("nsec3_nodata_error: no closest encloser proof"); #endif } } else { owner_nsec3 = nsec3_label_extension_self(owner->nsec.nsec3); *out_closest_encloser_nsec3 = NULL; *out_closest_encloser_nsec3_rrsig = NULL; } /* Append all items + sig to the authority * Don't do dups */ if(owner_nsec3 != NULL) { nsec3_parms.item = owner_nsec3; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_owner_nsec3_owner, out_owner_nsec3, out_owner_nsec3_rrsig); } else { log_err("%{dnsnamevector} has no NSEC3 owner, has DNSSEC mode been changed?", qname); // /* ((zone->_flags & ZDB_ZONE_HAS_OPTOUT_COVERAGE) != 0) digestname(closest_provable_encloser, dnsname_len(closest_provable_encloser), salt, salt_len, iterations, &digest[1], FALSE); closest_provable_encloser_nsec3 = nsec3_find(&n3->items, digest); */ } } /** * * @note Wildcard No Data Responses * * If there is a wildcard match for QNAME, but QTYPE is not present at * that name, the response MUST include a closest encloser proof for * QNAME and MUST include the NSEC3 RR that matches the wildcard. This * combination proves both that QNAME itself does not exist and that a * wildcard that matches QNAME does exist. Note that the closest * encloser to QNAME MUST be the immediate ancestor of the wildcard RR * (if this is not the case, then something has gone wrong). */ void nsec3_wild_nodata_error(const zdb_zone *zone, const zdb_rr_label *owner, const dnsname_vector *qname, u32 apex_index, u8 * restrict * pool, u8 **out_next_closer_nsec3_owner_p, zdb_packed_ttlrdata** out_encloser_nsec3, const zdb_packed_ttlrdata** out_encloser_nsec3_rrsig, u8 **out_closest_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_closest_encloser_nsec3, const zdb_packed_ttlrdata** out_closest_encloser_nsec3_rrsig, u8 **out_qname_encloser_nsec3_owner_p, zdb_packed_ttlrdata** out_qname_encloser_nsec3, const zdb_packed_ttlrdata** out_qname_encloser_nsec3_rrsig) { yassert(out_next_closer_nsec3_owner_p != NULL && out_encloser_nsec3 != NULL && out_encloser_nsec3_rrsig != NULL); yassert(out_closest_encloser_nsec3_owner_p != NULL && out_closest_encloser_nsec3 != NULL && out_closest_encloser_nsec3_rrsig != NULL); (void)owner; // find the *.fqdn // add the name error above it const nsec3_zone_item *wild_encloser_nsec3 = NULL; const nsec3_zone_item *closest_provable_encloser_nsec3 = NULL; const nsec3_zone_item *qname_encloser_nsec3 = NULL; nsec3_wild_closest_encloser_proof(zone, qname, apex_index, &wild_encloser_nsec3, &closest_provable_encloser_nsec3, &qname_encloser_nsec3); nsec3_zone* n3 = zone->nsec.nsec3; s32 min_ttl; zdb_zone_getminttl(zone, &min_ttl); nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm nsec3_parms = { n3, wild_encloser_nsec3, zone->origin, pool, min_ttl }; *out_encloser_nsec3 = NULL; if(wild_encloser_nsec3 != NULL) { nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_next_closer_nsec3_owner_p, out_encloser_nsec3, out_encloser_nsec3_rrsig); } *out_closest_encloser_nsec3 = NULL; if((closest_provable_encloser_nsec3 != wild_encloser_nsec3) && (closest_provable_encloser_nsec3 != NULL)) { nsec3_parms.item = closest_provable_encloser_nsec3; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_closest_encloser_nsec3_owner_p, out_closest_encloser_nsec3, out_closest_encloser_nsec3_rrsig); } if((qname_encloser_nsec3 != wild_encloser_nsec3) && (qname_encloser_nsec3 != closest_provable_encloser_nsec3) && (qname_encloser_nsec3 != NULL)) { nsec3_parms.item = qname_encloser_nsec3; nsec3_zone_item_to_new_zdb_packed_ttlrdata( &nsec3_parms, out_qname_encloser_nsec3_owner_p, out_qname_encloser_nsec3, out_qname_encloser_nsec3_rrsig); } } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec3_owner.c0000644000000000000000000000013214505005531021355 xustar000000000000000030 mtime=1695812441.704971618 30 atime=1695812445.800030268 30 ctime=1695812495.195737714 yadifa-2.6.5-11201/lib/dnsdb/src/nsec3_owner.c0000664000374500037450000006527414505005531021335 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * Owners & Stars * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include "dnsdb/zdb_types.h" #include "dnsdb/nsec3_owner.h" #if 0 /* fix */ #else #define NSEC3_OWNER_DEBUG 0 #endif //#if NSEC3_OWNER_DEBUG #include #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; //#endif #define OWNER_NAME(owner_) (((owner_) != NULL))?(owner_)->name:(u8*)"\011NULLOWNER" #define ITEM_DIGEST(item__) (((item__) != NULL)?(item__)->digest:NULL) /****************************************************************************** * * NSEC3 - tools : owners & stars * *****************************************************************************/ /** * Changes the value of the nsec3 extension of a label from a value to another. * * * @param n3ext the nsec3 extension of the label * @param item the old nsec3 item, CANNOT BE NULL * @param value the new nsec3 item, can be NULL * * 2 uses */ static int nsec3_label_extension_replace_self(nsec3_label_extension* n3ext, const nsec3_zone_item *item, nsec3_zone_item *value) { yassert(n3ext != NULL); yassert(item != NULL); // yassert(value != NULL); // can be NULL /* * This loops should only be run once or twice * Still it annoys me a lot. * * I'll have to find a better, dynamic, way to handle * multiple NSEC3PARAM. * (And of course memory usage and fragmentation is the * first enemy) */ #if NSEC3_OWNER_DEBUG log_debug("nsec3_label_extension_set_self: %p, %{digest32h} @ %p, %{digest32h} @ %p", n3ext, ITEM_DIGEST(item), item, ITEM_DIGEST(value), value); #endif int ret = 0; do { if(nsec3_label_extension_self(n3ext) == item) { yassert((value != NULL) || (nsec3_label_extension_self(n3ext) != NULL)); nsec3_label_extension_set_self(n3ext, value); /* Official way to change the "self" */ return ret; } #if NSEC3_OWNER_DEBUG if(value != NULL && nsec3_label_extension_self(n3ext) == value) { yassert((value != NULL) || (nsec3_label_extension_self(n3ext) != NULL)); log_debug("nsec3_label_extension_set_self: already %{digest32h} @ %p ???", ITEM_DIGEST(nsec3_label_extension_star(n3ext)), nsec3_label_extension_star(n3ext)); return ret; } log_debug("nsec3_label_extension_set_self: skipped %{digest32h} @ %p", ITEM_DIGEST(nsec3_label_extension_self(n3ext)), nsec3_label_extension_self(n3ext)); #endif ++ret; n3ext = nsec3_label_extension_next(n3ext); } while(n3ext != NULL); /* NULL means we didn't found the link back */ #if NSEC3_OWNER_DEBUG log_debug("nsec3_label_extension_set_self: reference not found (something is wrong)"); #endif logger_flush(); abort(); } /** * Changes the star value of the nsec3 extension of a label from a value to another. * * @param n3ext the nsec3 extension of the label * @param item the old nsec3 item, CANNOT BE NULL * @param value the new nsec3 item, can be NULL * * 6 uses */ static void nsec3_label_extension_replace_star(nsec3_label_extension* n3ext, const nsec3_zone_item *item, nsec3_zone_item* value) { yassert(n3ext != NULL); yassert(item != NULL); // yassert(value != NULL); @note value can be NULL #if NSEC3_OWNER_DEBUG log_debug("nsec3_label_extension_replace_star: %p, %{digest32h} @%p, %{digest32h} @%p", n3ext, ITEM_DIGEST(item), item, ITEM_DIGEST(value), value); #endif do { #if NSEC3_OWNER_DEBUG log_debug("nsec3_label_extension_replace_star: %{digest32h} @%p", ITEM_DIGEST(nsec3_label_extension_self(n3ext)), nsec3_label_extension_self(n3ext), ITEM_DIGEST(nsec3_label_extension_star(n3ext)), nsec3_label_extension_star(n3ext)); #endif if(nsec3_label_extension_star(n3ext) == item) { nsec3_label_extension_set_star(n3ext, value); return; } #if NSEC3_OWNER_DEBUG if(nsec3_label_extension_star(n3ext) == value) { log_debug("nsec3_label_extension_replace_star: already %{digest32h} @%p ???", ITEM_DIGEST(nsec3_label_extension_star(n3ext)), nsec3_label_extension_star(n3ext)); return; } log_debug("nsec3_label_extension_replace_star: skipped %{digest32h} @%p", ITEM_DIGEST(nsec3_label_extension_star(n3ext)), nsec3_label_extension_star(n3ext)); #endif n3ext = nsec3_label_extension_next(n3ext); } while(n3ext != NULL); /* NULL means we didn't found the link back */ if(value != NULL) { log_err("nsec3_label_extension_replace_star: did not found %{digest32h} NSEC3, while trying to replace it with (another) %{digest32h} NSEC3", item->digest, value->digest); } else { log_err("nsec3_label_extension_replace_star: did not found %{digest32h} NSEC3, while trying to remove it", item->digest); } logger_flush(); abort(); } /** * Adds an entry to the "owner" array (of an item) * * @param ownersp * @param countp * @param owner * * 2 uses */ static void nsec3_item_label_owner_add(nsec3_item_label_owner_array* ownersp, s32* countp, const zdb_rr_label *owner) { yassert(ownersp != NULL); yassert(countp != NULL); yassert(owner != NULL); if(*countp == 0) { (*ownersp).owner = (zdb_rr_label*)owner; *countp = 1; #if NSEC3_OWNER_DEBUG log_debug("nsec3_label_add: 1 '%{dnslabel}'", OWNER_NAME(owner)); #endif } else if(*countp == 1) { /* * We had one item : adding one will require using an array */ if((*ownersp).owner != owner) { *countp = 2; nsec3_item_label_owner_array owners; ZALLOC_ARRAY_OR_DIE(zdb_rr_label**, owners.owners, sizeof(zdb_rr_label*) * 2, NSEC3_LABELPTRARRAY_TAG); owners.owners[0] = (*ownersp).owner; owners.owners[1] = (zdb_rr_label*)owner; (*ownersp).owners = owners.owners; #if NSEC3_OWNER_DEBUG log_debug("nsec3_label_add: 2 '%{dnslabel}' '%{dnslabel}'", OWNER_NAME(owners.owners[0]), OWNER_NAME(owners.owners[1])); #endif } else { #if NSEC3_OWNER_DEBUG log_debug("nsec3_label_add: 1+1 '%{dnslabel}' already owned", OWNER_NAME(owner)); #endif } } else { /* * Just resize the current array to contain ONE more pointer */ s32 count = *countp; for(s32 i = 0; i < count; ++i) // count >= 2 so the loop runs at least twice (or returns) { if((*ownersp).owners[i] == owner) { #if NSEC3_OWNER_DEBUG log_debug("nsec3_label_add: %hi+1 '%{dnslabel}' already owned", count, OWNER_NAME(owner)); #endif return; } } /** @note ZALLOC_ARRAY_RESIZE does change the value of "count" to "count+1" */ ZALLOC_ARRAY_RESIZE(zdb_rr_label*, (*ownersp).owners, count, count + 1); (*ownersp).owners[count-1] = (zdb_rr_label*)owner; /// @note count is already set to count + 1 by the macro; scan-build false positive, VS false positive *countp = count; #if NSEC3_OWNER_DEBUG log_debug("nsec3_label_add: %i", count); for(s32 i = 0; i < count; i++) { log_debug(" + '%{dnslabel}'", OWNER_NAME((*ownersp).owners[i])); } #endif } } /** * Removes an entry from the "owner" array (of an item) * Raw collection change, does not propagates. * * @param ownersp * @param countp * @param owner * * 2 uses */ static void nsec3_item_label_owner_remove(nsec3_item_label_owner_array* ownersp, s32* countp, const zdb_rr_label *owner) { yassert(ownersp != NULL); yassert(countp != NULL); yassert(owner != NULL); yassert(*countp > 0); if(*countp == 1) { /* * We had one item, We will have none. * Set the pointer to NULL and the RC to 0 * * Also, the label's reference will have to be set to NULL * If the label's star reference was NULL already, then * free the owner->nsec.nsec3 */ yassert((*ownersp).owner == owner); (*ownersp).owner = NULL; *countp = 0; } else if(*countp == 2) { /* * We had one item, we will get one. * Keep the last pointer instead of the array. * Destroy the array */ zdb_rr_label* last_owner; if((*ownersp).owners[0] == owner) { last_owner = (*ownersp).owners[1]; } else { last_owner = (*ownersp).owners[0]; } ZFREE_ARRAY((*ownersp).owners, sizeof(zdb_rr_label*) * 2); (*ownersp).owner = last_owner; *countp = 1; } else { /* * We had more than 2 * * Find it, * replace it by the last one in the array, * shrink the array (resize) * */ s32 idx; s32 n = *countp; /* * Look for the owner */ for(idx = 0; idx < n; idx++) { if((*ownersp).owners[idx] == owner) { /* * Overwrite it by the next owner. * Move all following owners one step down */ n--; while(idx < n) { (*ownersp).owners[idx] = (*ownersp).owners[idx + 1]; idx++; } break; } } /* * Reduce the memory used by one count * Note : this macro will also set *countp to *countp - 1 */ ZALLOC_ARRAY_RESIZE(zdb_rr_label*, (*ownersp).owners, *countp, *countp - 1); } } /** * Returns TRUE if item is owned by owner * * @param item * @param owner * @return * * 1 use */ bool nsec3_item_is_owned_by_label(const nsec3_zone_item *item, const zdb_rr_label *owner) { yassert(item != NULL); yassert(owner != NULL); yassert(item->rc >= 0); if(item->rc == 1) { return (item->label.owner == owner); } else if(item->rc != 0) { zdb_rr_label* const * ownerp = item->label.owners; s32 i = item->rc; do { if(*ownerp++ == owner) { return TRUE; } } while(--i > 0); } return FALSE; } /** * Adds an owner to the NSEC3 item * * To be absolutely clear: links NSEC3 to LABEL, but does NOT links LABEL to NSEC3 * The label still has to be updated after this call. * * @param item * @param owner * * 6 uses */ void nsec3_item_add_owner(nsec3_zone_item *item, const zdb_rr_label *owner) { yassert(item != NULL); yassert(owner != NULL); #if NSEC3_OWNER_DEBUG log_debug("nsec3_add_owner: %{digest32h} @ %p, '%{dnslabel}' RC=%i", ITEM_DIGEST(item), item, OWNER_NAME(owner), item->rc); s32 rc = item->rc; #endif nsec3_item_label_owner_add(&item->label, &item->rc, owner); #if NSEC3_OWNER_DEBUG if(item->rc - rc != 1) { log_debug("nsec3_add_owner: %{digest32h} @ %p, '%{dnslabel}' RC went from %i to %i", ITEM_DIGEST(item), item, OWNER_NAME(owner), rc, item->rc); } #endif } /** * Removes an owner from the NSEC3 item * * The entry MUST have been set before * * @param item * @param owner * * 1 use */ void nsec3_item_remove_owner(nsec3_zone_item *item, const zdb_rr_label *owner) { yassert(item != NULL); yassert(owner != NULL); yassert(nsec3_owner_count(item) >= 0); #if NSEC3_OWNER_DEBUG log_debug("nsec3_remove_owner: %{digest32h} @ %p, '%{dnslabel}' RC=%i", ITEM_DIGEST(item), item, OWNER_NAME(owner), item->rc); s32 rc = item->rc; #endif nsec3_item_label_owner_remove(&item->label, &item->rc, owner); #if NSEC3_OWNER_DEBUG if(rc - item->rc != 1) { log_debug("nsec3_remove_owner: %{digest32h} @ %p, '%{dnslabel}' RC went from %i to %i", ITEM_DIGEST(item), item, OWNER_NAME(owner), rc, item->rc); } #endif } /** * Removes all owners from the NSEC3 item * * The entry MUST have been set before * * @param item * * 3 uses */ void nsec3_item_remove_all_owners(nsec3_zone_item *item) { yassert(item != NULL); #if NSEC3_OWNER_DEBUG log_debug("nsec3_remove_all_owners: %{digest32h} @ %p", ITEM_DIGEST(item), item); #endif if(item->rc > 0) { if(item->rc == 1) { zdb_rr_label* label = item->label.owner; if(label != NULL) { #if NSEC3_OWNER_DEBUG log_debug("nsec3_remove_all_owners: 1 : %p '%{dnslabel}'", item, label->name); #endif // if an nsec3_label_extension is attached to the label if(label->nsec.nsec3 != NULL) { // replace the self-NSEC3 link to 'item' by NULL, and retrieve the chain index int item_chain_index = nsec3_label_extension_replace_self(label->nsec.nsec3, item, NULL); // grab the nsec3_label_extension for the chain nsec3_label_extension *n3e = nsec3_label_extension_get_from_label(label, item_chain_index); if(nsec3_label_extension_star(n3e) != NULL) { // if there is a star reference, it needs to go // remove the star-reference to the label nsec3_item_remove_star(nsec3_label_extension_star(n3e), label); // and replace the star-reference from the nsec3_label_extension by NULL nsec3_label_extension_replace_star(n3e, nsec3_label_extension_star(n3e), NULL); } } else { log_warn("nsec3_remove_all_owners: label %{dnslabel} has no NSEC3 (flags=%04x)", label->name, zdb_rr_label_flag_get(label)); } // the label has no star reference as far as this is concerned // update the NSEC3 flags on the label u16 is_still_nsec3_mask = ~ZDB_RR_LABEL_NSEC3; struct nsec3_label_extension* n3e = label->nsec.nsec3; while(n3e != NULL) { if(nsec3_label_extension_self(n3e) != NULL) { is_still_nsec3_mask = ~0; break; } n3e = nsec3_label_extension_next(n3e); } zdb_rr_label_flag_and(label, is_still_nsec3_mask); item->label.owner = NULL; } } else { s32 n = item->rc; #if NSEC3_OWNER_DEBUG log_debug("nsec3_remove_all_owners: n : %p (%u)", item, n); #endif // for all owner labels for(s32 i = 0; i < n; i++) { zdb_rr_label* label = item->label.owners[i]; if(label != NULL) { #if NSEC3_OWNER_DEBUG log_debug("nsec3_remove_all_owners: n : %p '%{dnslabel}'", item, label->name); #endif if(label->nsec.nsec3 != NULL) { // replace the self-NSEC3 link to 'item' by NULL, and retrieve the chain index int item_chain_index = nsec3_label_extension_replace_self(label->nsec.nsec3, item, NULL); nsec3_label_extension *n3e = nsec3_label_extension_get_from_label(label, item_chain_index); if(nsec3_label_extension_star(n3e) != NULL) { nsec3_item_remove_star(nsec3_label_extension_star(n3e), label); nsec3_label_extension_replace_star(n3e, nsec3_label_extension_star(label->nsec.nsec3), NULL); } } else { log_warn("nsec3_remove_all_owners: label %{dnslabel} has no NSEC3 (flags=%04x)", label->name, zdb_rr_label_flag_get(label)); } // update the NSEC3 flags on the label u16 is_still_nsec3_mask = ~ZDB_RR_LABEL_NSEC3; struct nsec3_label_extension* n3e = label->nsec.nsec3; while(n3e != NULL) { if(nsec3_label_extension_self(n3e) != NULL) { is_still_nsec3_mask = ~0; break; } n3e = nsec3_label_extension_next(n3e); } zdb_rr_label_flag_and(label, is_still_nsec3_mask); item->label.owners[i] = NULL; } } ZFREE_ARRAY(item->label.owners, sizeof(zdb_rr_label*) * n); item->label.owners = NULL; } item->rc = 0; } } /** * * Returns the nth label owner for this item. * * @param item an NSEC3 item * @param idx the index of the label for this hash (usually 0, except if there are collisions of digest(transform(label)) * * @return the owner * * 1 use */ zdb_rr_label* nsec3_item_owner_get(const nsec3_zone_item *item, s32 idx) { yassert(item != NULL); if(item->rc == 1) { return item->label.owner; } else if(idx < item->rc) { return item->label.owners[idx]; } return NULL; } /* * Adds a "star" to the NSEC3 item * * 5 uses */ void nsec3_item_add_star(nsec3_zone_item *item, const zdb_rr_label *owner) { yassert(item != NULL); yassert(owner != NULL); #if NSEC3_OWNER_DEBUG log_debug("nsec3_add_star: %{digest32h} @ %p, %p '%{dnslabel}' SC=%hu", ITEM_DIGEST(item), item, owner, owner->name, item->sc); s32 sc = item->sc; #endif nsec3_item_label_owner_add(&item->star_label, &item->sc, owner); #if NSEC3_OWNER_DEBUG if(item->sc - sc != 1) { log_debug("nsec3_add_star: %{digest32h} @ %p, %p '%{dnslabel}' SC went from %hu to %hu", ITEM_DIGEST(item), item, owner, owner->name, sc, item->sc); } #endif } /** * Removes a star from the NSEC3 item * * The entry MUST have been set before * * @param item * @param owner * 3 uses */ void nsec3_item_remove_star(nsec3_zone_item *item, const zdb_rr_label *owner) { yassert(item != NULL); yassert(owner != NULL); #if NSEC3_OWNER_DEBUG log_debug("nsec3_remove_star: %{digest32h}@ @ %p '%{dnslabel}' SC=%hu", ITEM_DIGEST(item), item, owner->name, item->sc); s32 sc = item->sc; #endif nsec3_item_label_owner_remove(&item->star_label, &item->sc, owner); #if NSEC3_OWNER_DEBUG if(sc - item->sc != 1) { log_err("nsec3_remove_star: %{digest32h}@ @ %p '%{dnslabel}' SC went from %hu to %hu", ITEM_DIGEST(item), item, owner->name, sc, item->sc); } #endif } /** * Removes all stars from the NSEC3 item * * The entry MUST have been set before * * @param item * * 5 uses */ void nsec3_item_remove_all_star(nsec3_zone_item *item) { yassert(item != NULL); #if NSEC3_OWNER_DEBUG log_debug("nsec3_remove_all_star(%{digest32h} @ %p)", ITEM_DIGEST(item), item); #endif if(item->sc > 0) { if(item->sc == 1) { zdb_rr_label *label = item->star_label.owner; if(label != NULL) { #if NSEC3_OWNER_DEBUG log_debug("nsec3_remove_all_star: n = 1 : %p '%{dnslabel}'", label, label->name); #endif if(label->nsec.nsec3 != NULL) { nsec3_label_extension_replace_star(label->nsec.nsec3, item, NULL); } else { log_warn("nsec3_remove_all_star: label %{dnslabel} has no NSEC3 (flags=%04x)", label->name, zdb_rr_label_flag_get(label)); } item->star_label.owner = NULL; } } else { u32 n = (u32)item->sc; // sc > 0 #if NSEC3_OWNER_DEBUG log_debug("nsec3_remove_all_star: n = %u", n); for(u32 i = 0; i < n; i++) { log_debug("\tlabel[%i] = %p '%{dnslabel}'", i, item->star_label.owners[i], item->star_label.owners[i]->name); } #endif for(u32 i = 0; i < n; i++) { zdb_rr_label *label = item->star_label.owners[i]; if(label != NULL) { if(label->nsec.nsec3 != NULL) { #if NSEC3_OWNER_DEBUG log_debug("nsec3_remove_all_star: %i/%i %p '%{dnslabel}'", i, n, label, label->name); #endif nsec3_label_extension_replace_star(label->nsec.nsec3, item, NULL); } item->star_label.owners[i] = NULL; } } ZFREE_ARRAY(item->star_label.owners, sizeof(zdb_rr_label*) * n); item->star_label.owners = NULL; } item->sc = 0; } } /** * Moves all stars from one NSEC3 item to another. * * This is used when an NSEC3 item is removed: All its NSEC3 must be moved * to his predecessor. * * @param src * @param dst * * 3 uses */ void nsec3_item_move_all_star_to_nsec3_item(nsec3_zone_item* src, nsec3_zone_item* dst) { yassert(src != NULL); yassert(dst != NULL); #if NSEC3_OWNER_DEBUG log_debug("nsec3_move_all_star(%{digest32h} @ %p SC=%i, %{digest32h} @ %p SC=%i)", ITEM_DIGEST(src), src, src->sc, ITEM_DIGEST(dst), dst, dst->sc); s32 sum = src->sc + dst->sc; #endif yassert(src != dst); if(src->sc == 0) { /* nothing to move */ return; } // If there were no star in the dest : just move the star collection and update the referrenced labels if(dst->sc == 0) { dst->star_label.owner = src->star_label.owner; dst->sc = src->sc; for(s32 i = 0; i < src->sc; i++) { zdb_rr_label *label = nsec3_item_star_get(src, i); nsec3_label_extension_replace_star(label->nsec.nsec3, src, dst); } } else { // will merge both in dst nsec3_item_label_owner_array owners; s64 total = src->sc; total += dst->sc; yassert(total < (s64)(1ULL << (sizeof(src->sc) * 8))); /* * rc > 0 and sc > 0, so total of 2 means rc = 1 and sc = 1 */ ZALLOC_ARRAY_OR_DIE(zdb_rr_label**, owners.owners, sizeof(zdb_rr_label*) * total, NSEC3_LABELPTRARRAY_TAG); for(s32 i = 0; i < dst->sc; i++) // VS false positive: dst cannot be NULL { zdb_rr_label *label = nsec3_item_star_get(dst, i); log_debug("nsec3_move_all_star: %{digest32h} @%p %{dnslabel} @%p %i -> %i", ITEM_DIGEST(dst), dst, label->name, label, i, i); owners.owners[i] = label; } if(dst->sc > 1) // if it's a real array, free it { s32 len = dst->sc * sizeof(zdb_rr_label*); ZFREE_ARRAY(dst->star_label.owners, len); } /* change the star link of each label from src to dst */ for(s32 i = 0; i < src->sc; i++) // VS false positive: SRC cannot be NULL { zdb_rr_label *label = nsec3_item_star_get(src, i); log_debug("nsec3_move_all_star: %{digest32h} @%p %{dnslabel} @%p %i -> %i", ITEM_DIGEST(src), src, label->name, label, i, dst->sc + i); nsec3_label_extension_replace_star(label->nsec.nsec3, src, dst); owners.owners[dst->sc + i] = label; } if(src->sc > 1) // if it's a real array, free it { s32 len = src->sc * sizeof(zdb_rr_label*); ZFREE_ARRAY(src->star_label.owners, len); } dst->star_label.owners = owners.owners; // owner when 1 item, owners when multiple. False positives from static analysers. dst->sc = total; } src->star_label.owners = NULL; src->sc = 0; #if NSEC3_OWNER_DEBUG if(dst->sc != sum) { log_debug("nsec3_move_all_star(%{digest32h} @ %p, %{digest32h} @ %p SC went %i instead of %i)", ITEM_DIGEST(src), src, ITEM_DIGEST(dst), dst, dst->sc, sum); } #endif } /** * * Returns the nth star label owner for this item. * * @param item an NSEC3 item * @param idx the index of the label for this hash (usually 0, except if there are collisions of digest(transform(label)) * * @return the owner * * 4 uses */ zdb_rr_label * nsec3_item_star_get(const nsec3_zone_item *item, s32 idx) { yassert(item != NULL); if(item->sc == 1) { return item->star_label.owner; } else if(idx < item->sc) { return item->star_label.owners[idx]; } return NULL; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec3_zone.c0000644000000000000000000000013214505005531021176 xustar000000000000000030 mtime=1695812441.692971447 30 atime=1695812445.799030253 30 ctime=1695812495.197737742 yadifa-2.6.5-11201/lib/dnsdb/src/nsec3_zone.c0000664000374500037450000003361714505005531021152 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec3 NSEC3 functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include "dnsdb/nsec3_item.h" #include "dnsdb/nsec3_owner.h" #include "dnsdb/nsec3_zone.h" #include "dnsdb/zdb_zone_label_iterator.h" #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; /****************************************************************************** * * NSEC3 - tools : nsec3_zone (nsec3param's alter ego) * *****************************************************************************/ /* * Compares two nsec3_zone (binary compare <0 / = / >0 : less/equal/bigger) */ int nsec3param_compare_by_rdata(const u8 *a_rdata, const u8 *b_rdata) { int c; c = a_rdata[0]; c -= b_rdata[0]; if(c == 0) { c = a_rdata[2]; c -= b_rdata[2]; if(c == 0) { c = a_rdata[3]; c -= b_rdata[3]; if(c == 0) { c = a_rdata[4]; // size of the salt c -= b_rdata[4]; if(c == 0) { c = memcmp(&a_rdata[5], &b_rdata[5], a_rdata[4]); } } } } return c; } /* * Compares two nsec3_zone (binary compare <0 / = / >0 : less/equal/bigger) */ int nsec3_zone_compare(nsec3_zone* a, nsec3_zone* b) { return nsec3param_compare_by_rdata(a->rdata, b->rdata); } /* * Retrieves the nsec3_zone* (NSEC3PARAM alter-ego) from an item. * * This is done by looking for the NSEC3 root then looking for which nsec3_zone * contains the ptr. It requires up to 30 moves. (slow) * * I could also mark the nsec3 records and store the mark on every record but * it would be expensive (memory). * */ nsec3_zone* nsec3_zone_from_item(const zdb_zone* zone, const nsec3_zone_item* item) { const nsec3_zone_item* root = item; while(root->parent != NULL) { root = root->parent; } nsec3_zone* n3 = zone->nsec.nsec3; while(n3 != NULL) { if(n3->items == root) { break; } n3 = n3->next; } return n3; } /* * Recursively empties nsec3_zone_item * * Does not destroys the nodes, only the payload : owners, stars, bitmap, rrsig * * This should be followed by the destruction of the items */ static void nsec3_zone_item_empties_recursively(nsec3_zone_item* item) { if(item != NULL) { nsec3_zone_item_empties(item); nsec3_zone_item_empties_recursively(item->children.lr.left); nsec3_zone_item_empties_recursively(item->children.lr.right); } } /** * Detaches an nsec3 chain from the zone. * * @param zone * @param n3 * @return */ bool nsec3_zone_detach(zdb_zone *zone, nsec3_zone *n3) { nsec3_zone *first = zone->nsec.nsec3; if(first == n3) { zone->nsec.nsec3 = n3->next; } else { while(first->next != n3) { first = first->next; if(first == NULL) { return FALSE; } } first->next = n3->next; } n3->next = NULL; return TRUE; } /* * Destroys the nsec3param alter-ego from the database. * * The zdb_rr_label are also affected by the call. * * The NSEC3PARAM record is not changed. * */ void nsec3_zone_destroy(zdb_zone *zone, nsec3_zone *n3) { int n3_index = 0; /* * * Check for existence of n3 into zone * * For every nsec3 record found in zone: * * Get the self(s), unlink * Get the star(s), unlink * Destroy nsec3 record signature * Destroy nsec3 record */ // get the pointer chaining to n3 nsec3_zone **n3p = &zone->nsec.nsec3; yassert(*n3p != NULL); while(*n3p != n3) { ++n3_index; n3p = &(*n3p)->next; yassert(*n3p != NULL); } *n3p = n3->next; n3->next = NULL; nsec3_zone_item_empties_recursively(n3->items); nsec3_destroy(&n3->items); nsec3_zone_free(n3); // Every single label must have its chain updated zdb_zone_label_iterator label_iterator; zdb_zone_label_iterator_init(&label_iterator, zone); if(n3_index == 0) { while(zdb_zone_label_iterator_hasnext(&label_iterator)) { zdb_rr_label* label = zdb_zone_label_iterator_next(&label_iterator); if(label->nsec.nsec3 != NULL) { struct nsec3_label_extension *n3_ext = label->nsec.nsec3; if(n3_ext != NULL) { label->nsec.nsec3 = nsec3_label_extension_next(n3_ext); yassert(nsec3_label_extension_self(n3_ext) == NULL && nsec3_label_extension_star(n3_ext) == NULL); nsec3_label_extension_free(n3_ext); } } } } else { while(zdb_zone_label_iterator_hasnext(&label_iterator)) { #if DEBUG u8 fqdn[256]; zdb_zone_label_iterator_nextname(&label_iterator, fqdn); #endif zdb_rr_label* label = zdb_zone_label_iterator_next(&label_iterator); if(label->nsec.nsec3 != NULL) { struct nsec3_label_extension **n3_extp = nsec3_label_extension_next_ptr(label->nsec.nsec3); struct nsec3_label_extension *n3_ext = *n3_extp; for(int i = 1; i < n3_index; ++i) { n3_extp = nsec3_label_extension_next_ptr(n3_ext); n3_ext = *n3_extp; } *n3_extp = nsec3_label_extension_next(n3_ext); #if DEBUG if(nsec3_label_extension_self(n3_ext) != NULL) { log_debug2("%{dnsname} self %{digest32h}", fqdn, nsec3_label_extension_self(n3_ext)->digest); } if(nsec3_label_extension_star(n3_ext) != NULL) { log_debug2("%{dnsname} star %{digest32h}", fqdn, nsec3_label_extension_star(n3_ext)->digest); } #endif yassert(nsec3_label_extension_self(n3_ext) == NULL && nsec3_label_extension_star(n3_ext) == NULL); // both are expected to be cleared nsec3_label_extension_free(n3_ext); } } } } /* * Adds the nsec3_zone (NSEC3PARAM "alter-ego") to the zone. * * Updates labels flags + nsec3 item references placeholders * using nsec3_insert_empty_nsec3 * * Uses nsec3zone_compare * * Used by nsec3_add_nsec3param and nsec3_load_add_nsec3param * */ nsec3_zone* nsec3_zone_add_from_rdata(zdb_zone* zone, u16 nsec3param_rdata_size, const u8* nsec3param_rdata) { /* Check that the rdata is big enough */ yassert(nsec3param_rdata_size >= NSEC3PARAM_MINIMUM_LENGTH); nsec3_zone* n3 = nsec3_zone_get_from_rdata(zone, nsec3param_rdata_size, nsec3param_rdata); if(n3 == NULL) { n3 = nsec3_zone_new(nsec3param_rdata, nsec3param_rdata_size); /* * Insertion has to be sorted on the Algorithm + Iterations + Salt_len + Salt */ nsec3_zone** current = &zone->nsec.nsec3; nsec3_zone* next_n3 = zone->nsec.nsec3; u32 n3_pos = 0; for(;;) { /* if((next_n3 == NULL) || (nsec3_zone_compare(n3, next_n3) < 0)) */ if(next_n3 == NULL) { n3->next = next_n3; *current = n3; /* * For every existing label in the database: add a nsec3 node for * the current n3 record (same position in the list). */ //nsec3_insert_empty_nsec3(zone, n3_pos); break; } current = &next_n3->next; next_n3 = next_n3->next; n3_pos++; } } return n3; } nsec3_zone* nsec3_zone_new(const u8 *nsec3param_rdata, u16 nsec3param_rdata_size) { nsec3_zone *n3; u32 nsec3param_rdata_realsize = NSEC3PARAM_RDATA_SIZE_FROM_RDATA(nsec3param_rdata); yassert(nsec3param_rdata_size >= nsec3param_rdata_realsize); (void)nsec3param_rdata_size; ZALLOC_ARRAY_OR_DIE(nsec3_zone*, n3, sizeof(nsec3_zone) + nsec3param_rdata_realsize, NSEC3_ZONE_TAG); n3->next = NULL; n3->items = NULL; memcpy(n3->rdata, nsec3param_rdata, nsec3param_rdata_realsize); return n3; } void nsec3_zone_free(nsec3_zone *n3) { yassert(nsec3_isempty(&n3->items)); yassert(n3->next == NULL); ZFREE_ARRAY(n3, sizeof(nsec3_zone) + NSEC3PARAM_MINIMUM_LENGTH + n3->rdata[4]); } ya_result nsec3_zone_chain_count(zdb_zone* zone) { ya_result ret = 0;; nsec3_zone* n3 = zone->nsec.nsec3; while(n3 != NULL) { ++ret; n3 = n3->next; } return ret; } /** * * Adds the nsec3_zone (NSEC3PARAM "alter-ego") to the zone. * * Updates labels flags + nsec3 item references placeholders * using nsec3_insert_empty_nsec3 * * Uses nsec3zone_compare * * Used by nsec3_add_nsec3param and nsec3_load_add_nsec3param * * @note Does not add the record. * * @param zone * @param nsec3param_rdata * @param nsec3param_rdata_size * * @return an error code */ ya_result nsec3_zone_chain_add_with_rdata(zdb_zone* zone, const u8* nsec3param_rdata, u16 nsec3param_rdata_size) { /* Check that the rdata is big enough */ yassert(nsec3param_rdata_size >= NSEC3PARAM_MINIMUM_LENGTH); ya_result ret = 0; nsec3_zone* n3 = zone->nsec.nsec3; nsec3_zone** n3p; if(n3 != NULL) { if(memcmp(n3->rdata, nsec3param_rdata, nsec3param_rdata_size) == 0) { // duplicate return ERROR; } ++ret; while(n3->next != NULL) { n3 = n3->next; if(memcmp(n3->rdata, nsec3param_rdata, nsec3param_rdata_size) == 0) { // duplicate return ERROR; } ++ret; } // add after n3 n3p = &n3->next; } else { // create n3 n3p = &zone->nsec.nsec3; } n3 = nsec3_zone_new(nsec3param_rdata, nsec3param_rdata_size); *n3p = n3; return ret; } /** * Returns the index of an NSEC3PARAM in the zone, or an error code * * @param zone * @param nsec3param_rdata * @param nsec3param_rdata_size * @return */ ya_result nsec3_zone_chain_get_index_from_rdata(zdb_zone* zone, const u8* nsec3param_rdata, u16 nsec3param_rdata_size) { /* Check that the rdata is big enough */ yassert(nsec3param_rdata_size >= NSEC3PARAM_MINIMUM_LENGTH); ya_result ret = 0; nsec3_zone* n3 = zone->nsec.nsec3; while(n3 != NULL) { if(memcmp(n3->rdata, nsec3param_rdata, nsec3param_rdata_size) == 0) { // return the index of the match return ret; } ++ret; n3 = n3->next; } return ERROR; } /* * Returns the zone's matching nsec3_zone* or NULL * * The rdata can be of an NSEC3PARAM or of an NSEC3 * */ nsec3_zone* nsec3_zone_get_from_rdata(const zdb_zone* zone, u16 nsec3param_rdata_size, const u8* nsec3param_rdata) { /* Check that the rdata is big enough */ yassert(nsec3param_rdata_size >= NSEC3PARAM_MINIMUM_LENGTH); (void)nsec3param_rdata_size; nsec3_zone* n3; for(n3 = zone->nsec.nsec3; n3 != NULL; n3 = n3->next) { /* test the first 32 bits in one go */ u32 a = GET_U32_AT(n3->rdata[0]); u32 b = GET_U32_AT(nsec3param_rdata[0]); a &= NU32(0xff00ffff); b &= NU32(0xff00ffff); if(a == b) { u8 len = NSEC3_ZONE_SALT_LEN(n3); if(NSEC3PARAM_RDATA_SALT_LEN(nsec3param_rdata) == len) { if(memcmp(NSEC3_ZONE_SALT(n3), NSEC3PARAM_RDATA_SALT(nsec3param_rdata), len) == 0) { break; } } } } return n3; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec3-forall-label.c0000644000000000000000000000013214505005531022475 xustar000000000000000030 mtime=1695812441.711971719 30 atime=1695812445.800030268 30 ctime=1695812495.199737771 yadifa-2.6.5-11201/lib/dnsdb/src/nsec3-forall-label.c0000664000374500037450000001364614505005531022451 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "dnsdb/dnsdb-config.h" #include "dnscore/logger.h" #include "dnscore/thread_pool.h" #include "dnsdb/zdb-zone-lock.h" #include "dnsdb/nsec3-forall-label.h" #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; #define USE_RECURSIVE_LOCKS 0 static bool nsec3_forall_label_recursive(nsec3_forall_label_s* ctx) { #if USE_RECURSIVE_LOCKS if(ctx->zone_lock_owner != 0) zdb_zone_lock(ctx->zone, ctx->zone_lock_owner); #endif zdb_rr_label* label = nsec3_forall_label_get_label(ctx); bool nsec3_covered = FALSE; bool skip_children = FALSE; bool optout = ctx->optout; bool optin = !optout; if(!zdb_rr_label_is_apex(label)) { if(ZDB_LABEL_ATDELEGATION(label)) { skip_children = TRUE; if(!optin) { nsec3_covered |= zdb_record_find(&label->resource_record_set, TYPE_DS) != NULL; } nsec3_covered |= optin; } else if(ZDB_LABEL_UNDERDELEGATION(label)) { skip_children = TRUE; } else { nsec3_covered = !zdb_record_isempty(&label->resource_record_set); } } else { nsec3_covered = TRUE; } if(!skip_children) { ++ctx->label_stack_level; dictionary_iterator iter; dictionary_iterator_init(&label->sub, &iter); while(dictionary_iterator_hasnext(&iter)) { zdb_rr_label *sub_label = *(zdb_rr_label**)dictionary_iterator_next(&iter); /* if a child has been signed, then this one will be too */ ctx->label_stack[ctx->label_stack_level] = sub_label; nsec3_covered |= nsec3_forall_label_recursive(ctx); } --ctx->label_stack_level; } if(optout && !nsec3_covered) { #if USE_RECURSIVE_LOCKS if(ctx->zone_lock_owner != 0) zdb_zone_unlock(ctx->zone, ctx->zone_lock_owner); #endif return FALSE; } // build the fqdn of the label if(ctx->callback_need_fqdn) { u8 *p = ctx->name; for(s32 sp = ctx->label_stack_level; sp > 0; sp--) { u8 *q = ctx->label_stack[sp]->name; u8 len = *q + 1; memcpy(p, q, len); p += len; } memcpy(p, ctx->zone->origin, ctx->origin_len); ctx->name_len = (p - ctx->name) + ctx->origin_len; } ctx->nsec3_covered = nsec3_covered; // the label is nsec3-covered, what happens to it now is the responsibility of the callback ctx->callback(ctx); #if USE_RECURSIVE_LOCKS if(ctx->zone_lock_owner != 0) zdb_zone_unlock(ctx->zone, ctx->zone_lock_owner); #endif return nsec3_covered; } /** * Iterates through all labels of the zone and their associated NSEC3 record. * Generate NSEC3 data for labels missing it (not linking them together) * Calls the callback with that information. * * Calls the callback once at the end. * * @param zone * @param chain_index * @param opt_out */ void nsec3_forall_label(zdb_zone *zone, s8 chain_index, bool callback_need_fqdn, bool opt_out, bool can_ignore_signatures, u8 lock_owner, u8 reserved_owner, nsec3_forall_label_callback *callback, void *callback_args) { yassert(((lock_owner == 0) && (reserved_owner == 0)) || ((lock_owner != 0) && (reserved_owner != 0))); nsec3_forall_label_s ctx; memset(&ctx, 0, sizeof(nsec3_forall_label_s)); ctx.zone = zone; ctx.callback = callback; ctx.callback_args = callback_args; ctx.optout = opt_out; ctx.chain_index = chain_index; // no reader will ever try to read the chain in creation // (this is not enough) ctx.zone_lock_owner = lock_owner; ctx.zone_reserved_owner = reserved_owner; ctx.callback_need_fqdn = callback_need_fqdn; ctx.can_ignore_signatures = can_ignore_signatures; ctx.label_stack[0] = zone->apex; ctx.label_stack_level = 0; ctx.origin_len = dnsname_len(zone->origin); nsec3_forall_label_recursive(&ctx); ctx.last_call = TRUE; ctx.callback(&ctx); } yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec.c0000644000000000000000000000013014505005531020056 xustar000000000000000030 mtime=1695812441.740972134 30 atime=1695812445.802030296 28 ctime=1695812495.2017378 yadifa-2.6.5-11201/lib/dnsdb/src/nsec.c0000664000374500037450000006701114505005531020027 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec NSEC functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include #include "dnscore/ptr_set.h" #include "dnsdb/zdb_zone.h" #include "dnsdb/zdb-zone-lock.h" #include "dnsdb/zdb_rr_label.h" #include "dnsdb/zdb_zone_label_iterator.h" #include "dnsdb/zdb_record.h" #include "dnsdb/rrsig.h" #include "dnsdb/nsec.h" #include "dnsdb/nsec_common.h" #include "dnsdb/dynupdate-diff.h" #include "dnsdb/dynupdate-message.h" #include "dnsdb/zdb-zone-path-provider.h" /* Note : (rfc 4034) Because every authoritative name in a zone must be part of the NSEC chain, NSEC RRs must be present for names containing a CNAME RR. This is a change to the traditional DNS specification [RFC1034], which stated that if a CNAME is present for a name, it is the only type allowed at that name. An RRSIG (see Section 3) and NSEC MUST exist for the same name as does a CNAME resource record in a signed 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. */ /* * The NSEC processing must be done AFTER the RRSIG one * * Assuming there are no NSEC: * * _ Explore the zone * _ Canonize names * _ Build NSEC records * _ NSEC records have to be found quicky * _ The NSEC records are either in an array, either double-linked-listed * * Label => find the nsec record * Label => NSEC HASH => find the nsec record * * If there are NSEC records ... * * (dyn-)adding a record means adding/changing a/the NSEC record * (dyn-)removing a record means removing/changing a/the NSEC record * * What's the most efficient way to do all this ? * * First issue : canonization. * --------------------------- * * The ordering of the name is by label depth. * So the best way I can think of is to sort the actual labels in the database. * But this is not possible. Records are ordered by an hash. This is one of * most important parts of the architecture. * * Still I have to have order, so it means that for each label I have to have * a sorted (canization-wise) array for the sub-labels. * * This means a new pointer for each label in a NSEC(3) zone (ARGH) * (zdb_rr_label) * * For the eu-zone and its 3M names, we are speaking of an overhead of 24MB * (64 bits) * * Ok, I can still live with that ... * * Could I also make it so that this pointer only exists in nsec-zones ? * No. Because it means that an operation on the zone would basically require * a dup and complex size checks. I don't think it's reasonable. * * * The NSEC record is stored with other records. * The NSEC3 is not stored with other records. * */ /* NSEC: * * At zone apex ... * * For each label * If there are sub-labels * Get the sub-labels. * Canonize them. * Chain them, keep the chain. * Create the NSEC record. * Insert/Update the NSEC record in the label. * Sign the NSEC record. * * The chain contains a link to the NSEC and the RRSIG * * Recurse on sub-sub-label * */ #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; /* * New version of the NSEC handling * * Take all records * Prepare an NSEC record for them (using AVL) * For each entry in the AVL * if the entry matches keep its signature and go to the next entry * if the entry does not matches remove the old one and its signature and schedule for a new signature * */ static int nsec_update_zone_count = 0; void nsec_zone_label_detach(zdb_rr_label *rr_label) { yassert((rr_label != NULL) && zdb_rr_label_flag_isset(rr_label, ZDB_RR_LABEL_NSEC)); if((rr_label->nsec.dnssec != NULL) && (rr_label->nsec.nsec.node != NULL)) { rr_label->nsec.nsec.node->label = NULL; rr_label->nsec.nsec.node = NULL; } else { yassert((rr_label->nsec.dnssec == NULL) && (rr_label->nsec.nsec.node == NULL)); } zdb_rr_label_flag_and(rr_label, ~ZDB_RR_LABEL_NSEC); } ya_result nsec_update_zone(zdb_zone *zone, bool read_only) // read_only a.k.a slave { nsec_node *nsec_tree = NULL; nsec_node *first_node; nsec_node *node; u8 *prev_name; u8 *name; soa_rdata soa; u32 missing_nsec_records = 0; u32 sibling_count = 0; u32 nsec_under_delegation = 0; ya_result return_code; u8 name_buffer[2][MAX_DOMAIN_LENGTH]; u8 inverse_name[MAX_DOMAIN_LENGTH]; u8 tmp_bitmap[256 * (1 + 1 + 32)]; /* 'max window count' * 'max window length' */ yassert(zdb_zone_islocked_weak(zone)); if(FAIL(return_code = zdb_zone_getsoa(zone, &soa))) // zone is locked (weak) { return return_code; } #if DEBUG memset(name_buffer, 0xde, sizeof(name_buffer)); #endif name = &name_buffer[0][0]; prev_name = &name_buffer[1][0]; zdb_zone_label_iterator label_iterator; zdb_zone_label_iterator_init(&label_iterator, zone); while(zdb_zone_label_iterator_hasnext(&label_iterator)) { zdb_zone_label_iterator_nextname(&label_iterator, name); zdb_rr_label* label = zdb_zone_label_iterator_next(&label_iterator); if(zdb_rr_label_is_glue(label) || (label->resource_record_set == NULL)) { // we are under a delegation or on an empty (non-terminal) // there should not be an NSEC record here if(zdb_record_find(&label->resource_record_set, TYPE_NSEC) != NULL) // zone is locked { nsec_under_delegation++; log_err("nsec: %{dnsname}: unexpected NSEC record under a delegation", name); } continue; } nsec_inverse_name(inverse_name, name); nsec_node *node = nsec_insert(&nsec_tree, inverse_name); node->label = label; label->nsec.nsec.node = node; } /* * Now that we have the NSEC chain */ type_bit_maps_context tbmctx; nsec_iterator nsec_iter; nsec_iterator_init(&nsec_tree, &nsec_iter); if(nsec_iterator_hasnext(&nsec_iter)) { first_node = nsec_iterator_next_node(&nsec_iter); node = first_node; do { nsec_node *next_node; nsec_update_zone_count++; if(nsec_iterator_hasnext(&nsec_iter)) { next_node = nsec_iterator_next_node(&nsec_iter); } else { next_node = first_node; } /* * Compute the type bitmap */ zdb_rr_label *label = node->label; if(label == NULL) { node = next_node; continue; } u32 tbm_size = nsec_type_bit_maps_initialise_from_label(&tbmctx, label, TRUE, TRUE); type_bit_maps_write(&tbmctx, tmp_bitmap); u8 *tmp_name = prev_name; prev_name = name; name = tmp_name; nsec_inverse_name(name, next_node->inverse_relative_name); /* * Get the NSEC record */ zdb_packed_ttlrdata *nsec_record; if((nsec_record = zdb_record_find(&label->resource_record_set, TYPE_NSEC)) != NULL) // zone is locked { /* * has record -> compare the type and the nsec next * if something does not match remove the record and its signature (no record) * */ if(nsec_record->next == NULL) // should only be one record => delete all if not the case (the rrsig is lost anyway) { const u8 *rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec_record); const u16 size = ZDB_PACKEDRECORD_PTR_RDATASIZE(nsec_record); const u16 dname_len = dnsname_len(rdata); if(dname_len < size) { const u8 *type_bitmap = &rdata[dname_len]; /* * check the type bitmap */ if(memcmp(tmp_bitmap, type_bitmap, size - dname_len) == 0) { /* * check the nsec next */ if(dnsname_equals(rdata, name)) { /* All good */ zdb_rr_label_flag_or(label, ZDB_RR_LABEL_NSEC); zdb_rr_label_flag_and(label, ~(ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT)); node = next_node; continue; } else // else the "next fqdn" do not match (this is irrecoverable for a slave) { rdata_desc nsec_desc = {TYPE_NSEC, size, rdata}; log_debug("nsec: %{dnsname}: src: %{dnsname} %{typerdatadesc} next field do not match expected value (%{dnsname})", zone->origin, prev_name, &nsec_desc, name); } } else // else the type bitmap do not match (this is wrong) { rdata_desc nsec_desc = {TYPE_NSEC, size, rdata}; log_debug("nsec: %{dnsname}: src: %{dnsname} %{typerdatadesc} types map do not match expected value", zone->origin, prev_name, &nsec_desc); } } else // else the "next fqdn" do not match (early test, this is irrecoverable for a slave) { rdata_desc nsec_desc = {TYPE_NSEC, size, rdata}; log_debug("nsec: %{dnsname}: src: %{dnsname} %{typerdatadesc} next field do not match expected value (%{dnsname})", zone->origin, prev_name, &nsec_desc, name); } } else { sibling_count++; log_warn("nsec: %{dnsname}: %{dnsname}: multiple NSEC records where only one is expected", zone->origin, prev_name); } // wrong NSEC RRSET zdb_packed_ttlrdata *nsec_rec = nsec_record; do { zdb_ttlrdata unpacked_ttlrdata; unpacked_ttlrdata.ttl = nsec_rec->ttl; unpacked_ttlrdata.rdata_size = ZDB_PACKEDRECORD_PTR_RDATASIZE(nsec_rec); unpacked_ttlrdata.rdata_pointer = ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec_rec); rdata_desc nsec_desc = {TYPE_NSEC, unpacked_ttlrdata.rdata_size, unpacked_ttlrdata.rdata_pointer}; if(!read_only) { log_warn("nsec: %{dnsname}: del: %{dnsname} %{typerdatadesc}", zone->origin, prev_name, &nsec_desc); } else { log_err("nsec: %{dnsname}: got: %{dnsname} %{typerdatadesc}", zone->origin, prev_name, &nsec_desc); } nsec_rec = nsec_rec->next; } while(nsec_rec != NULL); if(!read_only) { zdb_record_delete(&label->resource_record_set, TYPE_NSEC); rrsig_delete(zone, name, label, TYPE_NSEC); nsec_record = NULL; } } /* * no record -> create one and schedule a signature (MASTER ONLY) */ if(nsec_record == NULL) { missing_nsec_records++; zdb_packed_ttlrdata *nsec_record; u16 dname_len = nsec_inverse_name(name, next_node->inverse_relative_name); u16 rdata_size = dname_len + tbm_size; ZDB_RECORD_ZALLOC_EMPTY(nsec_record, soa.minimum, rdata_size); u8* rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec_record); memcpy(rdata, name, dname_len); rdata += dname_len; memcpy(rdata, tmp_bitmap, tbm_size); rdata_desc nsec_desc = {TYPE_NSEC, ZDB_PACKEDRECORD_PTR_RDATASIZE(nsec_record), ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec_record)}; if(!read_only) { zdb_record_insert(&label->resource_record_set, TYPE_NSEC, nsec_record); #if DEBUG log_debug("nsec: %{dnsname}: add: %{dnsname} %{typerdatadesc}", zone->origin, prev_name, &nsec_desc); #endif /* * Schedule a signature */ } else { log_warn("nsec: %{dnsname}: need: %{dnsname} %{typerdatadesc}", zone->origin, prev_name, &nsec_desc); ZDB_RECORD_ZFREE(nsec_record); } } zdb_rr_label_flag_or(label, ZDB_RR_LABEL_NSEC); zdb_rr_label_flag_and(label, ~(ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT)); node = next_node; } while(node != first_node); } zone->nsec.nsec = nsec_tree; if(read_only) { if(missing_nsec_records + sibling_count + nsec_under_delegation) { log_err("nsec: missing records: %u, nsec with siblings: %u, nsec under delegation: %u", missing_nsec_records, sibling_count, nsec_under_delegation); //return DNSSEC_ERROR_NSEC_INVALIDZONESTATE; } } else { if(missing_nsec_records + sibling_count + nsec_under_delegation) { log_warn("nsec: missing records: %u, nsec with siblings: %u, nsec under delegation: %u", missing_nsec_records, sibling_count, nsec_under_delegation); } } return SUCCESS; } /** * Reverses the labels of the fqdn * * @param inverse_name * @param name * @return * * 3 www 5 eurid 2 eu 0 * * 3 5 2 0 */ u32 nsec_inverse_name(u8 *inverse_name, const u8 *name) { dnslabel_vector labels; s32 vtop = dnsname_to_dnslabel_vector(name, labels); u32 ret = dnslabel_stack_to_dnsname(labels, vtop, inverse_name); return ret; } /** * Verifies and, if needed, update the NSEC record. * There WILL be an NSEC record in the label at the end of the call. * It does NOT create the NSEC node (needs it created already). * It does NOT check for the relevancy of the NSEC record. * * @param label * @param node * @param next_node * @param name * @param ttl * @return */ bool nsec_update_label_record(zdb_zone *zone, zdb_rr_label *label, nsec_node *item, nsec_node *next_item, u8 *name) { yassert(zdb_zone_islocked(zone)); type_bit_maps_context tbmctx; u8 tmp_bitmap[256 * (1 + 1 + 32)]; /* 'max window count' * 'max window length' */ u32 tbm_size = nsec_type_bit_maps_initialise_from_label(&tbmctx, label, TRUE, TRUE); u32 ttl = zone->min_ttl; type_bit_maps_write(&tbmctx, tmp_bitmap); /* * Get the NSEC record */ zdb_packed_ttlrdata *nsec_record; if((nsec_record = zdb_record_find(&label->resource_record_set, TYPE_NSEC)) != NULL) // zone is locked { /* * has record -> compare the type and the nsec next * if something does not match remove the record and its signature (no record) * */ log_debug("nsec_update_label_record: [%{dnsname}] %{dnsname} (=> %{dnsname}) updating record.", name, item->inverse_relative_name, next_item->inverse_relative_name); /* * If there is more than one record, clean-up */ if(nsec_record->next == NULL) { u8* rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec_record); u16 size = ZDB_PACKEDRECORD_PTR_RDATASIZE(nsec_record); u16 dname_len = dnsname_len(rdata); if(dname_len < size) { u8* type_bitmap = &rdata[dname_len]; /* * check the type bitmap */ if(memcmp(tmp_bitmap, type_bitmap, size - dname_len) == 0) { /* * check the nsec next */ u8 tmp_name[MAX_DOMAIN_LENGTH]; nsec_inverse_name(tmp_name, next_item->inverse_relative_name); if(dnsname_equals(rdata, tmp_name)) { /* All good */ return FALSE; } } } } zdb_record_delete(&label->resource_record_set, TYPE_NSEC); rrsig_delete(zone, name, label, TYPE_NSEC); nsec_record = NULL; } /* * no record -> create one and schedule a signature */ if(nsec_record == NULL) { zdb_packed_ttlrdata *nsec_record; u8 next_name[256]; log_debug("nsec_update_label_record: [%{dnsname}] %{dnsname} (=> %{dnsname}) building new record.", name, item->inverse_relative_name, next_item->inverse_relative_name); u16 dname_len = nsec_inverse_name(next_name, next_item->inverse_relative_name); u16 rdata_size = dname_len + tbm_size; ZDB_RECORD_ZALLOC_EMPTY(nsec_record, ttl, rdata_size); u8* rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(nsec_record); memcpy(rdata, next_name, dname_len); rdata += dname_len; memcpy(rdata, tmp_bitmap, tbm_size); zdb_record_insert(&label->resource_record_set, TYPE_NSEC, nsec_record); /* * Schedule a signature */ } zdb_rr_label_flag_or(label, ZDB_RR_LABEL_NSEC); zdb_rr_label_flag_and(label, ~(ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT)); return TRUE; } /** * Creates the NSEC node, link it to the label. * * @param zone * @param label * @param labels * @param labels_top * @return */ nsec_node * nsec_update_label_node(zdb_zone* zone, zdb_rr_label* label, dnslabel_vector_reference labels, s32 labels_top) { u8 inverse_name[MAX_DOMAIN_LENGTH]; dnslabel_stack_to_dnsname(labels, labels_top, inverse_name); nsec_node *node = nsec_insert(&zone->nsec.nsec, inverse_name); node->label = label; label->nsec.nsec.node = node; zdb_rr_label_flag_or(label, ZDB_RR_LABEL_NSEC); zdb_rr_label_flag_and(label, ~(ZDB_RR_LABEL_NSEC3|ZDB_RR_LABEL_NSEC3_OPTOUT)); #if DEBUG memset(inverse_name, 0xff, sizeof(inverse_name)); log_debug("nsec_update_label_node: %{dnsname}", node->inverse_relative_name); #endif return node; } /** * * Unlink the NSEC node from the label, then deletes said node from the chain. * * @param zone * @param label * @param labels * @param labels_top * @return */ bool nsec_delete_label_node(zdb_zone *zone, dnslabel_vector_reference labels, s32 labels_top) { u8 inverse_name[MAX_DOMAIN_LENGTH]; dnslabel_stack_to_dnsname(labels, labels_top, inverse_name); nsec_node *node = nsec_find(&zone->nsec.nsec, inverse_name); if(node != NULL) { if(node->label != NULL) { zdb_rr_label_flag_and(node->label, ~ZDB_RR_LABEL_NSEC); node->label->nsec.nsec.node = NULL; node->label = NULL; } nsec_delete(&zone->nsec.nsec, inverse_name); #if DEBUG log_debug("nsec_delete_label_node: %{dnsname}", inverse_name); #endif return TRUE; } else { #if DEBUG log_debug("nsec_delete_label_node: %{dnsname} has not been found", inverse_name); #endif return FALSE; } } /** * Creates the NSEC node, creates or update the NSEC record * * @param zone * @param label * @param labels * @param labels_top */ void nsec_update_label(zdb_zone* zone, zdb_rr_label* label, dnslabel_vector_reference labels, s32 labels_top) { u8 name[MAX_DOMAIN_LENGTH]; /* Create or get the node */ nsec_node *node = nsec_update_label_node(zone, label, labels, labels_top); /* Get the next node */ nsec_node *next_node = nsec_node_mod_next(node); dnslabel_vector_to_dnsname(labels, labels_top, name); nsec_update_label_record(zone, label, node, next_node, name); } void nsec_destroy_zone(zdb_zone *zone) { if(!nsec_isempty(&zone->nsec.nsec)) { nsec_iterator iter; nsec_iterator_init(&zone->nsec.nsec,&iter); while(nsec_iterator_hasnext(&iter)) { nsec_node *node = nsec_iterator_next_node(&iter); if(node->label != NULL) { node->label->nsec.nsec.node = NULL; zdb_rr_label_flag_and(node->label, ~ZDB_RR_LABEL_NSEC); } } nsec_destroy(&zone->nsec.nsec); } } /** * * Find the label that has got the right NSEC interval for "nextname" * * @param zone * @param name_vector * @param dname_out * @return */ zdb_rr_label * nsec_find_interval(const zdb_zone *zone, const dnsname_vector *name_vector, u8 **out_dname_p, u8 * restrict * pool) { u8 dname_inverted[MAX_DOMAIN_LENGTH]; dnslabel_stack_to_dnsname(name_vector->labels, name_vector->size, dname_inverted); nsec_node *node = nsec_find_interval_start(&zone->nsec.nsec, dname_inverted); u8 *out_dname = *pool; *out_dname_p = out_dname; u32 out_dname_len = nsec_inverse_name(out_dname, node->inverse_relative_name); *pool += ALIGN16(out_dname_len); return node->label; } void nsec_name_error(const zdb_zone* zone, const dnsname_vector *name, s32 closest_index, u8 * restrict * pool, u8 **out_encloser_nsec_name_p, zdb_rr_label **out_encloser_nsec_label, u8 **out_wild_encloser_nsec_name_p, zdb_rr_label **out_wildencloser_nsec_label ) { u32 len; u8 dname_inverted[MAX_DOMAIN_LENGTH + 2]; dnslabel_stack_to_dnsname(name->labels, name->size, dname_inverted); nsec_node *node = nsec_find_interval_start(&zone->nsec.nsec, dname_inverted); u8 *out_encloser_nsec_name = *pool; *out_encloser_nsec_name_p = out_encloser_nsec_name; len = nsec_inverse_name(out_encloser_nsec_name, node->inverse_relative_name); *pool += ALIGN16(len); dnslabel_stack_to_dnsname(&name->labels[closest_index], name->size - closest_index, dname_inverted); nsec_node *wild_node = nsec_find_interval_start(&zone->nsec.nsec, dname_inverted); if(wild_node != node) { u8 *out_wild_encloser_nsec_name = *pool; *out_wild_encloser_nsec_name_p = out_wild_encloser_nsec_name; len = nsec_inverse_name(out_wild_encloser_nsec_name, wild_node->inverse_relative_name); *pool += ALIGN16(len); } *out_encloser_nsec_label = node->label; *out_wildencloser_nsec_label = wild_node->label; } void nsec_logdump_tree(zdb_zone *zone) { log_debug("dumping zone %{dnsname} nsec tree", zone->origin); nsec_iterator iter; nsec_iterator_init(&zone->nsec.nsec, &iter); while(nsec_iterator_hasnext(&iter)) { nsec_node *node = nsec_iterator_next_node(&iter); log_debug("%{dnsname}", node->inverse_relative_name); } log_debug("done dumping zone %{dnsname} nsec tree", zone->origin); } #if HAS_MASTER_SUPPORT /** * marks the zone with private records * * @param zone * @param status * * @return an error code */ ya_result nsec_zone_set_status(zdb_zone *zone, u8 secondary_lock, u8 status) { dynupdate_message dmsg; packet_unpack_reader_data reader; dynupdate_message_init(&dmsg, zone->origin, CLASS_IN); u8 prev_status = 0; u8 nsecparamadd_rdata[1]; nsecparamadd_rdata[0] = status; // look for the matching record if(nsec_zone_get_status(zone, &prev_status) == 1) { // if the record exists, remove it and add it dynupdate_message_del_record_set(&dmsg, zone->origin, TYPE_NSECCHAINSTATE); } dynupdate_message_add_record(&dmsg, zone->origin, TYPE_NSECCHAINSTATE, 0, 1, nsecparamadd_rdata); dynupdate_message_set_reader(&dmsg, &reader); u16 count = dynupdate_message_get_count(&dmsg); packet_reader_skip(&reader, DNS_HEADER_LENGTH); // checked below packet_reader_skip_fqdn(&reader); // checked below packet_reader_skip(&reader, 4); // checked below ya_result ret; if(!packet_reader_eof(&reader)) { ret = dynupdate_diff(zone, &reader, count, secondary_lock, DYNUPDATE_DIFF_RUN); if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { // trigger a background store of the zone zdb_zone_info_background_store_zone(zone->origin); } } else { ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } dynupdate_message_finalize(&dmsg); return ret; } #endif /** * gets the zone status from private records * * @param zone * @param statusp * * @return an error code */ ya_result nsec_zone_get_status(zdb_zone *zone, u8 *statusp) { // get the TYPE_NSEC3PARAMADD record set // search for a record matching the chain zdb_packed_ttlrdata *rrset = zdb_record_find(&zone->apex->resource_record_set, TYPE_NSECCHAINSTATE); if(rrset != NULL) { *statusp = rrset->rdata_start[0]; return 1; } return 0; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec-chain-replay.c0000644000000000000000000000013214505005531022432 xustar000000000000000030 mtime=1695812441.690971418 30 atime=1695812445.799030253 30 ctime=1695812495.203737828 yadifa-2.6.5-11201/lib/dnsdb/src/nsec-chain-replay.c0000664000374500037450000002723314505005531022403 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec NSEC functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #include #include #include "dnsdb/zdb_types.h" #include "dnsdb/nsec-chain-replay.h" #include "dnsdb/nsec.h" #include "dnsdb/rrsig.h" #include "dnsdb/zdb-zone-arc.h" #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; #define NSEC_CHAIN_REPLAY_DEBUG 0 #define NSEC3CNR_TAG 0x524e433345534e #define NSEC3RPL_TAG 0x4c50523345534e struct nsec_chain_replay_record { u8 status; u8 fqdn[]; }; typedef struct nsec_chain_replay_record nsec_chain_replay_record; static nsec_chain_replay_record * nsec_chain_replay_record_new(const u8 *fqdn, s32 ttl, const u8 *rdata, u16 rdata_size) { nsec_chain_replay_record *record; int fqdn_len = dnsname_len(fqdn); ZALLOC_ARRAY_OR_DIE(nsec_chain_replay_record*, record, sizeof(nsec_chain_replay_record) + fqdn_len, NSEC3CNR_TAG); (void)ttl; (void)rdata; (void)rdata_size; record->status = 0; memcpy(record->fqdn, fqdn, fqdn_len); return record; } static void nsec_chain_replay_record_delete(nsec_chain_replay_record *record) { int fqdn_len = dnsname_len(record->fqdn); ZFREE_ARRAY(record, sizeof(nsec_chain_replay_record) + fqdn_len); } static void nsec_chain_replay_record_delete_cb(void *record) { nsec_chain_replay_record_delete((nsec_chain_replay_record*)record); } static const u8 * nsec_chain_replay_record_fqdn(nsec_chain_replay_record *record) { return record->fqdn; } static int nsec_chain_replay_record_nsec_compare(const void *a, const void *b) { nsec_chain_replay_record *ra = (nsec_chain_replay_record*)a; nsec_chain_replay_record *rb = (nsec_chain_replay_record*)b; int d = dnsname_compare(nsec_chain_replay_record_fqdn(ra), nsec_chain_replay_record_fqdn(rb)); return d; } struct nsec_chain_replay_data { zdb_zone *zone; ptr_vector del_nsec_records; ptr_vector add_nsec_records; }; typedef struct nsec_chain_replay_data nsec_chain_replay_data; static ya_result nsec_chain_replay_record_del(chain_replay *cr, const u8 *fqdn, u16 rtype, const zdb_ttlrdata *ttlrdata) { nsec_chain_replay_data *crd = (nsec_chain_replay_data*)cr->data; #if NSEC_CHAIN_REPLAY_DEBUG rdata_desc type_len_rdata = {rtype, ZDB_RECORD_PTR_RDATASIZE(ttlrdata), ZDB_RECORD_PTR_RDATAPTR(ttlrdata)}; log_debug("nsec-chain: del %{dnsname} %{typerdatadesc}", fqdn, &type_len_rdata); #endif switch(rtype) { case TYPE_NSEC: { ptr_vector_append(&crd->del_nsec_records, nsec_chain_replay_record_new(fqdn, ttlrdata->ttl, ZDB_RECORD_PTR_RDATAPTR(ttlrdata), ZDB_RECORD_PTR_RDATASIZE(ttlrdata))); return 0; } default: { return 0; } } } static ya_result nsec_chain_replay_record_add(chain_replay *cr, const u8 *fqdn, u16 rtype, const zdb_ttlrdata *ttlrdata) { nsec_chain_replay_data *crd = (nsec_chain_replay_data*)cr->data; #if NSEC_CHAIN_REPLAY_DEBUG rdata_desc type_len_rdata = {rtype, ZDB_RECORD_PTR_RDATASIZE(ttlrdata), ZDB_RECORD_PTR_RDATAPTR(ttlrdata)}; log_debug("nsec-chain: add %{dnsname} %{typerdatadesc}", fqdn, &type_len_rdata); #endif switch(rtype) { case TYPE_NSEC: { ptr_vector_append(&crd->add_nsec_records, nsec_chain_replay_record_new(fqdn, ttlrdata->ttl, ZDB_RECORD_PTR_RDATAPTR(ttlrdata), ZDB_RECORD_PTR_RDATASIZE(ttlrdata))); return 0; } default: { return 0; } } } static ya_result nsec_chain_replay_execute(chain_replay *cr) { // sort NSEC records by chain,fqdn // verify chains are making sense // remove signatures from the relevant nsec_zone // remove nodes from the relevant nsec_zone // add nodes to the relevant nsec_zone // add signatures to the relevant nsec_zone // if an nsecparam was removed, choose the new best chain // (start) unlink old chain and add new chain nsec_chain_replay_data *crd = (nsec_chain_replay_data*)cr->data; dnslabel_vector labels; ptr_set del_nsec_set = PTR_SET_DNSNAME_EMPTY; ptr_vector_qsort(&crd->del_nsec_records, nsec_chain_replay_record_nsec_compare); ptr_vector_qsort(&crd->add_nsec_records, nsec_chain_replay_record_nsec_compare); for(int i = 0; i < ptr_vector_size(&crd->del_nsec_records); ++i) { nsec_chain_replay_record *record = (nsec_chain_replay_record*)ptr_vector_get(&crd->del_nsec_records, i); // check the record exists // find the chain // find the record // keep a quick access on the record ptr_node *node = ptr_set_insert(&del_nsec_set, (u8*)nsec_chain_replay_record_fqdn(record)); if(node->value == NULL) { node->value = record; } else { // duplicate : something is wrong } } for(int i = 0; i < ptr_vector_size(&crd->add_nsec_records); ++i) { nsec_chain_replay_record *record = (nsec_chain_replay_record*)ptr_vector_get(&crd->add_nsec_records, i); // find the start of a sub-chain // find the end of the sub-chain // if the sub-chain is not looping, the head must exist (and is being removed/added) // check for updates ptr_node *node = ptr_set_find(&del_nsec_set, nsec_chain_replay_record_fqdn(record)); if(node != NULL) { // the record is updated nsec_chain_replay_record *old_record = (nsec_chain_replay_record*)node->value; record->status = 1; old_record->status = 1; } } for(int i = ptr_vector_size(&crd->add_nsec_records); i >= 0; --i) { // check the next record exist or is // find the chain // find the record } // everything checks out : lock the zone for writing for(int i = 0; i < ptr_vector_size(&crd->del_nsec_records); ++i) { nsec_chain_replay_record *record = (nsec_chain_replay_record*)ptr_vector_get(&crd->del_nsec_records, i); if(record->status == 0) { #if NSEC_CHAIN_REPLAY_DEBUG log_debug("nsec-chain: - %{dnsname}", nsec_chain_replay_record_fqdn(record)); #endif s32 labels_top = dnsname_to_dnslabel_vector(record->fqdn, labels); nsec_delete_label_node(crd->zone, labels, labels_top); zdb_rr_label* label = zdb_rr_label_find_exact(crd->zone->apex, labels, labels_top - crd->zone->origin_vector.size - 1); if(label != NULL) { if(RR_LABEL_IRRELEVANT(label)) // irrelevant and RR_LABEL_EMPTY_TERMINAL should be equivalent here { ya_result ret; // the zdb_rr_label_delete_record checks that the label has no children, no records and no entry in the DNSSEC chain if(FAIL(ret = zdb_rr_label_delete_record(crd->zone, labels, labels_top - crd->zone->origin_vector.size - 1, TYPE_ANY))) { log_err("nsec-chain: - %{dnsname} could not be removed from the zone: %r", nsec_chain_replay_record_fqdn(record), ret); } } } } // else the record is being updated } for(int i = 0; i < ptr_vector_size(&crd->add_nsec_records); ++i) { nsec_chain_replay_record *record = (nsec_chain_replay_record*)ptr_vector_get(&crd->add_nsec_records, i); if(record->status == 0) { // insert the new record #if NSEC_CHAIN_REPLAY_DEBUG log_debug("nsec-chain: + %{dnsname}", nsec_chain_replay_record_fqdn(record)); #endif s32 labels_top = dnsname_to_dnslabel_vector(record->fqdn, labels); zdb_rr_label* label = zdb_rr_label_find_exact(crd->zone->apex, labels, labels_top - crd->zone->origin_vector.size - 1); if(label != NULL) { nsec_update_label_node(crd->zone, label, labels, labels_top); } } else { #if NSEC_CHAIN_REPLAY_DEBUG log_debug("nsec-chain: ~ %{dnsname}", nsec_chain_replay_record_fqdn(record)); #endif } } // unlock the zone for writing ptr_set_destroy(&del_nsec_set); ptr_vector_callback_and_clear(&crd->del_nsec_records, nsec_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->add_nsec_records, nsec_chain_replay_record_delete_cb); return SUCCESS; } static void nsec_chain_replay_finalize(chain_replay *cr) { nsec_chain_replay_data *crd = (nsec_chain_replay_data*)cr->data; ptr_vector_callback_and_clear(&crd->del_nsec_records, nsec_chain_replay_record_delete_cb); ptr_vector_callback_and_clear(&crd->add_nsec_records, nsec_chain_replay_record_delete_cb); ptr_vector_destroy(&crd->del_nsec_records); ptr_vector_destroy(&crd->add_nsec_records); zdb_zone_release(crd->zone); crd->zone = NULL; // release memory ZFREE_OBJECT(crd); cr->data = NULL; } static const struct chain_replay_vtbl nsec_chain_replay_vtbl = { nsec_chain_replay_record_add, nsec_chain_replay_record_del, nsec_chain_replay_execute, nsec_chain_replay_finalize, "nsec_chain_replay" }; ya_result nsec_chain_replay_init(chain_replay *cr, zdb_zone *zone) { nsec_chain_replay_data *data; ZALLOC_OBJECT_OR_DIE(data, nsec_chain_replay_data, NSEC3RPL_TAG); ptr_vector_init(&data->del_nsec_records); ptr_vector_init(&data->add_nsec_records); zdb_zone_acquire(zone); data->zone = zone; cr->vtbl = &nsec_chain_replay_vtbl; cr->data = data; return SUCCESS; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/src/PaxHeaders.1636/nsec_collection.c0000644000000000000000000000013214505005531022273 xustar000000000000000030 mtime=1695812441.747972234 30 atime=1695812445.802030296 30 ctime=1695812495.205737857 yadifa-2.6.5-11201/lib/dnsdb/src/nsec_collection.c0000664000374500037450000001763214505005531022246 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup nsec NSEC functions * @ingroup dnsdbdnssec * @brief * * * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "dnsdb/dnsdb-config.h" #include #include #define _NSEC_COLLECTION_C #define DEBUG_LEVEL 0 #include #include "dnsdb/nsec_collection.h" /* * The following macros are defining relevant fields in the node */ /* * Access to the field that points to the left child */ #define AVL_LEFT_CHILD(node) ((node)->children.lr.left) /* * Access to the field that points to the right child */ #define AVL_RIGHT_CHILD(node) ((node)->children.lr.right) /* * Access to the field that points to one of the children (0: left, 1: right) */ #define AVL_CHILD(node,id) ((node)->children.child[(id)]) /* * OPTIONAL : Access to the field that points the parent of the node. * * This field is optional but is mandatory if AVL_HAS_PARENT_POINTER is not 0 */ #define AVL_PARENT(node) ((node)->parent) /* * Access to the field that keeps the balance (a signed byte) */ #define AVL_BALANCE(node) ((node)->balance) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u8* /* * */ #define AVL_REFERENCE_FORMAT_STRING "%{dnsname}" #define AVL_REFERENCE_FORMAT(reference) reference /* * A macro to initialize a node and setting the reference */ #define AVL_INIT_NODE(node,reference) (node)->inverse_relative_name=dnsname_zdup(reference) /* * A macro to allocate a new node */ #define AVL_ALLOC_NODE(node,reference) \ ZALLOC_ARRAY_OR_DIE(AVL_NODE_TYPE*, node, (sizeof(AVL_NODE_TYPE)), NSECNODE_TAG); \ ZEROMEMORY(node,sizeof(AVL_NODE_TYPE)) /* * A macro to free a node allocated by ALLOC_NODE */ static void nsec_free_node(AVL_NODE_TYPE* node) { ZFREE_ARRAY(node, sizeof(AVL_NODE_TYPE)); } #define AVL_FREE_NODE(node) nsec_free_node(node) /* * A macro to print the node */ #define AVL_DUMP_NODE(node) format("node@%p",(node)); /* * A macro that returns the reference field of the node. * It must be of type REFERENCE_TYPE */ #define AVL_REFERENCE(node) (node)->inverse_relative_name #define AVL_TERNARYCMP 1 #if !AVL_TERNARYCMP /* * A macro to compare two references * Returns TRUE if and only if the references are equal. */ #define AVL_ISEQUAL(reference_a,reference_b) dnsname_equals((reference_a),(reference_b)) /* * A macro to compare two references * Returns TRUE if and only if the first one is bigger than the second one. */ #define AVL_ISBIGGER(reference_a,reference_b) (dnsname_compare((reference_a),(reference_b))>0) #else #define AVL_COMPARE(reference_a,reference_b) (dnsname_compare((reference_a),(reference_b))) #endif /* * Copies the payload of a node * It MUST NOT copy the "proprietary" node fields : children, parent, balance */ #define AVL_COPY_PAYLOAD(node_trg,node_src) (node_trg)->inverse_relative_name=(node_src)->inverse_relative_name /* * A macro to preprocess a node before it is preprocessed for a delete (detach) * If there was anything to do BEFORE deleting a node, we would do it here * After this macro is exectuted, the node * _ is detached, then deleted with FREE_NODE * _ has got its content overwritten by the one of another node, then the other * node is deleted with FREE_NODE */ #define AVL_NODE_DELETE_CALLBACK(node) dnsname_zfree((node)->inverse_relative_name); #include AVL_NODE_TYPE* AVL_PREFIXED(find_interval_start)(AVL_CONST_TREE_TYPE* root, AVL_REFERENCE_TYPE obj_hash) { const AVL_NODE_TYPE* node = *root; const AVL_NODE_TYPE* lower_bound = NULL; AVL_REFERENCE_TYPE h; yassert(node != NULL); /* This is one of the parts I could try to optimize * I've checked the assembly, and it sucks ... */ /* Both the double-test while/ternary and the current one * are producing the same assembly code. */ while(node != NULL) { h = AVL_REFERENCE(node); /* * [0] is the length of the obj_hash * * The obj_hashs starts at [1] * */ int cmp = dnsname_compare(obj_hash, h); /* equals */ if(cmp == 0) { return (AVL_NODE_TYPE*)node; } /* bigger */ if(cmp > 0) { lower_bound = node; node = AVL_CHILD(node, DIR_RIGHT); } else { node = AVL_CHILD(node, DIR_LEFT); } } if(lower_bound == NULL) { lower_bound = *root; yassert(lower_bound != NULL); while((node = AVL_CHILD(lower_bound, DIR_RIGHT)) != NULL) // VS false positive: an assert says this can't happen { lower_bound = node; } } return (AVL_NODE_TYPE*)lower_bound; } AVL_NODE_TYPE* AVL_PREFIXED(find_interval_prev_mod)(AVL_CONST_TREE_TYPE* root, const AVL_REFERENCE_TYPE obj_hash) { AVL_NODE_TYPE* node = *root; AVL_NODE_TYPE* lower_bound = NULL; AVL_REFERENCE_TYPE h; yassert(node != NULL); /* Both the double-test while/ternary and the current one * are producing the same assembly code. */ /** * Get a key that */ while(node != NULL) { h = AVL_REFERENCE(node); /* * [0] is the length of the obj_hash * * The obj_hashs starts at [1] * */ int cmp = dnsname_compare(obj_hash, h); /* equals */ if(cmp == 0) { return nsec_node_mod_prev(node); } /* bigger */ if(cmp > 0) { lower_bound = node; node = AVL_CHILD(node, DIR_RIGHT); } else { node = AVL_CHILD(node, DIR_LEFT); } } if(lower_bound == NULL) { lower_bound = *root; yassert(lower_bound != NULL); while((node = AVL_CHILD(lower_bound, DIR_RIGHT)) != NULL) // VS false positive: an assert says this can't happen { lower_bound = node; } } return lower_bound; } /** @} */ yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/Makefile.in0000644000000000000000000000013214505005547020251 xustar000000000000000030 mtime=1695812455.156164266 30 atime=1695812461.832259882 30 ctime=1695812494.882733231 yadifa-2.6.5-11201/lib/dnsdb/Makefile.in0000664000374500037450000017067314505005547020231 0ustar00signersigner00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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@ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ # # ALL # ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ 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@ DIST_COMMON = $(srcdir)/../../mk/common-settings.mk \ $(srcdir)/../../mk/common-labels.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp \ $(dist_noinst_DATA) $(am__pkginclude_HEADERS_DIST) AUTHORS \ COPYING ChangeLog INSTALL NEWS README @USES_SUNC_TRUE@am__append_1 = @USES_SUNC_FALSE@am__append_2 = -O0 @IS_DARWIN_OS_TRUE@am__append_3 = -Wno-deprecated @HAS_CC_NO_IDENT_TRUE@am__append_4 = -fno-ident @HAS_CC_ANSI_TRUE@am__append_5 = -ansi @HAS_CC_PEDANTIC_TRUE@am__append_6 = -pedantic @HAS_CC_WALL_TRUE@am__append_7 = -Wall -Wno-unknown-pragmas @HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE@am__append_8 = -Werror=missing-field-initializers @HAS_CC_STD_GNU11_TRUE@am__append_9 = -std=gnu11 @HAS_CC_STD_C11_TRUE@@HAS_CC_STD_GNU11_FALSE@am__append_10 = -std=c11 -D_GNU_SOURCE @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_TRUE@am__append_11 = -std=gnu99 @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_C99_TRUE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_FALSE@am__append_12 = -std=c99 @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_C99_FALSE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_FALSE@@HAS_CC_XC99_TRUE@am__append_13 = -xc99 @HAS_CC_TUNE_NATIVE_TRUE@am__append_14 = -mtune=native @FORCE64BITS_TRUE@@HAS_CC_M64_TRUE@am__append_15 = -m64 @FORCE64BITS_TRUE@@HAS_CC_M64_TRUE@am__append_16 = -m64 @FORCE32BITS_TRUE@@FORCE64BITS_FALSE@@HAS_CC_M32_TRUE@am__append_17 = -m32 @FORCE32BITS_TRUE@@FORCE64BITS_FALSE@@HAS_CC_M32_TRUE@am__append_18 = -m32 # # DEBUG # @HAS_CC_G3_TRUE@am__append_19 = -g3 @HAS_CC_G3_FALSE@@HAS_CC_G_TRUE@am__append_20 = -g @HAS_CC_DWARF4_TRUE@am__append_21 = -gdwarf-4 @HAS_CC_DWARF3_TRUE@@HAS_CC_DWARF4_FALSE@am__append_22 = -gdwarf-3 # # Intel C Compiler # ############################################################################### #ICC #IPO= -ipo (need to use the intel xiar instead of ar) @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@am__append_23 = -DLTO -ipo @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@am__append_24 = -ipo @USES_ICC_TRUE@am__append_25 = -DUSES_ICC @HAS_CC_ANSI_ALIAS_TRUE@@USES_ICC_TRUE@am__append_26 = -ansi-alias -U__STRICT_ANSI__ @USES_ICC_TRUE@am__append_27 = -DMODE_DEBUG_ICC # # LLVM Clang # ############################################################################### # CLANG @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@am__append_28 = -DLTO -flto @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@am__append_29 = -flto @USES_CLANG_TRUE@am__append_30 = -DUSES_LLVM -Wno-gnu #-Wno-extended-offsetof @USES_CLANG_TRUE@am__append_31 = -DMODE_DEBUG_CLANG -fsanitize=address -fsanitize=bounds @IS_LINUX_FAMILY_TRUE@@USES_CLANG_TRUE@am__append_32 = -Wl,-z,stack-size=8388608 # Note: add a _d suffix for debug builds ? # # Gnu C # ############################################################################### #GCC @HAS_CPU_NIAGARA_TRUE@@USES_GCC_TRUE@am__append_33 = -mcpu=niagara @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_34 = -DLTO -flto -fwhole-program -fno-fat-lto-objects -fuse-linker-plugin @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_35 = -flto \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fwhole-program \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fno-fat-lto-objects \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fuse-linker-plugin \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -Wl,-Map=module.map \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -Wl,--cref @USES_GCC_TRUE@am__append_36 = -DUSES_GCC @USES_GCC_TRUE@am__append_37 = -DMODE_DEBUG_GCC -fstack-check -fstack-protector-strong @HAS_BFD_DEBUG_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_38 = -rdynamic @IS_LINUX_FAMILY_TRUE@@USES_GCC_TRUE@am__append_39 = -Wl,-z,stack-size=8388608 @USES_SUNC_TRUE@am__append_40 = -DUSES_SUNC @USES_SUNC_TRUE@am__append_41 = -DMODE_DEBUG_SUNC # Note: add a _d suffix for debug builds ? # # Unknown compiler # ############################################################################### # if an unknown compiler is used, it should have its own section @USES_UNKNOWN_TRUE@am__append_42 = -DUSES_UNKNOWN_COMPILER @USES_UNKNOWN_TRUE@am__append_43 = -DMODE_DEBUG_UNKNOWN # # Some BSD-based OSes need this # @IS_BSD_FAMILY_TRUE@am__append_44 = -I./include @IS_SOLARIS_FAMILY_TRUE@am__append_45 = -D_POSIX_PTHREAD_SEMANTICS # DNSSEC is defined if either NSEC3 or NSEC are defined @HAS_MASTER_SUPPORT_TRUE@am__append_46 = \ @HAS_MASTER_SUPPORT_TRUE@ $(I)/dynupdate.h \ @HAS_MASTER_SUPPORT_TRUE@ $(I)/dynupdate-diff.h \ @HAS_MASTER_SUPPORT_TRUE@ $(I)/dynupdate-message.h @HAS_MASTER_SUPPORT_TRUE@am__append_47 = \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate_check_prerequisites.c \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate-diff.c \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate-message.c \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate-diff-nochain.c \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate-diff-nsec.c \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate-diff-nsec3.c \ @HAS_MASTER_SUPPORT_TRUE@ src/zdb-zone-maintenance.c \ @HAS_MASTER_SUPPORT_TRUE@ src/zdb-zone-maintenance-rrsig.c \ @HAS_MASTER_SUPPORT_TRUE@ src/zdb-zone-maintenance-nsec.c \ @HAS_MASTER_SUPPORT_TRUE@ src/zdb-zone-maintenance-nsec3.c subdir = lib/dnsdb ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/eurid.m4 $(top_srcdir)/m4/yadifa.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = 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__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libdnsdb_la_DEPENDENCIES = $(top_builddir)/lib/dnscore/libdnscore.la am__libdnsdb_la_SOURCES_DIST = src/avl.c src/dictionary.c \ src/dictionary_btree.c src/dictionary_htbt.c src/htable.c \ src/htbt.c src/journal.c src/journal_ix.c src/journal-cjf.c \ src/journal-cjf-idxt.c src/journal-cjf-page.c \ src/journal-cjf-page-cache.c \ src/journal-cjf-page-output-stream.c src/journal-cjf-ro.c \ src/journal-jnl.c src/xfr_copy.c src/zdb-zone-answer-axfr.c \ src/zdb-zone-answer-ixfr.c src/zdb-zone-arc.c \ src/zdb-zone-dnssec.c src/zdb-zone-find.c \ src/zdb-zone-garbage.c src/zdb-zone-journal.c \ src/zdb-zone-lock.c src/zdb-zone-lock-monitor.c \ src/zdb-zone-path-provider.c src/zdb-zone-reader-filter.c \ src/zdb.c src/zdb_cache.c src/zdb_error.c src/zdb_icmtl.c \ src/zdb_query_ex.c src/zdb_query_ex_wire.c src/zdb_record.c \ src/zdb_rr_label.c src/zdb_sanitize.c src/zdb_utils.c \ src/zdb_zone.c src/zdb_zone_axfr_input_stream.c \ src/zdb_zone_label.c src/zdb_zone_label_iterator.c \ src/zdb_zone_label_iterator_ex.c src/zdb_zone_load.c \ src/zdb_zone_process.c src/zdb_zone_store_axfr.c \ src/zdb-zone-image.c src/zdb_zone_write_text.c \ src/zdb_zone_write_unbound.c \ src/dynupdate_check_prerequisites.c src/dynupdate-diff.c \ src/dynupdate-message.c src/dynupdate-diff-nochain.c \ src/dynupdate-diff-nsec.c src/dynupdate-diff-nsec3.c \ src/zdb-zone-maintenance.c src/zdb-zone-maintenance-rrsig.c \ src/zdb-zone-maintenance-nsec.c \ src/zdb-zone-maintenance-nsec3.c src/dnssec.c \ src/dnssec-keystore.c src/nsec_common.c src/rrsig.c \ src/zdb-packed-ttlrdata.c src/nsec3.c src/nsec3_collection.c \ src/nsec3_item.c src/nsec3-chain-replay.c src/nsec3_load.c \ src/nsec3_name_error.c src/nsec3_nodata_error.c \ src/nsec3_owner.c src/nsec3_zone.c src/nsec3-forall-label.c \ src/nsec.c src/nsec-chain-replay.c src/nsec_collection.c am__dirstamp = $(am__leading_dot)dirstamp @HAS_MASTER_SUPPORT_TRUE@am__objects_1 = \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate_check_prerequisites.lo \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate-diff.lo \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate-message.lo \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate-diff-nochain.lo \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate-diff-nsec.lo \ @HAS_MASTER_SUPPORT_TRUE@ src/dynupdate-diff-nsec3.lo \ @HAS_MASTER_SUPPORT_TRUE@ src/zdb-zone-maintenance.lo \ @HAS_MASTER_SUPPORT_TRUE@ src/zdb-zone-maintenance-rrsig.lo \ @HAS_MASTER_SUPPORT_TRUE@ src/zdb-zone-maintenance-nsec.lo \ @HAS_MASTER_SUPPORT_TRUE@ src/zdb-zone-maintenance-nsec3.lo am_libdnsdb_la_OBJECTS = src/avl.lo src/dictionary.lo \ src/dictionary_btree.lo src/dictionary_htbt.lo src/htable.lo \ src/htbt.lo src/journal.lo src/journal_ix.lo \ src/journal-cjf.lo src/journal-cjf-idxt.lo \ src/journal-cjf-page.lo src/journal-cjf-page-cache.lo \ src/journal-cjf-page-output-stream.lo src/journal-cjf-ro.lo \ src/journal-jnl.lo src/xfr_copy.lo src/zdb-zone-answer-axfr.lo \ src/zdb-zone-answer-ixfr.lo src/zdb-zone-arc.lo \ src/zdb-zone-dnssec.lo src/zdb-zone-find.lo \ src/zdb-zone-garbage.lo src/zdb-zone-journal.lo \ src/zdb-zone-lock.lo src/zdb-zone-lock-monitor.lo \ src/zdb-zone-path-provider.lo src/zdb-zone-reader-filter.lo \ src/zdb.lo src/zdb_cache.lo src/zdb_error.lo src/zdb_icmtl.lo \ src/zdb_query_ex.lo src/zdb_query_ex_wire.lo src/zdb_record.lo \ src/zdb_rr_label.lo src/zdb_sanitize.lo src/zdb_utils.lo \ src/zdb_zone.lo src/zdb_zone_axfr_input_stream.lo \ src/zdb_zone_label.lo src/zdb_zone_label_iterator.lo \ src/zdb_zone_label_iterator_ex.lo src/zdb_zone_load.lo \ src/zdb_zone_process.lo src/zdb_zone_store_axfr.lo \ src/zdb-zone-image.lo src/zdb_zone_write_text.lo \ src/zdb_zone_write_unbound.lo $(am__objects_1) src/dnssec.lo \ src/dnssec-keystore.lo src/nsec_common.lo src/rrsig.lo \ src/zdb-packed-ttlrdata.lo src/nsec3.lo \ src/nsec3_collection.lo src/nsec3_item.lo \ src/nsec3-chain-replay.lo src/nsec3_load.lo \ src/nsec3_name_error.lo src/nsec3_nodata_error.lo \ src/nsec3_owner.lo src/nsec3_zone.lo src/nsec3-forall-label.lo \ src/nsec.lo src/nsec-chain-replay.lo src/nsec_collection.lo libdnsdb_la_OBJECTS = $(am_libdnsdb_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 = libdnsdb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libdnsdb_la_LDFLAGS) $(LDFLAGS) -o $@ 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__depfiles_maybe = depfiles 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 = $(libdnsdb_la_SOURCES) DIST_SOURCES = $(am__libdnsdb_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_noinst_DATA) am__pkginclude_HEADERS_DIST = $(I)/avl.h $(I)/btree.h \ $(I)/dictionary.h $(I)/dictionary-node.h $(I)/dnsrdata.h \ $(I)/dnssec.h $(I)/dnssec_config.h $(I)/dnssec-keystore.h \ $(I)/htable.h $(I)/htbt.h $(I)/journal.h $(I)/journal_ix.h \ $(I)/journal-jnl.h $(I)/journal-cjf.h \ $(I)/journal-cjf-common.h $(I)/journal-cjf-idxt.h \ $(I)/journal-cjf-page-output-stream.h $(I)/journal-cjf-page.h \ $(I)/journal-cjf-page-cache.h $(I)/chain-replay.h $(I)/nsec.h \ $(I)/nsec-chain-replay.h $(I)/nsec3.h $(I)/nsec3_collection.h \ $(I)/nsec3-chain-replay.h $(I)/nsec3_item.h $(I)/nsec3_load.h \ $(I)/nsec3_name_error.h $(I)/nsec3_nodata_error.h \ $(I)/nsec3_owner.h $(I)/nsec3_types.h $(I)/nsec3_zone.h \ $(I)/nsec_collection.h $(I)/nsec_common.h $(I)/rrsig.h \ $(I)/xfr_copy.h $(I)/zdb.h $(I)/zdb_config.h $(I)/zdb_error.h \ $(I)/zdb_icmtl.h $(I)/zdb_record.h $(I)/zdb_rr_label.h \ $(I)/zdb_sanitize.h $(I)/zdb_types.h $(I)/zdb_utils.h \ $(I)/zdb_cache.h $(I)/zdb_zone.h $(I)/zdb-lock.h \ $(I)/zdb-zone-arc.h $(I)/zdb-zone-dnssec.h \ $(I)/zdb-zone-find.h $(I)/zdb-zone-garbage.h \ $(I)/zdb-zone-journal.h $(I)/zdb-zone-lock.h \ $(I)/zdb-zone-lock-monitor.h $(I)/zdb-zone-answer-axfr.h \ $(I)/zdb-zone-answer-ixfr.h $(I)/zdb-zone-maintenance.h \ $(I)/zdb-packed-ttlrdata.h $(I)/zdb_zone_axfr_input_stream.h \ $(I)/zdb_zone_label.h $(I)/zdb_zone_label_iterator.h \ $(I)/zdb_zone_label_iterator_ex.h $(I)/zdb_zone_load.h \ $(I)/zdb-zone-path-provider.h $(I)/zdb_zone_process.h \ $(I)/zdb-zone-reader-filter.h $(I)/zdb_zone_write.h \ $(I)/nsec3-forall-label.h $(I)/dynupdate.h \ $(I)/dynupdate-diff.h $(I)/dynupdate-message.h HEADERS = $(pkginclude_HEADERS) 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)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) # libdnsdb_ladir=. # alphabetically please pkgincludedir = $(includedir)/dnsdb ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCOPTIMISATIONFLAGS = @CCOPTIMISATIONFLAGS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DNSCORE = @DNSCORE@ DNSDB = @DNSDB@ DNSLG = @DNSLG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAS_ACL_SUPPORT = @HAS_ACL_SUPPORT@ HAS_BFD_DEBUG_SUPPORT = @HAS_BFD_DEBUG_SUPPORT@ HAS_BIG_ENDIAN = @HAS_BIG_ENDIAN@ HAS_BUILD_TIMESTAMP = @HAS_BUILD_TIMESTAMP@ HAS_CC_ADDRESS_SANITIZER_CHECK = @HAS_CC_ADDRESS_SANITIZER_CHECK@ HAS_CC_ANSI = @HAS_CC_ANSI@ HAS_CC_ANSI_ALIAS = @HAS_CC_ANSI_ALIAS@ HAS_CC_CATCH_UNDEFINED_BEHAVIOR = @HAS_CC_CATCH_UNDEFINED_BEHAVIOR@ HAS_CC_DWARF2 = @HAS_CC_DWARF2@ HAS_CC_DWARF3 = @HAS_CC_DWARF3@ HAS_CC_DWARF4 = @HAS_CC_DWARF4@ HAS_CC_EXCEPTIONS = @HAS_CC_EXCEPTIONS@ HAS_CC_G = @HAS_CC_G@ HAS_CC_G3 = @HAS_CC_G3@ HAS_CC_M32 = @HAS_CC_M32@ HAS_CC_M64 = @HAS_CC_M64@ HAS_CC_MISSING_FIELD_INITIALIZERS = @HAS_CC_MISSING_FIELD_INITIALIZERS@ HAS_CC_NO_IDENT = @HAS_CC_NO_IDENT@ HAS_CC_NO_OMIT_FRAME_POINTER = @HAS_CC_NO_OMIT_FRAME_POINTER@ HAS_CC_PEDANTIC = @HAS_CC_PEDANTIC@ HAS_CC_RDYNAMIC = @HAS_CC_RDYNAMIC@ HAS_CC_SANITIZE_ADDRESS = @HAS_CC_SANITIZE_ADDRESS@ HAS_CC_STACK_PROTECTOR = @HAS_CC_STACK_PROTECTOR@ HAS_CC_STD_C11 = @HAS_CC_STD_C11@ HAS_CC_STD_C99 = @HAS_CC_STD_C99@ HAS_CC_STD_GNU11 = @HAS_CC_STD_GNU11@ HAS_CC_STD_GNU99 = @HAS_CC_STD_GNU99@ HAS_CC_TUNE_NATIVE = @HAS_CC_TUNE_NATIVE@ HAS_CC_WALL = @HAS_CC_WALL@ HAS_CC_XC99 = @HAS_CC_XC99@ HAS_CLOSE_EX_REF = @HAS_CLOSE_EX_REF@ HAS_CTRL = @HAS_CTRL@ HAS_DNSSEC_TOOLS = @HAS_DNSSEC_TOOLS@ HAS_DYNUPDATE_SUPPORT = @HAS_DYNUPDATE_SUPPORT@ HAS_ECDSA_SUPPORT = @HAS_ECDSA_SUPPORT@ HAS_EDDSA = @HAS_EDDSA@ HAS_EVENT_DYNAMIC_MODULE = @HAS_EVENT_DYNAMIC_MODULE@ HAS_FULL_ASCII7 = @HAS_FULL_ASCII7@ HAS_KEYGEN = @HAS_KEYGEN@ HAS_LIBC_MALLOC_DEBUG_SUPPORT = @HAS_LIBC_MALLOC_DEBUG_SUPPORT@ HAS_LITTLE_ENDIAN = @HAS_LITTLE_ENDIAN@ HAS_LOCK_DEBUG_SUPPORT = @HAS_LOCK_DEBUG_SUPPORT@ HAS_LOGDIR = @HAS_LOGDIR@ HAS_LOG_PID = @HAS_LOG_PID@ HAS_LOG_THREAD_ID = @HAS_LOG_THREAD_ID@ HAS_LOG_THREAD_TAG = @HAS_LOG_THREAD_TAG@ HAS_MALLOC_DEBUG_SUPPORT = @HAS_MALLOC_DEBUG_SUPPORT@ HAS_MASTER_SUPPORT = @HAS_MASTER_SUPPORT@ HAS_MEMALIGN_ISSUES = @HAS_MEMALIGN_ISSUES@ HAS_MUTEX_DEBUG_SUPPORT = @HAS_MUTEX_DEBUG_SUPPORT@ HAS_NON_AA_AXFR_SUPPORT = @HAS_NON_AA_AXFR_SUPPORT@ HAS_NSEC3_SUPPORT = @HAS_NSEC3_SUPPORT@ HAS_NSEC_SUPPORT = @HAS_NSEC_SUPPORT@ HAS_NSID_SUPPORT = @HAS_NSID_SUPPORT@ HAS_RRL_SUPPORT = @HAS_RRL_SUPPORT@ HAS_RRSIG_MANAGEMENT_SUPPORT = @HAS_RRSIG_MANAGEMENT_SUPPORT@ HAS_SYNC_BUILTINS = @HAS_SYNC_BUILTINS@ HAS_SYSTEMD_RESOLVED_AVOIDANCE = @HAS_SYSTEMD_RESOLVED_AVOIDANCE@ HAS_TESTS = @HAS_TESTS@ HAS_TOOLS = @HAS_TOOLS@ HAS_TRACK_ZONES_DEBUG_SUPPORT = @HAS_TRACK_ZONES_DEBUG_SUPPORT@ HAS_TSIG_SUPPORT = @HAS_TSIG_SUPPORT@ HAS_YADIFA = @HAS_YADIFA@ HAS_ZALLOC_DEBUG_SUPPORT = @HAS_ZALLOC_DEBUG_SUPPORT@ HAS_ZALLOC_STATISTICS_SUPPORT = @HAS_ZALLOC_STATISTICS_SUPPORT@ HAS_ZALLOC_SUPPORT = @HAS_ZALLOC_SUPPORT@ HAVE_RECVMMSG = @HAVE_RECVMMSG@ HAVE_SENDMMSG = @HAVE_SENDMMSG@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IS_BSD_FAMILY = @IS_BSD_FAMILY@ IS_DARWIN_GE14 = @IS_DARWIN_GE14@ IS_DARWIN_OS = @IS_DARWIN_OS@ IS_LINUX_FAMILY = @IS_LINUX_FAMILY@ IS_SOLARIS_FAMILY = @IS_SOLARIS_FAMILY@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL = @OPENSSL@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZDB_HAS_DNSSEC_SUPPORT = @ZDB_HAS_DNSSEC_SUPPORT@ 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_CXX = @ac_ct_CXX@ 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@ 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@ logdir = @logdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 # # # AM_CFLAGS = -D_THREAD_SAFE -D_REENTRANT -D_FILE_OFFSET_BITS=64 \ -I$(abs_builddir) -I$(abs_builddir)/include \ -I$(abs_srcdir)/include $(am__append_3) $(am__append_4) \ $(am__append_5) $(am__append_6) $(am__append_7) \ $(am__append_8) $(am__append_9) $(am__append_10) \ $(am__append_11) $(am__append_12) $(am__append_13) \ $(am__append_14) $(am__append_15) $(am__append_17) \ $(am__append_23) $(am__append_25) $(am__append_26) \ $(am__append_28) $(am__append_30) $(am__append_33) \ $(am__append_34) $(am__append_36) $(am__append_38) \ $(am__append_40) $(am__append_42) $(am__append_44) \ $(am__append_45) $(LOCALFLAGS) -DDNSDB_BUILD=1 \ -I$(top_srcdir)/lib/dnscore/include \ -I$(top_builddir)/lib/dnscore/include AM_LDFLAGS = $(am__append_16) $(am__append_18) $(am__append_24) \ $(am__append_29) $(am__append_32) $(am__append_35) \ $(am__append_39) DEBUGFLAGS = $(am__append_1) $(am__append_2) $(am__append_19) \ $(am__append_20) $(am__append_21) $(am__append_22) \ $(am__append_27) $(am__append_31) $(am__append_37) \ $(am__append_41) $(am__append_43) LOCALFLAGS = -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)"' -DLOCALSTATEDIR='"$(localstatedir)"' -DDATAROOTDIR='"$(datarootdir)"' -DDATADIR='"$(datadir)"' -DLOCALEDIR='"$(localedir)"' -DLOGDIR='"$(logdir)"' -DTCLDIR='"$(tcldir)"' @HAS_LTO_SUPPORT_FALSE@@USES_CLANG_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_FALSE@@USES_GCC_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@AM_AR = llvm-ar @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@AM_AR = gcc-ar @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@AM_AR = xiar # # Sun C # ############################################################################### # SUNC @USES_SUNC_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_FALSE@@USES_CLANG_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_FALSE@@USES_GCC_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@AM_LD = ld.gold @USES_ICC_TRUE@AM_LD = ld @USES_SUNC_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@AM_RANLIB = gcc-ranlib dist_noinst_DATA = VERSION lib_LTLIBRARIES = libdnsdb.la libdnsdb_la_LDFLAGS = -version-info 7:5:0 libdnsdb_la_LIBADD = $(top_builddir)/lib/dnscore/libdnscore.la I = include/dnsdb FEATURESFILE = zdb-config-features.h FEATURES = $(I)/$(FEATURESFILE) FEATURESDIR = lib/dnsdb/include/dnsdb FEATURESSRC = $(top_builddir)/$(FEATURESDIR)/dnsdb-config.h pkginclude_HEADERS = $(I)/avl.h $(I)/btree.h $(I)/dictionary.h \ $(I)/dictionary-node.h $(I)/dnsrdata.h $(I)/dnssec.h \ $(I)/dnssec_config.h $(I)/dnssec-keystore.h $(I)/htable.h \ $(I)/htbt.h $(I)/journal.h $(I)/journal_ix.h \ $(I)/journal-jnl.h $(I)/journal-cjf.h \ $(I)/journal-cjf-common.h $(I)/journal-cjf-idxt.h \ $(I)/journal-cjf-page-output-stream.h $(I)/journal-cjf-page.h \ $(I)/journal-cjf-page-cache.h $(I)/chain-replay.h $(I)/nsec.h \ $(I)/nsec-chain-replay.h $(I)/nsec3.h $(I)/nsec3_collection.h \ $(I)/nsec3-chain-replay.h $(I)/nsec3_item.h $(I)/nsec3_load.h \ $(I)/nsec3_name_error.h $(I)/nsec3_nodata_error.h \ $(I)/nsec3_owner.h $(I)/nsec3_types.h $(I)/nsec3_zone.h \ $(I)/nsec_collection.h $(I)/nsec_common.h $(I)/rrsig.h \ $(I)/xfr_copy.h $(I)/zdb.h $(I)/zdb_config.h $(I)/zdb_error.h \ $(I)/zdb_icmtl.h $(I)/zdb_record.h $(I)/zdb_rr_label.h \ $(I)/zdb_sanitize.h $(I)/zdb_types.h $(I)/zdb_utils.h \ $(I)/zdb_cache.h $(I)/zdb_zone.h $(I)/zdb-lock.h \ $(I)/zdb-zone-arc.h $(I)/zdb-zone-dnssec.h \ $(I)/zdb-zone-find.h $(I)/zdb-zone-garbage.h \ $(I)/zdb-zone-journal.h $(I)/zdb-zone-lock.h \ $(I)/zdb-zone-lock-monitor.h $(I)/zdb-zone-answer-axfr.h \ $(I)/zdb-zone-answer-ixfr.h $(I)/zdb-zone-maintenance.h \ $(I)/zdb-packed-ttlrdata.h $(I)/zdb_zone_axfr_input_stream.h \ $(I)/zdb_zone_label.h $(I)/zdb_zone_label_iterator.h \ $(I)/zdb_zone_label_iterator_ex.h $(I)/zdb_zone_load.h \ $(I)/zdb-zone-path-provider.h $(I)/zdb_zone_process.h \ $(I)/zdb-zone-reader-filter.h $(I)/zdb_zone_write.h \ $(I)/nsec3-forall-label.h $(am__append_46) libdnsdb_la_SOURCES = src/avl.c src/dictionary.c \ src/dictionary_btree.c src/dictionary_htbt.c src/htable.c \ src/htbt.c src/journal.c src/journal_ix.c src/journal-cjf.c \ src/journal-cjf-idxt.c src/journal-cjf-page.c \ src/journal-cjf-page-cache.c \ src/journal-cjf-page-output-stream.c src/journal-cjf-ro.c \ src/journal-jnl.c src/xfr_copy.c src/zdb-zone-answer-axfr.c \ src/zdb-zone-answer-ixfr.c src/zdb-zone-arc.c \ src/zdb-zone-dnssec.c src/zdb-zone-find.c \ src/zdb-zone-garbage.c src/zdb-zone-journal.c \ src/zdb-zone-lock.c src/zdb-zone-lock-monitor.c \ src/zdb-zone-path-provider.c src/zdb-zone-reader-filter.c \ src/zdb.c src/zdb_cache.c src/zdb_error.c src/zdb_icmtl.c \ src/zdb_query_ex.c src/zdb_query_ex_wire.c src/zdb_record.c \ src/zdb_rr_label.c src/zdb_sanitize.c src/zdb_utils.c \ src/zdb_zone.c src/zdb_zone_axfr_input_stream.c \ src/zdb_zone_label.c src/zdb_zone_label_iterator.c \ src/zdb_zone_label_iterator_ex.c src/zdb_zone_load.c \ src/zdb_zone_process.c src/zdb_zone_store_axfr.c \ src/zdb-zone-image.c src/zdb_zone_write_text.c \ src/zdb_zone_write_unbound.c $(am__append_47) src/dnssec.c \ src/dnssec-keystore.c src/nsec_common.c src/rrsig.c \ src/zdb-packed-ttlrdata.c src/nsec3.c src/nsec3_collection.c \ src/nsec3_item.c src/nsec3-chain-replay.c src/nsec3_load.c \ src/nsec3_name_error.c src/nsec3_nodata_error.c \ src/nsec3_owner.c src/nsec3_zone.c src/nsec3-forall-label.c \ src/nsec.c src/nsec-chain-replay.c src/nsec_collection.c # src/journal-cjf-idxt.c \ # src/journal-cjf-page-cache.c \ # src/journal-cjf-page-output-stream.c \ # src/journal-cjf-page.c \ # src/journal-cjf.c \ # BUILT_SOURCES = $(FEATURES) CLEANFILES = buildinfo.h $(FEATURESSRC) VP = ZDB all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../mk/common-settings.mk $(srcdir)/../../mk/common-labels.mk $(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) --gnu lib/dnsdb/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/dnsdb/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(srcdir)/../../mk/common-settings.mk $(srcdir)/../../mk/common-labels.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_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}; \ } src/$(am__dirstamp): @$(MKDIR_P) src @: > src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/$(DEPDIR) @: > src/$(DEPDIR)/$(am__dirstamp) src/avl.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dictionary.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dictionary_btree.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dictionary_htbt.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/htable.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/htbt.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/journal.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/journal_ix.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/journal-cjf.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/journal-cjf-idxt.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/journal-cjf-page.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/journal-cjf-page-cache.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/journal-cjf-page-output-stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/journal-cjf-ro.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/journal-jnl.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/xfr_copy.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-answer-axfr.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-answer-ixfr.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-arc.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-dnssec.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-find.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-garbage.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-journal.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-lock.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-lock-monitor.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-path-provider.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-reader-filter.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb_cache.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb_error.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb_icmtl.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb_query_ex.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb_query_ex_wire.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb_record.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb_rr_label.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb_sanitize.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb_utils.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb_zone.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb_zone_axfr_input_stream.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb_zone_label.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb_zone_label_iterator.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb_zone_label_iterator_ex.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb_zone_load.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb_zone_process.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb_zone_store_axfr.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-image.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb_zone_write_text.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb_zone_write_unbound.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dynupdate_check_prerequisites.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dynupdate-diff.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dynupdate-message.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dynupdate-diff-nochain.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dynupdate-diff-nsec.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dynupdate-diff-nsec3.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-maintenance.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-maintenance-rrsig.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-maintenance-nsec.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/zdb-zone-maintenance-nsec3.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dnssec.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/dnssec-keystore.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/nsec_common.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/rrsig.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/zdb-packed-ttlrdata.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/nsec3.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/nsec3_collection.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/nsec3_item.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/nsec3-chain-replay.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/nsec3_load.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/nsec3_name_error.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/nsec3_nodata_error.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/nsec3_owner.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/nsec3_zone.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/nsec3-forall-label.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/nsec.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/nsec-chain-replay.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/nsec_collection.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) libdnsdb.la: $(libdnsdb_la_OBJECTS) $(libdnsdb_la_DEPENDENCIES) $(EXTRA_libdnsdb_la_DEPENDENCIES) $(AM_V_CCLD)$(libdnsdb_la_LINK) -rpath $(libdir) $(libdnsdb_la_OBJECTS) $(libdnsdb_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f src/*.$(OBJEXT) -rm -f src/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/avl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dictionary.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dictionary_btree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dictionary_htbt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnssec-keystore.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dnssec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dynupdate-diff-nochain.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dynupdate-diff-nsec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dynupdate-diff-nsec3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dynupdate-diff.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dynupdate-message.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dynupdate_check_prerequisites.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/htable.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/htbt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/journal-cjf-idxt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/journal-cjf-page-cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/journal-cjf-page-output-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/journal-cjf-page.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/journal-cjf-ro.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/journal-cjf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/journal-jnl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/journal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/journal_ix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec-chain-replay.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3-chain-replay.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3-forall-label.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3_collection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3_item.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3_load.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3_name_error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3_nodata_error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3_owner.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec3_zone.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec_collection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/nsec_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/rrsig.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/xfr_copy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-packed-ttlrdata.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-answer-axfr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-answer-ixfr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-arc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-dnssec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-find.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-garbage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-image.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-journal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-lock-monitor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-lock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-maintenance-nsec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-maintenance-nsec3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-maintenance-rrsig.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-maintenance.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-path-provider.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb-zone-reader-filter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_icmtl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_query_ex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_query_ex_wire.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_record.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_rr_label.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_sanitize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_utils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_zone.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_zone_axfr_input_stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_zone_label.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_zone_label_iterator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_zone_label_iterator_ex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_zone_load.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_zone_process.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_zone_store_axfr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_zone_write_text.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zdb_zone_write_unbound.Plo@am__quote@ .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 -rm -rf src/.libs src/_libs install-pkgincludeHEADERS: $(pkginclude_HEADERS) @$(NORMAL_INSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ done uninstall-pkgincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) 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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) 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: -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) -rm -f src/$(DEPDIR)/$(am__dirstamp) -rm -f src/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf src/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-pkgincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES 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 -rf src/$(DEPDIR) -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: uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-data-local install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am \ install-pkgincludeHEADERS 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 uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS ### YRCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -g -DCMR ### YPCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -pg -DCMP ### YDCFLAGS = -DDEBUG $(DEBUGFLAGS) -DCMD ### YSCFLAGS = $(YRCFLAGS) ### ### YRLDFLAGS = -g ### YPLDFLAGS = -pg ### YDLDFLAGS = -g ### ### if HAS_CC_RDYNAMIC ### YPLDFLAGS += -rdynamic ### YDLDFLAGS += -rdynamic ### endif ### ### if USES_CLANG ### # workaround a bug where clang does not handle properly profiling and optimizations ### YPCFLAGS += -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer ### endif ### ### YSLDFLAGS = $(YRLDFLAGS) ### ### AM_CFLAGS += $(YCFLAGS) ### AM_LDFLAGS += $(YLDFLAGS) ### ### AM_MAKEFLAGS=MODE_CFLAGS="$(AM_CFLAGS)" CC=$(CC) AR=$(AM_AR) LD=$(AM_LD) buildinfo.h: $(abs_top_builddir)/config.log echo \#pragma once > buildinfo.h 2> /dev/null echo // generated file, do not modify >> buildinfo.h 2> /dev/null echo \#define BUILD_OPTIONS \"$$(grep "/configure" $(abs_top_builddir)/config.log | head -1 | sed 's/.*\.\/configure *//')\" >> buildinfo.h 2> /dev/null all: REVISION $(FEATURESSRC) REVISION: (svn info 2>/dev/null;if [ $$? -ne 0 ];then echo "Revision: 0";fi)|grep Revision:|sed 's/^Revision: *//' > REVISION $(srcdir)/src/avl.c: $(FEATURES) $(FEATURESSRC) $(FEATURESSRC): ../../config.h mkdir -p $(top_builddir)/$(FEATURESDIR) cp ../../config.h $(FEATURESSRC) features: $(FEATURES) $(FEATURES): ../../config.log REVISION VERSION $(FEATURESSRC) mkdir -p $(I) echo "#pragma once" > $(FEATURES) grep "^#define" $(FEATURESSRC) | sed -e 's/^#define /#define $(VP)_/' >> $(FEATURES) echo '#undef $(VP)_VERSION' >> $(FEATURES) which printf > /dev/null 2>&1 if [ $$? -eq 0 ];then \ printf '// version %i.%i.%i.%i-%i\n' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ printf '#define $(VP)_VERSION 0x%02x%02x%02x%02x%04xLL' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ else \ echo "#define $(VP)_VERSION_(vmain_,vsub_,vminor_,vpatch_,vrevision_) ((vmain_)<<40)|((vsub_)<<32)|((vminor_)<<24)|((vpatch_)<<16)|(vrevision_)" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMAIN_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VSUB_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\2')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMINOR_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\3')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VPATCH_ 0 >> $(FEATURES)" ; \ echo "#define $(VP)_VERSION_VREVISION_ $$(cat REVISION)" >> $(FEATURES) ; \ echo '#define $(VP)_VERSION $(VP)_VERSION_($(VP)_VERSION_VMAIN_,$(VP)_VERSION_VSUB_,$(VP)_VERSION_VMINOR_,$(VP)_VERSION_VPATCH_,$(VP)_VERSION_VREVISION_)' >> $(FEATURES) ; \ fi echo "// $(FEATURES)" >> $(FEATURES) echo >> $(FEATURES) install-data-local: $(FEATURES) mkdir -p $(DESTDIR)$(prefix)/include/dnsdb /usr/bin/install -c -m 644 $(FEATURES) $(DESTDIR)$(prefix)/$(FEATURES) # 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: yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/Makefile.am0000644000000000000000000000013214505005531020231 xustar000000000000000030 mtime=1695812441.769972549 30 atime=1695812445.799030253 30 ctime=1695812494.884733259 yadifa-2.6.5-11201/lib/dnsdb/Makefile.am0000664000374500037450000002077514505005531020206 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ACLOCAL_AMFLAGS = -I m4 include ../../mk/common-settings.mk AM_CFLAGS += -DDNSDB_BUILD=1 AM_CFLAGS += -I$(top_srcdir)/lib/dnscore/include -I$(top_builddir)/lib/dnscore/include dist_noinst_DATA = VERSION lib_LTLIBRARIES = libdnsdb.la libdnsdb_la_LDFLAGS = -version-info 7:5:0 libdnsdb_la_LIBADD=$(top_builddir)/lib/dnscore/libdnscore.la I = include/dnsdb FEATURESFILE=zdb-config-features.h FEATURES=$(I)/$(FEATURESFILE) FEATURESDIR=lib/dnsdb/include/dnsdb FEATURESSRC=$(top_builddir)/$(FEATURESDIR)/dnsdb-config.h # libdnsdb_ladir=. # alphabetically please pkgincludedir = $(includedir)/dnsdb pkginclude_HEADERS = \ $(I)/avl.h \ $(I)/btree.h \ $(I)/dictionary.h \ $(I)/dictionary-node.h \ $(I)/dnsrdata.h \ $(I)/dnssec.h \ $(I)/dnssec_config.h \ $(I)/dnssec-keystore.h \ $(I)/htable.h \ $(I)/htbt.h \ $(I)/journal.h \ $(I)/journal_ix.h \ $(I)/journal-jnl.h \ $(I)/journal-cjf.h \ $(I)/journal-cjf-common.h \ $(I)/journal-cjf-idxt.h \ $(I)/journal-cjf-page-output-stream.h \ $(I)/journal-cjf-page.h \ $(I)/journal-cjf-page-cache.h \ $(I)/chain-replay.h \ $(I)/nsec.h \ $(I)/nsec-chain-replay.h \ $(I)/nsec3.h \ $(I)/nsec3_collection.h \ $(I)/nsec3-chain-replay.h \ $(I)/nsec3_item.h \ $(I)/nsec3_load.h \ $(I)/nsec3_name_error.h \ $(I)/nsec3_nodata_error.h \ $(I)/nsec3_owner.h \ $(I)/nsec3_types.h \ $(I)/nsec3_zone.h \ $(I)/nsec_collection.h \ $(I)/nsec_common.h \ $(I)/rrsig.h \ $(I)/xfr_copy.h \ $(I)/zdb.h \ $(I)/zdb_config.h \ $(I)/zdb_error.h \ $(I)/zdb_icmtl.h \ $(I)/zdb_record.h \ $(I)/zdb_rr_label.h \ $(I)/zdb_sanitize.h \ $(I)/zdb_types.h \ $(I)/zdb_utils.h \ $(I)/zdb_cache.h \ $(I)/zdb_zone.h \ $(I)/zdb-lock.h \ $(I)/zdb-zone-arc.h \ $(I)/zdb-zone-dnssec.h \ $(I)/zdb-zone-find.h \ $(I)/zdb-zone-garbage.h \ $(I)/zdb-zone-journal.h \ $(I)/zdb-zone-lock.h \ $(I)/zdb-zone-lock-monitor.h \ $(I)/zdb-zone-answer-axfr.h \ $(I)/zdb-zone-answer-ixfr.h \ $(I)/zdb-zone-maintenance.h \ $(I)/zdb-packed-ttlrdata.h \ $(I)/zdb_zone_axfr_input_stream.h \ $(I)/zdb_zone_label.h \ $(I)/zdb_zone_label_iterator.h \ $(I)/zdb_zone_label_iterator_ex.h \ $(I)/zdb_zone_load.h \ $(I)/zdb-zone-path-provider.h \ $(I)/zdb_zone_process.h \ $(I)/zdb-zone-reader-filter.h \ $(I)/zdb_zone_write.h \ $(I)/nsec3-forall-label.h libdnsdb_la_SOURCES = \ src/avl.c \ src/dictionary.c \ src/dictionary_btree.c \ src/dictionary_htbt.c \ src/htable.c \ src/htbt.c \ src/journal.c \ src/journal_ix.c \ src/journal-cjf.c \ src/journal-cjf-idxt.c \ src/journal-cjf-page.c \ src/journal-cjf-page-cache.c \ src/journal-cjf-page-output-stream.c \ src/journal-cjf-ro.c \ src/journal-jnl.c \ src/xfr_copy.c \ src/zdb-zone-answer-axfr.c \ src/zdb-zone-answer-ixfr.c \ src/zdb-zone-arc.c \ src/zdb-zone-dnssec.c \ src/zdb-zone-find.c \ src/zdb-zone-garbage.c \ src/zdb-zone-journal.c \ src/zdb-zone-lock.c \ src/zdb-zone-lock-monitor.c \ src/zdb-zone-path-provider.c \ src/zdb-zone-reader-filter.c \ src/zdb.c \ src/zdb_cache.c \ src/zdb_error.c \ src/zdb_icmtl.c \ src/zdb_query_ex.c \ src/zdb_query_ex_wire.c \ src/zdb_record.c \ src/zdb_rr_label.c \ src/zdb_sanitize.c \ src/zdb_utils.c \ src/zdb_zone.c \ src/zdb_zone_axfr_input_stream.c \ src/zdb_zone_label.c \ src/zdb_zone_label_iterator.c \ src/zdb_zone_label_iterator_ex.c \ src/zdb_zone_load.c \ src/zdb_zone_process.c \ src/zdb_zone_store_axfr.c \ src/zdb-zone-image.c \ src/zdb_zone_write_text.c \ src/zdb_zone_write_unbound.c # src/journal-cjf-idxt.c \ # src/journal-cjf-page-cache.c \ # src/journal-cjf-page-output-stream.c \ # src/journal-cjf-page.c \ # src/journal-cjf.c \ # BUILT_SOURCES = $(FEATURES) # DNSSEC is defined if either NSEC3 or NSEC are defined if HAS_MASTER_SUPPORT pkginclude_HEADERS += \ $(I)/dynupdate.h \ $(I)/dynupdate-diff.h \ $(I)/dynupdate-message.h libdnsdb_la_SOURCES += \ src/dynupdate_check_prerequisites.c \ src/dynupdate-diff.c \ src/dynupdate-message.c \ src/dynupdate-diff-nochain.c \ src/dynupdate-diff-nsec.c \ src/dynupdate-diff-nsec3.c \ src/zdb-zone-maintenance.c \ src/zdb-zone-maintenance-rrsig.c \ src/zdb-zone-maintenance-nsec.c \ src/zdb-zone-maintenance-nsec3.c endif libdnsdb_la_SOURCES += \ src/dnssec.c \ src/dnssec-keystore.c \ src/nsec_common.c \ src/rrsig.c \ src/zdb-packed-ttlrdata.c libdnsdb_la_SOURCES += \ src/nsec3.c \ src/nsec3_collection.c \ src/nsec3_item.c \ src/nsec3-chain-replay.c \ src/nsec3_load.c \ src/nsec3_name_error.c \ src/nsec3_nodata_error.c \ src/nsec3_owner.c \ src/nsec3_zone.c \ src/nsec3-forall-label.c libdnsdb_la_SOURCES += \ src/nsec.c \ src/nsec-chain-replay.c \ src/nsec_collection.c include ../../mk/common-labels.mk all: REVISION $(FEATURESSRC) REVISION: (svn info 2>/dev/null;if [ $$? -ne 0 ];then echo "Revision: 0";fi)|grep Revision:|sed 's/^Revision: *//' > REVISION $(srcdir)/src/avl.c: $(FEATURES) $(FEATURESSRC) $(FEATURESSRC): ../../config.h mkdir -p $(top_builddir)/$(FEATURESDIR) cp ../../config.h $(FEATURESSRC) CLEANFILES += $(FEATURESSRC) features: $(FEATURES) $(FEATURES): ../../config.log REVISION VERSION $(FEATURESSRC) VP=ZDB mkdir -p $(I) echo "#pragma once" > $(FEATURES) grep "^#define" $(FEATURESSRC) | sed -e 's/^#define /#define $(VP)_/' >> $(FEATURES) echo '#undef $(VP)_VERSION' >> $(FEATURES) which printf > /dev/null 2>&1 if [ $$? -eq 0 ];then \ printf '// version %i.%i.%i.%i-%i\n' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ printf '#define $(VP)_VERSION 0x%02x%02x%02x%02x%04xLL' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ else \ echo "#define $(VP)_VERSION_(vmain_,vsub_,vminor_,vpatch_,vrevision_) ((vmain_)<<40)|((vsub_)<<32)|((vminor_)<<24)|((vpatch_)<<16)|(vrevision_)" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMAIN_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VSUB_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\2')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMINOR_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\3')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VPATCH_ 0 >> $(FEATURES)" ; \ echo "#define $(VP)_VERSION_VREVISION_ $$(cat REVISION)" >> $(FEATURES) ; \ echo '#define $(VP)_VERSION $(VP)_VERSION_($(VP)_VERSION_VMAIN_,$(VP)_VERSION_VSUB_,$(VP)_VERSION_VMINOR_,$(VP)_VERSION_VPATCH_,$(VP)_VERSION_VREVISION_)' >> $(FEATURES) ; \ fi echo "// $(FEATURES)" >> $(FEATURES) echo >> $(FEATURES) install-data-local: $(FEATURES) mkdir -p $(DESTDIR)$(prefix)/include/dnsdb /usr/bin/install -c -m 644 $(FEATURES) $(DESTDIR)$(prefix)/$(FEATURES) yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/VERSION0000644000000000000000000000013114505005531017244 xustar000000000000000029 mtime=1695812441.68697136 30 atime=1695812445.803030311 30 ctime=1695812494.887733303 yadifa-2.6.5-11201/lib/dnsdb/VERSION0000664000374500037450000000000614505005531017203 0ustar00signersigner000000000000002.6.5 yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/AUTHORS0000644000000000000000000000013214505005531017245 xustar000000000000000030 mtime=1695812441.685971346 30 atime=1695812445.797030225 30 ctime=1695812495.036735437 yadifa-2.6.5-11201/lib/dnsdb/AUTHORS0000664000374500037450000000013514505005531017206 0ustar00signersigner00000000000000Gery Van Emelen Eric Diaz Fernandez yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/COPYING0000644000000000000000000000013214505005531017230 xustar000000000000000030 mtime=1695812441.768972535 30 atime=1695812445.797030225 30 ctime=1695812495.038735465 yadifa-2.6.5-11201/lib/dnsdb/COPYING0000664000374500037450000000312414505005531017172 0ustar00signersigner00000000000000 Copyright (c) 2011-2023, EURid vzw. All rights reserved. The YADIFA TM software product is provided under the BSD 3-clause license: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of EURid nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/ChangeLog0000644000000000000000000000013214505005531017747 xustar000000000000000030 mtime=1695812441.688971389 30 atime=1695812445.797030225 30 ctime=1695812495.040735494 yadifa-2.6.5-11201/lib/dnsdb/ChangeLog0000664000374500037450000017673414505005531017733 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ 20230906: YADIFA 2.6.5-public Secondaries will nolonger enforce the TTL value of the NSEC3PARAM record. Fixes an issue caused by a limitation of the select system call. 20230301: YADIFA 2.6.4-public Fixes an issue building for 32 bits targets. 20230213: YADIFA 2.6.3-public Fixes an issue where the answer to a DNSSEC query to a wild record right below the apex in a DNSSEC3 zone would not return all the relevant NSEC3 records Fixes an issue where the answer to a DNSSEC query to a wild record in an NSEC zone would incorrectly use the name of the query in the answer Fixes an issue where NSEC3-owning labels were not compressed Complies with Fedora https://fedoraproject.org/wiki/Changes/PortingToModernC (see m4/contributions/20230118-fedora-toolchain-porting-to-modern-c.patch) 20221209: YADIFA 2.6.2-public Fixes an issue trying to link the backtrace call while building yadifad on FreeBSD 20221130: YADIFA 2.6.1-public Fixes an issue where the answer of an TSIG-signed IXFR query over an undefined domain would not be properly signed. Fixes an issue building for big-endian architectures. 20221004: YADIFA 2.6.0-public The server can optionally load the locally stored zone before asking for the last version to its primary (load-local-first) The server now avoids storing temporary zone transfer images to disk if the zone is small enough (axfr-memory-threshold) zone transfers source address can now be specified in the configuration (transfer-source) The server now allows to sign a zone using only zone signing keys. Fixes online chain generation started from an zone that is not covered by DNSSEC. Fixes an issue where a generated DNSKEY could be missing smart fields if the storage became full right before they needed to be written. Fixes an issue that could occur using EDDSA on big-enough data sets. 20220228: YADIFA 2.5.4-public Fixes an issue handling CNAME records. 20211025: YADIFA 2.5.3-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet with privileged access. 20210929: YADIFA 2.5.2-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet with privileged access. Fixes an issue where a corrupted configuration file could lead to a crash while starting-up. 20210924: YADIFA 2.5.1-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet. Fixes an issue where yadifad would sometimes reply with an AXFR instead of an IXFR if the journal is under maintenance. Increased the pid column in the logger to 6 characters Drastically increased the limit for TCP queries. Note that using a high enough number compared to the available memory will cause yadifad to warn about limits and OOM kill risks. In practice a few hundred TCP queries should be enough. 20210602: YADIFA 2.5.0-public Adds a new, friendlier, TCP manager. When enabled, TCP connections aren't closed harshly after some time has elapased without any activity. In a nutshell: It is enabled using --enable-tcp-manager. It works using a quota of allowed parallel connections per host. There is one value for the registeres hosts and one for unknown hosts. All defined primaries are automatically added to the TCP manager as registered hosts. The server's local addresses are automatically added to the registered hosts. The default timeout is set to 3 seconds but doesn't imply a connection will be closed : only that it is a candidate for being closed. EDDSA support has been enable. Sending a TCP message now uses a single system call (message_send_tcp) Fixes an issue in some FreeBSD setups where UDP messages couldn't be sent by YADIFA. Fixes an issue in FreeBSD where TCP connections would sometimes be closed too quickly. Fixes an issue where failed dynamic updates prerequisites would return SERVFAIL instead of the more accurate error code. Fixes atomic usage for older C compilers. Fixes an issue where some RRSIG records may not be updated in time if they happened to have their update bundled with NSEC3 records updates while the incremental change could not be immediately written in the journal. Fixes the yadifa keygen module to understand "help" as a command and not as a domain. 20210223: YADIFA 2.4.2-public Fixes an issue where records below delegation are not ignored (https://github.com/yadifa/yadifa/issues/12). Fixes an issue in the _mm model where shutting down while still initializing may not stop properly. Changes default user/group to 'yadifa' user in example configuration. Fixes an issue with autoconf 2.70 obsolete functions. Fixes an issue where an unknown key configured in a zone acl may lead to a crash. Fixes an issue where an query without EDNS involving ACLs using optional keys would incorrectly be rejected. Fixes an issue where a network thread with a failed context would incorrectly have its context deleted. Adds a feature to yadifad to ensure that the dates in the key-roll section can be successfully applied for the next 10 years (--check-policies). Added support for primary and secondary variant options. Fixes builds for gcc 11. 20201209: YADIFA 2.4.1-public Fixes an issue in dnscore where a DNS TCP query would not return the real DNS error code. Fixes an issue that could happen when a network model isn't supported. Fixes the propagation of sendmmsg/recvmmsg function availability detection. Fixes an issue where yadifad would issue a warning when a key with algorithm > 7 is used with an NSEC zone. Fixes an issue that will occur on a chrooted environment where a managed-path would be used incorrectly. Fixes CNAME answers not following the aliases chain. Fixes CNAME recursion not returning the same answer as named in NXDOMAIN cases (reported by https://github.com/SivaKesava1, see https://github.com/yadifa/yadifa/issues/11) Adds patch for musl support (from https://github.com/kolbma, see https://github.com/yadifa/yadifa/issues/9#issuecomment-723047226) Adds stack size fix for musl support (the default size is way too small) Now imports a custom version of stdatomic.h for systems where it is missing, located in dnscore/thirdpary/stdatomic.h Made for CentOS 7 and any other release where that file is missing. The import is only active if strictly needed and will only be visible during the build. At the moment, it is not being installed with the other headers. The original source of the file was taken from https://gist.github.com/nhatminhle/5181506 YAKEYROLLD 2.4.1 Fixes the handling of incomplete TCP queries. Fixes a possible race-condition when initialising the keyroll context error codes. The keyroll now has another automatic recovery layer where it completely restarts the handling of a domain, generating a one-step update to put the zone in the expected state. 20201012: YADIFA 2.4.0-public Fixes an issue that could happen with multiprocess logging. Fixes an issue parsing a *. domain. Improves support for LibreSSL. Added contributions directories with community-provided patches. Readied the source for the release. Many changes have been made since version 2.3.x. Please read the manual for more information. YAKEYROLLD 2.4.0 Since version 2.4.0, yadifad optionally allows dynamic update of RRSIG records. The external key managing tool using this feature is being released along with it. Please read the manual for more information. YADIFA CTRL 2.4.0 The updated version of the command line controller has been made more user-friendly. Please read the manual for more information. 20200722: YADIFA 2.4.0-67 Default listen is now "0.0.0.0,::0" Added "do-not-listen" feature to avoid conflicts with systemd-resolved, default is empty. Added --enable-systemd-resolved-avoidance in the configure script to change the default of "do-not-listen" to "127.0.0.53 port 53" Zone file reader now decodes \ddd tokens. Text zone parsing is now more lenient in what it accepts: unescaped @ and $ in a domain will be read as '@' and '$', with a warning. Improves the configuration update by keeping a timestamp of all files involved and checking they have been modified. Logger configuration can now be reconfigured during runtime. In the event of an incorrect reconfiguration of the network, yadifad will periodically try to reconfigure itself reading the configuration files. Fixes a potential issue in NSEC3 replying. Fixes TXT parsing issues. Fixes a leak with the chroot remapping when reconfiguring. Fixes a leak processing the command line. Fixes a leak in the policies configuration. 20200630: YADIFA 2.4.0-64 Network setup errors will now stop yadifad if they occur during the first configuration. If they occur during a reconfiguration the error will be logged every minute instead of every second. Fixes DSA API usage with OpenSSL 1.1.0 Fixes an other side effect of FreeBSD's process-shared mutexes where a thread waiting on a condition wouldn't always be woken up. Fixes IPv6 handling in FreeBSD. Fixes an issue where the logging could lock when daemonizing. Fixes the build-time-configuration paths when using cmake. Fixes an issue where a sync clean command would not delete the journal if the zone wasn't dynamically updated since the start of yadifad. Fixes an issue where the size of the buffer given for a message would be slightly bigger than needed. Duplicate but identical definition of a TSIG key are nolonger considered an error. Increased the log output handling control commands (mostly error conditions) yadifa ctrl: The fqdn isn't set by default anymore (it used to be '.' by default) Adds the "freeze", "thaw", "unfreeze", "freezeall", "unfreezeall" and "thawall" friendly keywords to yadfia ctrl. Adds the "notify" command. The FQDN has no default value anymore. Fixes the friendly parsing of the command line. Fixes several minor issues with the console output of the command line. 20200608: YADIFA 2.4.0-52 This is version is going to production as primary and for public release. Fixes limit case issues giving NSEC3 answers for some zone structures (mostly *, * + CNAME) Fixes an issue where the packet reader may not allocate enough room for SOA records (found in yakeyrolld) YKEYROLL-1.0.5-4 This is version is going to production as primary and for public release. Fixes the handling of more limit cases (broken setup). 20200515: YADIFA 2.4.0-51 In an effort to find issues using different tools, the code has been partially ported to compile in Visual Studio 2019. (Doesn't run) The code analyser from Visual Studio 2019 reported 290 potential issues, 5 of which were valid (understand: errors) and not reported by other analysers. We have used a mmap.c MIT-licensed code from github to help in this task. We'll have to decide to keep it or to write ours when we will do a Windows release. Adds a DNS pcap analyser tool to measure DNS traffic from a network pcap file. Used to find why so many packets were lost in the benchmark. (resut: The benchmark tool was broken.) Adds a --disable-filepool-cache build configure option. Logs clarity has been improved. Improved usability:
network-model option can now use words instead of just numbers, respectively: single, buffered, multi for 0, 1, 2. Fixes an issue that could occur in the logger service with some settings. Fixes an issue in the new network model. Fixes a memory leak that could occur in the cirular_file layer of the journal. Fixes a memory leak that could occur in the journal depending on the reason it was closed. Fixes a memory leak that could occur at shutdown while destroying a file pool. Fixes an issue where trying to print a corrupted fqdn (e.g.: random bytes) could have an undefined behaviour. Fixes an issue using the drop-before-load feature where the memory of the previous zone would not be completely freed yet before the new version of the zone started to load. Fixes a race condition that could occur while detaching stdout/stderr from console. Fixes missing AA flag in primary notification. Fixes a rare issue where a signal could block the logger. Fixes TSIG-covered answers of an unsupported opcode. YKEYROLL-1.0.5-3 Fixes the handling of several limit cases (all coming from a broken, corrupted state). 20200320: YADIFA 2.4.0-50 Efforts have been made to reduce the memory usage in the case where a lot of specific listening addresses are defined. A new network-model taking advantage of the multiple-send/receive of some kernels has been added. (recvmmsg, sendmmsg) Back-ported gcc-10 compatibility fix from the main development branch (trunk) This issue was reported by several distributions already using the yet-to-be-released gcc-10 (We are using gcc-9) Adds the tcp_manager for experimentation (an alternative way to keep track of opened TCP connections). Fixes a potential memory leak that could sometimes happen freeing NSEC3 records without removing their attached RRSIG first. Fixes FreeBSD 12.1/libressl build issue. YKEYROLL-1.0.5-2 Now handles SIGHUP to reopen the log files. Imrpoved the command line options help. 20200212: YADIFA 2.4.0-49 This version is going for production. Fixes an issue with signature expiration value where the time was sometimes incorrectly taken from the oldest key. The RRL tables are now growing faster in order to avoid wasting resources. YKEYROLL-1.0.4-2 This version is going for production. Now keeps the expected starting point and end point for all steps. This is used to verify the state before and after each update. Now has a "print" mode that logs the "plan" out (logs all the known steps). 20200128: YADIFA 2.4.0-48 New nameserver infrastructure update. In
, adds a log_files_disabled flag to disable checking the log-path directory for existence and writing rights. Without this, yadifad would refuse to work without a proper log output directory like we have on our SELinux setup. Fixes an issue that would occur if SELinux would reject a write operation with EPERM to a socket we have succesfully opened for writing. yadifad would not complain and end-up hammering both the socket creation and the logs Fixes an issue that would occur if SELinux would reject a read operation with EPERM on a socket we have successfully opened for reading. This happens, notably, the notify service, producing a lot of log lines. Now such an issue will make yadifad pause for one second. 20200106: YADIFA 2.4.0-45 Fixes an issue where having no ZSK would trigger a useless maintenance pass. Fixes an issue where notifies could stop being sent when their queue was full. (New dynamic queue used at minimal increased CPU cost for this part) Fixes an issue where reopening or syncing would have their effect delayed. Fixes an issue that could occur for DSA T parameter deduction from a public key. Made the command line more friendly using the new features from dnscore. YKEYROLL 1.0.3-0 Now filters-out publish and unpublish meta lines. Fixes an issue where retrying to send a message to an unresponsive server could have the message content reset. 20191120: YKEYROLL-1.0.2-3 This version is going for production. Adds switching to a uid/gid set in the configuration file (must be set to the same as yadifad). Adds process mutual-exclusion for plan generation. Improves shutdown speed. Reduces logging. 20191118: YADIFA 2.4.0-43 Fixes an issue where enabling key activation leniency would incorrectly enable deactivation leniency. Fixes an issue where redundant signatures would be kept longuer than needed. The journal name for the root zone will now be root_zone.cjf (only one dot) intead of ..cjf, as that name was troublesome. YKEYROLL-1.0.1-9 This version is going for production. Can now work in a loop without detaching from console. 20191106: YADIFA 2.4.0-42 This version is going for production. Issues found by CLion's code inspector fixed or marked as invalid. Downgrades several "error" into "notice". More generally, an effort has been made to reduce the log size. Setting a policy field with an incorrect value will now log an error instead of stopping yadifad. Slave zones don't run sanitization anymore, as the primary is "right". This avoids thight rules being counter-productive in production environments. Fixes an issue that would occur if an update happens at tahe same time as the removal of a DNSKEY when a maintenance has started. Fixes an issue where the authoritative bit coudl be flipped off in some operations. Fixes an issue where removing and adding the same record in a single update would incorrectly drop its signature. Fixes an issue where a secondary receiving an inccorrect IXFR stream (specifically: finishing on an incomplete page) would not reject the broken page. Fixes an issue where a primary would cut an IXFR page in half if a shutdown was triggered while the page was being read from the journal. Fixes an issue in the policy date computation that could lead to a time period without signature coverage. 20191010: YADIFA 2.4.0-41 Fixes typos. YKEYROLL-1.0.0 Improved error codes returned by the keyroll policies. Fixes an error that could occur parsing a corrupted step file. 20190927: YADIFA 2.4.0-40 Adds a tool to append an IXFR in text form (so, from a dig command) to a journal. This is an unfriendly pure dev tool meant to create some tests scenarii. The cjf-scan tool, used to print the content of a journal, can now print its content in a way similar to the dig command. Simply use the "-clean" command line option before the journal file name. Both the above tools mean that a journal can be dumped as text, edited then re-created as binary. Although not initially created for this purpose, it can be a powerful fix tool. Fixes the "11:04" issue. It was triggered by an optimisation not being handled on all exit paths of the maintenance function, potentially leading to a buffer overflow. Fixes an issue in the journal: If the first update written into a dynamically sized journal is bigger that the default size of the journal (64KB) then yadifad incorrectly tries to shift-out content to make room, which it obviously cannot do. 20190920: YADIFA 2.4.0-39 In
, adds axfr-strict-authority option. Defaulted to enabled unless yadifad was built-configured using --enable-non-aa-axfr-support. Improves TXT parsing (github/ JZerf). Fixes an potential crash on SIGHUP if the zone loader calee gives an incorrect answer (github/kolbma). Fixes an issue where a UDP query with invalid return address (port 0) would trigger an EINVAL leading yadifa to shutdown the thread. Fixes an issue with IPv6 aliased replies. Depending on the OS/release the value could be wrong. The fix tries several options. This has been tested on several Debian and RedHat variants and seems to work properly. 20190919: YADIFA 2.4.0-38 note: Serial bump due to issues during rpm packaging. Reduces the number of warnings triggered by type bitmap fixes. Now only prints one and leaves the rest available as debug. Contains code to track the "11:04" issue and verify the hypothesis of its cause. 20190913: YADIFA 2.4.0-26 Timestamp in dns-udp are now human-readable. Writing a zone as text now computes and updates the approximate wire size for the zone (AXFR/IXFR trigger accuracy) yadifad now replies to ENDS# bad format. Fixes an issue in dns-udp where the message size would not be reset on the received side. Fixes an issue in dns-udp where the rate-limiter would fire before a message would be checked for actual IO (aggregated queries). Fixes an issue in dns-udp where a very slow call-back would slow down the processing part of the receiver enough to trigger a timeout of the query. Fixes a warning that would be shown for keys being both NSEC and NSEC3. Fixes an issue where the '#' character was incorrectly set as a zone comment. Fixes an issue where a journal with an invalid character in a name would trigger an infinite error loop (until program shutdown). Fixes an issue where a DNSKEY dynamic update coming with an RRSIG push could fail under certain conditions. Fixes some typos. YKEYROLL-beta Improves error reporting. Allows different configuration files. Fixes corrupted plan handling. Updates the configuration example. Correction updates are now merged in a single step, then played. Added error-retries-cases in daemon mode. Added a --timeus-offset parameter (not publicly documented) to lie about the current time. Added a --dryrun parameter. Fixes an issue handling key duplicates. 20190627: YADIFA 2.4.0-25 Fixes an issue where a corrupted journal would prevent a secondary from working. Fixes an issue replaying NSEC3 chain changes as a secondary that could occur when a discrepancy was found. If a corrupted journal is found, yadifad now renames it adding ".bad" to its name. 20190613: YADIFA 2.4.0-24 Adds safeguards for the logger shutdown. FreeBSD 12.0 issue diagnostic: There was an elusive issue occurring only on FreeBSD 12.0 related to shared mutexes. After posting an the issue anonymously with a proof-of-concept code, it turns out it was bug in FreeBSD: An unlocked mutex is still being accessed by the thread library right after the effective unlock has occurred. yadifad destroys a structure containing mutexes right after it is unlocked for the last time. FreeBSD has issued a fix, but at the moment the fix appeared to have side effects. This may have been us not rebuilding "world" properly (First time we do this), or it may be that the patch wasn't complete at the time. The matter is closed as far as yadifad's source code is concerned so this is something to watch after the next FreeBSD update. Added the "freebsd12-test" proof-of-concept code in the test section of the code. Adds the IP_MTU_DISCOVER IP_PMTUDISC_OMIT patch: patch received 20190323 from daisuke.higashi@gmail.com /* * Linux 3.15 has IP_PMTUDISC_OMIT which makes sockets * ignore PMTU information and send packets with DF=0. * Fragmentation is allowed if and only if the packet * size exceeds the outgoing interface MTU or the packet * encounters smaller MTU link in network. * This mitigates DNS fragmentation attacks by preventing * forged PMTU information. * FreeBSD already has same semantics without setting * the option. */ Added sereral fixes for NetBSD builds. Ultimately, NetBSD declares but does not implement PSHARED. This makes that platform unusable for the moment. Logs have been improved (level & verbosity, some have been downgraded to debug). Improves command-line help. Internally, INVALID and UNPROCESSABLE messages are now seen as the same error. In
, added log_unprocessable boolean to add a warning log for bad DNS messages. If yadifad is not started as root but requires elevated privileges in order to bind an addess, it will stop. Fixes build on older sytems (FreeBSD). Fixes an incorrect warning message related to TSIG. Fixes an issue with garbage collection at shutdown. Fixes an issue that would occur if the signature max-interval was set high enough to end up in an integer overflow. Fixes an issue where newly added keys would not always be taken into account in the computations. Fixes an issue where the nttl cache could overflow. Fixes an issue in the path provider of yadifad where an empty secondary zone file setting could lead to a NULL pointer reference. Fixes an issue where the KSK public key would not be stored, losing the flags of the key as seen by libdnscore. Fixes an issue in dns-udp that would occur when TCP fails with a DNS error. Fixes an issue in dns-udp where the thread_pool destruction order could trigger some issues. Fixes an issue where a TCP read time-out from a client (thus when the server is sending) could lead to an indefinitely held connection. Fixes an issue that could happen in the RRL, leading to the current state pool being misused. Fixes an issue where an error code sent from the socket server would nto be interpreted correctly. Fixes an issue in the text parser that was being tripped in the yakeyrolld. Fixes an issue where asking the help from the command line would return to the shell with a non-zero value. YKEYROLL-alpha Code commited in alpha state to avoid potential issues related to a certain event. The new keyroll software is being written in C. It is based on the YADIFA framework. It's main features are: _ cron-like timings, _ KSK/ZSK separation, _ RRSIG push usage, _ one event per file and one file per event, _ integrity milestones, _ extension of the time-line on demand. 20190326: YADIFA 2.4.0-23 Added autogen.sh in the make dist. Improved yadifad startup so that simply asking for its version would not go through service start. Improved AXFR log messages: now showing the peer's IP address. 20190322: YADIFA 2.4.0-22 EDDSA is known but not handled. (EDDSA handling code is in the 2.5.x branch) Sanitization now checks for DNSKEY matching RRSIG records. Fixes an issue where yadifad would abort in a specific condition: A zone that allows RRSIG pushed by dynamic updates with a bunch of inactive ZSK keys available, one of them still in the zone with said inactive ZSK key in the zone having signature expiring after its deactivation date AND in the future with an active key in the zone that does not expire and is fully usable (key pair available) with a single KSK key in the zone that has no private part available ... ... was considered fubar and triggering an emergency stop (ending up in an abort()) Fixes an issue handling BigNum from OpenSSL being sometimes smaller than expected. Fixes a double-free issue (crashed yadifad the 20190311). Fixes an issue that would occur on a secondary when the journal is too small to work optimally. Added a "dsfromkey" in the test section, to be added in the command line later 20190218: YADIFA 2.4.0-21 Fixes an issue where killing yadifad while thread creation is in limbo would not work. yadifad will now ignore all signals until notify service thread is up and running (thus outside of limbo) Fixes an issue where policies would be tried on non-policed zones. 20190213: YADIFA 2.4.0-19 Improves CPU usage by inlining several small domain-related functions. Sanitization now occurs only once, after the journal has been replayed. Code marked as obsolete has been removed. Fixes an issue where an internal update message woudln't be properly initialised. Fixes an irrelevant warning when "publish" equals "active" or "inactive" equals "delete" in a DNSKEY key. Fixes embedded delegation issues. _ Sanitization complaining about wrong glue resource records in embedded delegations _ Sanitization complaining about unexpected signatures in embedded delegations _ Internal state is now correctly set. Fixes a policy issue where a DNSSEC chain would not be added if the DNSKEY was not already generated and added. Fixes an issue where removing an RRSIG covering a type could sometimes invalidate an RRSIG covering another in the same domain. Fixes an issue where a query that would return an RDATA with a '.' domain and require additionals, would trigger a memory underflow with undefined results. Fixes an issue that could occur when replaying NSEC3 updates from the journal. Fixes dnssec-policy NSEC chain generation that could not be completed because of an interference by the internal integrity tests. Fixes an issue with NSEC3 type bitmap handling that would occur on an empty broken zone without RRSIG records. Fixes an issue where reading corrupted messages would not be handled properly. Fixes an issue where the illegal addition of a DS resource record would not be handled properly. 20190205: YADIFA 2.4.0-18 Signature verification now has an abstract API (easier extension to future algorithms e.g.: EDDSA). Added our own zone test program. This includes signatures verification. It's in the test section and the feature should be moved inside the command line later. Fixes an issue where deleting a DNSKEY in a dynamic update would not be handled properly. Fixes an issue where removing an RRSIG in signature maintenance would not change the type bitmap in the associated NSEC3 record. Fixes an issue where maintenance would remove an RRSIG for a replacement (exchange) that could not be created (e.g.: private key missing). Fixes an issue managing a zone with an NSEC3PARAM record but no NSEC3 chain. Fixes an issue where NSEC3 chain recomputation could be called before RRSIG changes would be known. Fixes an issue where stopping yadifad while it started a signature thread (in a window of a few instructions) would trigger an assertion. Fixes an issue where dnssec-policies could conflict with RRSIG pushed with a dynamic update. Fixes an issue parsing records with a class ANY in update messages. 20190109: YADIFA 2.4.0-17 Added a test for the keyroll feature (test section). Key creation time is now systematically set in newly created keys. 20181122: YADIFA 2.4.0-11 Fixes handling of several limit cases in chain updates (that should never happen in a sane system). Fixes some minor memory leaks. This is the first release that is meant to prevent DNSKEY with incorrect "smart" setup making yadifad trying to take them at every occasion (e.g.: dynamic update). 20181122: YADIFA-2.4.0-10 Made to caters for the needs of an internal project. 20180802: YADIFA 2.4.0-1 Fixes all fixable -Wextra warnings (that ar not in -Wall for some reason) One of these warnings would have showed the suprise-issue with the ACL ... These fixes needs to be thoroughly tested before being used on anything production. 20180725: YADIFA 2.4.0 alpha Fixes an issue where a secondary having downloaded a invalid zone from an primary will proceed re-download it and failing until the zone is fixed on the primary. Now it will wait until the axfr-retry + random(axfr-retry-jitter) elapsed. It is now possible to change the network configuration at runtime. It is now possible to have threads logged with a tag instead of an opaque hexadecimal ID. (--enable-log-thread-tag) It is now possible to pipe execute loggers output. e.g.: my-zipped-channel "|/usr/bin/gzip - >> /var/log/yadifa.log.gz" Obviously, outputs are run using the uid/gid set for the server. As the command can be restarted for several reasons so using >> is the obvious choice. The maximum number of queries that are queued on an overloaded server is now configurable. Note this is currently only used by network-model 1 and the ram usage in bytes is about (workers * size * 64) For a server that only needs to answer 10000 queries per second, it would be suitable to use: e.g.: network-model-worker-backlog-size 10000 Our artificial benchmark tests are showing that setting this value to 500000 is enough to handle about 2.5 millions queries per second on a server with the appropriate hardware configured properly (network queues, ...). The zone journal maximum size is now an hard limit instead of "best effort within a few bytes". The --disable-messages ./configure option has now been removed as the send & recv are not suitable for proper aliased addresses handling. The build system has been changed: From now on, to do a debug build, add CFLAGS='-O0 -g3 -DEBUG=1' to the configure command. e.g.: ./configure --enable-shared --enable-log-thread-tag CC=clang CFLAGS='-O0 -g3 -DDEBUG=1' A release build that keeps the symbols would be: ./configure --enable-log-thread-tag CC=clang CFLAGS='-O3 -g -DDEBUG=0' The dnszone library has been merged into dnscore and dnsdb. Several of our unit tests have been added as well as the valgrind suppression file (yadifad.supp). Several simplifications and abstractions have been made on the internal APIs. Network model 1 is the only model available from this version. dnssec-thread-count parameter is now obsolete 20180213: YADIFA 2.3.8 Fixes the OPT record Z flags not being cleared in server answers. 20171207: YADIFA 2.3.0 - 2.3.7 From now on, both primary and secondaries are updating the zone in the same manner (journal transactions) Messages are now default (--enable-messages). Disable them using --disable-messages. Adds more (dynamic) update validation. Adds a build option to remove compile date and time from various help messages (--disable-build-timestamp) A primary can now be configured to allow updating RRSIG records externally (e.g.: update add domain. RRSIG ...) Fixes an issue where closing an (a)XFR stream could lead to a race over the file descriptors. Fixes an issue where an AXFR query would return a version of the zone too old to be upgradable by following incremntal updates. Fixes an issue where zones with big-enough NSEC3 coverage (several millions NSEC3 record) could potentially reach an internal limit of the database. Fixes an issue where shutting down YADIFA while a zone is being downloaded (AXFR) may make it wait forever. Fixes an issue where the secondary would complain about a missing private key. Fixes an issue where a specifically truncated IXFR query may make YADIFA replying with an AXFR. Fixes an issue where an IXFR query returning "not implemented" instead of an AXFR would be retried later as an IXFR. Fixes an issue where hammering reopening the logs on an overloaded server would not work properly. 20170912: YADIFA 2.2.6 Fixes an issue where a maliciously crafted message may block the server. (CVE-2017-14339) 20170420: YADIFA 2.2.5 Fixes an issue on message-enabled servers where the return address would not be captured Increased the maximum number of network interfaces to 256 20170406: YADIFA 2.2.4 Fixes an issue with relative include names that would not always be properly computed Fixes an issue where concurrent configuration reloads could lead to a crash 20170223: YADIFA 2.3.1 (internal) Added thread_pool_try_enqueue_call to give up if a queue is full or overworked (distance project) Fixes an issue with the CW queuing mechanism when trying to fill a full queue. 20161124: YADIFA 2.3.0 (internal) ECDSA can now be disabled at ./configure time. The support of ECDSA is not available in the openssl package of older Linux distributions. You can now add --disable-ecdsa at configure time to allow a build on these systems. Processed signals are now logged upon processing (info level) to allow the admin to know when a signal has effectively gone through. CPU affinity can now be tuned to stick a worker on a core. In
: thread-affinity-multiplier can be used to use every (1) or every odd (2) logical CPU. Parameter range from 0 to 4. (default is 0 = autodetect) By default, if hypertheading is detected, the multiplier is set to 2, else to 1. thread-affinity-base can be used to chose the first local CPU to consider. Parameter range from 0 to 3. (default is 0) In the end, network workers will have their affinity set to (base + multiplier * workerindex). The main purpose is to avoid using the hyperthread logical CPU as it can be counterproductive in some setups for high (10Gbps) troughput. Fixes: - fixed an issue on servers using the network-model 1 model (
: network-model 1) - fixed an issue where the removal in a certain order of hash/hash* related domains would end-up triggering an abort - fixed an issue where querying a signed domain that was deleted would answer NOERROR instead of NXDOMAIN - fixed an issue where a zone loaded with a journal would not be marked "dirty" and thus would not be fully dumped on disk upon kill -USR1 - fixed an issue with network aliases not configured on all setups of --enable-messages - fixed an issue with the logger not releasing the log files before reconfiguration - fixed an issue with the journal where heavy load would prevent notification to secondaries 20161108: YADIFA 2.2.2 OpenSSL 1.1.0 crypto API support 20160719: YADIFA 2.2.1 Multi-primary support: Added axfr-retry-failure-delay-multiplier and axfr-retry-failure-delay-max
parameters to increase the time between two AXFR/IXFR retries on a primary. Fixes: - fixed an issue that would crash a YADIFA secondary when restarting with a journal present - fixed an issue in AXFR/IXFR retry timing management 20160715: YADIFA 2.2.0 Multi-primary support: In , the primaries field is now a list. When the primary fails to answer, it is moved to the end of the list and (new) first one is used instead. There is a true-multiprimary setting, defaulted to 'no'. In true multiprimary mode, changing the primary implies dropping local zone data and ignore serial values. This is to be used for a setup with truly independent primaries. By default, the primary change occurs at first failure. This can be changed to a higher value with multiprimary-retries (maximum: 255) This mostly makes sense on true-multiprimary mode as you want to be sure before reloading a zone completely. Smart signing: Keys with smart signing information are now handled by YADIFA. DNSSEC policies: YADIFA generates an rolls your keys and makes a non-DNSSEC zone into an NSEC or NSEC3 one. Support for ECDSA algorithm. Better support for huge incremental changes of a zone: YADIFA used to do the modification in one go, which could make it unresponsive for very big changes. Now the changes are applied more slowly, allowing queries to be answered. New network model: A new network model can be enabled. This model's main purpose is to be more resistent to system stalls with minimal, if any, performance loss.
network-model 1 NSEC3 management improved. Several improvements have been made on the way NSEC3 is handlded. Chains partially covering the zone are now accepted. Fixes: - fixed an issue where the maximum pid value supported was 99999 - fixed an issue with RRSIG TTL values that were not always at the expected value. - fixed an issue with the $TTL not being respected. 20160126: YADIFA 2.1.6 Fixes: - fixed an issue where the referral would not be measured for UDP on a optimised build. 20160108: YADIFA 2.1.5 Dynamic updates do not use temporary files anymore which improves their general performance. The statistics now shows the referrals. Fixes: - fixed an issue where getting a huge incremental transfer would prevent the server from answering queries while applying the changes. - fixed an issue serving IXFR that would occur when a incremental change step was bigger than 64KB - fixed an issue for Solaris with the memory alignment fix not active everywhere - fixed an issue on the Solaris build settings - fixed an issue where sometimes yadifad would not find a configuration file given as a parameter with a relative path - fixed an issue where a wild-card would not be properly returned with an AXFR - fixed an issue where dynamically updating a zone at a speed such that the zone file would need to be written multiple times on disk before finishing the previous write could lead to a deadlock 20151026: YADIFA 2.1.4 The zone reader error reporting has been improved. Stacktrace support added for Solaris. Known issue: - Adding and or removing NSEC3PARAM dynamically is not properly handled. Fixes: - fixed an issue where an NSEC3 answer proving a * query would lead to a crash - fixed an issue where a private key may be not recognised as such - fixed an issue where dynamic update prerequisite check would fail a valid match - fixed an issue where zone signature maintenance would only start if all private keys were available. 20150821: YADIFA 2.1.3 Fixes: - fixed an issue that could lead to a crash at startup - fixed an issue where parsing a TYPE#### record would stop the parser prematurely 20150814: YADIFA 2.1.2 The ./configure script has a new option: --enable-full-ascii7 This changes the behaviour of DNS name validation to accept all the ASCII7 characters instead of only the DNS-space ones. Enabling this option is not recommended. Fixes: - fixes an issue where the hmac-shaX identification string sent with a TSIG had the suffix ".sig-alg.reg.int". 20150714: YADIFA 2.1.1 The yadifa command line has a new option: --config|-c file : read the specific configuration file instead of ~/.yadifa.rc Issues detected on the NSEC3 database have now been upgraded from debug to info/warning Fixes: - fixed an issue where, on some cases; the garbage collector for the zones was not triggering for a long time. - fixed an issue in the Makefile (courtesy of DENIC) - fixed an issue where a few bytes could be leaked in some rare cases when failing to unload a zone - fixed an issue in RRL where some values of IPv6 prefix - fixed an issue accepting some answers on IXFR transfers 20150424: YADIFA 2.1.0 New journal file format: This new format addresses a few issues like having maximum journal file and a relatively constant random access time even for very big sizes. The internal messaging queue has been changed to address huge amount of zones. New CHaos queries supported: hostname id.server Known issues: _ building successfully with LTO may require to append both AR=gcc-ar and RANLIB=gcc-ranlib to the ./configure command 20150403: YADIFA 2.0.6 This release is a public release. This minor update's sole purpose is to fix YADIFA builds on OpenBSD. Fixes: - fixed a crash that could occur while sending a massive amount of notifications - OpenBSD builds are fixed. Tested on: OpenBSD 5.6 amd64, standard installation. Configure: ./configure Tested on: OpenBSD 5.6 amd64, with gcc 4.9 installed. Configure: ./configure CC=egcc 20150226: YADIFA 2.0.5 This release is a public release. Fixes: - fixed an issue with huge IXFR transfers as a primary - fixed an issue with notifications on secondary-secondary-primary setup - fixed an issue with a potential infinite loop loading an AXFR from a primary - fixed missing hmac-sha* from configuration - fixed an issue with TLSA records parsing - fixed an issue with base 16 encoding - fixed an issue parsing * domains - fixed an issue with some RRL motivated answers - increased the maximum number of network interfaces from 5 to 16 - fixed an error in the configuration examples where "statistics" was used instead of "stats" - minor fixes and improvements 20141216: YADIFA 2.0.4 This release is a public release. By popular demand, the default log file directory is now PREFIX/var/log/yadifa. It can be set using --with-logdir=/my/dir Improved build mechanism. It has been tested to work automatically on Linux, FreeBSD, OSX, SunOS. RedHat family builds will use -O2 as maximum optimisations. Note that some optional features are now enabled by default but can be disabled. Fixes: - fixed an issue with the AXFR transfer where the serial number would not be properly taken into account - fixed an issue with the notify mechanism that could occur if the server was only listening to 127.0.0.1 - fixed an issue with bogus DNSKEY records that may potentially lead to a crash in openssl - fixed a reported potential "tmpfile" vulnerability on DEBUG builds (generated with make debug) - fixed an issue with IPv6 connections on some architectures - typos fixes - minor fixes and improvements 20141104: Architecture portability enhancements. On Solaris, if no --enable-force32bits nor --enable-force64bits is set, then 64 bits will be forced (fixes an issue at link-time) ELF 64-bit MSB executable SPARCV9 Version 1, UltraSPARC3 Extensions Required, dynamically linked, not stripped, no debugging information available PATH=/opt/csw/bin:/usr/ccs/bin:$PATH ./configure --enable-force32bits PATH=/opt/csw/bin:/usr/ccs/bin:$PATH make 20141030: Architecture portability enhancements. FreeBSD 9 FreeBSD dnode3 9.0-RELEASE-p3 FreeBSD 9.0-RELEASE-p3 #0: Tue Jun 12 02:52:29 UTC 2012 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 gcc (GCC) 4.2.1 20070831 patched [FreeBSD] ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 9.0 (900044), not stripped Ubuntu Linux dnode10 3.2.0-49-generic #75-Ubuntu SMP Tue Jun 18 17:39:32 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xe3b8601b9b5e59f8c9ce519cacbe9b8ff544ff1d, not stripped OSX Darwin RD-Mac-Mini.local 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun 3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64 Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) Mach-O 64-bit executable x86_64 20141029: Architecture portability enhancements. uname -a gcc --version file yadifad YellowDog Linux Linux 2.6.29-3.ydl61.4 #1 SMP Mon Sep 7 14:50:27 PDT 2009 ppc64 ppc64 ppc64 GNU/Linux gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44) ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped note: using --enable-force64bits failed because of ssl, no simple/quick way to install openssl-devel.ppc64 seemed available Debian PPC64 Linux 3.2.0-3-powerpc64 #1 SMP Mon Jul 23 08:03:56 UTC 2012 ppc64 GNU/Linux gcc (Debian 4.6.3-8) 4.6.3 ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xedc47c984a4af7eb9a7ecbc0f135e4d064ba08f0, with unknown capability 0x41000000 = 0x13676e75, with unknown capability 0x10000 = 0xb0401, not stripped note: using --enable-force64bits failed because of ssl, no simple/quick way to install openssl-devel.ppc64 seemed available 20141016: YADIFA 2.0.2 TCP fallback support on truncation 20140905: YADIFA 2.0.0 This release is a public release Fixes: - fixed a log incorrectly reporting an error when the client didn't close the TCP connection fast enough - fixed an issue with the statistics on TCP queries Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. 20140829: YADIFA 2.0.0-beta3-public This release is a public release - --disable-master feature at configure now builds a secondary-only server Fixes: - fixed an issue with TSIG signed queries - fixed an issue with thread pool live resizing - fixed an issue where reading an undeleted obsolete journal ending at the start of a newly transferred zone from the primary would incorrectly trigger an error Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. 20140630: YADIFA 2.0.0-beta2-public This release is a public release - basepath disabled - pidpath removed, only pidfile remains - log reopen notification is now timestamped - secondary zones no longer complain about missing NSEC/NSEC3 private keys - the error code ZRE_FILE_NOT_FOUND has been replaced by the more accurate code ZRE_NO_VALID_FILE_FOUND - default logging settings no longer output debug Fixes: - fixed issue in flag computation (AD,CD) - fixed an issue with journal truncation sometimes leading to a crash - zone parsing now correctly accepts '#' as a comment marker - zone parsing now rejects wrong fqdn as soon as it reads them, leading to a more accurate error message - removing the last dnskey of a zone no longer crashes the server Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. yadifa remote client commands prototype is now available with the following supported commands: -shutdown shuts down yadifa e.g. ./yadifa -s "192.0.2.1 port 53" -t shutdown -cfgreload reloads the and sections of the yadifad configuration e.g. ./yadifa -s "192.0.2.1 port 53" -t cfgreload -logreopen closes and reopen the log files e.g. ./yadifa -s "192.0.2.1 port 53" -t logreopen -freezeall prevents all zones from being updated dynamically with nsupdate e.g. ./yadifa -s "192.0.2.1 port 53" -t freezeall -freeze prevents a zone from being updated dynamically with nsupdate e.g. ./yadifa -s "192.0.2.1 port 53" -t freeze -q somedomain.eu -unfreezeall enables updates of all zones again e.g. ./yadifa -s "192.0.2.1 port 53" -t unfreezeall -unfreeze enables updates of a zone again e.g. ./yadifa -s "192.0.2.1 port 53" -t unfreeze -q somedomain.eu In order to work, the allow-control ACL must be defined either in
for the global commands and may also be defined in for the ones targeting a specific zone. e.g. allow-control 127.0.0.1 Note that tsig is not supported in the client yet. 20140528: YADIFA 2.0.0-beta1-public This release is a public release - NSID implemented (enabled at ./configure time with --enable-nsid - generic parser for: - getops - zone file - resolv.conf - configuration - '@' can now be used in a zone file - new binary for controlling 'yadifad' (yadifa) - framework is rewritten for multi core systems - single core server has been removed Fixes: - fixed several minor issues Know issues: - removing all dnskeys from a zone file crashes the server - yadifa has some issues with nodelay, nocork 20130424: YADIFA 1.1.0 _ added DSA signature _ added SHA-256 SHA-384 SHA-512 digest algorithms _ now supports additional DNSSEC algorithms: DSASHA1 DSASHA1_NSEC3 RSASHA256_NSEC3 RSASHA512_NSEC3 _ Respone Rate Limitation implemented (enabled at ./configure time with --enable-rrl) _ --enable-tiny-footprint now reduces the memory usage further by reducing the standard log queue from 2^20 to 2^12 entries _ the general speed has been slightly improved _ dynamic updates pending for more than 3 seconds are now dropped with an error _ dynamic provisioning Fixes: _ fixed a memory leak that could occur at NSEC3 generation when loading the zone failed in a particular way _ fixed a memory leak at ixfr send _ fixed handling of '_' character that was improperly stored in the database _ fixed bandwidth limit settings (tcp stream in and out) not always being taken from the configuration _ fixed TSIG answer verification for notifies _ fixed error codes not being registered and thus logged as unknown hexadecimal error code. _ other minor fixes 20130612: YADIFA 1.0.3 Fixes only (backports from 1.1.0) Fixes: _ fixed an issue preventing YADIFA from being build from another directory _ fixed an issue with OSX systems where gsed has to be used instead of sed _ fixed an issue with the '_' character not being properly handled _ fixed an issue where reading MX record from a zone file would incorrecly be rejected as invalid _ fixed an issue where the OPT record would not be properly written _ fixed an issue where an undefined ACL reference would be silently ignored _ fixed missing code tags for several error codes. From now on unregistered codes are dumped in hexadicimal. _ fixed portability issues with BSD and OSX _ fixed several minor issues 20120921: YADIFA 1.0.2 Fixes only Fixes: _ fixed an issue where the journal file was sometimes not properly closed at the end of a task _ fixed an issue where the TCP usage slots would sometimes wrongly return that they were all being used _ fixed an issue on IXFR processing (secondary side) where the type of answer from the primary would not be properly detected _ fixed an issue with TSIG on secrets not exactly 16 bytes long (binary form) _ fixed an issue on 32 bits architectures where the sig-validity-* fields would not be properly handled if not set on each zone section. _ slightly improved the replay time of big journal files _ fixed several minor issues Known issues: _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120709: YADIFA 1.0.1 _ logging repeat compression is now by channel instead of global Fixes: _ fixed an issue where glibc whould assert if libgcc_s.so (libgcc_s.so.1) and libc.so (libc.so.6) where not available inside the chrooted directory of YADIFA _ fixed an issue in the syslog module Known issues: _ on 32 bits architectures, the sig-validity-* fields are not properly copied from
to as a workaround, set the sig-validity fields in each container in 32 bits architectures ie: sig-validity-interval 7 sig-validity-regeneration 168 sig-validity-jitter 3600 _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120625: YADIFA 1.0.0 _ LTO support can be enabled with --enable-lto but this is not working with clang. LTO does not increase the performance significally _ parallel processing of listening addresses can now be enabled. It can be set using thread-count-by-address in the
section. By default YADIFA will not use parallel processing as this feature has not been as thoroughly tested as the single-thread processing model _ default parameters tuning _ fixes Known issue: _ on 32 bits architectures, the sig-validity-* fields are not properly copied from
to as a workaround, set the sig-validity fields in each container in 32 bits architectures ie: sig-validity-interval 7 sig-validity-regeneration 168 sig-validity-jitter 3600 20120530: YADIFA 1.0.0RC3 _ the configuration parser now ignores undefined logger names and report them with a warning _ syslog messages are now put in the name of "yadifad" instead of the name used for the "syslog" channel _ syslog messages do not print the time from YADIFA anymore _ improved the steps involved in loading a locally cached secondary zone _ zones are now loaded in background _ man page yadifad-conf.man5 renamed into yadifad.conf.man5 Fixes: _ AXFR/IXFR answers with the RA bit set are nolonger rejected as invalid _ YADIFA now answers to SIGINT again (shutdown) _ fixed an issue where obsolete AXFR files were not always being deleted _ fixed an issue occurring when both IPv4 and IPv6 were available to handle a notify _ fixed journal replay issue where some RRSIGs records were not properly removed _ fixed an issue occurring with IPv6 queries _ fixed an issue in the generation of a specific NSEC3 error answer _ fixed named query style layout Known issue: _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120328: YADIFA 1.0.0RC2 _ fixed logging issue on work file creation error _ fixed an issue where IXFR queries could be rejected as being wrongly formatted _ fixed an issue in the query logging text _ enabled command line options ( -u uid -g gid -d ) 20120319: YADIFA 1.0.0RC1 Is a full functional authoritative name server: - works as primary or secondary name server - AXFR - IXFR - NOTIFY - NSUPDATE - TSIG - CLASSES: - IN - CH (just for version) - TYPES: - AAAA - CNAME - DNSKEY - DS - HINFO - MX - NAPTR - NS - NSEC3 - NSEC3PARAM - NSEC - PTR - RRSIG - SOA - SRV - SSHFP - TXT - Automatic resigning - DNSSEC algorithms: - 5 (RSASHA1) - 7 (RSASHA1-NSEC3 - ACL's KNOWN ISSUES: NSEC3: _ cannot work with multiple NSEC3PARAM chains with mixed OPT-IN/OUT settings _ adding a new NSEC3 chain expects that the primary sends the NSEC3PARAM first (it does not seems to be always the case) We have a case where a primary starts with 2 thousands NSEC3 opt-out records then adds 6 millions NSEC3 opt-in records but does not give the NSEC3PARAM record first. The secondary server rejects them all because it's unable to link them to a chain. (This one has high priority) DNSSEC: _ it is not allowed to change the zone security mode (unsecure, NSEC, or NSEC3). Once the zone is loaded it keeps its security mode. _ dynamic updates of NSEC as well as NSEC3 records are refused QUIT: the server will shutdown on the following conditions: _ detection of an impossible situation or an internal integrity issue (ie: for any reason the SOA has vanished from a zone) _ memory limit reached which prevents any more work _ ipc issue which prevent internal services communication ACL: _ since the access control is set by zone and CHAOS class is not implemented as a configurable zone, it is not possible (yet) to specifically block CHAOS queries. 20111121: YADIFA 0.5.5 - many fixes KNOWN ISSUE: NSEC3 secondary zone replay fails. 20110706: YADIFA 0.5.0 - secondary mode, AXFR/IXFR (no TSIG yet for the secondary-side transfer) - answers to a notify from the primary - polls the (first) primary on the primaries list - maintains the .axfr & .ix files (deletes the obsoletes ones) - TSIG queries are checked - Replays the zone journal on startup after the zone load (journaling) - Answers IXFR queries (journaling) 20110601: YADIFA 0.4.0 Operational: - It works as a no dnssec name server - No notifies to secondary name servers - daemon - Answers AXFR queries with TSIG - nsupdate functionality (journaling) - TSIG on client server side will be transmitted, but not checked - ACL works - The zone has SOA, NS A resource records. 20110524: YADIFA 0.3.0 First release internally of yadifad 20110524115500 GMT+1. Operational: - It works as a no dnssec name server - No notifies to secondary name servers - daemon - Answers AXFR queries - The zone has SOA, NS A resource records. 20091224: YADIFA 0.2.0 _ Answers AXFR queries _ ACL based on IP and TSIG (not all query types are ACL'ed yet) 20091104: YADIFA 0.1.0 YADIFA is a work in progress. The main goal is to have an alternative for BIND or NSD. Version 0.1.0 is an authoritative server only. It has no: - AXFR/IXFR functionality - dynupdate - support for NSEC - support for NSEC3 - caching mechanism - additional tools (eg.dig, dnssectools, drill,...) It has: - a very fast way to give authoritative answer - a very fast method for loading the database and checking the zone files This first release is to have a feeling how it works in an operational environment. TODO Everything what is not implemented, has to be implemented. Most of the code is there, but is not activated. No comformity tests has been done. (This of course is on the todo list) Bug Reports and Mailing Lists Bugs reports should be sent to bugreport@yadifa.eu yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/INSTALL0000644000000000000000000000013214505005531017226 xustar000000000000000030 mtime=1695812441.687971375 30 atime=1695812445.799030253 30 ctime=1695812495.042735522 yadifa-2.6.5-11201/lib/dnsdb/INSTALL0000664000374500037450000004173114505005531017176 0ustar00signersigner00000000000000Quick installation ****************** You will need the most up-to-date aclocal, autoheader, automake, autoconf, make and a C compiler installed (clang, icc or gcc >= 4.6) By default gcc is used but you can specify your compiler adding CC=x in ./configure. ie: ./configure CC=clang openssl has to be build with shared Note that gcc < 4.6 will be build with -O0 and > 4.6 with -O3 ./configure make sudo make install cd /usr/local sudo mkdir -p var/run var/log var/zones/keys var/zones/masters var/zones/slaves var/zones/xfr Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" With "Homebrew" installed for openssl support: ./configure -with-openssl=/usr/local/opt/openssl@1.1 CFLAGS="-O2 -g -DDEBUG=0 -DNDEBUG=1" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `--with-openssl=DIR' Use the openssl from directory DIR (where DIR is the PREFIX of openssl) `--enable-tiny-footprint' This will change the behaviour of the memory allocation of the database. It will take the smallest increase in memory required to fulfill an allocation instead of getting a bunch at once. Disabled by default. `--enable-messages' Will use recvmsg/sendmsg instead of recvfrom/sendto. This is only useful if * any interface the server listens from has aliased IPs. (ie: eth0 & eth0:1) AND * the server is configured to listen to 0.0.0.0 (it's its default) Having aliased addresses on interfaces can also be handled without using messages but enumerating the listen addresses in yadifad.conf instead. ie: listen 192.0.2.1, 192.0.2.2 `--enable-lto' Will use the Link Time Optimisations of gcc (or ipo for ICC) The gain of speed is very marginal so it is not recommended `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/NEWS0000644000000000000000000000013214505005531016674 xustar000000000000000030 mtime=1695812441.770972564 30 atime=1695812445.799030253 30 ctime=1695812495.044735551 yadifa-2.6.5-11201/lib/dnsdb/NEWS0000664000374500037450000000001414505005531016631 0ustar00signersigner00000000000000See README yadifa-2.6.5-11201/lib/dnsdb/PaxHeaders.1636/README0000644000000000000000000000013114505005531017054 xustar000000000000000030 mtime=1695812441.772972592 30 atime=1695812445.799030253 29 ctime=1695812495.04673558 yadifa-2.6.5-11201/lib/dnsdb/README0000664000374500037450000000377514505005531017033 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ 20230906: YADIFA 2.6.5-public Secondaries will nolonger enforce the TTL value of the NSEC3PARAM record. Fixes an issue caused by a limitation of the select system call. yadifa-2.6.5-11201/lib/PaxHeaders.1636/dnslg0000644000000000000000000000013214505005617016142 xustar000000000000000030 mtime=1695812495.948748498 30 atime=1695812499.082793384 30 ctime=1695812495.948748498 yadifa-2.6.5-11201/lib/dnslg/0000775000374500037450000000000014505005617016161 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/include0000644000000000000000000000013214505005617017565 xustar000000000000000030 mtime=1695812495.919748083 30 atime=1695812499.082793384 30 ctime=1695812495.919748083 yadifa-2.6.5-11201/lib/dnslg/include/0000775000374500037450000000000014505005617017604 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnslg/include/PaxHeaders.1636/dnslg0000644000000000000000000000013214505005617020674 xustar000000000000000030 mtime=1695812495.936748327 30 atime=1695812499.082793384 30 ctime=1695812495.936748327 yadifa-2.6.5-11201/lib/dnslg/include/dnslg/0000775000374500037450000000000014505005617020713 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnslg/include/dnslg/PaxHeaders.1636/config-load.h0000644000000000000000000000013214505005531023277 xustar000000000000000030 mtime=1695812441.338966377 30 atime=1695812445.803030311 30 ctime=1695812495.928748212 yadifa-2.6.5-11201/lib/dnslg/include/dnslg/config-load.h0000664000374500037450000000367714505005531023256 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include ya_result config_load_rc(const char *file_path); ya_result config_load_resolv_conf(void); yadifa-2.6.5-11201/lib/dnslg/include/dnslg/PaxHeaders.1636/config-resolver.h0000644000000000000000000000013214505005531024221 xustar000000000000000030 mtime=1695812441.339966391 30 atime=1695812445.803030311 30 ctime=1695812495.930748241 yadifa-2.6.5-11201/lib/dnslg/include/dnslg/config-resolver.h0000664000374500037450000001013014505005531024156 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #include //#include #ifndef CONFIG_RESOLVER_C extern const char RESOLVER_CONTAINER[]; #endif #define RO_NO_DOMAIN_OR_SEARCH 0 #define RO_DOMAIN 1 #define RO_SEARCH 2 #define CONFIG_SEARCH_OR_DOMAIN(fieldname) \ {"search", offsetof(CONFIG_TYPE, fieldname), (config_set_field_function*)config_set_search_or_domain, NULL,{._u8=RO_SEARCH}, 0, 0, CONFIG_TABLE_SOURCE_NONE, 0}, \ {"domain", offsetof(CONFIG_TYPE, fieldname), (config_set_field_function*)config_set_search_or_domain, NULL,{._u8=RO_DOMAIN}, 0, 0, CONFIG_TABLE_SOURCE_NONE, 0}, struct search_or_domain_s { union { host_address *search; host_address *domain; host_address *list; } address; u8 search_or_domain; }; typedef struct search_or_domain_s search_or_domain_s; /* ------------------------------------------------------------ */ struct resolv_s { search_or_domain_s search_or_domain; host_address *nameserver; u16 timeout; u8 attempts; u8 ndots; bool no_tld_query; bool debug; }; typedef struct resolv_s resolv_s; // resolver section #define CMDLINE_RESOLVER(resolver) \ CMDLINE_SECTION( RESOLVER_CONTAINER) \ CMDLINE_BOOL( "no_tld_query", 'Z', "no_tld_query" ) \ CMDLINE_BOOL( "res_debug", 'Y', "debug" ) \ CMDLINE_OPT( "attempts", 0, "attempts" ) \ CMDLINE_OPT( "ndots", 0, "ndots" ) \ CMDLINE_OPT( "timeout", 0, "timeout" ) //CMDLINE_OPT( "retry", 0, "udp_retry" ) //CMDLINE_OPT( "nameserver", 's', "nameservers" ) ya_result config_register_resolver(u8 priority); bool resolver_no_tld_query(); bool resolver_res_debug_get(); u8 resolver_ndots_get(); u8 resolver_retry_get(); u8 resolver_time_get(); u8 resolver_tries_get(); host_address* resolver_nameservers_get(); yadifa-2.6.5-11201/lib/dnslg/include/dnslg/PaxHeaders.1636/dns.h0000644000000000000000000000013214505005531021701 xustar000000000000000030 mtime=1695812441.339966391 30 atime=1695812445.803030311 30 ctime=1695812495.932748269 yadifa-2.6.5-11201/lib/dnslg/include/dnslg/dns.h0000664000374500037450000000357414505005531021654 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include u16 dns_new_id(void); yadifa-2.6.5-11201/lib/dnslg/include/dnslg/PaxHeaders.1636/resolv-conf.h0000644000000000000000000000013214505005531023352 xustar000000000000000030 mtime=1695812441.337966362 30 atime=1695812445.803030311 30 ctime=1695812495.934748298 yadifa-2.6.5-11201/lib/dnslg/include/dnslg/resolv-conf.h0000664000374500037450000000530114505005531023313 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include #include #include #include "dnslg/config-resolver.h" /* ------------------------------------------------------------ */ void resolv_print(resolv_s *resolver); void resolver_init(resolv_s *resolver); ya_result config_set_search_or_domain(const char *value, struct search_or_domain_s *dest, anytype settings); ya_result resolv_conf_parse(input_stream *out_is); ya_result resolv_conf_parse_file(const char* file_name, resolv_s *resolver); ya_result resolv_conf_parse_stream(resolv_s *resolver, input_stream *is); /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnslg/include/dnslg/PaxHeaders.1636/resolv.h0000644000000000000000000000013214505005531022427 xustar000000000000000030 mtime=1695812441.336966348 30 atime=1695812445.803030311 30 ctime=1695812495.936748327 yadifa-2.6.5-11201/lib/dnslg/include/dnslg/resolv.h0000664000374500037450000000763214505005531022401 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef RESOLV_H_ #define RESOLV_H_ #ifdef __cplusplus extern "C" { #endif #include /* defaults, minimum and maximum values for the resolver_s struct */ #define RES_PATH_RESOLV_CONF "/etc/resolv.conf" #define RES_NAME_SERVERS_MAX 3 /* MAXNS */ #define RES_OPTION_ATTEMPTS_DEFAULT 2 #define RES_OPTION_ATTEMPTS_MAX 5 #define RES_OPTION_NDOTS_DEFAULT 1 #define RES_OPTION_NDOTS_MAX 15 #define RES_TIMEOUT_DEFAULT 5 #define RES_TIMEOUT_MAX 30 struct resolver_s { host_address *nameserver; u8 *sortlist[6]; union { u8 *domain; u8 *search[6]; } name_ascii; u8 name_ascii_type; u8 resolv_ns; u8 ndots; u8 attempts; u8 timeout; u8 timeout_max; }; typedef struct resolver_s resolver_s; void resolv_without_forward(void); void resolv_print_version(void); int resolv_normal(void); ya_result resolv_lookup_name_server(host_address **dest); ya_result resolv_init(resolver_s *resolv); ya_result resolv_add_hostaddress(resolver_s *resolv, host_address *address); ya_result resolv_add_domain(resolver_s *resolv, char *domain); ya_result resolv_add_search(resolver_s *resolv, char *search); ya_result resolv_add_ndots(resolver_s *resolv, u8 ndots); ya_result resolv_add_attemps(resolver_s *resolv, u8 attemps); ya_result resolv_add_timeout(resolver_s *resolv, u8 timeout); #define IP_LIST_MAX 16 #define HAS_IPV4 0x01 #define HAS_IPV6 0x02 ya_result resolv_address(host_address *src, host_address *dst, int ip_flags); ya_result resolv_host_address_list(host_address *src, host_address *dst); #ifdef __cplusplus } #endif #endif /* RESOLV_H_ */ /* ------------------------------------------------------------ */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/src0000644000000000000000000000013214505005617016731 xustar000000000000000030 mtime=1695812495.958748642 30 atime=1695812499.082793384 30 ctime=1695812495.958748642 yadifa-2.6.5-11201/lib/dnslg/src/0000775000374500037450000000000014505005617016750 5ustar00signersigner00000000000000yadifa-2.6.5-11201/lib/dnslg/src/PaxHeaders.1636/config-load.c0000644000000000000000000000013214505005531021327 xustar000000000000000030 mtime=1695812441.363966735 30 atime=1695812445.803030311 30 ctime=1695812495.950748527 yadifa-2.6.5-11201/lib/dnslg/src/config-load.c0000664000374500037450000000730114505005531021272 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include #include #include #include #include #include #include ya_result config_load_rc(const char *file_path) { config_error_s cfgerr; ya_result return_code; /* ------------------------------------------------------------ */ // check if file exist then parse it struct stat s; if(stat(file_path, &s) >= 0) { config_set_source(CONFIG_SOURCE_FILE); if(FAIL(return_code = config_read(file_path, &cfgerr))) { formatln("%s: config error: %s:%u : '%s': %r", "resolver", cfgerr.file, cfgerr.line_number, cfgerr.line, return_code); flushout(); return return_code; } return 1; } return OK; } ya_result config_load_resolv_conf(void) { input_stream config_is; config_error_s cfgerr; ya_result return_code; /* ------------------------------------------------------------ */ config_set_source(CONFIG_SOURCE_FILE - 1); resolv_conf_parse(&config_is); if(FAIL(return_code = config_read_from_buffer((const char*)bytearray_input_stream_buffer(&config_is), bytearray_input_stream_size(&config_is), "/etc/resolv.conf", &cfgerr))) { formatln("%s: config error: %s:%u : '%s': %r", "resolver", cfgerr.file, cfgerr.line_number, cfgerr.line, return_code); flushout(); input_stream_close(&config_is); return return_code; } input_stream_close(&config_is); return OK; } yadifa-2.6.5-11201/lib/dnslg/src/PaxHeaders.1636/config-resolver.c0000644000000000000000000000013214505005531022251 xustar000000000000000030 mtime=1695812441.364966749 30 atime=1695812445.803030311 30 ctime=1695812495.952748556 yadifa-2.6.5-11201/lib/dnslg/src/config-resolver.c0000664000374500037450000001024514505005531022215 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #define CONFIG_RESOLVER_C #include #include "dnslg/resolv-conf.h" const char RESOLVER_CONTAINER[] = "resolver"; // resolver defines #define DEF_VAL_CONF_OPTION_NAMESERVERS "172.19.110.8 port 53" #define DEF_VAL_CONF_OPTION_ATTEMPTS "3" #define DEF_VAL_CONF_OPTION_TIMEOUT "1" #define DEF_VAL_CONF_OPTION_UDP_TRIES "1" #define DEF_VAL_CONF_OPTION_NDOTS "1" #define DEF_VAL_CONF_OPTION_RES_DEBUG "0" #define DEF_VAL_CONF_OPTION_NO_TLD_QUERY "0" /// resolver container #define CONFIG_TYPE resolv_s CONFIG_BEGIN(config_resolver_desc) CONFIG_HOST_LIST_EX( nameserver, DEF_VAL_CONF_OPTION_NAMESERVERS, CONFIG_HOST_LIST_FLAGS_DEFAULT /*| CONFIG_HOST_LIST_FLAGS_APPEND*/, 3 ) CONFIG_U16( timeout, DEF_VAL_CONF_OPTION_TIMEOUT ) CONFIG_U8( attempts, DEF_VAL_CONF_OPTION_ATTEMPTS ) CONFIG_U8( ndots, DEF_VAL_CONF_OPTION_NDOTS ) CONFIG_BOOL( no_tld_query, DEF_VAL_CONF_OPTION_NO_TLD_QUERY ) CONFIG_BOOL( debug, DEF_VAL_CONF_OPTION_RES_DEBUG ) // tricky struct, so go raw on it CONFIG_SEARCH_OR_DOMAIN(search_or_domain) CONFIG_END(config_resolver_desc) #undef CONFIG_TYPE // declare global variable resolv_s config_resolver_settings; ya_result config_register_resolver(u8 priority) { ya_result return_code; // init and register resolver settings container ZEROMEMORY(&config_resolver_settings, sizeof(config_resolver_settings)); // ptr_vector_init(&config_resolver_settings.servers); if(FAIL(return_code = config_register_struct(RESOLVER_CONTAINER, config_resolver_desc, &config_resolver_settings, priority))) { return return_code; } return 0; } u8 resolver_time_get() { // return config_resolver_settings.udp_time; return 0; } u8 resolver_tries_get() { return config_resolver_settings.attempts; } u8 resolver_retry_get() { // return config_resolver_settings.udp_retry; return 0; } u8 resolver_ndots_get() { return config_resolver_settings.ndots; } bool resolver_res_debug_get() { return config_resolver_settings.debug; } bool resolver_no_tld_query() { return config_resolver_settings.no_tld_query; } host_address * resolver_nameservers_get() { return config_resolver_settings.nameserver; } yadifa-2.6.5-11201/lib/dnslg/src/PaxHeaders.1636/dns.c0000644000000000000000000000013214505005531017731 xustar000000000000000030 mtime=1695812441.364966749 30 atime=1695812445.803030311 30 ctime=1695812495.954748584 yadifa-2.6.5-11201/lib/dnslg/src/dns.c0000664000374500037450000000451514505005531017700 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include #include static random_ctx id_random_ctx = NULL; u16 dns_new_id(void) { if(id_random_ctx == NULL) { id_random_ctx = random_init_auto(); } u16 id = (u16)random_next(id_random_ctx); return id; } void dnslg_init() { // created because the detection functions for dnslg are looking specifically for this // initialise structures // start service(s) } void dnslg_finalize() { // stop service(s) // clear memory } yadifa-2.6.5-11201/lib/dnslg/src/PaxHeaders.1636/resolv-conf.c0000644000000000000000000000013214505005531021402 xustar000000000000000030 mtime=1695812441.367966792 30 atime=1695812445.804030325 30 ctime=1695812495.956748613 yadifa-2.6.5-11201/lib/dnslg/src/resolv-conf.c0000664000374500037450000005341114505005531021350 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include #include #include #include #include #include #include "dnslg/resolv-conf.h" #define INPUT_FILE "/etc/resolv.conf" #define DO_PRINT 1 #define RO_NOTHING 0 #define RO_KEY_WORD 1 #define RO_NAME_SERVER_VALUE 2 #define RO_DOMAIN_VALUE 3 #define RO_SEARCH_VALUE 4 #define RO_OPTIONS_VALUE 5 #define RO_SORTLIST_VALUE 6 #define RO_TIMEOUT_VALUE 7 #define RO_ATTEMPTS_VALUE 8 #define RO_NDOTS_VALUE 9 #define RO_NS_MAX 3 // the same as in the resolv.conf man page #define RO_DOMAIN_MAX 1 // the same as in the resolv.conf man page #define RO_SEARCH_MAX 6 // the same as in the resolv.conf man page #define RO_TIMOUT_DEFAULT 5 #define RO_TIMEOUT_MAX 65535 #define RO_ATTEMPTS_DEFAULT 3 #define RO_ATTEMPTS_MAX 5 #define RO_NDOTS_DEFAULT 1 #define RO_NDOTS_MAX 15 #define RO_NO_TLD_QUERY_OFF 0 #define RO_NO_TLD_QUERY_ON 1 #define RO_NO_TLD_QUERY_DEFAULT RO_NO_TLD_QUERY_OFF #define RO_DEBUG_OFF 0 #define RO_DEBUG_ON 1 #define RO_DEBUG_DEFAULT RO_DEBUG_OFF #define RO_NO_DOMAIN_OR_SEARCH 0 #define RO_DOMAIN 1 #define RO_SEARCH 2 ya_result config_set_search_or_domain(const char *value, struct search_or_domain_s *dest, anytype settings) { ya_result return_code; yassert((settings._u8 == RO_SEARCH) || (settings._u8 == RO_DOMAIN)); if(dest->address.list != NULL) { host_address_delete(dest->address.list); dest->address.domain = NULL; } if(settings._u8 == RO_SEARCH) { // search anytype settings = {._8u8 = {CONFIG_HOST_LIST_FLAGS_FQDN,3,0,0,0,0,0,0}}; return_code = config_set_host_list(value, &dest->address.search, settings); dest->search_or_domain = RO_SEARCH; } else { // domain anytype settings = {._8u8 = {CONFIG_HOST_LIST_FLAGS_FQDN,1,0,0,0,0,0,0}}; return_code = config_set_host_list(value, &dest->address.domain, settings); dest->search_or_domain = RO_DOMAIN; } return return_code; } void resolver_init(resolv_s *resolver) { resolver->search_or_domain.address.domain = NULL; // and search ... resolver->search_or_domain.search_or_domain = RO_NO_DOMAIN_OR_SEARCH; resolver->nameserver = NULL; resolver->timeout = RO_TIMOUT_DEFAULT; resolver->attempts = RO_ATTEMPTS_DEFAULT; resolver->ndots = RO_NDOTS_DEFAULT; resolver->no_tld_query = RO_NO_TLD_QUERY_DEFAULT; resolver->debug = RO_DEBUG_DEFAULT; } void write_search(host_address *address, char *text) { for(;;) { formatln("%s : %{hostaddr} ", text, address); if(address->next == NULL) { break; } address = address->next; } flushout(); } void resolv_print(resolv_s *resolver) { if(resolver->search_or_domain.search_or_domain == RO_SEARCH) { if (resolver->search_or_domain.address.search != NULL) { write_search(resolver->search_or_domain.address.search, "RO SEARCH "); } } else if(resolver->search_or_domain.search_or_domain == RO_DOMAIN) { if (resolver->search_or_domain.address.domain != NULL) { write_search(resolver->search_or_domain.address.domain, "RO DOMAIN "); } } if (resolver->nameserver != NULL) { write_search(resolver->nameserver, "RO NAMESE "); } formatln("RO TIMEOUT : %lu", resolver->timeout); formatln("RO ATTEMPTS : %u", resolver->attempts); formatln("RO NDOTS : %u", resolver->ndots); formatln("RO NO_TLD_QUERY : %u", resolver->no_tld_query); formatln("RO DEBUG : %u", resolver->debug); //formatln("RO SEARCH_OR_DOMAIN: %u", resolver->search_or_domain); flushout(); } ya_result resolv_conf_parse_stream(resolv_s *resolver, input_stream *is) { ya_result return_code; parser_s parser; const char *string_delimiters = "\"\"''"; const char *multiline_delimiters = ""; const char *comment_markers = "#"; const char *blank_makers = "\040\t\r:"; const char *escape_characters = "\\"; if(ISOK(return_code = parser_init(&parser, string_delimiters, // by 2 multiline_delimiters, // by 2 comment_markers, // by 1 blank_makers, // by 1 escape_characters))) // by 1 { parser_push_stream(&parser, is); u64 started_at = timeus(); u8 search_domain_count = 0; u8 name_server_count = 0; u8 expect_word = RO_KEY_WORD; u8 ip_buffer[MAX_DOMAIN_LENGTH]; // declare and init 'search FQDNs' host_address search_domains; search_domains.next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT search_domains.tsig = NULL; #endif search_domains.version = HOST_ADDRESS_NONE; // declare and init 'domain FQDN' host_address domain; domain.next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT domain.tsig = NULL; #endif // declare and init resolving 'name_servers' host_address name_servers; name_servers.next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT name_servers.tsig = NULL; #endif for(;;) { if(ISOK(return_code = parser_next_token(&parser))) { if(return_code & PARSER_WORD) { u32 text_len = parser_text_length(&parser); const char *text = parser_text(&parser); switch(expect_word) { case RO_KEY_WORD: // search for key { if (!strncmp(text, "nameserver", text_len) && (text_len == 10)) { expect_word = RO_NAME_SERVER_VALUE; // add name servers on the list } else if (!strncmp(text, "domain", text_len) && (text_len == 6)) { resolver->search_or_domain.search_or_domain = RO_DOMAIN; formatln("DOMAIN %u\n", resolver->search_or_domain.search_or_domain); expect_word = RO_DOMAIN_VALUE; } else if (!strncmp(text, "search", text_len) && (text_len == 6)) { // new line, so new list if (search_domains.next != NULL) { host_address_delete_list(search_domains.next); // re-init header search_domains.version = HOST_ADDRESS_NONE; search_domains.next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT search_domains.tsig = NULL; #endif } // reset counter and set on 'search' search_domain_count = 0; resolver->search_or_domain.search_or_domain = RO_SEARCH; formatln("SEARCH %u\n", resolver->search_or_domain.search_or_domain); expect_word = RO_SEARCH_VALUE; } else if (!strncmp(text, "options", text_len) && (text_len == 7)) { expect_word = RO_OPTIONS_VALUE; } else if (!strncmp(text, "sortlist", text_len) && (text_len == 8)) { expect_word = RO_SORTLIST_VALUE; } else { print("INCORRECT\n"); return_code = ERROR; // non-existing key found } break; } case RO_NAME_SERVER_VALUE: { u8 host_type = HOST_ADDRESS_NONE; u8 ip_size; // re-init only 1 name server allowed expect_word = RO_KEY_WORD; // // check if more than 1 name server on the same line // // if so report syntax error if(FAIL(return_code = parse_ip_address(text, text_len, ip_buffer, sizeof(ip_buffer)))) { return_code = INCORRECT_IPADDRESS; break; } ip_size = (u8)return_code; if (ip_size == 4) { host_type = HOST_ADDRESS_IPV4; } if (ip_size == 16) { host_type = HOST_ADDRESS_IPV6; } // check if no more than NS_MAX name_server_count++; if(name_server_count > 3) { break; } switch(host_type) { case HOST_ADDRESS_IPV4: { host_address_append_ipv4(&name_servers, ip_buffer, NU16(DNS_DEFAULT_PORT)); break; } case HOST_ADDRESS_IPV6: { host_address_append_ipv6(&name_servers, ip_buffer, NU16(DNS_DEFAULT_PORT)); break; } } break; } case RO_DOMAIN_VALUE: { // re-init expect_word = RO_KEY_WORD; // no need to check the amount this will be tested with "RO_KEY_WORD" // check for FQDN // if not a correct FQDN report syntax error, this is in the return_code if(FAIL(return_code = cstr_to_dnsname_with_check_len(ip_buffer, text, text_len))) { break; } host_address_set_dname(&domain, ip_buffer, NU16(DNS_DEFAULT_PORT)); break; } case RO_SEARCH_VALUE: { // check for FQDN // if not a correct FQDN report syntax error, this is in the return_code if(FAIL(return_code = cstr_to_dnsname_with_check_len(ip_buffer, text, text_len))) { break; } // needs a counter, only 6 search FQDNs are allowed search_domain_count++; if(search_domain_count > 6) { break; } host_address_append_dname(&search_domains, ip_buffer, NU16(DNS_DEFAULT_PORT)); break; } case RO_OPTIONS_VALUE: { if (!strncmp(text, "timeout", text_len) && (text_len == 7)) { expect_word = RO_TIMEOUT_VALUE; } else if (!strncmp(text, "attempts", text_len) && (text_len == 8)) { expect_word = RO_ATTEMPTS_VALUE; } else if (!strncmp(text, "ndots", text_len) && (text_len == 5)) { expect_word = RO_NDOTS_VALUE; } else if (!strncmp(text, "no_tld_query", text_len) && (text_len == 12)) { expect_word = RO_KEY_WORD; resolver->no_tld_query = RO_NO_TLD_QUERY_ON; } else if (!strncmp(text, "debug", text_len) && (text_len == 5)) { expect_word = RO_KEY_WORD; resolver->debug = RO_DEBUG_ON; } else { print("INCORRECT OPTIONS\n"); return_code = ERROR; // non-existing key found } break; } case RO_TIMEOUT_VALUE: { u32 val; if(ISOK(return_code = parse_u32_check_range(text, &val, 0, MAX_U16, BASE_10))) { resolver->timeout = (u16)val; } break; } case RO_ATTEMPTS_VALUE: { u32 val; if(ISOK(return_code = parse_u32_check_range(text, &val, 0, MAX_U8, BASE_10))) { resolver->attempts = (u8)val; } break; } case RO_NDOTS_VALUE: { u32 val; if(ISOK(return_code = parse_u32_check_range(text, &val, 0, MAX_U8, BASE_10))) { resolver->ndots = (u8)val; } break; } case RO_SORTLIST_VALUE: // @todo 20140507 gve -- still needs todo this when I got time { #if DO_PRINT format("\n*** SORTLIST VALUE: "); output_stream_write(termout, (u8*)text, text_len); flushout(); #endif break; } default: // is not defined, so did will never be reached { #if DO_PRINT print("WRONG\n"); #endif return_code = ERROR; // non-existing key found break; } } } // PARSER_WORD else if(return_code & PARSER_EOL) { /// @todo 20140507 gve -- missing 'values' for the keys found still needs to be implemented for all keys -- gery if(expect_word == RO_NAME_SERVER_VALUE) { return_code = ERROR; break; } expect_word = RO_KEY_WORD; } // PARSER_EOL else if(return_code & PARSER_EOF) { input_stream *completed_stream = parser_pop_stream(&parser); input_stream_close(completed_stream); if(parser_stream_count(&parser) <= 0) { break; } } // PARSER_EOF } else { break; } if(FAIL(return_code)) { break; } } u64 stopped_at = timeus(); u64 delta = stopped_at - started_at; formatln("\nparsing lasted %lluus : %r", delta, return_code); if(resolver->search_or_domain.search_or_domain == RO_SEARCH) { resolver->search_or_domain.address.search = search_domains.next; } else if(resolver->search_or_domain.search_or_domain == RO_DOMAIN) { resolver->search_or_domain.address.domain = host_address_copy(&domain); } else { resolver->search_or_domain.address.list = NULL; } resolver->nameserver = name_servers.next; } return return_code; } ya_result resolv_conf_parse_file(const char* file_name, resolv_s *resolver) { input_stream is; ya_result return_code; if(ISOK(return_code = file_input_stream_open(&is, file_name))) { if(ISOK(return_code = resolv_conf_parse_stream(resolver, &is))) { #if DO_PRINT resolv_print(resolver); } else { formatln("oops: %r", return_code); flushout(); #endif } } return return_code; } ya_result resolv_conf_parse(input_stream *out_is) { resolv_s resolver; resolver_init(&resolver); resolv_conf_parse_file(INPUT_FILE, &resolver); // put the struct back in a stream output_stream os; bytearray_output_stream_init(&os, NULL, 0); osformatln(&os, ""); if(resolver.search_or_domain.search_or_domain == RO_DOMAIN) { // domain osformatln(&os, "domain %{hostaddrlist}", resolver.search_or_domain.address.domain); } else if(resolver.search_or_domain.search_or_domain == RO_SEARCH) { // search` osformatln(&os, "search %{hostaddrlist}", resolver.search_or_domain.address.search); } if(resolver.nameserver != NULL) { osformatln(&os, "nameserver %{hostaddrlist}", resolver.nameserver); } osformatln(&os, "timeout %hu", resolver.timeout); osformatln(&os, "attempts %hhu", resolver.attempts); osformatln(&os, "ndots %hhu", resolver.ndots); osformatln(&os, "no_tld_query %hhu", resolver.no_tld_query); osformatln(&os, "debug %hhu", resolver.debug); osformatln(&os, ""); u32 buffer_size = bytearray_output_stream_size(&os); u8 *buffer = bytearray_output_stream_detach(&os); output_stream_close(&os); bytearray_input_stream_init(out_is, buffer, buffer_size, TRUE); return buffer_size; } /** @} */ yadifa-2.6.5-11201/lib/dnslg/src/PaxHeaders.1636/resolv.c0000644000000000000000000000013214505005531020457 xustar000000000000000030 mtime=1695812441.366966777 30 atime=1695812445.804030325 30 ctime=1695812495.958748642 yadifa-2.6.5-11201/lib/dnslg/src/resolv.c0000664000374500037450000002237114505005531020426 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include #include #include #include #include #include "dnslg/resolv.h" /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ /** @brief Function ... * * ... * * @param ... * * @retval OK * @retval NOK */ #define RESOLVER_TAG 0x7A457E72757B457A void resolv_without_forward(void) { // } void resolv_print_version(void) { printf("1.0.1"); return; } ya_result resolv_lookup_name_server(host_address **dest) { ya_result return_code; host_address *address; u8 dname[MAX_DOMAIN_LENGTH + 1]; /// tsig_item *tsig = NULL; u16 ip_port = 53; u8 ip_buffer[16]; u8 ip_size; u32 port_value = 53; /// @todo 20130618 gve -- needs to be more generic char *value = "172.19.110.8"; /* ------------------------------------------------------------ */ // 1. GET THE IP ADDRESS(ES) FROM "/etc/resolv.conf" if(FAIL(return_code = parse_ip_address(value, strlen(value), ip_buffer, sizeof(ip_buffer)))) { return_code = 255; } ip_size = (u8)return_code; ip_port = (u16)port_value; // 2. STORE THE IP ADDRESS(ES) IN "dest" MALLOC_OBJECT_OR_DIE(address, host_address, HOSTADDR_TAG); address->next = NULL; #if DNSCORE_HAS_TSIG_SUPPORT address->tsig = NULL; #endif switch(ip_size) { case 4: { host_address_set_ipv4(address, ip_buffer, htons(ip_port)); break; } case 16: { host_address_set_ipv6(address, ip_buffer, htons(ip_port)); break; } case 255: { host_address_set_dname(address, dname, htons(ip_port)); break; } } *dest = address; return SUCCESS; } ya_result resolv_init(resolver_s *resolv) { ZEROMEMORY(resolv, sizeof(struct resolver_s)); /*** @todo 20130823 gve -- implement resolv->option_attempts = RES_OPTION_ATTEMPTS_DEFAULT; resolv->option_ndots = RES_OPTION_NDOTS_DEFAULT; resolv->option_timeout = RES_TIMEOUT_DEFAULT; */ return OK; } ya_result resolv_add_hostaddress(resolver_s *resolv, host_address *address) { // host_address **nameserver; return 0; } // 172.19.110.8 // 172.31.110.8 // search be.eurid.eu vt.eurid.eu tc.eurid.eu eurid.eu int.eurid.eu /* ------------------------------------------------------------ */ /** * * Resolving * * - * * * * * */ // remove addrinfo structure static void free_addrinfo(struct addrinfo *ai) { struct addrinfo *temp_ai; /* ------------------------------------------------------------ */ while (ai != NULL) { temp_ai = ai->ai_next; if (ai->ai_addr != NULL) { free(ai->ai_addr); } if (ai->ai_canonname) { free(ai->ai_canonname); } free(ai); ai = temp_ai; } } ya_result resolv_address(host_address *src, host_address *dst, int ip_flags) { struct addrinfo hints; struct addrinfo *ai_list; struct addrinfo *ai; struct sockaddr_in *sin; /// @todo 20160308 gve -- needs to be checked for linux int error_code; ya_result return_code = TRUE; char fqdn[MAX_DOMAIN_TEXT_LENGTH + 1]; /* ------------------------------------------------------------ */ // 1. PREPARE THE HINTS // memset(&hints, 0, sizeof(hints)); hints.ai_flags |= AI_CANONNAME; // no need to search for IPv6, IPv4 only if (! (ip_flags & HAS_IPV6)) { hints.ai_family = PF_INET; } // no need to search for IPv4, IPv6 only if (! (ip_flags & HAS_IPV4)) { hints.ai_family = PF_INET6; } // go search for IPv4 and IPv6 else { hints.ai_family = PF_UNSPEC; } hints.ai_socktype = SOCK_STREAM; hints.ai_addr = NULL; hints.ai_next = NULL; // 2. GET THE IP ADDRESS // dnsname_to_cstr(fqdn, src->ip.dname.dname); #if DEBUG formatln("dname: %{hostaddr}", src); #endif // size_t len = strlen(fqdn); // fqdn[len -1] = '\0'; // formatln("dname: %s", fqdn); error_code = getaddrinfo(fqdn, NULL, &hints, &ai_list); if (error_code != 0) { perror ("getaddrinfo"); return -1; // @todo 20140509 gve -- nicer error code --- } // 3. WRITE THE RESULT INTO HOST_ADDRESS LIST // int i; for (ai = ai_list, i = 0; ai != NULL && i < IP_LIST_MAX; ai = ai->ai_next) { switch (ai->ai_family) { case AF_INET: sin = (struct sockaddr_in *)ai->ai_addr; if (dst->version == 0) { host_address_set_ipv4(dst, (const u8 *)&sin->sin_addr.s_addr, dst->port); /// @note use host_address_set_with_sockaddr (translates v4 & v6) } else { host_address_append_ipv4(dst, (const u8 *)&sin->sin_addr.s_addr, dst->port); } break; } i++; } free_addrinfo(ai); return return_code; } ya_result resolv_host_address_list(host_address *src, host_address *dst) { ya_result return_code = TRUE; // char fqdn[MAX_DOMAIN_TEXT_LENGTH + 1]; // s32 fqdn_len; /* ------------------------------------------------------------ */ // init destination host address list host_address_clear(dst); dst->next = NULL; // go thru the list and all fqdn will be resolved into a new list (dst) while(src != NULL) { if (src->version == HOST_ADDRESS_DNAME) { // fqdn_len = dnsname_to_cstr(fqdn, src->ip.dname.dname); if(FAIL(return_code = resolv_address(src, dst, HAS_IPV4 | HAS_IPV6))) { #if DEBUG formatln("RESOLV ADDRESS FAULT"); #endif return return_code; } } src = src->next; } return return_code; } /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/Makefile.in0000644000000000000000000000013214505005547020266 xustar000000000000000030 mtime=1695812455.308166443 30 atime=1695812461.839259982 30 ctime=1695812495.922748126 yadifa-2.6.5-11201/lib/dnslg/Makefile.in0000664000374500037450000012116614505005547020237 0ustar00signersigner00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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@ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ # # ALL # ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ 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@ DIST_COMMON = $(srcdir)/../../mk/common-settings.mk \ $(srcdir)/../../mk/common-labels.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp \ $(dist_noinst_DATA) $(pkginclude_HEADERS) AUTHORS COPYING \ ChangeLog INSTALL NEWS README @USES_SUNC_TRUE@am__append_1 = @USES_SUNC_FALSE@am__append_2 = -O0 @IS_DARWIN_OS_TRUE@am__append_3 = -Wno-deprecated @HAS_CC_NO_IDENT_TRUE@am__append_4 = -fno-ident @HAS_CC_ANSI_TRUE@am__append_5 = -ansi @HAS_CC_PEDANTIC_TRUE@am__append_6 = -pedantic @HAS_CC_WALL_TRUE@am__append_7 = -Wall -Wno-unknown-pragmas @HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE@am__append_8 = -Werror=missing-field-initializers @HAS_CC_STD_GNU11_TRUE@am__append_9 = -std=gnu11 @HAS_CC_STD_C11_TRUE@@HAS_CC_STD_GNU11_FALSE@am__append_10 = -std=c11 -D_GNU_SOURCE @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_TRUE@am__append_11 = -std=gnu99 @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_C99_TRUE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_FALSE@am__append_12 = -std=c99 @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_C99_FALSE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_FALSE@@HAS_CC_XC99_TRUE@am__append_13 = -xc99 @HAS_CC_TUNE_NATIVE_TRUE@am__append_14 = -mtune=native @FORCE64BITS_TRUE@@HAS_CC_M64_TRUE@am__append_15 = -m64 @FORCE64BITS_TRUE@@HAS_CC_M64_TRUE@am__append_16 = -m64 @FORCE32BITS_TRUE@@FORCE64BITS_FALSE@@HAS_CC_M32_TRUE@am__append_17 = -m32 @FORCE32BITS_TRUE@@FORCE64BITS_FALSE@@HAS_CC_M32_TRUE@am__append_18 = -m32 # # DEBUG # @HAS_CC_G3_TRUE@am__append_19 = -g3 @HAS_CC_G3_FALSE@@HAS_CC_G_TRUE@am__append_20 = -g @HAS_CC_DWARF4_TRUE@am__append_21 = -gdwarf-4 @HAS_CC_DWARF3_TRUE@@HAS_CC_DWARF4_FALSE@am__append_22 = -gdwarf-3 # # Intel C Compiler # ############################################################################### #ICC #IPO= -ipo (need to use the intel xiar instead of ar) @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@am__append_23 = -DLTO -ipo @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@am__append_24 = -ipo @USES_ICC_TRUE@am__append_25 = -DUSES_ICC @HAS_CC_ANSI_ALIAS_TRUE@@USES_ICC_TRUE@am__append_26 = -ansi-alias -U__STRICT_ANSI__ @USES_ICC_TRUE@am__append_27 = -DMODE_DEBUG_ICC # # LLVM Clang # ############################################################################### # CLANG @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@am__append_28 = -DLTO -flto @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@am__append_29 = -flto @USES_CLANG_TRUE@am__append_30 = -DUSES_LLVM -Wno-gnu #-Wno-extended-offsetof @USES_CLANG_TRUE@am__append_31 = -DMODE_DEBUG_CLANG -fsanitize=address -fsanitize=bounds @IS_LINUX_FAMILY_TRUE@@USES_CLANG_TRUE@am__append_32 = -Wl,-z,stack-size=8388608 # Note: add a _d suffix for debug builds ? # # Gnu C # ############################################################################### #GCC @HAS_CPU_NIAGARA_TRUE@@USES_GCC_TRUE@am__append_33 = -mcpu=niagara @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_34 = -DLTO -flto -fwhole-program -fno-fat-lto-objects -fuse-linker-plugin @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_35 = -flto \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fwhole-program \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fno-fat-lto-objects \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fuse-linker-plugin \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -Wl,-Map=module.map \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -Wl,--cref @USES_GCC_TRUE@am__append_36 = -DUSES_GCC @USES_GCC_TRUE@am__append_37 = -DMODE_DEBUG_GCC -fstack-check -fstack-protector-strong @HAS_BFD_DEBUG_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_38 = -rdynamic @IS_LINUX_FAMILY_TRUE@@USES_GCC_TRUE@am__append_39 = -Wl,-z,stack-size=8388608 @USES_SUNC_TRUE@am__append_40 = -DUSES_SUNC @USES_SUNC_TRUE@am__append_41 = -DMODE_DEBUG_SUNC # Note: add a _d suffix for debug builds ? # # Unknown compiler # ############################################################################### # if an unknown compiler is used, it should have its own section @USES_UNKNOWN_TRUE@am__append_42 = -DUSES_UNKNOWN_COMPILER @USES_UNKNOWN_TRUE@am__append_43 = -DMODE_DEBUG_UNKNOWN # # Some BSD-based OSes need this # @IS_BSD_FAMILY_TRUE@am__append_44 = -I./include @IS_SOLARIS_FAMILY_TRUE@am__append_45 = -D_POSIX_PTHREAD_SEMANTICS subdir = lib/dnslg ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/eurid.m4 $(top_srcdir)/m4/yadifa.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = 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__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libdnslg_la_DEPENDENCIES = $(top_builddir)/lib/dnscore/libdnscore.la am__dirstamp = $(am__leading_dot)dirstamp am_libdnslg_la_OBJECTS = src/config-load.lo src/config-resolver.lo \ src/dns.lo src/resolv-conf.lo src/resolv.lo libdnslg_la_OBJECTS = $(am_libdnslg_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 = libdnslg_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libdnslg_la_LDFLAGS) $(LDFLAGS) -o $@ 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__depfiles_maybe = depfiles 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 = $(libdnslg_la_SOURCES) DIST_SOURCES = $(libdnslg_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_noinst_DATA) HEADERS = $(pkginclude_HEADERS) 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)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) # libdnslg_ladir=. # alphabetically please pkgincludedir = $(includedir)/dnslg ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCOPTIMISATIONFLAGS = @CCOPTIMISATIONFLAGS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DNSCORE = @DNSCORE@ DNSDB = @DNSDB@ DNSLG = @DNSLG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAS_ACL_SUPPORT = @HAS_ACL_SUPPORT@ HAS_BFD_DEBUG_SUPPORT = @HAS_BFD_DEBUG_SUPPORT@ HAS_BIG_ENDIAN = @HAS_BIG_ENDIAN@ HAS_BUILD_TIMESTAMP = @HAS_BUILD_TIMESTAMP@ HAS_CC_ADDRESS_SANITIZER_CHECK = @HAS_CC_ADDRESS_SANITIZER_CHECK@ HAS_CC_ANSI = @HAS_CC_ANSI@ HAS_CC_ANSI_ALIAS = @HAS_CC_ANSI_ALIAS@ HAS_CC_CATCH_UNDEFINED_BEHAVIOR = @HAS_CC_CATCH_UNDEFINED_BEHAVIOR@ HAS_CC_DWARF2 = @HAS_CC_DWARF2@ HAS_CC_DWARF3 = @HAS_CC_DWARF3@ HAS_CC_DWARF4 = @HAS_CC_DWARF4@ HAS_CC_EXCEPTIONS = @HAS_CC_EXCEPTIONS@ HAS_CC_G = @HAS_CC_G@ HAS_CC_G3 = @HAS_CC_G3@ HAS_CC_M32 = @HAS_CC_M32@ HAS_CC_M64 = @HAS_CC_M64@ HAS_CC_MISSING_FIELD_INITIALIZERS = @HAS_CC_MISSING_FIELD_INITIALIZERS@ HAS_CC_NO_IDENT = @HAS_CC_NO_IDENT@ HAS_CC_NO_OMIT_FRAME_POINTER = @HAS_CC_NO_OMIT_FRAME_POINTER@ HAS_CC_PEDANTIC = @HAS_CC_PEDANTIC@ HAS_CC_RDYNAMIC = @HAS_CC_RDYNAMIC@ HAS_CC_SANITIZE_ADDRESS = @HAS_CC_SANITIZE_ADDRESS@ HAS_CC_STACK_PROTECTOR = @HAS_CC_STACK_PROTECTOR@ HAS_CC_STD_C11 = @HAS_CC_STD_C11@ HAS_CC_STD_C99 = @HAS_CC_STD_C99@ HAS_CC_STD_GNU11 = @HAS_CC_STD_GNU11@ HAS_CC_STD_GNU99 = @HAS_CC_STD_GNU99@ HAS_CC_TUNE_NATIVE = @HAS_CC_TUNE_NATIVE@ HAS_CC_WALL = @HAS_CC_WALL@ HAS_CC_XC99 = @HAS_CC_XC99@ HAS_CLOSE_EX_REF = @HAS_CLOSE_EX_REF@ HAS_CTRL = @HAS_CTRL@ HAS_DNSSEC_TOOLS = @HAS_DNSSEC_TOOLS@ HAS_DYNUPDATE_SUPPORT = @HAS_DYNUPDATE_SUPPORT@ HAS_ECDSA_SUPPORT = @HAS_ECDSA_SUPPORT@ HAS_EDDSA = @HAS_EDDSA@ HAS_EVENT_DYNAMIC_MODULE = @HAS_EVENT_DYNAMIC_MODULE@ HAS_FULL_ASCII7 = @HAS_FULL_ASCII7@ HAS_KEYGEN = @HAS_KEYGEN@ HAS_LIBC_MALLOC_DEBUG_SUPPORT = @HAS_LIBC_MALLOC_DEBUG_SUPPORT@ HAS_LITTLE_ENDIAN = @HAS_LITTLE_ENDIAN@ HAS_LOCK_DEBUG_SUPPORT = @HAS_LOCK_DEBUG_SUPPORT@ HAS_LOGDIR = @HAS_LOGDIR@ HAS_LOG_PID = @HAS_LOG_PID@ HAS_LOG_THREAD_ID = @HAS_LOG_THREAD_ID@ HAS_LOG_THREAD_TAG = @HAS_LOG_THREAD_TAG@ HAS_MALLOC_DEBUG_SUPPORT = @HAS_MALLOC_DEBUG_SUPPORT@ HAS_MASTER_SUPPORT = @HAS_MASTER_SUPPORT@ HAS_MEMALIGN_ISSUES = @HAS_MEMALIGN_ISSUES@ HAS_MUTEX_DEBUG_SUPPORT = @HAS_MUTEX_DEBUG_SUPPORT@ HAS_NON_AA_AXFR_SUPPORT = @HAS_NON_AA_AXFR_SUPPORT@ HAS_NSEC3_SUPPORT = @HAS_NSEC3_SUPPORT@ HAS_NSEC_SUPPORT = @HAS_NSEC_SUPPORT@ HAS_NSID_SUPPORT = @HAS_NSID_SUPPORT@ HAS_RRL_SUPPORT = @HAS_RRL_SUPPORT@ HAS_RRSIG_MANAGEMENT_SUPPORT = @HAS_RRSIG_MANAGEMENT_SUPPORT@ HAS_SYNC_BUILTINS = @HAS_SYNC_BUILTINS@ HAS_SYSTEMD_RESOLVED_AVOIDANCE = @HAS_SYSTEMD_RESOLVED_AVOIDANCE@ HAS_TESTS = @HAS_TESTS@ HAS_TOOLS = @HAS_TOOLS@ HAS_TRACK_ZONES_DEBUG_SUPPORT = @HAS_TRACK_ZONES_DEBUG_SUPPORT@ HAS_TSIG_SUPPORT = @HAS_TSIG_SUPPORT@ HAS_YADIFA = @HAS_YADIFA@ HAS_ZALLOC_DEBUG_SUPPORT = @HAS_ZALLOC_DEBUG_SUPPORT@ HAS_ZALLOC_STATISTICS_SUPPORT = @HAS_ZALLOC_STATISTICS_SUPPORT@ HAS_ZALLOC_SUPPORT = @HAS_ZALLOC_SUPPORT@ HAVE_RECVMMSG = @HAVE_RECVMMSG@ HAVE_SENDMMSG = @HAVE_SENDMMSG@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IS_BSD_FAMILY = @IS_BSD_FAMILY@ IS_DARWIN_GE14 = @IS_DARWIN_GE14@ IS_DARWIN_OS = @IS_DARWIN_OS@ IS_LINUX_FAMILY = @IS_LINUX_FAMILY@ IS_SOLARIS_FAMILY = @IS_SOLARIS_FAMILY@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL = @OPENSSL@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZDB_HAS_DNSSEC_SUPPORT = @ZDB_HAS_DNSSEC_SUPPORT@ 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_CXX = @ac_ct_CXX@ 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@ 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@ logdir = @logdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 # # # AM_CFLAGS = -D_THREAD_SAFE -D_REENTRANT -D_FILE_OFFSET_BITS=64 \ -I$(abs_builddir) -I$(abs_builddir)/include \ -I$(abs_srcdir)/include $(am__append_3) $(am__append_4) \ $(am__append_5) $(am__append_6) $(am__append_7) \ $(am__append_8) $(am__append_9) $(am__append_10) \ $(am__append_11) $(am__append_12) $(am__append_13) \ $(am__append_14) $(am__append_15) $(am__append_17) \ $(am__append_23) $(am__append_25) $(am__append_26) \ $(am__append_28) $(am__append_30) $(am__append_33) \ $(am__append_34) $(am__append_36) $(am__append_38) \ $(am__append_40) $(am__append_42) $(am__append_44) \ $(am__append_45) $(LOCALFLAGS) -DDNSLG_BUILD=1 \ -I$(top_srcdir)/lib/dnscore/include \ -I$(top_builddir)/lib/dnscore/include \ -I$(top_srcdir)/lib/dnsdb/include \ -I$(top_builddir)/lib/dnsdb/include \ -I$(top_srcdir)/lib/dnslg/include \ -I$(top_builddir)/lib/dnslg/include AM_LDFLAGS = $(am__append_16) $(am__append_18) $(am__append_24) \ $(am__append_29) $(am__append_32) $(am__append_35) \ $(am__append_39) DEBUGFLAGS = $(am__append_1) $(am__append_2) $(am__append_19) \ $(am__append_20) $(am__append_21) $(am__append_22) \ $(am__append_27) $(am__append_31) $(am__append_37) \ $(am__append_41) $(am__append_43) LOCALFLAGS = -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)"' -DLOCALSTATEDIR='"$(localstatedir)"' -DDATAROOTDIR='"$(datarootdir)"' -DDATADIR='"$(datadir)"' -DLOCALEDIR='"$(localedir)"' -DLOGDIR='"$(logdir)"' -DTCLDIR='"$(tcldir)"' @HAS_LTO_SUPPORT_FALSE@@USES_CLANG_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_FALSE@@USES_GCC_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@AM_AR = llvm-ar @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@AM_AR = gcc-ar @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@AM_AR = xiar # # Sun C # ############################################################################### # SUNC @USES_SUNC_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_FALSE@@USES_CLANG_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_FALSE@@USES_GCC_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@AM_LD = ld.gold @USES_ICC_TRUE@AM_LD = ld @USES_SUNC_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@AM_RANLIB = gcc-ranlib #AM_CFLAGS += -I$(top_srcdir)/lib/dnstcl/include -I$(top_builddir)/lib/dnstcl/include dist_noinst_DATA = VERSION lib_LTLIBRARIES = libdnslg.la libdnslg_la_LDFLAGS = -version-info 7:4:0 libdnslg_la_LIBADD = $(top_builddir)/lib/dnscore/libdnscore.la I = include/dnslg FEATURESFILE = dnslg-config-features.h FEATURES = $(I)/$(FEATURESFILE) FEATURESDIR = lib/dnslg/include/dnslg FEATURESSRC = $(top_builddir)/$(FEATURESDIR)/dnslg-config.h pkginclude_HEADERS = \ include/dnslg/config-load.h \ include/dnslg/config-resolver.h \ include/dnslg/dns.h \ include/dnslg/resolv-conf.h \ include/dnslg/resolv.h libdnslg_la_SOURCES = \ src/config-load.c \ src/config-resolver.c \ src/dns.c \ src/resolv-conf.c \ src/resolv.c BUILT_SOURCES = $(FEATURES) CLEANFILES = buildinfo.h $(FEATURESSRC) VP = DNSLG all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../mk/common-settings.mk $(srcdir)/../../mk/common-labels.mk $(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) --gnu lib/dnslg/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/dnslg/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(srcdir)/../../mk/common-settings.mk $(srcdir)/../../mk/common-labels.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_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}; \ } src/$(am__dirstamp): @$(MKDIR_P) src @: > src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/$(DEPDIR) @: > src/$(DEPDIR)/$(am__dirstamp) src/config-load.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/config-resolver.lo: src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/dns.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/resolv-conf.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/resolv.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) libdnslg.la: $(libdnslg_la_OBJECTS) $(libdnslg_la_DEPENDENCIES) $(EXTRA_libdnslg_la_DEPENDENCIES) $(AM_V_CCLD)$(libdnslg_la_LINK) -rpath $(libdir) $(libdnslg_la_OBJECTS) $(libdnslg_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f src/*.$(OBJEXT) -rm -f src/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/config-load.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/config-resolver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dns.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/resolv-conf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/resolv.Plo@am__quote@ .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 -rm -rf src/.libs src/_libs install-pkgincludeHEADERS: $(pkginclude_HEADERS) @$(NORMAL_INSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ done uninstall-pkgincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) 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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) 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: -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) -rm -f src/$(DEPDIR)/$(am__dirstamp) -rm -f src/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf src/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-pkgincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES 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 -rf src/$(DEPDIR) -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: uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-data-local install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am \ install-pkgincludeHEADERS 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 uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-pkgincludeHEADERS ### YRCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -g -DCMR ### YPCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -pg -DCMP ### YDCFLAGS = -DDEBUG $(DEBUGFLAGS) -DCMD ### YSCFLAGS = $(YRCFLAGS) ### ### YRLDFLAGS = -g ### YPLDFLAGS = -pg ### YDLDFLAGS = -g ### ### if HAS_CC_RDYNAMIC ### YPLDFLAGS += -rdynamic ### YDLDFLAGS += -rdynamic ### endif ### ### if USES_CLANG ### # workaround a bug where clang does not handle properly profiling and optimizations ### YPCFLAGS += -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer ### endif ### ### YSLDFLAGS = $(YRLDFLAGS) ### ### AM_CFLAGS += $(YCFLAGS) ### AM_LDFLAGS += $(YLDFLAGS) ### ### AM_MAKEFLAGS=MODE_CFLAGS="$(AM_CFLAGS)" CC=$(CC) AR=$(AM_AR) LD=$(AM_LD) buildinfo.h: $(abs_top_builddir)/config.log echo \#pragma once > buildinfo.h 2> /dev/null echo // generated file, do not modify >> buildinfo.h 2> /dev/null echo \#define BUILD_OPTIONS \"$$(grep "/configure" $(abs_top_builddir)/config.log | head -1 | sed 's/.*\.\/configure *//')\" >> buildinfo.h 2> /dev/null all: REVISION $(FEATURESSRC) REVISION: (svn info 2>/dev/null;if [ $$? -ne 0 ];then echo "Revision: 0";fi)|grep Revision:|sed 's/^Revision: *//' > REVISION $(srcdir)/src/config-load.c: $(FEATURES) $(FEATURESSRC) $(FEATURESSRC): ../../config.h mkdir -p $(top_builddir)/$(FEATURESDIR) cp ../../config.h $(FEATURESSRC) features: $(FEATURES) $(FEATURES): ../../config.log REVISION VERSION $(FEATURESSRC) mkdir -p $(I) echo "#pragma once" > $(FEATURES) grep "^#define" $(FEATURESSRC) | sed -e 's/^#define /#define $(VP)_/' >> $(FEATURES) echo '#undef $(VP)_VERSION' >> $(FEATURES) which printf > /dev/null 2>&1 if [ $$? -eq 0 ];then \ printf '// version %i.%i.%i.%i-%i\n' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ printf '#define $(VP)_VERSION 0x%02x%02x%02x%02x%04xLL' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ else \ echo "#define $(VP)_VERSION_(vmain_,vsub_,vminor_,vpatch_,vrevision_) ((vmain_)<<40)|((vsub_)<<32)|((vminor_)<<24)|((vpatch_)<<16)|(vrevision_)" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMAIN_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VSUB_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\2')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMINOR_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\3')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VPATCH_ 0 >> $(FEATURES)" ; \ echo "#define $(VP)_VERSION_VREVISION_ $$(cat REVISION)" >> $(FEATURES) ; \ echo '#define $(VP)_VERSION $(VP)_VERSION_($(VP)_VERSION_VMAIN_,$(VP)_VERSION_VSUB_,$(VP)_VERSION_VMINOR_,$(VP)_VERSION_VPATCH_,$(VP)_VERSION_VREVISION_)' >> $(FEATURES) ; \ fi echo "// $(FEATURES)" >> $(FEATURES) echo >> $(FEATURES) install-data-local: $(FEATURES) mkdir -p $(DESTDIR)$(prefix)/include/dnslg /usr/bin/install -c -m 644 $(FEATURES) $(DESTDIR)$(prefix)/$(FEATURES) # 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: yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/Makefile.am0000644000000000000000000000013214505005531020246 xustar000000000000000030 mtime=1695812441.375966906 30 atime=1695812445.803030311 30 ctime=1695812495.924748155 yadifa-2.6.5-11201/lib/dnslg/Makefile.am0000664000374500037450000001217214505005531020213 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ACLOCAL_AMFLAGS = -I m4 include ../../mk/common-settings.mk AM_CFLAGS += -DDNSLG_BUILD=1 AM_CFLAGS += -I$(top_srcdir)/lib/dnscore/include -I$(top_builddir)/lib/dnscore/include AM_CFLAGS += -I$(top_srcdir)/lib/dnsdb/include -I$(top_builddir)/lib/dnsdb/include AM_CFLAGS += -I$(top_srcdir)/lib/dnslg/include -I$(top_builddir)/lib/dnslg/include #AM_CFLAGS += -I$(top_srcdir)/lib/dnstcl/include -I$(top_builddir)/lib/dnstcl/include dist_noinst_DATA = VERSION lib_LTLIBRARIES= libdnslg.la libdnslg_la_LDFLAGS = -version-info 7:4:0 libdnslg_la_LIBADD=$(top_builddir)/lib/dnscore/libdnscore.la I=include/dnslg FEATURESFILE=dnslg-config-features.h FEATURES=$(I)/$(FEATURESFILE) FEATURESDIR=lib/dnslg/include/dnslg FEATURESSRC=$(top_builddir)/$(FEATURESDIR)/dnslg-config.h # libdnslg_ladir=. # alphabetically please pkgincludedir = $(includedir)/dnslg pkginclude_HEADERS = \ include/dnslg/config-load.h \ include/dnslg/config-resolver.h \ include/dnslg/dns.h \ include/dnslg/resolv-conf.h \ include/dnslg/resolv.h libdnslg_la_SOURCES = \ src/config-load.c \ src/config-resolver.c \ src/dns.c \ src/resolv-conf.c \ src/resolv.c BUILT_SOURCES = $(FEATURES) include ../../mk/common-labels.mk all: REVISION $(FEATURESSRC) REVISION: (svn info 2>/dev/null;if [ $$? -ne 0 ];then echo "Revision: 0";fi)|grep Revision:|sed 's/^Revision: *//' > REVISION $(srcdir)/src/config-load.c: $(FEATURES) $(FEATURESSRC) $(FEATURESSRC): ../../config.h mkdir -p $(top_builddir)/$(FEATURESDIR) cp ../../config.h $(FEATURESSRC) CLEANFILES += $(FEATURESSRC) features: $(FEATURES) $(FEATURES): ../../config.log REVISION VERSION $(FEATURESSRC) VP=DNSLG mkdir -p $(I) echo "#pragma once" > $(FEATURES) grep "^#define" $(FEATURESSRC) | sed -e 's/^#define /#define $(VP)_/' >> $(FEATURES) echo '#undef $(VP)_VERSION' >> $(FEATURES) which printf > /dev/null 2>&1 if [ $$? -eq 0 ];then \ printf '// version %i.%i.%i.%i-%i\n' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ printf '#define $(VP)_VERSION 0x%02x%02x%02x%02x%04xLL' $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1 \2 \3/') 0 $$(cat REVISION) >> $(FEATURES) ; \ else \ echo "#define $(VP)_VERSION_(vmain_,vsub_,vminor_,vpatch_,vrevision_) ((vmain_)<<40)|((vsub_)<<32)|((vminor_)<<24)|((vpatch_)<<16)|(vrevision_)" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMAIN_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\1')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VSUB_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\2')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VMINOR_ $$(cat VERSION|sed 's/.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\3')" >> $(FEATURES) ; \ echo "#define $(VP)_VERSION_VPATCH_ 0 >> $(FEATURES)" ; \ echo "#define $(VP)_VERSION_VREVISION_ $$(cat REVISION)" >> $(FEATURES) ; \ echo '#define $(VP)_VERSION $(VP)_VERSION_($(VP)_VERSION_VMAIN_,$(VP)_VERSION_VSUB_,$(VP)_VERSION_VMINOR_,$(VP)_VERSION_VPATCH_,$(VP)_VERSION_VREVISION_)' >> $(FEATURES) ; \ fi echo "// $(FEATURES)" >> $(FEATURES) echo >> $(FEATURES) install-data-local: $(FEATURES) mkdir -p $(DESTDIR)$(prefix)/include/dnslg /usr/bin/install -c -m 644 $(FEATURES) $(DESTDIR)$(prefix)/$(FEATURES) yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/VERSION0000644000000000000000000000013214505005531017262 xustar000000000000000030 mtime=1695812441.360966692 30 atime=1695812445.804030325 30 ctime=1695812495.926748183 yadifa-2.6.5-11201/lib/dnslg/VERSION0000664000374500037450000000000614505005531017220 0ustar00signersigner000000000000002.6.5 yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/AUTHORS0000644000000000000000000000013214505005531017262 xustar000000000000000030 mtime=1695812441.359966677 30 atime=1695812445.803030311 30 ctime=1695812495.938748355 yadifa-2.6.5-11201/lib/dnslg/AUTHORS0000664000374500037450000000013514505005531017223 0ustar00signersigner00000000000000Gery Van Emelen Eric Diaz Fernandez yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/COPYING0000644000000000000000000000013214505005531017245 xustar000000000000000030 mtime=1695812441.374966892 30 atime=1695812445.803030311 30 ctime=1695812495.940748384 yadifa-2.6.5-11201/lib/dnslg/COPYING0000664000374500037450000000312414505005531017207 0ustar00signersigner00000000000000 Copyright (c) 2011-2023, EURid vzw. All rights reserved. The YADIFA TM software product is provided under the BSD 3-clause license: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of EURid nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/ChangeLog0000644000000000000000000000013114505005531017763 xustar000000000000000029 mtime=1695812441.36296672 30 atime=1695812445.803030311 30 ctime=1695812495.942748412 yadifa-2.6.5-11201/lib/dnslg/ChangeLog0000664000374500037450000017673414505005531017750 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ 20230906: YADIFA 2.6.5-public Secondaries will nolonger enforce the TTL value of the NSEC3PARAM record. Fixes an issue caused by a limitation of the select system call. 20230301: YADIFA 2.6.4-public Fixes an issue building for 32 bits targets. 20230213: YADIFA 2.6.3-public Fixes an issue where the answer to a DNSSEC query to a wild record right below the apex in a DNSSEC3 zone would not return all the relevant NSEC3 records Fixes an issue where the answer to a DNSSEC query to a wild record in an NSEC zone would incorrectly use the name of the query in the answer Fixes an issue where NSEC3-owning labels were not compressed Complies with Fedora https://fedoraproject.org/wiki/Changes/PortingToModernC (see m4/contributions/20230118-fedora-toolchain-porting-to-modern-c.patch) 20221209: YADIFA 2.6.2-public Fixes an issue trying to link the backtrace call while building yadifad on FreeBSD 20221130: YADIFA 2.6.1-public Fixes an issue where the answer of an TSIG-signed IXFR query over an undefined domain would not be properly signed. Fixes an issue building for big-endian architectures. 20221004: YADIFA 2.6.0-public The server can optionally load the locally stored zone before asking for the last version to its primary (load-local-first) The server now avoids storing temporary zone transfer images to disk if the zone is small enough (axfr-memory-threshold) zone transfers source address can now be specified in the configuration (transfer-source) The server now allows to sign a zone using only zone signing keys. Fixes online chain generation started from an zone that is not covered by DNSSEC. Fixes an issue where a generated DNSKEY could be missing smart fields if the storage became full right before they needed to be written. Fixes an issue that could occur using EDDSA on big-enough data sets. 20220228: YADIFA 2.5.4-public Fixes an issue handling CNAME records. 20211025: YADIFA 2.5.3-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet with privileged access. 20210929: YADIFA 2.5.2-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet with privileged access. Fixes an issue where a corrupted configuration file could lead to a crash while starting-up. 20210924: YADIFA 2.5.1-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet. Fixes an issue where yadifad would sometimes reply with an AXFR instead of an IXFR if the journal is under maintenance. Increased the pid column in the logger to 6 characters Drastically increased the limit for TCP queries. Note that using a high enough number compared to the available memory will cause yadifad to warn about limits and OOM kill risks. In practice a few hundred TCP queries should be enough. 20210602: YADIFA 2.5.0-public Adds a new, friendlier, TCP manager. When enabled, TCP connections aren't closed harshly after some time has elapased without any activity. In a nutshell: It is enabled using --enable-tcp-manager. It works using a quota of allowed parallel connections per host. There is one value for the registeres hosts and one for unknown hosts. All defined primaries are automatically added to the TCP manager as registered hosts. The server's local addresses are automatically added to the registered hosts. The default timeout is set to 3 seconds but doesn't imply a connection will be closed : only that it is a candidate for being closed. EDDSA support has been enable. Sending a TCP message now uses a single system call (message_send_tcp) Fixes an issue in some FreeBSD setups where UDP messages couldn't be sent by YADIFA. Fixes an issue in FreeBSD where TCP connections would sometimes be closed too quickly. Fixes an issue where failed dynamic updates prerequisites would return SERVFAIL instead of the more accurate error code. Fixes atomic usage for older C compilers. Fixes an issue where some RRSIG records may not be updated in time if they happened to have their update bundled with NSEC3 records updates while the incremental change could not be immediately written in the journal. Fixes the yadifa keygen module to understand "help" as a command and not as a domain. 20210223: YADIFA 2.4.2-public Fixes an issue where records below delegation are not ignored (https://github.com/yadifa/yadifa/issues/12). Fixes an issue in the _mm model where shutting down while still initializing may not stop properly. Changes default user/group to 'yadifa' user in example configuration. Fixes an issue with autoconf 2.70 obsolete functions. Fixes an issue where an unknown key configured in a zone acl may lead to a crash. Fixes an issue where an query without EDNS involving ACLs using optional keys would incorrectly be rejected. Fixes an issue where a network thread with a failed context would incorrectly have its context deleted. Adds a feature to yadifad to ensure that the dates in the key-roll section can be successfully applied for the next 10 years (--check-policies). Added support for primary and secondary variant options. Fixes builds for gcc 11. 20201209: YADIFA 2.4.1-public Fixes an issue in dnscore where a DNS TCP query would not return the real DNS error code. Fixes an issue that could happen when a network model isn't supported. Fixes the propagation of sendmmsg/recvmmsg function availability detection. Fixes an issue where yadifad would issue a warning when a key with algorithm > 7 is used with an NSEC zone. Fixes an issue that will occur on a chrooted environment where a managed-path would be used incorrectly. Fixes CNAME answers not following the aliases chain. Fixes CNAME recursion not returning the same answer as named in NXDOMAIN cases (reported by https://github.com/SivaKesava1, see https://github.com/yadifa/yadifa/issues/11) Adds patch for musl support (from https://github.com/kolbma, see https://github.com/yadifa/yadifa/issues/9#issuecomment-723047226) Adds stack size fix for musl support (the default size is way too small) Now imports a custom version of stdatomic.h for systems where it is missing, located in dnscore/thirdpary/stdatomic.h Made for CentOS 7 and any other release where that file is missing. The import is only active if strictly needed and will only be visible during the build. At the moment, it is not being installed with the other headers. The original source of the file was taken from https://gist.github.com/nhatminhle/5181506 YAKEYROLLD 2.4.1 Fixes the handling of incomplete TCP queries. Fixes a possible race-condition when initialising the keyroll context error codes. The keyroll now has another automatic recovery layer where it completely restarts the handling of a domain, generating a one-step update to put the zone in the expected state. 20201012: YADIFA 2.4.0-public Fixes an issue that could happen with multiprocess logging. Fixes an issue parsing a *. domain. Improves support for LibreSSL. Added contributions directories with community-provided patches. Readied the source for the release. Many changes have been made since version 2.3.x. Please read the manual for more information. YAKEYROLLD 2.4.0 Since version 2.4.0, yadifad optionally allows dynamic update of RRSIG records. The external key managing tool using this feature is being released along with it. Please read the manual for more information. YADIFA CTRL 2.4.0 The updated version of the command line controller has been made more user-friendly. Please read the manual for more information. 20200722: YADIFA 2.4.0-67 Default listen is now "0.0.0.0,::0" Added "do-not-listen" feature to avoid conflicts with systemd-resolved, default is empty. Added --enable-systemd-resolved-avoidance in the configure script to change the default of "do-not-listen" to "127.0.0.53 port 53" Zone file reader now decodes \ddd tokens. Text zone parsing is now more lenient in what it accepts: unescaped @ and $ in a domain will be read as '@' and '$', with a warning. Improves the configuration update by keeping a timestamp of all files involved and checking they have been modified. Logger configuration can now be reconfigured during runtime. In the event of an incorrect reconfiguration of the network, yadifad will periodically try to reconfigure itself reading the configuration files. Fixes a potential issue in NSEC3 replying. Fixes TXT parsing issues. Fixes a leak with the chroot remapping when reconfiguring. Fixes a leak processing the command line. Fixes a leak in the policies configuration. 20200630: YADIFA 2.4.0-64 Network setup errors will now stop yadifad if they occur during the first configuration. If they occur during a reconfiguration the error will be logged every minute instead of every second. Fixes DSA API usage with OpenSSL 1.1.0 Fixes an other side effect of FreeBSD's process-shared mutexes where a thread waiting on a condition wouldn't always be woken up. Fixes IPv6 handling in FreeBSD. Fixes an issue where the logging could lock when daemonizing. Fixes the build-time-configuration paths when using cmake. Fixes an issue where a sync clean command would not delete the journal if the zone wasn't dynamically updated since the start of yadifad. Fixes an issue where the size of the buffer given for a message would be slightly bigger than needed. Duplicate but identical definition of a TSIG key are nolonger considered an error. Increased the log output handling control commands (mostly error conditions) yadifa ctrl: The fqdn isn't set by default anymore (it used to be '.' by default) Adds the "freeze", "thaw", "unfreeze", "freezeall", "unfreezeall" and "thawall" friendly keywords to yadfia ctrl. Adds the "notify" command. The FQDN has no default value anymore. Fixes the friendly parsing of the command line. Fixes several minor issues with the console output of the command line. 20200608: YADIFA 2.4.0-52 This is version is going to production as primary and for public release. Fixes limit case issues giving NSEC3 answers for some zone structures (mostly *, * + CNAME) Fixes an issue where the packet reader may not allocate enough room for SOA records (found in yakeyrolld) YKEYROLL-1.0.5-4 This is version is going to production as primary and for public release. Fixes the handling of more limit cases (broken setup). 20200515: YADIFA 2.4.0-51 In an effort to find issues using different tools, the code has been partially ported to compile in Visual Studio 2019. (Doesn't run) The code analyser from Visual Studio 2019 reported 290 potential issues, 5 of which were valid (understand: errors) and not reported by other analysers. We have used a mmap.c MIT-licensed code from github to help in this task. We'll have to decide to keep it or to write ours when we will do a Windows release. Adds a DNS pcap analyser tool to measure DNS traffic from a network pcap file. Used to find why so many packets were lost in the benchmark. (resut: The benchmark tool was broken.) Adds a --disable-filepool-cache build configure option. Logs clarity has been improved. Improved usability:
network-model option can now use words instead of just numbers, respectively: single, buffered, multi for 0, 1, 2. Fixes an issue that could occur in the logger service with some settings. Fixes an issue in the new network model. Fixes a memory leak that could occur in the cirular_file layer of the journal. Fixes a memory leak that could occur in the journal depending on the reason it was closed. Fixes a memory leak that could occur at shutdown while destroying a file pool. Fixes an issue where trying to print a corrupted fqdn (e.g.: random bytes) could have an undefined behaviour. Fixes an issue using the drop-before-load feature where the memory of the previous zone would not be completely freed yet before the new version of the zone started to load. Fixes a race condition that could occur while detaching stdout/stderr from console. Fixes missing AA flag in primary notification. Fixes a rare issue where a signal could block the logger. Fixes TSIG-covered answers of an unsupported opcode. YKEYROLL-1.0.5-3 Fixes the handling of several limit cases (all coming from a broken, corrupted state). 20200320: YADIFA 2.4.0-50 Efforts have been made to reduce the memory usage in the case where a lot of specific listening addresses are defined. A new network-model taking advantage of the multiple-send/receive of some kernels has been added. (recvmmsg, sendmmsg) Back-ported gcc-10 compatibility fix from the main development branch (trunk) This issue was reported by several distributions already using the yet-to-be-released gcc-10 (We are using gcc-9) Adds the tcp_manager for experimentation (an alternative way to keep track of opened TCP connections). Fixes a potential memory leak that could sometimes happen freeing NSEC3 records without removing their attached RRSIG first. Fixes FreeBSD 12.1/libressl build issue. YKEYROLL-1.0.5-2 Now handles SIGHUP to reopen the log files. Imrpoved the command line options help. 20200212: YADIFA 2.4.0-49 This version is going for production. Fixes an issue with signature expiration value where the time was sometimes incorrectly taken from the oldest key. The RRL tables are now growing faster in order to avoid wasting resources. YKEYROLL-1.0.4-2 This version is going for production. Now keeps the expected starting point and end point for all steps. This is used to verify the state before and after each update. Now has a "print" mode that logs the "plan" out (logs all the known steps). 20200128: YADIFA 2.4.0-48 New nameserver infrastructure update. In
, adds a log_files_disabled flag to disable checking the log-path directory for existence and writing rights. Without this, yadifad would refuse to work without a proper log output directory like we have on our SELinux setup. Fixes an issue that would occur if SELinux would reject a write operation with EPERM to a socket we have succesfully opened for writing. yadifad would not complain and end-up hammering both the socket creation and the logs Fixes an issue that would occur if SELinux would reject a read operation with EPERM on a socket we have successfully opened for reading. This happens, notably, the notify service, producing a lot of log lines. Now such an issue will make yadifad pause for one second. 20200106: YADIFA 2.4.0-45 Fixes an issue where having no ZSK would trigger a useless maintenance pass. Fixes an issue where notifies could stop being sent when their queue was full. (New dynamic queue used at minimal increased CPU cost for this part) Fixes an issue where reopening or syncing would have their effect delayed. Fixes an issue that could occur for DSA T parameter deduction from a public key. Made the command line more friendly using the new features from dnscore. YKEYROLL 1.0.3-0 Now filters-out publish and unpublish meta lines. Fixes an issue where retrying to send a message to an unresponsive server could have the message content reset. 20191120: YKEYROLL-1.0.2-3 This version is going for production. Adds switching to a uid/gid set in the configuration file (must be set to the same as yadifad). Adds process mutual-exclusion for plan generation. Improves shutdown speed. Reduces logging. 20191118: YADIFA 2.4.0-43 Fixes an issue where enabling key activation leniency would incorrectly enable deactivation leniency. Fixes an issue where redundant signatures would be kept longuer than needed. The journal name for the root zone will now be root_zone.cjf (only one dot) intead of ..cjf, as that name was troublesome. YKEYROLL-1.0.1-9 This version is going for production. Can now work in a loop without detaching from console. 20191106: YADIFA 2.4.0-42 This version is going for production. Issues found by CLion's code inspector fixed or marked as invalid. Downgrades several "error" into "notice". More generally, an effort has been made to reduce the log size. Setting a policy field with an incorrect value will now log an error instead of stopping yadifad. Slave zones don't run sanitization anymore, as the primary is "right". This avoids thight rules being counter-productive in production environments. Fixes an issue that would occur if an update happens at tahe same time as the removal of a DNSKEY when a maintenance has started. Fixes an issue where the authoritative bit coudl be flipped off in some operations. Fixes an issue where removing and adding the same record in a single update would incorrectly drop its signature. Fixes an issue where a secondary receiving an inccorrect IXFR stream (specifically: finishing on an incomplete page) would not reject the broken page. Fixes an issue where a primary would cut an IXFR page in half if a shutdown was triggered while the page was being read from the journal. Fixes an issue in the policy date computation that could lead to a time period without signature coverage. 20191010: YADIFA 2.4.0-41 Fixes typos. YKEYROLL-1.0.0 Improved error codes returned by the keyroll policies. Fixes an error that could occur parsing a corrupted step file. 20190927: YADIFA 2.4.0-40 Adds a tool to append an IXFR in text form (so, from a dig command) to a journal. This is an unfriendly pure dev tool meant to create some tests scenarii. The cjf-scan tool, used to print the content of a journal, can now print its content in a way similar to the dig command. Simply use the "-clean" command line option before the journal file name. Both the above tools mean that a journal can be dumped as text, edited then re-created as binary. Although not initially created for this purpose, it can be a powerful fix tool. Fixes the "11:04" issue. It was triggered by an optimisation not being handled on all exit paths of the maintenance function, potentially leading to a buffer overflow. Fixes an issue in the journal: If the first update written into a dynamically sized journal is bigger that the default size of the journal (64KB) then yadifad incorrectly tries to shift-out content to make room, which it obviously cannot do. 20190920: YADIFA 2.4.0-39 In
, adds axfr-strict-authority option. Defaulted to enabled unless yadifad was built-configured using --enable-non-aa-axfr-support. Improves TXT parsing (github/ JZerf). Fixes an potential crash on SIGHUP if the zone loader calee gives an incorrect answer (github/kolbma). Fixes an issue where a UDP query with invalid return address (port 0) would trigger an EINVAL leading yadifa to shutdown the thread. Fixes an issue with IPv6 aliased replies. Depending on the OS/release the value could be wrong. The fix tries several options. This has been tested on several Debian and RedHat variants and seems to work properly. 20190919: YADIFA 2.4.0-38 note: Serial bump due to issues during rpm packaging. Reduces the number of warnings triggered by type bitmap fixes. Now only prints one and leaves the rest available as debug. Contains code to track the "11:04" issue and verify the hypothesis of its cause. 20190913: YADIFA 2.4.0-26 Timestamp in dns-udp are now human-readable. Writing a zone as text now computes and updates the approximate wire size for the zone (AXFR/IXFR trigger accuracy) yadifad now replies to ENDS# bad format. Fixes an issue in dns-udp where the message size would not be reset on the received side. Fixes an issue in dns-udp where the rate-limiter would fire before a message would be checked for actual IO (aggregated queries). Fixes an issue in dns-udp where a very slow call-back would slow down the processing part of the receiver enough to trigger a timeout of the query. Fixes a warning that would be shown for keys being both NSEC and NSEC3. Fixes an issue where the '#' character was incorrectly set as a zone comment. Fixes an issue where a journal with an invalid character in a name would trigger an infinite error loop (until program shutdown). Fixes an issue where a DNSKEY dynamic update coming with an RRSIG push could fail under certain conditions. Fixes some typos. YKEYROLL-beta Improves error reporting. Allows different configuration files. Fixes corrupted plan handling. Updates the configuration example. Correction updates are now merged in a single step, then played. Added error-retries-cases in daemon mode. Added a --timeus-offset parameter (not publicly documented) to lie about the current time. Added a --dryrun parameter. Fixes an issue handling key duplicates. 20190627: YADIFA 2.4.0-25 Fixes an issue where a corrupted journal would prevent a secondary from working. Fixes an issue replaying NSEC3 chain changes as a secondary that could occur when a discrepancy was found. If a corrupted journal is found, yadifad now renames it adding ".bad" to its name. 20190613: YADIFA 2.4.0-24 Adds safeguards for the logger shutdown. FreeBSD 12.0 issue diagnostic: There was an elusive issue occurring only on FreeBSD 12.0 related to shared mutexes. After posting an the issue anonymously with a proof-of-concept code, it turns out it was bug in FreeBSD: An unlocked mutex is still being accessed by the thread library right after the effective unlock has occurred. yadifad destroys a structure containing mutexes right after it is unlocked for the last time. FreeBSD has issued a fix, but at the moment the fix appeared to have side effects. This may have been us not rebuilding "world" properly (First time we do this), or it may be that the patch wasn't complete at the time. The matter is closed as far as yadifad's source code is concerned so this is something to watch after the next FreeBSD update. Added the "freebsd12-test" proof-of-concept code in the test section of the code. Adds the IP_MTU_DISCOVER IP_PMTUDISC_OMIT patch: patch received 20190323 from daisuke.higashi@gmail.com /* * Linux 3.15 has IP_PMTUDISC_OMIT which makes sockets * ignore PMTU information and send packets with DF=0. * Fragmentation is allowed if and only if the packet * size exceeds the outgoing interface MTU or the packet * encounters smaller MTU link in network. * This mitigates DNS fragmentation attacks by preventing * forged PMTU information. * FreeBSD already has same semantics without setting * the option. */ Added sereral fixes for NetBSD builds. Ultimately, NetBSD declares but does not implement PSHARED. This makes that platform unusable for the moment. Logs have been improved (level & verbosity, some have been downgraded to debug). Improves command-line help. Internally, INVALID and UNPROCESSABLE messages are now seen as the same error. In
, added log_unprocessable boolean to add a warning log for bad DNS messages. If yadifad is not started as root but requires elevated privileges in order to bind an addess, it will stop. Fixes build on older sytems (FreeBSD). Fixes an incorrect warning message related to TSIG. Fixes an issue with garbage collection at shutdown. Fixes an issue that would occur if the signature max-interval was set high enough to end up in an integer overflow. Fixes an issue where newly added keys would not always be taken into account in the computations. Fixes an issue where the nttl cache could overflow. Fixes an issue in the path provider of yadifad where an empty secondary zone file setting could lead to a NULL pointer reference. Fixes an issue where the KSK public key would not be stored, losing the flags of the key as seen by libdnscore. Fixes an issue in dns-udp that would occur when TCP fails with a DNS error. Fixes an issue in dns-udp where the thread_pool destruction order could trigger some issues. Fixes an issue where a TCP read time-out from a client (thus when the server is sending) could lead to an indefinitely held connection. Fixes an issue that could happen in the RRL, leading to the current state pool being misused. Fixes an issue where an error code sent from the socket server would nto be interpreted correctly. Fixes an issue in the text parser that was being tripped in the yakeyrolld. Fixes an issue where asking the help from the command line would return to the shell with a non-zero value. YKEYROLL-alpha Code commited in alpha state to avoid potential issues related to a certain event. The new keyroll software is being written in C. It is based on the YADIFA framework. It's main features are: _ cron-like timings, _ KSK/ZSK separation, _ RRSIG push usage, _ one event per file and one file per event, _ integrity milestones, _ extension of the time-line on demand. 20190326: YADIFA 2.4.0-23 Added autogen.sh in the make dist. Improved yadifad startup so that simply asking for its version would not go through service start. Improved AXFR log messages: now showing the peer's IP address. 20190322: YADIFA 2.4.0-22 EDDSA is known but not handled. (EDDSA handling code is in the 2.5.x branch) Sanitization now checks for DNSKEY matching RRSIG records. Fixes an issue where yadifad would abort in a specific condition: A zone that allows RRSIG pushed by dynamic updates with a bunch of inactive ZSK keys available, one of them still in the zone with said inactive ZSK key in the zone having signature expiring after its deactivation date AND in the future with an active key in the zone that does not expire and is fully usable (key pair available) with a single KSK key in the zone that has no private part available ... ... was considered fubar and triggering an emergency stop (ending up in an abort()) Fixes an issue handling BigNum from OpenSSL being sometimes smaller than expected. Fixes a double-free issue (crashed yadifad the 20190311). Fixes an issue that would occur on a secondary when the journal is too small to work optimally. Added a "dsfromkey" in the test section, to be added in the command line later 20190218: YADIFA 2.4.0-21 Fixes an issue where killing yadifad while thread creation is in limbo would not work. yadifad will now ignore all signals until notify service thread is up and running (thus outside of limbo) Fixes an issue where policies would be tried on non-policed zones. 20190213: YADIFA 2.4.0-19 Improves CPU usage by inlining several small domain-related functions. Sanitization now occurs only once, after the journal has been replayed. Code marked as obsolete has been removed. Fixes an issue where an internal update message woudln't be properly initialised. Fixes an irrelevant warning when "publish" equals "active" or "inactive" equals "delete" in a DNSKEY key. Fixes embedded delegation issues. _ Sanitization complaining about wrong glue resource records in embedded delegations _ Sanitization complaining about unexpected signatures in embedded delegations _ Internal state is now correctly set. Fixes a policy issue where a DNSSEC chain would not be added if the DNSKEY was not already generated and added. Fixes an issue where removing an RRSIG covering a type could sometimes invalidate an RRSIG covering another in the same domain. Fixes an issue where a query that would return an RDATA with a '.' domain and require additionals, would trigger a memory underflow with undefined results. Fixes an issue that could occur when replaying NSEC3 updates from the journal. Fixes dnssec-policy NSEC chain generation that could not be completed because of an interference by the internal integrity tests. Fixes an issue with NSEC3 type bitmap handling that would occur on an empty broken zone without RRSIG records. Fixes an issue where reading corrupted messages would not be handled properly. Fixes an issue where the illegal addition of a DS resource record would not be handled properly. 20190205: YADIFA 2.4.0-18 Signature verification now has an abstract API (easier extension to future algorithms e.g.: EDDSA). Added our own zone test program. This includes signatures verification. It's in the test section and the feature should be moved inside the command line later. Fixes an issue where deleting a DNSKEY in a dynamic update would not be handled properly. Fixes an issue where removing an RRSIG in signature maintenance would not change the type bitmap in the associated NSEC3 record. Fixes an issue where maintenance would remove an RRSIG for a replacement (exchange) that could not be created (e.g.: private key missing). Fixes an issue managing a zone with an NSEC3PARAM record but no NSEC3 chain. Fixes an issue where NSEC3 chain recomputation could be called before RRSIG changes would be known. Fixes an issue where stopping yadifad while it started a signature thread (in a window of a few instructions) would trigger an assertion. Fixes an issue where dnssec-policies could conflict with RRSIG pushed with a dynamic update. Fixes an issue parsing records with a class ANY in update messages. 20190109: YADIFA 2.4.0-17 Added a test for the keyroll feature (test section). Key creation time is now systematically set in newly created keys. 20181122: YADIFA 2.4.0-11 Fixes handling of several limit cases in chain updates (that should never happen in a sane system). Fixes some minor memory leaks. This is the first release that is meant to prevent DNSKEY with incorrect "smart" setup making yadifad trying to take them at every occasion (e.g.: dynamic update). 20181122: YADIFA-2.4.0-10 Made to caters for the needs of an internal project. 20180802: YADIFA 2.4.0-1 Fixes all fixable -Wextra warnings (that ar not in -Wall for some reason) One of these warnings would have showed the suprise-issue with the ACL ... These fixes needs to be thoroughly tested before being used on anything production. 20180725: YADIFA 2.4.0 alpha Fixes an issue where a secondary having downloaded a invalid zone from an primary will proceed re-download it and failing until the zone is fixed on the primary. Now it will wait until the axfr-retry + random(axfr-retry-jitter) elapsed. It is now possible to change the network configuration at runtime. It is now possible to have threads logged with a tag instead of an opaque hexadecimal ID. (--enable-log-thread-tag) It is now possible to pipe execute loggers output. e.g.: my-zipped-channel "|/usr/bin/gzip - >> /var/log/yadifa.log.gz" Obviously, outputs are run using the uid/gid set for the server. As the command can be restarted for several reasons so using >> is the obvious choice. The maximum number of queries that are queued on an overloaded server is now configurable. Note this is currently only used by network-model 1 and the ram usage in bytes is about (workers * size * 64) For a server that only needs to answer 10000 queries per second, it would be suitable to use: e.g.: network-model-worker-backlog-size 10000 Our artificial benchmark tests are showing that setting this value to 500000 is enough to handle about 2.5 millions queries per second on a server with the appropriate hardware configured properly (network queues, ...). The zone journal maximum size is now an hard limit instead of "best effort within a few bytes". The --disable-messages ./configure option has now been removed as the send & recv are not suitable for proper aliased addresses handling. The build system has been changed: From now on, to do a debug build, add CFLAGS='-O0 -g3 -DEBUG=1' to the configure command. e.g.: ./configure --enable-shared --enable-log-thread-tag CC=clang CFLAGS='-O0 -g3 -DDEBUG=1' A release build that keeps the symbols would be: ./configure --enable-log-thread-tag CC=clang CFLAGS='-O3 -g -DDEBUG=0' The dnszone library has been merged into dnscore and dnsdb. Several of our unit tests have been added as well as the valgrind suppression file (yadifad.supp). Several simplifications and abstractions have been made on the internal APIs. Network model 1 is the only model available from this version. dnssec-thread-count parameter is now obsolete 20180213: YADIFA 2.3.8 Fixes the OPT record Z flags not being cleared in server answers. 20171207: YADIFA 2.3.0 - 2.3.7 From now on, both primary and secondaries are updating the zone in the same manner (journal transactions) Messages are now default (--enable-messages). Disable them using --disable-messages. Adds more (dynamic) update validation. Adds a build option to remove compile date and time from various help messages (--disable-build-timestamp) A primary can now be configured to allow updating RRSIG records externally (e.g.: update add domain. RRSIG ...) Fixes an issue where closing an (a)XFR stream could lead to a race over the file descriptors. Fixes an issue where an AXFR query would return a version of the zone too old to be upgradable by following incremntal updates. Fixes an issue where zones with big-enough NSEC3 coverage (several millions NSEC3 record) could potentially reach an internal limit of the database. Fixes an issue where shutting down YADIFA while a zone is being downloaded (AXFR) may make it wait forever. Fixes an issue where the secondary would complain about a missing private key. Fixes an issue where a specifically truncated IXFR query may make YADIFA replying with an AXFR. Fixes an issue where an IXFR query returning "not implemented" instead of an AXFR would be retried later as an IXFR. Fixes an issue where hammering reopening the logs on an overloaded server would not work properly. 20170912: YADIFA 2.2.6 Fixes an issue where a maliciously crafted message may block the server. (CVE-2017-14339) 20170420: YADIFA 2.2.5 Fixes an issue on message-enabled servers where the return address would not be captured Increased the maximum number of network interfaces to 256 20170406: YADIFA 2.2.4 Fixes an issue with relative include names that would not always be properly computed Fixes an issue where concurrent configuration reloads could lead to a crash 20170223: YADIFA 2.3.1 (internal) Added thread_pool_try_enqueue_call to give up if a queue is full or overworked (distance project) Fixes an issue with the CW queuing mechanism when trying to fill a full queue. 20161124: YADIFA 2.3.0 (internal) ECDSA can now be disabled at ./configure time. The support of ECDSA is not available in the openssl package of older Linux distributions. You can now add --disable-ecdsa at configure time to allow a build on these systems. Processed signals are now logged upon processing (info level) to allow the admin to know when a signal has effectively gone through. CPU affinity can now be tuned to stick a worker on a core. In
: thread-affinity-multiplier can be used to use every (1) or every odd (2) logical CPU. Parameter range from 0 to 4. (default is 0 = autodetect) By default, if hypertheading is detected, the multiplier is set to 2, else to 1. thread-affinity-base can be used to chose the first local CPU to consider. Parameter range from 0 to 3. (default is 0) In the end, network workers will have their affinity set to (base + multiplier * workerindex). The main purpose is to avoid using the hyperthread logical CPU as it can be counterproductive in some setups for high (10Gbps) troughput. Fixes: - fixed an issue on servers using the network-model 1 model (
: network-model 1) - fixed an issue where the removal in a certain order of hash/hash* related domains would end-up triggering an abort - fixed an issue where querying a signed domain that was deleted would answer NOERROR instead of NXDOMAIN - fixed an issue where a zone loaded with a journal would not be marked "dirty" and thus would not be fully dumped on disk upon kill -USR1 - fixed an issue with network aliases not configured on all setups of --enable-messages - fixed an issue with the logger not releasing the log files before reconfiguration - fixed an issue with the journal where heavy load would prevent notification to secondaries 20161108: YADIFA 2.2.2 OpenSSL 1.1.0 crypto API support 20160719: YADIFA 2.2.1 Multi-primary support: Added axfr-retry-failure-delay-multiplier and axfr-retry-failure-delay-max
parameters to increase the time between two AXFR/IXFR retries on a primary. Fixes: - fixed an issue that would crash a YADIFA secondary when restarting with a journal present - fixed an issue in AXFR/IXFR retry timing management 20160715: YADIFA 2.2.0 Multi-primary support: In , the primaries field is now a list. When the primary fails to answer, it is moved to the end of the list and (new) first one is used instead. There is a true-multiprimary setting, defaulted to 'no'. In true multiprimary mode, changing the primary implies dropping local zone data and ignore serial values. This is to be used for a setup with truly independent primaries. By default, the primary change occurs at first failure. This can be changed to a higher value with multiprimary-retries (maximum: 255) This mostly makes sense on true-multiprimary mode as you want to be sure before reloading a zone completely. Smart signing: Keys with smart signing information are now handled by YADIFA. DNSSEC policies: YADIFA generates an rolls your keys and makes a non-DNSSEC zone into an NSEC or NSEC3 one. Support for ECDSA algorithm. Better support for huge incremental changes of a zone: YADIFA used to do the modification in one go, which could make it unresponsive for very big changes. Now the changes are applied more slowly, allowing queries to be answered. New network model: A new network model can be enabled. This model's main purpose is to be more resistent to system stalls with minimal, if any, performance loss.
network-model 1 NSEC3 management improved. Several improvements have been made on the way NSEC3 is handlded. Chains partially covering the zone are now accepted. Fixes: - fixed an issue where the maximum pid value supported was 99999 - fixed an issue with RRSIG TTL values that were not always at the expected value. - fixed an issue with the $TTL not being respected. 20160126: YADIFA 2.1.6 Fixes: - fixed an issue where the referral would not be measured for UDP on a optimised build. 20160108: YADIFA 2.1.5 Dynamic updates do not use temporary files anymore which improves their general performance. The statistics now shows the referrals. Fixes: - fixed an issue where getting a huge incremental transfer would prevent the server from answering queries while applying the changes. - fixed an issue serving IXFR that would occur when a incremental change step was bigger than 64KB - fixed an issue for Solaris with the memory alignment fix not active everywhere - fixed an issue on the Solaris build settings - fixed an issue where sometimes yadifad would not find a configuration file given as a parameter with a relative path - fixed an issue where a wild-card would not be properly returned with an AXFR - fixed an issue where dynamically updating a zone at a speed such that the zone file would need to be written multiple times on disk before finishing the previous write could lead to a deadlock 20151026: YADIFA 2.1.4 The zone reader error reporting has been improved. Stacktrace support added for Solaris. Known issue: - Adding and or removing NSEC3PARAM dynamically is not properly handled. Fixes: - fixed an issue where an NSEC3 answer proving a * query would lead to a crash - fixed an issue where a private key may be not recognised as such - fixed an issue where dynamic update prerequisite check would fail a valid match - fixed an issue where zone signature maintenance would only start if all private keys were available. 20150821: YADIFA 2.1.3 Fixes: - fixed an issue that could lead to a crash at startup - fixed an issue where parsing a TYPE#### record would stop the parser prematurely 20150814: YADIFA 2.1.2 The ./configure script has a new option: --enable-full-ascii7 This changes the behaviour of DNS name validation to accept all the ASCII7 characters instead of only the DNS-space ones. Enabling this option is not recommended. Fixes: - fixes an issue where the hmac-shaX identification string sent with a TSIG had the suffix ".sig-alg.reg.int". 20150714: YADIFA 2.1.1 The yadifa command line has a new option: --config|-c file : read the specific configuration file instead of ~/.yadifa.rc Issues detected on the NSEC3 database have now been upgraded from debug to info/warning Fixes: - fixed an issue where, on some cases; the garbage collector for the zones was not triggering for a long time. - fixed an issue in the Makefile (courtesy of DENIC) - fixed an issue where a few bytes could be leaked in some rare cases when failing to unload a zone - fixed an issue in RRL where some values of IPv6 prefix - fixed an issue accepting some answers on IXFR transfers 20150424: YADIFA 2.1.0 New journal file format: This new format addresses a few issues like having maximum journal file and a relatively constant random access time even for very big sizes. The internal messaging queue has been changed to address huge amount of zones. New CHaos queries supported: hostname id.server Known issues: _ building successfully with LTO may require to append both AR=gcc-ar and RANLIB=gcc-ranlib to the ./configure command 20150403: YADIFA 2.0.6 This release is a public release. This minor update's sole purpose is to fix YADIFA builds on OpenBSD. Fixes: - fixed a crash that could occur while sending a massive amount of notifications - OpenBSD builds are fixed. Tested on: OpenBSD 5.6 amd64, standard installation. Configure: ./configure Tested on: OpenBSD 5.6 amd64, with gcc 4.9 installed. Configure: ./configure CC=egcc 20150226: YADIFA 2.0.5 This release is a public release. Fixes: - fixed an issue with huge IXFR transfers as a primary - fixed an issue with notifications on secondary-secondary-primary setup - fixed an issue with a potential infinite loop loading an AXFR from a primary - fixed missing hmac-sha* from configuration - fixed an issue with TLSA records parsing - fixed an issue with base 16 encoding - fixed an issue parsing * domains - fixed an issue with some RRL motivated answers - increased the maximum number of network interfaces from 5 to 16 - fixed an error in the configuration examples where "statistics" was used instead of "stats" - minor fixes and improvements 20141216: YADIFA 2.0.4 This release is a public release. By popular demand, the default log file directory is now PREFIX/var/log/yadifa. It can be set using --with-logdir=/my/dir Improved build mechanism. It has been tested to work automatically on Linux, FreeBSD, OSX, SunOS. RedHat family builds will use -O2 as maximum optimisations. Note that some optional features are now enabled by default but can be disabled. Fixes: - fixed an issue with the AXFR transfer where the serial number would not be properly taken into account - fixed an issue with the notify mechanism that could occur if the server was only listening to 127.0.0.1 - fixed an issue with bogus DNSKEY records that may potentially lead to a crash in openssl - fixed a reported potential "tmpfile" vulnerability on DEBUG builds (generated with make debug) - fixed an issue with IPv6 connections on some architectures - typos fixes - minor fixes and improvements 20141104: Architecture portability enhancements. On Solaris, if no --enable-force32bits nor --enable-force64bits is set, then 64 bits will be forced (fixes an issue at link-time) ELF 64-bit MSB executable SPARCV9 Version 1, UltraSPARC3 Extensions Required, dynamically linked, not stripped, no debugging information available PATH=/opt/csw/bin:/usr/ccs/bin:$PATH ./configure --enable-force32bits PATH=/opt/csw/bin:/usr/ccs/bin:$PATH make 20141030: Architecture portability enhancements. FreeBSD 9 FreeBSD dnode3 9.0-RELEASE-p3 FreeBSD 9.0-RELEASE-p3 #0: Tue Jun 12 02:52:29 UTC 2012 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 gcc (GCC) 4.2.1 20070831 patched [FreeBSD] ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 9.0 (900044), not stripped Ubuntu Linux dnode10 3.2.0-49-generic #75-Ubuntu SMP Tue Jun 18 17:39:32 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xe3b8601b9b5e59f8c9ce519cacbe9b8ff544ff1d, not stripped OSX Darwin RD-Mac-Mini.local 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun 3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64 Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) Mach-O 64-bit executable x86_64 20141029: Architecture portability enhancements. uname -a gcc --version file yadifad YellowDog Linux Linux 2.6.29-3.ydl61.4 #1 SMP Mon Sep 7 14:50:27 PDT 2009 ppc64 ppc64 ppc64 GNU/Linux gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44) ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped note: using --enable-force64bits failed because of ssl, no simple/quick way to install openssl-devel.ppc64 seemed available Debian PPC64 Linux 3.2.0-3-powerpc64 #1 SMP Mon Jul 23 08:03:56 UTC 2012 ppc64 GNU/Linux gcc (Debian 4.6.3-8) 4.6.3 ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xedc47c984a4af7eb9a7ecbc0f135e4d064ba08f0, with unknown capability 0x41000000 = 0x13676e75, with unknown capability 0x10000 = 0xb0401, not stripped note: using --enable-force64bits failed because of ssl, no simple/quick way to install openssl-devel.ppc64 seemed available 20141016: YADIFA 2.0.2 TCP fallback support on truncation 20140905: YADIFA 2.0.0 This release is a public release Fixes: - fixed a log incorrectly reporting an error when the client didn't close the TCP connection fast enough - fixed an issue with the statistics on TCP queries Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. 20140829: YADIFA 2.0.0-beta3-public This release is a public release - --disable-master feature at configure now builds a secondary-only server Fixes: - fixed an issue with TSIG signed queries - fixed an issue with thread pool live resizing - fixed an issue where reading an undeleted obsolete journal ending at the start of a newly transferred zone from the primary would incorrectly trigger an error Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. 20140630: YADIFA 2.0.0-beta2-public This release is a public release - basepath disabled - pidpath removed, only pidfile remains - log reopen notification is now timestamped - secondary zones no longer complain about missing NSEC/NSEC3 private keys - the error code ZRE_FILE_NOT_FOUND has been replaced by the more accurate code ZRE_NO_VALID_FILE_FOUND - default logging settings no longer output debug Fixes: - fixed issue in flag computation (AD,CD) - fixed an issue with journal truncation sometimes leading to a crash - zone parsing now correctly accepts '#' as a comment marker - zone parsing now rejects wrong fqdn as soon as it reads them, leading to a more accurate error message - removing the last dnskey of a zone no longer crashes the server Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. yadifa remote client commands prototype is now available with the following supported commands: -shutdown shuts down yadifa e.g. ./yadifa -s "192.0.2.1 port 53" -t shutdown -cfgreload reloads the and sections of the yadifad configuration e.g. ./yadifa -s "192.0.2.1 port 53" -t cfgreload -logreopen closes and reopen the log files e.g. ./yadifa -s "192.0.2.1 port 53" -t logreopen -freezeall prevents all zones from being updated dynamically with nsupdate e.g. ./yadifa -s "192.0.2.1 port 53" -t freezeall -freeze prevents a zone from being updated dynamically with nsupdate e.g. ./yadifa -s "192.0.2.1 port 53" -t freeze -q somedomain.eu -unfreezeall enables updates of all zones again e.g. ./yadifa -s "192.0.2.1 port 53" -t unfreezeall -unfreeze enables updates of a zone again e.g. ./yadifa -s "192.0.2.1 port 53" -t unfreeze -q somedomain.eu In order to work, the allow-control ACL must be defined either in
for the global commands and may also be defined in for the ones targeting a specific zone. e.g. allow-control 127.0.0.1 Note that tsig is not supported in the client yet. 20140528: YADIFA 2.0.0-beta1-public This release is a public release - NSID implemented (enabled at ./configure time with --enable-nsid - generic parser for: - getops - zone file - resolv.conf - configuration - '@' can now be used in a zone file - new binary for controlling 'yadifad' (yadifa) - framework is rewritten for multi core systems - single core server has been removed Fixes: - fixed several minor issues Know issues: - removing all dnskeys from a zone file crashes the server - yadifa has some issues with nodelay, nocork 20130424: YADIFA 1.1.0 _ added DSA signature _ added SHA-256 SHA-384 SHA-512 digest algorithms _ now supports additional DNSSEC algorithms: DSASHA1 DSASHA1_NSEC3 RSASHA256_NSEC3 RSASHA512_NSEC3 _ Respone Rate Limitation implemented (enabled at ./configure time with --enable-rrl) _ --enable-tiny-footprint now reduces the memory usage further by reducing the standard log queue from 2^20 to 2^12 entries _ the general speed has been slightly improved _ dynamic updates pending for more than 3 seconds are now dropped with an error _ dynamic provisioning Fixes: _ fixed a memory leak that could occur at NSEC3 generation when loading the zone failed in a particular way _ fixed a memory leak at ixfr send _ fixed handling of '_' character that was improperly stored in the database _ fixed bandwidth limit settings (tcp stream in and out) not always being taken from the configuration _ fixed TSIG answer verification for notifies _ fixed error codes not being registered and thus logged as unknown hexadecimal error code. _ other minor fixes 20130612: YADIFA 1.0.3 Fixes only (backports from 1.1.0) Fixes: _ fixed an issue preventing YADIFA from being build from another directory _ fixed an issue with OSX systems where gsed has to be used instead of sed _ fixed an issue with the '_' character not being properly handled _ fixed an issue where reading MX record from a zone file would incorrecly be rejected as invalid _ fixed an issue where the OPT record would not be properly written _ fixed an issue where an undefined ACL reference would be silently ignored _ fixed missing code tags for several error codes. From now on unregistered codes are dumped in hexadicimal. _ fixed portability issues with BSD and OSX _ fixed several minor issues 20120921: YADIFA 1.0.2 Fixes only Fixes: _ fixed an issue where the journal file was sometimes not properly closed at the end of a task _ fixed an issue where the TCP usage slots would sometimes wrongly return that they were all being used _ fixed an issue on IXFR processing (secondary side) where the type of answer from the primary would not be properly detected _ fixed an issue with TSIG on secrets not exactly 16 bytes long (binary form) _ fixed an issue on 32 bits architectures where the sig-validity-* fields would not be properly handled if not set on each zone section. _ slightly improved the replay time of big journal files _ fixed several minor issues Known issues: _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120709: YADIFA 1.0.1 _ logging repeat compression is now by channel instead of global Fixes: _ fixed an issue where glibc whould assert if libgcc_s.so (libgcc_s.so.1) and libc.so (libc.so.6) where not available inside the chrooted directory of YADIFA _ fixed an issue in the syslog module Known issues: _ on 32 bits architectures, the sig-validity-* fields are not properly copied from
to as a workaround, set the sig-validity fields in each container in 32 bits architectures ie: sig-validity-interval 7 sig-validity-regeneration 168 sig-validity-jitter 3600 _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120625: YADIFA 1.0.0 _ LTO support can be enabled with --enable-lto but this is not working with clang. LTO does not increase the performance significally _ parallel processing of listening addresses can now be enabled. It can be set using thread-count-by-address in the
section. By default YADIFA will not use parallel processing as this feature has not been as thoroughly tested as the single-thread processing model _ default parameters tuning _ fixes Known issue: _ on 32 bits architectures, the sig-validity-* fields are not properly copied from
to as a workaround, set the sig-validity fields in each container in 32 bits architectures ie: sig-validity-interval 7 sig-validity-regeneration 168 sig-validity-jitter 3600 20120530: YADIFA 1.0.0RC3 _ the configuration parser now ignores undefined logger names and report them with a warning _ syslog messages are now put in the name of "yadifad" instead of the name used for the "syslog" channel _ syslog messages do not print the time from YADIFA anymore _ improved the steps involved in loading a locally cached secondary zone _ zones are now loaded in background _ man page yadifad-conf.man5 renamed into yadifad.conf.man5 Fixes: _ AXFR/IXFR answers with the RA bit set are nolonger rejected as invalid _ YADIFA now answers to SIGINT again (shutdown) _ fixed an issue where obsolete AXFR files were not always being deleted _ fixed an issue occurring when both IPv4 and IPv6 were available to handle a notify _ fixed journal replay issue where some RRSIGs records were not properly removed _ fixed an issue occurring with IPv6 queries _ fixed an issue in the generation of a specific NSEC3 error answer _ fixed named query style layout Known issue: _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120328: YADIFA 1.0.0RC2 _ fixed logging issue on work file creation error _ fixed an issue where IXFR queries could be rejected as being wrongly formatted _ fixed an issue in the query logging text _ enabled command line options ( -u uid -g gid -d ) 20120319: YADIFA 1.0.0RC1 Is a full functional authoritative name server: - works as primary or secondary name server - AXFR - IXFR - NOTIFY - NSUPDATE - TSIG - CLASSES: - IN - CH (just for version) - TYPES: - AAAA - CNAME - DNSKEY - DS - HINFO - MX - NAPTR - NS - NSEC3 - NSEC3PARAM - NSEC - PTR - RRSIG - SOA - SRV - SSHFP - TXT - Automatic resigning - DNSSEC algorithms: - 5 (RSASHA1) - 7 (RSASHA1-NSEC3 - ACL's KNOWN ISSUES: NSEC3: _ cannot work with multiple NSEC3PARAM chains with mixed OPT-IN/OUT settings _ adding a new NSEC3 chain expects that the primary sends the NSEC3PARAM first (it does not seems to be always the case) We have a case where a primary starts with 2 thousands NSEC3 opt-out records then adds 6 millions NSEC3 opt-in records but does not give the NSEC3PARAM record first. The secondary server rejects them all because it's unable to link them to a chain. (This one has high priority) DNSSEC: _ it is not allowed to change the zone security mode (unsecure, NSEC, or NSEC3). Once the zone is loaded it keeps its security mode. _ dynamic updates of NSEC as well as NSEC3 records are refused QUIT: the server will shutdown on the following conditions: _ detection of an impossible situation or an internal integrity issue (ie: for any reason the SOA has vanished from a zone) _ memory limit reached which prevents any more work _ ipc issue which prevent internal services communication ACL: _ since the access control is set by zone and CHAOS class is not implemented as a configurable zone, it is not possible (yet) to specifically block CHAOS queries. 20111121: YADIFA 0.5.5 - many fixes KNOWN ISSUE: NSEC3 secondary zone replay fails. 20110706: YADIFA 0.5.0 - secondary mode, AXFR/IXFR (no TSIG yet for the secondary-side transfer) - answers to a notify from the primary - polls the (first) primary on the primaries list - maintains the .axfr & .ix files (deletes the obsoletes ones) - TSIG queries are checked - Replays the zone journal on startup after the zone load (journaling) - Answers IXFR queries (journaling) 20110601: YADIFA 0.4.0 Operational: - It works as a no dnssec name server - No notifies to secondary name servers - daemon - Answers AXFR queries with TSIG - nsupdate functionality (journaling) - TSIG on client server side will be transmitted, but not checked - ACL works - The zone has SOA, NS A resource records. 20110524: YADIFA 0.3.0 First release internally of yadifad 20110524115500 GMT+1. Operational: - It works as a no dnssec name server - No notifies to secondary name servers - daemon - Answers AXFR queries - The zone has SOA, NS A resource records. 20091224: YADIFA 0.2.0 _ Answers AXFR queries _ ACL based on IP and TSIG (not all query types are ACL'ed yet) 20091104: YADIFA 0.1.0 YADIFA is a work in progress. The main goal is to have an alternative for BIND or NSD. Version 0.1.0 is an authoritative server only. It has no: - AXFR/IXFR functionality - dynupdate - support for NSEC - support for NSEC3 - caching mechanism - additional tools (eg.dig, dnssectools, drill,...) It has: - a very fast way to give authoritative answer - a very fast method for loading the database and checking the zone files This first release is to have a feeling how it works in an operational environment. TODO Everything what is not implemented, has to be implemented. Most of the code is there, but is not activated. No comformity tests has been done. (This of course is on the todo list) Bug Reports and Mailing Lists Bugs reports should be sent to bugreport@yadifa.eu yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/INSTALL0000644000000000000000000000013214505005531017243 xustar000000000000000030 mtime=1695812441.361966706 30 atime=1695812445.803030311 30 ctime=1695812495.944748441 yadifa-2.6.5-11201/lib/dnslg/INSTALL0000664000374500037450000004173114505005531017213 0ustar00signersigner00000000000000Quick installation ****************** You will need the most up-to-date aclocal, autoheader, automake, autoconf, make and a C compiler installed (clang, icc or gcc >= 4.6) By default gcc is used but you can specify your compiler adding CC=x in ./configure. ie: ./configure CC=clang openssl has to be build with shared Note that gcc < 4.6 will be build with -O0 and > 4.6 with -O3 ./configure make sudo make install cd /usr/local sudo mkdir -p var/run var/log var/zones/keys var/zones/masters var/zones/slaves var/zones/xfr Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" With "Homebrew" installed for openssl support: ./configure -with-openssl=/usr/local/opt/openssl@1.1 CFLAGS="-O2 -g -DDEBUG=0 -DNDEBUG=1" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `--with-openssl=DIR' Use the openssl from directory DIR (where DIR is the PREFIX of openssl) `--enable-tiny-footprint' This will change the behaviour of the memory allocation of the database. It will take the smallest increase in memory required to fulfill an allocation instead of getting a bunch at once. Disabled by default. `--enable-messages' Will use recvmsg/sendmsg instead of recvfrom/sendto. This is only useful if * any interface the server listens from has aliased IPs. (ie: eth0 & eth0:1) AND * the server is configured to listen to 0.0.0.0 (it's its default) Having aliased addresses on interfaces can also be handled without using messages but enumerating the listen addresses in yadifad.conf instead. ie: listen 192.0.2.1, 192.0.2.2 `--enable-lto' Will use the Link Time Optimisations of gcc (or ipo for ICC) The gain of speed is very marginal so it is not recommended `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/NEWS0000644000000000000000000000013114505005531016710 xustar000000000000000030 mtime=1695812441.376966921 30 atime=1695812445.803030311 29 ctime=1695812495.94674847 yadifa-2.6.5-11201/lib/dnslg/NEWS0000664000374500037450000000001414505005531016646 0ustar00signersigner00000000000000See README yadifa-2.6.5-11201/lib/dnslg/PaxHeaders.1636/README0000644000000000000000000000013214505005531017072 xustar000000000000000030 mtime=1695812441.377966935 30 atime=1695812445.803030311 30 ctime=1695812495.948748498 yadifa-2.6.5-11201/lib/dnslg/README0000664000374500037450000000377514505005531017050 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ 20230906: YADIFA 2.6.5-public Secondaries will nolonger enforce the TTL value of the NSEC3PARAM record. Fixes an issue caused by a limitation of the select system call. yadifa-2.6.5-11201/PaxHeaders.1636/mk0000644000000000000000000000013214505005616014673 xustar000000000000000030 mtime=1695812494.117722274 30 atime=1695812499.082793384 30 ctime=1695812494.117722274 yadifa-2.6.5-11201/mk/0000775000374500037450000000000014505005616014712 5ustar00signersigner00000000000000yadifa-2.6.5-11201/mk/PaxHeaders.1636/common-settings.mk0000644000000000000000000000013214505005533020425 xustar000000000000000030 mtime=1695812443.579998473 30 atime=1695812454.439153998 30 ctime=1695812494.115722246 yadifa-2.6.5-11201/mk/common-settings.mk0000664000374500037450000001440214505005533020370 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ # # ALL # AM_CFLAGS = -D_THREAD_SAFE -D_REENTRANT -D_FILE_OFFSET_BITS=64 -I$(abs_builddir) -I$(abs_builddir)/include -I$(abs_srcdir)/include AM_LDFLAGS = DEBUGFLAGS = LOCALFLAGS = -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)"' -DLOCALSTATEDIR='"$(localstatedir)"' -DDATAROOTDIR='"$(datarootdir)"' -DDATADIR='"$(datadir)"' -DLOCALEDIR='"$(localedir)"' -DLOGDIR='"$(logdir)"' -DTCLDIR='"$(tcldir)"' if USES_SUNC DEBUGFLAGS += else DEBUGFLAGS += -O0 endif if IS_DARWIN_OS AM_CFLAGS += -Wno-deprecated endif if HAS_CC_NO_IDENT AM_CFLAGS += -fno-ident endif if HAS_CC_ANSI AM_CFLAGS += -ansi endif if HAS_CC_PEDANTIC AM_CFLAGS += -pedantic endif if HAS_CC_WALL AM_CFLAGS += -Wall -Wno-unknown-pragmas endif if HAS_CC_MISSING_FIELD_INITIALIZERS AM_CFLAGS += -Werror=missing-field-initializers endif if HAS_CC_STD_GNU11 AM_CFLAGS += -std=gnu11 else if HAS_CC_STD_C11 AM_CFLAGS += -std=c11 -D_GNU_SOURCE else if HAS_CC_STD_GNU99 AM_CFLAGS += -std=gnu99 else if HAS_CC_STD_C99 AM_CFLAGS += -std=c99 else if HAS_CC_XC99 AM_CFLAGS += -xc99 endif # XC99 endif # C99 endif # GNU99 endif # C11 endif # GNU11 if HAS_CC_TUNE_NATIVE AM_CFLAGS += -mtune=native endif if FORCE64BITS if HAS_CC_M64 AM_CFLAGS += -m64 AM_LDFLAGS += -m64 endif else if FORCE32BITS if HAS_CC_M32 AM_CFLAGS += -m32 AM_LDFLAGS += -m32 endif endif endif # # DEBUG # if HAS_CC_G3 DEBUGFLAGS += -g3 else if HAS_CC_G DEBUGFLAGS += -g endif endif if HAS_CC_DWARF4 DEBUGFLAGS += -gdwarf-4 else if HAS_CC_DWARF3 DEBUGFLAGS += -gdwarf-3 endif endif # # Intel C Compiler # ############################################################################### if USES_ICC #ICC #IPO= -ipo (need to use the intel xiar instead of ar) if HAS_LTO_SUPPORT AM_CFLAGS += -DLTO -ipo AM_LDFLAGS += -ipo AM_AR = xiar endif AM_LD = ld AM_CFLAGS += -DUSES_ICC if HAS_CC_ANSI_ALIAS AM_CFLAGS += -ansi-alias -U__STRICT_ANSI__ endif DEBUGFLAGS += -DMODE_DEBUG_ICC endif # # LLVM Clang # ############################################################################### if USES_CLANG # CLANG if HAS_LTO_SUPPORT AM_CFLAGS += -DLTO -flto AM_LDFLAGS += -flto AM_AR = llvm-ar AM_LD = ld.gold else AM_AR = ar AM_LD = ld endif AM_CFLAGS += -DUSES_LLVM -Wno-gnu #-Wno-extended-offsetof DEBUGFLAGS += -DMODE_DEBUG_CLANG -fsanitize=address -fsanitize=bounds if IS_LINUX_FAMILY AM_LDFLAGS += -Wl,-z,stack-size=8388608 endif # Note: add a _d suffix for debug builds ? endif # CLANG # # Gnu C # ############################################################################### if USES_GCC #GCC if HAS_CPU_NIAGARA AM_CFLAGS += -mcpu=niagara endif if HAS_LTO_SUPPORT AM_CFLAGS += -DLTO -flto -fwhole-program -fno-fat-lto-objects -fuse-linker-plugin AM_LDFLAGS += -flto -fwhole-program -fno-fat-lto-objects -fuse-linker-plugin AM_LDFLAGS += -Wl,-Map=module.map -Wl,--cref AM_AR = gcc-ar AM_RANLIB = gcc-ranlib else AM_AR = ar AM_LD = ld endif AM_CFLAGS += -DUSES_GCC DEBUGFLAGS += -DMODE_DEBUG_GCC -fstack-check -fstack-protector-strong if HAS_BFD_DEBUG_SUPPORT AM_CFLAGS += -rdynamic endif if IS_LINUX_FAMILY AM_LDFLAGS += -Wl,-z,stack-size=8388608 endif endif # USES_GCC # # Sun C # ############################################################################### if USES_SUNC # SUNC AM_AR = ar AM_LD = ld AM_CFLAGS += -DUSES_SUNC DEBUGFLAGS += -DMODE_DEBUG_SUNC # Note: add a _d suffix for debug builds ? endif # SUNC # # Unknown compiler # ############################################################################### if USES_UNKNOWN # if an unknown compiler is used, it should have its own section AM_CFLAGS += -DUSES_UNKNOWN_COMPILER DEBUGFLAGS += -DMODE_DEBUG_UNKNOWN endif # # Some BSD-based OSes need this # if IS_BSD_FAMILY AM_CFLAGS += -I./include endif if IS_SOLARIS_FAMILY AM_CFLAGS += -D_POSIX_PTHREAD_SEMANTICS endif # # # AM_CFLAGS += $(LOCALFLAGS) ### YRCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -g -DCMR ### YPCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -pg -DCMP ### YDCFLAGS = -DDEBUG $(DEBUGFLAGS) -DCMD ### YSCFLAGS = $(YRCFLAGS) ### ### YRLDFLAGS = -g ### YPLDFLAGS = -pg ### YDLDFLAGS = -g ### ### if HAS_CC_RDYNAMIC ### YPLDFLAGS += -rdynamic ### YDLDFLAGS += -rdynamic ### endif ### ### if USES_CLANG ### # workaround a bug where clang does not handle properly profiling and optimizations ### YPCFLAGS += -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer ### endif ### ### YSLDFLAGS = $(YRLDFLAGS) ### ### AM_CFLAGS += $(YCFLAGS) ### AM_LDFLAGS += $(YLDFLAGS) ### ### AM_MAKEFLAGS=MODE_CFLAGS="$(AM_CFLAGS)" CC=$(CC) AR=$(AM_AR) LD=$(AM_LD) yadifa-2.6.5-11201/mk/PaxHeaders.1636/common-labels.mk0000644000000000000000000000013114505005533020026 xustar000000000000000030 mtime=1695812443.579998473 29 atime=1695812454.47215447 30 ctime=1695812494.117722274 yadifa-2.6.5-11201/mk/common-labels.mk0000664000374500037450000000422114505005533017770 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ buildinfo.h: $(abs_top_builddir)/config.log echo \#pragma once > buildinfo.h 2> /dev/null echo // generated file, do not modify >> buildinfo.h 2> /dev/null echo \#define BUILD_OPTIONS \"$$(grep "/configure" $(abs_top_builddir)/config.log | head -1 | sed 's/.*\.\/configure *//')\" >> buildinfo.h 2> /dev/null CLEANFILES = buildinfo.h yadifa-2.6.5-11201/PaxHeaders.1636/depcomp0000644000000000000000000000007312345535677015736 xustar000000000000000030 atime=1695812108.264196076 29 ctime=1695812494.12372236 yadifa-2.6.5-11201/depcomp0000755000374500037450000005601612345535677015705 0ustar00signersigner00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: yadifa-2.6.5-11201/PaxHeaders.1636/etc0000644000000000000000000000013214505005617015040 xustar000000000000000030 mtime=1695812495.283738974 30 atime=1695812499.082793384 30 ctime=1695812495.283738974 yadifa-2.6.5-11201/etc/0000775000374500037450000000000014505005617015057 5ustar00signersigner00000000000000yadifa-2.6.5-11201/etc/PaxHeaders.1636/Makefile.in0000644000000000000000000000013114505005546017162 xustar000000000000000029 mtime=1695812454.76815871 30 atime=1695812461.842260025 30 ctime=1695812495.249738487 yadifa-2.6.5-11201/etc/Makefile.in0000664000374500037450000005524214505005546017135 0ustar00signersigner00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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@ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ subdir = etc DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(noinst_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/eurid.m4 $(top_srcdir)/m4/yadifa.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = 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 = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac 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__installdirs = "$(DESTDIR)$(docdir)" DATA = $(doc_DATA) HEADERS = $(noinst_HEADERS) 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)` ETAGS = etags CTAGS = ctags 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@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCOPTIMISATIONFLAGS = @CCOPTIMISATIONFLAGS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DNSCORE = @DNSCORE@ DNSDB = @DNSDB@ DNSLG = @DNSLG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAS_ACL_SUPPORT = @HAS_ACL_SUPPORT@ HAS_BFD_DEBUG_SUPPORT = @HAS_BFD_DEBUG_SUPPORT@ HAS_BIG_ENDIAN = @HAS_BIG_ENDIAN@ HAS_BUILD_TIMESTAMP = @HAS_BUILD_TIMESTAMP@ HAS_CC_ADDRESS_SANITIZER_CHECK = @HAS_CC_ADDRESS_SANITIZER_CHECK@ HAS_CC_ANSI = @HAS_CC_ANSI@ HAS_CC_ANSI_ALIAS = @HAS_CC_ANSI_ALIAS@ HAS_CC_CATCH_UNDEFINED_BEHAVIOR = @HAS_CC_CATCH_UNDEFINED_BEHAVIOR@ HAS_CC_DWARF2 = @HAS_CC_DWARF2@ HAS_CC_DWARF3 = @HAS_CC_DWARF3@ HAS_CC_DWARF4 = @HAS_CC_DWARF4@ HAS_CC_EXCEPTIONS = @HAS_CC_EXCEPTIONS@ HAS_CC_G = @HAS_CC_G@ HAS_CC_G3 = @HAS_CC_G3@ HAS_CC_M32 = @HAS_CC_M32@ HAS_CC_M64 = @HAS_CC_M64@ HAS_CC_MISSING_FIELD_INITIALIZERS = @HAS_CC_MISSING_FIELD_INITIALIZERS@ HAS_CC_NO_IDENT = @HAS_CC_NO_IDENT@ HAS_CC_NO_OMIT_FRAME_POINTER = @HAS_CC_NO_OMIT_FRAME_POINTER@ HAS_CC_PEDANTIC = @HAS_CC_PEDANTIC@ HAS_CC_RDYNAMIC = @HAS_CC_RDYNAMIC@ HAS_CC_SANITIZE_ADDRESS = @HAS_CC_SANITIZE_ADDRESS@ HAS_CC_STACK_PROTECTOR = @HAS_CC_STACK_PROTECTOR@ HAS_CC_STD_C11 = @HAS_CC_STD_C11@ HAS_CC_STD_C99 = @HAS_CC_STD_C99@ HAS_CC_STD_GNU11 = @HAS_CC_STD_GNU11@ HAS_CC_STD_GNU99 = @HAS_CC_STD_GNU99@ HAS_CC_TUNE_NATIVE = @HAS_CC_TUNE_NATIVE@ HAS_CC_WALL = @HAS_CC_WALL@ HAS_CC_XC99 = @HAS_CC_XC99@ HAS_CLOSE_EX_REF = @HAS_CLOSE_EX_REF@ HAS_CTRL = @HAS_CTRL@ HAS_DNSSEC_TOOLS = @HAS_DNSSEC_TOOLS@ HAS_DYNUPDATE_SUPPORT = @HAS_DYNUPDATE_SUPPORT@ HAS_ECDSA_SUPPORT = @HAS_ECDSA_SUPPORT@ HAS_EDDSA = @HAS_EDDSA@ HAS_EVENT_DYNAMIC_MODULE = @HAS_EVENT_DYNAMIC_MODULE@ HAS_FULL_ASCII7 = @HAS_FULL_ASCII7@ HAS_KEYGEN = @HAS_KEYGEN@ HAS_LIBC_MALLOC_DEBUG_SUPPORT = @HAS_LIBC_MALLOC_DEBUG_SUPPORT@ HAS_LITTLE_ENDIAN = @HAS_LITTLE_ENDIAN@ HAS_LOCK_DEBUG_SUPPORT = @HAS_LOCK_DEBUG_SUPPORT@ HAS_LOGDIR = @HAS_LOGDIR@ HAS_LOG_PID = @HAS_LOG_PID@ HAS_LOG_THREAD_ID = @HAS_LOG_THREAD_ID@ HAS_LOG_THREAD_TAG = @HAS_LOG_THREAD_TAG@ HAS_MALLOC_DEBUG_SUPPORT = @HAS_MALLOC_DEBUG_SUPPORT@ HAS_MASTER_SUPPORT = @HAS_MASTER_SUPPORT@ HAS_MEMALIGN_ISSUES = @HAS_MEMALIGN_ISSUES@ HAS_MUTEX_DEBUG_SUPPORT = @HAS_MUTEX_DEBUG_SUPPORT@ HAS_NON_AA_AXFR_SUPPORT = @HAS_NON_AA_AXFR_SUPPORT@ HAS_NSEC3_SUPPORT = @HAS_NSEC3_SUPPORT@ HAS_NSEC_SUPPORT = @HAS_NSEC_SUPPORT@ HAS_NSID_SUPPORT = @HAS_NSID_SUPPORT@ HAS_RRL_SUPPORT = @HAS_RRL_SUPPORT@ HAS_RRSIG_MANAGEMENT_SUPPORT = @HAS_RRSIG_MANAGEMENT_SUPPORT@ HAS_SYNC_BUILTINS = @HAS_SYNC_BUILTINS@ HAS_SYSTEMD_RESOLVED_AVOIDANCE = @HAS_SYSTEMD_RESOLVED_AVOIDANCE@ HAS_TESTS = @HAS_TESTS@ HAS_TOOLS = @HAS_TOOLS@ HAS_TRACK_ZONES_DEBUG_SUPPORT = @HAS_TRACK_ZONES_DEBUG_SUPPORT@ HAS_TSIG_SUPPORT = @HAS_TSIG_SUPPORT@ HAS_YADIFA = @HAS_YADIFA@ HAS_ZALLOC_DEBUG_SUPPORT = @HAS_ZALLOC_DEBUG_SUPPORT@ HAS_ZALLOC_STATISTICS_SUPPORT = @HAS_ZALLOC_STATISTICS_SUPPORT@ HAS_ZALLOC_SUPPORT = @HAS_ZALLOC_SUPPORT@ HAVE_RECVMMSG = @HAVE_RECVMMSG@ HAVE_SENDMMSG = @HAVE_SENDMMSG@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IS_BSD_FAMILY = @IS_BSD_FAMILY@ IS_DARWIN_GE14 = @IS_DARWIN_GE14@ IS_DARWIN_OS = @IS_DARWIN_OS@ IS_LINUX_FAMILY = @IS_LINUX_FAMILY@ IS_SOLARIS_FAMILY = @IS_SOLARIS_FAMILY@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL = @OPENSSL@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZDB_HAS_DNSSEC_SUPPORT = @ZDB_HAS_DNSSEC_SUPPORT@ 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_CXX = @ac_ct_CXX@ 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@ 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@ logdir = @logdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 OC = yadifad.conf OCE = $(srcdir)/$(OC).example MC = yadifa.conf MCE = $(srcdir)/$(MC).example KC = keys.conf KCE = $(srcdir)/$(KC).example YI = yadifad.init YIE = $(srcdir)/$(YI).example YS = yadifad.service YSE = $(srcdir)/$(YS).example YC = yadifa YCE = $(srcdir)/$(YC).bash_completion YD = yadifad YDE = $(srcdir)/$(YD).bash_completion YKR = yakeyrolld.conf YKRE = $(srcdir)/$(YKR).example BC = /etc/bash_completion.d/ doc_DATA = $(OC) $(MC) $(KC) $(YI) $(YS) $(YKR) $(YDE) $(YCE) $(YKRE) \ yadifad-primary.conf.example yadifad-secondary.conf.example \ yadifad.init.debian yadifad.init.rhel \ yadifad.logrotate \ yadifad.service.arch yadifad.service.debian yadifad.service.rhel noinst_HEADERS = $(OCE) $(MCE) $(KCE) $(YIE) $(YSE) $(YDE) $(YCE) \ yadifad-primary.conf.example yadifad-secondary.conf.example \ yadifad.init.debian yadifad.init.rhel \ yadifad.logrotate \ yadifad.service.arch yadifad.service.debian yadifad.service.rhel \ yakeyrolld.conf.example all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(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) --gnu etc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu etc/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-docDATA: @$(NORMAL_UNINSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) 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: $(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 $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(docdir)"; 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-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-docDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook 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 Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-docDATA .MAKE: install-am install-data-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags ctags-am \ distclean distclean-generic distclean-libtool distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-data-hook \ install-docDATA 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-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-docDATA $(OC): $(OCE) cat $(OCE) | sed "s@\"\(\|.*>\)\(.*\)/var/\(.*\)\"@\"\1$(localstatedir)/\3\"@" > $(OC) $(MC): $(MCE) cp $(MCE) $(MC) $(KC): $(KCE) cat $(KCE) | sed "s@PleaseChangeThisKey=@`head -c 16 /dev/urandom | openssl enc -base64 2>/dev/null`@" > $(KC) $(YI): $(YIE) cat $(YIE) | sed "s@^PREFIX=.*@PREFIX=\"$(prefix)\"@" > $(YI) $(YS): $(YSE) cat $(YSE) | sed -e "s@/usr/sbin@$(sbindir)@g" -e "s@/etc/yadifa@$(sysconfdir)@g" -e "s@/var@$(localstatedir)@g" > $(YS) $(YC): $(YCE) cp $(YCE) $(YC) $(YD): $(YDE) cp $(YDE) $(YD) $(YKR): $(YKRE) cat $(YKRE) | sed "s@\"\(\|.*>\)\(.*\)/var/\(.*\)\"@\"\1$(localstatedir)/\3\"@" > $(YKR) all: $(YI) $(OC) $(MC) $(KC) $(YC) $(YD) install-data-hook: $(OC) $(YKR) mkdir -p $(DESTDIR)$(sysconfdir) touch $(DESTDIR)$(sysconfdir)/$(OC) touch $(DESTDIR)$(sysconfdir)/$(YKR) if [ -d "$(DESTDIR)$(BC)" -a -w "$(DESTDIR)$(BC)" ] ; then cp $(YC) $(YD) $(DESTDIR)$(BC) ; fi clean-local: rm -f $(YI) $(OC) $(MC) $(KC) $(YS) $(YC) $(YD) $(YKR) features: # 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: yadifa-2.6.5-11201/etc/PaxHeaders.1636/Makefile.am0000644000000000000000000000013214505005533017146 xustar000000000000000030 mtime=1695812443.637999303 30 atime=1695812445.806030354 30 ctime=1695812495.251738516 yadifa-2.6.5-11201/etc/Makefile.am0000664000374500037450000000742014505005533017113 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ACLOCAL_AMFLAGS = -I m4 OC=yadifad.conf OCE=$(srcdir)/$(OC).example MC=yadifa.conf MCE=$(srcdir)/$(MC).example KC=keys.conf KCE=$(srcdir)/$(KC).example YI=yadifad.init YIE=$(srcdir)/$(YI).example YS=yadifad.service YSE=$(srcdir)/$(YS).example YC=yadifa YCE=$(srcdir)/$(YC).bash_completion YD=yadifad YDE=$(srcdir)/$(YD).bash_completion YKR=yakeyrolld.conf YKRE=$(srcdir)/$(YKR).example BC=/etc/bash_completion.d/ doc_DATA = $(OC) $(MC) $(KC) $(YI) $(YS) $(YKR) $(YDE) $(YCE) $(YKRE) \ yadifad-primary.conf.example yadifad-secondary.conf.example \ yadifad.init.debian yadifad.init.rhel \ yadifad.logrotate \ yadifad.service.arch yadifad.service.debian yadifad.service.rhel noinst_HEADERS = $(OCE) $(MCE) $(KCE) $(YIE) $(YSE) $(YDE) $(YCE) \ yadifad-primary.conf.example yadifad-secondary.conf.example \ yadifad.init.debian yadifad.init.rhel \ yadifad.logrotate \ yadifad.service.arch yadifad.service.debian yadifad.service.rhel \ yakeyrolld.conf.example $(OC): $(OCE) cat $(OCE) | sed "s@\"\(\|.*>\)\(.*\)/var/\(.*\)\"@\"\1$(localstatedir)/\3\"@" > $(OC) $(MC): $(MCE) cp $(MCE) $(MC) $(KC): $(KCE) cat $(KCE) | sed "s@PleaseChangeThisKey=@`head -c 16 /dev/urandom | openssl enc -base64 2>/dev/null`@" > $(KC) $(YI): $(YIE) cat $(YIE) | sed "s@^PREFIX=.*@PREFIX=\"$(prefix)\"@" > $(YI) $(YS): $(YSE) cat $(YSE) | sed -e "s@/usr/sbin@$(sbindir)@g" -e "s@/etc/yadifa@$(sysconfdir)@g" -e "s@/var@$(localstatedir)@g" > $(YS) $(YC): $(YCE) cp $(YCE) $(YC) $(YD): $(YDE) cp $(YDE) $(YD) $(YKR): $(YKRE) cat $(YKRE) | sed "s@\"\(\|.*>\)\(.*\)/var/\(.*\)\"@\"\1$(localstatedir)/\3\"@" > $(YKR) all: $(YI) $(OC) $(MC) $(KC) $(YC) $(YD) install-data-hook: $(OC) $(YKR) mkdir -p $(DESTDIR)$(sysconfdir) touch $(DESTDIR)$(sysconfdir)/$(OC) touch $(DESTDIR)$(sysconfdir)/$(YKR) if [ -d "$(DESTDIR)$(BC)" -a -w "$(DESTDIR)$(BC)" ] ; then cp $(YC) $(YD) $(DESTDIR)$(BC) ; fi clean-local: rm -f $(YI) $(OC) $(MC) $(KC) $(YS) $(YC) $(YD) $(YKR) features: yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad.conf.example0000644000000000000000000000013214505005533021014 xustar000000000000000030 mtime=1695812443.619999045 30 atime=1695812445.807030368 30 ctime=1695812495.253738544 yadifa-2.6.5-11201/etc/yadifad.conf.example0000664000374500037450000003642414505005533020767 0ustar00signersigner00000000000000# # Example yadifa configuration file. #
# Detach from the console daemon off # Jail the application chroot off # The path where all the log files will be written logpath "/var/log/yadifa" # The location of the pid file pidfile "/var/run/yadifad.pid" # The path where all zone files will be written datapath "/var/zones" # The path where the DNSSEC keys are found keyspath "/var/zones/keys" # The path where the transfer and journaling files will be written (AXFR & IXFR) xfrpath "/var/zones/xfr" # A string returned by a query of hostname. CH TXT (note if you leave this out, the real hostname will be given back) hostname "server-yadifad" # An ID returned by a query to id.server. CH TXT serverid "yadifad-01" # The version returned by a query to version.yadifa. CH TXT version "2.6.5" # Set the maximum UDP packet size. Cannot be less than 512. Cannot be more than 65535. Typical choice is 4096. edns0-max-size 4096 # The maximum number of parallel TCP queries. max-tcp-queries 100 # The user id to use (an integer can be used) user root # The group id to use (an integer can be used) group root # The DNS port. Any DNS query will be made using that port unless a specific value is used. port 53 # The interfaces to listen to. listen 0.0.0.0 # Specifies what address to bind to to do transfer requests # Can be specified per-zone # transfer-source 192.0.2.53 # Enable the collection and logging of statistics statistics on # Choose the query log format (0 for none, 1 for YADIFA, 2 for BIND compatible, 3 for YADIFA and BIND) queries-log-type 1 # Drop queries with erroneous content # answer-formerr-packets on # Maximum number of records in an AXFR packet. Set to one for compatibility # with very old name servers # axfr-maxrecordbypacket 0 # Zones smaller than this will be sent witout using temporary storage in the 'xfrpath' directory # axfr-memory-threshold 65536 # Global Access Control List rules. # # Rules can be defined on network ranges, TSIG signatures, and ACL rules # simple queries: allow-query any # dynamic update of a zone allow-update none # transfer of a zone (AXFR or IXFR) allow-transfer none # notify of a change in the primary allow-notify none # If YADIFA has the controller enabled, allow control only for these clients (none by default) allow-control controller
# If YADIFA has NSID support (default) ascii "yadifad example NSID" # alternatively, an hexadecimal format can be used # hex 79616469666164206578616d706c65204e5349440a # If YADIFA has the controller enabled (needs to have been configured at build using --enable-ctrl) # enable the controller enabled true # If YADIFA has been compiled with the Response Rate Limiter (default) # enable the RRL enabled true # don't actually limit the response rate, only log what the filter would do log_only false # how many responses per second are allowed for a (masked with the prefix) client responses_per_second 5 # how many errors per second are allowed for a (masked with the prefix) client errors_per_second 5 # window of time in which the rates are measured, expressed in seconds window 15 # every "slip" dropped answers, a truncated answer may randomly be given so the client can ask again using TCP slip 2 # the minimum size of the table storing (masked with the prefix) clients min_table_size 1024 # the maximum size of the table storing (masked with the prefix) clients max_table_size 16384 # IPv4 clients are masked with this prefix ipv4_prefix_length 24 # IPv6 clients are masked with this prefix ipv6_prefix_length 56 # the list of IP/networks (Access Control List) not impacted by the RRL exempted none # # Logging output channels configurations # # name stream-name arguments # # name is arbitrary # stream-name defines the output type (ie: a file name or syslog) # arguments is specific to the output type (ie: unix file access rights or syslog options and facilities # name stream-name arguments database database.log 0644 dnssec dnssec.log 0644 server server.log 0644 statistics statistics.log 0644 system system.log 0644 zone zone.log 0644 queries queries.log 0644 all all.log 0644 syslog syslog USER,CRON,PID # It is to be noted that the command will be run even if no logger is bound to it. # gzip-log "|/usr/bin/gzip - >> /var/log/yadifa/yadifa.log.gz" # although possible, these two will end up writing to /dev/null if daemon is enabled stderr STDERR stdout STDOUT # Logging input configurations # # name debug-level channels # # name is predefined # debuglevel uses the same names as syslog or * or all to filter the input # channels is a comma-separated list of channels # In production, use EMERG,ALERT,CRIT,ERR,WARNING,NOTICE,INFO instead of * # bundle debuglevel channels database prod database,all dnssec prod dnssec,all server prod server,all stats prod statistics system prod system,all zone prod zone,all queries prod queries # # TSIG Key configuration # include "keys.conf" name primary-secondary algorithm hmac-md5 secret PrimaryAndSecondaryKey== # # Access Control List definitions # # Meant to be used in access lists parameters (allow-*) # arbitrary-name comma-separated-list # transferer key primary-secondary admins 192.0.2.0/24, 2001:db8::74 primary 192.0.2.53 controller key abroad-admin-key # # Primary domain zone config # type primary domain localhost file masters/localhost.zone allow-transfer none allow-update none allow-update-forwarding none type primary domain localhost6 file masters/localhost6.zone allow-transfer none allow-update none allow-update-forwarding none type primary domain 0.0.127.in-addr.arpa file masters/0.0.127.in-addr.arpa.zone allow-transfer none allow-update none allow-update-forwarding none type primary domain 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa file masters/0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone allow-transfer none allow-update none allow-update-forwarding none # This server is primary for that zone (mandatory) type primary # The domain name (mandatory) domain somedomain.eu. # The zone file, relative to 'datapath'. (mandatory for a primary) file masters/somedomain.eu.zone # Specifies what address to bind to to do transfer requests for this zone # transfer-source 192.0.2.53 dnssec-policy "typical-policy" # This server is primary for that zone (mandatory) type primary # The domain name (mandatory) domain somedomain.eu. # The zone file, relative to 'datapath'. (mandatory for a primary) file masters/somedomain.eu.zone # The DNSSEC policy to apply for automatic key management by YADIFA dnssec-policy "typical-policy" # This server is primary for that zone (mandatory) type secondary # The domain name (mandatory) domain someotherdomain.eu. # The zone file, relative to 'datapath'. (mandatory for a primary) file slaves/someotherdomain.eu.zone primary 192.0.2.54 # With this set, the zone will be loaded from its local source before # looking for updates on the primary load-local-first yes ################################################################################ ################################################################################ ### ### POLICIES ### ################################################################################ ################################################################################ # name of the 'dnssec-policy' id "typical-policy" description "Example of a policy with ZSK and KSK" # denial nsec|"nsec3-parameters-section-name" # can be the keyword 'nsec' or the 'id | name' of a 'denial' section denial "nsec3-fixed" # at least one: key-descriptor "name" # they define KSK & ZSK keys key-suite "zsk-1024" key-suite "ksk-2048" # name of the key-suite id "zsk-1024" key-template "zsk-rsa-sha256-1024" # optional, without it, the keys found in the storage are used key-roll "monthly-diary" # name of the key-suite id "ksk-2048" key-template "ksk-rsa-sha256-2048" # optional, without it, the keys found in the storage are used key-roll "yearly-diary" ###################################################### id "zsk-rsa-sha512-1024" algorithm RSASHA512 size 1024 id "zsk-rsa-sha512-2048" algorithm RSASHA512 size 2048 id "zsk-rsa-sha256-1024" algorithm RSASHA256 size 1024 id "zsk-rsa-sha256-2048" algorithm RSASHA256 size 2048 id "ksk-rsa-sha512-1024" ksk 1 algorithm RSASHA512 size 1024 id "ksk-rsa-sha512-2048" ksk 1 algorithm RSASHA512 size 2048 id "ksk-rsa-sha256-1024" ksk 1 algorithm RSASHA256 size 1024 id "ksk-rsa-sha256-2048" ksk 1 algorithm RSASHA256 size 2048 ###################################################### type NSEC3 id "nsec3-random" salt-length 32 iterations 10 # can be 0 or 1, true or false, and on or off optout off type NSEC3 id "nsec3-fixed" salt "BA5EBA11" # if nsec3-resalting is off iterations 5 # the number of additional times the hash function has been performe # can be 0 or 1, true or false, and on or off optout off ###################################################### # The order of fields goes: # # minutes hours days months weekdays weeks id "yearly-diary" generate 5 0 15 6 * * # this year (2018) 15/06 at 00:05 publish 10 0 15 * * * # 00:10 activate 15 0 16 * * * # 16/06 at 00:15 inactive 15 0 17 * * * # (2019) 17/06 at 00:15 remove 15 11 18 * * * # (2019) 18/06 at 11:15 id "monthly-diary" generate 5 0 * * tue 0 # 1 tuesday of the month at 00:05 publish 10 0 * * tue 0 # 00:10 activate 15 0 * * wed 0 # 1 wednesday of the month at 00:15 inactive 15 0 * * thu 0 # 1 thursday of the month at 00:15 remove 15 11 * * fri 0 # 1 friday of the month at 11:15 id "weekly-diary" generate 25 0 * * sun * # every sunday of the month at 00:25 publish 30 0 * * * * # at 00:30 activate 35 0 * * * * # at 00:35 inactive 35 0 * * * * # at 00:35 remove 35 11 * * * * # at 11:35 yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifa.conf.example0000644000000000000000000000013214505005533020650 xustar000000000000000030 mtime=1695812443.638999318 30 atime=1695812445.806030354 30 ctime=1695812495.255738573 yadifa-2.6.5-11201/etc/yadifa.conf.example0000664000374500037450000000015214505005533020610 0ustar00signersigner00000000000000 server 127.0.0.1 tsig-key-name "abroad-admin-key" include "keys.conf" yadifa-2.6.5-11201/etc/PaxHeaders.1636/keys.conf.example0000644000000000000000000000013214505005533020366 xustar000000000000000030 mtime=1695812443.625999131 30 atime=1695812445.806030354 30 ctime=1695812495.257738602 yadifa-2.6.5-11201/etc/keys.conf.example0000664000374500037450000000017014505005533020326 0ustar00signersigner00000000000000 name abroad-admin-key algorithm hmac-md5 secret PleaseChangeThisKey= yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad.init.example0000644000000000000000000000013114505005533021031 xustar000000000000000030 mtime=1695812443.629999189 30 atime=1695812445.807030368 29 ctime=1695812495.25973863 yadifa-2.6.5-11201/etc/yadifad.init.example0000664000374500037450000001142414505005533020776 0ustar00signersigner00000000000000#! /bin/sh #------------------------------------------------------------------------------ ## ## #------------------------------------------------------------------------------ ### BEGIN INIT INFO # Provides: yadifad # Required-Start: $local_fs $network # Required-Stop: # Should-Start: udev module-init-tools # Should-Stop: $named # Default-Start: 2 3 4 5 # Default-Stop: # Short-Description: Starts the YADIFAD name server # Description: Starts the YADIFAD name server ### END INIT INFO PATH=/sbin:/usr/sbin:/bin:/usr/bin PREFIX="/usr/local" NAME="yadifad" DAEMON="/sbin/${NAME}" SCRIPTNAME="/etc/init.d/${NAME}" PIDFILE="$PREFIX/var/run/yadifa.pid" CHROOTS=0 CHROOTDIR=$PREFIX YADIFA_CHROOT=/var if [ "$DEBUG" = "" ] then DEBUG=0 fi log() { echo $* logger -t $NAME-init-script -- $* } debug() { if [ $DEBUG -ne 0 ] then echo $* logger -t $NAME-init-script -- $* fi } if [ $CHROOTS -ne 0 ] then PREFIX= fi VAR="$PREFIX/var" CONF="$PREFIX/etc/yadifad.conf" if [ "$MAX_STOP_WAIT" = "" ] then MAX_STOP_WAIT=5 fi # Inside the internal chroot if [ "$CORE_PREFIX" = "" ] then CORE_PREFIX=/log fi if [ "$DUMPS_CORE" = "" ] then DUMPS_CORE=1 fi if [ $DUMPS_CORE -ne 0 ] then if [ ! -d $CHROOTDIR/$YADIFA_CHROOT/$CORE_PREFIX ] then log "Core dump enabled but '$CHROOTDIR/$YADIFA_CHROOT/$CORE_PREFIX' directory does not exists" exit 1 fi fi # not yet: # # CHECK="/sbin/yadifa-checkconf" # $? : supposed to be set # 1 : message # 2 : optional override code # 3 : what to do in case of error (command) die_on_error() { ERR="$?" if [ ! "" = "$2" ] then ERR="$2" fi if [ 0 -ne ${ERR} ] then if [ ! "" = "$3" ] then $3 fi log "error: '$1' ($ERR)" exit $err fi } # # Function that checks if yadifa is running # do_status_internal() { debug "checking for valid PIDFILE ${PIDFILE}" running=0 if [ -f ${PIDFILE} ] then PID=$(cat ${PIDFILE}) if [ "${PID}" != "" ] then PROC=$(ps -p ${PID} | tail -1| awk '{print $4}') if [ "$PROC" = "$NAME" ] then running=1 else log "error : process with pid ${PID} is '$PROC' and not '$NAME' : deleting pid file" rm -f ${PIDFILE} fi else log "error: empty '${PIDFILE}' : deleting pid file" rm -f ${PIDFILE} fi fi return $running } do_status() { do_status_internal running=$? if [ $running -eq 1 ] then log "${NAME} seems to be already running." exit 0 else log "${NAME} does not seem to be running." exit 1 fi } # # Function that starts the daemon/service # do_start() { log "Starting $NAME" debug "starting if no valid PIDFILE ${PIDFILE}" do_status_internal running=$? if [ $running -eq 1 ] then log "${NAME} seems to be already running." exit 1 fi debug cd $CHROOTDIR cd $CHROOTDIR debug prefix = ${PREFIX} debug daemon = ${DAEMON} if [ $DUMPS_CORE -ne 0 ] then COREPATH="$CHROOTDIR/$YADIFA_CHROOT/$CORE_PREFIX/cores" log "enabling core dump in $COREPATH" ulimit -c unlimited mkdir -p $COREPATH chmod 0777 $COREPATH chmod +t $COREPATH log "core dump will be stored in '$COREPATH' ($CORE_PREFIX/cores)" echo "$CORE_PREFIX/cores/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern echo 0x7 > /proc/self/coredump_filter echo -n 1 > /proc/sys/kernel/core_uses_pid echo -n 1 > /proc/sys/fs/suid_dumpable fi CMD="${PREFIX}${DAEMON} -c ${CONF} --daemon" if [ $CHROOTS -ne 0 ] then CMD="chroot $CHROOTDIR $CMD" fi debug $CMD $CMD die_on_error "${DAEMON} returned $?" exit 0 } # # Function that stops the daemon/service # do_stop() { log "Stopping $NAME" debug "stopping if valid PIDFILE ${PIDFILE}" if [ -f ${PIDFILE} ] then while [ -f ${PIDFILE} ] do PID=$(cat ${PIDFILE}) if [ "${PID}" = "" ] then log "error: empty '${PIDFILE}' : deleting pid file" rm -f ${PIDFILE} break fi PROC=$(ps -p ${PID} | tail -1| awk '{print $4}') if [ "$PROC" != "$NAME" ] then log "error : process with pid ${PID} is '$PROC' and not '$NAME' : deleting pid file" rm -f ${PIDFILE} break fi kill ${PID} > /dev/null 2>&1 for count in $(seq 0 $MAX_STOP_WAIT) do if [ ! -f ${PIDFILE} ] then break fi kill -0 ${PID} > /dev/null 2>&1 if [ $? -ne 0 ] then rm -f ${PIDFILE} break fi log "waiting for the process to stop (waited $count seconds)" sleep 1 done done else log "${NAME} does not seem to be running ..." debug "reason: ${PIDFILE} not found" fi } debug called with $1 case "$1" in start) do_start ;; stop) do_stop ;; restart) do_stop do_start ;; status) do_status ;; *) log "Usage: $SCRIPTNAME {start|stop|restart|status}" >&2 exit 3 ;; esac : yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad.service.example0000644000000000000000000000013214505005533021527 xustar000000000000000030 mtime=1695812443.626999145 30 atime=1695812445.807030368 30 ctime=1695812495.261738659 yadifa-2.6.5-11201/etc/yadifad.service.example0000664000374500037450000000045714505005533021477 0ustar00signersigner00000000000000[Unit] Description=YADIFA Domain Name Server Documentation=man:yadifa(8) After=network.target [Service] Type=simple PIDFile=/var/run/yadifad.pid ExecStart=/usr/sbin/yadifad -c /etc/yadifa/yadifad.conf --nodaemon ExecReload=/bin/kill -HUP $MAINPID KillMode=process [Install] WantedBy=multi-user.target yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad.bash_completion0000644000000000000000000000013114505005533021602 xustar000000000000000029 mtime=1695812443.63499926 30 atime=1695812445.807030368 30 ctime=1695812495.263738688 yadifa-2.6.5-11201/etc/yadifad.bash_completion0000664000374500037450000000605514505005533021553 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ _yadifad() { local cur prev opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" # standard options to complete opts="--config -c --daemon -d --nodaemon --uid -u --gid -g --port -P --version -V --help -h" # # some basic options' arguments can be completed # case ${prev} in -u|--uid) # options to complete if '-u' or '--uid' has been used local running=$(getent passwd | cut -d: -f1) COMPREPLY=( $( compgen -W "${running}" -- "$cur" ) ) return 0 ;; -g|--gid) # options to complete if '-g' or '--gid' has been used if [ -e /etc/group ]; then local running=$(getent group | cut -d: -f1) COMPREPLY=( $( compgen -W "${running}" -- "$cur" ) ) fi return 0 ;; -c|--config) # options to complete if '-c' or '--config' has been used local xpat='conf' _filedir "${xpat}" return 0 ;; *) ;; esac if [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W "${opts}" -- "$cur" ) ) return 0 fi } && complete -F _yadifad yadifad yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifa.bash_completion0000644000000000000000000000013214505005533021437 xustar000000000000000030 mtime=1695812443.633999246 30 atime=1695812445.806030354 30 ctime=1695812495.265738716 yadifa-2.6.5-11201/etc/yadifa.bash_completion0000664000374500037450000001322614505005533021405 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ _yadifa_ctrl_find_subcmd() { local subcword for (( subcword=1; subcword < ${#COMP_WORDS[@]}-1; subcword++ )) do case ${COMP_WORDS[subcword]} in cfgreload|freeze|freezeall|loglevel|logreopen|notify|querylog|reload|shutdown|sync|thaw|thawall|unfreeze|unfreezeall|zonecfgreload) subcmd="${COMP_WORDS[subcword]}" break ;; *) ;; esac done } _yadifa_ctrl() { local subcmd _yadifa_ctrl_find_subcmd if [[ "x$subcmd" = "x" ]] then # standard options to complete opts="cfgreload freeze freezeall loglevel logreopen notify querylog reload shutdown sync thaw thawall unfreeze unfreezeall zonecfgreload" else opts="-c --config -s --server -p --port -K --key-name -y --key" fi # # some basic options' arguments can be completed # case ${prev} in freeze|notify|reload|sync|thaw|unfreeze|zonecfgreload) _yadifa_find_all_zones return 0 ;; -p) _yadifa_find_ports return 0 ;; -s|--server) _yadifa_find_servers return 0 ;; -K|--key-name) _yadifa_find_key_names return 0 ;; -y|--key) _yadifa_find_key_names return 0 ;; loglevel) local running="$(seq 0 15)" COMPREPLY=( $( compgen -W "${running}" -- "$cur" ) ) return 0 ;; querylog) local running="enable disable" COMPREPLY=( $( compgen -W "${running}" -- "$cur" ) ) return 0 ;; -c|--config) local xpat='conf' _filedir "${xpat}" return 0 ;; -t) # options to complete if '-t' has been used local running="freeze unfreeze reload cfgreload sync querylog loglevel logreopen shutdown" COMPREPLY=( $( compgen -W "${running}" -- "$cur" ) ) return 0 ;; *) ;; esac COMPREPLY=( $( compgen -W "${opts}" -- "$cur" ) ) return 0 } _yadifa_find_keys() { # TODO find different keys in the configuration local keys COMPREPLY=( $( compgen -W "${keys}" -- "$cur" ) ) return 0 } _yadifa_find_key_names() { # TODO find different key names in the configuration local keynames COMPREPLY=( $( compgen -W "${keynames}" -- "$cur" ) ) return 0 } _yadifa_find_servers() { # TODO find different servers in the configuration local servers COMPREPLY=( $( compgen -W "${servers}" -- "$cur" ) ) return 0 } _yadifa_find_ports() { # TODO find different port numbers in the configuration local ports="53" COMPREPLY=( $( compgen -W "${ports}" -- "$cur" ) ) return 0 } _yadifa_find_all_zones() { # TODO find all the zones in the configuration local zones COMPREPLY=( $( compgen -W "${zones}" -- "$cur" ) ) return 0 } _yadifa_find_cmd() { local subcword for (( subcword=1; subcword < ${#COMP_WORDS[@]}-1; subcword++ )) do case ${COMP_WORDS[subcword]} in ctrl) cmd="ctrl" break ;; *) ;; esac done } _yadifa() { local cur prev bprev cmd opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" bprev="${COMP_WORDS[COMP_CWORD-2]}" # Look if we have a command or not _yadifa_find_cmd # standard options to complete opts="ctrl -V --version --help -h -v --verbose" case $cmd in ctrl) _yadifa_ctrl return 0 ;; *) ;; esac COMPREPLY=( $( compgen -W "${opts}" -- "$cur" ) ) return 0 } && complete -F _yadifa yadifa yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad-primary.conf.example0000644000000000000000000000013214505005533022475 xustar000000000000000030 mtime=1695812443.631999217 30 atime=1695812445.807030368 30 ctime=1695812495.267738745 yadifa-2.6.5-11201/etc/yadifad-primary.conf.example0000664000374500037450000000013014505005533022431 0ustar00signersigner00000000000000 domain somedomain.eu file masters/somedomain.eu.zone type primary yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad-secondary.conf.example0000644000000000000000000000013114505005533023000 xustar000000000000000029 mtime=1695812443.63499926 30 atime=1695812445.807030368 30 ctime=1695812495.269738774 yadifa-2.6.5-11201/etc/yadifad-secondary.conf.example0000664000374500037450000000015514505005533022744 0ustar00signersigner00000000000000 domain somedomain.eu file slaves/somedomain.eu.zone type secondary primary 192.0.2.1 yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad.init.debian0000644000000000000000000000013214505005533020621 xustar000000000000000030 mtime=1695812443.623999102 30 atime=1695812445.807030368 30 ctime=1695812495.271738802 yadifa-2.6.5-11201/etc/yadifad.init.debian0000775000374500037450000001100614505005533020564 0ustar00signersigner00000000000000N INIT INFO # Provides: yadifa # Required-Start: $remote_fs # Required-Stop: $remote_fs # Should-Start: $network $syslog # Should-Stop: $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Starts and stops the YADIFA name server # Description: YADIFA is a lightweight authoritative domain name server ### END INIT INFO # Author: Markus Schade PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="domain name service" NAME=yadifa DAEMON=/usr/sbin/yadifad DAEMON_ARGS="" # Arguments to run the daemon with PIDFILE=/var/run/$NAME/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed [ -x $DAEMON ] || exit 0 # Read configuration variable file if it is present [ -r /etc/default/$NAME ] && . /etc/default/$NAME # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh # Define LSB log_* functions. # Depend on lsb-base (>= 3.0-6) to ensure that this file is present. . /lib/lsb/init-functions # # Function that starts the daemon/service # do_start() { # dirs under /var/run can go away on reboots. mkdir -p /var/run/yadifa chmod 775 /var/run/yadifa chown root:yadifa /var/run/yadifa >/dev/null 2>&1 || true # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ || return 1 start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2 # Add code here, if necessary, that waits for the process to be ready # to handle requests from services started subsequently which depend # on this one. As a last resort, sleep for some time. } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME RETVAL="$?" [ "$RETVAL" = 2 ] && return 2 # Wait for children to finish too if this is a daemon that forks # and if the daemon is only ever run from this initscript. # If the above conditions are not satisfied then add some other code # that waits for the process to drop all resources that could be # needed by services started subsequently. A last resort is to # sleep for some time. start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON [ "$?" = 2 ] && return 2 # Many daemons don't delete their pidfiles when they exit. rm -f $PIDFILE return "$RETVAL" } # # Function that sends a SIGHUP to the daemon/service # do_reload() { # # If the daemon can reload its configuration without # restarting (for example, when it is sent a SIGHUP), # then implement that here. # start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME return 0 } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; status) status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? ;; #reload|force-reload) # # If do_reload() is not implemented then leave this commented out # and leave 'force-reload' as an alias for 'restart'. # #log_daemon_msg "Reloading $DESC" "$NAME" #do_reload #log_end_msg $? #;; restart|force-reload) # # If the "reload" option is implemented then remove the # 'force-reload' alias # log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 exit 3 ;; esac : yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad.init.rhel0000644000000000000000000000013114505005533020330 xustar000000000000000029 mtime=1695812443.62799916 30 atime=1695812445.807030368 30 ctime=1695812495.273738831 yadifa-2.6.5-11201/etc/yadifad.init.rhel0000775000374500037450000000510014505005533020272 0ustar00signersigner00000000000000#!/bin/bash # # yadifad This shell script takes care of starting and stopping # yadifad on RedHat or other chkconfig-based system. # # chkconfig: - 13 87 # processname: yadifad # config: /etc/yadifad.conf # pidfile: /var/run/yadifad.pid # # description: YADIFA is a name server implementation developed from \ # scratch by .eu. It is portable across multiple operating \ # systems and supports DNSSEC, TSIG, DNS notify, DNS update, IPv6. ### BEGIN INIT INFO # Provides: yadifad # Required-Start: $network # Required-Stop: $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start and stop yadifad # Description: YADIFA is a name server implementation developed from \ # scratch by .eu. It is portable across multiple operating \ # systems and supports DNSSEC, TSIG, DNS notify, DNS update, IPv6. ### END INIT INFO # Written by Denis Fateyev (denis@fateyev.com) # 2014.07.05 # Source function library . /etc/init.d/functions # Source networking configuration [ -r /etc/sysconfig/network ] && . /etc/sysconfig/network start() { [ "$EUID" != "0" ] && exit 4 [ "${NETWORKING}" = "no" ] && exit 1 [ -f /usr/sbin/yadifad ] || exit 5 # Start daemon echo -n $"Starting yadifad: " daemon /usr/sbin/yadifad >/dev/null 2>&1 && success || failure RETVAL=$? echo [ $RETVAL = 0 ] && touch /var/lock/subsys/yadifad } stop() { [ "$EUID" != "0" ] && exit 4 # Stop daemon echo -n $"Shutting down yadifad: " if [ -n "`pidfileofproc yadifad`" ] ; then killproc /usr/sbin/yadifad else failure $"Shutting down yadifad" fi RETVAL=$? echo [ $RETVAL = 0 ] && rm -f /var/lock/subsys/yadifad } restart() { stop start } reload() { [ "$EUID" != "0" ] && exit 4 # Reload daemon echo -n $"Reloading yadifad: " if [ -n "`pidfileofproc yadifad`" ] ; then killproc /usr/sbin/yadifad -HUP else failure $"Reloading yadifad" fi RETVAL=$? echo } # See how we were called case "$1" in start) start ;; stop) stop ;; restart) restart ;; reload) reload ;; condrestart|try-restart) status yadifad > /dev/null || exit 0 restart ;; status) status yadifad ;; *) echo $"Usage: $0 {start|stop|restart|reload|status|condrestart|try-restart}" exit 2 esac exit $RETVAL yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad.logrotate0000644000000000000000000000013214505005533020435 xustar000000000000000030 mtime=1695812443.632999232 30 atime=1695812445.807030368 30 ctime=1695812495.275738859 yadifa-2.6.5-11201/etc/yadifad.logrotate0000664000374500037450000000133614505005533020402 0ustar00signersigner00000000000000/var/log/yadifa/*log { daily rotate 10 compress missingok notifempty sharedscripts postrotate if [ -f "/usr/sbin/service" ]; then /usr/sbin/service yadifad reload > /dev/null 2>/dev/null || true else /sbin/service yadifad reload > /dev/null 2>/dev/null || true fi endscript } #/var/log/yadifa/*log.gz { # daily # rotate 10 # nocompress # missingok # notifempty # sharedscripts # postrotate # if [ -f "/usr/sbin/service" ]; then # /usr/sbin/service yadifad reload > /dev/null 2>/dev/null || true # else # /sbin/service yadifad reload > /dev/null 2>/dev/null || true # fi # endscript #} yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad.service.arch0000644000000000000000000000013214505005533021011 xustar000000000000000030 mtime=1695812443.639999332 30 atime=1695812445.807030368 30 ctime=1695812495.277738888 yadifa-2.6.5-11201/etc/yadifad.service.arch0000664000374500037450000000027414505005533020756 0ustar00signersigner00000000000000[Unit] Description=yadifa nameserver [Service] Type=simple ExecStart=/usr/bin/yadifad --nodaemon ExecReload=/bin/kill -HUP $MAINPID KillMode=process [Install] WantedBy=multi-user.target yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad.service.debian0000644000000000000000000000013214505005533021316 xustar000000000000000030 mtime=1695812443.621999074 30 atime=1695812445.807030368 30 ctime=1695812495.279738917 yadifa-2.6.5-11201/etc/yadifad.service.debian0000664000374500037450000000033614505005533021262 0ustar00signersigner00000000000000[Unit] Description=YADIFA Domain Name Server Documentation=man:yadifa(8) After=network.target [Service] Type=simple ExecStart=/usr/sbin/yadifad -c /etc/yadifa/yadifad.conf --nodaemon [Install] WantedBy=multi-user.target yadifa-2.6.5-11201/etc/PaxHeaders.1636/yadifad.service.rhel0000644000000000000000000000013214505005533021026 xustar000000000000000030 mtime=1695812443.624999117 30 atime=1695812445.807030368 30 ctime=1695812495.281738945 yadifa-2.6.5-11201/etc/yadifad.service.rhel0000664000374500037450000000033214505005533020766 0ustar00signersigner00000000000000[Unit] Description=Yadifa DNS server After=network.target [Service] Type=simple PIDFile=/run/yadifad.pid ExecStart=/usr/sbin/yadifad --nodaemon ExecReload=/bin/kill -HUP $MAINPID [Install] WantedBy=multi-user.target yadifa-2.6.5-11201/etc/PaxHeaders.1636/yakeyrolld.conf.example0000644000000000000000000000013214505005533021572 xustar000000000000000030 mtime=1695812443.628999174 30 atime=1695812445.807030368 30 ctime=1695812495.283738974 yadifa-2.6.5-11201/etc/yakeyrolld.conf.example0000664000374500037450000001134214505005533021535 0ustar00signersigner00000000000000# # Example yakeyrolld configuration file. # domain example.eu # This MUST point into yadifa's keys directory. # Only one key path is supported, one path per zone handling can be implemented if needed keys-path "/usr/local/var/zones/keys" plan-path "/usr/local/var/plans" log-path "/usr/local/var/log/yakeyrolld" uid yadifad gid yadifad generate-from "now" generate-until "+1y" server 127.0.0.1 policy "primary-policy" # # TSIG Key configuration # name primary-secondary algorithm hmac-md5 secret PrimaryAndSecondaryKey== dnssec dnssec.log 0644 system system.log 0644 keyroll keyroll.log 0644 all all.log 0644 system prod system dnssec prod dnssec keyroll prod keyroll,all ################################################################################ ################################################################################ ### ### POLICIES ### ################################################################################ ################################################################################ # name of the 'dnssec-policy' id "primary-policy" description "primary zone policy" # at least one: key-descriptor "name" # they define KSK & ZSK keys key-suite "zsk-2048" key-suite "ksk-2048" # name of the key-suite id "zsk-2048" key-template "zsk-rsa-sha512-2048" key-roll "monthly-calendar" # name of the key-suite id "ksk-2048" key-template "ksk-rsa-sha512-2048" key-roll "yearly-calendar" id "zsk-rsa-sha512-2048" algorithm RSASHA512 size 1024 id "ksk-rsa-sha512-2048" ksk 1 algorithm RSASHA512 size 2048 # # Quick note about how the sheduler computes times. # # The calendar triggers events in this order: Generates, publishes, activates, de-activates, removes. # The sheduling always arranges so the de-activation occurs at or after the next sheduled activation. # So if generate, publish and activate are relative to each-other, inactive is relative to the activate of the next key. # id "yearly-calendar" generate 11 10 * 1 mon 1 # Januay, Monday of the second week at 10:11 publish 11 10 * 1 tue * # following Tuesday at 10:11 activate 11 10 * 1 wed * # following Wednesday at 10:11 inactive 11 10 * 1 mon * # following Monday, a year after, at 10:11 remove 11 10 * 1 wed * # following Wednesday at 10:11 id "monthly-calendar" generate 17 10 * * mon 0 # 1st monday the month at 10:17 publish 17 10 * * tue * # following tuesday at 10:17 activate 17 10 * * wed * # following wednesday at 10:17 inactive 17 10 * * wed * # following wednesday at 10:17 (one week after the activation) remove 17 10 * * thu * # following thursday at 10:17 id "weekly-calendar" generate 0 9 * * mon * # Monday at 09:00 publish 0 8 * * tue * # Tuesday at 08:00 activate 0 6 * * wed * # Wednesday at 06:00 inactive 0 6 * * wed * # Wednesday at 06:00 (next Wednesday, if >06:00 the Wednesday in two weeks) remove 0 12 * * fri * # Friday at 12:00 yadifa-2.6.5-11201/PaxHeaders.1636/doc0000644000000000000000000000013214505005617015032 xustar000000000000000030 mtime=1695812495.342739819 30 atime=1695812499.082793384 30 ctime=1695812495.342739819 yadifa-2.6.5-11201/doc/0000775000374500037450000000000014505005617015051 5ustar00signersigner00000000000000yadifa-2.6.5-11201/doc/PaxHeaders.1636/Makefile.in0000644000000000000000000000013014505005546017153 xustar000000000000000030 mtime=1695812454.663157206 29 atime=1695812461.84126001 29 ctime=1695812495.32673959 yadifa-2.6.5-11201/doc/Makefile.in0000664000374500037450000005241514505005546017126 0ustar00signersigner00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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@ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ subdir = doc DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(dist_man5_MANS) $(dist_man8_MANS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/eurid.m4 $(top_srcdir)/m4/yadifa.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = 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 = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac 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; }; \ } man5dir = $(mandir)/man5 am__installdirs = "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" man8dir = $(mandir)/man8 NROFF = nroff MANS = $(dist_man5_MANS) $(dist_man8_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) 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@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCOPTIMISATIONFLAGS = @CCOPTIMISATIONFLAGS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DNSCORE = @DNSCORE@ DNSDB = @DNSDB@ DNSLG = @DNSLG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAS_ACL_SUPPORT = @HAS_ACL_SUPPORT@ HAS_BFD_DEBUG_SUPPORT = @HAS_BFD_DEBUG_SUPPORT@ HAS_BIG_ENDIAN = @HAS_BIG_ENDIAN@ HAS_BUILD_TIMESTAMP = @HAS_BUILD_TIMESTAMP@ HAS_CC_ADDRESS_SANITIZER_CHECK = @HAS_CC_ADDRESS_SANITIZER_CHECK@ HAS_CC_ANSI = @HAS_CC_ANSI@ HAS_CC_ANSI_ALIAS = @HAS_CC_ANSI_ALIAS@ HAS_CC_CATCH_UNDEFINED_BEHAVIOR = @HAS_CC_CATCH_UNDEFINED_BEHAVIOR@ HAS_CC_DWARF2 = @HAS_CC_DWARF2@ HAS_CC_DWARF3 = @HAS_CC_DWARF3@ HAS_CC_DWARF4 = @HAS_CC_DWARF4@ HAS_CC_EXCEPTIONS = @HAS_CC_EXCEPTIONS@ HAS_CC_G = @HAS_CC_G@ HAS_CC_G3 = @HAS_CC_G3@ HAS_CC_M32 = @HAS_CC_M32@ HAS_CC_M64 = @HAS_CC_M64@ HAS_CC_MISSING_FIELD_INITIALIZERS = @HAS_CC_MISSING_FIELD_INITIALIZERS@ HAS_CC_NO_IDENT = @HAS_CC_NO_IDENT@ HAS_CC_NO_OMIT_FRAME_POINTER = @HAS_CC_NO_OMIT_FRAME_POINTER@ HAS_CC_PEDANTIC = @HAS_CC_PEDANTIC@ HAS_CC_RDYNAMIC = @HAS_CC_RDYNAMIC@ HAS_CC_SANITIZE_ADDRESS = @HAS_CC_SANITIZE_ADDRESS@ HAS_CC_STACK_PROTECTOR = @HAS_CC_STACK_PROTECTOR@ HAS_CC_STD_C11 = @HAS_CC_STD_C11@ HAS_CC_STD_C99 = @HAS_CC_STD_C99@ HAS_CC_STD_GNU11 = @HAS_CC_STD_GNU11@ HAS_CC_STD_GNU99 = @HAS_CC_STD_GNU99@ HAS_CC_TUNE_NATIVE = @HAS_CC_TUNE_NATIVE@ HAS_CC_WALL = @HAS_CC_WALL@ HAS_CC_XC99 = @HAS_CC_XC99@ HAS_CLOSE_EX_REF = @HAS_CLOSE_EX_REF@ HAS_CTRL = @HAS_CTRL@ HAS_DNSSEC_TOOLS = @HAS_DNSSEC_TOOLS@ HAS_DYNUPDATE_SUPPORT = @HAS_DYNUPDATE_SUPPORT@ HAS_ECDSA_SUPPORT = @HAS_ECDSA_SUPPORT@ HAS_EDDSA = @HAS_EDDSA@ HAS_EVENT_DYNAMIC_MODULE = @HAS_EVENT_DYNAMIC_MODULE@ HAS_FULL_ASCII7 = @HAS_FULL_ASCII7@ HAS_KEYGEN = @HAS_KEYGEN@ HAS_LIBC_MALLOC_DEBUG_SUPPORT = @HAS_LIBC_MALLOC_DEBUG_SUPPORT@ HAS_LITTLE_ENDIAN = @HAS_LITTLE_ENDIAN@ HAS_LOCK_DEBUG_SUPPORT = @HAS_LOCK_DEBUG_SUPPORT@ HAS_LOGDIR = @HAS_LOGDIR@ HAS_LOG_PID = @HAS_LOG_PID@ HAS_LOG_THREAD_ID = @HAS_LOG_THREAD_ID@ HAS_LOG_THREAD_TAG = @HAS_LOG_THREAD_TAG@ HAS_MALLOC_DEBUG_SUPPORT = @HAS_MALLOC_DEBUG_SUPPORT@ HAS_MASTER_SUPPORT = @HAS_MASTER_SUPPORT@ HAS_MEMALIGN_ISSUES = @HAS_MEMALIGN_ISSUES@ HAS_MUTEX_DEBUG_SUPPORT = @HAS_MUTEX_DEBUG_SUPPORT@ HAS_NON_AA_AXFR_SUPPORT = @HAS_NON_AA_AXFR_SUPPORT@ HAS_NSEC3_SUPPORT = @HAS_NSEC3_SUPPORT@ HAS_NSEC_SUPPORT = @HAS_NSEC_SUPPORT@ HAS_NSID_SUPPORT = @HAS_NSID_SUPPORT@ HAS_RRL_SUPPORT = @HAS_RRL_SUPPORT@ HAS_RRSIG_MANAGEMENT_SUPPORT = @HAS_RRSIG_MANAGEMENT_SUPPORT@ HAS_SYNC_BUILTINS = @HAS_SYNC_BUILTINS@ HAS_SYSTEMD_RESOLVED_AVOIDANCE = @HAS_SYSTEMD_RESOLVED_AVOIDANCE@ HAS_TESTS = @HAS_TESTS@ HAS_TOOLS = @HAS_TOOLS@ HAS_TRACK_ZONES_DEBUG_SUPPORT = @HAS_TRACK_ZONES_DEBUG_SUPPORT@ HAS_TSIG_SUPPORT = @HAS_TSIG_SUPPORT@ HAS_YADIFA = @HAS_YADIFA@ HAS_ZALLOC_DEBUG_SUPPORT = @HAS_ZALLOC_DEBUG_SUPPORT@ HAS_ZALLOC_STATISTICS_SUPPORT = @HAS_ZALLOC_STATISTICS_SUPPORT@ HAS_ZALLOC_SUPPORT = @HAS_ZALLOC_SUPPORT@ HAVE_RECVMMSG = @HAVE_RECVMMSG@ HAVE_SENDMMSG = @HAVE_SENDMMSG@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IS_BSD_FAMILY = @IS_BSD_FAMILY@ IS_DARWIN_GE14 = @IS_DARWIN_GE14@ IS_DARWIN_OS = @IS_DARWIN_OS@ IS_LINUX_FAMILY = @IS_LINUX_FAMILY@ IS_SOLARIS_FAMILY = @IS_SOLARIS_FAMILY@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL = @OPENSSL@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZDB_HAS_DNSSEC_SUPPORT = @ZDB_HAS_DNSSEC_SUPPORT@ 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_CXX = @ac_ct_CXX@ 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@ 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@ logdir = @logdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ dist_man8_MANS = yadifad.man yadifa.man yakeyrolld.man dist_man5_MANS = yadifad.conf.man yadifa.conf.man yadifa.rc.man yakeyrolld.conf.man ACLOCAL_AMFLAGS = -I m4 all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(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) --gnu doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man5: $(dist_man5_MANS) @$(NORMAL_INSTALL) @list1='$(dist_man5_MANS)'; \ list2=''; \ test -n "$(man5dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.5[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ done; } uninstall-man5: @$(NORMAL_UNINSTALL) @list='$(dist_man5_MANS)'; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) install-man8: $(dist_man8_MANS) @$(NORMAL_INSTALL) @list1='$(dist_man8_MANS)'; \ list2=''; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list='$(dist_man8_MANS)'; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(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 $(MANS) installdirs: for dir in "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; 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-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man 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-man5 install-man8 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 Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-man uninstall-man: uninstall-man5 uninstall-man8 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir 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-man5 install-man8 install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-man uninstall-man5 uninstall-man8 doc: . doxygen $(srcdir)/yadifa.doxygen features: # 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: yadifa-2.6.5-11201/doc/PaxHeaders.1636/Makefile.am0000644000000000000000000000013214505005531017136 xustar000000000000000030 mtime=1695812441.317966076 30 atime=1695812445.806030354 30 ctime=1695812495.328739619 yadifa-2.6.5-11201/doc/Makefile.am0000664000374500037450000000403014505005531017075 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ dist_man8_MANS = yadifad.man yadifa.man yakeyrolld.man dist_man5_MANS = yadifad.conf.man yadifa.conf.man yadifa.rc.man yakeyrolld.conf.man ACLOCAL_AMFLAGS = -I m4 doc: . doxygen $(srcdir)/yadifa.doxygen features: yadifa-2.6.5-11201/doc/PaxHeaders.1636/yadifad.conf.man0000644000000000000000000000013214505005531020124 xustar000000000000000030 mtime=1695812441.312966004 30 atime=1695812445.806030354 30 ctime=1695812495.330739647 yadifa-2.6.5-11201/doc/yadifad.conf.man0000664000374500037450000012531414505005531020074 0ustar00signersigner00000000000000'\" t .\" Manual page created with latex2man on Tue Oct 13 12:59:04 2020 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW .nf .. .de Ve .ft R .fi .. .TH "YADIFAD\-CONF" "5" "2023\-09\-06" "YADIFA " "YADIFA " .SH NAME .PP yadifad.conf \- configuration file for \fIyadifad\fP(8)\&. .PP .SH SYNOPSIS .PP ${SYSCONFDIR}/yadifad.conf .PP .SH DESCRIPTION .PP The configuration of yadifad is consistent in a text file that can optionally include others. The general structure is a sequence of containers: a sequence of lines of text starting with a and ending with a . Each line between these delimitters is in the form: variable\-name value. The format of the value is determined by the type of the variable. .PP .SS TYPES .PP There are 15 types: .PP .TP \fIACL\fP A list of ACL descriptors. User\-defined ACLs are found in the ACL section. The "any" and "none" descriptors are always defined. Elements of the list are separated by a "," or a ";". .TP \fIDNSSECTYPE\fP A DNSSEC type name. It can be a DNSSEC\-enabled value ("nsec", "nsec3" or "nsec3\-optout") or a DNSSEC\-disabled value ("none", "no", "off" or "0"). .TP \fIENUM\fP A word from a specified set. .TP \fIFLAG\fP A boolean value. It can be true ("1", "enable", "enabled", "on", "true", "yes") or false ("0", "disable", "disabled", "off", "false", "no"). .TP \fIFQDN\fP A fully\-qualified domain name text string. e.g.: www.eurid.eu. .TP \fIGID\fP Group ID. (Can be a number or a name) .TP \fIHOST(S)\fP A (list of) host(s). A host is defined by an IP (v4 or v6) and can be followed by the word `port\&' and a port number. Elements of the list are separated by a `,\&' or a `;\&'\&. .TP \fIINTEGER / INT\fP A base\-ten integer. .TP \fINETMOD\fP A word or integer that identifies the network model: .br \fBsingle or 0\fP Each working thread reads a single message, processes its answer and replies to it. .br \fBbuffered or 1\fP Working threads are working by couple. One reads a single message and queues it, one de\-queues it, processes its answer and replies to it. .br \fBmulti or 2\fP Each working thread reads a multiple messages, processes their answers and replies to them. .br .TP \fIPATH / FILE\fP A file or directory path. i.e.: "/var/zones". .TP \fISTRING / STR\fP A text string. Double quotes can be used but are not mandatory. Without quotes the string will be taken from the first non\-blank charater to the last non\-blank character. .TP \fIHEXSTR\fP A hexadecimal even\-length text string. .TP \fIRELDATE\fP A cron\-like date to be matched, relative to another. The columns are minutes [0;59], hours [0;23], days [0;31], months [1;12], weekdays [mon,tue,wed,thu,fri,sat,sun] and week\-of\-the\-month [0;4]. Multiple values can be set in a column cell using \&',\&' as a separator. The \&'*\&' character can be used to set all possible values of its column cell. .TP \fIRELTIME\fP A time offset relative to another. It\&'s written as +integer[unit\-character] (e.g.: +24h) where the unit character can be \fIs\fPeconds, \fIm\fPinutes, \fIh\fPours, \fId\fPays or \fIw\fPeeks. .TP \fISECONDS\fP A base\-ten integer. .TP \fIHOURS\fP A base\-ten integer. .TP \fIDAYS\fP A base\-ten integer. .TP \fIUID\fP User ID. (Can be a number or a name) .PP .SS CONTAINERS .PP The configuration of yadifad has several containers: .PP .TP \fB
\fP General container .TP \fB\fP TSIG keys .TP \fB\fP Access lists .TP \fB\fP NameServer IDentifier .TP \fB\fP Response Rate Limiting directives .TP \fB\fP Description of the domain name in specific attributes. .TP \fB\fP Description of the logger outputs. .TP \fB\fP Description of dnssec policies. .TP \fB\fP Description of the key\-suites needed if \&'dnssec policies\&' are used. .TP \fB\fP Description of the key\-rolls needed if \&'dnssec policies\&' are used. .TP \fB\fP Description of the key\-templates needed if \&'dnssec policies\&' are used. .TP \fB\fP Description of \&'denial\&', this can be used in certain \&'dnssec policies\&'\&. .PP The configuration supports included files. .br example: include /etc/yadifa/conf.d/local.conf .PP The configuration files can be nested. .PP The configuration consists of: .TP .B * Container, which starts with and ends with .TP .B * Variable name .TP .B * 1 or 2 arguments .TP .B * Arguments can contain 1 or more comma separated values. .PP .SS STANDARD SECTIONS .PP .TP \fB
\fP General container, contains all the configuration parameters needed to start up yadifad\&. .PP .RS .TP \fBallow\-control \fP\fIACL \fP default: none Default server\-control access control list. Only the sources matching the ACL are accepted. .TP \fBallow\-notify \fP\fIACL \fP default: any Default notify access control list. Only the servers matching the ACL will be handled. .TP \fBallow\-query \fP\fIACL \fP default: any Default query access control list. Only the clients matching the ACL will be replied to. .TP \fBallow\-transfer \fP\fIACL \fP default: none Default transfer access control list. Only the clients matching the ACL will be allowed to transfer a zone (\fIaxfr\fP/\fIixfr\fP). .TP \fBallow\-update \fP\fIACL \fP default: none Default update access control list. Only the clients matching the ACL will be allowed to update a zone. .TP \fBallow\-update\-forwarding \fP\fIACL \fP default: none Default update\-forwarding access control list. Only the sources matching the ACL are accepted. .TP \fBanswer\-formerr\-packets \fP\fIFLAG \fP default: true If this flag is disabled; the server will not reply to badly formatted packets. .TP \fBaxfr\-compress\-packets \fP\fIFLAG \fP default: true Enables the \fIdns\fP packet compression of each \fIaxfr\fP packet. .TP \fBaxfr\-max\-packet\-size \fP\fIINT \fP default: 4096 bytes The maximum size of an \fIaxfr\fP packet. (MIN: 512; MAX: 65535) .TP \fBaxfr\-max\-record\-by\-packet \fP\fIINT \fP default: 0 The maximum number of records in each \fIaxfr\fP packet. Older name servers can only handle 1. Set to 0 to disable the limit. (MIN: 0; MAX: 65535) .TP \fBaxfr\-retry\-delay \fP\fISECONDS \fP default: 600 Number of seconds between each retry for the first transfer from the primary name server. (MIN: 60; MAX: 86400) .TP \fBaxfr\-retry\-jitter \fP\fISECONDS \fP default: 180 Jitter applied to axfr\-retry\-delay. (MIN: 60; MAX: axfr\-retry\-delay) .TP \fBaxfr\-retry\-failure\-delay\-multiplier \fP\fIINT \fP default: 5 Linear back\-off multiplier. The multiplier times the number of failures is added to the xfr\-retry\-delay. (MIN: 0; MAX: 86400) .TP \fBaxfr\-retry\-failure\-delay\-max \fP\fISECONDS \fP default: 3600 Maximum delay added for the back\-off. (MIN: 0; MAX: 604800) .TP \fBaxfr\-strict\-authority \fP\fIFLAG \fP default: yes (unless \-\-enable\-non\-aa\-axfr\-support was used) Tells yadifad to be strict with the AA flag in AXFR answers .TP \fBchroot \fP\fIFLAG \fP default: off Enabling this flag will make the server jail itself in the chroot\-path directory. .TP \fBchroot\-path; chrootpath \fP\fIPATH \fP default: / The directory used for the jail. .TP \fBcpu\-count\-override \fP\fIINT \fP default: 0 Overrides the detected number of logical cpus. Set to 0 for automatic. (MIN: 0; MAX: 256) .TP \fBdaemon; daemonize \fP\fIFLAG \fP default: false Enabling this flag will make the server detach from the console and work in background. .TP \fBdata\-path; datapath \fP\fIPATH \fP default: zones The base path were lies the data (zone file path; journaling data; temporary files; etc.) .TP \fBdo\-not\-listen \fP\fIHOSTS \fP default: \- An exclusion list of addresses to never listen to. If set, 0.0.0.0 and ::0 will always be split by interface to isolate the address. .TP \fBedns0\-max\-size \fP\fIINT \fP default: 4096 \fIedns0\fP packets size. (MIN: 512; MAX: 65535) .TP \fBgid; group \fP\fIGID \fP default: 0 (or root) The group ID that the server will use. .TP \fBhidden\-primary; hidden\-master \fP\fIFLAG \fP default: no As a hidden primary more CPU will be used for various maintenance tasks. .TP \fBhostname\-chaos; hostname \fP\fISTR \fP default: the host name The string returned by a hostname\-chaos TXT CH query. .TP \fBkeys\-path; keyspath \fP\fIPATH \fP default: zones/keys The base path of the \fIdnssec\fP keys. .TP \fBlisten \fP\fIHOSTS \fP default: 0.0.0.0,::0 The list of interfaces to listen to. .TP \fBlog\-files\-disabled \fP\fIFLAG \fP default: no If set, disables checking the log\-path directory for existence and writing rights. .TP \fBlog\-path; logpath \fP\fIPATH \fP default: log The base path where the log files are written. .TP \fBlog\-unprocessable \fP\fIFLAG \fP default: off Enabling this flag will make the server log unprocessable queries. .TP \fBmax\-tcp\-queries; max\-tcp\-connections \fP\fIINT \fP default: 16 The maximum number of parallel \fItcp\fP queries; allowed. (MIN: 1; MAX: 255) .TP \fBnetwork\-model \fP\fINETMOD \fP default: multi Sets the networking model of yadifa. .TP \fBpid\-file; pidfile \fP\fISTR \fP default: run/yadifad.pid The pid file name. .TP \fBqueries\-log\-type \fP\fIINT \fP default: 1 Query log format. (0: none; 1: \fIyadifa\fP format; 2: BIND format; 3: \fIyadifa\fP and BIND format at once) .TP \fBserverid\-chaos; serverid \fP\fISTR \fP default: \- The string returned by a id.server. TXT CH query. If not set; REFUSED is answered. .TP \fBserver\-port; port \fP\fIINT \fP default: 53 The default \fIdns\fP port. (MIN: 1; MAX: 65535) .TP \fBsig\-validity\-interval \fP\fIDAYS \fP default: 30 The number of days for which an automatic signature is valid. (MIN: 7 days; MAX: 30 days) .TP \fBsig\-validity\-jitter; sig\-jitter \fP\fISECONDS \fP default: 3600 The signature expiration validity jitter in seconds (1 hour). (MIN: 0 sec; MAX: 86400 sec) .TP \fBsig\-validity\-regeneration \fP\fIHOURS \fP default: automatic Signatures expiring in less than the indicated amount of hours will be recomputed. The default will be chosen by \fIyadifa\fP\&. (MIN: 24 hours; MAX: 168 hours) .TP \fBstatistics \fP\fIFLAG \fP default: true The server will log a report line about some internal statistics. .TP \fBstatistics\-max\-period \fP\fISECONDS \fP default: 60 The period in seconds between two statistics log lines. (MIN: 1 sec; MAX: 31 * 86400 seconds (31 days)) .TP \fBtcp\-query\-min\-rate \fP\fIINT \fP default: 512 bytes/second The minimum transfer rate required in a \fItcp\fP connection (read and write). Slower connections are closed. The units are bytes per second. (MIN: 0; MAX: 4294967295 .TP \fBthread\-affinity\-base \fP\fIINT \fP default: 0 Sets the first CPU to set affinity for. Set it to the real CPU of a core. (MIN: 0; MAX: 3) .TP \fBthread\-affinity\-multiplier \fP\fIINT \fP default: 0 Sets the multiplier chosing CPU to set affinity for. Allows avoiding hyperthread cores. Set to 0 for automatic avoiding. (MIN: 0; MAX: 4) .TP \fBthread\-count\-by\-address \fP\fIINT \fP default: \-1 Number of independent threads used to process each listening address. Set to \-1 for automatic. Set to 0 for single threaded. (MIN: \-1; MAX: number of CPU\&'s) .TP \fBuid; user \fP\fIUID \fP default: 0 (or root) The user ID that the server will use. .TP \fBversion\-chaos; version \fP\fISTR \fP default: yadifa version# The text to include in the version TXT CH query. .TP \fBxfr\-connect\-timeout \fP\fISECONDS \fP default: 5 Timeout for establishing a connection for \fIaxfr\fP and \fIixfr\fP transfers. Set to 0 to disable. (MIN: 0; MAX: 4294967295) .TP \fBxfr\-path; xfrpath \fP\fIPATH \fP default: zones/xfr The base path used for \fIaxfr\fP and journal storage. .TP \fBzone\-download\-thread\-count \fP\fIINT \fP default: 4 Number of independent threads used to download the zones. (MIN: 0; MAX: 255) .TP \fBzone\-load\-thread\-count \fP\fIINT \fP default: 1 Number of independent threads used to process loading of the zones. (MIN: 0; MAX: 255) .TP \fBzone\-store\-thread\-count \fP\fIINT \fP default: 1 Sets the number of threads used to store a zone on disk (MIN: 1, MAX: 4). .TP \fBzone\-unload\-thread\-count \fP\fIINT \fP default: 1 Sets the number of threads used to delete a zone from memory (MIN: 1, MAX: 4). .TP \fBworker\-backlog\-queue\-size \fP\fIINT \fP default: 16384 For network\-model 1, sets the size of the backlog queue (MIN: 4096, MAX: 1048576). .RE .RS .PP .RE .TP \fB\fP TSIG keys .PP .RS .TP \fBalgorithm \fP\fIENUM \fP default: \- Mandatory. Sets the algorithm of the key. .RS .PP Supported values are: .RS .RE .TP \fB \fP\fB \fP\fB \fP\fIhmac\-md5\fP .TP \fB \fP\fB \fP\fB \fP\fIhmac\-sha1\fP .TP \fB \fP\fB \fP\fB \fP\fIhmac\-sha224\fP .TP \fB \fP\fB \fP\fB \fP\fIhmac\-sha256\fP .TP \fB \fP\fB \fP\fB \fP\fIhmac\-sha384\fP .TP \fB \fP\fB \fP\fB \fP\fIhmac\-sha512\fP .RE .RS .PP (the algorithm names are case insensitive)} .RE .TP \fBname \fP\fIFQDN \fP default: \- Mandatory. Sets the name of the key. .TP \fBsecret \fP\fITEXT \fP default: \- Mandatory. Sets the value of the key. BASE64 encoded. .RE .RS .PP .RE .TP \fB\fP Access lists .PP Each entry of the acl section defines a rule of access. Each rule is a name (a single user\-defined word) followed by a rule in the form of a list of statements. The separator can be "," or ";". The "any" and "none" names are reserved. A statement tells if a source is accepted or rejected. Reject statements are prefixed with "!". Statements are evaluated in the following order: first from more specific to less specific, then from reject to accept. If a statement matches, the evaluation will stop and accordingly accept or reject the source. If no statement matches, then the source is rejected. .PP A statement can be either: .PP .RS .TP .B * An IPv4 or an IPv6 address followed (or not) by a mask. .br [\fI!\fP]ipv4 |ipv6 [\fI/mask\fP] .br .RS .PP For example: .RS .RE .TP .B * internal\-network 192.0.2.128/26;2001:DB8::/32 .RE .RS .PP .RE .TP .B * The word `key\&' followed by the name of a TSIG key. .br key key\-name .br .RS .PP For example: .RS .RE .TP .B * slaves key public\-slave;key hidden\-slave .RE .RS .PP .RE .TP .B * An ACL statement name from the \fIacl\fP section. Note that negation and recursion are forbidden and duly rejected. .br acl\-name .br .RS .PP For example: .RS .RE .TP .B * who\-can\-ask\-for\-an\-ixfr primary;secondaries;127.0.0.1 .RE .RS .PP .RE .RE .RS .PP .RE .TP \fB\fP NameServer IDentifier .PP .RS .TP \fBascii \fP\fI STR \fP default: "" The string can be 512 characters long. .TP \fBhex \fP\fI \fP default: "" .RE .RS .PP .RE .TP \fB\fP Response Rate Limiting directives .PP .RS .TP \fBresponses\-per\-second \fP\fI INT \fP default: 5 Allowed response rate. .TP \fBerrors\-per\-second \fP\fI INT \fP default: 5 Allowed error rate. .TP \fBslip \fP\fI INT \fP default: 2 Random slip parameter. .TP \fBlog\-only \fP\fI FLAG \fP default: false If set to true, logs what it should do without doing it. .TP \fBipv4\-prefix\-length \fP\fI INT \fP default: 24 Mask applied to group the IPv4 clients. .TP \fBipv6\-prefix\-length \fP\fI INT \fP default: 56 Mask applied to group the IPv6 clients. .TP \fBexempt\-clients \fP\fI ACL \fP default: none Clients maching this rule are not subject to the RRL. .TP \fBenabled \fP\fI FLAG \fP default: false Enables the RRL .TP \fBmin\-table\-size \fP\fI INT \fP default: 1024 RRL buffer minimum size .TP \fBmax\-table\-size \fP\fI INT \fP default: 16384 RRL buffer maximum size .TP \fBwindow \fP\fI INT \fP default: 15 RRL sliding window size in seconds .RE .RS .PP .RE .TP \fB\fP Description of the domain name in specific attributes. .PP .RS .TP \fBallow\-control \fP\fIACL \fP default: as main Control commands control list. Only the matching sources are allowed. .TP \fBallow\-notify \fP\fIACL \fP default: as main Notify access control list. Only the servers matching the ACL will be handled. .TP \fBallow\-query \fP\fIACL \fP default: as main Query access control list. Only the clients matching the ACL will be replied to. .TP \fBallow\-transfer \fP\fIACL \fP default: as main Tansfer access control list. Only the clients matching the ACL will be allowed to transfer a zone (\fIaxfr\fP/\fIixfr\fP .TP \fBallow\-update \fP\fIACL \fP default: as main Update access control list. Only the clients matching the ACL will be allowed to update a zone. .TP \fBallow\-update\-forwarding \fP\fIACL \fP default: as main Update forwarding control list. Only the matching sources are allowed. .TP \fBdnssec\-mode; dnssec \fP\fIDNSSEC\-TYPE\fP default: off Type of \fIdnssec\fP used for the zone. As primary name sever; \fIyadifa\fP will try to maintain that state. .TP \fBdnssec\-policy \fP\fISTR \fP default: \- Sets the dnssec\-policy id to be used. .TP \fBdomain \fP\fIFQDN \fP default: \- Mandatory. Sets the domain of the zone (i.e.: eurid.eu). .TP \fBdrop\-before\-load \fP\fIFLAG \fP default: off Enabling this flag will make the server drop the zone before loading the updated zone from disk. Use this on systems constrained for RAM. .TP \fBfile\-name; file \fP\fIFILE \fP default: \- Sets the zone file name. Only mandatory for a primary zone. .TP \fBjournal\-size\-kb \fP\fIINT \fP default: 0 Puts a soft limit on the size of the journal; expressed in KB. (MIN: 0; MAX: 3698688 (3GB)) .TP \fBkeys\-path; keyspath \fP\fIPATH \fP default: as main The base path of the \fIdnssec\fP keys. .TP \fBmaintain\-dnssec \fP\fIFLAG \fP default: true Enabling this flag will cause the server to try and maintain \fIrrsig\fP records .TP \fBprimaries; primary; masters; master \fP\fIHOSTS \fP default: \- Mandatory for a slave. Sets the primary server(s). Multiple primaries are supported. .TP \fBmultiprimary\-retries; multimaster\-retries \fP\fIINT \fP default: 0 The number of times the primary is unreachable before switching to a different primary (MIN: 0; MAX: 255) .TP \fBno\-primary\-updates; no\-master\-updates \fP\fIFLAG \fP default: false Enabling this flag will prevent the server from probing or downloading changes from the primary .TP \fBnotifies; also\-notify; notify \fP\fIHOSTS \fP default: \- The list of servers to notify in the event of a change. Currently only used by primaries when a dynamic update occurs. .TP \fBnotify\-auto \fP\fIFLAG \fP default: true Enabling this flag will cause \fInotify\fP messages to be sent to all name servers in the APEX. Disabling this flags causes the content of APEX to be ignored (\fIns\fP Records). .TP \fBnotify\-retry\-count \fP\fIINT \fP default: 5 Number of times \fIyadifa\fP tries to send a \fInotify\fP\&. (MIN: 0; MAX: 10) .TP \fBnotify\-retry\-period \fP\fIINT \fP default: 1 Time period in minutes between two \fInotify\fP attempts. (MIN: 1; MAX: 600) .TP \fBnotify\-retry\-period\-increase \fP\fIINT \fP default: 0 Increase of the time period in minutes between two \fInotify\fP attempts. (MIN: 0; MAX: 600) .TP \fBrrsig\-nsupdate\-allowed \fP\fIFLAG \fP default: false If this flag is set the server allows to edit RRSIG records using dynamic updates. .TP \fBsig\-validity\-interval \fP\fIDAYS \fP default: as main The number of days for which an automatic signature is valid. (MIN: 7 days; MAX: 30 days) .TP \fBsig\-validity\-regeneration \fP\fIHOURS \fP default: as main The signatures expiring in less than the indicated amount of hours will be recomputed. (MIN: 24 hours; MAX: 168 hours) .TP \fBsig\-validity\-jitter \fP\fISECONDS \fP default: as main The signature expiration validity jitter in seconds. (MIN: 0 sec; MAX: 86400 sec) .TP \fBtrue\-multiprimary; true\-multimaster \fP\fIFLAG \fP default: off Enabling this flag will make the server use \fIaxfr\fP when switching to a new primary .TP \fBtype \fP\fIENUM \fP default: \- Mandatory. Sets the type of zone : either \fIprimary\fP/\fImaster\fP or \fIsecondary\fP/\fIslave\fP\&. .RE .RS .PP .RE .TP \fB\fP Description of the logger outputs. .PP It contains a list descriptions of user\-defined outputs for the logger. Depending on the kind of output, the format is different. .PP The "name" is arbitrary and is used for identification in the . .br The "stream\-name" defines the output type (ie: a file name, a program output or syslog). .br The "arguments" are specific to the output type (ie: unix file access rights or syslog options and facilities). .br .PP .RS .TP .B * file output stream channel\-name file\-name access\-rights (octal). .TP .B * pipe to a program channel\-name "| shell command" channel\-name "| path\-to\-program program arguments >> append\-redirect" .TP .B * STDOUT, STDERR output stream channel\-name stdout channel\-name stderr .TP .B * syslog channel\-name syslog syslog\-facility .RE .RS .PP .RE .TP \fB\fP Description of the logger outputs sources. .PP Sets the output of a pre\-defined logger from yadifad. .br .PP The format of the line is: logger\-name output\-filter comma\-separated\-channel\-names .br .PP Filters are: .br \fIDEBUG7\fP, \fIDEBUG6\fP, \fIDEBUG5\fP, \fIDEBUG4\fP, \fIDEBUG3\fP, \fIDEBUG2\fP, \fIDEBUG1\fP, \fIDEBUG\fP, \fIINFO\fP, \fINOTICE\fP, \fIWARNING\fP, \fIERR\fP, \fICRIT\fP, \fIALERT\fP, \fIEMERG\fP .br .PP Additionally, there are: .br .PP .RS .TP .B * \fIALL\fP (or \&'\fI*\fP\&') meaning all the filters. .TP .B * \fIPROD\fP means all but the DEBUG filters. .RE .RS .PP The defined loggers are: .br .PP .RS .RE .TP \fBsystem\fP contains low level messages about the system such as memory allocation, threading, IOs, timers and cryptography, \&.\&.\&. .TP \fBdatabase\fP It contains messages about most lower\-level operations in the DNS database. ie: journal, updates, zone loading and sanitization, DNS message query resolution, \&.\&.\&.) .TP \fBdnssec\fP contains messages about lower\-level dnssec operations in the DNS database. ie: status, maintenance, verification, \&.\&.\&. .TP \fBserver\fP contains messages about operations in the DNS server. ie: start up, shutdown, configuration, transfers, various services status (database management, network management, DNS notification management, dynamic update management, resource rate limiting, \&.\&.\&.) .TP \fBzone\fP contains messages about the loading of a zone from a source (file parsing, transferred binary zone reading, \&.\&.\&.) .TP \fBstats\fP contains the statistics of the server. .TP \fBqueries\fP contains the queries on the server. Queries can be logged with the BIND and/or with the YADIFA format. .br .br \fBBIND format:\fP .br .br client sender\-ip#port: query: fqdn class type +SETDC (listen\-ip) .br .br \fBYADIFA format:\fP .br .br query [ id ] {+SETDC} fqdn class type (sender\-ip#port) .br .br where: .RS .TP id is the query message id .TP + means the message has the Recursion Desired flag set .TP S means the message is signed with a TSIG .TP E means the message is EDNS .TP T means the message was sent using TCP instead of UDP .TP D means the message has the DNSSEC OK flag set .TP C means the message has the Checking Disabled flag set .TP fqdn is the queried FQDN .TP class is the queried class .TP type is the queried type .TP sender\-ip is the IP of the client that sent the query .TP port is the port of the client that sent the query .TP listen\-ip is the listen network interface that received the message .RE .RS .PP Note that on YADIFA any unset flag is replaced by a \&'\-\&', on BIND only the \&'+\&' follows that rule. .RE .RE .RS .PP System operators will mostly be interested in the info and above messages of queries and stats, as well as the error and above messages of the other loggers. .PP .RE .PP .SS DNSSEC\-POLICY .PP There are 5 sections: .PP .TP \fB\fP The dnssec\-policy section binds up to four key suites and a denial mode. It is meant to be used as a dnssec\-policy parameter in a zone section. Usually two key\-suite will be given: one for a KSK and one for a ZSK. The denial mode can be either \&'nsec\&' either the name of a denial section. .PP .RS .TP \fBid \fP\fISTR \fP default: \- \fIid\fP of the dnssec\-policy section. .TP \fBdescription \fP\fISTR \fP default: \- Description for the dnssec\-policy section. .TP \fBkey\-suite \fP\fISTR \fP default: \- \fIid\fP of the \fIkey\-suite\fP to be used. Usually both a KSK and a ZSK suites are given. .TP \fBdenial \fP\fISTR \fP default: nsec \fIid\fP of the \fIdenial\fP to be used for \fInsec3\fP or the argument \&'nsec\&' to use \fInsec\fP\&. .RE .RS .PP .RE .TP \fB\fP The key\-suite section is used by dnssec policies and is meant to be referenced by a dnssec\-policy section. A key\-suite links a key definition (key\-template) with a deployment calendar (key\-roll). .PP .RS .TP \fBid \fP\fISTR \fP default: \- \fIid\fP of the key\-suite section. .TP \fBkey\-template \fP\fISTR \fP default: \- \fIid\fP of the \fIkey\-template\fP to be used. .TP \fBkey\-roll \fP\fISTR \fP default: \- \fIid\fP of the \fIkey\-roll\fP to be used. .RE .RS .PP .RE .TP \fB\fP The key\-roll section is used by dnssec policies and is meant to be referenced by a key\-suite section. It\&'s essentially a deployment calendar. Each event is computed relatively to another. Dates are chosen so that there is always a key in an active state. Please look at the examples as a misconfiguration could easily span the life of a key over several years. (e.g.: by too restrictive on the matching conditions) If the RELDATE format is being used, the first valid date matching the line is used. Usage of the RELDATE format is recommended over the RELTIME one. .PP .RS .TP \fBid \fP\fIRELDATE|RELTIME\fP default: \- \fIid\fP of the key\-roll section. .TP \fBgenerate \fP\fIRELDATE|RELTIME\fP default: \- Time when the key must be generated. Pre\-dated before so it\&'s active right now if it\&'s the first one. Always computed so that the next activation happens before the last deactivation. .TP \fBpublish \fP\fIRELDATE|RELTIME\fP default: \- Time when the key must be published in the zone. Relative to the generation. .TP \fBactivate \fP\fIRELDATE|RELTIME\fP default: \- Time when the key will be used for signing the zone or apex of the zone. Relative to the publication. .TP \fBinactive \fP\fIRELDATE|RELTIME\fP default: \- Time when the key will not be used anymore for signing. Relative to the activation. .TP \fBdelete \fP\fIRELDATE|RELTIME\fP default: \- Time when the key will be removed out of the zone. Relative to the deactivation. .RE .RS .PP .RE .TP \fB\fP The key\-template section is used by dnssec policies and is meant to be referenced by a key\-suite section. It contains the various parameters of a key for its generation. .PP .RS .TP \fBid \fP\fISTR \fP default: \- \fIid\fP of the key\-template section. .TP \fBksk \fP\fIFLAG \fP default: false When this flag is enabled a \fIksk\fP will be generated. When disabled a \fIzsk\fP will be generated. .TP \fBalgorithm \fP\fIENUM \fP default: 7 Sets the algorithm of the key. Supported values are: \fI’DSA’\fP; \fI3\fP; \fI’RSASHA1’\fP; \fI5\fP; \fI’NSEC3DSA’\fP; \fI6\fP; \fI’NSEC3RSASHA1’\fP; \fI7\fP; \fI’RSASHA256’\fP; \fI8\fP; \fI’RSASHA512’\fP; \fI10\fP; \fI’ECDSAP256SHA256’\fP; \fI13\fP; \fI’ECDSAP384SHA384’\fP; \fI14\fP\&. .RS .PP .RE .TP \fBsize \fP\fIINT \fP default: 0 The length of the key in bits (incompatible sizes will be rejected). (MIN: 0; MAX: 4096) .RE .RS .PP .RE .TP \fB\fP The denial section is used by dnssec policies and is meant to be referenced by a dnssec\-policy section. It is used to define the NSEC3 denial parameters of a dnssec policy. Policies using a NSEC denial don\&'t need to use this section. .PP .RS .TP \fBid \fP\fISTR \fP default: \- \fIid\fP of the denial section. .TP \fBsalt \fP\fIHEXSTR \fP default: empty A base16 encoded sequence of bytes used as the salt parameter of the NSEC3 chain. .TP \fBsalt\-length \fP\fIINT \fP default: 0 If the salt parameter isn\&'t set, generates a random salt parameter of that length. (MIN: 0; MAX: 255) .TP \fBiterations \fP\fIINT \fP default: 1 Iteration parameter of the NSEC3 chain. (MIN: 0; MAX: 65535) .TP \fBoptout \fP\fIFLAG \fP default: false Enables opt\-out coverage in the NSEC3 chain. When this flag is enabled, delegations which do not have a DS record will not be covered by an NSEC3 record. .RE .RS .PP .RE .PP .SH EXAMPLES .PP Examples of containers defined for a configuration file. .PP .TP .B * Main .RS .TP 1. Main section example .RS .PP .Vb
# Detach from the console (alias: daemonize) daemon off # Jail the application chroot off # The path of the log files (alias: chroot\-path) chrootpath "/chroot/yadifad" # The path of the log files (alias: log\-path) logpath "/var/log/yadifa" # The location of the pid file (alias: pid\-file) pidfile "/var/run/yadifa/yadifad.pid" # The path of the zone files (alias: data\-path) datapath "/var/lib/yadifa" # The path of the DNSSEC keys (alias: keys\-path) keyspath "/var/lib/yadifa/keys" # The path of the transfer and journaling files (AXFR & IXFR) (alias: xfr\-path) xfrpath "/var/lib/yadifa/xfr" # A string returned by a query of hostname. CH TXT # note: if you leave this out, the real hostname will be given back (alias: hostname\-chaos) hostname "server\-yadifad" # An ID returned by a query to id.server. CH TXT (alias: serverid\-chaos) serverid "yadifad\-01" # The version returned by a query to version.yadifa. CH TXT (alias: version\-chaos) version 2.5.0 # Set the maximum UDP packet size. # note: the packetsize cannot be less than 512 or more than 65535. # Typical choice is 4096. edns0\-max\-size 4096 # The maximum number of parallel TCP queries (max\-tcp\-connections) max\-tcp\-queries 100 # The minimum data rate for a TCP query (in bytes per second) tcp\-query\-min\-rate 512 # The user id to use (alias: user) uid yadifa # The group id to use (alias: group) gid yadifa # The DNS port \- any DNS query will use that port unless a specific value is used (alias: server\-port) port 53 # The interfaces to listen to. listen 127.0.0.1, 192.0.2.2, 192.0.2.130 port 8053, 2001:db8::2 # Type of querylog to use # 0: none # 1: yadifa # 2: bind # 3: both yadifa and bind queries\-log\-type 1 # Enable the collection and logging of statistics statistics on # Maximum number of seconds between two statistics lines statistics\-max\-period 60 # Drop queries with erroneous content # # answer\-formerr\-packets on answer\-formerr\-packets off # Maximum number of records in an AXFR packet. Set to 1 for compatibility # with very old name servers (alias: axfr\-max\-record\-by\-packet) axfr\-maxrecordbypacket 0 # Global Access Control rules # # Rules can be defined on network ranges, TSIG signatures, and ACL rules # simple queries: # # allow\-query any allow\-query !192.0.2.251,any # dynamic update of a zone # # allow\-update none allow\-update admins # dynamic update of a slave (forwarded to the primary) # # allow\-update\-forwarding none allow\-update\-forwarding admins,key abroad\-admin\-key # transfer of a zone (AXFR or IXFR) # # allow\-transfer any allow\-transfer transferer # notify of a change in the primary # # allow\-notify any allow\-notify primary,admins # If YADIFA has the controller enabled, allow control only for these # clients (none by default) allow\-control controller # overwrite the amount of CPUs detected by yadifad cpu\-count\-override 3 # set the number of threads to serve queries thread\-count\-by\-address 2
.Ve .RE .RE .RS .PP .RE .TP .B * Key .br TSIG\-key configuration .br .PP .RS .TP 1. Admin\-key key definition (the name is arbitrary) .RS .PP .Vb name abroad\-admin\-key algorithm hmac\-md5 secret WorthlessKeyForExample== .Ve .PP .RE .TP 2. primary\-secondary key definition (the name is arbitrary) .RS .PP .Vb name primary\-secondary algorithm hmac\-md5 secret PrimaryAndSecondaryKey== .Ve .RE .RE .RS .PP .RE .TP .B * ACL .br Access Control List definitions .br .PP .RS .TP 1. primary\-secondary key use .RS .PP .Vb transferer key primary\-secondary admins 192.0.2.0/24, 2001:db8::74 primary 192.0.2.53 localhost 127.0.0.0/8, ::1 controller key controller # the ACL for the controller MUST use a key .Ve .PP .RE .RE .RS .PP .RE .TP .B * NSID .br DNS NameServer IDentifier .br .PP .RS .TP 1. Example with ascii .RS .PP .Vb ascii belgium\-brussels\-01 .Ve .PP .RE .TP 2. Example with hex .RS .PP .Vb hex 00320201 .Ve .RE .RE .RS .PP .RE .TP .B * RRL .br Response Rate Limiting .PP .RS .RS .PP .RE .TP 1. Example .RS .PP .Vb # Number of identical responses per second before responses are being limited responses\-per\-second 5 # Number of errors per second before responses are being limited errors\-per\-second 5 # Random slip parameter slip 10 # If enabled, the rate limits are only logged and not enforced log\-only off # Mask applied to group the IPv4 clients ipv4\-prefix\-length 24 # Mask applied to group the IPv6 clients ipv6\-prefix\-length 56 # Rate limits are not subject to the following clients (aka whitelist) exempt\-clients none # Enable or disable the rate limit capabilities enabled yes .Ve .PP .RE .RE .RS .PP .RE .TP .B * Zone .PP .RS .TP 1. Primary domain zone config .RS .PP .Vb # This server is primary for the zone (mandatory) type primary # The domain name (mandatory) domain mydomain.eu # The zone file, relative to 'datapath' (mandatory for a primary) (alias: file\-name) file primaries/mydomain.eu # List of servers also notified of a change (beside the ones in the zone file) (alias: notifies, notify) also\-notify 192.0.2.84, 192.0.2.149 # Set the size of the journal file in KB (alias: journal\-size\-kb) journal\-size 8192 # Allow dynupdate for these ACL entries allow\-update admins # Allow AXFR/IXFR for these ACL entries allow\-transfer transferer # Use DNSSEC policies otherwise remove or put in remark line below dnssec\-policy 1 .Ve .PP .RE .TP 2. Slave domain zone config .RS .PP .Vb # This server is slave for that zone (mandatory) type slave # The domain name (mandatory) domain myotherdomain.eu # The address of the primary (mandatory for a slave, forbidden for a primary) (alias: primary) primaries 191.0.2.53 port 4053 key primary\-secondary # The zone file, relative to 'datapath'. file slaves/myotherdomain.eu # Accept notifes from these ACL entries allow\-notify primary .Ve .PP .RE .RE .RS .PP .RE .TP .B * DNSSEC\-Policy .PP DNSSEC\-Policy needs some extra sections: key\-suite, key\-roll, key\-template (and denial if NSEC3 is configured) .PP .RS .TP 1. dnssec\-policy example with all the needed sections .RS .PP example with NSEC3 .Vb id "1" description "Example of ZSK and KSK" denial "nsec3\-with\-salt\-on" key\-suite "zsk\-1024" key\-suite "ksk\-2048" .Ve example with NSEC .Vb id "2" description "Example of ZSK and KSK" denial nsec key\-suite "zsk\-1024" key\-suite "ksk\-2048" .Ve .PP .RE .TP 2. key\-suite .Vb id "ksk\-2048" key\-template "ksk\-2048" key\-roll "yearly\-schedule" id "zsk\-1024" key\-template "zsk\-1024" key\-roll "monthly\-schedule" .Ve .TP 3. key\-roll .Vb id "yearly\-schedule" generate 5 0 15 6 * * # this year (2018) 15/06 at 00:05 publish 10 0 15 6 * * # 00:10 activate 15 0 16 6 * * # 16/06 at 00:15 inactive 15 0 17 6 * * # (2019) 17/06 at 00:15 remove 15 11 18 6 * * # (2019) 18/06 at 11:15 id "monthly\-schedule" generate 5 0 * * tue 0 # 1 tuesday of the month at 00:05 publish 10 0 * * tue 0 # 00:10 activate 15 0 * * wed 0 # 1 wednesday of the month at 00:15 inactive 15 0 * * thu 0 # 1 thursday of the month at 00:15 remove 15 11 * * fri 0 # 1 friday of the month at 11:15 .Ve .TP 4. key\-template .Vb id "ksk\-2048" ksk true algorithm 8 size 2048 id "zsk\-1024" ksk false algorithm 8 size 1024 .Ve .TP 5. denial .Vb id "nsec3\-with\-salt\-on" salt "ABCD" algorithm 1 iterations 5 optout off .Ve .RS .PP .Vb id "nsec3\-with\-salt\-length\-on" salt\-length 4 algorithm 1 iterations 5 optout off .Ve .PP .RE .RE .RS .PP .RE .TP .B * Channels .PP Logging output\-channel configurations: .PP It contains a list of user\-defined outputs for the logger. .PP The "name" is arbitrary and is used for identification in the . .br The "stream\-name" defines the output type (ie: a file name, a program output or syslog). .br The "arguments" are specific to the output type (ie: unix file access rights or syslog options and facilities). .br .PP .RS .RS .PP .RE .TP 1. Example: YADIFA running as daemon channel definition. .br .RS .PP .Vb # name stream\-name arguments database database.log 0644 dnssec dnssec.log 0644 server server.log 0644 statistics statistics.log 0644 system system.log 0644 queries queries.log 0644 zone zone.log 0644 all all.log 0644 gziplog "|/usr/bin/gzip \\\- >> /var/log/yadifa.log.gz" syslog syslog user .Ve .PP .RE .TP 2. Example: YADIFA running in debug mode. .br This example shows the "stderr" and "stdout" which can also be used in the first example, but will output to the console. .RS .PP .Vb # name stream\-name arguments syslog syslog user stderr STDERR stdout STDOUT .Ve .PP .RE .RE .RS .PP .RE .TP .B * Loggers .PP Logging input configurations: .PP The "bundle" is the name of the section of YADIDA being logged, sources are : database, dnssec, queries, server, stats, system, zone. .br The "debuglevel" uses the same names as syslog. .br Additionally, "*" or "all" means all the levels; "prod" means all but the debug levels. .br .PP The "channels" are a comma\-separated list of channels. .PP .RS .TP 1. Example without syslog .RS .PP .Vb # bundle debuglevel channels database ALL database,all dnssec warning dnssec,all server INFO,WARNING,ERR,CRIT,ALERT,EMERG server,all stats prod statistics system * system,all queries * queries zone * zone,all .Ve .PP .RE .TP 2. Example with syslog .RS .PP .Vb # bundle debuglevel channels database ALL database,syslog dnssec warning dnssec,syslog server INFO,WARNING,ERR,CRIT,ALERT,EMERG server,syslog stats prod statistics, syslog system * system,syslog queries * queries,syslog zone * zone,syslog .Ve .RE .RE .RS .PP .RE .PP .SH SEE ALSO .PP \fIyadifad\fP(8) .PP .SH NOTES .PP Since unquoted leading whitespace is generally ignored in the yadifad.conf you can indent everything to taste. .PP .SH CHANGES .PP Please check the file README from the sources. .PP .SH VERSION .PP Version: 2.6.5 of 2023\-09\-06. .PP .SH MAILING LISTS .PP There exists a mailinglist for questions relating to any program in the yadifa package: .br .TP .B * \fByadifa\-users@mailinglists.yadifa.eu\fP .br for submitting questions/answers. .PP .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-users\fP .br for subscription requests. .PP If you would like to stay informed about new versions and official patches send a subscription request to via: .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-announcements\fP .PP (this is a readonly list). .PP .SH LICENSE AND COPYRIGHT .PP .TP Copyright (C)2011\-2023, EURid .br B\-1831 Diegem, Belgium .br \fBinfo@yadifa.eu\fP .PP .SH AUTHORS .PP Gery Van Emelen .br Email: \fBGery.VanEmelen@EURid.eu\fP .br Eric Diaz Fernandez .br Email: \fBEric.DiazFernandez@EURid.eu\fP .PP WWW: \fBhttp://www.EURid.eu\fP .PP .\" NOTE: This file is generated, DO NOT EDIT. yadifa-2.6.5-11201/doc/PaxHeaders.1636/yadifa.conf.man0000644000000000000000000000013214505005531017760 xustar000000000000000030 mtime=1695812441.309965961 30 atime=1695812445.806030354 30 ctime=1695812495.332739676 yadifa-2.6.5-11201/doc/yadifa.conf.man0000664000374500037450000000563414505005531017732 0ustar00signersigner00000000000000'\" t .\" Manual page created with latex2man on Tue Oct 13 12:59:04 2020 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW .nf .. .de Ve .ft R .fi .. .TH "YADIFA\-CONF" "5" "2023\-09\-06" "YADIFA " "YADIFA " .SH NAME .PP yadifa.conf is the configuration file for \fIyadifa\fP(8)\&. .PP .SH SYNOPSIS .PP ${SYSCONFDIR}/yadifa.conf .PP .SH DESCRIPTION .PP The configuration of yadifa has several containers: .PP .TP \fB\fP Controller module settings .TP \fB\fP TSIG keys .PP The configuration supports included files. .br example: include /home/yadifa/yadifa\-keys.conf .PP The configuration files can be nested. .PP The configuration consists of: .PP .TP .B * Container, which starts with \fB\fP and ends with \fB\fP .TP .B * Variable name .TP .B * 1 or 2 arguments .TP .B * Arguments can contain 1 or more comma separated values. .PP eg. .PP .Vb # variable argument variable value1 # variable argument1 argument2 variable value1 value2 # variable argument1 variable value1,value2 .Ve .PP .SH EXAMPLES .PP Examples of containers defined for a configuration file. .PP .TP .B * Controller .PP .Vb server "192.0.2.1 port 53" tsig\-key\-name controller .Ve .PP .TP .B * KEY, controller TSIG key definition (the name is arbitrary) .br .PP .Vb name controller algorithm hmac\-md5 secret WorthlessKeyForExample== .Ve .PP .SH FILES .PP .TP yadifa The name server remote client. .TP ${SYSCONFDIR}/yadifa.conf default conffile. .TP ${HOME}/.yadifa.rc default rcfile. .PP .TP yadifa.conf.5 This man page. .TP yadifa.8 Man page for yadifa\&. .PP .SH SEE ALSO .PP \fIyadifa.rc\fP(5) \fIyadifa\fP(8) .PP .SH NOTES .PP Since unquoted leading whitespace is generally ignored in the yadifa.conf you can indent everything to taste. .PP .SH CHANGES .PP Please check the file README from the sources. .PP .SH VERSION .PP Version: 2.6.5 of 2023\-09\-06 .PP .SH MAILING LISTS .PP There exists a mailinglist for questions relating to any program in the yadifa package: .br .TP .B * \fByadifa\-users@mailinglists.yadifa.eu\fP .br for submitting questions/answers. .PP .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-users\fP .br for subscription requests. .PP If you would like to stay informed about new versions and official patches send a subscription request to via: .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-announcements\fP .PP (this is a readonly list). .PP .SH LICENSE AND COPYRIGHT .PP .TP Copyright (C)2011\-2023, EURid .br B\-1831 Diegem, Belgium .br \fBinfo@yadifa.eu\fP .PP .SH AUTHORS .PP Gery Van Emelen .br Email: \fBGery.VanEmelen@EURid.eu\fP .br Eric Diaz Fernandez .br Email: \fBEric.DiazFernandez@EURid.eu\fP .PP WWW: \fBhttp://www.EURid.eu\fP .PP .\" NOTE: This file is generated, DO NOT EDIT. yadifa-2.6.5-11201/doc/PaxHeaders.1636/yadifa.rc.man0000644000000000000000000000013114505005531017436 xustar000000000000000029 mtime=1695812441.31896609 30 atime=1695812445.806030354 30 ctime=1695812495.334739705 yadifa-2.6.5-11201/doc/yadifa.rc.man0000664000374500037450000000561214505005531017405 0ustar00signersigner00000000000000'\" t .\" Manual page created with latex2man on Tue Oct 13 12:59:04 2020 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW .nf .. .de Ve .ft R .fi .. .TH "YADIFA\-RC" "5" "2023\-09\-06" "YADIFA " "YADIFA " .SH NAME .PP yadifa.rc is the configuration file for \fIyadifa\fP(8)\&. .PP .SH SYNOPSIS .PP ${HOME}/.yadifa.rc .PP .SH DESCRIPTION .PP The configuration of yadifa has several containers: .PP .TP \fB\fP Controller module settings .TP \fB\fP TSIG keys .PP The configuration supports included files. .br example: include /home/yadifa/yadifa\-keys.conf .PP The configuration files can be nested. .PP The configuration consists of: .PP .TP .B * Container, which starts with \fB\fP and ends with \fB\fP .TP .B * Variable name .TP .B * 1 or 2 arguments .TP .B * Arguments can contain 1 or more comma separated values. .PP eg. .PP .Vb # variable argument variable value1 # variable argument1 argument2 variable value1 value2 # variable argument1 variable value1,value2 .Ve .PP .SH EXAMPLES .PP Examples of containers defined for a configuration file. .PP .TP .B * Controller .PP .Vb server "192.0.2.1 port 53" tsig\-key\-name controller .Ve .PP .TP .B * KEY, controller key definition (the name is arbitrary) .PP .Vb name controller algorithm hmac\-md5 secret WorthlessKeyForExample== .Ve .PP .SH FILES .PP .TP yadifa The name server remote client. .TP ${SYSCONFDIR}/yadifa.conf default conf file. .TP ${HOME}/.yadifa.rc default rcfile. .PP .TP yadifa.rc.5 This man page. .TP yadifa.8 Man page for yadifa\&. .PP .SH SEE ALSO .PP \fIyadifa.conf\fP(5) \fIyadifa\fP(8) .PP .SH NOTES .PP Since unquoted leading whitespace is generally ignored in the \&.yadifa.rc you can indent everything to taste. .PP .SH CHANGES .PP Please check the file README from the sources. .PP .SH VERSION .PP Version: 2.6.5 of 2023\-09\-06 .PP .SH MAILING LISTS .PP There exists a mailinglist for questions relating to any program in the yadifa package: .br .TP .B * \fByadifa\-users@mailinglists.yadifa.eu\fP .br for submitting questions/answers. .PP .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-users\fP .br for subscription requests. .PP If you would like to stay informed about new versions and official patches send a subscription request to via: .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-announcements\fP .PP (this is a readonly list). .PP .SH LICENSE AND COPYRIGHT .PP .TP Copyright (C)2011\-2023, EURid .br B\-1831 Diegem, Belgium .br \fBinfo@yadifa.eu\fP .PP .SH AUTHORS .PP Gery Van Emelen .br Email: \fBGery.VanEmelen@EURid.eu\fP .br Eric Diaz Fernandez .br Email: \fBEric.DiazFernandez@EURid.eu\fP .PP WWW: \fBhttp://www.EURid.eu\fP .PP .\" NOTE: This file is generated, DO NOT EDIT. yadifa-2.6.5-11201/doc/PaxHeaders.1636/yakeyrolld.conf.man0000644000000000000000000000013114505005531020701 xustar000000000000000029 mtime=1695812441.32596619 30 atime=1695812445.806030354 30 ctime=1695812495.336739733 yadifa-2.6.5-11201/doc/yakeyrolld.conf.man0000664000374500037450000003600714505005531020652 0ustar00signersigner00000000000000'\" t .\" Manual page created with latex2man on Tue Oct 13 12:59:04 2020 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW .nf .. .de Ve .ft R .fi .. .TH "YAKEYROLLD\-CONF" "5" "2023\-09\-06" "YAKEYROLLD " "YADIFA " .SH NAME .PP yakeyrolld.conf \- configuration file for \fIyakeyrolld\fP(8)\&. .PP .SH SYNOPSIS .PP ${SYSCONFDIR}/yakeyrolld.conf .PP .SH DESCRIPTION .PP The configuration of yakeyrolld is consistent in a text file that can optionally include others. The general structure is a a sequence of containers: a sequence of lines of text starting with a and ending with a . Each line between these delimitters is in the form: variable\-name value. The format of the value is determined by the type of the variable. .PP There are 7 types: .PP .TP \fIFQDN\fP A fully\-qualified domain name text string. e.g.: www.eurid.eu. .TP \fIGID\fP Group ID. (Can be a number or a name) .TP \fIHOST(S)\fP A (list of) host(s). A host is defined by an IP (v4 or v6) and can be followed by the word `port\&' and a port number. Elements of the list are separated by a `,\&' or a `;\&'\&. .TP \fIINTEGER / INT\fP A base\-ten integer. .TP \fIPATH / FILE\fP A file or directory path. i.e.: "/var/plans". .TP \fISTRING / STR\fP A text string. Double quotes can be used but are not mandatory. Without quotes the string will be taken from the first non\-blank charater to the last non\-blank character. .TP \fIUID\fP User ID. (Can be a number or a name) .PP .SS STANDARD SECTIONS .PP There are 9 sections: .PP .TP \fB\fP General container, contains all the configuration parameters needed to start up yakeyrolld\&. .RS .TP \fBdomain \fP\fI FQDN \fP default: \&. Names one domain to manage, can be used up to 200 times. In yadifad.conf, each of these domains must have rrsig\-nsupdate\-allowed enabled in their respective section. .TP \fBlog\-path \fP\fI PATH \fP default: ${localstatedir}/log/yakeyrolld The directory that will contain the log files. .TP \fBkeys\-path \fP\fI PATH \fP default: ${localstatedir}/zones/keys The directory the name server uses to read zone key file. .TP \fBplan\-path \fP\fI PATH \fP default: ${localstatedir}/plans The directory of the step files. .TP \fBpid\-path \fP\fI PATH \fP default: ${localstatedir}/run The directory of the pid file. .TP \fBpid\-file \fP\fI STRING \fP default: yakeyrolld.pid The name of the pid file. .TP \fBgenerate\-from \fP\fI STRING \fP default: "now" For plan generation, when to start the plan, can be overridden by the command line. .TP \fBgenerate\-until \fP\fI STRING \fP default: "+1y" For plan generation, when to stop the plan, can be overridden by the command line. .TP \fBserver \fP\fI HOST \fP default: 127.0.0.1 The address of the name server for queries and dynamic updates. .TP \fBtimeout \fP\fI INT \fP default: 3 The number of seconds spent trying to communicate with the primary until it\&'s considered a time\-out. .TP \fBttl \fP\fI INT \fP default: 600 The default \fIttl\fP value to use when generating records. .TP \fBupdate\-apply\-verify\-retries \fP\fI INT \fP default: 60 If an update isn\&'t checked successfully, retries that many times. .TP \fBupdate\-apply\-verify\-retries\-delay \fP\fI INT \fP default: 1 Waits that many seconds between two update apply tries. .TP \fBmatch\-verify\-retries \fP\fI INT \fP default: 60 If a match test fails, retries that many times. .TP \fBmatch\-verify\-retries\-delay \fP\fI INT \fP default: 1 Waits that many seconds between two match test tries. .TP \fBpolicy \fP\fI STRING \fP default: undefined The name of the policy to use when generating the plan. .TP \fBuid \fP\fI UID \fP default: 0 The uid to swich to. This should match the name server\&'s. .TP \fBgid \fP\fI GID \fP default: 0 The gid to swich to. This should match the name server\&'s. .RE .RS .PP .RE .TP \fB\fP Description of dnssec policies. .PP .RS .TP \fBid \fP\fISTR \fP default: \- \fIid\fP of the dnssec\-policy section. .TP \fBdescription \fP\fISTR \fP default: \- Description for the dnssec\-policy section. .TP \fBkey\-suite \fP\fISTR \fP default: \- \fIid\fP of the \fIkey\-suite\fP to be used. .RE .RS .PP .RE .TP \fB\fP Description of the key\-suites needed if \&'dnssec policies\&' are used. .PP .RS .TP \fBid \fP\fISTR \fP default: \- \fIid\fP of the key\-suite section. .TP \fBkey\-template \fP\fISTR \fP default: \- \fIid\fP of the \fIkey\-template\fP to be used. .TP \fBkey\-roll \fP\fISTR \fP default: \- \fIid\fP of the \fIkey\-roll\fP to be used. .RE .RS .PP .RE .TP \fB\fP TSIG keys .PP .RS .TP \fBalgorithm \fP\fIENUM \fP default: \- Mandatory. Sets the algorithm of the key. .RS .PP Supported values are: .RS .RE .TP \fB \fP\fB \fP\fB \fP\fIhmac\-md5\fP .TP \fB \fP\fB \fP\fB \fP\fIhmac\-sha1\fP .TP \fB \fP\fB \fP\fB \fP\fIhmac\-sha224\fP .TP \fB \fP\fB \fP\fB \fP\fIhmac\-sha256\fP .TP \fB \fP\fB \fP\fB \fP\fIhmac\-sha384\fP .TP \fB \fP\fB \fP\fB \fP\fIhmac\-sha512\fP .RE .RS .PP (the algorithm names are case insensitive)} .RE .TP \fBname \fP\fIFQDN \fP default: \- Mandatory. Sets the name of the key. .TP \fBsecret \fP\fITEXT \fP default: \- Mandatory. Sets the value of the key. BASE64 encoded. .RE .RS .PP .RE .TP \fB\fP Description of the key\-rolls needed if \&'dnssec policies\&' are used. .PP .RS .TP \fBid \fP\fISTR \fP default: \- \fIid\fP of the key\-roll section. .TP \fBgenerate \fP\fISTR \fP default: \- Time when the key must be generated. .TP \fBpublish \fP\fISTR \fP default: \- Time when the key must be published in the zone. .TP \fBactivate \fP\fISTR \fP default: \- Time when the key will be used for signing the zone or apex of the zone. .TP \fBinactive \fP\fISTR \fP default: \- Time when the key will not be used anymore for signing. .TP \fBdelete \fP\fISTR \fP default: \- Time when the key will be removed out of the zone. .RE .RS .PP .RE .TP \fB\fP Description of the key\-templates needed if \&'dnssec policies\&' are used. .PP .RS .TP \fBid \fP\fISTR \fP default: \- \fIid\fP of the key\-roll section. .TP \fBgenerate \fP\fISTR \fP default: \- Time when the key must be generated. .TP \fBpublish \fP\fISTR \fP default: \- Time when the key must be published in the zone. .TP \fBactivate \fP\fISTR \fP default: \- Time when the key will be used for signing the zone or apex of the zone. .TP \fBinactive \fP\fISTR \fP default: \- Time when the key will not be used anymore for signing. .TP \fBdelete \fP\fISTR \fP default: \- Time when the key will be removed out of the zone. .RE .RS .PP .RE .TP \fB\fP Description of the logger outputs. .PP It contains a list descriptions of user\-defined outputs for the logger. Depending on the kind of output, the format is different. .PP The "name" is arbitrary and is used for identification in the . .br The "stream\-name" defines the output type (i.e.: a file name, a program output or syslog). .br The "arguments" are specific to the output type (i.e.: unix file access rights or syslog options and facilities). .br .PP .RS .TP .B * file output stream channel\-name file\-name access\-rights (octal). .TP .B * pipe to a program channel\-name "| shell command" channel\-name "| path\-to\-program program arguments >> append\-redirect" .TP .B * STDOUT, STDERR output stream channel\-name stdout channel\-name stderr .TP .B * syslog channel\-name syslog syslog\-facility .RE .RS .PP .RE .TP \fB\fP Description of the logger outputs sources. .PP Sets the output of a pre\-defined logger for yakeyrolld. .br .PP The format of the line is: logger\-name output\-filter comma\-separated\-channel\-names .br .PP Filters are: .br \fIDEBUG7\fP, \fIDEBUG6\fP, \fIDEBUG5\fP, \fIDEBUG4\fP, \fIDEBUG3\fP, \fIDEBUG2\fP, \fIDEBUG1\fP, \fIDEBUG\fP, \fIINFO\fP, \fINOTICE\fP, \fIWARNING\fP, \fIERR\fP, \fICRIT\fP, \fIALERT\fP, \fIEMERG\fP .br .PP Additionally, there are: .br .PP .RS .TP .B * \fIALL\fP (or \&'\fI*\fP\&') meaning all the filters. .TP .B * \fIPROD\fP means all but the DEBUG filters. .RE .RS .PP The defined loggers are: .br .PP .RS .RE .TP \fBkeyroll\fP contains general messages about the keyroll .TP \fBdnssec\fP contains messages about DNSSEC\-related computations during the generation. .TP \fBsystem\fP contains low level messages about the system such as memory allocation, threading, IOs, timers and cryptography, \&.\&.\&. .RE .RS .PP System operators will mostly be interested in the info and above messages of the keyroll and dnssec loggers. .PP .RE .PP .SH EXAMPLES .PP Examples of containers defined for a configuration file. .PP .TP .B * Main .RS .TP 1. Config with includes .RS .PP .Vb # start yakeyrolld.conf container include /etc/yakeyrolld/conf.d/local.conf # end yakeyrolld.conf container .Ve .PP .RE .TP 2. Main without includes .RS .PP .Vb # Detach from the console (alias: daemonize) daemon off # The directory to use for the log files log\-path "/var/log/yakeyrolld" # The directory that yadifad uses to load private keys keys\-path "/var/lib/yadifa/keys" # The directory to use to store the plans plan\-path "/var/lib/yadifa/plans" generate\-from "now" generate\-until "+1y" server 127.0.0.1 policy "keyroll\-policy" .Ve .RE .RE .RS .PP .RE .TP .B * Key .br TSIG\-key configuration .br .PP .RS .TP 1. Admin\-key key definition (the name is arbitrary) .RS .PP .Vb name abroad\-admin\-key algorithm hmac\-md5 secret WorthlessKeyForExample== .Ve .PP .RE .TP 2. primary\-secondary key definition .RS .PP .Vb name primary\-secondary algorithm hmac\-md5 secret PrimaryAndSecondaryKey== .Ve .RE .RE .RS .PP .RE .TP .B * DNSSEC\-Policy .PP DNSSEC\-Policy needs some extra sections: key\-suite, key\-roll, key\-template .PP .RS .TP 1. dnssec\-policy example with all the needed sections .Vb id "keyroll\-policy" description "Example of ZSK and KSK" key\-suite "zsk\-1024" key\-suite "ksk\-2048" .Ve .RS .PP .RE .TP 2. key\-suite .Vb id "ksk\-2048" key\-template "ksk\-2048" key\-roll "yearly\-calendar" id "zsk\-1024" key\-template "zsk\-1024" key\-roll "monthly\-calendar" .Ve .TP 3. key\-roll .Vb id "yearly\-calendar" generate 11 10 * 1 mon 1 # Januay, Monday of the second week at 10:11 publish 11 10 * 1 tue * # following Tuesday at 10:11 activate 11 10 * 1 wed * # following Wednesday at 10:11 inactive 11 10 * 1 mon * # following Monday, a year after, at 10:11 remove 11 10 * 1 wed * # following Wednesday at 10:11 id "monthly\-calendar" generate 17 10 * * mon 0 # 1st monday the month at 10:17 publish 17 10 * * tue * # following tuesday at 10:17 activate 17 10 * * wed * # following wednesday at 10:17 inactive 17 10 * * wed * # following wednesday at 10:17 (one week after the activation) remove 17 10 * * thu * # following thursday at 10:17 .Ve .TP 4. key\-template .Vb id "ksk\-2048" ksk true algorithm RSASHA512 size 2048 id "zsk\-1024" ksk false algorithm RSASHA512 size 1024 .Ve .RS .PP .RE .RE .RS .PP .RE .TP .B * Channels .PP Logging output\-channel configurations: .PP It contains a list of user\-defined outputs for the logger. .PP The "name" is arbitrary and is used for identification in the . .br The "stream\-name" defines the output type (i.e.: a file name, a program output or syslog). .br The "arguments" are specific to the output type (i.e.: unix file access rights or syslog options and facilities). .br .PP .RS .RS .PP .RE .TP 1. Example: logging channels definition. .br .RS .PP .Vb # name stream\-name arguments keyroll keyroll.log 0644 dnssec dnssec.log 0644 system system.log 0644 all all.log 0644 .Ve .PP .RE .RE .RS .PP .RE .TP .B * Loggers .PP Logging input configurations: .PP The "bundle" is the name of the section of yakeyroll being logged, sources are : database, dnssec, queries, server, stats, system, zone. .br The "debuglevel" uses the same names as syslog. .br Additionally, "*" or "all" means all the levels; "prod" means all but the debug levels. .br .PP The "channels" are a comma\-separated list of channels. .PP .RS .TP 1. Example logger configuration .RS .PP .Vb # bundle debuglevel channels keyroll prod keyroll,all dnssec prod dnssec,all system prod system,all .Ve .PP .RE .RE .RS .PP .RE .PP .SH SEE ALSO .PP \fIyakeyrolld\fP(8) .PP .SH NOTES .PP Since unquoted leading whitespace is generally ignored in the yadifad.conf you can indent everything to taste. .PP .SH CHANGES .PP Please check the file README from the sources. .PP .SH VERSION .PP Version: 2.6.5 of 2023\-09\-06. .PP .SH MAILING LISTS .PP There exists a mailinglist for questions relating to any program in the yadifa package: .br .TP .B * \fByadifa\-users@mailinglists.yadifa.eu\fP .br for submitting questions/answers. .PP .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-users\fP .br for subscription requests. .PP If you would like to stay informed about new versions and official patches send a subscription request to via: .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-announcements\fP .PP (this is a readonly list). .PP .SH LICENSE AND COPYRIGHT .PP .TP Copyright (C)2011\-2023, EURid .br B\-1831 Diegem, Belgium .br \fBinfo@yadifa.eu\fP .PP .SH AUTHORS .PP Gery Van Emelen .br Email: \fBGery.VanEmelen@EURid.eu\fP .br Eric Diaz Fernandez .br Email: \fBEric.DiazFernandez@EURid.eu\fP .PP WWW: \fBhttp://www.EURid.eu\fP .PP .\" NOTE: This file is generated, DO NOT EDIT. yadifa-2.6.5-11201/doc/PaxHeaders.1636/yadifad.man0000644000000000000000000000013214505005531017200 xustar000000000000000030 mtime=1695812441.319966104 30 atime=1695812445.806030354 30 ctime=1695812495.338739762 yadifa-2.6.5-11201/doc/yadifad.man0000664000374500037450000001050614505005531017144 0ustar00signersigner00000000000000'\" t .\" Manual page created with latex2man on Tue Oct 13 12:59:04 2020 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW .nf .. .de Ve .ft R .fi .. .TH "YADIFAD" "8" "2023\-09\-06" "YADIFA " "YADIFA " .SH NAME .PP YADIFAD \- an authoritative Internet domain name server. .PP .SH SYNOPSIS .PP yadifad [\fB\-\-config|\-c\fP\fI configfile\fP] [\fB\-\-daemon|\-d\fP] [\fB\-u\fP\fI uid\fP] [\fB\-g\fP\fI gid\fP] [\fB\-V\fP] [\fB\-h\fP] .PP .SH DESCRIPTION .PP yadifad is a Domain Name System (DNS) server, part of the YADIFA distribution from EURid vzw/asbl. The latest version of YADIFA can be found on: .br .ce 100 \fBhttp://www.yadifa.eu/download\fP .ce 0 .PP yadifad reads the zone files from yadifad.conf, and starts up an authoritative name server. It listens to UDP and TCP DNS queries and returns answers from its own database. .PP yadifad knows the main DNS protocols: .TP .B * AXFR .TP .B * IXFR .TP .B * DNSSEC .TP .B * DNS Update .TP .B * NOTIFY .PP yadifad works only with 1 CLASS: .PP .TS tab(&); l l lw(2cm). T{ Class T}&T{ Value T}&T{ Definition T} T{ T} T{ IN T}&T{ 1 T}&T{ Internet class T} .TE .PP yadifad supports following TYPES: .PP .TS tab(&); l l l. T{ Type T}&T{ Value T}&T{ Defining RFC T} T{ T} T{ A T}&T{ 1 T}&T{ 1035 T} T{ AAAA T}&T{ 28 T}&T{ 3596 T} T{ CNAME T}&T{ 5 T}&T{ 1035 T} T{ DNSKEY T}&T{ 48 T}&T{ 4034 T} T{ DS T}&T{ 43 T}&T{ 4034 T} T{ HINFO T}&T{ 12 T}&T{ 1035 T} T{ MX T}&T{ 15 T}&T{ 1035 T} T{ NAPTR T}&T{ 35 T}&T{ 3403 T} T{ NS T}&T{ 2 T}&T{ 1035 T} T{ NSEC T}&T{ 47 T}&T{ 4034 T} T{ NSEC3 T}&T{ 50 T}&T{ 5155 T} T{ NSEC3PARAM T}&T{ 51 T}&T{ 5155 T} T{ PTR T}&T{ 12 T}&T{ 1035 T} T{ RRSIG T}&T{ 46 T}&T{ 4034 T} T{ SOA T}&T{ 6 T}&T{ 1035 T} T{ SRV T}&T{ 33 T}&T{ 2782 T} T{ SSHFP T}&T{ 44 T}&T{ 4255 T} T{ TXT T}&T{ 16 T}&T{ 1035 T} .TE .PP Other tyes and pseudo resource records: .PP .TS tab(&); l l l. T{ Type T}&T{ Value T}&T{ Defining RFC T} T{ T} T{ * T}&T{ 255 T}&T{ 1035 T} T{ AXFR T}&T{ 252 T}&T{ 1035 T} T{ IXFR T}&T{ 251 T}&T{ 1035 T} T{ OPT T}&T{ 41 T}&T{ 6891 T} .TE .PP .SH OPTIONS .PP .TP [\fB\-\-config|\-c\fP\fI configfile\fP] Another config file will be used. .TP [\fB\-\-daemon|\-d\fP] Starts the name server in daemon mode (default) .TP [\fB\-\-uid|\-u\fP\fI uid\fP] Starts the name server with the given uid. .TP [\fB\-\-gid|\-g\fP\fI gid\fP] Starts the name server with the given gid. .PP .TP [\fB\-V\fP] Shows version information. .TP [\fB\-\-help|\-h\fP] Shows a help text .PP .SH SIGNALS .PP .TP SIGHUP reloads the zone and key sections in the configuration file and reloads the zone file(s) with incremented serial number, and close all log files and reopens them. .TP SIGINT shutdowns the server .TP SIGTERM (see SIGINT) .PP .SH CONFIGURATION .PP The yadifad.conf itself is mandatory, but can be empty. No options is needed for using yadifad DNS name server. .PP The yadifad configuration options can be found in yadifad.conf.5 man page. A complete description is provided in the YADIFA 2.6.5 Reference Manual (YM26). .PP .SH FILES .PP .TP yadifad.conf The YADIFA configuration file. .TP yadifad The name server binary. .TP yadifad.8 This man page. .TP yadifad.conf.5 Configuration man page for YADIFA. .PP .SH SEE ALSO .PP \fIyadifad.conf\fP(5) .PP .SH REQUIREMENTS .PP .TP OpenSSL yadifad requires OpenSSL version 1.1.1 or later. .PP .SH CHANGES .PP Please check the README file from the source code. .PP .SH VERSION .PP Version: 2.6.5 of 2023\-09\-06. .PP .SH MAILING LISTS .PP There is a mailinglist for questions relating to any program in the yadifa package: .br .TP .B * \fByadifa\-users@mailinglists.yadifa.eu\fP .br for submitting questions/answers. .PP .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-users\fP .br for subscription requests. .PP If you would like to stay informed about new versions and official patches send a subscription request to via: .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-announcements\fP .PP (this is a read\-only list). .PP .SH LICENSE AND COPYRIGHT .PP .TP Copyright (C)2011\-2023, EURid vzw/asbl .br B\-1831 Diegem, Belgium .br \fBinfo@yadifa.eu\fP .PP .SH AUTHORS .PP Gery Van Emelen .br Email: \fBGery.VanEmelen@EURid.eu\fP .br Eric Diaz Fernandez .br Email: \fBEric.DiazFernandez@EURid.eu\fP .PP WWW: \fBhttp://www.EURid.eu\fP .PP .\" NOTE: This file is generated, DO NOT EDIT. yadifa-2.6.5-11201/doc/PaxHeaders.1636/yadifa.man0000644000000000000000000000013114505005531017033 xustar000000000000000030 mtime=1695812441.315966047 30 atime=1695812445.806030354 29 ctime=1695812495.34073979 yadifa-2.6.5-11201/doc/yadifa.man0000664000374500037450000001632114505005531017001 0ustar00signersigner00000000000000'\" t .\" Manual page created with latex2man on Tue Oct 13 12:59:04 2020 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW .nf .. .de Ve .ft R .fi .. .TH "YADIFA" "8" "2023\-09\-06" "YADIFA " "YADIFA " .SH NAME .PP YADIFA is an utility for controlling YADIFAD .PP .SH SYNOPSIS .PP yadifa \fBmodule\fP [\fB\-\-config|\-c\fP\fI configfile\fP] [\fB\-\-server|\-s\fP\fI host\fP] [\fB@host \fP] [\fB\-\-port|\-p\fP\fI port\fP] [\fB\-K\fP\fI key\-name\fP] [\fB\-\-version|\-V\fP] [\fB\-h\fP] [\fB\-\-verbose|\-v\fP] \fB[\-t]\fP\fI command\fP [\fB[\-q]\fP\fI zone\fP] .PP .SH DESCRIPTION .PP yadifa controls the operation of yadifad with its control module (ctrl), part of the YADIFA distribution from EURid vzw/asbl. The latest version of YADIFA can be found on: .br .ce 100 \fBhttp://www.yadifa.eu/download\fP .ce 0 .PP yadifa communicates with a name server over a TCP connection. Messages are authenticated using a TSIG signature. The key is a secret shared between client and server. The key can be defined using a section both in the client and the server. Additionally, the client accepts a full definition as a command line option. Note that using authentication is mandatory when using the control module. .PP For details about the key, see the manual or the TSIG section below. .PP .SH MODULES .PP .TP .B * \fBctrl\fP \fIcommand\fP Controls yadifad\&. .PP .SH SIMPLE USAGE .PP For controlling yadifad a command can be: .PP .SS NORMAL USE CASE .PP yadifa ctrl @server \-t command \-q argument .PP .SS FRIENDLIER USE CASE .PP yadifa ctrl @server command argument .PP .TP \fBctrl\fP Module used for controlling yadifad .TP \fBserver\fP Is the IP address of the name server to control. If no "server" argument is given yadifa.rc will be checked. .TP \fBcommand\fP Is the command to be invoked .TP \fIargument\fP Depending the command this can be e.g. a domain name. .PP .SS EXAMPLE .PP yadifa ctrl @127.0.0.1 freeze somedomain.eu .PP .SH OPTIONS .PP .TP [\fB\-\-config|\-c \fP\fIconfigfile\fP] Another config file will be used. .TP [\fB\-\-server|\-s \fP\fIhost\fP] | [\fB @host \fP] Host is the remote server to operate. e.g.: .RS .TP yadifa \-\-server 192.0.2.1 .TP yadifa @192.0.2.1 .RE .RS .PP By default the DNS port is used. A port can be specified along with the IP address: e.g.: .RS .RE .TP yadifa \-\-server "192.0.2.1 port 5353" .TP yadifa @"192.0.2.1 port 5353" .RE .RS .PP .RE .TP [\fB\-\-port|\-p \fP\fIport\fP] Changes the DNS port. (default: 53) .TP [\fB\-K \fP\fIkey\-name\fP] Name of the key to be used for the controller. It needs to have been defined using a section. (default: \&'ctrl\-key\&') .TP [\fB\-y \fP\fIhmac\-algorithm:key\-name:base64\-key\fP] Definition of the key to be used for the controller. .RS .TP \fIhmac\-algorithm\fP Optional, can be: hmac\-md5, hmac\-sha1, hmac\-sha224, hmac\-256, hmac\-384, hmac\-512. (default: hmac\-md5) .TP \fIkey\-name\fP is the fqdn of the key. .TP \fIbase64\-key\fP is a base64 encoding of the key bytes. .RE .RS .PP e.g.: .RS .RE .TP \-y hmac\-sha1:our\-shared\-secret:ThisIsASecretShared= .TP \-y our\-shared\-secret:ThisIsASecretShared= .RE .RS .PP .RE .TP [\fB\-\-verbose|\-v\fP] Verbose output. .TP [\fB\-\-version|\-V\fP] Show version information. .TP [\fB\-\-help|\-h\fP] Show a help text .PP .SH COMMANDS .PP .TP [\fB\-t\fP] \fBcfgreload\fP Reload the settings from the configuration file on disk. .TP [\fB\-t\fP] \fBfreeze\fP [\fB\-q\fP] zone Disables dynamic updates to a zone. .TP [\fB\-t\fP] \fBfreezeall\fP [\fB\-q\fP] zone Disables dynamic updates to every zone currently loaded. .PP .TP [\fB\-t\fP] \fBloglevel\fP \fIlevel\fP Sets the log level to the given value (0\-15), 6 = INFO, 15 = ALL. .TP [\fB\-t\fP] \fBlogreopen\fP Close all log files and reopens them. .TP [\fB\-t\fP] \fBnotify\fP Sends notifies to slaves of these zones. .PP .TP [\fB\-t\fP] \fBquerylog\fP [\fIenable|disable\fP] Sets the log for queries on or off (default: enable). .PP .TP [\fB\-t\fP] \fBreload\fP [\fB\-q\fP] zone Triggers the loading of the zone file(s) if the serial number is incremented. .PP .TP [\fB\-t\fP] \fBshutdown\fP Shuts down the server. .PP .TP [\fB\-t\fP] \fBsync\fP [\fB\-q\fP] [\fIzone\fP] [\fBclean\fP] Write the zone to disk and optionally cleans up the journal. .PP .TP [\fB\-t\fP] \fBthaw\fP [\fB\-q\fP] [\fIzone\fP] Enables dynamic updates to a zone. .TP [\fB\-t\fP] \fBthawall\fP Enables dynamic updates to every zone. .TP [\fB\-t\fP] \fBunfreeze\fP [\fB\-q\fP] [\fIzone\fP] Enables dynamic updates to a zone. .PP .TP [\fB\-t\fP] \fBunfreezeall\fP Enables dynamic updates to every zone. .PP .TP [\fB\-t\fP] \fBzonecfgreload\fP [\fB\-q \fP\fIzone\fP] Reload the zone information in the configuration file and reload the zone file(s) with increased serial number. .PP .SH TSIG KEYS .PP TSIG keys are used for authentication of messages. .br Their use is mandatory in the controller module. .br .PP Several digest algorithms are supported for the TSIG key: .RS .TP .B * hmac\-md5 .TP .B * hmac\-sha1 .TP .B * hmac\-sha224 .TP .B * hmac\-sha256 .TP .B * hmac\-sha384 .TP .B * hmac\-sha512 .RE .RS .PP .RE .PP Several methods can be used to generate the base64\-encoded sequence of bytes for the secret: .PP .TP .B * %openssl rand \-base64 32 .TP .B * %dd if=/dev/random count=1 bs=32 2>/dev/null|base64 .br .TP .B * %dd if=/dev/urandom count=1 bs=32 2>/dev/null|base64 .br .PP e.g.: .br .PP .Vb #!/bin/sh # TSIG key generation example # can a key_algorithm="hmac\-sha256" key_name="secretkey" key_secret=$(openssl rand \-base64 32) if [ ! "x$1" == "x" ] then key_name="$1" fi echo "# Encoded for the yadifa command\-line: \-y $key_algorithm:$key_name:$key_secret" echo echo "" echo "algorithm $key_algorithm" echo "name $key_name" echo "secret $key_secret" echo "" .Ve .PP .SH FILES .PP .TP yadifa The name server remote client. .TP ${SYSCONFDIR}/yadifa.conf default yadifa configuration file. .TP ${HOME}/.yadifa.rc default rcfile. .PP .TP yadifa.conf.5 Configuration man page for yadifa\&. .TP yadifa.rc.5 Configuration man page for yadifa\&. .TP yadifa.8 This man page. .PP .SH SEE ALSO .PP \fIyadifa.conf\fP(5) \fIyadifa.rc\fP(5) \fIyadifad\fP(8) .PP .SH REQUIREMENTS .PP .TP OpenSSL yadifad requires OpenSSL version 1.1.1 or later. .PP .SH CHANGES .PP Please check the ChangeLog file from the sources code. .PP .SH VERSION .PP Version: 2.6.5 of 2023-09-06. .PP .SH MAILINGLIST .PP There is a mailinglist for questions relating to any program in the yadifa package: .br .PP .TP .B * \fByadifa\-users@mailinglists.yadifa.eu\fP .br for submitting questions/answers. .PP .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-users\fP .br for subscription requests. .PP If you would like to stay informed about new versions and official patches send a subscription request to via: .PP .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-announcements\fP .PP (this is a read\-only list). .PP .SH LICENSE AND COPYRIGHT .PP .TP Copyright (C)2011\-2023, EURid .br B\-1831 Diegem, Belgium .br \fBinfo@yadifa.eu\fP .PP .SH AUTHORS .PP Gery Van Emelen .br Email: \fBGery.VanEmelen@EURid.eu\fP .br Eric Diaz Fernandez .br Email: \fBEric.DiazFernandez@EURid.eu\fP .PP WWW: \fBhttp://www.EURid.eu\fP .PP .\" NOTE: This file is generated, DO NOT EDIT. yadifa-2.6.5-11201/doc/PaxHeaders.1636/yakeyrolld.man0000644000000000000000000000013214505005531017756 xustar000000000000000030 mtime=1695812441.306965918 30 atime=1695812445.806030354 30 ctime=1695812495.342739819 yadifa-2.6.5-11201/doc/yakeyrolld.man0000664000374500037450000001560314505005531017725 0ustar00signersigner00000000000000'\" t .\" Manual page created with latex2man on Tue Oct 13 12:59:04 2020 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW .nf .. .de Ve .ft R .fi .. .TH "YAKEYROLLD" "8" "2023\-09\-06" "YAKEYROLLD " "YADIFA " .SH NAME .PP YAKEYROLLD is an utility for genrating a sequence of KSK and ZSK for a zone. .PP .SH SYNOPSIS .PP yakeyrolld \fBcommand \fP[\fIargument\fP] .PP .SH DESCRIPTION .PP The yakeyrolld program generates a sequence of \fIKSK\fP and \fIZSK\fP for a zone, with all the steps of their lifecycles. .PP yakeyrolld is part of the YADIFA distribution from EURid vzw/asbl. The latest version of YADIFA can be found on: .br .ce 100 \fBhttp://www.yadifa.eu/download\fP .ce 0 .PP .SH LIFECYCLE .PP A lifecyle for a key has several steps: .PP .TP .B * Time of creation .TP .B * Time of publication .TP .B * Time of activation .TP .B * Time of de\-activation .TP .B * Time of un\-publication. .PP These times are determined using a cron\-like schedule. .br .PP For all these steps, it computes the following: .PP .TP .B * The expected \fIDNSSEC\fP and \fIRRSIG\fP \fIDNSSEC\fP records on the primary before the step is started .TP .B * The \fIZSK\fP files to add .TP .B * The \fIZSK\fP files to remove .TP .B * The \fIDNSSEC\fP and \fIRRSIG\fP \fIDNSKEY\fP records to add .TP .B * The \fIDNSKEY\fP and \fIRRSIG\fP \fIDNSKEY\fP records to remove .TP .B * The expected \fIDNSKEY\fP and \fIRRSIG\fP \fIDNSKEY\fP records on the dns primary after the step has been completed. .PP Each step is stored as a file. The file contains fields like: .PP .TP \fBepochus \fP An integer with the epoch of the step expressed in microseconds. .TP \fBdateus \fP A user\-friendly date text matching the epochus field. .TP \fBactions \fP A list of actions expected to happen on the step (informational). .TP \fBdebug \fP A text meant to help understand the step (informational). .TP \fBupdate \fP Each entry is a dynamic update command to be sent to the server. .TP \fBexpect \fP Each entry defines one record expected to be in the zone on the server prior to executing the current step. .TP \fBendresult \fP Each entry defines one record expected to be in the zone on the server after the step has been executed. .TP \fBadd \fP Defines a key file to create in \fIkeys\-path\fP\&. .TP \fBdel \fP Names a key file to delete from \fIkeys\-path\fP\&. .PP .SH COMMANDS .PP .TP \fB\-\-help|\-h \fP Shows the help .TP \fB\-\-version|\-V \fP Prints the version of the software .TP \fB\-\-config|\-c \fP \fIconfigfile\fP Sets the configuration file to use .TP \fB\-\-mode|\-m \fP \fIgenerate | play | playloop | print | print\-json \fP Sets the program mode .TP \fB\-\-domain \fP \fIfqdn\fP The domain name .TP \fB\-\-path|\-p \fP \fIdirectory\fP The directory where to store the keys .TP \fB\-\-server|\-s \fP \fIaddress\fP The address of the server .TP \fB\-\-ttl|\-t \fP \fIseconds\fP The \fIttl\fP to use for both \fIdnskey\fP and \fIrrsig\fP records .TP \fB\-\-explain \fP prints the planned schedule .TP \fB\-\-reset \fP start by removing all the keys and create a new KSK and a new ZSK. The server will not be queried. .TP \fB\-\-policy \fP Name of the policy to use .TP \fB\-\-from \fP \fItime\fP The lower time bound covered by the plan (now) .TP \fB\-\-until \fP \fItime\fP The upper time bound covered by the plan (+1y) .TP \fB\-\-dryrun \fP Do not write files to disk, do not send updates to the server .TP \fB\-\-wait \fP Wait for yadifad to answer before starting to work (default) .TP \fB\-\-nowait \fP Do not wait for yadifad to answer before starting to work .TP \fB\-\-daemon \fP Daemonise the program for supported modes (default) .TP \fB\-\-nodaemon \fP Do not daemonise the program .TP \fB\-\-noconfirm \fP Do not ask for confirmation before doing a data reset .PP .SH USAGE .PP The yakeyrolld daemon writes key files in the yadifad keys directory and pushes DNSKEY and RRSIG records with a dynamic update. .br Zones managed by the keyroll needs to have the rrsig\-nsupdate\-allowed setting enabled ( section). .br In generation mode, the daemon needs access to both the plan and private keys directory. .br For all other modes, the private keys directory is ignored. .br When not doing any kind of generation, they should not be kept on the machine. Their encrypted backup sitting in a safe place. .br .PP .TP \fBInitialisation\fP .br .br Destroys all current data that could exist and starts from nothing. Creates all the steps of the rolls for the next two years. Creates all the private keys in a separate directory. .br The directory that contains the private key files is required for this command as private keys will be added. .br .br yakeyrolld \fB\-m \fP\fIgenerate\fP \fB\-\-until \fP\fI+1y\fP \fI\-\-reset\fP .br .br .TP \fBRenewal\fP .br .br In order to extend a plan further, simply do another generation. .br The operation loads the current plan, extends it to cover the new limit date and saves the updated modified version back on disk. .br Previously stored private keys may be used to generate signatures and new private keys may be added. .br Because of this, the directory that contains the private key files is required for this command. .br .br yakeyrolld \fB\-m \fP\fIgenerate\fP \fB\-\-until \fP\fI+1y\fP .br .br .TP \fBPlan calendar\fP .br .br Details of the current plan can be printed on stdout using: .br .br yakeyrolld \fB\-m \fP\fIprint\fP .br The output format of that command isn\&'t meant to be parsed by a program. .br For a script, use instead: .br .br yakeyrolld \fB\-m \fP\fIprint\-json\fP .br .br .TP \fBDaemon\fP .br .br To start the rolling the keys and pushing them to the server, use: .br .br yakeyrolld \fB\-m \fP\fIplayloop\fP .br .PP .SH FILES .PP .TP ${SYSCONFDIR}/yakeyrolld.conf The default yakeyrolld configuration file. .PP .TP yakeyrolld.conf.5 Configuration man page for yakeyrolld\&. .PP .SH SEE ALSO .PP \fIyakeyrolld.conf\fP(5) .PP .SH REQUIREMENTS .PP .TP OpenSSL yakeyrolld requires OpenSSL version 1.1.1 or later. .PP .SH CHANGES .PP Please check the ChangeLog file from the sources code. .PP .SH VERSION .PP Version: 2.6.5 of 2023\-09\-06. .PP .SH MAILINGLIST .PP There is a mailinglist for questions relating to any program in the yadifa package: .br .PP .TP .B * \fByadifa\-users@mailinglists.yadifa.eu\fP .br for submitting questions/answers. .PP .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-users\fP .br for subscription requests. .PP If you would like to stay informed about new versions and official patches send a subscription request to via: .PP .TP .B * \fBhttp://www.yadifa.eu/mailing\-list\-announcements\fP .PP (this is a read\-only list). .PP .SH LICENSE AND COPYRIGHT .PP .TP Copyright (C)2011\-2023, EURid .br B\-1831 Diegem, Belgium .br \fBinfo@yadifa.eu\fP .PP .SH AUTHORS .PP Gery Van Emelen .br Email: \fBGery.VanEmelen@EURid.eu\fP .br Eric Diaz Fernandez .br Email: \fBEric.DiazFernandez@EURid.eu\fP .PP WWW: \fBhttp://www.EURid.eu\fP .PP .\" NOTE: This file is generated, DO NOT EDIT. yadifa-2.6.5-11201/PaxHeaders.1636/var0000644000000000000000000000013214505005617015055 xustar000000000000000030 mtime=1695812495.391740521 30 atime=1695812499.082793384 30 ctime=1695812495.391740521 yadifa-2.6.5-11201/var/0000775000374500037450000000000014505005617015074 5ustar00signersigner00000000000000yadifa-2.6.5-11201/var/PaxHeaders.1636/zones0000644000000000000000000000013214505005617016213 xustar000000000000000030 mtime=1695812495.387740464 30 atime=1695812499.082793384 30 ctime=1695812495.387740464 yadifa-2.6.5-11201/var/zones/0000775000374500037450000000000014505005617016232 5ustar00signersigner00000000000000yadifa-2.6.5-11201/var/zones/PaxHeaders.1636/masters0000644000000000000000000000013214505005617017671 xustar000000000000000030 mtime=1695812495.402740678 30 atime=1695812499.082793384 30 ctime=1695812495.402740678 yadifa-2.6.5-11201/var/zones/masters/0000775000374500037450000000000014505005617017710 5ustar00signersigner00000000000000yadifa-2.6.5-11201/var/zones/masters/PaxHeaders.1636/0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.00000644000000000000000000000032414505005533024212 xustar0000000000000000122 path=yadifa-2.6.5-11201/var/zones/masters/0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone 30 mtime=1695812443.215993259 30 atime=1695812443.215993259 30 ctime=1695812495.394740564 yadifa-2.6.5-11201/var/zones/masters/0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.i0000664000374500037450000000107214505005533025622 0ustar00signersigner00000000000000$TTL 86400 ; 24 hours $ORIGIN 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 86400 IN SOA localhost. root.localhost. ( 20120201 ; Serial 3h ; Refresh 15 ; Retry 1w ; Expire 3h ; Minimum ) 86400 IN NS localhost. 1 86400 IN PTR localhost. yadifa-2.6.5-11201/var/zones/masters/PaxHeaders.1636/0.0.127.in-addr.arpa.zone0000644000000000000000000000013214505005533023704 xustar000000000000000030 mtime=1695812443.216993274 30 atime=1695812443.216993274 30 ctime=1695812495.396740593 yadifa-2.6.5-11201/var/zones/masters/0.0.127.in-addr.arpa.zone0000664000374500037450000000110314505005533023641 0ustar00signersigner00000000000000$TTL 86400 ; 24 hours $ORIGIN 0.0.127.IN-ADDR.ARPA. 0.0.127.IN-ADDR.ARPA. 86400 IN SOA localhost. root.localhost. ( 20120201 ; Serial 3h ; Refresh 15 ; Retry 1w ; Expire 3h ; Minimum ) 86400 IN NS localhost. 1 86400 IN PTR localhost. yadifa-2.6.5-11201/var/zones/masters/PaxHeaders.1636/localhost6.zone0000644000000000000000000000013214505005533022716 xustar000000000000000030 mtime=1695812443.214993245 30 atime=1695812443.214993245 30 ctime=1695812495.398740621 yadifa-2.6.5-11201/var/zones/masters/localhost6.zone0000664000374500037450000000072514505005533022664 0ustar00signersigner00000000000000$TTL 86400 ; 24 hours $ORIGIN localhost6. localhost6. 86400 IN SOA localhost6. root.localhost6. ( 20120201 ; serial 3H ; refresh 15 ; retry 1w ; expire 3h ; minimum ) 86400 IN NS localhost6. 86400 IN AAAA ::1 yadifa-2.6.5-11201/var/zones/masters/PaxHeaders.1636/localhost.zone0000644000000000000000000000013114505005533022627 xustar000000000000000030 mtime=1695812443.213993231 30 atime=1695812443.213993231 29 ctime=1695812495.40074065 yadifa-2.6.5-11201/var/zones/masters/localhost.zone0000664000374500037450000000070214505005533022571 0ustar00signersigner00000000000000$TTL 86400 ; 24 hours $ORIGIN localhost. localhost. 86400 IN SOA localhost. root.localhost. ( 20120201 ; serial 3H ; refresh 15 ; retry 1w ; expire 3h ; minimum ) 86400 IN NS localhost. 86400 IN A 127.0.0.1 yadifa-2.6.5-11201/var/zones/masters/PaxHeaders.1636/somedomain.eu.zone0000644000000000000000000000013214505005533023403 xustar000000000000000030 mtime=1695812443.215993259 30 atime=1695812443.215993259 30 ctime=1695812495.402740678 yadifa-2.6.5-11201/var/zones/masters/somedomain.eu.zone0000664000374500037450000000064714505005533023354 0ustar00signersigner00000000000000;; Example domain $TTL 86400 ; 24 hours $ORIGIN somedomain.eu. somedomain.eu. 86400 IN SOA ns1.somedomain.eu. info.somedomain.eu. 1 3600 1800 3600000 600 86400 IN MX 10 mail.somedomain.eu. 86400 IN NS ns1.somedomain.eu. ns1.somedomain.eu. 86400 IN A 192.0.2.2 mail.somedomain.eu. 86400 IN A 192.0.2.3 www.somedomain.eu. 86400 IN A 192.0.2.4 yadifa-2.6.5-11201/var/PaxHeaders.1636/Makefile.in0000644000000000000000000000013214505005555017200 xustar000000000000000030 mtime=1695812461.491254998 30 atime=1695812489.721659314 30 ctime=1695812495.390740507 yadifa-2.6.5-11201/var/Makefile.in0000664000374500037450000004677714505005555017167 0ustar00signersigner00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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@ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ subdir = var DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(dist_zonesmasters_DATA) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/eurid.m4 $(top_srcdir)/m4/yadifa.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = 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 = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac 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__installdirs = "$(DESTDIR)$(zonesmastersdir)" DATA = $(dist_zonesmasters_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) 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@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCOPTIMISATIONFLAGS = @CCOPTIMISATIONFLAGS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DNSCORE = @DNSCORE@ DNSDB = @DNSDB@ DNSLG = @DNSLG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAS_ACL_SUPPORT = @HAS_ACL_SUPPORT@ HAS_BFD_DEBUG_SUPPORT = @HAS_BFD_DEBUG_SUPPORT@ HAS_BIG_ENDIAN = @HAS_BIG_ENDIAN@ HAS_BUILD_TIMESTAMP = @HAS_BUILD_TIMESTAMP@ HAS_CC_ADDRESS_SANITIZER_CHECK = @HAS_CC_ADDRESS_SANITIZER_CHECK@ HAS_CC_ANSI = @HAS_CC_ANSI@ HAS_CC_ANSI_ALIAS = @HAS_CC_ANSI_ALIAS@ HAS_CC_CATCH_UNDEFINED_BEHAVIOR = @HAS_CC_CATCH_UNDEFINED_BEHAVIOR@ HAS_CC_DWARF2 = @HAS_CC_DWARF2@ HAS_CC_DWARF3 = @HAS_CC_DWARF3@ HAS_CC_DWARF4 = @HAS_CC_DWARF4@ HAS_CC_EXCEPTIONS = @HAS_CC_EXCEPTIONS@ HAS_CC_G = @HAS_CC_G@ HAS_CC_G3 = @HAS_CC_G3@ HAS_CC_M32 = @HAS_CC_M32@ HAS_CC_M64 = @HAS_CC_M64@ HAS_CC_MISSING_FIELD_INITIALIZERS = @HAS_CC_MISSING_FIELD_INITIALIZERS@ HAS_CC_NO_IDENT = @HAS_CC_NO_IDENT@ HAS_CC_NO_OMIT_FRAME_POINTER = @HAS_CC_NO_OMIT_FRAME_POINTER@ HAS_CC_PEDANTIC = @HAS_CC_PEDANTIC@ HAS_CC_RDYNAMIC = @HAS_CC_RDYNAMIC@ HAS_CC_SANITIZE_ADDRESS = @HAS_CC_SANITIZE_ADDRESS@ HAS_CC_STACK_PROTECTOR = @HAS_CC_STACK_PROTECTOR@ HAS_CC_STD_C11 = @HAS_CC_STD_C11@ HAS_CC_STD_C99 = @HAS_CC_STD_C99@ HAS_CC_STD_GNU11 = @HAS_CC_STD_GNU11@ HAS_CC_STD_GNU99 = @HAS_CC_STD_GNU99@ HAS_CC_TUNE_NATIVE = @HAS_CC_TUNE_NATIVE@ HAS_CC_WALL = @HAS_CC_WALL@ HAS_CC_XC99 = @HAS_CC_XC99@ HAS_CLOSE_EX_REF = @HAS_CLOSE_EX_REF@ HAS_CTRL = @HAS_CTRL@ HAS_DNSSEC_TOOLS = @HAS_DNSSEC_TOOLS@ HAS_DYNUPDATE_SUPPORT = @HAS_DYNUPDATE_SUPPORT@ HAS_ECDSA_SUPPORT = @HAS_ECDSA_SUPPORT@ HAS_EDDSA = @HAS_EDDSA@ HAS_EVENT_DYNAMIC_MODULE = @HAS_EVENT_DYNAMIC_MODULE@ HAS_FULL_ASCII7 = @HAS_FULL_ASCII7@ HAS_KEYGEN = @HAS_KEYGEN@ HAS_LIBC_MALLOC_DEBUG_SUPPORT = @HAS_LIBC_MALLOC_DEBUG_SUPPORT@ HAS_LITTLE_ENDIAN = @HAS_LITTLE_ENDIAN@ HAS_LOCK_DEBUG_SUPPORT = @HAS_LOCK_DEBUG_SUPPORT@ HAS_LOGDIR = @HAS_LOGDIR@ HAS_LOG_PID = @HAS_LOG_PID@ HAS_LOG_THREAD_ID = @HAS_LOG_THREAD_ID@ HAS_LOG_THREAD_TAG = @HAS_LOG_THREAD_TAG@ HAS_MALLOC_DEBUG_SUPPORT = @HAS_MALLOC_DEBUG_SUPPORT@ HAS_MASTER_SUPPORT = @HAS_MASTER_SUPPORT@ HAS_MEMALIGN_ISSUES = @HAS_MEMALIGN_ISSUES@ HAS_MUTEX_DEBUG_SUPPORT = @HAS_MUTEX_DEBUG_SUPPORT@ HAS_NON_AA_AXFR_SUPPORT = @HAS_NON_AA_AXFR_SUPPORT@ HAS_NSEC3_SUPPORT = @HAS_NSEC3_SUPPORT@ HAS_NSEC_SUPPORT = @HAS_NSEC_SUPPORT@ HAS_NSID_SUPPORT = @HAS_NSID_SUPPORT@ HAS_RRL_SUPPORT = @HAS_RRL_SUPPORT@ HAS_RRSIG_MANAGEMENT_SUPPORT = @HAS_RRSIG_MANAGEMENT_SUPPORT@ HAS_SYNC_BUILTINS = @HAS_SYNC_BUILTINS@ HAS_SYSTEMD_RESOLVED_AVOIDANCE = @HAS_SYSTEMD_RESOLVED_AVOIDANCE@ HAS_TESTS = @HAS_TESTS@ HAS_TOOLS = @HAS_TOOLS@ HAS_TRACK_ZONES_DEBUG_SUPPORT = @HAS_TRACK_ZONES_DEBUG_SUPPORT@ HAS_TSIG_SUPPORT = @HAS_TSIG_SUPPORT@ HAS_YADIFA = @HAS_YADIFA@ HAS_ZALLOC_DEBUG_SUPPORT = @HAS_ZALLOC_DEBUG_SUPPORT@ HAS_ZALLOC_STATISTICS_SUPPORT = @HAS_ZALLOC_STATISTICS_SUPPORT@ HAS_ZALLOC_SUPPORT = @HAS_ZALLOC_SUPPORT@ HAVE_RECVMMSG = @HAVE_RECVMMSG@ HAVE_SENDMMSG = @HAVE_SENDMMSG@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IS_BSD_FAMILY = @IS_BSD_FAMILY@ IS_DARWIN_GE14 = @IS_DARWIN_GE14@ IS_DARWIN_OS = @IS_DARWIN_OS@ IS_LINUX_FAMILY = @IS_LINUX_FAMILY@ IS_SOLARIS_FAMILY = @IS_SOLARIS_FAMILY@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL = @OPENSSL@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZDB_HAS_DNSSEC_SUPPORT = @ZDB_HAS_DNSSEC_SUPPORT@ 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_CXX = @ac_ct_CXX@ 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@ 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@ logdir = @logdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 zonesmastersdir = $(localstatedir)/zones/masters dist_zonesmasters_DATA = zones/masters/0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone zones/masters/0.0.127.in-addr.arpa.zone zones/masters/localhost6.zone zones/masters/localhost.zone zones/masters/somedomain.eu.zone all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(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) --gnu var/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu var/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_zonesmastersDATA: $(dist_zonesmasters_DATA) @$(NORMAL_INSTALL) @list='$(dist_zonesmasters_DATA)'; test -n "$(zonesmastersdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(zonesmastersdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(zonesmastersdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(zonesmastersdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(zonesmastersdir)" || exit $$?; \ done uninstall-dist_zonesmastersDATA: @$(NORMAL_UNINSTALL) @list='$(dist_zonesmasters_DATA)'; test -n "$(zonesmastersdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(zonesmastersdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(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 $(DATA) installdirs: for dir in "$(DESTDIR)$(zonesmastersdir)"; 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-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_zonesmastersDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook 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 Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_zonesmastersDATA .MAKE: install-am install-data-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-hook install-dist_zonesmastersDATA 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-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am uninstall-dist_zonesmastersDATA all: release: profile: debug: features: install-data-hook: @for d in zones/masters zones/slaves zones/xfr zones/keys run log/yadifad log/yakeyrolld plans ; \ do \ mkdir -p "$(DESTDIR)/$(localstatedir)/$$d"; \ chmod 755 "$(DESTDIR)/$(localstatedir)/$$d"; \ done mkdir -p "$(DESTDIR)/$(logdir)" chmod 755 "$(DESTDIR)/$(logdir)" # 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: yadifa-2.6.5-11201/var/PaxHeaders.1636/Makefile.am0000644000000000000000000000013214505005533017163 xustar000000000000000030 mtime=1695812443.204993101 30 atime=1695812461.433254167 30 ctime=1695812495.392740535 yadifa-2.6.5-11201/var/Makefile.am0000664000374500037450000000475714505005533017142 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ACLOCAL_AMFLAGS = -I m4 zonesmastersdir = $(localstatedir)/zones/masters dist_zonesmasters_DATA = zones/masters/0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.zone zones/masters/0.0.127.in-addr.arpa.zone zones/masters/localhost6.zone zones/masters/localhost.zone zones/masters/somedomain.eu.zone all: release: profile: debug: features: install-data-hook: @for d in zones/masters zones/slaves zones/xfr zones/keys run log/yadifad log/yakeyrolld plans ; \ do \ mkdir -p "$(DESTDIR)/$(localstatedir)/$$d"; \ chmod 755 "$(DESTDIR)/$(localstatedir)/$$d"; \ done mkdir -p "$(DESTDIR)/$(logdir)" chmod 755 "$(DESTDIR)/$(logdir)" yadifa-2.6.5-11201/PaxHeaders.1636/sbin0000644000000000000000000000013214505005617015220 xustar000000000000000030 mtime=1695812495.723745276 30 atime=1695812499.082793384 30 ctime=1695812495.723745276 yadifa-2.6.5-11201/sbin/0000775000374500037450000000000014505005617015237 5ustar00signersigner00000000000000yadifa-2.6.5-11201/sbin/PaxHeaders.1636/yadifad0000644000000000000000000000013214505005617016621 xustar000000000000000030 mtime=1695812495.718745204 30 atime=1695812499.083793398 30 ctime=1695812495.718745204 yadifa-2.6.5-11201/sbin/yadifad/0000775000374500037450000000000014505005617016640 5ustar00signersigner00000000000000yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/contributions0000644000000000000000000000013214505005617021523 xustar000000000000000030 mtime=1695812495.502742111 30 atime=1695812499.083793398 30 ctime=1695812495.502742111 yadifa-2.6.5-11201/sbin/yadifad/contributions/0000775000374500037450000000000014505005617021542 5ustar00signersigner00000000000000yadifa-2.6.5-11201/sbin/yadifad/contributions/PaxHeaders.1636/20170225-libressl-detection-and-fix.pa0000644000000000000000000000013114505005533030135 xustar000000000000000030 mtime=1695812443.336994992 30 atime=1695812445.781029996 29 ctime=1695812495.48874191 yadifa-2.6.5-11201/sbin/yadifad/contributions/20170225-libressl-detection-and-fix.patch0000664000374500037450000000656414505005533030612 0ustar00signersigner00000000000000From 553b9d7d2a3c7cf56d1f02d73eb37cbd5a29e9df Mon Sep 17 00:00:00 2001 From: Bernard Spil Date: Sat, 25 Feb 2017 12:32:24 +0100 Subject: [PATCH] Fix build issues with LibreSSL - Check LIBRESSL_VERSION_NUMBER in addition to OpenSSL > 1.1 LibreSSL forked from OpenSSL 1.0.1f and does not have all features from 1.1.0. --- lib/dnscore/src/dnskey_dsa.c | 4 ++-- lib/dnscore/src/dnskey_ecdsa.c | 2 +- lib/dnscore/src/dnskey_rsa.c | 2 +- lib/dnscore/src/tsig.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/dnscore/src/dnskey_dsa.c b/lib/dnscore/src/dnskey_dsa.c index 43fe450..54b93f0 100644 --- a/lib/dnscore/src/dnskey_dsa.c +++ b/lib/dnscore/src/dnskey_dsa.c @@ -70,7 +70,7 @@ #error "OPENSSL_VERSION_NUMBER not defined" #endif -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) /* * Backward-compatible interface for 0.9.x @@ -226,7 +226,7 @@ dnskey_dsa_genkey(u32 size) int err; DSA* dsa; -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) dsa = DSA_generate_parameters(size, NULL,0, NULL, NULL, NULL, NULL); #else dsa = DSA_new(); diff --git a/lib/dnscore/src/dnskey_ecdsa.c b/lib/dnscore/src/dnskey_ecdsa.c index 1638c3b..1ed19d4 100644 --- a/lib/dnscore/src/dnskey_ecdsa.c +++ b/lib/dnscore/src/dnskey_ecdsa.c @@ -79,7 +79,7 @@ #define DNSKEY_ALGORITHM_ECDSAP256SHA256_NID NID_X9_62_prime256v1 #define DNSKEY_ALGORITHM_ECDSAP384SHA384_NID NID_secp384r1 -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) #define SSL_FIELD_GET(st_,f_) if(f_ != NULL) { *f_ = st_->f_; } #define SSL_FIELD_SET(st_,f_) if(f_ != NULL) { BN_free(st_->f_); st_->f_ = f_; } diff --git a/lib/dnscore/src/dnskey_rsa.c b/lib/dnscore/src/dnskey_rsa.c index f52f84f..00529ea 100644 --- a/lib/dnscore/src/dnskey_rsa.c +++ b/lib/dnscore/src/dnskey_rsa.c @@ -64,7 +64,7 @@ #define MODULE_MSG_HANDLE g_system_logger -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) #define SSL_FIELD_GET(st_,f_) if(f_ != NULL) { *f_ = st_->f_; } #define SSL_FIELD_SET(st_,f_) if(f_ != NULL) { BN_free(st_->f_); st_->f_ = f_; } diff --git a/lib/dnscore/src/tsig.c b/lib/dnscore/src/tsig.c index 21d7e9d..391e72a 100644 --- a/lib/dnscore/src/tsig.c +++ b/lib/dnscore/src/tsig.c @@ -233,7 +233,7 @@ tsig_hmac_t tsig_hmac_allocate() { -#if OPENSSL_VERSION_NUMBER < 0x10100000L // ie: 0.9.x +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) // ie: 0.9.x HMAC_CTX *hmac; ZALLOC_OR_DIE(HMAC_CTX*, hmac, HMAC_CTX, GENERIC_TAG); HMAC_CTX_init(hmac); @@ -257,7 +257,7 @@ tsig_hmac_free(tsig_hmac_t t) { HMAC_CTX *hmac = (HMAC_CTX*)t; yassert(hmac != NULL); -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) HMAC_CTX_cleanup(hmac); ZFREE(t, HMAC_CTX); #else @@ -268,7 +268,7 @@ tsig_hmac_free(tsig_hmac_t t) void tsig_hmac_reset(tsig_hmac_t t) { HMAC_CTX *hmac = (HMAC_CTX*)t; -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) HMAC_CTX_cleanup(hmac); HMAC_CTX_init(hmac); #else yadifa-2.6.5-11201/sbin/yadifad/contributions/PaxHeaders.1636/20190112-escape-character-fix.patch0000644000000000000000000000013214505005533027471 xustar000000000000000030 mtime=1695812443.334994963 30 atime=1695812445.781029996 30 ctime=1695812495.490741939 yadifa-2.6.5-11201/sbin/yadifad/contributions/20190112-escape-character-fix.patch0000664000374500037450000000306114505005533027433 0ustar00signersigner00000000000000From 2ad56c317484b6303c0b3d8618263a77108f8a46 Mon Sep 17 00:00:00 2001 From: Jeremy Zerfas <46632101+JZerf@users.noreply.github.com> Date: Sat, 12 Jan 2019 15:43:51 -0600 Subject: [PATCH] Fix escape character searching loop to work properly Fix the escape character searching loop so that it isn't ran when the string is empty. --- lib/dnscore/src/format.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/dnscore/src/format.c b/lib/dnscore/src/format.c index a3225c5..dfad0d4 100644 --- a/lib/dnscore/src/format.c +++ b/lib/dnscore/src/format.c @@ -1914,7 +1914,7 @@ osprint_rdata(output_stream* os, u16 type, const u8* rdata_pointer, u16 rdata_si const char *character_to_check = (char *)rdata_pointer; const char * const limit = character_to_check + pstring_len; output_stream_write_u8(os, '"'); /* Opening double quote for the string. */ - do + for(; character_to_check < limit; character_to_check++) { if(memchr("\"\n\\", *character_to_check, 3)) { @@ -1927,7 +1927,6 @@ osprint_rdata(output_stream* os, u16 type, const u8* rdata_pointer, u16 rdata_si rdata_pointer += preceding_span_len + 1; } } - while(++character_to_check < limit); /* Output any remaining characters in the Pascal string if rdata_pointer didn't * reach limit (because it ended with a character that didn't have to be escaped). yadifa-2.6.5-11201/sbin/yadifad/contributions/PaxHeaders.1636/20190112-txt-record-parsing-improvemen0000644000000000000000000000013214505005533030330 xustar000000000000000030 mtime=1695812443.337995006 30 atime=1695812445.781029996 30 ctime=1695812495.492741967 yadifa-2.6.5-11201/sbin/yadifad/contributions/20190112-txt-record-parsing-improvements.patch0000664000374500037450000002010614505005533031736 0ustar00signersigner00000000000000From 8c06fbe679554b6d18326717ce7b7a661e85befc Mon Sep 17 00:00:00 2001 From: Jeremy Zerfas Date: Sat, 12 Jan 2019 14:29:04 -0600 Subject: [PATCH] Make string parsing and TXT record writing more robust Improves string parsing so that text between string delimiters is handled correctly when it contains string delimiter characters that have been escaped or when it ends with escape characters. Changes TXT records to be written as quoted strings and characters are now escaped when needed. --- lib/dnscore/src/format.c | 89 +++++++++++++++++++++++++--------------- lib/dnscore/src/parser.c | 42 ++++++++++++------- 2 files changed, 83 insertions(+), 48 deletions(-) diff --git a/lib/dnscore/src/format.c b/lib/dnscore/src/format.c index 6baba24..a3225c5 100644 --- a/lib/dnscore/src/format.c +++ b/lib/dnscore/src/format.c @@ -1884,53 +1884,76 @@ osprint_rdata(output_stream* os, u16 type, const u8* rdata_pointer, u16 rdata_si return total; } - - - - - - - - - - - - - - - - - - - - case TYPE_TXT: - - - { - u8 c; + /* rdata_pointer should be a chain of Pascal strings and the chain should be EXACTLY + * rdata_size bytes long. Check the chain to make sure the last Pascal string in the + * chain ends at exactly rdata_size bytes, if it doesn't then consider that an error and + * return an error code. + */ + u32 pstring_chain_size = 0; + while(pstring_chain_size < rdata_size) + { + pstring_chain_size += 1 + rdata_pointer[pstring_chain_size]; + if(pstring_chain_size > rdata_size) + { + return INCORRECT_RDATA; + } + } while(rdata_size > 0) { - c = *rdata_pointer++; - - if(c > 0) + /* Check each character in the Pascal string to see if it is one of the characters + * which needs to be escaped (double quotes, line feeds, and backslashes currently) + * when used in a zone file quoted string. If we find a character which needs to be + * escaped, then output any characters that preceded it which we didn't output + * already, the escape character, and that character which needed to be escaped. + */ + const u8 pstring_len = *rdata_pointer++; + const char *character_to_check = (char *)rdata_pointer; + const char * const limit = character_to_check + pstring_len; + output_stream_write_u8(os, '"'); /* Opening double quote for the string. */ + do { - c = MIN(c, rdata_size); + if(memchr("\"\n\\", *character_to_check, 3)) + { + const u8 preceding_span_len = character_to_check - (char *)rdata_pointer; + + output_stream_write(os, rdata_pointer, preceding_span_len); + output_stream_write_u8(os, '\\'); + output_stream_write_u8(os, *character_to_check); - output_stream_write(os, rdata_pointer, c); - output_stream_write(os, (u8*)" ", 1); + rdata_pointer += preceding_span_len + 1; + } + } + while(++character_to_check < limit); + + /* Output any remaining characters in the Pascal string if rdata_pointer didn't + * reach limit (because it ended with a character that didn't have to be escaped). + */ + if((char *)rdata_pointer < limit) + { + output_stream_write(os, rdata_pointer, limit - (char *)rdata_pointer); + rdata_pointer += limit - (char *)rdata_pointer; } - rdata_size--; - rdata_pointer += c; - rdata_size -= c; + output_stream_write_u8(os, '"'); /* Closing double quote for the string. */ + + rdata_size -= 1 + pstring_len; /* Decrement by the FULL Pascal string size. */ + + /* If there are still more Pascal strings in the chain, then output a space to + * separate them from the one that was just output. + */ + if(rdata_size > 0) + { + output_stream_write_u8(os, ' '); + } } return SUCCESS; } + case TYPE_CTRL_ZONERELOAD: { /* ONE NAME record */ diff --git a/lib/dnscore/src/parser.c b/lib/dnscore/src/parser.c index 82e7ad4..13720be 100644 --- a/lib/dnscore/src/parser.c +++ b/lib/dnscore/src/parser.c @@ -556,36 +556,48 @@ parser_next_token(parser_s *parser) // find the end char ... // note: see strpbrk - char end_char = parser->delimiter_close[b]; + const char end_char = parser->delimiter_close[b]; - char *string_end; + char *string_end = ++needle; for(;;) { - needle++; - - string_end = memchr(needle, end_char, parser->limit - needle); + string_end = memchr(string_end, end_char, parser->limit - string_end); if(string_end != NULL) { - if(parser->char_type[(u8)string_end[-1]] != PARSER_CHAR_TYPE_ESCAPE_CHARACTER) - { - break; + /* Check if the string delimiter that was found was escaped. Keep in + * mind that if there was an escape character in front of the string + * delimiter, the escape character itself could have also been escaped + * (and the one before that and the one before that...). What we can do + * is check to see how many consecutive preceding escape characters + * there are (by finding the first preceding nonescape character or the + * opening string delimiter if there isn't one) and if it's an even + * number then the string delimiter we found is unescaped but if it's an + * odd number then it is escaped. Note that this will need to be revised + * if YADIDA later adds support for using \DDD type escape sequences + * between string delimiters. + */ + const char *prior_nonescape_character = string_end; + while(--prior_nonescape_character >= needle){ + if(parser->char_type[(u8)*prior_nonescape_character] != PARSER_CHAR_TYPE_ESCAPE_CHARACTER) + break; } - + if((string_end - prior_nonescape_character) % 2 == 1){ + break; /* String delimiter was not escaped if we got here. */ + } + // this one was escaped ... string_end++; - + // needle = string_end + 1 and try again ? - - if(string_end > parser->limit) + + if(string_end >= parser->limit) { return PARSER_EXPECTED_STRING_END_DELIMITER; } - - needle = string_end; - + //string_end = memchr(string_end, end_char, parser->limit - string_end); } else yadifa-2.6.5-11201/sbin/yadifad/contributions/PaxHeaders.1636/20190323-yadifa-2.3.9-pmtudisc_omit.pa0000644000000000000000000000013214505005533027602 xustar000000000000000030 mtime=1695812443.332994935 30 atime=1695812445.781029996 30 ctime=1695812495.494741996 yadifa-2.6.5-11201/sbin/yadifad/contributions/20190323-yadifa-2.3.9-pmtudisc_omit.patch0000664000374500037450000000514014505005533030243 0ustar00signersigner00000000000000From: Daisuke HIGASHI To: "yadifa-users@mailinglists.yadifa.eu" Date: Sat, 23 Mar 2019 11:03:02 +0000 Subject: [yadifa-users] Patch: IP_PMTUDISC_OMIT on IPv4/UDP for mitigating fragment attack Hi, Linux 3.15 introduced a new socket option IP_PMTUDISC_OMIT[1] which makes sockets ignore PMTU information and send packets with DF=0. With this sockopt fragmentation is allowed if and only if the packet size exceeds the outgoing interface MTU or the packet encounters smaller MTU link in network. By preventing forged PMTU information, setting IP_PMTUDISC_OMIT (instead of IP_PMTUDISC_DONT) to DNS responder's IPv4/UDP socket mitigates DNS fragmentation attacks [2]. Some DNS implementations already have this feature [3][4][5]. Patches for yadifa-2.3.9 to set IP_PMTUDISC_OMIT to IPv4/UDP sockets (if available) attached. It would be appreciated if this patch be applied to mainline. [1] Linux kernel introduced IP*_PMTUDISC_OMIT https://lists.openwall.net/netdev/2014/02/26/4 [2] IP fragmentation attack on DNS https://ripe67.ripe.net/presentations/240-ipfragattack.pdf [3] Unbound 1.5.0 introduced this feature. https://github.com/NLnetLabs/unbound/commit/470b7bda8763c36a7db255d1d981f3ae06d41ba0 [4] BIND 9.9.10 introduced this feature. https://www.isc.org/blogs/bind-april-2017/ [5] NSD 4.1.27 will introduce this feature https://www.nlnetlabs.nl/bugs-script/show_bug.cgi?id=4235 -- Daisuke Higashi diff -ur yadifa-2.3.9-8497/sbin/yadifad/server_context.c yadifa-2.3.9-8497.omit/sbin/yadifad/server_context.c --- yadifa-2.3.9-8497/sbin/yadifad/server_context.c 2019-02-11 12:45:56.956114538 +0000 +++ yadifa-2.3.9-8497.omit/sbin/yadifad/server_context.c 2019-03-23 10:42:31.549563989 +0000 @@ -355,6 +355,25 @@ } } #endif + +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT) + /* + * Linux 3.15 has IP_PMTUDISC_OMIT which makes sockets + * ignore PMTU information and send packets with DF=0. + * Fragmentation is allowed if and only if the packet + * size exceeds the outgoing interface MTU or the packet + * encounters smaller MTU link in network. + * This mitigates DNS fragmentation attacks by preventing + * forged PMTU information. + * FreeBSD already has same semantics without setting + * the option. + */ + if(family == SOCK_DGRAM) + { + int action_omit = IP_PMTUDISC_OMIT; + (void)setsockopt(sockfd, IPPROTO_IP,IP_MTU_DISCOVER, &action_omit, sizeof(action_omit)); + } +#endif /* IP_MTU_DISCOVER && IP_PMTUDISC_OMIT */ } if(FAIL(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)))) yadifa-2.6.5-11201/sbin/yadifad/contributions/PaxHeaders.1636/20190911-sighup-crash-fix.patch0000644000000000000000000000013214505005533026703 xustar000000000000000030 mtime=1695812443.334994963 30 atime=1695812445.781029996 30 ctime=1695812495.496742025 yadifa-2.6.5-11201/sbin/yadifad/contributions/20190911-sighup-crash-fix.patch0000664000374500037450000000160514505005533026647 0ustar00signersigner00000000000000From 58675f943fc9acdea7d9c27f576d9f515779a45c Mon Sep 17 00:00:00 2001 From: Markus Kolb Date: Wed, 11 Sep 2019 13:05:40 +0200 Subject: [PATCH] Fix crash on SIGHUP when zone files changed --- sbin/yadifad/database-service-zone-load.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sbin/yadifad/database-service-zone-load.c b/sbin/yadifad/database-service-zone-load.c index 2ecc92c..119fdfc 100644 --- a/sbin/yadifad/database-service-zone-load.c +++ b/sbin/yadifad/database-service-zone-load.c @@ -1671,11 +1671,14 @@ database_service_zone_load_thread(void *parms) } database_fire_zone_loaded(zone_desc, zone, return_code); - - zdb_zone_release(zone); + + if(zone != NULL) + { + zdb_zone_release(zone); #ifdef DEBUG zone = NULL; #endif + } } else { yadifa-2.6.5-11201/sbin/yadifad/contributions/PaxHeaders.1636/20201106-musl-support.patch0000644000000000000000000000013214505005533026201 xustar000000000000000030 mtime=1695812443.333994949 30 atime=1695812445.781029996 30 ctime=1695812495.498742053 yadifa-2.6.5-11201/sbin/yadifad/contributions/20201106-musl-support.patch0000664000374500037450000000641414505005533026150 0ustar00signersigner00000000000000From: Kolbma Source: https://github.com/yadifa/yadifa/issues/9 --- --- a/lib/dnscore/src/debug.c +++ b/lib/dnscore/src/debug.c @@ -56,7 +56,7 @@ #include "dnscore/dnscore-config.h" #include "dnscore/timems.h" -#if defined(__linux__) || defined(__APPLE__) +#if defined(__GLIBC__) || defined(__APPLE__) #include #if HAS_BFD_DEBUG_SUPPORT #include @@ -84,7 +84,7 @@ #undef debug_stat #undef debug_mallocated -#if defined(__linux__) || defined(__APPLE__) +#if defined(__GLIBC__) || defined(__APPLE__) #define DNSCORE_DEBUG_STACKTRACE 1 #else /* __FreeBSD__ or unknown */ #define DNSCORE_DEBUG_STACKTRACE 0 @@ -603,7 +603,7 @@ stacktrace debug_stacktrace_get() { -#ifdef __linux__ +#ifdef __GLIBC__ void* buffer_[1024]; int n = backtrace(buffer_, sizeof(buffer_) / sizeof(void*)); @@ -705,7 +705,7 @@ void debug_stacktrace_log(logger_handle* handle, u32 level, stacktrace trace) { -#ifdef __linux__ +#ifdef __GLIBC__ int n = 0; if(trace != NULL) @@ -825,7 +825,7 @@ void debug_stacktrace_try_log(logger_handle* handle, u32 level, stacktrace trace) { -#ifdef __linux__ +#ifdef __GLIBC__ int n = 0; if(trace != NULL) @@ -891,7 +891,7 @@ return; } -#ifdef __linux__ +#ifdef __GLIBC__ int n = 0; while(trace[n] != 0) @@ -983,7 +983,7 @@ /****************************************************************************/ -#if defined(__linux__) +#if defined(__GLIBC__) bool debug_log_stacktrace(logger_handle *handle, u32 level, const char *prefix) @@ -993,7 +993,7 @@ char binary[PATH_MAX]; #endif -#if defined(__linux__) +#if defined(__GLIBC__) int n = backtrace(addresses, sizeof(addresses) / sizeof(void*)); --- a/lib/dnscore/src/signals.c +++ b/lib/dnscore/src/signals.c @@ -55,7 +55,7 @@ #include #include -#if defined(__linux__) || defined(__gnu_hurd__) +#if defined(__GLIBC__) || defined(__gnu_hurd__) #define _GNU_SOURCE 1 #include #include @@ -694,7 +694,7 @@ log_err(filepath); } -#if defined(__linux__) || defined(__gnu_hurd__) +#if defined(__GLIBC__) || defined(__gnu_hurd__) void* buffer[MAXTRACE]; char** strings; int n = backtrace(buffer, MAXTRACE); @@ -724,7 +724,7 @@ log_err(filepath); } -#if __linux__ +#if __GLIBC__ ucontext_t* ucontext = (ucontext_t*)context; /* @@ -902,7 +902,7 @@ log_err(filepath); } -#if __linux__ && (defined(__x86_64__) || defined(__i386__)) && (_BSD_SOURCE || _SVID_SOURCE || _DEFAULT_SOURCE) +#if __GLIBC__ && (defined(__x86_64__) || defined(__i386__)) && (_BSD_SOURCE || _SVID_SOURCE || _DEFAULT_SOURCE) // dump more information about the memory address of the error #define PAGESIZE 4096 #define LINESIZE 32 --- a/sbin/yadifad/signals.c +++ b/sbin/yadifad/signals.c @@ -53,7 +53,7 @@ #include #include -#if defined(__linux__) || defined(__gnu_hurd__) +#if defined(__GLIBC__) || defined(__gnu_hurd__) #define _GNU_SOURCE 1 #include #include yadifa-2.6.5-11201/sbin/yadifad/contributions/PaxHeaders.1636/20210301-dynupdate-error-code.patch0000644000000000000000000000013214505005533027540 xustar000000000000000030 mtime=1695812443.332994935 30 atime=1695812445.781029996 30 ctime=1695812495.500742082 yadifa-2.6.5-11201/sbin/yadifad/contributions/20210301-dynupdate-error-code.patch0000664000374500037450000000202014505005533027474 0ustar00signersigner00000000000000From: dextercd Source: https://github.com/yadifa/yadifa/issues/15 --- --- a/sbin/yadifad/database.c +++ b/sbin/yadifad/database.c @@ -1375,7 +1375,14 @@ database_update(zdb *database, message_data *mesg) log_warn("database: update: %{dnsname}: prerequisites not met", message_get_canonised_fqdn(mesg)); - message_set_status(mesg, FP_RCODE_SERVFAIL); + if((ret & 0xffff0000) == RCODE_ERROR_BASE) + { + message_set_status(mesg, RCODE_ERROR_GETCODE(ret)); + } + else + { + message_set_status(mesg, FP_RCODE_SERVFAIL); + } } zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); yadifa-2.6.5-11201/sbin/yadifad/contributions/PaxHeaders.1636/20210810-null-tsig-crash-fix.patch0000644000000000000000000000013214505005533027311 xustar000000000000000030 mtime=1695812443.335994978 30 atime=1695812445.781029996 30 ctime=1695812495.502742111 yadifa-2.6.5-11201/sbin/yadifad/contributions/20210810-null-tsig-crash-fix.patch0000664000374500037450000000131414505005533027252 0ustar00signersigner00000000000000From: "Arjun singh" Date: Tue, 10 Aug 2021 11:57:14 +0530 Subject: NULL-Pointer DOS Attack Source: Internal ticket report Note: A proof of concept was provided with the report. The proposed fix has been transposed here as a patch. --- diff -ur trunk/lib/dnscore/src/tsig.c trunk-tsig-fix/lib/dnscore/src/tsig.c --- trunk/lib/dnscore/src/tsig.c 2021-05-28 08:39:31.000000000 +0200 +++ trunk-tsig-fix/lib/dnscore/src/tsig.c 2021-08-24 12:35:33.228664598 +0200 @@ -609,6 +609,11 @@ static ya_result tsig_digest_answer(message_data *mesg) { + if(mesg->_tsig.tsig == NULL) + { + return ERROR; + } + tsig_hmac_t hmac = tsig_hmac_allocate(); if(hmac == NULL) yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/Makefile.in0000644000000000000000000000013214505005547020745 xustar000000000000000030 mtime=1695812455.488169021 30 atime=1695812461.819259695 30 ctime=1695812495.482741824 yadifa-2.6.5-11201/sbin/yadifad/Makefile.in0000664000374500037450000014447214505005547020723 0ustar00signersigner00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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@ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ # # ALL # ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ DIST_COMMON = $(srcdir)/../../mk/common-settings.mk \ $(srcdir)/../../mk/common-labels.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp \ $(dist_noinst_DATA) $(am__noinst_HEADERS_DIST) \ $(am__pkginclude_HEADERS_DIST) AUTHORS COPYING ChangeLog NEWS \ README @USES_SUNC_TRUE@am__append_1 = @USES_SUNC_FALSE@am__append_2 = -O0 @IS_DARWIN_OS_TRUE@am__append_3 = -Wno-deprecated @HAS_CC_NO_IDENT_TRUE@am__append_4 = -fno-ident @HAS_CC_ANSI_TRUE@am__append_5 = -ansi @HAS_CC_PEDANTIC_TRUE@am__append_6 = -pedantic @HAS_CC_WALL_TRUE@am__append_7 = -Wall -Wno-unknown-pragmas @HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE@am__append_8 = -Werror=missing-field-initializers @HAS_CC_STD_GNU11_TRUE@am__append_9 = -std=gnu11 @HAS_CC_STD_C11_TRUE@@HAS_CC_STD_GNU11_FALSE@am__append_10 = -std=c11 -D_GNU_SOURCE @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_TRUE@am__append_11 = -std=gnu99 @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_C99_TRUE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_FALSE@am__append_12 = -std=c99 @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_C99_FALSE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_FALSE@@HAS_CC_XC99_TRUE@am__append_13 = -xc99 @HAS_CC_TUNE_NATIVE_TRUE@am__append_14 = -mtune=native @FORCE64BITS_TRUE@@HAS_CC_M64_TRUE@am__append_15 = -m64 @FORCE64BITS_TRUE@@HAS_CC_M64_TRUE@am__append_16 = -m64 @FORCE32BITS_TRUE@@FORCE64BITS_FALSE@@HAS_CC_M32_TRUE@am__append_17 = -m32 @FORCE32BITS_TRUE@@FORCE64BITS_FALSE@@HAS_CC_M32_TRUE@am__append_18 = -m32 # # DEBUG # @HAS_CC_G3_TRUE@am__append_19 = -g3 @HAS_CC_G3_FALSE@@HAS_CC_G_TRUE@am__append_20 = -g @HAS_CC_DWARF4_TRUE@am__append_21 = -gdwarf-4 @HAS_CC_DWARF3_TRUE@@HAS_CC_DWARF4_FALSE@am__append_22 = -gdwarf-3 # # Intel C Compiler # ############################################################################### #ICC #IPO= -ipo (need to use the intel xiar instead of ar) @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@am__append_23 = -DLTO -ipo @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@am__append_24 = -ipo @USES_ICC_TRUE@am__append_25 = -DUSES_ICC @HAS_CC_ANSI_ALIAS_TRUE@@USES_ICC_TRUE@am__append_26 = -ansi-alias -U__STRICT_ANSI__ @USES_ICC_TRUE@am__append_27 = -DMODE_DEBUG_ICC # # LLVM Clang # ############################################################################### # CLANG @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@am__append_28 = -DLTO -flto @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@am__append_29 = -flto @USES_CLANG_TRUE@am__append_30 = -DUSES_LLVM -Wno-gnu #-Wno-extended-offsetof @USES_CLANG_TRUE@am__append_31 = -DMODE_DEBUG_CLANG -fsanitize=address -fsanitize=bounds @IS_LINUX_FAMILY_TRUE@@USES_CLANG_TRUE@am__append_32 = -Wl,-z,stack-size=8388608 # Note: add a _d suffix for debug builds ? # # Gnu C # ############################################################################### #GCC @HAS_CPU_NIAGARA_TRUE@@USES_GCC_TRUE@am__append_33 = -mcpu=niagara @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_34 = -DLTO -flto -fwhole-program -fno-fat-lto-objects -fuse-linker-plugin @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_35 = -flto \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fwhole-program \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fno-fat-lto-objects \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fuse-linker-plugin \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -Wl,-Map=module.map \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -Wl,--cref @USES_GCC_TRUE@am__append_36 = -DUSES_GCC @USES_GCC_TRUE@am__append_37 = -DMODE_DEBUG_GCC -fstack-check -fstack-protector-strong @HAS_BFD_DEBUG_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_38 = -rdynamic @IS_LINUX_FAMILY_TRUE@@USES_GCC_TRUE@am__append_39 = -Wl,-z,stack-size=8388608 @USES_SUNC_TRUE@am__append_40 = -DUSES_SUNC @USES_SUNC_TRUE@am__append_41 = -DMODE_DEBUG_SUNC # Note: add a _d suffix for debug builds ? # # Unknown compiler # ############################################################################### # if an unknown compiler is used, it should have its own section @USES_UNKNOWN_TRUE@am__append_42 = -DUSES_UNKNOWN_COMPILER @USES_UNKNOWN_TRUE@am__append_43 = -DMODE_DEBUG_UNKNOWN # # Some BSD-based OSes need this # @IS_BSD_FAMILY_TRUE@am__append_44 = -I./include @IS_SOLARIS_FAMILY_TRUE@am__append_45 = -D_POSIX_PTHREAD_SEMANTICS sbin_PROGRAMS = yadifad$(EXEEXT) @HAVE_SENDMMSG_TRUE@@IS_LINUX_FAMILY_TRUE@am__append_46 = server-mm.c @HAVE_SENDMMSG_TRUE@@IS_LINUX_FAMILY_TRUE@am__append_47 = server-mm.h @HAS_EVENT_DYNAMIC_MODULE_TRUE@am__append_48 = dynamic-module-handler.c @HAS_EVENT_DYNAMIC_MODULE_TRUE@am__append_49 = dynamic-module-handler.h @HAS_NSID_SUPPORT_TRUE@am__append_50 = config-nsid.c @HAS_CTRL_TRUE@am__append_51 = config_control.c ctrl.c ctrl_query.c \ @HAS_CTRL_TRUE@ ctrl_zone.c ctrl_notify.c ctrl_query_axfr.c \ @HAS_CTRL_TRUE@ ctrl_query_message.c ctrl_update.c @HAS_CTRL_TRUE@am__append_52 = ctrl.h ctrl_query.h ctrl_zone.h \ @HAS_CTRL_TRUE@ ctrl_notify.h ctrl_query_axfr.h \ @HAS_CTRL_TRUE@ ctrl_query_message.h ctrl_update.h @HAS_RRL_SUPPORT_TRUE@am__append_53 = rrl.c @HAS_RRL_SUPPORT_TRUE@am__append_54 = rrl.h @HAS_DYNUPDATE_SUPPORT_TRUE@am__append_55 = dynupdate_query_service.c @HAS_DYNUPDATE_SUPPORT_TRUE@am__append_56 = dynupdate_query_service.h @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@am__append_57 = database-service-zone-resignature.c \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-denial.c \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-dnssec-policy.c \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-key-roll.c \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-key-suite.c \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-key-template.c \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-key-roll-parser.c \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ zone-signature-policy.c \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ zone-signature-date-next.c \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ zone-signature-date-prev.c @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@am__append_58 = database-service-zone-resignature.h \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-dnssec-policy.h \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-key-roll-parser.h \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ zone-signature-policy.h subdir = sbin/yadifad ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/eurid.m4 $(top_srcdir)/m4/yadifa.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(pkgincludedir)" PROGRAMS = $(sbin_PROGRAMS) am__yadifad_SOURCES_DIST = main.c axfr.c config_main.c config_zone.c \ confs.c database-service-zone-desc-load.c \ database-service-zone-desc-unload.c \ database-service-zone-download.c \ database-service-zone-freeze.c database-service-zone-load.c \ database-service-zone-mount.c database-service-zone-store.c \ database-service-zone-unfreeze.c \ database-service-zone-unload.c database-service-zone-unmount.c \ database-service.c database.c ixfr.c log_query.c \ log_statistics.c notify.c poll-util.c process_class_ch.c \ server-sm.c server.c server_context.c \ server_process_message_udp.c signals.c zone.c server-rw.c \ server-mm.c dynamic-module-handler.c config-nsid.c \ config_control.c ctrl.c ctrl_query.c ctrl_zone.c ctrl_notify.c \ ctrl_query_axfr.c ctrl_query_message.c ctrl_update.c rrl.c \ dynupdate_query_service.c database-service-zone-resignature.c \ config-denial.c config-dnssec-policy.c config-key-roll.c \ config-key-suite.c config-key-template.c \ config-key-roll-parser.c zone-signature-policy.c \ zone-signature-date-next.c zone-signature-date-prev.c @HAVE_SENDMMSG_TRUE@@IS_LINUX_FAMILY_TRUE@am__objects_1 = \ @HAVE_SENDMMSG_TRUE@@IS_LINUX_FAMILY_TRUE@ server-mm.$(OBJEXT) @HAS_EVENT_DYNAMIC_MODULE_TRUE@am__objects_2 = dynamic-module-handler.$(OBJEXT) @HAS_NSID_SUPPORT_TRUE@am__objects_3 = config-nsid.$(OBJEXT) @HAS_CTRL_TRUE@am__objects_4 = config_control.$(OBJEXT) ctrl.$(OBJEXT) \ @HAS_CTRL_TRUE@ ctrl_query.$(OBJEXT) ctrl_zone.$(OBJEXT) \ @HAS_CTRL_TRUE@ ctrl_notify.$(OBJEXT) ctrl_query_axfr.$(OBJEXT) \ @HAS_CTRL_TRUE@ ctrl_query_message.$(OBJEXT) \ @HAS_CTRL_TRUE@ ctrl_update.$(OBJEXT) @HAS_RRL_SUPPORT_TRUE@am__objects_5 = rrl.$(OBJEXT) @HAS_DYNUPDATE_SUPPORT_TRUE@am__objects_6 = \ @HAS_DYNUPDATE_SUPPORT_TRUE@ dynupdate_query_service.$(OBJEXT) @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@am__objects_7 = database-service-zone-resignature.$(OBJEXT) \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-denial.$(OBJEXT) \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-dnssec-policy.$(OBJEXT) \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-key-roll.$(OBJEXT) \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-key-suite.$(OBJEXT) \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-key-template.$(OBJEXT) \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ config-key-roll-parser.$(OBJEXT) \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ zone-signature-policy.$(OBJEXT) \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ zone-signature-date-next.$(OBJEXT) \ @HAS_MASTER_SUPPORT_TRUE@@HAS_RRSIG_MANAGEMENT_SUPPORT_TRUE@ zone-signature-date-prev.$(OBJEXT) am_yadifad_OBJECTS = main.$(OBJEXT) axfr.$(OBJEXT) \ config_main.$(OBJEXT) config_zone.$(OBJEXT) confs.$(OBJEXT) \ database-service-zone-desc-load.$(OBJEXT) \ database-service-zone-desc-unload.$(OBJEXT) \ database-service-zone-download.$(OBJEXT) \ database-service-zone-freeze.$(OBJEXT) \ database-service-zone-load.$(OBJEXT) \ database-service-zone-mount.$(OBJEXT) \ database-service-zone-store.$(OBJEXT) \ database-service-zone-unfreeze.$(OBJEXT) \ database-service-zone-unload.$(OBJEXT) \ database-service-zone-unmount.$(OBJEXT) \ database-service.$(OBJEXT) database.$(OBJEXT) ixfr.$(OBJEXT) \ log_query.$(OBJEXT) log_statistics.$(OBJEXT) notify.$(OBJEXT) \ poll-util.$(OBJEXT) process_class_ch.$(OBJEXT) \ server-sm.$(OBJEXT) server.$(OBJEXT) server_context.$(OBJEXT) \ server_process_message_udp.$(OBJEXT) signals.$(OBJEXT) \ zone.$(OBJEXT) server-rw.$(OBJEXT) $(am__objects_1) \ $(am__objects_2) $(am__objects_3) $(am__objects_4) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) yadifad_OBJECTS = $(am_yadifad_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__depfiles_maybe = depfiles 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 = $(yadifad_SOURCES) DIST_SOURCES = $(am__yadifad_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_noinst_DATA) am__noinst_HEADERS_DIST = axfr.h config_error.h confs.h \ database-service-zone-desc-load.h \ database-service-zone-desc-unload.h \ database-service-zone-download.h \ database-service-zone-freeze.h database-service-zone-load.h \ database-service-zone-mount.h database-service-zone-store.h \ database-service-zone-unfreeze.h \ database-service-zone-unload.h database-service-zone-unmount.h \ database-service.h database.h dnssec-policy.h ixfr.h \ log_query.h log_statistics.h notify.h poll-util.h \ process_class_ch.h server-sm.h server.h server_context.h \ server_error.h signals.h zone.h zone_desc.h zone-source.h \ server-rw.h server-mm.h dynamic-module-handler.h ctrl.h \ ctrl_query.h ctrl_zone.h ctrl_notify.h ctrl_query_axfr.h \ ctrl_query_message.h ctrl_update.h rrl.h \ dynupdate_query_service.h database-service-zone-resignature.h \ config-dnssec-policy.h config-key-roll-parser.h \ zone-signature-policy.h am__pkginclude_HEADERS_DIST = dynamic-module-interface.h 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; }; \ } HEADERS = $(noinst_HEADERS) $(pkginclude_HEADERS) 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)` ETAGS = etags CTAGS = ctags 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@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCOPTIMISATIONFLAGS = @CCOPTIMISATIONFLAGS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DNSCORE = @DNSCORE@ DNSDB = @DNSDB@ DNSLG = @DNSLG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAS_ACL_SUPPORT = @HAS_ACL_SUPPORT@ HAS_BFD_DEBUG_SUPPORT = @HAS_BFD_DEBUG_SUPPORT@ HAS_BIG_ENDIAN = @HAS_BIG_ENDIAN@ HAS_BUILD_TIMESTAMP = @HAS_BUILD_TIMESTAMP@ HAS_CC_ADDRESS_SANITIZER_CHECK = @HAS_CC_ADDRESS_SANITIZER_CHECK@ HAS_CC_ANSI = @HAS_CC_ANSI@ HAS_CC_ANSI_ALIAS = @HAS_CC_ANSI_ALIAS@ HAS_CC_CATCH_UNDEFINED_BEHAVIOR = @HAS_CC_CATCH_UNDEFINED_BEHAVIOR@ HAS_CC_DWARF2 = @HAS_CC_DWARF2@ HAS_CC_DWARF3 = @HAS_CC_DWARF3@ HAS_CC_DWARF4 = @HAS_CC_DWARF4@ HAS_CC_EXCEPTIONS = @HAS_CC_EXCEPTIONS@ HAS_CC_G = @HAS_CC_G@ HAS_CC_G3 = @HAS_CC_G3@ HAS_CC_M32 = @HAS_CC_M32@ HAS_CC_M64 = @HAS_CC_M64@ HAS_CC_MISSING_FIELD_INITIALIZERS = @HAS_CC_MISSING_FIELD_INITIALIZERS@ HAS_CC_NO_IDENT = @HAS_CC_NO_IDENT@ HAS_CC_NO_OMIT_FRAME_POINTER = @HAS_CC_NO_OMIT_FRAME_POINTER@ HAS_CC_PEDANTIC = @HAS_CC_PEDANTIC@ HAS_CC_RDYNAMIC = @HAS_CC_RDYNAMIC@ HAS_CC_SANITIZE_ADDRESS = @HAS_CC_SANITIZE_ADDRESS@ HAS_CC_STACK_PROTECTOR = @HAS_CC_STACK_PROTECTOR@ HAS_CC_STD_C11 = @HAS_CC_STD_C11@ HAS_CC_STD_C99 = @HAS_CC_STD_C99@ HAS_CC_STD_GNU11 = @HAS_CC_STD_GNU11@ HAS_CC_STD_GNU99 = @HAS_CC_STD_GNU99@ HAS_CC_TUNE_NATIVE = @HAS_CC_TUNE_NATIVE@ HAS_CC_WALL = @HAS_CC_WALL@ HAS_CC_XC99 = @HAS_CC_XC99@ HAS_CLOSE_EX_REF = @HAS_CLOSE_EX_REF@ HAS_CTRL = @HAS_CTRL@ HAS_DNSSEC_TOOLS = @HAS_DNSSEC_TOOLS@ HAS_DYNUPDATE_SUPPORT = @HAS_DYNUPDATE_SUPPORT@ HAS_ECDSA_SUPPORT = @HAS_ECDSA_SUPPORT@ HAS_EDDSA = @HAS_EDDSA@ HAS_EVENT_DYNAMIC_MODULE = @HAS_EVENT_DYNAMIC_MODULE@ HAS_FULL_ASCII7 = @HAS_FULL_ASCII7@ HAS_KEYGEN = @HAS_KEYGEN@ HAS_LIBC_MALLOC_DEBUG_SUPPORT = @HAS_LIBC_MALLOC_DEBUG_SUPPORT@ HAS_LITTLE_ENDIAN = @HAS_LITTLE_ENDIAN@ HAS_LOCK_DEBUG_SUPPORT = @HAS_LOCK_DEBUG_SUPPORT@ HAS_LOGDIR = @HAS_LOGDIR@ HAS_LOG_PID = @HAS_LOG_PID@ HAS_LOG_THREAD_ID = @HAS_LOG_THREAD_ID@ HAS_LOG_THREAD_TAG = @HAS_LOG_THREAD_TAG@ HAS_MALLOC_DEBUG_SUPPORT = @HAS_MALLOC_DEBUG_SUPPORT@ HAS_MASTER_SUPPORT = @HAS_MASTER_SUPPORT@ HAS_MEMALIGN_ISSUES = @HAS_MEMALIGN_ISSUES@ HAS_MUTEX_DEBUG_SUPPORT = @HAS_MUTEX_DEBUG_SUPPORT@ HAS_NON_AA_AXFR_SUPPORT = @HAS_NON_AA_AXFR_SUPPORT@ HAS_NSEC3_SUPPORT = @HAS_NSEC3_SUPPORT@ HAS_NSEC_SUPPORT = @HAS_NSEC_SUPPORT@ HAS_NSID_SUPPORT = @HAS_NSID_SUPPORT@ HAS_RRL_SUPPORT = @HAS_RRL_SUPPORT@ HAS_RRSIG_MANAGEMENT_SUPPORT = @HAS_RRSIG_MANAGEMENT_SUPPORT@ HAS_SYNC_BUILTINS = @HAS_SYNC_BUILTINS@ HAS_SYSTEMD_RESOLVED_AVOIDANCE = @HAS_SYSTEMD_RESOLVED_AVOIDANCE@ HAS_TESTS = @HAS_TESTS@ HAS_TOOLS = @HAS_TOOLS@ HAS_TRACK_ZONES_DEBUG_SUPPORT = @HAS_TRACK_ZONES_DEBUG_SUPPORT@ HAS_TSIG_SUPPORT = @HAS_TSIG_SUPPORT@ HAS_YADIFA = @HAS_YADIFA@ HAS_ZALLOC_DEBUG_SUPPORT = @HAS_ZALLOC_DEBUG_SUPPORT@ HAS_ZALLOC_STATISTICS_SUPPORT = @HAS_ZALLOC_STATISTICS_SUPPORT@ HAS_ZALLOC_SUPPORT = @HAS_ZALLOC_SUPPORT@ HAVE_RECVMMSG = @HAVE_RECVMMSG@ HAVE_SENDMMSG = @HAVE_SENDMMSG@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IS_BSD_FAMILY = @IS_BSD_FAMILY@ IS_DARWIN_GE14 = @IS_DARWIN_GE14@ IS_DARWIN_OS = @IS_DARWIN_OS@ IS_LINUX_FAMILY = @IS_LINUX_FAMILY@ IS_SOLARIS_FAMILY = @IS_SOLARIS_FAMILY@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL = @OPENSSL@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZDB_HAS_DNSSEC_SUPPORT = @ZDB_HAS_DNSSEC_SUPPORT@ 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_CXX = @ac_ct_CXX@ 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@ 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@ logdir = @logdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I ../../m4 # # # AM_CFLAGS = -D_THREAD_SAFE -D_REENTRANT -D_FILE_OFFSET_BITS=64 \ -I$(abs_builddir) -I$(abs_builddir)/include \ -I$(abs_srcdir)/include $(am__append_3) $(am__append_4) \ $(am__append_5) $(am__append_6) $(am__append_7) \ $(am__append_8) $(am__append_9) $(am__append_10) \ $(am__append_11) $(am__append_12) $(am__append_13) \ $(am__append_14) $(am__append_15) $(am__append_17) \ $(am__append_23) $(am__append_25) $(am__append_26) \ $(am__append_28) $(am__append_30) $(am__append_33) \ $(am__append_34) $(am__append_36) $(am__append_38) \ $(am__append_40) $(am__append_42) $(am__append_44) \ $(am__append_45) $(LOCALFLAGS) \ -I$(top_srcdir)/lib/dnscore/include \ -I$(top_builddir)/lib/dnscore/include \ -I$(top_srcdir)/lib/dnsdb/include \ -I$(top_builddir)/lib/dnsdb/include \ -I$(top_srcdir)/lib/dnstcl/include \ -I$(top_builddir)/lib/dnstcl/include AM_LDFLAGS = $(am__append_16) $(am__append_18) $(am__append_24) \ $(am__append_29) $(am__append_32) $(am__append_35) \ $(am__append_39) DEBUGFLAGS = $(am__append_1) $(am__append_2) $(am__append_19) \ $(am__append_20) $(am__append_21) $(am__append_22) \ $(am__append_27) $(am__append_31) $(am__append_37) \ $(am__append_41) $(am__append_43) LOCALFLAGS = -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)"' -DLOCALSTATEDIR='"$(localstatedir)"' -DDATAROOTDIR='"$(datarootdir)"' -DDATADIR='"$(datadir)"' -DLOCALEDIR='"$(localedir)"' -DLOGDIR='"$(logdir)"' -DTCLDIR='"$(tcldir)"' @HAS_LTO_SUPPORT_FALSE@@USES_CLANG_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_FALSE@@USES_GCC_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@AM_AR = llvm-ar @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@AM_AR = gcc-ar @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@AM_AR = xiar # # Sun C # ############################################################################### # SUNC @USES_SUNC_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_FALSE@@USES_CLANG_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_FALSE@@USES_GCC_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@AM_LD = ld.gold @USES_ICC_TRUE@AM_LD = ld @USES_SUNC_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@AM_RANLIB = gcc-ranlib BUILT_SOURCES = buildinfo.h server-config.h dist_noinst_DATA = VERSION \ contributions/20170225-libressl-detection-and-fix.patch \ contributions/20190112-escape-character-fix.patch \ contributions/20190112-txt-record-parsing-improvements.patch \ contributions/20190323-yadifa-2.3.9-pmtudisc_omit.patch \ contributions/20190911-sighup-crash-fix.patch \ contributions/20201106-musl-support.patch \ contributions/20210301-dynupdate-error-code.patch \ contributions/20210810-null-tsig-crash-fix.patch yadifad_LDADD = $(abs_top_builddir)/lib/dnsdb/libdnsdb.la \ $(abs_top_builddir)/lib/dnscore/libdnscore.la yadifad_SOURCES = main.c axfr.c config_main.c config_zone.c confs.c \ database-service-zone-desc-load.c \ database-service-zone-desc-unload.c \ database-service-zone-download.c \ database-service-zone-freeze.c database-service-zone-load.c \ database-service-zone-mount.c database-service-zone-store.c \ database-service-zone-unfreeze.c \ database-service-zone-unload.c database-service-zone-unmount.c \ database-service.c database.c ixfr.c log_query.c \ log_statistics.c notify.c poll-util.c process_class_ch.c \ server-sm.c server.c server_context.c \ server_process_message_udp.c signals.c zone.c server-rw.c \ $(am__append_46) $(am__append_48) $(am__append_50) \ $(am__append_51) $(am__append_53) $(am__append_55) \ $(am__append_57) yadifad_DEPENDENCIES = server-config.h buildinfo.h noinst_HEADERS = axfr.h config_error.h confs.h \ database-service-zone-desc-load.h \ database-service-zone-desc-unload.h \ database-service-zone-download.h \ database-service-zone-freeze.h database-service-zone-load.h \ database-service-zone-mount.h database-service-zone-store.h \ database-service-zone-unfreeze.h \ database-service-zone-unload.h database-service-zone-unmount.h \ database-service.h database.h dnssec-policy.h ixfr.h \ log_query.h log_statistics.h notify.h poll-util.h \ process_class_ch.h server-sm.h server.h server_context.h \ server_error.h signals.h zone.h zone_desc.h zone-source.h \ server-rw.h $(am__append_47) $(am__append_49) $(am__append_52) \ $(am__append_54) $(am__append_56) $(am__append_58) # pkgincludedir is already defined to $(includedir)/yadifa (as the package name is yadifa) # pkgincludedir = $(includedir)/yadifad @HAS_EVENT_DYNAMIC_MODULE_TRUE@pkginclude_HEADERS = dynamic-module-interface.h CLEANFILES = buildinfo.h server-config.h all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../mk/common-settings.mk $(srcdir)/../../mk/common-labels.mk $(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) --gnu sbin/yadifad/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu sbin/yadifad/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(srcdir)/../../mk/common-settings.mk $(srcdir)/../../mk/common-labels.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || 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)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || 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)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_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 yadifad$(EXEEXT): $(yadifad_OBJECTS) $(yadifad_DEPENDENCIES) $(EXTRA_yadifad_DEPENDENCIES) @rm -f yadifad$(EXEEXT) $(AM_V_CCLD)$(LINK) $(yadifad_OBJECTS) $(yadifad_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/axfr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-denial.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-dnssec-policy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-key-roll-parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-key-roll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-key-suite.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-key-template.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-nsid.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config_control.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config_main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config_zone.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/confs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctrl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctrl_notify.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctrl_query.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctrl_query_axfr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctrl_query_message.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctrl_update.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctrl_zone.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-desc-load.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-desc-unload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-download.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-freeze.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-load.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-mount.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-resignature.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-store.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-unfreeze.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-unload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service-zone-unmount.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database-service.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynamic-module-handler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynupdate_query_service.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixfr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_query.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_statistics.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll-util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_class_ch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server-mm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server-rw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server-sm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_context.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_process_message_udp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signals.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone-signature-date-next.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone-signature-date-prev.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone-signature-policy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone.Po@am__quote@ .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 install-pkgincludeHEADERS: $(pkginclude_HEADERS) @$(NORMAL_INSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ done uninstall-pkgincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) 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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(PROGRAMS) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(pkgincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) 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: -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." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS 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 -rf ./$(DEPDIR) -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: uninstall-am: uninstall-pkgincludeHEADERS uninstall-sbinPROGRAMS .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir 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-pkgincludeHEADERS install-ps install-ps-am \ install-sbinPROGRAMS 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 uninstall uninstall-am \ uninstall-pkgincludeHEADERS uninstall-sbinPROGRAMS ### YRCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -g -DCMR ### YPCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -pg -DCMP ### YDCFLAGS = -DDEBUG $(DEBUGFLAGS) -DCMD ### YSCFLAGS = $(YRCFLAGS) ### ### YRLDFLAGS = -g ### YPLDFLAGS = -pg ### YDLDFLAGS = -g ### ### if HAS_CC_RDYNAMIC ### YPLDFLAGS += -rdynamic ### YDLDFLAGS += -rdynamic ### endif ### ### if USES_CLANG ### # workaround a bug where clang does not handle properly profiling and optimizations ### YPCFLAGS += -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer ### endif ### ### YSLDFLAGS = $(YRLDFLAGS) ### ### AM_CFLAGS += $(YCFLAGS) ### AM_LDFLAGS += $(YLDFLAGS) ### ### AM_MAKEFLAGS=MODE_CFLAGS="$(AM_CFLAGS)" CC=$(CC) AR=$(AM_AR) LD=$(AM_LD) buildinfo.h: $(abs_top_builddir)/config.log echo \#pragma once > buildinfo.h 2> /dev/null echo // generated file, do not modify >> buildinfo.h 2> /dev/null echo \#define BUILD_OPTIONS \"$$(grep "/configure" $(abs_top_builddir)/config.log | head -1 | sed 's/.*\.\/configure *//')\" >> buildinfo.h 2> /dev/null server-config.h: ../../config.h cp ../../config.h server-config.h features: # 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: yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/Makefile.am0000644000000000000000000000013214505005533020727 xustar000000000000000030 mtime=1695812443.543997957 30 atime=1695812445.785030053 30 ctime=1695812495.484741853 yadifa-2.6.5-11201/sbin/yadifad/Makefile.am0000664000374500037450000001356214505005533020700 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ACLOCAL_AMFLAGS = -I ../../m4 include ../../mk/common-settings.mk BUILT_SOURCES=buildinfo.h server-config.h dist_noinst_DATA = VERSION sbin_PROGRAMS = yadifad AM_CFLAGS += -I$(top_srcdir)/lib/dnscore/include -I$(top_builddir)/lib/dnscore/include AM_CFLAGS += -I$(top_srcdir)/lib/dnsdb/include -I$(top_builddir)/lib/dnsdb/include AM_CFLAGS += -I$(top_srcdir)/lib/dnstcl/include -I$(top_builddir)/lib/dnstcl/include yadifad_LDADD= yadifad_LDADD+=$(abs_top_builddir)/lib/dnsdb/libdnsdb.la yadifad_LDADD+=$(abs_top_builddir)/lib/dnscore/libdnscore.la yadifad_SOURCES = \ main.c \ axfr.c \ config_main.c \ config_zone.c \ confs.c \ database-service-zone-desc-load.c \ database-service-zone-desc-unload.c \ database-service-zone-download.c \ database-service-zone-freeze.c \ database-service-zone-load.c \ database-service-zone-mount.c \ database-service-zone-store.c \ database-service-zone-unfreeze.c \ database-service-zone-unload.c \ database-service-zone-unmount.c \ database-service.c \ database.c \ ixfr.c \ log_query.c \ log_statistics.c \ notify.c \ poll-util.c \ process_class_ch.c \ server-sm.c \ server.c \ server_context.c \ server_process_message_udp.c \ signals.c \ zone.c yadifad_DEPENDENCIES = server-config.h buildinfo.h noinst_HEADERS = \ axfr.h \ config_error.h \ confs.h \ database-service-zone-desc-load.h \ database-service-zone-desc-unload.h \ database-service-zone-download.h \ database-service-zone-freeze.h \ database-service-zone-load.h \ database-service-zone-mount.h \ database-service-zone-store.h \ database-service-zone-unfreeze.h \ database-service-zone-unload.h \ database-service-zone-unmount.h \ database-service.h \ database.h \ dnssec-policy.h \ ixfr.h \ log_query.h \ log_statistics.h \ notify.h \ poll-util.h \ process_class_ch.h \ server-sm.h \ server.h \ server_context.h \ server_error.h \ signals.h \ zone.h \ zone_desc.h \ zone-source.h yadifad_SOURCES += server-rw.c noinst_HEADERS += server-rw.h if HAVE_SENDMMSG if IS_LINUX_FAMILY yadifad_SOURCES += server-mm.c noinst_HEADERS += server-mm.h endif endif if HAS_EVENT_DYNAMIC_MODULE yadifad_SOURCES += dynamic-module-handler.c noinst_HEADERS += dynamic-module-handler.h # pkgincludedir is already defined to $(includedir)/yadifa (as the package name is yadifa) # pkgincludedir = $(includedir)/yadifad pkginclude_HEADERS = dynamic-module-interface.h endif if HAS_NSID_SUPPORT yadifad_SOURCES += config-nsid.c endif if HAS_CTRL yadifad_SOURCES += config_control.c \ ctrl.c \ ctrl_query.c \ ctrl_zone.c noinst_HEADERS += ctrl.h ctrl_query.h ctrl_zone.h yadifad_SOURCES += ctrl_notify.c \ ctrl_query_axfr.c \ ctrl_query_message.c \ ctrl_update.c noinst_HEADERS += ctrl_notify.h \ ctrl_query_axfr.h \ ctrl_query_message.h \ ctrl_update.h endif # HAS_CTRL if HAS_RRL_SUPPORT yadifad_SOURCES += rrl.c noinst_HEADERS += rrl.h endif if HAS_DYNUPDATE_SUPPORT yadifad_SOURCES += dynupdate_query_service.c noinst_HEADERS += dynupdate_query_service.h endif if HAS_RRSIG_MANAGEMENT_SUPPORT if HAS_MASTER_SUPPORT yadifad_SOURCES += database-service-zone-resignature.c \ config-denial.c \ config-dnssec-policy.c \ config-key-roll.c \ config-key-suite.c \ config-key-template.c \ config-key-roll-parser.c \ zone-signature-policy.c \ zone-signature-date-next.c \ zone-signature-date-prev.c noinst_HEADERS += database-service-zone-resignature.h \ config-dnssec-policy.h \ config-key-roll-parser.h \ zone-signature-policy.h endif endif dist_noinst_DATA += contributions/20170225-libressl-detection-and-fix.patch \ contributions/20190112-escape-character-fix.patch \ contributions/20190112-txt-record-parsing-improvements.patch \ contributions/20190323-yadifa-2.3.9-pmtudisc_omit.patch \ contributions/20190911-sighup-crash-fix.patch \ contributions/20201106-musl-support.patch \ contributions/20210301-dynupdate-error-code.patch \ contributions/20210810-null-tsig-crash-fix.patch include ../../mk/common-labels.mk server-config.h: ../../config.h cp ../../config.h server-config.h CLEANFILES += server-config.h features: yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/VERSION0000644000000000000000000000013114505005533017742 xustar000000000000000029 mtime=1695812443.31799472 30 atime=1695812445.781029996 30 ctime=1695812495.486741881 yadifa-2.6.5-11201/sbin/yadifad/VERSION0000664000374500037450000000000614505005533017701 0ustar00signersigner000000000000002.6.5 yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/axfr.h0000644000000000000000000000013114505005533020003 xustar000000000000000029 mtime=1695812443.52399767 30 atime=1695812445.784030039 30 ctime=1695812495.504742139 yadifa-2.6.5-11201/sbin/yadifad/axfr.h0000664000374500037450000000551114505005533017750 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #ifndef _AXFR_H #define _AXFR_H #include #include #if DNSCORE_HAS_TCP_MANAGER #include #endif /** * * Handle an AXFR query from a slave. * * If we don't do this many slaves could call with a small interval asking a just-dynupdated snapshot. * If we do it the slaves will be only a few steps behind and the next notification/ixfr will bring them up to date. * */ #if DNSCORE_HAS_TCP_MANAGER ya_result axfr_process(message_data *mesg, tcp_manager_socket_context_t *sctx); #else ya_result axfr_process(message_data *mesg, int sockfd); #endif /** * * Send an AXFR query to a master and handle the answer (loads the zone) * */ ya_result axfr_query(const host_address *servers, const u8 *origin, u32* out_loaded_serial); ya_result axfr_query_ex(const host_address *servers, const u8 *origin, u32* out_loaded_serial, u32* out_loaded_refresh); #endif /* _AXFR_H */ /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config_error.h0000644000000000000000000000013114505005533021521 xustar000000000000000029 mtime=1695812443.50999747 30 atime=1695812445.783030024 30 ctime=1695812495.507742182 yadifa-2.6.5-11201/sbin/yadifad/config_error.h0000664000374500037450000000603014505005533021463 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup config Configuration handling * @ingroup yadifad * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef _CONFIG_ERROR_H #define _CONFIG_ERROR_H #ifdef __cplusplus extern "C" { #endif #define CFG_ERROR_BASE 0x80070000 #define CFG_ERROR_CODE(code_) ((s32)(CFG_ERROR_BASE+(code_))) /* Config errorcodes */ #define CONFIG_ZONE_ERR CFG_ERROR_CODE(50) /* Error in config file */ /* Zone errorcondes */ #define CONFIG_WRONG_SIG_TYPE CFG_ERROR_CODE(201) #define CONFIG_WRONG_SIG_VALIDITY CFG_ERROR_CODE(202) #define CONFIG_WRONG_SIG_REGEN CFG_ERROR_CODE(203) #define DATABASE_ZONE_MISSING_DOMAIN CFG_ERROR_CODE(301) #define DATABASE_ZONE_MISSING_MASTER CFG_ERROR_CODE(302) #define DATABASE_ZONE_MISSING_TYPE CFG_ERROR_CODE(303) #define DATABASE_ZONE_CONFIG_DUP CFG_ERROR_CODE(304) #define DATABASE_ZONE_CONFIG_CLONE CFG_ERROR_CODE(306) #ifdef __cplusplus } #endif #endif /* _CONFIG_ERROR_H */ /* ------------------------------------------------------------ */ /** @} */ /*----------------------------------------------------------------------------*/ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/confs.h0000644000000000000000000000013114505005533020153 xustar000000000000000030 mtime=1695812443.329994892 29 atime=1695812445.78203001 30 ctime=1695812495.509742211 yadifa-2.6.5-11201/sbin/yadifad/confs.h0000664000374500037450000005260214505005533020123 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup config Configuration handling * @ingroup yadifad * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef CONFS_H_ #define CONFS_H_ #ifdef __cplusplus extern "C" { #endif /* ------------------------------------------------------------ */ #include #include #include #include "server-config.h" #include #include #include #include #include /* ------------------------------------------------------------ */ #define PREPROCESSOR_INT2STR(x) #x #define TCP_QUERIES_MIN 0 #define TCP_QUERIES_MAX 0x20000 #define AXFR_PACKET_SIZE_MIN 512 #define AXFR_PACKET_SIZE_MAX 65535 #define AXFR_RECORD_BY_PACKET_MIN 0 #define AXFR_RECORD_BY_PACKET_MAX 65535 #define AXFR_RETRY_DELAY_MIN 60 #define AXFR_RETRY_DELAY_MAX 86400 #define AXFR_RETRY_JITTER_MIN 60 #define AXFR_RETRY_JITTER_MAX "don't use me, use the axfr_retry_delay value instead" #define MAX_CONFIG_STRING 50 #define PRINTARGLEN 10 #define PROGRAM_NAME "yadifad" #define PROGRAM_VERSION PACKAGE_VERSION #define RELEASEDATE YADIFA_DNSCORE_RELEASE_DATE #ifndef RUNSTATEDIR #define RUNSTATEDIR LOCALSTATEDIR "/run" #endif /* List of default values for the different configuration parameters */ #define S_CONFIGDIR SYSCONFDIR "/" #define S_CONFIGFILE PROGRAM_NAME ".conf" #define S_CONFIGFILEDYNAMIC PROGRAM_NAME ".conf.dyn" #define S_DATAPATH LOCALSTATEDIR "/zones/" #define S_XFRPATH LOCALSTATEDIR "/zones/xfr/" #define S_KEYSPATH LOCALSTATEDIR "/zones/keys/" /** Keys should not be in "shared" */ #define S_LOGPATH LOGDIR #define S_PIDFILE RUNSTATEDIR "/" PROGRAM_NAME ".pid" #define S_VERSION_CHAOS PACKAGE_VERSION /* limit the size */ #define S_HOSTNAME_CHAOS NULL #define S_SERVERID_CHAOS NULL #define S_DEBUGLEVEL "0" /* default values for SERVER_FL */ #define S_SYSLOG "0" #define S_STATISTICS "1" #define S_STATISTICS_MAX_PERIOD "60" /* 1 -> 31 * 86400 */ #define S_DAEMONRUN "0" #define S_ANSWER_FORMERR_PACKETS "1" #define S_DYNAMIC_PROVISIONING "0" /** \def S_RUNMODE * Run mode of the program */ #define S_RUNMODE RUNMODE_CONTINUE_CLEAN #define S_NETWORK_MODEL "2" #define S_INTERACTIVE "0" #define S_LOG_FROM_START "0" #define S_LOG_FILES_DISABLED "0" /* */ #define S_CPU_COUNT_OVERRIDE "0" /* max 256 */ #define S_THREAD_COUNT_BY_ADDRESS "-1" /* -1 for auto */ #define S_DNSSEC_THREAD_COUNT "0" /* max 1024 */ #define S_ZONE_LOAD_THREAD_COUNT "1" // disk #define ZONE_LOAD_THREAD_COUNT_MIN 1 #define ZONE_LOAD_THREAD_COUNT_MAX 256 #define S_ZONE_SAVE_THREAD_COUNT "1" // disk #define ZONE_SAVE_THREAD_COUNT_MIN 1 #define ZONE_SAVE_THREAD_COUNT_MAX 256 #define S_ZONE_UNLOAD_THREAD_COUNT "1" // cpu #define ZONE_UNLOAD_THREAD_COUNT_MIN 1 #define ZONE_UNLOAD_THREAD_COUNT_MAX 256 #define S_ZONE_DOWNLOAD_THREAD_COUNT "4" // network #define ZONE_DOWNLOAD_THREAD_COUNT_MIN 1 #define ZONE_DOWNLOAD_THREAD_COUNT_MAX 256 /* Chroot, uid and gid */ #define S_CHROOT "0" #define S_LOG_UNPROCESSABLE "0" #define S_CHROOTPATH "/" #define S_UID "0" #define S_GID "0" /** \def S_LISTEN * Listening to all interfaces */ #define S_LISTEN "0.0.0.0;::0" #define S_TRANSFER_SOURCE NULL #if HAS_SYSTEMD_RESOLVED_AVOIDANCE #define S_DO_NOT_LISTEN "127.0.0.53 port 53" #else #define S_DO_NOT_LISTEN "" #endif #define MAX_INTERFACES 256 #define S_TOTALINTERFACES 1 #define S_MAX_TCP_QUERIES "128" /* max : 65536 */ #define S_MAX_TCP_QUERIES_PER_ADDRESS "2" #define S_MAX_SECONDARY_TCP_QUERIES "16" #define S_TCP_QUERY_MIN_RATE "512" /* bytes per second minimum rate */ #define S_TCP_QUEUE_SIZE "1024" #define S_TCP_QUEUE_SIZE_MIN 64 #define S_TCP_QUEUE_SIZE_MAX 65536 #define S_MAX_AXFR "10" #define S_AXFR_MAX_RECORD_BY_PACKET "0" /** No limit. Old applications can only work with this set to 1 */ #define S_AXFR_PACKET_SIZE_MAX "4096" /** plus TSIG */ #define S_AXFR_COMPRESS_PACKETS "1" #define S_AXFR_RETRY_DELAY "600" #define S_AXFR_RETRY_JITTER "180" #define S_AXFR_MEMORY_THREHOLD "65536" #define AXFR_MEMORY_THREHOLD_MIN 0x00000000 // 0MB #define AXFR_MEMORY_THREHOLD_MAX 0x00100000 // 1MB #if HAS_NON_AA_AXFR_SUPPORT #define S_AXFR_STRICT_AUTHORITY "0" #else #define S_AXFR_STRICT_AUTHORITY "1" #endif #define S_AXFR_RETRY_FAILURE_DELAY_MULTIPLIER "5" #define AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MIN 0 #define AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX 86400 #define S_AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX "3600" #define AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX_MIN 0 #define AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX_MAX 604800 #define S_SERVER_RW_BACKLOG_QUEUE_SIZE "16384" #define SERVER_RW_BACKLOG_QUEUE_SIZE_MIN 0x001000 #define SERVER_RW_BACKLOG_QUEUE_SIZE_MAX 0x100000 #define S_XFR_CONNECT_TIMEOUT "5" /* seconds */ #define S_QUERIES_LOG_TYPE "1" /* 0: none, 1: YADIFA, 2: bind 3:both */ #define S_ALLOW_QUERY "any" #define S_ALLOW_UPDATE "none" #define S_ALLOW_TRANSFER "none" #define S_ALLOW_UPDATE_FORWARDING "none" #define S_ALLOW_NOTIFY "any" #define S_ALLOW_CONTROL "none" /** \def S_SERVERPORT * Standard port for listening udp and tcp */ #define S_SERVERPORT "53" /* PREPROCESSOR_INT2STR(DNS_DEFAULT_PORT) */ /* IP FLAGS */ #define S_IPV4 "1" #define S_IPV6 "1" /* QUERIES FLAGS */ #define S_ADDITIONAL_AUTH "1" #define S_AUTHORITY_AUTH "1" #define S_ADDITIONAL_CACHE "1" #define S_AUTHORITY_CACHE "1" #define S_EDNS0 "1" #define S_EDNS0_MAX_SIZE "4096" #define S_RECURSION "1" #define S_S32_VALUE_NOT_SET NULL #define S_SIG_VALIDITY_INTERVAL "30" /* 30 days in days */ #define S_SIG_VALIDITY_REGENERATION "168" /* 7 days in hours 24->168 */ #define S_SIG_VALIDITY_JITTER "3600" /* 1 hour in seconds */ #define S_SIG_SIGNING_TYPE "65534" #define S_NOTIFY_RETRY_COUNT "5" /* 5 retries */ #define S_NOTIFY_RETRY_PERIOD "1" /* first after 1 minute */ #define S_NOTIFY_RETRY_PERIOD_INCREASE "0" /* period increased by "0" after every try */ #define S_ZONE_NOTIFY_AUTO "1" #define S_ZONE_FLAG_DROP_BEFORE_LOAD "0" #define S_ZONE_NO_MASTER_UPDATES "0" #define S_ZONE_FLAG_MAINTAIN_DNSSEC "1" #define S_ZONE_FLAG_TRUE_MULTIMASTER "0" #define S_ZONE_FLAG_RRSIG_NSUPDATE_ALLOWED "0" #define S_MULTIMASTER_RETRIES "0" // in a multimaster setup, how many retries before changing master // 0 is perfectly fine except in true-multimaster mode where the resource cost // asks for some caution. In that case 60 would be a good choice. Maximum is 255 #define S_ZONE_DNSSEC_DNSSEC "off" #define S_JOURNAL_SIZE_KB_DEFAULT "0" // 0 means "automatic" #define S_JOURNAL_SIZE_KB_MIN 0 // less than 64KB is asking for trouble (0 means "automatic") #define S_JOURNAL_SIZE_KB_MAX 3698688 // 3GB /* ------------------------------------------------------------ */ /* List of cases for adjusting the keys configuration parameters */ #define KC_NAME 1 #define KC_ALGORITHM 2 #define KC_SECRET 3 /* List of cases for adjusting the control configuration parameters */ #define CC_NET 1 #define CC_KEYS 2 #define CONTAINER_MAIN 1 #define CONTAINER_ZONE 2 #define CONTAINER_CHANNELS 3 #define CONTAINER_LOGGERS 4 #define CONTAINER_KEYS 5 #define CONTAINER_CONTROL 6 /* Run modes of the program, * only RUNMODE_DAEMON can be asked via the configuration file */ #define RUNMODE_FLAG 0x0F /* Only one of these can be active */ #define RUNMODE_EXIT_CLEAN 0x01 #define RUNMODE_CONTINUE_CLEAN 0x02 /* normal mode */ #define RUNMODE_DAEMON 0x03 /* daemon mode */ #define RUNMODE_INTERACTIVE 0x04 /* interactive mode */ #define RUNMODE_SWITCH_FLAG 0xF0 /* Server flags */ #define SERVER_FL_CHROOT 0x01 #define SERVER_FL_DAEMON 0x02 #define SERVER_FL_STATISTICS 0x04 #define SERVER_FL_ANSWER_FORMERR 0x08 #define SERVER_FL_LOG_UNPROCESSABLE 0x10 #define SERVER_FL_INTERACTIVE 0x20 #define SERVER_FL_DYNAMIC_PROVISIONING 0x40 #define SERVER_FL_LOG_FROM_START 0x8000 #define SERVER_FL_LOG_FILE_DISABLED 0x4000 /* IP flags */ #define IP_FLAGS_IPV4 0x01 #define IP_FLAGS_IPV6 0x02 #if 0 /* fix */ #else #define SIGNATURE_VALIDITY_INTERVAL_MIN 7 /* 7 days */ #endif #define SIGNATURE_VALIDITY_INTERVAL_MAX 366 /* 366 days */ #define SIGNATURE_VALIDITY_INTERVAL_S 86400 /* seconds for that unit */ #if 0 /* fix */ #else #define SIGNATURE_VALIDITY_REGENERATION_MIN 24 /* 1 day */ #endif #define SIGNATURE_VALIDITY_REGENERATION_MAX 168 /* 7 days */ #define SIGNATURE_VALIDITY_REGENERATION_S 3600 /* seconds for that unit */ #define SIGNATURE_VALIDITY_JITTER_MIN 0 #define SIGNATURE_VALIDITY_JITTER_MAX 86400 #define SIGNATURE_VALIDITY_JITTER_S 1 /* seconds for that unit */ #define NOTIFY_RETRY_COUNT_MIN 0 #define NOTIFY_RETRY_COUNT_MAX 10 #define NOTIFY_RETRY_PERIOD_MIN 1 #define NOTIFY_RETRY_PERIOD_MAX 600 #define NOTIFY_RETRY_PERIOD_INCREASE_MIN 0 #define NOTIFY_RETRY_PERIOD_INCREASE_MAX 600 /* ------------------------------------------------------------ */ typedef struct udp udp; struct udp { struct addrinfo *addr; int sockfd; }; typedef struct tcp tcp; struct tcp { struct addrinfo *addr; int sockfd; }; #ifdef WIN32 #ifdef interface #undef interface #endif #endif // WIN32 typedef struct interface interface; struct interface { udp udp; tcp tcp; }; typedef struct scheduler scheduler; struct scheduler { int sockfd; }; #define CONFIG_READER_CONTEXT_MAX_DEPTH 128 typedef struct config_reader_context config_reader_context; struct config_reader_context { s32 top; // -1 bool dynamic; FILE* data[CONFIG_READER_CONTEXT_MAX_DEPTH]; char* file_name[CONFIG_READER_CONTEXT_MAX_DEPTH]; }; /** \struct config_data * Struct with the configuration data. This data can be the default * data, data from a configuration file, or data as arguments on * the command line */ typedef struct config_data config_data; #define YGCONFIG_TAG 0x4749464e4f434759 #define CONFIG_SIGNATURE_TYPE_CONFIGURABLE 0 struct config_data { // Which are the interfaces to listen to host_address *listen; // Which are the interfaces to not listen to host_address *do_not_listen; // List of hosts registered by the TCP manager host_address *known_hosts; // List of hosts for default transfer sources, can be empty host_address *transfer_source; /* General variables */ char *data_path; /* zones */ char *xfr_path; /* full and incremental images base ... */ #ifndef WIN32 char *chroot_path; /* chroot point */ #endif char *log_path; /* log files */ char *keys_path; /* keys */ char *config_file; /* config */ char *pid_file; /* pid file path and name */ char *version_chaos; char *hostname_chaos; char *serverid_chaos; char *server_port; #if HAS_EVENT_DYNAMIC_MODULE ptr_vector dynamic_modules; #endif pid_t pid; /* Server variables */ u16 server_flags; int total_interfaces; int cpu_count_override; s32 thread_count_by_address; int thread_affinity_base; int thread_affinity_multiplier; #if DATABASE_ZONE_RRSIG_THREAD_POOL int dnssec_thread_count; #endif int zone_load_thread_count; int zone_store_thread_count; int zone_unload_thread_count; int zone_download_thread_count; int max_tcp_queries; int max_tcp_queries_per_address; int max_secondary_tcp_queries; int tcp_query_min_rate; int tcp_queue_size; int axfr_max_record_by_packet; int axfr_max_packet_size; int axfr_retry_delay; int axfr_retry_jitter; u32 axfr_retry_failure_delay_multiplier; u32 axfr_retry_failure_delay_max; u32 axfr_memory_threshold; int xfr_connect_timeout; u32 statistics_max_period; int edns0_max_size; int network_model; // 0: default MT, 1: experimental RqW u32 worker_backlog_queue_size; s32 set_nofile; bool axfr_compress_packets; bool axfr_strict_authority; // if the AA bit isn't set, AXFR is rejected /**/ access_control *ac; /**/ gid_t gid; uid_t uid; u16 process_flags; u16 server_port_value; //u8 ip; /* * The pid of the only child (a.k.a the server) */ zdb *database; u32 queries_log_type; #if DNSCORE_HAS_DNSSEC_SUPPORT u32 sig_validity_interval; u32 sig_validity_regeneration; u32 sig_validity_jitter; #if CONFIG_SIGNATURE_TYPE_CONFIGURABLE u16 sig_signing_type; #endif #endif double tcp_query_min_rate_us; bool chrooted; bool reloadable; bool hidden_master; bool check_policies; #if DEBUG bool print_config; #endif }; /** * zone_desc filter callback, * The second argument is the proprietary data passed to the * * Must return 1 for accept, 0 for reject, or an error code. * */ struct zone_desc_s; typedef struct zone_desc_s zone_desc_s; typedef ya_result config_section_zone_filter_callback(zone_desc_s *, void *); #ifndef CONFS_MAIN_C_ extern config_data *g_config; #endif /** * @brief Tool function printing all the known names in a table. */ /* ------------------------------------------------------------ */ void config_logger_setdefault(); void config_logger_cleardefault(); /* ------------------------------------------------------------ */ ya_result yadifad_config_init(); ya_result yadifad_config_cmdline(int argc, char **argv); ya_result yadifad_config_read(const char *config_file); ya_result yadifad_config_finalize(); ya_result yadifad_config_update(const char *config_file); ya_result yadifad_config_update_zone(const char *config_file, const ptr_set *fqdn); void yadifad_print_usage(const char *name); /* ------------------------------------------------------------ */ ya_result confs_set_dnssec(const char *value, u32 *dest, anytype notused); void config_zone_print(zone_desc_s *zone_desc, output_stream *os); /** * * Enables a callback filter that is called before pushing a zone_desc to the database service. * * @param cb a callback function or NULL to reset to the "accept all" filter. * @param params a pointer that will be passed to the callback */ void config_section_zone_set_filter(config_section_zone_filter_callback *cb, void *params); bool config_check_bounds_s32(s32 minval, s32 maxval, s32 val, const char *name); #ifdef __cplusplus } #endif #endif /* CONFS_H_ */ /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-desc-load.h0000644000000000000000000000013214505005533025050 xustar000000000000000030 mtime=1695812443.501997355 30 atime=1695812445.783030024 30 ctime=1695812495.511742239 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-desc-load.h0000664000374500037450000000376414505005533025024 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include "zone_desc.h" void database_load_zone_desc(zone_desc_s *zone_desc); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-desc-unload.h0000644000000000000000000000013214505005533025413 xustar000000000000000030 mtime=1695812443.504997398 30 atime=1695812445.783030024 30 ctime=1695812495.513742268 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-desc-unload.h0000664000374500037450000000377614505005533025372 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include "zone_desc.h" void database_service_zone_desc_unload(zone_desc_s *zone_desc); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-download.h0000644000000000000000000000013214505005533025024 xustar000000000000000030 mtime=1695812443.494997255 30 atime=1695812445.783030024 30 ctime=1695812495.515742297 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-download.h0000664000374500037450000000406714505005533024775 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include void database_service_zone_axfr_query(const u8 *origin); void database_service_zone_ixfr_query(const u8 *origin); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-freeze.h0000644000000000000000000000013214505005533024475 xustar000000000000000030 mtime=1695812443.311994634 30 atime=1695812445.781029996 30 ctime=1695812495.517742326 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-freeze.h0000664000374500037450000000377214505005533024450 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include "zone_desc.h" void database_service_zone_freeze(zone_desc_s *zone_desc); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-load.h0000644000000000000000000000013214505005533024134 xustar000000000000000030 mtime=1695812443.512997513 30 atime=1695812445.783030024 30 ctime=1695812495.519742354 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-load.h0000664000374500037450000000377414505005533024111 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include "zone_desc.h" ya_result database_service_zone_load(zone_desc_s *zone_desc); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-mount.h0000644000000000000000000000013114505005533024356 xustar000000000000000030 mtime=1695812443.330994906 29 atime=1695812445.78203001 30 ctime=1695812495.521742383 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-mount.h0000664000374500037450000000377714505005533024337 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include void database_service_zone_mount(zone_desc_s *zone_desc); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-store.h0000644000000000000000000000013214505005533024351 xustar000000000000000030 mtime=1695812443.530997771 30 atime=1695812445.784030039 30 ctime=1695812495.523742411 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-store.h0000664000374500037450000000377114505005533024323 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include "zone_desc.h" void database_service_zone_store(zone_desc_s *zone_desc); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-unfreeze.h0000644000000000000000000000013114505005533025037 xustar000000000000000030 mtime=1695812443.498997312 30 atime=1695812445.783030024 29 ctime=1695812495.52574244 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-unfreeze.h0000664000374500037450000000377414505005533025015 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include "zone_desc.h" void database_service_zone_unfreeze(zone_desc_s *zone_desc); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-unload.h0000644000000000000000000000013214505005533024477 xustar000000000000000030 mtime=1695812443.515997556 30 atime=1695812445.783030024 30 ctime=1695812495.527742469 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-unload.h0000664000374500037450000000401114505005533024435 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include "zone_desc.h" void database_service_zone_unload(zone_desc_s *zone_desc, zdb_zone *zone); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-unmount.h0000644000000000000000000000013214505005533024722 xustar000000000000000030 mtime=1695812443.539997899 30 atime=1695812445.784030039 30 ctime=1695812495.529742497 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-unmount.h0000664000374500037450000000400114505005533024657 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include void database_service_zone_unmount(zone_desc_s *zone_desc); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service.h0000644000000000000000000000013114505005533022245 xustar000000000000000030 mtime=1695812443.487997155 29 atime=1695812445.78203001 30 ctime=1695812495.531742526 yadifa-2.6.5-11201/sbin/yadifad/database-service.h0000664000374500037450000003767114505005533022226 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include #include #include #include #include "server.h" #include "config_error.h" #include "zone.h" #define DATABASE_SERVICE_STOP 0 #define DATABASE_SERVICE_ZONE_DESC_LOAD 1 #define DATABASE_SERVICE_ZONE_DESC_UNLOAD 2 #define DATABASE_SERVICE_ZONE_LOAD 3 #define DATABASE_SERVICE_ZONE_LOADED_EVENT 4 #define DATABASE_SERVICE_ZONE_MOUNT 5 #define DATABASE_SERVICE_ZONE_MOUNTED_EVENT 6 #define DATABASE_SERVICE_ZONE_UNMOUNT 7 #define DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT 8 #define DATABASE_SERVICE_ZONE_UNLOAD 9 #define DATABASE_SERVICE_ZONE_UNLOADED_EVENT 10 #define DATABASE_SERVICE_ZONE_SAVE_TEXT 11 #define DATABASE_SERVICE_QUERY_AXFR 12 #define DATABASE_SERVICE_QUERY_IXFR 13 #define DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT 14 #define DATABASE_SERVICE_SET_DROP_AFTER_RELOAD 15 #define DATABASE_SERVICE_CLEAR_DROP_AFTER_RELOAD 16 #define DATABASE_SERVICE_DO_DROP_AFTER_RELOAD 17 #define DATABASE_SERVICE_RECONFIGURE_BEGIN 18 #define DATABASE_SERVICE_RECONFIGURE_END 19 #define DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES 20 #define DATABASE_SERVICE_ZONE_FREEZE 21 #define DATABASE_SERVICE_ZONE_UNFREEZE 22 #define DATABASE_SERVICE_ZONE_PROCESSED 23 #define DATABASE_SERVICE_CALLBACK 24 // #define DATABASE_SERVICE_OPERATION_COUNT 25 struct database_message_stop_s { u8 type; }; /// @note HAS_DYNAMIC_PROVISIONING struct database_message_zone_desc_load_s { u8 type; zone_desc_s *zone_desc; }; struct database_message_zone_desc_unload_s { u8 type; }; struct database_message_zone_desc_destroy_s { u8 type; zone_desc_s *zone_desc; }; struct database_message_zone_desc_process_s { u8 type; zone_desc_s *zone_desc; }; struct database_message_origin_process_s { u8 type; zone_desc_s *zone_desc; }; struct database_message_zone_load_s { u8 type; }; struct database_message_zone_store_s { u8 type; bool clear; }; struct database_message_zone_unload_s { u8 type; zdb_zone *zone; // to be destroyed }; struct database_message_zone_update_signatures_s { u8 type; zone_desc_s *expected_zone_desc; zdb_zone *expected_zone; // to be destroyed }; struct database_message_zone_loaded_event_s { u8 type; ya_result result_code; // yes, I meant to put this 32 bits field before the pointers ... zone_desc_s *zone_desc; zdb_zone *zone; // to be mounted }; struct database_message_zone_mounted_event_s { u8 type; ya_result result_code; // yes, I meant to put this 32 bits field before the pointers ... zone_desc_s *zone_desc; zdb_zone *zone; // mounted }; struct database_message_zone_unloaded_event_s { u8 type; ya_result result_code; // yes, I meant to put this 32 bits field before the pointers ... zone_desc_s *zone_desc; zdb_zone *zone; // to be unloaded }; struct database_message_zone_unmounted_event_s { u8 type; zone_desc_s *zone_desc; // }; struct database_message_zone_downloaded_event_s { u8 type; u16 download_type; // yes, I meant to put this 16 bits field before the 32 bits ones ... u32 serial; ya_result result_code; }; struct database_message_drop_after_reload_s { u8 type; ptr_set zone_set; bool do_subset; }; /** * void* args * bool delete_only (do not run the task, just cleanup the args) */ typedef void (*database_message_callback_function)(void*, bool); struct database_message_callback_s { u8 type; database_message_callback_function callback; void* args; u64 timestamp; const char * name; }; typedef struct database_message_callback_s database_message_callback_s; /// typedef struct database_message database_message; struct database_message { u8 *origin; union { u8 type; struct database_message_stop_s stop; /// @note HAS_DYNAMIC_PROVISIONING struct database_message_zone_desc_load_s zone_desc_load; struct database_message_zone_desc_unload_s zone_desc_unload; struct database_message_zone_desc_destroy_s zone_desc_destroy; struct database_message_zone_desc_process_s zone_desc_process; struct database_message_origin_process_s origin_process; struct database_message_zone_load_s zone_load; struct database_message_zone_store_s zone_store; struct database_message_zone_unload_s zone_unload; struct database_message_zone_update_signatures_s zone_update_signatures; /// struct database_message_zone_loaded_event_s zone_loaded_event; struct database_message_zone_mounted_event_s zone_mounted_event; struct database_message_zone_unloaded_event_s zone_unloaded_event; struct database_message_zone_unmounted_event_s zone_unmounted_event; struct database_message_zone_downloaded_event_s zone_downloaded_event; // struct database_message_zone_processed_event_s zone_processed_event; struct database_message_drop_after_reload_s drop_after_reload; struct database_message_callback_s callback; } payload; }; bool database_service_started(); ya_result database_service_init(); ya_result database_service_start(); ya_result database_service_stop(); ya_result database_service_finalize(); void database_load_all_zones(); /** * Loads then mounts a zone in the database. * This is using the registered zone settings (zone_desc_s) to do so. * The task is done in the background. */ void database_zone_load(const u8 *origin); /** * Unloads a zone from memory. If the zone is mounted it will be first be unmounted. * The task is done in the background. */ void database_zone_unload(zdb_zone *zone); void database_zone_freeze(const u8 *origin); void database_zone_unfreeze(const u8 *origin); /** * Enqueues the storage of a zone * * @param origin */ void database_zone_store(const u8 *origin); /** * Enqueues the storage of a zone, optionally clearing its journal * * @param origin */ void database_zone_store_ex(const u8 *origin, bool clear_journal); /** * Saves a zone in the current thread using the provided locks (0 meaning: do not try to lock) * Not locking puts the responsibility of the lock to the caller as having this code running * without any lock whatsoever on the descriptor/zone will give undefined results, a.k.a : crash. * * @param zone_desc * @param desclockowner * @param zonelockowner * @param save_unmodified * @return */ #define DATABASE_SERVICE_ZONE_SAVE_DEFAULTS ZDB_ZONE_WRITE_TEXT_FILE_DEFAULTS #define DATABASE_SERVICE_ZONE_SAVE_FORCE_LABEL ZDB_ZONE_WRITE_TEXT_FILE_FORCE_LABEL #define DATABASE_SERVICE_ZONE_SAVE_IGNORE_SHUTDOWN ZDB_ZONE_WRITE_TEXT_FILE_IGNORE_SHUTDOWN #define DATABASE_SERVICE_ZONE_SAVE_UNMODIFIED 4 ya_result database_service_zone_store_ex(zone_desc_s *zone_desc, u8 desclockowner, u8 zonelockowner, u8 flags); /// @note HAS_DYNAMIC_PROVISIONING /** * * Loads or updates the zone settings. * * If the service is running, * the task is done in the background, * else * the zone is registered. * Note that direct registration is only meant to be used at program startup. * * @param zone_desc */ void database_zone_desc_load(zone_desc_s *zone_desc); /** * Unloads the zone settings. * The zone will be unmounted and unloaded first. * The task is done in the background. * * @param origin */ void database_zone_desc_unload(const u8 *origin); /** * Returns true if the zone with the origin is mounted * * @param origin * @return */ bool database_zone_desc_is_mounted(const u8* origin); /** * * Does an AXFR query for the origin. * If a new zone is downloaded, its loading is queued. * * @param origin */ void database_zone_axfr_query(const u8 *origin); /** * * Does an AXFR query for the origin at a given time * If a new zone is downloaded, its loading is queued. * * @param origin * @param at epoch */ void database_zone_axfr_query_at(const u8 *origin, time_t at); /** * Does an IXFR query for the origin. * If changes are downloaded, they are loaded into the zone. * * @param origin */ void database_zone_ixfr_query(const u8 *origin); /** * * Does an IXFR query for the origin at a given time * If changes are downloaded, they are loaded into the zone. * * @param origin * @param at epoch */ void database_zone_ixfr_query_at(const u8 *origin, time_t at); /** * Creates an empty zone setting for the given origin. * * @param origin * @return */ ya_result database_zone_create(const u8 *origin); /** * Updates the file path of a zone setting * * @param origin * @param file_path * @return */ ya_result database_zone_set_file(const u8 *origin, const char *file_path); /** * * Updates the zone type of a zone setting * * @param origin * @param master_slave_etc * @return */ ya_result database_zone_set_type(const u8 *origin, u8 master_slave_etc); /** * Commits the changes to a zone setting. * * @param origin * @return */ ya_result database_zone_apply(const u8* origin); void database_set_drop_after_reload_for_set(const ptr_set *fqdn_set); /* void database_clear_drop_after_reload(); void database_do_drop_after_reload(); */ void database_zone_reconfigure_do_drop_and_disable(bool do_drop_after_reload); bool database_zone_is_reconfigure_enabled(); bool database_zone_try_reconfigure_enable(); void database_zone_reconfigure_disable(); void database_zone_postpone_reconfigure_all(); void database_zone_postpone_reconfigure_zones(); void database_zone_postpone_reconfigure_zone(const ptr_set *fqdn_set); /** * Queues a function in the thread pool for loading zones * * @param func * @param parm * @param counter * @param categoryname */ void database_service_zone_load_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname); /** * Queues a function in the thread pool for saving zones * * @param func * @param parm * @param counter * @param categoryname */ void database_service_zone_store_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char *categoryname); /** * Queues a function in the thread pool for unloading zones * * @param func * @param parm * @param counter * @param categoryname */ void database_service_zone_unload_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname); /** * Queues a function in the thread pool for downloading zones * * @param func * @param parm * @param counter * @param categoryname */ void database_service_zone_download_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname); void database_service_zone_resignature_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname); /** * Tells the database service that a zone has been loaded or failed to load. * Meant to be used internally. * * @param zone_desc the descriptor * @param zone the zone structure that contains the zone (may be NULL) * @param result_code the error code */ void database_fire_zone_loaded(zone_desc_s *zone_desc, zdb_zone *zone, ya_result result_code); /** * Tells the database service that a zone has been mounted or failed to mount. * Meant to be used internally. * * @param zone_desc the descriptor * @param zone the zone structure that contains the zone (may be NULL) * @param result_code the error code */ void database_fire_zone_mounted(zone_desc_s *zone_desc, zdb_zone *zone, ya_result result_code); /** * Tells the database service that a zone has been unloaded. * Although there is a result code, it most likely cannot fail with the current implementation. * Meant to be used internally. * * @param zone a zone to mount in its place * @param result_code */ void database_fire_zone_unloaded(zdb_zone *zone, ya_result result_code); /** * Tells the database service that a zone has been unloaded. * Meant to be used internally. * * @param zone_desc */ void database_fire_zone_unmounted(zone_desc_s *zone_desc); /** * Tells the database service that a zone has been downloaded. * Meant to be used internally. * * @param origin * @param qtype AXFR/IXFR * @param serial the last serial of the zone * @param result_code */ void database_fire_zone_downloaded(const u8 *origin, u16 qtype, u32 serial, ya_result result_code); /** * Return the name of a command id. Used for debugging/logging. * * @param id * @return */ const char *database_service_operation_get_name(u32 id); /** * Triggers a re-signature, should only be used by database-service-zone-resignature * * @param origin * @param expected_zone_desc * @param expected_zone */ void database_zone_update_signatures(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone); void database_zone_update_signatures_resume(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone); void database_zone_update_signatures_allow_queue(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone); /** * * Sets an alarm to enqueue a zone maintenance at a given time (best effort) * * @param zone * @param at */ void database_zone_update_signatures_at(zdb_zone *zone, u32 at); /** * * Creates an empty, invalid zone for every single registered zone descriptor (config) * */ void database_service_create_invalid_zones(); bool database_service_is_running(); void database_service_run_garbage_collector(); void database_fire_zone_processed(zone_desc_s *zone_desc); void database_post_callback(database_message_callback_function callback, void *args, const char * const name); bool database_server_down_cache_query(const host_address *ha); void database_server_down_cache_add(const host_address *ha); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database.h0000644000000000000000000000013214505005533020610 xustar000000000000000030 mtime=1695812443.529997757 30 atime=1695812445.784030039 30 ctime=1695812495.533742555 yadifa-2.6.5-11201/sbin/yadifad/database.h0000664000374500037450000001043614505005533020556 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef DATABASE_H_ #define DATABASE_H_ #ifdef __cplusplus extern "C"{ #endif #include "server-config.h" #include #include #include #include #include #include "zone.h" #if HAS_RRL_SUPPORT #include "rrl.h" #endif /* List of database type in string form */ #define DB_STRING_NO "no database" #define DATABASE_JOURNAL_MINIMUM_SIZE 65536 void database_init(); void database_finalize(); ya_result database_clear_zones(zdb *database, zone_data_set *dset); ya_result database_startup(zdb **); /** \brief Get dns answer from database * * @param database * @param mesg */ static inline void database_query(zdb *database, message_data *mesg) { zdb_query_and_update(database, mesg, message_get_pool_buffer(mesg)); #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) /* NOTE: the TSIG information is in mesg */ { tsig_sign_answer(mesg); } #endif } #if HAS_RRL_SUPPORT /** \brief Get DNS answer from database * * Get DNS answer from database * * @param mesg * * @return RRL code */ static inline ya_result database_query_with_rrl(zdb *db, message_data *mesg) { ya_result rrl = zdb_query_and_update_with_rrl(db, mesg, message_get_pool_buffer(mesg), rrl_process); #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) /* NOTE: the TSIG information is in mesg */ { tsig_sign_answer(mesg); } #endif return rrl; } #endif ya_result database_apply_nsec3paramqueued(zdb_zone *zone, zdb_packed_ttlrdata *rrset, u8 lock_owner); ya_result database_update(zdb *database, message_data *mesg); ya_result database_print_zones(zone_desc_s *, char *); ya_result database_shutdown(zdb *); /* Slave only */ ya_result database_zone_refresh_maintenance_wih_zone(zdb_zone* zone, u32 next_alarm_epoch); ya_result database_zone_refresh_maintenance(zdb *database, const u8 *origin, u32 next_alarm_epoch); bool database_are_all_zones_stored_to_disk(); void database_wait_all_zones_stored_to_disk(); void database_disable_all_zone_store_to_disk(); ya_result database_store_all_zones_to_disk(); #ifdef __cplusplus } #endif #endif /* DATABASE_H_ */ /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/dnssec-policy.h0000644000000000000000000000013214505005533021620 xustar000000000000000030 mtime=1695812443.491997212 30 atime=1695812445.783030024 30 ctime=1695812495.535742583 yadifa-2.6.5-11201/sbin/yadifad/dnssec-policy.h0000664000374500037450000001133714505005533021567 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup ### * @brief */ #pragma once #include #include #include "zone-signature-policy.h" typedef struct dnssec_policy_desc_s dnssec_policy_desc_s; struct dnssec_policy_desc_s { char *id; char *description; char *denial; ptr_vector key_suite; s32 ds_ttl; u8 flags; // weaker-key & stronger-key u8 max_key; // not used }; typedef struct key_suite_desc_s key_suite_desc_s; struct key_suite_desc_s { char *id; char *key_template; char *key_roll; }; typedef struct key_template_desc_s key_template_desc_s; struct key_template_desc_s { char *id; bool ksk; u32 algorithm; u16 size; char *engine; }; typedef struct denial_desc_s denial_desc_s; struct denial_desc_s { char *id; u32 type; u32 resalting; char *salt; char *algorithm; u8 algorithm_val; u16 iterations; u8 salt_length; bool optout; }; typedef struct key_roll_desc_s key_roll_desc_s; struct key_roll_desc_s { char *id; char *generate; char *publish; char *activate; char *inactive; char *remove; char *ds_publish; char *ds_remove; }; yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ixfr.h0000644000000000000000000000013014505005533020012 xustar000000000000000028 mtime=1695812443.5329978 30 atime=1695812445.784030039 30 ctime=1695812495.537742612 yadifa-2.6.5-11201/sbin/yadifad/ixfr.h0000664000374500037450000000610014505005533017753 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #ifndef _IXFR_H #define _IXFR_H #include #include #if DNSCORE_HAS_TCP_MANAGER #include #endif #include "database.h" #ifdef __cplusplus extern "C" { #endif #if DNSCORE_HAS_TCP_MANAGER ya_result ixfr_process(message_data *mesg, tcp_manager_socket_context_t *sctx); #else ya_result ixfr_process(message_data *mesg, int sockfd); #endif /** * * Send an IXFR query to a master and handle the answer (loads the zone). * */ ya_result ixfr_query(const host_address *servers, zdb_zone *zone, u32 *output_loaded_serial); /** * Connects to the server and sends an IXFR query with the given parameters. * In case of success the input and output streams are tcp streams to the server, ready to read the answer * In case of error the streams are undefined * * @param servers * @param origin * @param ttl * @param rdata * @param rdata_size * @param is * @param os * @return */ ya_result ixfr_start_query(const host_address *servers, const u8 *origin, u32 ttl, const u8 *rdata, u16 rdata_size, input_stream *is, output_stream *os, message_data *ixfr_queryp); #ifdef __cplusplus } #endif #endif /* _IXFR_H */ /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/log_query.h0000644000000000000000000000013214505005533021052 xustar000000000000000030 mtime=1695812443.326994849 30 atime=1695812445.781029996 30 ctime=1695812495.539742641 yadifa-2.6.5-11201/sbin/yadifad/log_query.h0000664000374500037450000000635614505005533021026 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logging Server logging * @ingroup yadifad * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _LOG_QUERY_H #define _LOG_QUERY_H #include #include #include /******************************************************************************************************************* * * QUERY LOG SPECIALISED FUNCTIONS * ******************************************************************************************************************/ #ifndef LOG_QUERY_C_ extern logger_handle* g_queries_logger; #endif #define log_query_i(...) logger_handle_msg(g_queries_logger,MSG_INFO,__VA_ARGS__) #define log_query_w(...) logger_handle_msg(g_queries_logger,MSG_WARNING,__VA_ARGS__) #define log_query_e(...) logger_handle_msg(g_queries_logger,MSG_ERR,__VA_ARGS__) #ifndef LOG_QUERY_C_ typedef void log_query_function(int, message_data*); #endif extern log_query_function* log_query; void log_query_bind(int socket_fd, message_data *mesg); void log_query_yadifa(int socket_fd, message_data *mesg); static inline void log_query_both(int socket_fd, message_data *mesg) { log_query_yadifa(socket_fd, mesg); log_query_bind(socket_fd, mesg); } static inline void log_query_none(int socket_fd, message_data *mesg) { (void)socket_fd; (void)mesg; } void log_query_set_mode(u32 mode); #endif /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/log_statistics.h0000644000000000000000000000013114505005533022076 xustar000000000000000030 mtime=1695812443.475996983 29 atime=1695812445.78203001 30 ctime=1695812495.541742669 yadifa-2.6.5-11201/sbin/yadifad/log_statistics.h0000664000374500037450000000501314505005533022040 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logging Server logging * @ingroup yadifad * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _LOG_STATISTICS_H #define _LOG_STATISTICS_H /******************************************************************************************************************* * * Statistics logging * ******************************************************************************************************************/ #include "server.h" #ifndef LOG_STATISTICS_C_ extern logger_handle* g_statistics_logger; #endif void log_statistics_legend(); void log_statistics(server_statistics_t *server_statistics); #endif /* _LOG_STATISTICS_H */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/notify.h0000644000000000000000000000013214505005533020354 xustar000000000000000030 mtime=1695812443.533997814 30 atime=1695812445.784030039 30 ctime=1695812495.543742698 yadifa-2.6.5-11201/sbin/yadifad/notify.h0000664000374500037450000000574114505005533020325 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup yadifad * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _NOTIFY_H #define _NOTIFY_H #include "server-config.h" #if DNSCORE_HAS_CTRL #include "ctrl.h" #endif #include #include #include "database.h" /** * @brief Handle a notify from the master (or another slave) * * @param database : the database * @param mesg : the input message * * @retval OK * @retval NOK */ ya_result notify_process(message_data *msg); /** * Sends a notify to all the slave for a given domain name * * @param origin */ void notify_slaves(const u8 *origin); /** * Stops all notification for zone with origin * * @param origin */ void notify_clear(const u8 *origin); ya_result notify_service_init(); /** * Starts the notify service thread */ ya_result notify_service_start(); void notify_wait_servicing(); /** * Stops the notify service thread */ ya_result notify_service_stop(); ya_result notify_service_finalize(); bool notify_has_candidates_for_zone(zone_desc_s *zone_desc); #endif /* _NOTIFY_H */ /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/poll-util.h0000644000000000000000000000013114505005533020764 xustar000000000000000030 mtime=1695812443.471996926 29 atime=1695812445.78203001 30 ctime=1695812495.545742726 yadifa-2.6.5-11201/sbin/yadifad/poll-util.h0000664000374500037450000000533114505005533020731 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /******************************************************************************************************************* * * TCP USAGE LIMITS * ******************************************************************************************************************/ #pragma once #include #include #if !DNSCORE_HAS_TCP_MANAGER /** * This code maintains the limit on the TCP sockets */ /** * Frees the pool. */ void poll_free(); /** * * Allocates a number of slots for (TCP) connections * This is global to yadifad * */ void poll_alloc(nfds_t count); /** * Tries to add a file descriptor to the pool */ bool poll_add(int fd); /** * Look at the current state of the pool, adjusts the currently used slots. Returns the number of used slots. */ int poll_update(); #else #pragma message("poll-util.h should not be included if dnscore/tcp-manager.h is included") #endif yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/process_class_ch.h0000644000000000000000000000013214505005533022361 xustar000000000000000030 mtime=1695812443.508997456 30 atime=1695812445.783030024 30 ctime=1695812495.547742755 yadifa-2.6.5-11201/sbin/yadifad/process_class_ch.h0000664000374500037450000000450614505005533022330 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #pragma once #include void class_ch_set_hostname(const char *name); void class_ch_set_version(const char *name); void class_ch_set_id_server(const char *name); /** * Answers to a CH query. Query operation assumed. */ void class_ch_process(message_data *mesg); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server-sm.h0000644000000000000000000000013214505005533020767 xustar000000000000000030 mtime=1695812443.544997971 30 atime=1695812445.785030053 30 ctime=1695812495.549742784 yadifa-2.6.5-11201/sbin/yadifad/server-sm.h0000664000374500037450000000421414505005533020732 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup server Server * @ingroup yadifad * @brief Buffered input UDP server * * @{ */ #pragma once #include #define SERVER_NETWORK_MODEL_MM 2 ya_result server_sm_context_init(int workers_per_interface); ya_result server_sm_query_loop(struct service_worker_s *worker); /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server.h0000644000000000000000000000013214505005533020352 xustar000000000000000030 mtime=1695812443.530997771 30 atime=1695812445.784030039 30 ctime=1695812495.551742812 yadifa-2.6.5-11201/sbin/yadifad/server.h0000664000374500037450000001570414505005533020323 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup server Server * @ingroup yadifad * @brief Server initialisation and launch * * @{ */ #pragma once /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include #include #include #include #include "confs.h" #include "server_context.h" #include "server_error.h" #ifndef SERVER_C_ extern logger_handle *g_server_logger; extern volatile int program_mode; #endif #include #define SOA_MIN_REFRESH 60 #define SOA_MIN_RETRY 60 #define SOA_MIN_EXPIRE 60 #define TPROCPRM_TAG 0x4d5250434f525054 #define POLLFDBF_TAG 0x464244464c4c4f50 #define SERVER_POOL_BUFFER_SIZE 0x20000 /* ------------------------------------------------------------ * * PROTOTYPES */ /** * The servers are completely static entities with static accesses. * This is really just a set of methods to call to make a server type ready and run it. */ struct server_desc_s { ya_result (* const context_init)(int workers_per_interface); ya_result (* const loop)(struct service_worker_s *worker); const char *name; }; typedef struct server_statistics_t server_statistics_t; #define SUCCESS_DROPPED ((int)0x80ff0001) /** * volatile is only needed for variables changed by another thread */ #define SERVER_STATISTICS_ERROR_CODES_COUNT 32 struct server_statistics_t { mutex_t mtx; volatile u64 input_loop_count; volatile u64 input_timeout_count; volatile u64 loop_rate_counter; volatile u64 loop_rate_elapsed; /* udp */ #ifndef WIN32 volatile u64 udp_input_count __attribute__ ((aligned (64))); volatile u64 udp_queries_count __attribute__ ((aligned (64))); #else volatile u64 udp_input_count; volatile u64 udp_queries_count; #endif volatile u64 udp_notify_input_count; volatile u64 udp_updates_count; volatile u64 udp_dropped_count; volatile u64 udp_output_size_total; volatile u64 udp_undefined_count; volatile u64 udp_referrals_count; /* tcp */ volatile u64 tcp_input_count; volatile u64 tcp_queries_count; volatile u64 tcp_notify_input_count; volatile u64 tcp_updates_count; volatile u64 tcp_dropped_count; volatile u64 tcp_output_size_total; volatile u64 tcp_undefined_count; volatile u64 tcp_referrals_count; volatile u64 tcp_axfr_count; volatile u64 tcp_ixfr_count; volatile u64 tcp_overflow_count; /* rrl */ #if HAS_RRL_SUPPORT volatile u64 rrl_slip; volatile u64 rrl_drop; #endif /* answers */ volatile u64 udp_fp[SERVER_STATISTICS_ERROR_CODES_COUNT]; volatile u64 tcp_fp[SERVER_STATISTICS_ERROR_CODES_COUNT]; }; struct network_thread_context_base_s { struct service_worker_s *worker; server_statistics_t *statisticsp; thread_t idr; int sockfd; u16 idx; volatile bool must_stop; }; typedef struct network_thread_context_base_s network_thread_context_base_t; void server_process_message_udp_set_database(zdb *db); int server_process_message_udp(network_thread_context_base_t *ctx, message_data *mesg); #define TCPSTATS(__field__) mutex_lock(&server_statistics.mtx);server_statistics. __field__ ;mutex_unlock(&server_statistics.mtx) #define TCPSTATS_LOCK() mutex_lock(&server_statistics.mtx) #define TCPSTATS_FIELD(__field__) server_statistics. __field__ #define TCPSTATS_UNLOCK() mutex_unlock(&server_statistics.mtx) #ifndef SERVER_C_ extern server_statistics_t server_statistics; #endif void server_tcp_allocate_poll(struct pollfd **pollfdsp, unsigned int *pollfds_sizep); void server_tcp_accept_loop(struct service_worker_s *worker, server_statistics_t **statistics_array, u32 statistics_array_size); void server_tcp_process(int sockfd); /** * Initialises the DNS service. * * @return an error code */ ya_result server_service_init(); /** * Returns TRUE iff the service has been started. * * @return TRUE iff the service has been started. */ bool server_service_started(); /** * Starts the DNS service. * * @return an error code */ ya_result server_service_start(); /** * Starts the DNS service and waits for it to stop. * This is the most efficient startup when its use is possible. * * @return an error code */ ya_result server_service_start_and_wait(); /** * Waits for the DNS service to stop * * @return an error code */ ya_result server_service_wait(); /** * Tells the DNS service to reconfigure at the earliest convenience * * @return an error code */ ya_result server_service_reconfigure(); /** * Tell the DNS service to stop, do not wait for completion. * * @return an error code */ ya_result server_service_stop_nowait(); /** * Closes all server sockets (UDP/TCP) */ void server_context_close(); /** * Stops the DNS service. * * @return an error code */ ya_result server_service_stop(); /** * Finalise the DNS service. * * @return an error code */ ya_result server_service_finalize(); void server_tcp_client_register(const struct sockaddr_storage* sa, s64 connections_max); s64 server_tcp_client_connections_max(const struct sockaddr_storage* sa, s64 default_value); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server_context.h0000644000000000000000000000013214505005533022116 xustar000000000000000030 mtime=1695812443.506997427 30 atime=1695812445.783030024 30 ctime=1695812495.553742841 yadifa-2.6.5-11201/sbin/yadifad/server_context.h0000664000374500037450000001117214505005533022062 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server Server * @ingroup yadifad * @brief * * @{ */ #pragma once #include "server-config.h" #include #include "database.h" #include "confs.h" #ifdef __cplusplus extern "C" { #endif typedef struct server_context_s server_context_s; /** * This structure describes every single piece of information required * for setting up the server workers. */ struct server_context_s { host_address **listen; u32 listen_count; // struct addrinfo **udp_interface; u32 udp_interface_count; struct addrinfo **tcp_interface; u32 tcp_interface_count; // int *udp_socket; // sorted by interface u32 udp_socket_count; // int *tcp_socket; u32 tcp_socket_count; // the fields below have to be set by the network model setup in server-rw.c u32 udp_unit_per_interface; // = udp_socket_count / listen_count u32 tcp_unit_per_interface; // = tcp_socket_count / listen_count u32 thread_per_udp_worker_count;// = mt: 1, rw: 2 u32 thread_per_tcp_worker_count;// = mt: 1, rw: 1 u32 worker_backlog_queue_size; // this value indicates the backlog entries for the workers for the models that support it // if the server is overloaded, that's how many messages will be kept for later processing until // new queries are dropped. (Also messages are to be pushed out of the queue after a small amount // of time e.g.: 1 to 3 seconds) // on server-mt, the memory usage in bytes is this value * 64 (2^20 => 64MB) // at this time, by default, 2^19 but should be changed to something much lower unsigned int reuse:1,ready:1; }; #define SERVER_CONTEXT_INITIALISER {NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, 1, 1, 65536, 0, 0} #ifndef SERVER_CONTEXT_C extern server_context_s g_server_context; #endif typedef struct server_vtbl_s server_vtbl_s; /** \brief Initialize sockets and copy the config parameters into server_context_t * * @param[in] config * @param[out] server_context * * @retval OK * @return otherwise log_quit will stop the program */ int server_context_create(); bool server_context_matches_config(); /** * Appends the name of the socket s to the buffer. * The buffer has to be big enough, no size test is performed. * * @param buffer * @param s * * @return the length of the name */ u32 server_context_append_socket_name(char *buffer, u16 s); /** \brief Closes all sockets and remove pid file * * @param[in] config * @param[in] server_context * * @retval OK * @return otherwise log_quit will stop the program */ void server_context_stop(); #ifdef __cplusplus } #endif yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server_error.h0000644000000000000000000000013114505005533021562 xustar000000000000000030 mtime=1695812443.543997957 30 atime=1695812445.785030053 29 ctime=1695812495.55574287 yadifa-2.6.5-11201/sbin/yadifad/server_error.h0000664000374500037450000001426214505005533021532 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server Server * @ingroup yadifad * @brief * * @{ */ #ifndef _SERVER_ERROR_H #define _SERVER_ERROR_H #include #include #ifdef __cplusplus extern "C" { #endif /* ------------------------------------------------------------ * * VALUES */ #define YDF_ERROR_BASE 0x80080000 #define YDF_ERROR_CODE(code_) ((s32)(YDF_ERROR_BASE+(code_))) #define YDF_ERROR YDF_ERROR_CODE(0) #define YDF_ALREADY_RUNNING YDF_ERROR_CODE(1) #define YDF_PID_PATH_IS_WRONG YDF_ERROR_CODE(2) /* Main errorcodes */ #define ZONE_LOAD_ERROR_BASE (YDF_ERROR_BASE + 0x10) #define ZONE_LOAD_ERROR_CODE(code_) ((s32)(ZONE_LOAD_ERROR_BASE+(code_))) #define ZONE_LOAD_MASTER_TYPE_EXPECTED ZONE_LOAD_ERROR_CODE(0) #define ZONE_LOAD_MASTER_ZONE_FILE_UNDEFINED ZONE_LOAD_ERROR_CODE(1) #define ZONE_LOAD_SLAVE_TYPE_EXPECTED ZONE_LOAD_ERROR_CODE(2) #define ZONE_NOT_DEFINED ZONE_LOAD_ERROR_CODE(3) #define ZRE_NO_VALID_FILE_FOUND ZONE_LOAD_ERROR_CODE(4) #define ANSWER_ERROR_BASE (ZONE_LOAD_ERROR_BASE + 0x10) #define ANSWER_ERROR_CODE(code_) ((s32)(ANSWER_ERROR_BASE+(code_))) #define ANSWER_NOT_ACCEPTABLE ANSWER_ERROR_CODE(0) #define ANSWER_UNEXPECTED_EOF ANSWER_ERROR_CODE(1) #define NOTIFY_ERROR_BASE (ANSWER_ERROR_BASE + 0x10) #define NOTIFY_ERROR_CODE(code_) ((s32)(NOTIFY_ERROR_BASE+(code_))) #define NOTIFY_QUERY_TO_MASTER NOTIFY_ERROR_CODE(0) #define NOTIFY_QUERY_TO_UNKNOWN NOTIFY_ERROR_CODE(1) #define NOTIFY_QUERY_FROM_UNKNOWN NOTIFY_ERROR_CODE(2) #define POLICY_ERROR_BASE (NOTIFY_ERROR_BASE + 0x10) #define POLICY_ERROR_CODE(code_) ((s32)(POLICY_ERROR_BASE+(code_))) #define POLICY_ILLEGAL_DATE POLICY_ERROR_CODE(0) #define POLICY_ILLEGAL_DATE_TYPE POLICY_ERROR_CODE(1) #define POLICY_ILLEGAL_DATE_PARAMETERS POLICY_ERROR_CODE(2) #define POLICY_ILLEGAL_DATE_COMPARE POLICY_ERROR_CODE(3) #define POLICY_UNDEFINED POLICY_ERROR_CODE(4) #define POLICY_KEY_SUITE_UNDEFINED POLICY_ERROR_CODE(5) #define POLICY_NULL_REQUESTED POLICY_ERROR_CODE(6) #define POLICY_ZONE_NOT_READY POLICY_ERROR_CODE(7) // executable return codes #define EXIT_CONFIG_ERROR 10 #define EXIT_CODE_DATABASE_LOAD_ERROR 11 #define EXIT_CODE_SYSCLEANUP_ERROR 12 #ifndef MODULE_MSG_HANDLE extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #endif static inline void ttylog_err(const char *format, ...) { va_list args; if(logger_is_running()) { va_start(args, format); logger_handle_vmsg(MODULE_MSG_HANDLE, MSG_ERR, format, args); va_end(args); logger_flush(); } // else { flushout(); osprint(termerr, "error: "); va_start(args, format); vosformat(termerr, format, args); va_end(args); osprintln(termerr, ""); flusherr(); } } static inline void ttylog_warn(const char *format, ...) { va_list args; if(logger_is_running()) { va_start(args, format); logger_handle_vmsg(MODULE_MSG_HANDLE, MSG_WARNING, format, args); va_end(args); logger_flush(); } // else { flushout(); osprint(termerr, "warning: "); va_start(args, format); vosformat(termerr, format, args); va_end(args); osprintln(termerr, ""); flusherr(); } } static inline void ttylog_notice(const char *format, ...) { va_list args; if(logger_is_running()) { va_start(args, format); logger_handle_vmsg(MODULE_MSG_HANDLE, MSG_NOTICE, format, args); va_end(args); logger_flush(); } // else { flushout(); osprint(termerr, "notice: "); va_start(args, format); vosformat(termerr, format, args); va_end(args); osprintln(termerr, ""); flusherr(); } } #ifdef __cplusplus } #endif #endif /* _SERVER_ERROR_H */ /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/signals.h0000644000000000000000000000013214505005533020504 xustar000000000000000030 mtime=1695812443.524997685 30 atime=1695812445.784030039 30 ctime=1695812495.557742898 yadifa-2.6.5-11201/sbin/yadifad/signals.h0000664000374500037450000000465714505005533020462 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include #include #include "confs.h" /* ------------------------------------------------------------ * * VALUES */ #define SA_SHUTDOWN 0 #define SA_CONT 1 /* ------------------------------------------------------------ * * PROTOTYPES */ void signal_setup(); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/zone.h0000644000000000000000000000013214505005533020017 xustar000000000000000030 mtime=1695812443.507997441 30 atime=1695812445.783030024 30 ctime=1695812495.559742927 yadifa-2.6.5-11201/sbin/yadifad/zone.h0000664000374500037450000002655614505005533017777 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #pragma once /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include #include #include #define MAINTAIN_ONLY_AT_DIFF_AND_REPLAY 0 typedef struct zone_data_set zone_data_set; struct zone_data_set { ptr_set set; group_mutex_t lock; u32 set_count; }; #if DNSCORE_HAS_CTRL #include "ctrl.h" #endif #include "zone_desc.h" /* ------------------------------------------------------------ * * VALUES */ #define BRACKET_CLOSED 0x00U #define BRACKET_OPEN 0x01U /** flag settings for printing the zone file * \param 0 means not printing of the resource records * \param 1 means printing of the resource records */ #define WITHOUT_RR 0 #define WITH_RR 1 #define ZONE_NAME 0x01U #define ZONE_TYPE 0x02U #define ZONE_ACL 0x04U #define ZONE_GLOBAL_RR 0x08U #define ZONE_RR 0x10U #define ZONE_ALL (ZONE_NAME | ZONE_TYPE | ZONE_ACL | ZONE_GLOBAL_RR | ZONE_RR) #define ZONECMD_TAG 0x444d43454e4f5a #if 0 /* fix */ #else struct zone_command_s { union { u8 *origin; zdb_zone *zone; void *ptr; } parm; u32 id; }; typedef struct zone_command_s zone_command_s; #endif typedef bool zone_data_matching_callback(zone_desc_s*); bool zone_data_is_clone(zone_desc_s *desc); s32 zone_desc_match(const zone_desc_s *a, const zone_desc_s *b); void zone_init(zone_data_set *set); /** @brief Initializing zone_data variable * * Allocates and clears a new zone data (fully empty) * * @retval clean new zone_data */ zone_desc_s *zone_alloc(); zone_desc_s *zone_clone(zone_desc_s *zone_setup); /** \brief * Frees a zone data * * @param[in] src is a * to the zone data */ void zone_acquire(zone_desc_s *zone_desc); void zone_release(zone_desc_s *zone_desc); #define zone_free(zd__) zone_release(zd__) void zone_dump_allocated(); /** * */ void zone_remove_all_matching(zone_data_set *dset, zone_data_matching_callback *matchcallback); #if 1 // NOT USED /** \brief Frees all elements of the collection * * @param[in] src the collection * * @return NONE */ void zone_free_all(zone_data_set *set); #endif ya_result zone_complete_settings(zone_desc_s *zone_desc); /** * * Adds the zone in the collection (if it's not there already) * * @param set * @param zone * @return */ ya_result zone_register(zone_data_set *set, zone_desc_s *zone); /** * Removes the zone with the given origin from the collection. * Returns a pointer to the zone. (The caller may destroy it if * he wants) */ zone_desc_s *zone_unregister(zone_data_set *set, const u8 *origin); /** * returns the zone_data from the zone config that's just after the name * in lexicographic order * * @param name * @return */ zone_desc_s *zone_getafterdnsname(const u8 *name); /** * returns the zone_data from the zone config for the name * * @param name * @return */ zone_desc_s *zone_acquirebydnsname(const u8 *name); /* * functions used for removing a zone_desc */ void zone_setloading(zone_desc_s *zone_desc, bool v); void zone_setmustsavefile(zone_desc_s *zone_desc, bool v); void zone_setmustsaveaxfr(zone_desc_s *zone_desc, bool v); void zone_setsavingfile(zone_desc_s *zone_desc, bool v); void zone_setsavingaxfr(zone_desc_s *zone_desc, bool v); void zone_setstartingup(zone_desc_s *zone_desc, bool v); void zone_setdynamicupdating(zone_desc_s *zone_desc, bool v); bool zone_isidle(zone_desc_s *zone_desc); bool zone_isfrozen(zone_desc_s *zone_desc); bool zone_isloading(zone_desc_s *zone_desc); bool zone_mustsavefile(zone_desc_s *zone_desc); bool zone_mustsaveaxfr(zone_desc_s *zone_desc); bool zone_issavingfile(zone_desc_s *zone_desc); bool zone_issavingaxfr(zone_desc_s *zone_desc); bool zone_isdynamicupdating(zone_desc_s *zone_desc); bool zone_canbeedited(zone_desc_s *zone_desc); bool zone_ismaster(zone_desc_s *zone_desc); zdb_zone *zone_get_loaded_zone(zone_desc_s *zone_desc); zdb_zone *zone_set_loaded_zone(zone_desc_s *zone_desc, zdb_zone *zone); bool zone_has_loaded_zone(zone_desc_s *zone_desc); /* * This will mark a zone as being obsolete. * It means that we are about to delete it. * It also means that nobody can lock it anymore, but the destoyer) (lock will return an error for anybody else) */ ya_result zone_wait_unlocked(zone_desc_s *zone_desc); void zone_set_lock(zone_data_set *dset); void zone_set_unlock(zone_data_set *dset); bool zone_islocked(zone_desc_s *zone_desc); /* * returns true if a zone is obsolete */ bool zone_is_obsolete(zone_desc_s *zone_desc); /* * returns true if the zone hasn't even tried to load its zone */ bool zone_isstartingup(zone_desc_s *zone_desc); /* * returns the owner, or error if the zone_desc is obsolete */ ya_result zone_try_lock(zone_desc_s *zone_desc, u8 owner_mark); /* * wait for lock (and return the owner) or return an error if the zone_desc becomes obsolete */ ya_result zone_lock(zone_desc_s *zone_desc, u8 owner_mark); /* * wait a while for lock (and return the owner) or return an error if the zone_desc becomes obsolete */ ya_result zone_try_lock_wait(zone_desc_s *zone_desc, u64 usec, u8 owner_id); /* * unlocks if locked by the owner, else return an error */ void zone_unlock(zone_desc_s *zone_desc, u8 owner_mark); const char *zone_type_to_name(zone_type t); const char* zone_dnssec_to_name(u32 dnssec_flags); void zone_setdefaults(zone_desc_s *zone_desc); // 0 : no merge, 1 : merge, < 0 : error ya_result zone_setwithzone(zone_desc_s *zone_desc, zone_desc_s *src); /** * Returns TRUE iff the zone has DNSSEC maintenance on. * * @return TRUE iff zone has ZONE_FLAG_MAINTAIN_DNSSEC. */ #if ZDB_HAS_MASTER_SUPPORT static inline bool zone_maintains_dnssec(zone_desc_s *zone_desc) { return (zone_desc->flags & ZONE_FLAG_MAINTAIN_DNSSEC) != 0; } #endif #if ZDB_HAS_MASTER_SUPPORT static inline void zone_maintains_dnssec_set(zone_desc_s *zone_desc, bool enable) { if(enable) { zone_desc->flags |= ZONE_FLAG_MAINTAIN_DNSSEC; } else { zone_desc->flags &= ~ZONE_FLAG_MAINTAIN_DNSSEC; } } #endif static inline bool zone_is_auto_notify(zone_desc_s *zone_desc) { return (zone_desc->flags & ZONE_FLAG_NOTIFY_AUTO) != 0; } static inline void zone_auto_notify_set(zone_desc_s *zone_desc, bool enable) { if(enable) { zone_desc->flags |= ZONE_FLAG_NOTIFY_AUTO; } else { zone_desc->flags &= ~ZONE_FLAG_NOTIFY_AUTO; } } static inline bool zone_is_drop_before_load(zone_desc_s *zone_desc) { return (zone_desc->flags & ZONE_FLAG_DROP_BEFORE_LOAD) != 0; } #if ZDB_HAS_MASTER_SUPPORT static inline bool zone_rrsig_nsupdate_allowed(zone_desc_s *zone_desc) { return (zone_desc->flags & ZONE_FLAG_RRSIG_NSUPDATE_ALLOWED) != 0; } #endif void zone_enqueue_command(zone_desc_s *zone_desc, u32 id, void* parm, bool has_priority); zone_command_s* zone_dequeue_command(zone_desc_s *zone_desc); void zone_command_free(zone_command_s *cmd); /** * * Functions to log a zone desc * * @param zone_desc * @param text */ void zone_desc_log(logger_handle* handle, u32 level, const zone_desc_s *zone_desc, const char *text); void zone_desc_log_all(logger_handle* handle, u32 level, zone_data_set *dset, const char *text); /** * Callback for zone_desc_for_all */ typedef ya_result zone_desc_for_all_callback(zone_desc_s *zone_desc, void *args); /** * * Calls the callback for all zone_desc. * If the callback returns an error, the process stops. * * @param cb * @param args * @return SUCCESS or the error code returned by the callback */ ya_result zone_desc_for_all(zone_desc_for_all_callback *cb, void *args); /** */ void zone_desc_status_flags_long_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters); static inline bool zone_is_multimaster(const zone_desc_s *zone_desc) { return (zone_desc->masters != NULL) && (zone_desc->masters->next != NULL); } static inline bool zone_is_true_multimaster(const zone_desc_s *zone_desc) { return zone_is_multimaster(zone_desc) && ((zone_desc->flags & ZONE_FLAG_TRUE_MULTIMASTER) != 0); } void zone_set_status(zone_desc_s *zone_desc, u32 flags); u32 zone_get_set_status(zone_desc_s *zone_desc, u32 flags); void zone_clear_status(zone_desc_s *zone_desc, u32 flags); u32 zone_get_status(const zone_desc_s *zone_desc); host_address* zone_transfer_source_copy(const u8 *domain); ya_result zone_transfer_source_tcp_connect(const host_address *server, host_address **current_transfer_sourcep, input_stream *is, output_stream *os, int to_sec); void zone_dnssec_status_update(zdb_zone *zone); u8 zone_policy_guess_dnssec_type(zdb_zone *zone); u32 zone_policy_get_earliest_queued_key_generation(zone_desc_s *zone_desc); u32 zone_policy_set_earliest_queued_key_generation(zone_desc_s *zone_desc, u32 epoch); u32 zone_policy_clear_earliest_queued_key_generation(zone_desc_s *zone_desc, u32 epoch); struct dnssec_policy_key_suite; bool zone_policy_key_suite_is_marked_processed(zone_desc_s *zone_desc, const struct dnssec_policy_key_suite *kr); bool zone_policy_key_suite_mark_processed(zone_desc_s *zone_desc, const struct dnssec_policy_key_suite *kr); void zone_policy_key_suite_unmark_processed(zone_desc_s *zone_desc, const struct dnssec_policy_key_suite *kr); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/zone_desc.h0000644000000000000000000000013214505005533021015 xustar000000000000000030 mtime=1695812443.536997857 30 atime=1695812445.784030039 30 ctime=1695812495.561742956 yadifa-2.6.5-11201/sbin/yadifad/zone_desc.h0000664000374500037450000004401314505005533020761 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef ZONE_DESC_H #define ZONE_DESC_H #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define ZONE_LOCK_HAS_OWNER_ID 0 // debug #if ZONE_LOCK_HAS_OWNER_ID #pragma message("***********************************************************") #pragma message("***********************************************************") #pragma message("ZONE_LOCK_HAS_OWNER_ID 1") #pragma message("***********************************************************") #pragma message("***********************************************************") #endif #define ZT_HINT 0 /**< zone file: hint */ #define ZT_MASTER 1 /**< zone file: master */ #define ZT_SLAVE 2 /**< zone file: slave */ #define ZT_STUB 3 /**< zone file: stub */ #define ZT_UNKNOWN 4 /**< zone file: unknown */ #define ZT_STRING_HINT "hint" #define ZT_STRING_MASTER "master" #define ZT_STRING_SLAVE "slave" #define ZT_STRING_PRIMARY "primary" #define ZT_STRING_SECONDARY "secondary" #define ZT_STRING_STUB "stub" #define ZT_STRING_UNKNOWN "unknown" #define ZONE_DNSSEC_FL_NOSEC 0 #define ZONE_DNSSEC_FL_NSEC 1 #define ZONE_DNSSEC_FL_NSEC3 2 #define ZONE_DNSSEC_FL_NSEC3_OPTOUT 3 #define ZONE_DNSSEC_FL_MASK 7 #define ZONE_CTRL_FLAG_CLONE 1 /* has a parent in the config */ #define ZONE_CTRL_FLAG_EDITED 2 /* has been edited dynamically (it's a dynamic provisioning zone) */ #define ZONE_CTRL_FLAG_READ_FROM_CONF 4 /* has been read from the configuration file */ #define ZONE_CTRL_FLAG_READ_FROM_DIFF 8 /* has been read from the configuration updates file */ #define ZONE_CTRL_FLAG_SAVED_TO_DIFF 16 /* has been saved to the configuration updates file */ #define ZONE_CTRL_FLAG_DYNAMIC 32 // #define ZONE_CTRL_FLAG_GENERATE_ZONE 128 // behavioural flags #define ZONE_FLAG_NOTIFY_AUTO 1 #define ZONE_FLAG_DROP_BEFORE_LOAD 2 // drops the old instance of a zone before loading it again (spare memory) #define ZONE_FLAG_NO_MASTER_UPDATES 4 /* so a slave will not ask for updates * edf: I added this so I would not hammer * the root servers when doing tests */ #if ZDB_HAS_MASTER_SUPPORT #define ZONE_FLAG_MAINTAIN_DNSSEC 8 #endif #define ZONE_FLAG_TRUE_MULTIMASTER 16 // drops a zone whenever changing the master #define ZONE_FLAG_DROP_CURRENT_ZONE_ON_LOAD 32 // only triggered while changing the true master: the current zone will be dropped #if ZDB_HAS_MASTER_SUPPORT #define ZONE_FLAG_RRSIG_NSUPDATE_ALLOWED 64 // allows to push a signature with an update //#define ZONE_FLAG_MAINTAIN_ZONE_BEFORE_MOUNT 128 // must finishing applying policies and signature before mounting the zone #endif #define ZONE_FLAG_PRIORITISE_LOCAL_SOURCE 256 // If a zone exists locally : do not probe the master, just load it. Probe later. // status flags // iIclLMUdDzZaAsSeERxX#---T---ur/! //#define ZONE_STATUS_IDLE 0x00000000 /* i nothing happening at ALL */ #define ZONE_STATUS_STARTING_UP 0x00000001 /* I before we even tried to load it */ #define ZONE_STATUS_LOAD 0x00000004 /* l loading of the zone queried */ #define ZONE_STATUS_LOADING 0x00000008 /* L in the process of loading the zone */ #define ZONE_STATUS_MOUNTING 0x00000010 /* M loading of the zone queried */ #define ZONE_STATUS_UNMOUNTING 0x00000020 /* U in the process of loading the zone */ #define ZONE_STATUS_DROP 0x00000040 /* d unloading of the zone queried */ #define ZONE_STATUS_DROPPING 0x00000080 /* D in the process of unloading the zone */ #define ZONE_STATUS_SAVETO_ZONE_FILE 0x00000100 /* z dumping to ... queried */ #define ZONE_STATUS_SAVING_ZONE_FILE 0x00000200 /* Z dumping to ... at this moment */ #define ZONE_STATUS_SAVETO_AXFR_FILE 0x00000400 /* a dumping to ... queried */ #define ZONE_STATUS_SAVING_AXFR_FILE 0x00000800 /* A dumping to ... at this moment */ #define ZONE_STATUS_SIGNATURES_UPDATE 0x00001000 /* s needs to update the signatures (?) */ #define ZONE_STATUS_SIGNATURES_UPDATING 0x00002000 /* S updating signatures */ #define ZONE_STATUS_DYNAMIC_UPDATE 0x00004000 /* e needs to update the database (?) */ #define ZONE_STATUS_DYNAMIC_UPDATING 0x00008000 /* E updating the database */ #define ZONE_STATUS_READONLY_______NOT_USED 0x00010000 /* R database updates not allowed */ #define ZONE_STATUS_DOWNLOAD_XFR_FILE 0x00020000 /* x */ #define ZONE_STATUS_DOWNLOADING_XFR_FILE 0x00040000 /* X */ #define ZONE_STATUS_DROP_AFTER_RELOAD 0x00080000 /* # when a config reload occurrs, this flag is set to all zones * when the zone has its config reloaded, it is cleared * all zones with this bit set after the reload are dropped */ #define ZONE_STATUS_FROZEN 0x00100000 /* f zone is read only <-> READONLY ? */ #define ZONE_STATUS_TEMPLATE_SOURCE_FILE 0x00200000 #define ZONE_STATUS_MUST_CLEAR_JOURNAL 0x00400000 #define ZONE_STATUS_NOTIFIED 0x00800000 #define ZONE_STATUS_DOWNLOADED 0x01000000 /* T the file is on disk, soon to be loaded */ #define ZONE_STATUS_UPDATE_FROM_MASTER 0x02000000 #define ZONE_STATUS_LOAD_AFTER_DROP 0x04000000 #define ZONE_STATUS_RESERVED1 0x08000000 #define ZONE_STATUS_UNREGISTERING 0x10000000 /* u */ #define ZONE_STATUS_REGISTERED 0x20000000 /* r this instance of the zone is registered */ #define ZONE_STATUS_MARKED_FOR_DESTRUCTION 0x40000000 /* / a "destroy" command has been put in the queue */ #define ZONE_STATUS_PROCESSING 0x80000000 /* ! */ #define ZONE_STATUS_BUSY (\ ZONE_STATUS_LOAD|ZONE_STATUS_LOADING |\ ZONE_STATUS_MOUNTING|ZONE_STATUS_UNMOUNTING |\ ZONE_STATUS_DROP|ZONE_STATUS_DROPPING |\ ZONE_STATUS_SAVETO_ZONE_FILE|ZONE_STATUS_SAVING_ZONE_FILE |\ ZONE_STATUS_SAVETO_AXFR_FILE|ZONE_STATUS_SAVING_AXFR_FILE |\ ZONE_STATUS_SIGNATURES_UPDATE|ZONE_STATUS_SIGNATURES_UPDATING |\ ZONE_STATUS_DYNAMIC_UPDATE|ZONE_STATUS_DYNAMIC_UPDATING |\ ZONE_STATUS_DOWNLOAD_XFR_FILE|ZONE_STATUS_DOWNLOADING_XFR_FILE |\ ZONE_STATUS_PROCESSING |\ 0) // locks owners #define ZONE_LOCK_NOBODY 0x00 #define ZONE_LOCK_READONLY 0x01 #define ZONE_LOCK_LOAD 0x82 #define ZONE_LOCK_UNLOAD 0x83 #define ZONE_LOCK_LOAD_DESC 0x84 #define ZONE_LOCK_DESC_UNLOAD 0x85 #define ZONE_LOCK_REPLACE_DESC 0x86 #define ZONE_LOCK_DOWNLOAD_DESC 0x87 #define ZONE_LOCK_MOUNT 0x88 #define ZONE_LOCK_UNMOUNT 0x89 #define ZONE_LOCK_SERVICE 0x8a #define ZONE_LOCK_SIGNATURE 0x8b #define ZONE_LOCK_FREEZE 0x8c #define ZONE_LOCK_UNFREEZE 0x8d #define ZONE_LOCK_SAVE 0x8e #define ZONE_LOCK_DYNUPDATE 0x8f enum zone_type { UNKNOWN = ZT_UNKNOWN, HINT = ZT_HINT, MASTER = ZT_MASTER, SLAVE = ZT_SLAVE, STUB = ZT_STUB, INVALID = MAX_S32 /* ensures the enum is 32 bits (at least) */ }; typedef enum zone_type zone_type; /** * * About slave refresh: * * 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. */ typedef struct zone_refresh_s zone_refresh_s; struct zone_refresh_s { // last successful refresh time u32 refreshed_time; // last time we retried u32 retried_time; // for the sole use of retry.c (updated and used by it) u32 zone_update_next_time; /* // last advertised serial (notification) u32 advertised_serial; // queued to handle notification bool notification_handling; */ }; typedef struct zone_notify_s zone_notify_s; struct zone_notify_s { /* retry count */ u32 retry_count; /* period in minutes */ u32 retry_period; /* increase of the period (in minutes) after each retry */ u32 retry_period_increase; }; #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_DNSSEC_SUPPORT #define ZONE_SIGNATURE_INVALID_FIRST_ASSUME_BROKEN 0 typedef struct zone_signature_s zone_signature_s; struct zone_signature_s { // The newly generated signatures will be valid for that amount of days u32 sig_validity_interval; // The amount of time before expiration to update a signature u32 sig_validity_regeneration; // The validity of newly generated signature will be off by at most this u32 sig_validity_jitter; // The earliest epoch at which a signature in the zone is expired. u32 sig_invalid_first; // The first epoch when a signature will be updated u32 scheduled_sig_invalid_first; }; #endif /// @note HAS_DYNAMIC_PROVISIONING typedef struct dynamic_provisioning_s dynamic_provisioning_s; struct dynamic_provisioning_s { u8 version; u8 padding; u16 flags; u32 timestamp; u32 refresh; u32 retry; u32 expire; u32 timestamp_lo; /* 0 for now */ u32 checksum; /* MUST BE LAST FIELD */ }; /// #define ZONE_DESC_MATCH_ORIGIN 0x00000001 #define ZONE_DESC_MATCH_DOMAIN 0x00000002 #define ZONE_DESC_MATCH_FILE_NAME 0x00000004 #define ZONE_DESC_MATCH_MASTERS 0x00000008 #define ZONE_DESC_MATCH_NOTIFIES 0x00000010 #define ZONE_DESC_MATCH_TRANSFERSOURCE 0x00000020 #if HAS_DYNAMIC_PROVISIONING #define ZONE_DESC_MATCH_DYNAMIC 0x00000040 #endif #define ZONE_DESC_MATCH_SLAVES 0x00000080 #define ZONE_DESC_MATCH_REFRESH 0x00000100 #define ZONE_DESC_MATCH_NOTIFY 0x00000200 #define ZONE_DESC_MATCH_DNSSEC_MODE 0x00000400 #define ZONE_DESC_MATCH_TYPE 0x00000800 #define ZONE_DESC_MATCH_ACL 0x00001000 #define ZONE_DESC_MATCH_DNSSEC_POLICIES 0x00002000 struct dnssec_policy; typedef struct zone_desc_s zone_desc_s; struct zone_desc_s { // fqdn u8 *_origin; // cannot change // ascii domain name char *domain; // cannot change // name of the file on disk char *file_name; // may change // path where to find the keys char *keys_path; // can be NULL // The list of the masters (for a slave) host_address *masters; // may change // If master which are the servers to notify for updates IXFR or AXFR host_address *notifies; // may change #if ZDB_HAS_ACL_SUPPORT // Restrited list of ip address allowed to query */ access_control ac; // may change (content is made of pointers) #endif // zone notify settings zone_notify_s notify; // may change (3 * 32 bits) #if DNSCORE_HAS_DNSSEC_SUPPORT #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT #if ZDB_HAS_MASTER_SUPPORT struct dnssec_policy *dnssec_policy; ptr_set dnssec_policy_processed_key_suites; #endif // zone signature settings zone_signature_s signature; // may change (5 * 32 bits) #endif u32 dnssec_mode; // needs to be u32 (config descriptor requirement) #endif // zone refresh status zone_refresh_s refresh; // internal (3 * 32 bits) volatile u32 _status_flags; // internal volatile u32 last_processor; // internal, diagnostic u32 flags; // may change ? (notify auto, drop before load, ...) u32 journal_size_kb; // may change, expressed in kb, 0 "choose", 2^32-1 " u32 stored_serial; // serial of the last stored full zone image /* Type of zone file (master, slave, stub, unknown) */ u32 download_failure_count; // axfr or ixfr downloads that failed since the last one that succeeded zone_type type; u16 qclass; // cannot change, most likely CLASS_IN u8 multimaster_retries; // config : how many failures before changing master u8 multimaster_failures; // the number of error on the current primary master (reset on success) // instead of having a priority queue with two levels, two queues will do // the job bpqueue_s commands; // queue of commands #if HAS_DYNAMIC_PROVISIONING /// @note HAS_DYNAMIC_PROVISIONING dynamic_provisioning_s dynamic_provisioning; // proprietary #endif host_address *slaves; // proprietary host_address *transfer_source; zdb_zone *loaded_zone; // internal, keeps an RC, has to be increased by users grabbing it (mutex required) /// /* marks */ mutex_t lock; cond_t lock_cond; u32 commands_bits; volatile s32 rc; volatile s32 lock_wait_count; volatile s32 lock_owner_count; volatile u8 lock_owner; #if ZONE_LOCK_HAS_OWNER_ID volatile thread_t lock_last_owner_tid; #endif #if DEBUG u64 instance_time_us; u64 instance_id; #endif }; static inline const u8* zone_origin(const zone_desc_s *zone_desc) { return zone_desc->_origin; } static inline const char* zone_domain(const zone_desc_s *zone_desc) { return zone_desc->domain; } #ifdef __cplusplus } #endif #endif /* ZONE_DESC_H */ /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/zone-source.h0000644000000000000000000000013214505005533021315 xustar000000000000000030 mtime=1695812443.535997842 30 atime=1695812445.784030039 30 ctime=1695812495.563742984 yadifa-2.6.5-11201/sbin/yadifad/zone-source.h0000664000374500037450000001263514505005533021266 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #define ZONE_SOURCE_MISSING 0 #define ZONE_SOURCE_EXISTS 1 #define ZONE_SOURCE_OBSOLETE 2 #define ZONE_SOURCE_RELEVANT 4 #define ZONE_SOURCE_TEMPLATE 8 #define ZONE_SOURCE_LOCALE 16 // on disk #define ZONE_SOURCE_REMOTE 32 // on master #define ZONE_SOURCE_LOADED 64 // in DB struct zone_source { u32 serial; u32 base_serial; u32 flags; const char *type_name; u16 rdata_size; u8 rdata[MAX_SOA_RDATA_LENGTH]; }; typedef struct zone_source zone_source; #define ZONE_SOURCE_EMPTY {0, 0, 0, "UNDEFINED"} #define ZONE_SOURCE_INIT(__type_name) {0, 0, 0, (__type_name), 0, {0}} static inline void zone_source_init(zone_source *zs, const char *type_name) { zs->serial = 0; zs->flags = 0; zs->type_name = type_name; } static inline void zone_source_set(zone_source *zs, u32 flags) { zs->flags |= flags; } static inline void zone_source_unset(zone_source *zs, u32 flags) { zs->flags &= ~flags; } static inline bool zone_source_has_flags(zone_source *zs, u32 flags) { return (zs->flags & flags) == flags; } static inline bool zone_source_exists(zone_source *zs) { yassert(zs != NULL); bool ret = zone_source_has_flags(zs, ZONE_SOURCE_EXISTS); return ret; } static inline bool zone_source_is_relevant(zone_source *zs) { yassert(zs != NULL); bool ret = zone_source_has_flags(zs, ZONE_SOURCE_RELEVANT|ZONE_SOURCE_EXISTS); return ret; } static inline void zone_source_disable(zone_source *zs) { yassert(zs != NULL); zs->flags |= ZONE_SOURCE_OBSOLETE; zs->flags &= ~ZONE_SOURCE_RELEVANT; } static inline void zone_source_set_serial(zone_source *zs, u32 serial) { yassert(zs != NULL); zs->serial = serial; zs->base_serial = serial; } static inline ya_result zone_source_update_serial_from_soa(zone_source *zs) { ya_result ret; u32 serial; if(ISOK(ret = rr_soa_get_serial(zs->rdata, zs->rdata_size, &serial))) { zone_source_set_serial(zs, serial); } return ret; } static inline void zone_source_set_journal_serial(zone_source *zs, u32 serial) { yassert(zs != NULL); zs->serial = serial; } static inline int zone_source_compare(zone_source *zsa, zone_source *zsb) { yassert(zsa != NULL); yassert(zsb != NULL); if(zone_source_exists(zsa)) { if(zone_source_exists(zsb)) { if(zsa->serial != zsb->serial) { return serial_gt(zsa->serial, zsb->serial)?1:-1; // B or A } else { return 0; // equal } } else { return -1; // A } } else { if(zone_source_exists(zsb)) { return 1; // B } else { return 0; // equaly lame } } } static inline zone_source* zone_source_get_best(zone_source *zsa, zone_source *zsb) { yassert(zsa != NULL); yassert(zsb != NULL); if(zone_source_exists(zsa)) { if(zone_source_exists(zsb)) { if(zsa->serial != zsb->serial) { return serial_gt(zsa->serial, zsb->serial)?zsa:zsb; // B or A } else { return zsa; // equal } } else { return zsa; // A } } else { if(zone_source_exists(zsb)) { return zsb; // B } else { return zsa; // equaly lame } } } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server-rw.h0000644000000000000000000000013114505005533020777 xustar000000000000000030 mtime=1695812443.476996997 29 atime=1695812445.78203001 30 ctime=1695812495.565743013 yadifa-2.6.5-11201/sbin/yadifad/server-rw.h0000664000374500037450000000421414505005533020743 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup server Server * @ingroup yadifad * @brief Buffered input UDP server * * @{ */ #pragma once #include #define SERVER_NETWORK_MODEL_RW 1 ya_result server_rw_context_init(int workers_per_interface); ya_result server_rw_query_loop(struct service_worker_s *worker); /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server-mm.h0000644000000000000000000000013214505005533020761 xustar000000000000000030 mtime=1695812443.492997227 30 atime=1695812445.783030024 30 ctime=1695812495.567743042 yadifa-2.6.5-11201/sbin/yadifad/server-mm.h0000664000374500037450000000421414505005533020724 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup server Server * @ingroup yadifad * @brief Buffered input UDP server * * @{ */ #pragma once #include #define SERVER_NETWORK_MODEL_MM 2 ya_result server_mm_context_init(int workers_per_interface); ya_result server_mm_query_loop(struct service_worker_s *worker); /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/dynamic-module-handler.h0000644000000000000000000000013014505005533023364 xustar000000000000000029 mtime=1695812443.49599727 30 atime=1695812445.783030024 29 ctime=1695812495.56974307 yadifa-2.6.5-11201/sbin/yadifad/dynamic-module-handler.h0000664000374500037450000001064114505005533023332 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include struct dynamic_module_interface_chain; struct dynamic_module_dnskey_interface_chain; struct dynamic_module_statistics_interface_chain; struct server_statistics_t; #if !DYNAMIC_MODULE_HANDLER_C extern struct dynamic_module_interface_chain *g_dynamic_module_interface_chain; extern struct dynamic_module_dnskey_interface_chain *g_dynamic_module_dnskey_interface_chain; extern struct dynamic_module_statistics_interface_chain *g_dynamic_module_statistics_interface_chain; #endif /** * Trivial. */ ya_result dynamic_module_handler_init(); /** * Trivial. */ ya_result dynamic_module_handler_finalize(); /** * Loads a module given its full path name (with luck relative may work too ... so yes: full path) * Don't forget to take into account the choot. * * Modules should only be loaded AFTER the last fork. */ ya_result dynamic_module_handler_load(int argc, const char **argv); ya_result dynamic_module_handler_load_from_command(const char *command); static inline bool dynamic_module_interface_chain_available() { return g_dynamic_module_interface_chain != NULL; } static inline bool dynamic_module_dnskey_interface_chain_available() { return g_dynamic_module_dnskey_interface_chain != NULL; } static inline bool dynamic_module_statistics_interface_chain_available() { return g_dynamic_module_statistics_interface_chain != NULL; } // interface void dynamic_module_startup(); void dynamic_module_settings(); void dynamic_module_shutdown(); // dnskey_interface void dynamic_module_on_dnskey_created(const dnssec_key *key); void dynamic_module_on_dnskey_publish(const dnssec_key *key); void dynamic_module_on_dnskey_activate(const dnssec_key *key); void dynamic_module_on_dnskey_revoke(const dnssec_key *key); void dynamic_module_on_dnskey_inactive(const dnssec_key *key); void dynamic_module_on_dnskey_delete(const dnssec_key *key); #define DYNAMIC_MODULE_STATISTICS_RCODE_COUNT 32 #define DYNAMIC_MODULE_STATISTICS_TSIG_RCODE_COUNT 4 struct dynamic_module_statistics_args_buffers { uint64_t udp_rcode_buffer[DYNAMIC_MODULE_STATISTICS_RCODE_COUNT]; uint64_t tcp_rcode_buffer[DYNAMIC_MODULE_STATISTICS_RCODE_COUNT]; uint64_t udp_tsig_rcode_buffer[DYNAMIC_MODULE_STATISTICS_TSIG_RCODE_COUNT]; uint64_t tcp_tsig_rcode_buffer[DYNAMIC_MODULE_STATISTICS_TSIG_RCODE_COUNT]; }; void dynamic_module_on_statistics_update(struct server_statistics_t *st, u64 epoch); /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl.h0000644000000000000000000000013114505005533020007 xustar000000000000000030 mtime=1695812443.488997169 29 atime=1695812445.78203001 30 ctime=1695812495.571743099 yadifa-2.6.5-11201/sbin/yadifad/ctrl.h0000664000374500037450000000553514505005533017762 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef __CTRL__H__ #define __CTRL__H__ #include #include #include #include "server-config.h" #if !HAS_CTRL #error "CTRL has not been enabled : do not include this" #endif #define CTRL_PORT_DEFAULT 1021 // highest prime under 1023 #define HAS_CTRL_DYNAMIC_PROVISIONING 0 /** * CTRL handling */ typedef struct config_control config_control; struct config_control { host_address *listen; bool enabled; }; void ctrl_set_listen(host_address *hosts); void ctrl_exclude_listen(host_address *address_list); host_address* ctrl_get_listen(); static inline bool ctrl_has_dedicated_listen() { return ctrl_get_listen() != NULL; } void ctrl_set_enabled(bool b); bool ctrl_get_enabled(); ya_result ctrl_message_process(message_data *mesg); /** @} */ #endif yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_query.h0000644000000000000000000000013114505005533021234 xustar000000000000000029 mtime=1695812443.31099462 30 atime=1695812445.781029996 30 ctime=1695812495.573743127 yadifa-2.6.5-11201/sbin/yadifad/ctrl_query.h0000664000374500037450000000465214505005533021206 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef __CTRL_QUERY__H__ #define __CTRL_QUERY__H__ #include "server-config.h" #if !HAS_CTRL #error "CTRL has not been enabled : do not include this" #endif #include #include /** * CTRL handling of the queries */ #if DNSCORE_HAS_CTRL bool ctrl_query_is_listened(int sockfd); void ctrl_query_process(message_data *mesg); #endif /** @} */ #endif yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_zone.h0000644000000000000000000000013214505005533021043 xustar000000000000000030 mtime=1695812443.519997613 30 atime=1695812445.784030039 30 ctime=1695812495.575743156 yadifa-2.6.5-11201/sbin/yadifad/ctrl_zone.h0000664000374500037450000000607014505005533021010 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef __CTRL_ZONE__H__ #define __CTRL_ZONE__H__ #include "server-config.h" #if !HAS_CTRL #error "CTRL has not been enabled : do not include this" #endif #include /** * CTRL handling */ ya_result ctrl_zone_freeze(zone_desc_s *zone_desc, bool dolock); ya_result ctrl_zone_unfreeze(zone_desc_s *zone_desc, bool dolock); ya_result ctrl_zone_sync_doclean(zone_desc_s *zone_desc, bool dolock); ya_result ctrl_zone_sync_noclean(zone_desc_s *zone_desc, bool dolock); ya_result ctrl_zone_sync(zone_desc_s *zone_desc, bool dolock, bool clear_journal); ya_result ctrl_zone_notify(zone_desc_s *zone_desc, bool dolock); ya_result ctrl_zone_reload(zone_desc_s *zone_desc, bool dolock); #if HAS_DYNAMIC_PROVISIONING ya_result ctrl_zone_generate_from_message(message_data *mesg); /* generate but let on the unactivated side */ ya_result ctrl_zone_config_merge(zone_desc_s *zone_desc, bool dolock); ya_result ctrl_zone_config_merge_all(); ya_result ctrl_zone_config_delete(zone_desc_s *zone_desc, bool dolock); #endif /** @} */ #endif yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_notify.h0000644000000000000000000000013214505005533021400 xustar000000000000000030 mtime=1695812443.314994677 30 atime=1695812445.781029996 30 ctime=1695812495.577743185 yadifa-2.6.5-11201/sbin/yadifad/ctrl_notify.h0000664000374500037450000000455714505005533021355 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef __CTRL_NOTIFY__H__ #define __CTRL_NOTIFY__H__ #include "server-config.h" #if !HAS_CTRL #error "CTRL has not been enabled : do not include this" #endif #include /** * CTRL handling of the notifies */ #if HAS_DYNAMIC_PROVISIONING ya_result ctrl_notify_process(message_data *mesg); #endif /** @} */ #endif yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_query_axfr.h0000644000000000000000000000013214505005533022255 xustar000000000000000030 mtime=1695812443.535997842 30 atime=1695812445.784030039 30 ctime=1695812495.579743214 yadifa-2.6.5-11201/sbin/yadifad/ctrl_query_axfr.h0000664000374500037450000000505714505005533022226 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef __CTRL_QUERY_AXFR__H__ #define __CTRL_QUERY_AXFR__H__ #include "server-config.h" #if !HAS_CTRL #error "CTRL has not been enabled : do not include this" #endif #include #include #if HAS_DYNAMIC_PROVISIONING void ctrl_query_axfr_make_answer(message_data *mesg); void ctrl_query_axfr_start(); void ctrl_query_axfr_enqueue(u8 *origin, host_address *master); void ctrl_query_axfr_enqueue_from_message(message_data *mesg); void ctrl_query_axfr_stop(); #endif #endif /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_query_message.h0000644000000000000000000000013214505005533022741 xustar000000000000000030 mtime=1695812443.315994691 30 atime=1695812445.781029996 30 ctime=1695812495.581743242 yadifa-2.6.5-11201/sbin/yadifad/ctrl_query_message.h0000664000374500037450000000722214505005533022706 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef __CTRL_QUERY__H__ #define __CTRL_QUERY__H__ #include "server-config.h" #if !HAS_CTRL #error "CTRL has not been enabled : do not include this" #endif #include #include #include #include #include "zone_desc.h" ya_result ctrl_query_message_add_soa(packet_writer *pw, zone_desc_s *zone_desc); /* Adds record using the TXT type */ ya_result ctrl_query_message_add_u32_txt(packet_writer *pw, const char* name, u32 value); ya_result ctrl_query_message_add_type_txt(packet_writer *pw, const char* name, u16 value); ya_result ctrl_query_message_add_class_txt(packet_writer *pw, const char* name, u16 value); ya_result ctrl_query_message_add_hosts_txt(packet_writer *pw, const char* name, host_address *hosts); ya_result ctrl_query_message_add_time_txt(packet_writer *pw, const char* name, u32 value); ya_result ctrl_query_message_add_text_txt(packet_writer *pw, const char* name, const char* value); ya_result ctrl_query_message_add_aml_txt(packet_writer *pw, const char* name, const address_match_list *aml); ya_result ctrl_query_message_add_ams_txt(packet_writer *pw, const char* name, const address_match_set *ams); ya_result ctrl_query_message_add_u8(packet_writer *pw, const u8 *origin, u16 rtype, u8 value); ya_result ctrl_query_message_add_u32(packet_writer *pw, const u8 *origin, u16 rtype, u32 value); ya_result ctrl_query_message_add_utf8(packet_writer *pw, const u8 *origin, u16 rtype, const char *value); ya_result ctrl_query_message_add_hosts(packet_writer *pw, const u8 *origin, u16 rtype, const host_address *value); /** @} */ #endif yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_update.h0000644000000000000000000000013214505005533021352 xustar000000000000000030 mtime=1695812443.326994849 30 atime=1695812445.781029996 30 ctime=1695812495.583743271 yadifa-2.6.5-11201/sbin/yadifad/ctrl_update.h0000664000374500037450000000455214505005533021322 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #ifndef __CTRL_UPDATE__H__ #define __CTRL_UPDATE__H__ #include "server-config.h" #if !HAS_CTRL #error "CTRL has not been enabled : do not include this" #endif #include /** * CTRL handling of the updates */ #if HAS_DYNAMIC_PROVISIONING void ctrl_update_process(message_data *mesg); #endif /** @} */ #endif yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/rrl.h0000644000000000000000000000013214505005533017643 xustar000000000000000030 mtime=1695812443.521997642 30 atime=1695812445.784030039 30 ctime=1695812495.585743299 yadifa-2.6.5-11201/sbin/yadifad/rrl.h0000664000374500037450000000734214505005533017613 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup yadifad * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #ifndef _RRL_H #define _RRL_H #include #include #include #ifndef RRL_PROCEED #define RRL_PROCEED 0 #define RRL_SLIP 1 #define RRL_DROP 2 #endif #define RRL_PROCEED_SLIP (RRL_SLIP|4) // ignored slip #define RRL_PROCEED_DROP (RRL_DROP|4) // ignored drop #define RRL_QUEUE_SIZE_MIN 0x00000400 #define RRL_QUEUE_SIZE_MAX 0x01000000 #define RRL_RESPONSES_PER_SECOND_DEFAULT 5 // MUST be stored in base 10 #define RRL_ERRORS_PER_SECOND_DEFAULT 5 // MUST be stored in base 10 #define RRL_WINDOW_DEFAULT 15 // MUST be stored in base 10 #define RRL_SLIP_DEFAULT 2 // MUST be stored in base 10 #define RRL_QUEUE_SIZE_MAX_DEFAULT 16384 // MUST be stored in base 10 #define RRL_QUEUE_SIZE_MIN_DEFAULT 1024 // MUST be stored in base 10 #define RRL_IPV4_PREFIX_LENGTH_DEFAULT 24 // MUST be stored in base 10 #define RRL_IPV6_PREFIX_LENGTH_DEFAULT 56 // MUST be stored in base 10 #define RRL_LOG_ONLY_DEFAULT 0 // MUST be stored in base 10 #define RRL_ENABLED_DEFAULT 0 // MUST be stored in base 10 #define RRL_EXEMPTED_DEFAULT "none" void rrl_init(); void rrl_finalize(); /** * Look at the message for RRL processing. * Returns an RRL code. * After this call, the message may be truncated. * * @param mesg the query message * @param ans_auth_add the answer that would be given to the client * @return an RRL error code */ ya_result rrl_process(message_data *mesg, zdb_query_ex_answer *ans_auth_add); void rrl_cull(); bool rrl_is_logonly(); const config_section_descriptor_s *confs_rrl_get_descriptor(); #endif /* _RRL_H */ /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/dynupdate_query_service.h0000644000000000000000000000013114505005533024005 xustar000000000000000030 mtime=1695812443.486997141 29 atime=1695812445.78203001 30 ctime=1695812495.587743328 yadifa-2.6.5-11201/sbin/yadifad/dynupdate_query_service.h0000664000374500037450000000505214505005533023752 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include #include "database.h" /** * The dynupdate service loads the next update from the queue and runs it. */ ya_result dynupdate_query_service_init(); ya_result dynupdate_query_service_start(); ya_result dynupdate_query_service_stop(); void dynupdate_query_service_finalise(); /** * This is only used by the UDP side. * * direct socket reference may have some bad side effects if the network is restarted or stopped */ ya_result dynupdate_query_service_enqueue(zdb *db, message_data *msg, int sockfd); void dynupdate_query_service_reset(); /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-resignature.h0000644000000000000000000000013114505005533025544 xustar000000000000000030 mtime=1695812443.485997126 29 atime=1695812445.78203001 30 ctime=1695812495.589743357 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-resignature.h0000664000374500037450000000571514505005533025517 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #pragma once #include "server-config.h" #include #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_DNSSEC_SUPPORT /** * If zone_desc_owner is 0, does not lock the zone_desc */ ya_result database_service_zone_dnssec_maintenance_lock_for(zone_desc_s *zone_desc, u8 zone_desc_owner); ya_result database_service_zone_dnssec_maintenance(zone_desc_s *zone_desc); // one thread for all the program void database_service_zone_dnskey_set_alarms_for_key(zdb_zone *zone, dnssec_key *key); /** * * Fetches all (smart signing) events of all the keys of a zone and arms them. * * @param zone */ void database_service_zone_dnskey_set_alarms(zdb_zone *zone); /** * * Fetches all (smart signing) events of all the keys of all the zones and arms them. * * @return */ void database_service_zone_dnskey_set_alarms_on_all_zones(); ya_result database_service_zone_resignature_init(); ya_result database_service_zone_resignature_finalize(); #else #error "no RRSIG management support: database-service-zone-resignature.h should not be included" #endif /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config-dnssec-policy.h0000644000000000000000000000013214505005533023063 xustar000000000000000030 mtime=1695812443.541997928 30 atime=1695812445.785030053 30 ctime=1695812495.591743385 yadifa-2.6.5-11201/sbin/yadifad/config-dnssec-policy.h0000664000374500037450000000547214505005533023035 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup configuration * @brief */ #pragma once #include ya_result config_register_key_roll(const char *null_or_key_name, s32 priority); ya_result config_register_key_suite(const char *null_or_key_name, s32 priority); ya_result config_register_key_template(const char *null_or_key_name, s32 priority); ya_result config_register_denial(const char *null_or_key_name, s32 priority); /** * @fn ya_result config_register_dnssec_policy(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * , , and are needed for * get all of them before registering all sections * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_dnssec_policy(const char *null_or_key_name, s32 priority); yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config-key-roll-parser.h0000644000000000000000000000013214505005533023337 xustar000000000000000030 mtime=1695812443.313994663 30 atime=1695812445.781029996 30 ctime=1695812495.593743414 yadifa-2.6.5-11201/sbin/yadifad/config-key-roll-parser.h0000664000374500037450000000703514505005533023306 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifa * @ingroup ### * @brief */ #pragma once #include #include #include "zone-signature-policy.h" /*----------------------------------------------------------------------------*/ #pragma mark DEFINES #define KEY_ROLL_LINE_CRON_TYPE true #define KEY_ROLL_LINE_RELATIVE_TYPE false // key roll actions values #define KR_ACTION_GENERATE 0 #define KR_ACTION_PUBLISH 1 #define KR_ACTION_ACTIVATE 2 #define KR_ACTION_INACTIVE 3 #define KR_ACTION_REMOVE 4 #define KR_ACTION_DS_PUBLISH 5 #define KR_ACTION_DS_REMOVE 6 // key roll actions names #define KR_ACTION_GENERATE_NAME "generate" #define KR_ACTION_PUBLISH_NAME "publish" #define KR_ACTION_ACTIVATE_NAME "activate" #define KR_ACTION_INACTIVE_NAME "inactive" #define KR_ACTION_REMOVE_NAME "remove" #define KR_ACTION_DS_PUBLISH_NAME "ds-publish" #define KR_ACTION_DS_REMOVE_NAME "ds-remove" /*----------------------------------------------------------------------------*/ #pragma mark STRUCTS typedef struct key_roll_line_s key_roll_line_s; struct key_roll_line_s { union { zone_policy_rule_definition_s cron; zone_policy_relative_s relative; } policy; s32 action; s32 relative_to; bool type; }; /*----------------------------------------------------------------------------*/ #pragma mark PROTOTYPES ya_result config_key_roll_parser_line(const char *key_roll_line, key_roll_line_s *krl, u8 action); yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/zone-signature-policy.h0000644000000000000000000000013214505005533023313 xustar000000000000000030 mtime=1695812443.328994877 30 atime=1695812445.781029996 30 ctime=1695812495.595743443 yadifa-2.6.5-11201/sbin/yadifad/zone-signature-policy.h0000664000374500037450000003515114505005533023262 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ // YYYY MM DD hh mm // 7 4 5 5 6 : 27 bits : one bit is not worth it, shifts it is // 134217728 : // 68567040 : 26.031 bits => 27 bits #pragma once #include #include #include #include "zone_desc.h" #define ZONE_POLICY_DATE_YEAR_BASE 2000 #define DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM 4 #define DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS (7*86400) #define ZONE_POLICY_ABSOLUTE 1 #define ZONE_POLICY_RELATIVE 2 #define ZONE_POLICY_RULE 3 // index to a rule typedef struct zone_policy_rule_definition_s zone_policy_rule_definition_s; #define ZONE_POLICY_RULE_ANYMINUTE 0x0fffffffffffffffLL #define ZONE_POLICY_RULE_ANYWEEK 0x0000000f #define ZONE_POLICY_RULE_ANYHOUR 0x00ffffff #define ZONE_POLICY_RULE_ANYDAY 0x7fffffff #define ZONE_POLICY_RULE_ANYWEEKDAY 0x0000007f #define ZONE_POLICY_RULE_ANYMONTH 0x00000fff #define ZONE_POLICY_RELATIVE_TO_GENERATE 0 #define ZONE_POLICY_RELATIVE_TO_PUBLISH 1 #define ZONE_POLICY_RELATIVE_TO_ACTIVATE 2 #define ZONE_POLICY_RELATIVE_TO_INACTIVE 3 #define ZONE_POLICY_RELATIVE_TO_REMOVE 4 #define ZONE_POLICY_RELATIVE_TO_DS_PUBLISH 5 #define ZONE_POLICY_RELATIVE_TO_DS_REMOVE 6 #define DNSSEC_POLICY_FLAGS_REMOVE_OTHER_KEYS 0x01 // remove keys not matching a policy struct zone_policy_rule_definition_s // rule-like match { u64 minute:60,week:4; // 64 / 0 minutes, nth dayname of month u64 hour:24,day:31,weekday:7; // 62 / 2 hours, day of month, day of week u16 month:12; // 12 / 4 month of year }; struct zone_policy_time_type_s { u32 reserved:30,type:2; }; struct zone_policy_absolute_s // all zero-based except year 2000-based { u32 minute:6,hour:5,day:5,month:4,year:7,zeroes:3,type:2; }; // 60 + 24 + 31 + 12 + 7 + 4 = 138 typedef struct zone_policy_rule_s zone_policy_rule_s; struct zone_policy_rule_s // points to a rule-like match { u32 index:30,type:2; }; typedef struct zone_policy_relative_s zone_policy_relative_s; struct zone_policy_relative_s { // 25 bits ~ 1 year, 26 2, 27 ~ 4 u32 seconds:27, relativeto:3, type:2; }; typedef union zone_policy_date zone_policy_date; union zone_policy_date { struct zone_policy_time_type_s type; struct zone_policy_absolute_s absolute; struct zone_policy_rule_s rule; struct zone_policy_relative_s relative; }; typedef struct zone_policy_table_s zone_policy_table_s; struct zone_policy_table_s { zone_policy_date created; // from previous created ? zone_policy_date publish; // from created zone_policy_date activate; // from publish zone_policy_date inactive; // from activate zone_policy_date delete; // from inactive #if HAS_DS_PUBLICATION_SUPPORT zone_policy_date ds_add; // from publish zone_policy_date ds_del; // from delete #endif }; typedef struct dnssec_denial dnssec_denial; struct dnssec_denial { char *name; u8 *salt; u32 resalting; u16 iterations; u8 algorithm; // hash algorithm: 1 u8 salt_length; bool optout; // volatile int rc; }; typedef struct dnssec_policy_key dnssec_policy_key; struct dnssec_policy_key { char *name; // default u16 size; // 1024 u16 flags; // 0 u8 algorithm; // RSA-SHA256 volatile int rc; }; typedef struct dnssec_policy_roll dnssec_policy_roll; struct dnssec_policy_roll { char *name; // default struct zone_policy_table_s time_table; volatile int rc; }; typedef struct dnssec_policy_key_suite dnssec_policy_key_suite; struct dnssec_policy_key_suite { char *name; dnssec_policy_key *key; dnssec_policy_roll *roll; volatile int rc; }; struct dnssec_policy { char *name; // default struct dnssec_denial *denial; ptr_vector key_suite; u8 flags; u8 dnskey_count_max; volatile int rc; }; typedef struct dnssec_policy dnssec_policy; #define DNSSEC_POLICY_COMMAND_INIT 0 #define DNSSEC_POLICY_COMMAND_GENERATE_KEY 1 #define ALARM_KEY_DNSSEC_POLICY_EVENT 16 struct dnssec_policy_queue_parameter_generate_key { struct dnssec_policy_key_suite *suite; zone_desc_s *zone_desc; }; typedef struct dnssec_policy_queue dnssec_policy_queue; struct dnssec_policy_queue { struct dnssec_policy_queue *next; u8 *origin; time_t epoch; // 0 for ASAP // create one key with these parameters ... // first signature of a zone ... (with or without key generation) // ... u8 command; bool queued; union { struct dnssec_policy_queue_parameter_generate_key generate_key; } parameters; }; /** * Compare two dates together. * Absolute with Absolute * Relative with Relative * * Any other combination will return -1 * * @param d1 first date * @param d2 second date * @return <0,0,>0 if d1 is less than, equal to, or greater than d2 */ int zone_policy_date_compare(const zone_policy_date *d1, const zone_policy_date *d2); /** * Retrieves the first day of the month. * * 0 is Sunday * * @param year 0-based * @param month 0-based * @return the number of the day of the month or an error code */ ya_result zone_policy_get_first_day_from_year_month(int year, int month); /** * Retrieves the first day of the month. * * 0 is Sunday * * @param year 0-based * @param month 0-based * @param week 0 to 4, week of the day * @param wday 0 to 6, day of the week, 0 for Sunday * @return the number of the day of the month or an error code */ ya_result zone_policy_get_mday_from_year_month_week_wday(int year, int month, int week, int wday); /** * Initialises an absolute date from a year, month, week and week-day * * ie: 2nd Wednesday of January 2001 * * 0 is Sunday * * @param date the date to initialise * @param year 0-based * @param month 0-based * @param week 0 to 4, week of the day * @param wday 0 to 6, day of the week, 0 for Sunday * @return an error code */ ya_result zone_policy_date_init_from_year_month_week_wday(zone_policy_date *date, int year, int month, int week, int wday); /** * Initialises an absolute date from a UNIX epoch * * @param date * @param epoch * @return an error code */ ya_result zone_policy_date_init_from_epoch(zone_policy_date *date, time_t epoch); /** * Gets the UNIX epoch from an absolute date * * @param date * @param epoch a pointer to hold the result * @return an error code */ ya_result zone_policy_date_get_epoch(const zone_policy_date *date, time_t *epoch); /** * Initialises the absolute date with an epoch plus time in seconds. * * @param date * @param epoch an epoch to add the seconds to * @param seconds * @return an error code */ ya_result zone_policy_date_init_after_epoch(zone_policy_date *date, time_t epoch, u32 seconds); /** * Initialises the absolute date with an absolute date plus time in seconds. * * @param date * @param from an absolute date to add the seconds to * @param seconds * @return an error code */ ya_result zone_policy_date_init_after_date(zone_policy_date *date, const zone_policy_date *from, u32 seconds); /** * Initialises a date using a rule applied on an epoch * * @param result_date * @param rule_date * @param after_epoch * @return */ ya_result zone_policy_date_init_from_rule_applied_with_epoch(zone_policy_date *result_date, const zone_policy_date *rule_date, time_t after_epoch); /** * Initialises an epoch from a rule applied on an epoch * * @param rule_date * @param after_epoch * @param result_epoch * @return */ ya_result zone_policy_get_epoch_from_rule_applied_with_epoch(const zone_policy_date *rule_date, time_t after_epoch, time_t *result_epoch); zone_policy_rule_definition_s *zone_policy_rule_definition_get_from_index(u32 index); zone_policy_rule_definition_s *zone_policy_rule_definition_get_from_rule(const zone_policy_date *rule); /** * This complicated functions initialises a date with the earliest matching of the rule starting from 'from' * * @param date * @param from * @param rule * * @return an error code */ ya_result zone_policy_date_init_at_next_date(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule); ya_result zone_policy_table_init_from_date(zone_policy_table_s *tbl, zone_policy_table_s *with, zone_policy_date *from); /** * Sets the DNSSEC mode of the zone using the policy. * * Expects zone_desc to be locked (for reading). */ ya_result zone_policy_process_dnssec_chain(zone_desc_s *zone_desc); ya_result zone_policy_process(zone_desc_s *zone_desc); ya_result zone_policy_roll_create_from_rules(const char *id, const zone_policy_rule_definition_s *generate, const zone_policy_rule_definition_s *publish, const zone_policy_rule_definition_s *activate, const zone_policy_rule_definition_s *inactive, const zone_policy_rule_definition_s *remove, const zone_policy_rule_definition_s *ds_publish, const zone_policy_rule_definition_s *ds_remove); ya_result zone_policy_roll_create_from_relatives(const char *id, const zone_policy_relative_s *generate, u8 generate_from, const zone_policy_relative_s *publish, u8 publish_from, const zone_policy_relative_s *activate, u8 activate_from, const zone_policy_relative_s *inactive, u8 inactive_from, const zone_policy_relative_s *remove, u8 remove_from #if HAS_DS_PUBLICATION_SUPPORT , const zone_policy_relative_s *ds_publish, u8 ds_publish_from, const zone_policy_relative_s *ds_remove, u8 ds_remove_from #endif ); dnssec_policy_roll *dnssec_policy_roll_acquire_from_name(const char *id); void dnssec_policy_roll_release(dnssec_policy_roll *dpr); ya_result dnssec_policy_roll_test_all(time_t active_at, u32 duration_seconds, bool print_text, bool log_text); dnssec_denial *dnssec_policy_denial_create(const char *id, u8 algorithm, u16 iterations, const u8 *salt, u8 salt_length, u32 resalting, bool optout); dnssec_denial *dnssec_policy_denial_acquire(const char *id); void dnssec_policy_denial_release(dnssec_denial *dd); dnssec_policy_key *dnssec_policy_key_create(const char *id, u8 algorithm, u16 size, bool ksk, char* engine); dnssec_policy_key *dnssec_policy_key_acquire_from_name(const char *id); void dnssec_policy_key_release(dnssec_policy_key *dpk); ya_result dnssec_policy_roll_test_at(struct dnssec_policy_roll *kr, time_t active_at, time_t *will_be_inactive_at, bool print_text, bool log_text); ya_result dnssec_policy_roll_test(struct dnssec_policy_roll *kr, time_t active_at, u32 duration_seconds, bool print_text, bool log_text); dnssec_policy_key_suite *dnssec_policy_key_suite_create(const char *id, dnssec_policy_key *dpk, dnssec_policy_roll *dpr); dnssec_policy_key_suite *dnssec_policy_key_suite_acquire_from_name(const char *id); void dnssec_policy_key_suite_acquire(dnssec_policy_key_suite *dpks); void dnssec_policy_key_suite_release(dnssec_policy_key_suite *dpks); dnssec_policy *dnssec_policy_create(char *name, dnssec_denial *denial, ptr_vector *key_suite); dnssec_policy *dnssec_policy_acquire_from_name(const char *id); void dnssec_policy_acquire(dnssec_policy *dp); void dnssec_policy_release(dnssec_policy *dp); bool dnssec_policy_is_key_matching(dnssec_policy *dp, dnssec_key *key); bool dnssec_policy_defines_ksk(dnssec_policy *dp); #define CONFIG_DNSSEC_POLICY(fieldname_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)dnssec_policy_zone_desc_config, NULL,{._intptr=0}, sizeof(dnssec_policy), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, ya_result dnssec_policy_zone_desc_config(const char *value, void *dest, anytype sizeoftarget); void dnssec_policy_initialise(); // remove all previously defined policies void dnssec_policy_finalize(); /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/dynamic-module-interface.h0000644000000000000000000000013114505005533023710 xustar000000000000000029 mtime=1695812443.32499482 30 atime=1695812445.781029996 30 ctime=1695812495.597743471 yadifa-2.6.5-11201/sbin/yadifad/dynamic-module-interface.h0000664000374500037450000002104514505005533023655 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #pragma once #include /** * Modules are meant for easy integration with existing infrastructure beyond the scope of what a name server has to do * * The basic rules for the module: * * _ check sizeof_struct field to match what you expect * _ never cast a const, if you do you could as well call abort() and be done with it * _ you don't own anything and can expect all pointer values to be destroyed at the instant you return * _ be quick : if you need to spend time (a millisecond is an insane amount of time), use a queue/thread and give up if the queue is full * _ there are threads : you can fork() => exec(), but you cannot simply fork(). * _ be instance-aware: more than one instance of the module could be running at the same time, not all instances * * Failing to respect these rules will have detrimental consequences on yadifad * * There is no plan yet to support "unload" as it may be very complex and is not needed for our requirements. * Once a module is loaded, it's until shutdown. */ #define DYNAMIC_MODULE_INTERFACE_ID 0 struct dynamic_module_settings_args { size_t sizeof_struct; // sizeof(struct dynamic_module_on_dnskey_created_args) char **argv; // the parameters given to the module char *data_path; // the data path as configured for yadifad int argc; // the parameters count given to the module }; typedef void dynamic_module_startup_callback(); typedef void dynamic_module_settings_callback(const struct dynamic_module_settings_args *); typedef void dynamic_module_shutdown_callback(); static inline void dynamic_module_startup_callback_nop() {} static inline void dynamic_module_settings_callback_nop(const struct dynamic_module_settings_args *args) {(void) args;} static inline void dynamic_module_shutdown_callback_nop() {} struct dynamic_module_interface { size_t sizeof_struct; dynamic_module_startup_callback *on_startup; dynamic_module_settings_callback *on_settings_updated; dynamic_module_shutdown_callback *on_shutdown; }; // no: no typedef, thanks #define DYNAMIC_MODULE_DNSKEY_INTERFACE_ID 1 struct dynamic_module_on_dnskey_args { size_t sizeof_struct; // sizeof(struct dynamic_module_on_dnskey_args) const char *caller_name; // the name of the caller const uint8_t *origin; // the origin of the key const uint8_t *rdata; // the rdata record time_t epoch_created; time_t epoch_publish; // if not published yet, at that time, it needs to be added in the zone time_t epoch_activate; // if not activated yet, at that time, it needs to be used for signatures time_t epoch_revoke; // not handled yet time_t epoch_inactive; // if active, at that time, it needs to stop being used for signatures time_t epoch_delete; // if still in the zone, at that time, it needs to be removed from the zone uint16_t rdata_size; uint16_t flags; // the flags (network endian) uint16_t tag; // uint8_t algorithm; // dnskey algorithm }; // no: no typedef, thanks typedef void dynamic_module_on_dnskey_callback(const struct dynamic_module_on_dnskey_args *); static inline void dynamic_module_on_dnskey_callback_nop(const struct dynamic_module_on_dnskey_args *args) {(void)args;} struct dynamic_module_dnskey_interface { size_t sizeof_struct; dynamic_module_on_dnskey_callback *on_dnskey_created; dynamic_module_on_dnskey_callback *on_dnskey_publish; dynamic_module_on_dnskey_callback *on_dnskey_activate; dynamic_module_on_dnskey_callback *on_dnskey_revoke; dynamic_module_on_dnskey_callback *on_dnskey_inactive; dynamic_module_on_dnskey_callback *on_dnskey_delete; }; // no: no typedef, thanks #define DYNAMIC_MODULE_STATISTICS_ID 2 enum dynamic_module_rcode_index { NOERROR = 0, // RCODE FORMERR = 1, SERVFAIL = 2, NXDOMAIN = 3, NOTIMP = 4, REFUSED = 5, YXDOMAIN = 6, YXRRSET = 7, NXRRSET = 8, NOTAUTH = 9, NOTZONE = 10, BADVERS = 16, // OPT BADMODE = 19, BADNAME = 20, BADALG = 21, BADTRUNC = 22 }; enum dynamic_module_tsig_rcode_index { BADSIG = 16 - 16, // TSIG BADKEY = 17 - 16, BADTIME = 18 - 16 }; struct dynamic_module_statistics_args { size_t sizeof_struct; uint64_t epoch_us; // epoch in microseconds uint64_t input_loop_count; uint64_t input_timeout_count; uint64_t loop_rate_counter; uint64_t loop_rate_elapsed; /* udp */ uint64_t udp_input_count; uint64_t udp_queries_count; uint64_t udp_notify_input_count; uint64_t udp_updates_count; uint64_t udp_dropped_count; uint64_t udp_output_size_total; uint64_t udp_undefined_count; uint64_t udp_referrals_count; /* tcp */ uint64_t tcp_input_count; uint64_t tcp_queries_count; uint64_t tcp_notify_input_count; uint64_t tcp_updates_count; uint64_t tcp_dropped_count; uint64_t tcp_output_size_total; uint64_t tcp_undefined_count; uint64_t tcp_referrals_count; uint64_t tcp_axfr_count; uint64_t tcp_ixfr_count; uint64_t tcp_overflow_count; /* rrl */ uint64_t rrl_slip; uint64_t rrl_drop; /* answers RCODEs */ uint64_t *udp_rcode_count; uint64_t *tcp_rcode_count; uint64_t *udp_tsig_rcode_count; uint64_t *tcp_tsig_rcode_count; uint32_t rcode_count_size; uint32_t tsig_rcode_count_size; }; // no: no typedef, thanks typedef void dynamic_module_statistics_callback(const struct dynamic_module_statistics_args *); static inline void dynamic_module_statistics_callback_nop(const struct dynamic_module_statistics_args *args) {(void)args;} struct dynamic_module_statistics_interface { size_t sizeof_struct; dynamic_module_statistics_callback *on_statistics_update; }; // no: no typedef, thanks union dynamic_module_interfaces { struct dynamic_module_interface interface; struct dynamic_module_dnskey_interface dnskey_interface; struct dynamic_module_statistics_interface statistics_interface; }; /** * The module will be called with this signature to return the relevant interface. * * Typically, at least id=0 will be called and should be returned (or not) * * The entry point will have to be specified at configuration or tried, in order, as: * * _ module_interface_init * _ "shared object file name with '-' replaced by '_'" + _interface_init */ typedef int dynamic_module_interface_init(int id, union dynamic_module_interfaces *out_interface); /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/AUTHORS0000644000000000000000000000013014505005533017741 xustar000000000000000030 mtime=1695812443.316994706 30 atime=1695812445.781029996 28 ctime=1695812495.5997435 yadifa-2.6.5-11201/sbin/yadifad/AUTHORS0000664000374500037450000000013514505005533017704 0ustar00signersigner00000000000000Gery Van Emelen Eric Diaz Fernandez yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/COPYING0000644000000000000000000000013014505005533017724 xustar000000000000000029 mtime=1695812443.47299694 29 atime=1695812445.78203001 30 ctime=1695812495.601743529 yadifa-2.6.5-11201/sbin/yadifad/COPYING0000664000374500037450000000312414505005533017670 0ustar00signersigner00000000000000 Copyright (c) 2011-2023, EURid vzw. All rights reserved. The YADIFA TM software product is provided under the BSD 3-clause license: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of EURid nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ChangeLog0000644000000000000000000000013114505005533020444 xustar000000000000000030 mtime=1695812443.485997126 29 atime=1695812445.78203001 30 ctime=1695812495.604743572 yadifa-2.6.5-11201/sbin/yadifad/ChangeLog0000664000374500037450000017673414505005533020431 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ 20230906: YADIFA 2.6.5-public Secondaries will nolonger enforce the TTL value of the NSEC3PARAM record. Fixes an issue caused by a limitation of the select system call. 20230301: YADIFA 2.6.4-public Fixes an issue building for 32 bits targets. 20230213: YADIFA 2.6.3-public Fixes an issue where the answer to a DNSSEC query to a wild record right below the apex in a DNSSEC3 zone would not return all the relevant NSEC3 records Fixes an issue where the answer to a DNSSEC query to a wild record in an NSEC zone would incorrectly use the name of the query in the answer Fixes an issue where NSEC3-owning labels were not compressed Complies with Fedora https://fedoraproject.org/wiki/Changes/PortingToModernC (see m4/contributions/20230118-fedora-toolchain-porting-to-modern-c.patch) 20221209: YADIFA 2.6.2-public Fixes an issue trying to link the backtrace call while building yadifad on FreeBSD 20221130: YADIFA 2.6.1-public Fixes an issue where the answer of an TSIG-signed IXFR query over an undefined domain would not be properly signed. Fixes an issue building for big-endian architectures. 20221004: YADIFA 2.6.0-public The server can optionally load the locally stored zone before asking for the last version to its primary (load-local-first) The server now avoids storing temporary zone transfer images to disk if the zone is small enough (axfr-memory-threshold) zone transfers source address can now be specified in the configuration (transfer-source) The server now allows to sign a zone using only zone signing keys. Fixes online chain generation started from an zone that is not covered by DNSSEC. Fixes an issue where a generated DNSKEY could be missing smart fields if the storage became full right before they needed to be written. Fixes an issue that could occur using EDDSA on big-enough data sets. 20220228: YADIFA 2.5.4-public Fixes an issue handling CNAME records. 20211025: YADIFA 2.5.3-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet with privileged access. 20210929: YADIFA 2.5.2-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet with privileged access. Fixes an issue where a corrupted configuration file could lead to a crash while starting-up. 20210924: YADIFA 2.5.1-public Fixes a critical issue that could cause yadifad to crash handling certain DNS packet. Fixes an issue where yadifad would sometimes reply with an AXFR instead of an IXFR if the journal is under maintenance. Increased the pid column in the logger to 6 characters Drastically increased the limit for TCP queries. Note that using a high enough number compared to the available memory will cause yadifad to warn about limits and OOM kill risks. In practice a few hundred TCP queries should be enough. 20210602: YADIFA 2.5.0-public Adds a new, friendlier, TCP manager. When enabled, TCP connections aren't closed harshly after some time has elapased without any activity. In a nutshell: It is enabled using --enable-tcp-manager. It works using a quota of allowed parallel connections per host. There is one value for the registeres hosts and one for unknown hosts. All defined primaries are automatically added to the TCP manager as registered hosts. The server's local addresses are automatically added to the registered hosts. The default timeout is set to 3 seconds but doesn't imply a connection will be closed : only that it is a candidate for being closed. EDDSA support has been enable. Sending a TCP message now uses a single system call (message_send_tcp) Fixes an issue in some FreeBSD setups where UDP messages couldn't be sent by YADIFA. Fixes an issue in FreeBSD where TCP connections would sometimes be closed too quickly. Fixes an issue where failed dynamic updates prerequisites would return SERVFAIL instead of the more accurate error code. Fixes atomic usage for older C compilers. Fixes an issue where some RRSIG records may not be updated in time if they happened to have their update bundled with NSEC3 records updates while the incremental change could not be immediately written in the journal. Fixes the yadifa keygen module to understand "help" as a command and not as a domain. 20210223: YADIFA 2.4.2-public Fixes an issue where records below delegation are not ignored (https://github.com/yadifa/yadifa/issues/12). Fixes an issue in the _mm model where shutting down while still initializing may not stop properly. Changes default user/group to 'yadifa' user in example configuration. Fixes an issue with autoconf 2.70 obsolete functions. Fixes an issue where an unknown key configured in a zone acl may lead to a crash. Fixes an issue where an query without EDNS involving ACLs using optional keys would incorrectly be rejected. Fixes an issue where a network thread with a failed context would incorrectly have its context deleted. Adds a feature to yadifad to ensure that the dates in the key-roll section can be successfully applied for the next 10 years (--check-policies). Added support for primary and secondary variant options. Fixes builds for gcc 11. 20201209: YADIFA 2.4.1-public Fixes an issue in dnscore where a DNS TCP query would not return the real DNS error code. Fixes an issue that could happen when a network model isn't supported. Fixes the propagation of sendmmsg/recvmmsg function availability detection. Fixes an issue where yadifad would issue a warning when a key with algorithm > 7 is used with an NSEC zone. Fixes an issue that will occur on a chrooted environment where a managed-path would be used incorrectly. Fixes CNAME answers not following the aliases chain. Fixes CNAME recursion not returning the same answer as named in NXDOMAIN cases (reported by https://github.com/SivaKesava1, see https://github.com/yadifa/yadifa/issues/11) Adds patch for musl support (from https://github.com/kolbma, see https://github.com/yadifa/yadifa/issues/9#issuecomment-723047226) Adds stack size fix for musl support (the default size is way too small) Now imports a custom version of stdatomic.h for systems where it is missing, located in dnscore/thirdpary/stdatomic.h Made for CentOS 7 and any other release where that file is missing. The import is only active if strictly needed and will only be visible during the build. At the moment, it is not being installed with the other headers. The original source of the file was taken from https://gist.github.com/nhatminhle/5181506 YAKEYROLLD 2.4.1 Fixes the handling of incomplete TCP queries. Fixes a possible race-condition when initialising the keyroll context error codes. The keyroll now has another automatic recovery layer where it completely restarts the handling of a domain, generating a one-step update to put the zone in the expected state. 20201012: YADIFA 2.4.0-public Fixes an issue that could happen with multiprocess logging. Fixes an issue parsing a *. domain. Improves support for LibreSSL. Added contributions directories with community-provided patches. Readied the source for the release. Many changes have been made since version 2.3.x. Please read the manual for more information. YAKEYROLLD 2.4.0 Since version 2.4.0, yadifad optionally allows dynamic update of RRSIG records. The external key managing tool using this feature is being released along with it. Please read the manual for more information. YADIFA CTRL 2.4.0 The updated version of the command line controller has been made more user-friendly. Please read the manual for more information. 20200722: YADIFA 2.4.0-67 Default listen is now "0.0.0.0,::0" Added "do-not-listen" feature to avoid conflicts with systemd-resolved, default is empty. Added --enable-systemd-resolved-avoidance in the configure script to change the default of "do-not-listen" to "127.0.0.53 port 53" Zone file reader now decodes \ddd tokens. Text zone parsing is now more lenient in what it accepts: unescaped @ and $ in a domain will be read as '@' and '$', with a warning. Improves the configuration update by keeping a timestamp of all files involved and checking they have been modified. Logger configuration can now be reconfigured during runtime. In the event of an incorrect reconfiguration of the network, yadifad will periodically try to reconfigure itself reading the configuration files. Fixes a potential issue in NSEC3 replying. Fixes TXT parsing issues. Fixes a leak with the chroot remapping when reconfiguring. Fixes a leak processing the command line. Fixes a leak in the policies configuration. 20200630: YADIFA 2.4.0-64 Network setup errors will now stop yadifad if they occur during the first configuration. If they occur during a reconfiguration the error will be logged every minute instead of every second. Fixes DSA API usage with OpenSSL 1.1.0 Fixes an other side effect of FreeBSD's process-shared mutexes where a thread waiting on a condition wouldn't always be woken up. Fixes IPv6 handling in FreeBSD. Fixes an issue where the logging could lock when daemonizing. Fixes the build-time-configuration paths when using cmake. Fixes an issue where a sync clean command would not delete the journal if the zone wasn't dynamically updated since the start of yadifad. Fixes an issue where the size of the buffer given for a message would be slightly bigger than needed. Duplicate but identical definition of a TSIG key are nolonger considered an error. Increased the log output handling control commands (mostly error conditions) yadifa ctrl: The fqdn isn't set by default anymore (it used to be '.' by default) Adds the "freeze", "thaw", "unfreeze", "freezeall", "unfreezeall" and "thawall" friendly keywords to yadfia ctrl. Adds the "notify" command. The FQDN has no default value anymore. Fixes the friendly parsing of the command line. Fixes several minor issues with the console output of the command line. 20200608: YADIFA 2.4.0-52 This is version is going to production as primary and for public release. Fixes limit case issues giving NSEC3 answers for some zone structures (mostly *, * + CNAME) Fixes an issue where the packet reader may not allocate enough room for SOA records (found in yakeyrolld) YKEYROLL-1.0.5-4 This is version is going to production as primary and for public release. Fixes the handling of more limit cases (broken setup). 20200515: YADIFA 2.4.0-51 In an effort to find issues using different tools, the code has been partially ported to compile in Visual Studio 2019. (Doesn't run) The code analyser from Visual Studio 2019 reported 290 potential issues, 5 of which were valid (understand: errors) and not reported by other analysers. We have used a mmap.c MIT-licensed code from github to help in this task. We'll have to decide to keep it or to write ours when we will do a Windows release. Adds a DNS pcap analyser tool to measure DNS traffic from a network pcap file. Used to find why so many packets were lost in the benchmark. (resut: The benchmark tool was broken.) Adds a --disable-filepool-cache build configure option. Logs clarity has been improved. Improved usability:
network-model option can now use words instead of just numbers, respectively: single, buffered, multi for 0, 1, 2. Fixes an issue that could occur in the logger service with some settings. Fixes an issue in the new network model. Fixes a memory leak that could occur in the cirular_file layer of the journal. Fixes a memory leak that could occur in the journal depending on the reason it was closed. Fixes a memory leak that could occur at shutdown while destroying a file pool. Fixes an issue where trying to print a corrupted fqdn (e.g.: random bytes) could have an undefined behaviour. Fixes an issue using the drop-before-load feature where the memory of the previous zone would not be completely freed yet before the new version of the zone started to load. Fixes a race condition that could occur while detaching stdout/stderr from console. Fixes missing AA flag in primary notification. Fixes a rare issue where a signal could block the logger. Fixes TSIG-covered answers of an unsupported opcode. YKEYROLL-1.0.5-3 Fixes the handling of several limit cases (all coming from a broken, corrupted state). 20200320: YADIFA 2.4.0-50 Efforts have been made to reduce the memory usage in the case where a lot of specific listening addresses are defined. A new network-model taking advantage of the multiple-send/receive of some kernels has been added. (recvmmsg, sendmmsg) Back-ported gcc-10 compatibility fix from the main development branch (trunk) This issue was reported by several distributions already using the yet-to-be-released gcc-10 (We are using gcc-9) Adds the tcp_manager for experimentation (an alternative way to keep track of opened TCP connections). Fixes a potential memory leak that could sometimes happen freeing NSEC3 records without removing their attached RRSIG first. Fixes FreeBSD 12.1/libressl build issue. YKEYROLL-1.0.5-2 Now handles SIGHUP to reopen the log files. Imrpoved the command line options help. 20200212: YADIFA 2.4.0-49 This version is going for production. Fixes an issue with signature expiration value where the time was sometimes incorrectly taken from the oldest key. The RRL tables are now growing faster in order to avoid wasting resources. YKEYROLL-1.0.4-2 This version is going for production. Now keeps the expected starting point and end point for all steps. This is used to verify the state before and after each update. Now has a "print" mode that logs the "plan" out (logs all the known steps). 20200128: YADIFA 2.4.0-48 New nameserver infrastructure update. In
, adds a log_files_disabled flag to disable checking the log-path directory for existence and writing rights. Without this, yadifad would refuse to work without a proper log output directory like we have on our SELinux setup. Fixes an issue that would occur if SELinux would reject a write operation with EPERM to a socket we have succesfully opened for writing. yadifad would not complain and end-up hammering both the socket creation and the logs Fixes an issue that would occur if SELinux would reject a read operation with EPERM on a socket we have successfully opened for reading. This happens, notably, the notify service, producing a lot of log lines. Now such an issue will make yadifad pause for one second. 20200106: YADIFA 2.4.0-45 Fixes an issue where having no ZSK would trigger a useless maintenance pass. Fixes an issue where notifies could stop being sent when their queue was full. (New dynamic queue used at minimal increased CPU cost for this part) Fixes an issue where reopening or syncing would have their effect delayed. Fixes an issue that could occur for DSA T parameter deduction from a public key. Made the command line more friendly using the new features from dnscore. YKEYROLL 1.0.3-0 Now filters-out publish and unpublish meta lines. Fixes an issue where retrying to send a message to an unresponsive server could have the message content reset. 20191120: YKEYROLL-1.0.2-3 This version is going for production. Adds switching to a uid/gid set in the configuration file (must be set to the same as yadifad). Adds process mutual-exclusion for plan generation. Improves shutdown speed. Reduces logging. 20191118: YADIFA 2.4.0-43 Fixes an issue where enabling key activation leniency would incorrectly enable deactivation leniency. Fixes an issue where redundant signatures would be kept longuer than needed. The journal name for the root zone will now be root_zone.cjf (only one dot) intead of ..cjf, as that name was troublesome. YKEYROLL-1.0.1-9 This version is going for production. Can now work in a loop without detaching from console. 20191106: YADIFA 2.4.0-42 This version is going for production. Issues found by CLion's code inspector fixed or marked as invalid. Downgrades several "error" into "notice". More generally, an effort has been made to reduce the log size. Setting a policy field with an incorrect value will now log an error instead of stopping yadifad. Slave zones don't run sanitization anymore, as the primary is "right". This avoids thight rules being counter-productive in production environments. Fixes an issue that would occur if an update happens at tahe same time as the removal of a DNSKEY when a maintenance has started. Fixes an issue where the authoritative bit coudl be flipped off in some operations. Fixes an issue where removing and adding the same record in a single update would incorrectly drop its signature. Fixes an issue where a secondary receiving an inccorrect IXFR stream (specifically: finishing on an incomplete page) would not reject the broken page. Fixes an issue where a primary would cut an IXFR page in half if a shutdown was triggered while the page was being read from the journal. Fixes an issue in the policy date computation that could lead to a time period without signature coverage. 20191010: YADIFA 2.4.0-41 Fixes typos. YKEYROLL-1.0.0 Improved error codes returned by the keyroll policies. Fixes an error that could occur parsing a corrupted step file. 20190927: YADIFA 2.4.0-40 Adds a tool to append an IXFR in text form (so, from a dig command) to a journal. This is an unfriendly pure dev tool meant to create some tests scenarii. The cjf-scan tool, used to print the content of a journal, can now print its content in a way similar to the dig command. Simply use the "-clean" command line option before the journal file name. Both the above tools mean that a journal can be dumped as text, edited then re-created as binary. Although not initially created for this purpose, it can be a powerful fix tool. Fixes the "11:04" issue. It was triggered by an optimisation not being handled on all exit paths of the maintenance function, potentially leading to a buffer overflow. Fixes an issue in the journal: If the first update written into a dynamically sized journal is bigger that the default size of the journal (64KB) then yadifad incorrectly tries to shift-out content to make room, which it obviously cannot do. 20190920: YADIFA 2.4.0-39 In
, adds axfr-strict-authority option. Defaulted to enabled unless yadifad was built-configured using --enable-non-aa-axfr-support. Improves TXT parsing (github/ JZerf). Fixes an potential crash on SIGHUP if the zone loader calee gives an incorrect answer (github/kolbma). Fixes an issue where a UDP query with invalid return address (port 0) would trigger an EINVAL leading yadifa to shutdown the thread. Fixes an issue with IPv6 aliased replies. Depending on the OS/release the value could be wrong. The fix tries several options. This has been tested on several Debian and RedHat variants and seems to work properly. 20190919: YADIFA 2.4.0-38 note: Serial bump due to issues during rpm packaging. Reduces the number of warnings triggered by type bitmap fixes. Now only prints one and leaves the rest available as debug. Contains code to track the "11:04" issue and verify the hypothesis of its cause. 20190913: YADIFA 2.4.0-26 Timestamp in dns-udp are now human-readable. Writing a zone as text now computes and updates the approximate wire size for the zone (AXFR/IXFR trigger accuracy) yadifad now replies to ENDS# bad format. Fixes an issue in dns-udp where the message size would not be reset on the received side. Fixes an issue in dns-udp where the rate-limiter would fire before a message would be checked for actual IO (aggregated queries). Fixes an issue in dns-udp where a very slow call-back would slow down the processing part of the receiver enough to trigger a timeout of the query. Fixes a warning that would be shown for keys being both NSEC and NSEC3. Fixes an issue where the '#' character was incorrectly set as a zone comment. Fixes an issue where a journal with an invalid character in a name would trigger an infinite error loop (until program shutdown). Fixes an issue where a DNSKEY dynamic update coming with an RRSIG push could fail under certain conditions. Fixes some typos. YKEYROLL-beta Improves error reporting. Allows different configuration files. Fixes corrupted plan handling. Updates the configuration example. Correction updates are now merged in a single step, then played. Added error-retries-cases in daemon mode. Added a --timeus-offset parameter (not publicly documented) to lie about the current time. Added a --dryrun parameter. Fixes an issue handling key duplicates. 20190627: YADIFA 2.4.0-25 Fixes an issue where a corrupted journal would prevent a secondary from working. Fixes an issue replaying NSEC3 chain changes as a secondary that could occur when a discrepancy was found. If a corrupted journal is found, yadifad now renames it adding ".bad" to its name. 20190613: YADIFA 2.4.0-24 Adds safeguards for the logger shutdown. FreeBSD 12.0 issue diagnostic: There was an elusive issue occurring only on FreeBSD 12.0 related to shared mutexes. After posting an the issue anonymously with a proof-of-concept code, it turns out it was bug in FreeBSD: An unlocked mutex is still being accessed by the thread library right after the effective unlock has occurred. yadifad destroys a structure containing mutexes right after it is unlocked for the last time. FreeBSD has issued a fix, but at the moment the fix appeared to have side effects. This may have been us not rebuilding "world" properly (First time we do this), or it may be that the patch wasn't complete at the time. The matter is closed as far as yadifad's source code is concerned so this is something to watch after the next FreeBSD update. Added the "freebsd12-test" proof-of-concept code in the test section of the code. Adds the IP_MTU_DISCOVER IP_PMTUDISC_OMIT patch: patch received 20190323 from daisuke.higashi@gmail.com /* * Linux 3.15 has IP_PMTUDISC_OMIT which makes sockets * ignore PMTU information and send packets with DF=0. * Fragmentation is allowed if and only if the packet * size exceeds the outgoing interface MTU or the packet * encounters smaller MTU link in network. * This mitigates DNS fragmentation attacks by preventing * forged PMTU information. * FreeBSD already has same semantics without setting * the option. */ Added sereral fixes for NetBSD builds. Ultimately, NetBSD declares but does not implement PSHARED. This makes that platform unusable for the moment. Logs have been improved (level & verbosity, some have been downgraded to debug). Improves command-line help. Internally, INVALID and UNPROCESSABLE messages are now seen as the same error. In
, added log_unprocessable boolean to add a warning log for bad DNS messages. If yadifad is not started as root but requires elevated privileges in order to bind an addess, it will stop. Fixes build on older sytems (FreeBSD). Fixes an incorrect warning message related to TSIG. Fixes an issue with garbage collection at shutdown. Fixes an issue that would occur if the signature max-interval was set high enough to end up in an integer overflow. Fixes an issue where newly added keys would not always be taken into account in the computations. Fixes an issue where the nttl cache could overflow. Fixes an issue in the path provider of yadifad where an empty secondary zone file setting could lead to a NULL pointer reference. Fixes an issue where the KSK public key would not be stored, losing the flags of the key as seen by libdnscore. Fixes an issue in dns-udp that would occur when TCP fails with a DNS error. Fixes an issue in dns-udp where the thread_pool destruction order could trigger some issues. Fixes an issue where a TCP read time-out from a client (thus when the server is sending) could lead to an indefinitely held connection. Fixes an issue that could happen in the RRL, leading to the current state pool being misused. Fixes an issue where an error code sent from the socket server would nto be interpreted correctly. Fixes an issue in the text parser that was being tripped in the yakeyrolld. Fixes an issue where asking the help from the command line would return to the shell with a non-zero value. YKEYROLL-alpha Code commited in alpha state to avoid potential issues related to a certain event. The new keyroll software is being written in C. It is based on the YADIFA framework. It's main features are: _ cron-like timings, _ KSK/ZSK separation, _ RRSIG push usage, _ one event per file and one file per event, _ integrity milestones, _ extension of the time-line on demand. 20190326: YADIFA 2.4.0-23 Added autogen.sh in the make dist. Improved yadifad startup so that simply asking for its version would not go through service start. Improved AXFR log messages: now showing the peer's IP address. 20190322: YADIFA 2.4.0-22 EDDSA is known but not handled. (EDDSA handling code is in the 2.5.x branch) Sanitization now checks for DNSKEY matching RRSIG records. Fixes an issue where yadifad would abort in a specific condition: A zone that allows RRSIG pushed by dynamic updates with a bunch of inactive ZSK keys available, one of them still in the zone with said inactive ZSK key in the zone having signature expiring after its deactivation date AND in the future with an active key in the zone that does not expire and is fully usable (key pair available) with a single KSK key in the zone that has no private part available ... ... was considered fubar and triggering an emergency stop (ending up in an abort()) Fixes an issue handling BigNum from OpenSSL being sometimes smaller than expected. Fixes a double-free issue (crashed yadifad the 20190311). Fixes an issue that would occur on a secondary when the journal is too small to work optimally. Added a "dsfromkey" in the test section, to be added in the command line later 20190218: YADIFA 2.4.0-21 Fixes an issue where killing yadifad while thread creation is in limbo would not work. yadifad will now ignore all signals until notify service thread is up and running (thus outside of limbo) Fixes an issue where policies would be tried on non-policed zones. 20190213: YADIFA 2.4.0-19 Improves CPU usage by inlining several small domain-related functions. Sanitization now occurs only once, after the journal has been replayed. Code marked as obsolete has been removed. Fixes an issue where an internal update message woudln't be properly initialised. Fixes an irrelevant warning when "publish" equals "active" or "inactive" equals "delete" in a DNSKEY key. Fixes embedded delegation issues. _ Sanitization complaining about wrong glue resource records in embedded delegations _ Sanitization complaining about unexpected signatures in embedded delegations _ Internal state is now correctly set. Fixes a policy issue where a DNSSEC chain would not be added if the DNSKEY was not already generated and added. Fixes an issue where removing an RRSIG covering a type could sometimes invalidate an RRSIG covering another in the same domain. Fixes an issue where a query that would return an RDATA with a '.' domain and require additionals, would trigger a memory underflow with undefined results. Fixes an issue that could occur when replaying NSEC3 updates from the journal. Fixes dnssec-policy NSEC chain generation that could not be completed because of an interference by the internal integrity tests. Fixes an issue with NSEC3 type bitmap handling that would occur on an empty broken zone without RRSIG records. Fixes an issue where reading corrupted messages would not be handled properly. Fixes an issue where the illegal addition of a DS resource record would not be handled properly. 20190205: YADIFA 2.4.0-18 Signature verification now has an abstract API (easier extension to future algorithms e.g.: EDDSA). Added our own zone test program. This includes signatures verification. It's in the test section and the feature should be moved inside the command line later. Fixes an issue where deleting a DNSKEY in a dynamic update would not be handled properly. Fixes an issue where removing an RRSIG in signature maintenance would not change the type bitmap in the associated NSEC3 record. Fixes an issue where maintenance would remove an RRSIG for a replacement (exchange) that could not be created (e.g.: private key missing). Fixes an issue managing a zone with an NSEC3PARAM record but no NSEC3 chain. Fixes an issue where NSEC3 chain recomputation could be called before RRSIG changes would be known. Fixes an issue where stopping yadifad while it started a signature thread (in a window of a few instructions) would trigger an assertion. Fixes an issue where dnssec-policies could conflict with RRSIG pushed with a dynamic update. Fixes an issue parsing records with a class ANY in update messages. 20190109: YADIFA 2.4.0-17 Added a test for the keyroll feature (test section). Key creation time is now systematically set in newly created keys. 20181122: YADIFA 2.4.0-11 Fixes handling of several limit cases in chain updates (that should never happen in a sane system). Fixes some minor memory leaks. This is the first release that is meant to prevent DNSKEY with incorrect "smart" setup making yadifad trying to take them at every occasion (e.g.: dynamic update). 20181122: YADIFA-2.4.0-10 Made to caters for the needs of an internal project. 20180802: YADIFA 2.4.0-1 Fixes all fixable -Wextra warnings (that ar not in -Wall for some reason) One of these warnings would have showed the suprise-issue with the ACL ... These fixes needs to be thoroughly tested before being used on anything production. 20180725: YADIFA 2.4.0 alpha Fixes an issue where a secondary having downloaded a invalid zone from an primary will proceed re-download it and failing until the zone is fixed on the primary. Now it will wait until the axfr-retry + random(axfr-retry-jitter) elapsed. It is now possible to change the network configuration at runtime. It is now possible to have threads logged with a tag instead of an opaque hexadecimal ID. (--enable-log-thread-tag) It is now possible to pipe execute loggers output. e.g.: my-zipped-channel "|/usr/bin/gzip - >> /var/log/yadifa.log.gz" Obviously, outputs are run using the uid/gid set for the server. As the command can be restarted for several reasons so using >> is the obvious choice. The maximum number of queries that are queued on an overloaded server is now configurable. Note this is currently only used by network-model 1 and the ram usage in bytes is about (workers * size * 64) For a server that only needs to answer 10000 queries per second, it would be suitable to use: e.g.: network-model-worker-backlog-size 10000 Our artificial benchmark tests are showing that setting this value to 500000 is enough to handle about 2.5 millions queries per second on a server with the appropriate hardware configured properly (network queues, ...). The zone journal maximum size is now an hard limit instead of "best effort within a few bytes". The --disable-messages ./configure option has now been removed as the send & recv are not suitable for proper aliased addresses handling. The build system has been changed: From now on, to do a debug build, add CFLAGS='-O0 -g3 -DEBUG=1' to the configure command. e.g.: ./configure --enable-shared --enable-log-thread-tag CC=clang CFLAGS='-O0 -g3 -DDEBUG=1' A release build that keeps the symbols would be: ./configure --enable-log-thread-tag CC=clang CFLAGS='-O3 -g -DDEBUG=0' The dnszone library has been merged into dnscore and dnsdb. Several of our unit tests have been added as well as the valgrind suppression file (yadifad.supp). Several simplifications and abstractions have been made on the internal APIs. Network model 1 is the only model available from this version. dnssec-thread-count parameter is now obsolete 20180213: YADIFA 2.3.8 Fixes the OPT record Z flags not being cleared in server answers. 20171207: YADIFA 2.3.0 - 2.3.7 From now on, both primary and secondaries are updating the zone in the same manner (journal transactions) Messages are now default (--enable-messages). Disable them using --disable-messages. Adds more (dynamic) update validation. Adds a build option to remove compile date and time from various help messages (--disable-build-timestamp) A primary can now be configured to allow updating RRSIG records externally (e.g.: update add domain. RRSIG ...) Fixes an issue where closing an (a)XFR stream could lead to a race over the file descriptors. Fixes an issue where an AXFR query would return a version of the zone too old to be upgradable by following incremntal updates. Fixes an issue where zones with big-enough NSEC3 coverage (several millions NSEC3 record) could potentially reach an internal limit of the database. Fixes an issue where shutting down YADIFA while a zone is being downloaded (AXFR) may make it wait forever. Fixes an issue where the secondary would complain about a missing private key. Fixes an issue where a specifically truncated IXFR query may make YADIFA replying with an AXFR. Fixes an issue where an IXFR query returning "not implemented" instead of an AXFR would be retried later as an IXFR. Fixes an issue where hammering reopening the logs on an overloaded server would not work properly. 20170912: YADIFA 2.2.6 Fixes an issue where a maliciously crafted message may block the server. (CVE-2017-14339) 20170420: YADIFA 2.2.5 Fixes an issue on message-enabled servers where the return address would not be captured Increased the maximum number of network interfaces to 256 20170406: YADIFA 2.2.4 Fixes an issue with relative include names that would not always be properly computed Fixes an issue where concurrent configuration reloads could lead to a crash 20170223: YADIFA 2.3.1 (internal) Added thread_pool_try_enqueue_call to give up if a queue is full or overworked (distance project) Fixes an issue with the CW queuing mechanism when trying to fill a full queue. 20161124: YADIFA 2.3.0 (internal) ECDSA can now be disabled at ./configure time. The support of ECDSA is not available in the openssl package of older Linux distributions. You can now add --disable-ecdsa at configure time to allow a build on these systems. Processed signals are now logged upon processing (info level) to allow the admin to know when a signal has effectively gone through. CPU affinity can now be tuned to stick a worker on a core. In
: thread-affinity-multiplier can be used to use every (1) or every odd (2) logical CPU. Parameter range from 0 to 4. (default is 0 = autodetect) By default, if hypertheading is detected, the multiplier is set to 2, else to 1. thread-affinity-base can be used to chose the first local CPU to consider. Parameter range from 0 to 3. (default is 0) In the end, network workers will have their affinity set to (base + multiplier * workerindex). The main purpose is to avoid using the hyperthread logical CPU as it can be counterproductive in some setups for high (10Gbps) troughput. Fixes: - fixed an issue on servers using the network-model 1 model (
: network-model 1) - fixed an issue where the removal in a certain order of hash/hash* related domains would end-up triggering an abort - fixed an issue where querying a signed domain that was deleted would answer NOERROR instead of NXDOMAIN - fixed an issue where a zone loaded with a journal would not be marked "dirty" and thus would not be fully dumped on disk upon kill -USR1 - fixed an issue with network aliases not configured on all setups of --enable-messages - fixed an issue with the logger not releasing the log files before reconfiguration - fixed an issue with the journal where heavy load would prevent notification to secondaries 20161108: YADIFA 2.2.2 OpenSSL 1.1.0 crypto API support 20160719: YADIFA 2.2.1 Multi-primary support: Added axfr-retry-failure-delay-multiplier and axfr-retry-failure-delay-max
parameters to increase the time between two AXFR/IXFR retries on a primary. Fixes: - fixed an issue that would crash a YADIFA secondary when restarting with a journal present - fixed an issue in AXFR/IXFR retry timing management 20160715: YADIFA 2.2.0 Multi-primary support: In , the primaries field is now a list. When the primary fails to answer, it is moved to the end of the list and (new) first one is used instead. There is a true-multiprimary setting, defaulted to 'no'. In true multiprimary mode, changing the primary implies dropping local zone data and ignore serial values. This is to be used for a setup with truly independent primaries. By default, the primary change occurs at first failure. This can be changed to a higher value with multiprimary-retries (maximum: 255) This mostly makes sense on true-multiprimary mode as you want to be sure before reloading a zone completely. Smart signing: Keys with smart signing information are now handled by YADIFA. DNSSEC policies: YADIFA generates an rolls your keys and makes a non-DNSSEC zone into an NSEC or NSEC3 one. Support for ECDSA algorithm. Better support for huge incremental changes of a zone: YADIFA used to do the modification in one go, which could make it unresponsive for very big changes. Now the changes are applied more slowly, allowing queries to be answered. New network model: A new network model can be enabled. This model's main purpose is to be more resistent to system stalls with minimal, if any, performance loss.
network-model 1 NSEC3 management improved. Several improvements have been made on the way NSEC3 is handlded. Chains partially covering the zone are now accepted. Fixes: - fixed an issue where the maximum pid value supported was 99999 - fixed an issue with RRSIG TTL values that were not always at the expected value. - fixed an issue with the $TTL not being respected. 20160126: YADIFA 2.1.6 Fixes: - fixed an issue where the referral would not be measured for UDP on a optimised build. 20160108: YADIFA 2.1.5 Dynamic updates do not use temporary files anymore which improves their general performance. The statistics now shows the referrals. Fixes: - fixed an issue where getting a huge incremental transfer would prevent the server from answering queries while applying the changes. - fixed an issue serving IXFR that would occur when a incremental change step was bigger than 64KB - fixed an issue for Solaris with the memory alignment fix not active everywhere - fixed an issue on the Solaris build settings - fixed an issue where sometimes yadifad would not find a configuration file given as a parameter with a relative path - fixed an issue where a wild-card would not be properly returned with an AXFR - fixed an issue where dynamically updating a zone at a speed such that the zone file would need to be written multiple times on disk before finishing the previous write could lead to a deadlock 20151026: YADIFA 2.1.4 The zone reader error reporting has been improved. Stacktrace support added for Solaris. Known issue: - Adding and or removing NSEC3PARAM dynamically is not properly handled. Fixes: - fixed an issue where an NSEC3 answer proving a * query would lead to a crash - fixed an issue where a private key may be not recognised as such - fixed an issue where dynamic update prerequisite check would fail a valid match - fixed an issue where zone signature maintenance would only start if all private keys were available. 20150821: YADIFA 2.1.3 Fixes: - fixed an issue that could lead to a crash at startup - fixed an issue where parsing a TYPE#### record would stop the parser prematurely 20150814: YADIFA 2.1.2 The ./configure script has a new option: --enable-full-ascii7 This changes the behaviour of DNS name validation to accept all the ASCII7 characters instead of only the DNS-space ones. Enabling this option is not recommended. Fixes: - fixes an issue where the hmac-shaX identification string sent with a TSIG had the suffix ".sig-alg.reg.int". 20150714: YADIFA 2.1.1 The yadifa command line has a new option: --config|-c file : read the specific configuration file instead of ~/.yadifa.rc Issues detected on the NSEC3 database have now been upgraded from debug to info/warning Fixes: - fixed an issue where, on some cases; the garbage collector for the zones was not triggering for a long time. - fixed an issue in the Makefile (courtesy of DENIC) - fixed an issue where a few bytes could be leaked in some rare cases when failing to unload a zone - fixed an issue in RRL where some values of IPv6 prefix - fixed an issue accepting some answers on IXFR transfers 20150424: YADIFA 2.1.0 New journal file format: This new format addresses a few issues like having maximum journal file and a relatively constant random access time even for very big sizes. The internal messaging queue has been changed to address huge amount of zones. New CHaos queries supported: hostname id.server Known issues: _ building successfully with LTO may require to append both AR=gcc-ar and RANLIB=gcc-ranlib to the ./configure command 20150403: YADIFA 2.0.6 This release is a public release. This minor update's sole purpose is to fix YADIFA builds on OpenBSD. Fixes: - fixed a crash that could occur while sending a massive amount of notifications - OpenBSD builds are fixed. Tested on: OpenBSD 5.6 amd64, standard installation. Configure: ./configure Tested on: OpenBSD 5.6 amd64, with gcc 4.9 installed. Configure: ./configure CC=egcc 20150226: YADIFA 2.0.5 This release is a public release. Fixes: - fixed an issue with huge IXFR transfers as a primary - fixed an issue with notifications on secondary-secondary-primary setup - fixed an issue with a potential infinite loop loading an AXFR from a primary - fixed missing hmac-sha* from configuration - fixed an issue with TLSA records parsing - fixed an issue with base 16 encoding - fixed an issue parsing * domains - fixed an issue with some RRL motivated answers - increased the maximum number of network interfaces from 5 to 16 - fixed an error in the configuration examples where "statistics" was used instead of "stats" - minor fixes and improvements 20141216: YADIFA 2.0.4 This release is a public release. By popular demand, the default log file directory is now PREFIX/var/log/yadifa. It can be set using --with-logdir=/my/dir Improved build mechanism. It has been tested to work automatically on Linux, FreeBSD, OSX, SunOS. RedHat family builds will use -O2 as maximum optimisations. Note that some optional features are now enabled by default but can be disabled. Fixes: - fixed an issue with the AXFR transfer where the serial number would not be properly taken into account - fixed an issue with the notify mechanism that could occur if the server was only listening to 127.0.0.1 - fixed an issue with bogus DNSKEY records that may potentially lead to a crash in openssl - fixed a reported potential "tmpfile" vulnerability on DEBUG builds (generated with make debug) - fixed an issue with IPv6 connections on some architectures - typos fixes - minor fixes and improvements 20141104: Architecture portability enhancements. On Solaris, if no --enable-force32bits nor --enable-force64bits is set, then 64 bits will be forced (fixes an issue at link-time) ELF 64-bit MSB executable SPARCV9 Version 1, UltraSPARC3 Extensions Required, dynamically linked, not stripped, no debugging information available PATH=/opt/csw/bin:/usr/ccs/bin:$PATH ./configure --enable-force32bits PATH=/opt/csw/bin:/usr/ccs/bin:$PATH make 20141030: Architecture portability enhancements. FreeBSD 9 FreeBSD dnode3 9.0-RELEASE-p3 FreeBSD 9.0-RELEASE-p3 #0: Tue Jun 12 02:52:29 UTC 2012 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 gcc (GCC) 4.2.1 20070831 patched [FreeBSD] ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 9.0 (900044), not stripped Ubuntu Linux dnode10 3.2.0-49-generic #75-Ubuntu SMP Tue Jun 18 17:39:32 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xe3b8601b9b5e59f8c9ce519cacbe9b8ff544ff1d, not stripped OSX Darwin RD-Mac-Mini.local 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun 3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64 Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) Mach-O 64-bit executable x86_64 20141029: Architecture portability enhancements. uname -a gcc --version file yadifad YellowDog Linux Linux 2.6.29-3.ydl61.4 #1 SMP Mon Sep 7 14:50:27 PDT 2009 ppc64 ppc64 ppc64 GNU/Linux gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44) ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped note: using --enable-force64bits failed because of ssl, no simple/quick way to install openssl-devel.ppc64 seemed available Debian PPC64 Linux 3.2.0-3-powerpc64 #1 SMP Mon Jul 23 08:03:56 UTC 2012 ppc64 GNU/Linux gcc (Debian 4.6.3-8) 4.6.3 ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xedc47c984a4af7eb9a7ecbc0f135e4d064ba08f0, with unknown capability 0x41000000 = 0x13676e75, with unknown capability 0x10000 = 0xb0401, not stripped note: using --enable-force64bits failed because of ssl, no simple/quick way to install openssl-devel.ppc64 seemed available 20141016: YADIFA 2.0.2 TCP fallback support on truncation 20140905: YADIFA 2.0.0 This release is a public release Fixes: - fixed a log incorrectly reporting an error when the client didn't close the TCP connection fast enough - fixed an issue with the statistics on TCP queries Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. 20140829: YADIFA 2.0.0-beta3-public This release is a public release - --disable-master feature at configure now builds a secondary-only server Fixes: - fixed an issue with TSIG signed queries - fixed an issue with thread pool live resizing - fixed an issue where reading an undeleted obsolete journal ending at the start of a newly transferred zone from the primary would incorrectly trigger an error Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. 20140630: YADIFA 2.0.0-beta2-public This release is a public release - basepath disabled - pidpath removed, only pidfile remains - log reopen notification is now timestamped - secondary zones no longer complain about missing NSEC/NSEC3 private keys - the error code ZRE_FILE_NOT_FOUND has been replaced by the more accurate code ZRE_NO_VALID_FILE_FOUND - default logging settings no longer output debug Fixes: - fixed issue in flag computation (AD,CD) - fixed an issue with journal truncation sometimes leading to a crash - zone parsing now correctly accepts '#' as a comment marker - zone parsing now rejects wrong fqdn as soon as it reads them, leading to a more accurate error message - removing the last dnskey of a zone no longer crashes the server Known issue: - removing the last key of a signed zone is permitted by YADIFA but triggers some chicken-egg issue with signatures. yadifa remote client commands prototype is now available with the following supported commands: -shutdown shuts down yadifa e.g. ./yadifa -s "192.0.2.1 port 53" -t shutdown -cfgreload reloads the and sections of the yadifad configuration e.g. ./yadifa -s "192.0.2.1 port 53" -t cfgreload -logreopen closes and reopen the log files e.g. ./yadifa -s "192.0.2.1 port 53" -t logreopen -freezeall prevents all zones from being updated dynamically with nsupdate e.g. ./yadifa -s "192.0.2.1 port 53" -t freezeall -freeze prevents a zone from being updated dynamically with nsupdate e.g. ./yadifa -s "192.0.2.1 port 53" -t freeze -q somedomain.eu -unfreezeall enables updates of all zones again e.g. ./yadifa -s "192.0.2.1 port 53" -t unfreezeall -unfreeze enables updates of a zone again e.g. ./yadifa -s "192.0.2.1 port 53" -t unfreeze -q somedomain.eu In order to work, the allow-control ACL must be defined either in
for the global commands and may also be defined in for the ones targeting a specific zone. e.g. allow-control 127.0.0.1 Note that tsig is not supported in the client yet. 20140528: YADIFA 2.0.0-beta1-public This release is a public release - NSID implemented (enabled at ./configure time with --enable-nsid - generic parser for: - getops - zone file - resolv.conf - configuration - '@' can now be used in a zone file - new binary for controlling 'yadifad' (yadifa) - framework is rewritten for multi core systems - single core server has been removed Fixes: - fixed several minor issues Know issues: - removing all dnskeys from a zone file crashes the server - yadifa has some issues with nodelay, nocork 20130424: YADIFA 1.1.0 _ added DSA signature _ added SHA-256 SHA-384 SHA-512 digest algorithms _ now supports additional DNSSEC algorithms: DSASHA1 DSASHA1_NSEC3 RSASHA256_NSEC3 RSASHA512_NSEC3 _ Respone Rate Limitation implemented (enabled at ./configure time with --enable-rrl) _ --enable-tiny-footprint now reduces the memory usage further by reducing the standard log queue from 2^20 to 2^12 entries _ the general speed has been slightly improved _ dynamic updates pending for more than 3 seconds are now dropped with an error _ dynamic provisioning Fixes: _ fixed a memory leak that could occur at NSEC3 generation when loading the zone failed in a particular way _ fixed a memory leak at ixfr send _ fixed handling of '_' character that was improperly stored in the database _ fixed bandwidth limit settings (tcp stream in and out) not always being taken from the configuration _ fixed TSIG answer verification for notifies _ fixed error codes not being registered and thus logged as unknown hexadecimal error code. _ other minor fixes 20130612: YADIFA 1.0.3 Fixes only (backports from 1.1.0) Fixes: _ fixed an issue preventing YADIFA from being build from another directory _ fixed an issue with OSX systems where gsed has to be used instead of sed _ fixed an issue with the '_' character not being properly handled _ fixed an issue where reading MX record from a zone file would incorrecly be rejected as invalid _ fixed an issue where the OPT record would not be properly written _ fixed an issue where an undefined ACL reference would be silently ignored _ fixed missing code tags for several error codes. From now on unregistered codes are dumped in hexadicimal. _ fixed portability issues with BSD and OSX _ fixed several minor issues 20120921: YADIFA 1.0.2 Fixes only Fixes: _ fixed an issue where the journal file was sometimes not properly closed at the end of a task _ fixed an issue where the TCP usage slots would sometimes wrongly return that they were all being used _ fixed an issue on IXFR processing (secondary side) where the type of answer from the primary would not be properly detected _ fixed an issue with TSIG on secrets not exactly 16 bytes long (binary form) _ fixed an issue on 32 bits architectures where the sig-validity-* fields would not be properly handled if not set on each zone section. _ slightly improved the replay time of big journal files _ fixed several minor issues Known issues: _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120709: YADIFA 1.0.1 _ logging repeat compression is now by channel instead of global Fixes: _ fixed an issue where glibc whould assert if libgcc_s.so (libgcc_s.so.1) and libc.so (libc.so.6) where not available inside the chrooted directory of YADIFA _ fixed an issue in the syslog module Known issues: _ on 32 bits architectures, the sig-validity-* fields are not properly copied from
to as a workaround, set the sig-validity fields in each container in 32 bits architectures ie: sig-validity-interval 7 sig-validity-regeneration 168 sig-validity-jitter 3600 _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120625: YADIFA 1.0.0 _ LTO support can be enabled with --enable-lto but this is not working with clang. LTO does not increase the performance significally _ parallel processing of listening addresses can now be enabled. It can be set using thread-count-by-address in the
section. By default YADIFA will not use parallel processing as this feature has not been as thoroughly tested as the single-thread processing model _ default parameters tuning _ fixes Known issue: _ on 32 bits architectures, the sig-validity-* fields are not properly copied from
to as a workaround, set the sig-validity fields in each container in 32 bits architectures ie: sig-validity-interval 7 sig-validity-regeneration 168 sig-validity-jitter 3600 20120530: YADIFA 1.0.0RC3 _ the configuration parser now ignores undefined logger names and report them with a warning _ syslog messages are now put in the name of "yadifad" instead of the name used for the "syslog" channel _ syslog messages do not print the time from YADIFA anymore _ improved the steps involved in loading a locally cached secondary zone _ zones are now loaded in background _ man page yadifad-conf.man5 renamed into yadifad.conf.man5 Fixes: _ AXFR/IXFR answers with the RA bit set are nolonger rejected as invalid _ YADIFA now answers to SIGINT again (shutdown) _ fixed an issue where obsolete AXFR files were not always being deleted _ fixed an issue occurring when both IPv4 and IPv6 were available to handle a notify _ fixed journal replay issue where some RRSIGs records were not properly removed _ fixed an issue occurring with IPv6 queries _ fixed an issue in the generation of a specific NSEC3 error answer _ fixed named query style layout Known issue: _ if the serial of a zone is changed in a way that it goes beyond a value such as the journal serial start is bigger than the journal serial end, issues are expected for IXFR answers. _ notify is ignored on TCP 20120328: YADIFA 1.0.0RC2 _ fixed logging issue on work file creation error _ fixed an issue where IXFR queries could be rejected as being wrongly formatted _ fixed an issue in the query logging text _ enabled command line options ( -u uid -g gid -d ) 20120319: YADIFA 1.0.0RC1 Is a full functional authoritative name server: - works as primary or secondary name server - AXFR - IXFR - NOTIFY - NSUPDATE - TSIG - CLASSES: - IN - CH (just for version) - TYPES: - AAAA - CNAME - DNSKEY - DS - HINFO - MX - NAPTR - NS - NSEC3 - NSEC3PARAM - NSEC - PTR - RRSIG - SOA - SRV - SSHFP - TXT - Automatic resigning - DNSSEC algorithms: - 5 (RSASHA1) - 7 (RSASHA1-NSEC3 - ACL's KNOWN ISSUES: NSEC3: _ cannot work with multiple NSEC3PARAM chains with mixed OPT-IN/OUT settings _ adding a new NSEC3 chain expects that the primary sends the NSEC3PARAM first (it does not seems to be always the case) We have a case where a primary starts with 2 thousands NSEC3 opt-out records then adds 6 millions NSEC3 opt-in records but does not give the NSEC3PARAM record first. The secondary server rejects them all because it's unable to link them to a chain. (This one has high priority) DNSSEC: _ it is not allowed to change the zone security mode (unsecure, NSEC, or NSEC3). Once the zone is loaded it keeps its security mode. _ dynamic updates of NSEC as well as NSEC3 records are refused QUIT: the server will shutdown on the following conditions: _ detection of an impossible situation or an internal integrity issue (ie: for any reason the SOA has vanished from a zone) _ memory limit reached which prevents any more work _ ipc issue which prevent internal services communication ACL: _ since the access control is set by zone and CHAOS class is not implemented as a configurable zone, it is not possible (yet) to specifically block CHAOS queries. 20111121: YADIFA 0.5.5 - many fixes KNOWN ISSUE: NSEC3 secondary zone replay fails. 20110706: YADIFA 0.5.0 - secondary mode, AXFR/IXFR (no TSIG yet for the secondary-side transfer) - answers to a notify from the primary - polls the (first) primary on the primaries list - maintains the .axfr & .ix files (deletes the obsoletes ones) - TSIG queries are checked - Replays the zone journal on startup after the zone load (journaling) - Answers IXFR queries (journaling) 20110601: YADIFA 0.4.0 Operational: - It works as a no dnssec name server - No notifies to secondary name servers - daemon - Answers AXFR queries with TSIG - nsupdate functionality (journaling) - TSIG on client server side will be transmitted, but not checked - ACL works - The zone has SOA, NS A resource records. 20110524: YADIFA 0.3.0 First release internally of yadifad 20110524115500 GMT+1. Operational: - It works as a no dnssec name server - No notifies to secondary name servers - daemon - Answers AXFR queries - The zone has SOA, NS A resource records. 20091224: YADIFA 0.2.0 _ Answers AXFR queries _ ACL based on IP and TSIG (not all query types are ACL'ed yet) 20091104: YADIFA 0.1.0 YADIFA is a work in progress. The main goal is to have an alternative for BIND or NSD. Version 0.1.0 is an authoritative server only. It has no: - AXFR/IXFR functionality - dynupdate - support for NSEC - support for NSEC3 - caching mechanism - additional tools (eg.dig, dnssectools, drill,...) It has: - a very fast way to give authoritative answer - a very fast method for loading the database and checking the zone files This first release is to have a feeling how it works in an operational environment. TODO Everything what is not implemented, has to be implemented. Most of the code is there, but is not activated. No comformity tests has been done. (This of course is on the todo list) Bug Reports and Mailing Lists Bugs reports should be sent to bugreport@yadifa.eu yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/NEWS0000644000000000000000000000012614505005533017375 xustar000000000000000029 mtime=1695812443.47299694 29 atime=1695812445.78203001 28 ctime=1695812495.6067436 yadifa-2.6.5-11201/sbin/yadifad/NEWS0000664000374500037450000000001414505005533017327 0ustar00signersigner00000000000000See README yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/README0000644000000000000000000000013214505005533017553 xustar000000000000000030 mtime=1695812443.531997785 30 atime=1695812445.784030039 30 ctime=1695812495.608743629 yadifa-2.6.5-11201/sbin/yadifad/README0000664000374500037450000000377514505005533017531 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ 20230906: YADIFA 2.6.5-public Secondaries will nolonger enforce the TTL value of the NSEC3PARAM record. Fixes an issue caused by a limitation of the select system call. yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/main.c0000644000000000000000000000013214505005533017763 xustar000000000000000030 mtime=1695812443.542997942 30 atime=1695812445.785030053 30 ctime=1695812495.610743657 yadifa-2.6.5-11201/sbin/yadifad/main.c0000664000374500037450000005640214505005533017734 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad Yet Another DNS Implementation for all * * @brief Yet Another DNS Implementation for all * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #define _POSIX_SOURCES #define __USE_POSIX #include "server-config.h" #include #include #ifndef WIN32 #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #include #include #include #include #include #if ZDB_HAS_DNSSEC_SUPPORT #include #include #endif #include "server_error.h" #include "config_error.h" #include "signals.h" #include "server.h" #include "notify.h" #include "database-service.h" #if HAS_DYNUPDATE_SUPPORT #include "dynupdate_query_service.h" #endif #if HAS_DYNCONF_SUPPORT #include "dynconf.h" #endif #include "process_class_ch.h" #include "zone-signature-policy.h" #if HAS_EVENT_DYNAMIC_MODULE #include "dynamic-module-handler.h" #endif #include "buildinfo.h" #define MODULE_MSG_HANDLE g_server_logger /*------------------------------------------------------------------------------ * GO */ static bool server_do_clean_exit = FALSE; int g_yadifa_exitcode = EXIT_SUCCESS; static bool own_pid = FALSE; static bool main_config_log_from_start = FALSE; // start logging asap static u32 main_config_features = DNSCORE_ALL; // start all services (can be reduced on early config) static bool main_config_help_requested = FALSE; // no point in starting anything void config_logger_setdefault(); void config_logger_cleardefault(); int process_command_line(int argc, char **argv, config_data *config); int zalloc_init(); void config_unregister_main(); static void server_register_errors() { error_register(CFG_ERROR_BASE,"CFG_ERROR_BASE"); /* Config error codes */ error_register(CONFIG_ZONE_ERR,"Error in config file"); /* error_register(YDF_ERROR_BASE,"YDF_ERROR_BASE"); error_register(YDF_ALREADY_RUNNING,"YDF_ALREADY_RUNNING"); error_register(YDF_PID_PATH_IS_WRONG,"YDF_PID_PATH_IS_WRONG"); */ /* Main error codes */ error_register(ZONE_LOAD_MASTER_TYPE_EXPECTED,"ZONE_LOAD_MASTER_TYPE_EXPECTED"); error_register(ZONE_LOAD_MASTER_ZONE_FILE_UNDEFINED,"ZONE_LOAD_MASTER_ZONE_FILE_UNDEFINED"); error_register(ZONE_LOAD_SLAVE_TYPE_EXPECTED,"ZONE_LOAD_SLAVE_TYPE_EXPECTED"); error_register(ZRE_NO_VALID_FILE_FOUND,"ZRE_NO_VALID_FILE_FOUND"); error_register(ANSWER_NOT_ACCEPTABLE,"ANSWER_NOT_ACCEPTABLE"); error_register(ANSWER_UNEXPECTED_EOF,"ANSWER_UNEXPECTED_EOF"); /* ACL */ error_register(ACL_ERROR_BASE,"ACL_ERROR_BASE"); error_register(ACL_TOKEN_SIZE_ERROR,"ACL_TOKEN_SIZE_ERROR"); error_register(ACL_UNEXPECTED_NEGATION,"ACL_UNEXPECTED_NEGATION"); error_register(ACL_WRONG_V4_MASK,"ACL_WRONG_V4_MASK"); error_register(ACL_WRONG_V6_MASK,"ACL_WRONG_V6_MASK"); error_register(ACL_WRONG_MASK,"ACL_WRONG_MASK"); error_register(ACL_DUPLICATE_ENTRY,"ACL_DUPLICATE_ENTRY"); error_register(ACL_RESERVED_KEYWORD,"ACL_RESERVED_KEYWORD"); error_register(ACL_TOO_MANY_TOKENS,"ACL_TOO_MANY_TOKENS"); error_register(ACL_NAME_PARSE_ERROR,"ACL_NAME_PARSE_ERROR"); error_register(ACL_UNKNOWN_TSIG_KEY,"ACL_UNKNOWN_TSIG_KEY"); error_register(ACL_UPDATE_REJECTED,"ACL_UPDATE_REJECTED"); error_register(ACL_NOTIFY_REJECTED,"ACL_NOTIFY_REJECTED"); error_register(ACL_UNDEFINED_TOKEN,"ACL_UNDEFINED_TOKEN"); error_register(CONFIG_WRONG_SIG_TYPE, "CONFIG_WRONG_SIG_TYPE"); error_register(CONFIG_WRONG_SIG_VALIDITY, "CONFIG_WRONG_SIG_VALIDITY"); error_register(CONFIG_WRONG_SIG_REGEN, "CONFIG_WRONG_SIG_REGEN"); error_register(DATABASE_ZONE_MISSING_DOMAIN, "DATABASE_ZONE_MISSING_DOMAIN"); error_register(DATABASE_ZONE_MISSING_MASTER, "DATABASE_ZONE_MISSING_MASTER"); error_register(DATABASE_ZONE_MISSING_TYPE, "DATABASE_ZONE_MISSING_TYPE"); error_register(DATABASE_ZONE_CONFIG_DUP, "DATABASE_ZONE_CONFIG_DUP"); error_register(NOTIFY_QUERY_TO_MASTER, "NOTIFY_QUERY_TO_MASTER"); error_register(NOTIFY_QUERY_TO_UNKNOWN, "NOTIFY_QUERY_TO_UNKNOWN"); error_register(NOTIFY_QUERY_FROM_UNKNOWN, "NOTIFY_QUERY_FROM_UNKNOWN"); error_register(POLICY_ILLEGAL_DATE, "POLICY_ILLEGAL_DATE"); error_register(POLICY_ILLEGAL_DATE_TYPE, "POLICY_ILLEGAL_DATE_TYPE"); error_register(POLICY_ILLEGAL_DATE_PARAMETERS, "POLICY_ILLEGAL_DATE_PARAMETERS"); error_register(POLICY_ILLEGAL_DATE_COMPARE, "POLICY_ILLEGAL_DATE_COMPARE"); error_register(POLICY_UNDEFINED, "POLICY_UNDEFINED"); error_register(POLICY_KEY_SUITE_UNDEFINED, "POLICY_KEY_SUITE_UNDEFINED"); error_register(POLICY_NULL_REQUESTED, "POLICY_NULL_REQUESTED"); error_register(POLICY_ZONE_NOT_READY, "POLICY_ZONE_NOT_READY"); } static void main_dump_info() { log_info("starting YADIFA " VERSION); log_info("built with " BUILD_OPTIONS); #if !DEBUG log_info("release build"); #else log_info("debug build"); #endif log_info("------------------------------------------------"); log_info("YADIFA is maintained by EURid"); log_info("Source code is available at https://www.yadifa.eu"); log_info("------------------------------------------------"); log_info("got %u CPUs", sys_get_cpu_count()); log_info("using %u UDP listeners per interface", g_config->thread_count_by_address); log_info("accepting up to %u TCP queries", g_config->max_tcp_queries); #if DNSCORE_HAS_ZALLOC_SUPPORT log_info("self-managed memory enabled"); // ZALLOC #endif #if HAS_RRL_SUPPORT log_info("response rate limiter enabled"); // RRL #endif } static bool yadifad_config_on_section_loggers_read_done_once = FALSE; static ya_result yadifad_config_on_section_loggers_read(const char* name, int index) { (void)name; (void)index; if(yadifad_config_on_section_loggers_read_done_once) { return SUCCESS; } //formatln("yadifad_config_on_section_main_read(%s,%i)", name, index); ya_result ret; pid_t pid; if(FAIL(ret = pid_check_running_program(g_config->pid_file, &pid))) { log_err("%s already running with pid: %lu (%s)", PROGRAM_NAME, pid, g_config->pid_file); return ret; } /* * From here we have the loggers ready (if any was set) */ if(g_config->server_flags & SERVER_FL_DAEMON) { server_setup_daemon_go(); } logger_start(); if(!config_logger_isconfigured()) { config_logger_setdefault(); } else { config_logger_cleardefault(); } main_dump_info(); if(FAIL(ret = server_service_init())) { log_err("failed to initialise network service: %r", ret); return ret; } database_service_init(); notify_service_init(); /* Initialize signals used for inter process communication and * quitting the program */ if(FAIL(ret = signal_handler_init())) { log_err("failed to setup the signal handler: %r", ret); if(!(g_config->server_flags & SERVER_FL_DAEMON)) { osformatln(termerr, "error: failed to setup the signal handler: %r", ret); flusherr(); } logger_flush(); return ret; } notify_wait_servicing(); signal_setup(); // hooks the signals #if DEBUG println("yadifad_config_on_section_loggers_read done"); flushout(); #endif yadifad_config_on_section_loggers_read_done_once = TRUE; return CONFIG_CALLBACK_RESULT_CONTINUE; } /** * Handles the configuration part of the server. * * @param argc * @param argv * @return 0 if the configuration is successful and the server can start * @return 1 if no error occurred but the server must stop * @return -1 if an error occurred and the server must stop */ int main_config(int argc, char *argv[]) { ya_result ret; if(main_config_log_from_start) // -L was used on the command line { config_logger_setdefault(); } /* * Initialise configuration file and set standard values */ if(FAIL(ret = yadifad_config_init())) { osformatln(termerr, "error: setting up configuration: %r", ret); flusherr(); return ret; } // channels then loggers config_add_on_section_read_callback("loggers", yadifad_config_on_section_loggers_read); if((ret = yadifad_config_cmdline(argc, argv)) != 0) { if(FAIL(ret)) { return ret; } return 1; } if(FAIL(ret = yadifad_config_read(g_config->config_file))) { osformatln(termerr, "error: reading configuration: %r", ret); flusherr(); return ret; } if(FAIL(ret = yadifad_config_finalize())) { osformatln(termerr, "error: processing configuration: %r", ret); flusherr(); return ret; } #if 0 && DEBUG config_print(termout); osformatln(termout, "starting logging service"); #endif /* * flushes whatever is in the buffers */ flushout(); flusherr(); return 0; } /** * Tries to create a temporary file in a directory. * Deletes the file afterward. * * @param dir * @return true iff the file was created */ static bool main_final_tests_is_directory_writable(const char* dir) { ya_result ret; if(FAIL(ret = access_check(dir, ACCESS_CHECK_READWRITE))) { ttylog_err("error: '%s' is not writable as (%d:%d): %r", dir, getuid(), getgid(), ret); return FALSE; } return TRUE; } /** * last tests before the real startup (directory writable) */ static ya_result main_final_tests() { if(!main_final_tests_is_directory_writable(g_config->data_path)) { return DIRECTORY_NOT_WRITABLE; } if(!main_final_tests_is_directory_writable(g_config->keys_path)) { return DIRECTORY_NOT_WRITABLE; } if((g_config->server_flags & SERVER_FL_LOG_FILE_DISABLED) == 0) { if(!main_final_tests_is_directory_writable(g_config->log_path)) { return DIRECTORY_NOT_WRITABLE; } } if(!main_final_tests_is_directory_writable(g_config->xfr_path)) { return DIRECTORY_NOT_WRITABLE; } return SUCCESS; } /** \brief Function executed by atexit * * The atexit() function registers the given function to be called at normal * process termination, either via exit(?) or via return from the program * main(). Functions so registered are called in the reverse order of their * registration; no arguments are passed. */ static void main_exit() { if(own_pid) { log_info("shutting down"); } server_service_stop(); server_service_finalize(); #if HAS_DYNUPDATE_SUPPORT dynupdate_query_service_stop(); #endif notify_service_stop(); #if HAS_EVENT_DYNAMIC_MODULE dynamic_module_handler_finalize(); #endif signal_handler_finalize(); notify_service_finalize(); database_service_finalize(); #if DNSCORE_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT dnssec_policy_finalize(); #endif class_ch_set_hostname(NULL); class_ch_set_id_server(NULL); class_ch_set_version(NULL); #if DNSCORE_HAS_NSID_SUPPORT edns0_set_nsid(NULL, 0); #endif logger_flush(); flushout(); flusherr(); if(server_do_clean_exit) { log_info("stopping database"); database_shutdown(g_config->database); if(own_pid) { log_info("releasing pid file lock"); pid_file_destroy(g_config->pid_file); } //config_unregister_main(); logger_flush(); flushout(); flusherr(); #if DNSCORE_HAS_ACL_SUPPORT acl_definitions_free(); #endif dnscore_finalize(); } else { if(own_pid) { log_info("releasing pid file lock"); pid_file_destroy(g_config->pid_file); } logger_flush(); flushout(); flusherr(); } } /** \brief Main function of yadifa * * @param[in] argc number of arguments on the command line * @param[in] argv array of arguments on the command line * * @return EXIT_SUCCESS * @return EXIT_FAILURE * @return exit codes * * */ /** * This will stop YADIFAD if the libraries have been build-configured differently or made differently. * * The most typical trigger is "make debug" vs "make", is, because it has not been followed by, * respectively, a "make debug-install" or a "make install" * * Or, in the case of a static build, a mix code versions that would have required a "make clean" * */ static void main_check_build_settings() { if(dnscore_getfingerprint() != dnscore_getmyfingerprint()) { printf("yadifad: the linked dnscore features are %08x but the lib has been compiled against one with %08x", dnscore_getfingerprint(), dnscore_getmyfingerprint()); fflush(NULL); abort(); // binary incompatiblity : full stop } if(dnsdb_getfingerprint() != dnsdb_getmyfingerprint()) { printf("yadifad: the linked dnsdb features are %08x but the lib has been compiled against one with %08x", dnsdb_getfingerprint(), dnsdb_getmyfingerprint()); fflush(NULL); abort(); // binary incompatiblity : full stop } } /** * The flag must be checked this way as the internal command line/configuration parsing mechanism * would miss the start. * * @param argc * @param argv */ static int main_early_argv_check(int argc, char *argv[]) { int ret = 0; for(int i = 1; i < argc; ++i) { if(strcmp(argv[i], "-L") == 0) { main_config_log_from_start = TRUE; } if(strcmp(argv[i], "-h") == 0) { main_config_help_requested = TRUE; main_config_features = DNSCORE_TINYRUN; ++ret; } else if(strcmp(argv[i], "--help") == 0) { main_config_help_requested = TRUE; main_config_features = DNSCORE_TINYRUN; ++ret; } else if(strcmp(argv[i], "-V") == 0) { main_config_features = DNSCORE_TINYRUN; } else if(strcmp(argv[i], "--version") == 0) { main_config_features = DNSCORE_TINYRUN; } } return ret; } static void main_ignore_signals_while_starting_up() { static const int ignore_these[] = {SIGHUP, SIGUSR1, SIGINT, SIGTERM, SIGPIPE, 0}; for(int i = 0; ignore_these[i] != 0; ++i) { signal(ignore_these[i], SIG_IGN); } } int main(int argc, char *argv[]) { ya_result ret; /** * Initialises the core library: * _ checks basic architecture settings (endianness, types sizes, random generator, ...) * _ initialises dns types and classes name<->id matching * _ initialises text formatting (format*, log*) * _ initialises standard output streams * _ initialises the logger * _ registers core error codes * _ registers TSIG algorithms * _ registers an exit function * _ resets and start the alarm/timer function */ #if DEBUG puts("YADIFA debug build"); #if HAS_RRL_SUPPORT puts("RRL support: yes"); #else puts("RRL support: no"); #endif #endif main_check_build_settings(); if(main_early_argv_check(argc, argv) != 0) { // print the help using printf & flush dnscore_init_ex(DNSCORE_TINYRUN, argc, argv); yadifad_print_usage(argv[0]); return 1; } main_ignore_signals_while_starting_up(); dnscore_init_ex(main_config_features, argc, argv); //main_check_log_from_start(argc, (const char**)argv); async_message_pool_init(); // registers yadifad error codes server_register_errors(); // arms the exit handling function #if HAS_EVENT_DYNAMIC_MODULE dynamic_module_handler_init(); #endif atexit(main_exit); // ? // register all the services: // server, database, ... #if HAS_DYNCONF_SUPPORT //dynconf_service_init(); //dynconf_service_start(); #endif // configures, exit if ordered to (version/help or error) // if((ret = main_config(argc, argv)) != SUCCESS) { return ISOK(ret)?EXIT_SUCCESS:EXIT_CONFIG_ERROR; } // This is always 'exit' on failure pid_t pid; if(FAIL(ret = pid_check_running_program(g_config->pid_file, &pid))) { log_err("%s already running with pid: %lu (%s)", PROGRAM_NAME, pid, g_config->pid_file); return EXIT_FAILURE; // don't use ret } /* * We are really starting up. After this we may want to do a clean exit. */ server_do_clean_exit = TRUE; /* * Setup the necessary environmental changes: core limits, root change, id change, and creation of pid file */ u32 setup_flags = SETUP_CORE_LIMITS | SETUP_ID_CHANGE | SETUP_CREATE_PID_FILE; if(g_config->server_flags & SERVER_FL_CHROOT) { setup_flags |= SETUP_ROOT_CHANGE; } #ifndef WIN32 { if(g_config->set_nofile >= 0) { struct rlimit nofile_limits = {0, 0}; if(g_config->set_nofile == 0) { int tcp = g_config->max_tcp_queries; int addresses = host_address_count(g_config->listen); int workers_by_addresses = g_config->thread_count_by_address; int nofile = tcp * 2 + addresses * workers_by_addresses + 1024; nofile_limits.rlim_cur = nofile; nofile_limits.rlim_max = nofile; } else { nofile_limits.rlim_cur = g_config->set_nofile; nofile_limits.rlim_max = g_config->set_nofile; } ttylog_notice("setting file open limits to %i", nofile_limits.rlim_cur); if(setrlimit(RLIMIT_NOFILE, &nofile_limits) < 0) { ttylog_err("failed to set file open limits to %i : %r", nofile_limits.rlim_cur, ERRNO_ERROR); } } struct rlimit limits; getrlimit(RLIMIT_NOFILE, &limits); if(limits.rlim_cur < 1024) { ttylog_err("file open limits are too small (%i < 1024) to even try to go on.", limits.rlim_cur); return EXIT_FAILURE; } if(limits.rlim_cur < 65536) { ttylog_notice("file open limits could be higher (%i < 65536). The highest the better.", limits.rlim_cur); } } #endif if(FAIL(ret = server_setup_env(&g_config->pid, &g_config->pid_file, g_config->uid, g_config->gid, setup_flags))) { log_err("server setup failed: %r", ret); return EXIT_FAILURE; } own_pid = TRUE; #if ZDB_HAS_DNSSEC_SUPPORT dnssec_keystore_setpath(g_config->keys_path); #endif logger_reopen(); /// last tests before the real startup (directory writable) if(FAIL(main_final_tests())) { return EXIT_FAILURE; } // database service // // needs about nobody log_info("loading zones"); if(FAIL(ret = database_startup(&g_config->database))) { log_err("loading zones: %r", ret); return EXIT_FAILURE; } /* * Starts the services, ending with the server. * Waits for the shutdown signal. */ int exit_code = EXIT_SUCCESS; #if HAS_EVENT_DYNAMIC_MODULE dynamic_module_startup(); #endif while(!dnscore_shuttingdown()) { log_info("starting notify service"); notify_service_start(); #if HAS_DYNUPDATE_SUPPORT log_info("starting dynupdate service"); // dynupdate service // // called by the dns server // uses the database dynupdate_query_service_init(); dynupdate_query_service_start(); #endif /* if(ctrl_has_dedicated_listen()) { // start ctrl server on its address(es) that does not match the DNS server addresses } */ log_info("starting server"); if(ISOK(ret = server_service_start_and_wait())) { exit_code = EXIT_SUCCESS; } else { exit_code = EXIT_FAILURE; } #if HAS_DYNUPDATE_SUPPORT log_info("stopping dynupdate service"); dynupdate_query_service_stop(); dynupdate_query_service_finalise(); log_info("dynupdate service stopped"); #endif log_info("stopping notify service"); notify_service_stop(); if(!dnscore_shuttingdown()) { // server stop // server context stop server_context_stop(); // server context start if(ISOK(ret = server_context_create())) { // server start } else { log_try_err("failed to start server: %r", ret); } } } #if HAS_EVENT_DYNAMIC_MODULE dynamic_module_shutdown(); #endif /// @note DO NOT: logger_finalize() don't, it will be done automatically at exit return exit_code; } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/axfr.c0000644000000000000000000000013114505005533017776 xustar000000000000000029 mtime=1695812443.51699757 30 atime=1695812445.784030039 30 ctime=1695812495.612743686 yadifa-2.6.5-11201/sbin/yadifad/axfr.c0000664000374500037450000003204014505005533017740 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #include "server-config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ZDB_JOURNAL_CODE 1 #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "axfr.h" #include "confs.h" #include "server.h" extern struct thread_pool_s *server_disk_thread_pool; /** * * Handle an AXFR query from a slave. * * If we don't do this many slaves could call with a small interval asking a just-dynupdated snapshot. * If we do it the slaves will be only a few steps behind and the next notification/ixfr will bring them up to date. */ #if DNSCORE_HAS_TCP_MANAGER ya_result axfr_process(message_data *mesg, tcp_manager_socket_context_t *sctx) #else ya_result axfr_process(message_data *mesg, int sockfd) #endif { /* * Start an AXFR "writer" thread * Give it the tcp fd * It will store the AXFR for the current database snapshot on the disk if it does not exist yet (writers blocked) * It will then open the stored file and stream it to the tcp fd (writers freed) * ACL/TSIG is not taken in account yet. */ zdb_zone *zone; const u8 *fqdn = message_get_canonised_fqdn(mesg); u32 fqdn_len = dnsname_len(fqdn); if(fqdn_len > MAX_DOMAIN_LENGTH) { #if DNSCORE_HAS_TCP_MANAGER tcp_manager_context_release(sctx); tcp_manager_close(sctx); #endif return DOMAIN_TOO_LONG; } u16 rcode; if((zone = zdb_acquire_zone_read_from_fqdn(g_config->database, fqdn)) != NULL) { if(zdb_zone_valid(zone)) { #if ZDB_HAS_ACL_SUPPORT access_control *ac = zone->acl; if(!ACL_REJECTED(acl_check_access_filter(mesg, &ac->allow_transfer))) { #endif log_info("axfr: %{dnsname}: scheduling axfr answer to %{sockaddr}", message_get_canonised_fqdn(mesg), message_get_sender(mesg)); /* * This is an asynchronous call * * Get the zone AXFR * If not exist create it and start sending back while writing (implies two threads) * else simply send back */ #if DNSCORE_HAS_TCP_MANAGER zdb_zone_answer_axfr(zone, mesg, sctx, NULL, server_disk_thread_pool, g_config->axfr_max_packet_size, g_config->axfr_max_record_by_packet, g_config->axfr_compress_packets); tcp_manager_context_release(sctx); // sctx has been acquired by the xfr call #else zdb_zone_answer_axfr(zone, mesg, sockfd, NULL, server_disk_thread_pool, g_config->axfr_max_packet_size, g_config->axfr_max_record_by_packet, g_config->axfr_compress_packets); #endif zdb_zone_release(zone); return SUCCESS; #if DNSCORE_HAS_ACL_SUPPORT } else { /* notauth */ if(message_has_tsig(mesg)) { log_notice("axfr: %{dnsname}: not authorised (%{sockaddr} key %{dnsname})", message_get_canonised_fqdn(mesg), message_get_sender(mesg), message_tsig_get_name(mesg)); } else { log_notice("axfr: %{dnsname}: not authorised (%{sockaddr})", message_get_canonised_fqdn(mesg), message_get_sender(mesg)); } rcode = FP_XFR_REFUSED; } #endif } else { rcode = FP_INVALID_ZONE; } zdb_zone_release(zone); } else { /* zone not found */ zone_desc_s *zone_desc; if((zone_desc = zone_acquirebydnsname(message_get_canonised_fqdn(mesg))) != NULL) { zone_release(zone_desc); log_warn("axfr: %{dnsname}: zone not loaded (%{sockaddr})", message_get_canonised_fqdn(mesg), message_get_sender(mesg)); rcode = FP_RCODE_SERVFAIL; } else { log_notice("axfr: %{dnsname}: no such zone (%{sockaddr})", message_get_canonised_fqdn(mesg), message_get_sender(mesg)); rcode = FP_NOZONE_FOUND; } } message_make_error(mesg, rcode); #if DNSCORE_HAS_TCP_MANAGER int sockfd = tcp_manager_socket(sctx); #endif ya_result send_ret; #if DNSCORE_HAS_TCP_MANAGER send_ret = message_send_tcp(mesg, sockfd); #else send_ret = message_update_length_send_tcp_with_default_minimum_throughput(mesg, sockfd); #endif if(ISOK(send_ret)) { #if DNSCORE_HAS_TCP_MANAGER tcp_manager_write_update(sctx, send_ret); #endif } else { log_err("axfr: %{dnsname}: could not send error message: %r (%{sockaddr})", message_get_canonised_fqdn(mesg), send_ret, message_get_sender(mesg)); } yassert((sockfd < 0)||(sockfd >2)); #if DNSCORE_HAS_TCP_MANAGER tcp_manager_context_release(sctx); #else shutdown(sockfd, SHUT_RDWR); close_ex(sockfd); #endif return SUCCESS; } /** * * Send an AXFR query to a master and handle the answer (downloads the zone). */ ya_result axfr_query_ex(const host_address *servers, const u8 *origin, u32* out_loaded_serial, u32* out_loaded_refresh) { /* * AXFR query */ ya_result return_value; char data_path[PATH_MAX]; if(host_address_is_any(servers)) { return INVALID_ARGUMENT_ERROR; } log_info("axfr: %{dnsname}: querying servers", origin); if(FAIL(return_value = zdb_zone_path_get_provider()(origin, data_path, sizeof(data_path), ZDB_ZONE_PATH_PROVIDER_AXFR_PATH|ZDB_ZONE_PATH_PROVIDER_MKDIR))) { log_err("axfr: %{dnsname}: unable to create directory '%s' : %r", origin, data_path, return_value); return return_value; } random_ctx rndctx = thread_pool_get_random_ctx(); /** * Create the AXFR query packet */ message_data_with_buffer axfr_query_buff; message_data_with_buffer_init(&axfr_query_buff); message_data *axfr_query = message_data_with_buffer_init(&axfr_query_buff); message_make_query(axfr_query, (u16)random_next(rndctx), origin, TYPE_AXFR, CLASS_IN); #if DNSCORE_HAS_TSIG_SUPPORT if(servers->tsig != NULL) { log_info("axfr: %{dnsname}: transfer will be signed with key '%{dnsname}'", origin, servers->tsig->name); message_sign_query(axfr_query, servers->tsig); } #endif /* * connect & send */ input_stream is; output_stream os; // connect host_address *transfer_source = zone_transfer_source_copy(origin); host_address *current_transfer_source; current_transfer_source = transfer_source; return_value = zone_transfer_source_tcp_connect(servers, ¤t_transfer_source, &is, &os, g_config->xfr_connect_timeout); if(ISOK(return_value)) { // send if(ISOK(return_value = message_write_tcp(axfr_query, &os))) { output_stream_flush(&os); int fd = fd_input_stream_get_filedescriptor(&is); tcp_set_sendtimeout(fd, 30, 0); tcp_set_recvtimeout(fd, 30, 0); log_info("axfr: %{dnsname}: truncating journal", origin); /* delete ix files */ journal_truncate(origin); zdb_zone *zone = zdb_acquire_zone_write_lock_from_fqdn(g_config->database, origin, ZDB_ZONE_MUTEX_XFR); if(zone != NULL) { if(!zdb_zone_isinvalid(zone)) { #if ZDB_ZONE_HAS_JNL_REFERENCE if(zone->journal != NULL) { journal_close(zone->journal); } #endif bool have_writing_rights = !zdb_zone_get_set_dumping_axfr(zone); if(!have_writing_rights) { // zone is already being dumped log_err("axfr: %{dnsname}: zone already marked as being dumped", origin); } } zdb_zone_release_unlock(zone, ZDB_ZONE_MUTEX_XFR); } xfr_copy_flags xfr_flags = XFR_ALLOW_AXFR | ((g_config->axfr_strict_authority)? 0: XFR_LOOSE_AUTHORITY); input_stream xfris; if(ISOK(return_value = xfr_input_stream_init(&xfris, origin, &is, axfr_query, 0, xfr_flags))) { if(ISOK(return_value = xfr_copy(&xfris, g_config->xfr_path, FALSE))) { return_value = xfr_input_stream_get_type(&xfris); if(out_loaded_serial != NULL) { *out_loaded_serial = xfr_input_stream_get_serial(&xfris); } if(out_loaded_refresh != NULL) { *out_loaded_refresh = xfr_input_stream_get_refresh(&xfris); } } else { log_warn("axfr: %{dnsname}: AXFR stream copy in '%s' failed: %r", origin, data_path, return_value); } input_stream_close(&xfris); } else { log_warn("axfr: %{dnsname}: AXFR stream copy init failed: %r", origin, return_value); } output_stream_close(&os); output_stream_close(&is); zone = zdb_acquire_zone_write_lock_from_fqdn(g_config->database, origin, ZDB_ZONE_MUTEX_XFR); if(zone != NULL) { if(!zdb_zone_isinvalid(zone)) { zdb_zone_clear_dumping_axfr(zone); } zdb_zone_release_unlock(zone, ZDB_ZONE_MUTEX_XFR); } } else { log_warn("axfr: %{dnsname}: AXFR query to %{hostaddr} failed: %r", origin, servers, return_value); } } else { if((transfer_source != NULL) && (current_transfer_source == NULL)) { log_warn("axfr: %{dnsname}: %{hostaddr}: could not find a valid bind point to query a transfer from", origin, servers); } else { log_info("axfr: %{dnsname}: %{hostaddr}: stream connection failed: %r", origin, servers, return_value); } } if(transfer_source != NULL) { host_address_delete_list(transfer_source); } return return_value; } /** * * Send an AXFR query to a master and handle the answer (downloads the zone). */ ya_result axfr_query(const host_address *servers, const u8 *origin, u32* out_loaded_serial) { ya_result ret = axfr_query_ex(servers, origin, out_loaded_serial, NULL); return ret; } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config_main.c0000644000000000000000000000013214505005533021310 xustar000000000000000030 mtime=1695812443.322994792 30 atime=1695812445.781029996 30 ctime=1695812495.614743715 yadifa-2.6.5-11201/sbin/yadifad/config_main.c0000664000374500037450000007244714505005533021270 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup config Configuration handling * @ingroup yadifad * @brief * * @{ */ #define ZDB_JOURNAL_CODE 1 #include "server-config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if ZDB_HAS_DNSSEC_SUPPORT #include #include #endif #include "confs.h" #include "config_error.h" #include #include "server_error.h" #include "process_class_ch.h" #include "server_context.h" #include "server.h" #include "dnsdb/zdb_zone_load.h" #if HAS_EVENT_DYNAMIC_MODULE #include "dynamic-module-handler.h" #endif #if DNSCORE_HAS_TCP_MANAGER #include #endif /* * */ #define CONFS_MAIN_C_ config_data *g_config = NULL; static value_name_table network_model_enum[]= { {0, "single" }, {0, "0" }, {1, "buffered"}, {1, "1"}, {2, "multi" }, {2, "2" }, {0, NULL} }; /*------------------------------------------------------------------------------ * MACROS */ /* Table with the parameters that can be set in the config file * main container */ #define CONFIG_TYPE config_data CONFIG_BEGIN(config_main_desc) CONFIG_FILE( config_file , S_CONFIGDIR S_CONFIGFILE ) #ifndef WIN32 /* Path to chroot, will be used if chroot is on */ CONFIG_CHROOT( chroot_path , S_CHROOTPATH ) // doc #endif /* Path to data which will be used for relative data */ CONFIG_PATH( data_path , S_DATAPATH ) // doc /* Path which will be used for logs */ CONFIG_LOGPATH( log_path , S_LOGPATH ) // doc CONFIG_PATH( xfr_path , S_XFRPATH ) // doc /* Path to keys */ CONFIG_PATH( keys_path , S_KEYSPATH ) // doc /* PID file */ CONFIG_STRING( pid_file , S_PIDFILE ) // doc /* Switch for turning chroot, uid & gid off */ CONFIG_FLAG16( daemon , S_DAEMONRUN , server_flags, SERVER_FL_DAEMON ) // doc CONFIG_FLAG16( chroot , S_CHROOT , server_flags, SERVER_FL_CHROOT ) // doc CONFIG_FLAG16( log_unprocessable , S_LOG_UNPROCESSABLE , server_flags, SERVER_FL_LOG_UNPROCESSABLE ) // doc CONFIG_FLAG16( log_from_start , S_LOG_FROM_START , server_flags, SERVER_FL_LOG_FROM_START ) // for the command line // if set, disables checking the log-path directory for existence and writing rights. CONFIG_FLAG16( log_files_disabled , S_LOG_FILES_DISABLED , server_flags, SERVER_FL_LOG_FILE_DISABLED ) // doc CONFIG_UID( uid , S_UID ) // doc CONFIG_GID( gid , S_GID ) // doc // Above settings probably cannot be changed at run time // Below settings may be changed at runtime /* string used for query of version */ CONFIG_STRING( version_chaos , S_VERSION_CHAOS ) // doc CONFIG_STRING( hostname_chaos , S_HOSTNAME_CHAOS ) // doc CONFIG_STRING( serverid_chaos , S_SERVERID_CHAOS ) // doc #if ZDB_HAS_ACL_SUPPORT CONFIG_ACL_PTR( allow_query , S_ALLOW_QUERY ) // doc CONFIG_ACL_PTR( allow_update , S_ALLOW_UPDATE ) // doc CONFIG_ACL_PTR( allow_transfer , S_ALLOW_TRANSFER ) // doc CONFIG_ACL_PTR( allow_update_forwarding , S_ALLOW_UPDATE_FORWARDING ) // doc CONFIG_ACL_PTR( allow_notify , S_ALLOW_NOTIFY ) // doc CONFIG_ACL_PTR( allow_control , S_ALLOW_CONTROL ) // doc #endif /* Listening to interfaces */ CONFIG_HOST_LIST(listen , S_LISTEN ) // doc CONFIG_HOST_LIST(do_not_listen , S_DO_NOT_LISTEN ) // doc CONFIG_HOST_LIST(known_hosts , S_LISTEN ) CONFIG_HOST_LIST(transfer_source , S_TRANSFER_SOURCE ) /* size of an EDNS0 packet */ CONFIG_U32_RANGE(edns0_max_size , S_EDNS0_MAX_SIZE ,EDNS0_MIN_LENGTH, EDNS0_MAX_LENGTH ) // doc // overrides the cpu detection CONFIG_U32( cpu_count_override , S_CPU_COUNT_OVERRIDE ) // doc // how many threads by address (UDP) CONFIG_S32( thread_count_by_address , S_THREAD_COUNT_BY_ADDRESS ) // doc CONFIG_U32_RANGE(thread_affinity_base , "0", 0, 3 ) // first virtual cpu // doc CONFIG_U32_RANGE(thread_affinity_multiplier , "0", 0, 4 ) // dual thread // doc // how many threads for the dnssec processing #if DATABASE_ZONE_RRSIG_THREAD_POOL CONFIG_U32( dnssec_thread_count , S_DNSSEC_THREAD_COUNT ) /// @note 20180712 edf -- THIS PARAMETER IS OBSOLETE #else CONFIG_OBSOLETE(dnssec_thread_count) /// @note 20180712 edf -- THIS PARAMETER IS OBSOLETE #endif CONFIG_U32_RANGE(zone_load_thread_count , S_ZONE_LOAD_THREAD_COUNT, ZONE_LOAD_THREAD_COUNT_MIN, ZONE_LOAD_THREAD_COUNT_MAX) // doc CONFIG_U32_RANGE(zone_store_thread_count , S_ZONE_SAVE_THREAD_COUNT, ZONE_SAVE_THREAD_COUNT_MIN, ZONE_SAVE_THREAD_COUNT_MAX) // doc CONFIG_U32_RANGE(zone_download_thread_count , S_ZONE_DOWNLOAD_THREAD_COUNT , ZONE_DOWNLOAD_THREAD_COUNT_MIN, ZONE_DOWNLOAD_THREAD_COUNT_MAX) // doc CONFIG_U32_RANGE(zone_unload_thread_count , S_ZONE_UNLOAD_THREAD_COUNT, ZONE_UNLOAD_THREAD_COUNT_MIN, ZONE_UNLOAD_THREAD_COUNT_MAX ) // doc CONFIG_ENUM( network_model ,S_NETWORK_MODEL, network_model_enum) // doc /* Max number of TCP queries */ CONFIG_U32_RANGE(max_tcp_queries , S_MAX_TCP_QUERIES ,TCP_QUERIES_MIN, TCP_QUERIES_MAX) // doc CONFIG_U32_RANGE(max_tcp_queries_per_address , S_MAX_TCP_QUERIES_PER_ADDRESS,TCP_QUERIES_MIN, TCP_QUERIES_MAX) // doc CONFIG_U32_RANGE(max_secondary_tcp_queries , S_MAX_SECONDARY_TCP_QUERIES,TCP_QUERIES_MIN, TCP_QUERIES_MAX) // doc CONFIG_U32( tcp_query_min_rate , S_TCP_QUERY_MIN_RATE ) // doc CONFIG_U32_RANGE(tcp_queue_size , S_TCP_QUEUE_SIZE , S_TCP_QUEUE_SIZE_MIN, S_TCP_QUEUE_SIZE_MAX) /* Ignores messages that would be answered by a FORMERR */ CONFIG_FLAG16( answer_formerr_packets , S_ANSWER_FORMERR_PACKETS , server_flags, SERVER_FL_ANSWER_FORMERR) // doc /* Listen to port (eg 53) */ CONFIG_STRING( server_port , S_SERVERPORT ) // doc /* Switch for cache server or not */ CONFIG_FLAG16( statistics , S_STATISTICS , server_flags, SERVER_FL_STATISTICS) /* Maximum number of seconds between two statistics lines */ // doc CONFIG_U32( statistics_max_period , S_STATISTICS_MAX_PERIOD ) // doc CONFIG_U32( xfr_connect_timeout , S_XFR_CONNECT_TIMEOUT ) // doc CONFIG_U32( queries_log_type , S_QUERIES_LOG_TYPE ) // doc #if DNSCORE_HAS_DNSSEC_SUPPORT #if CONFIG_SIGNATURE_TYPE_CONFIGURABLE CONFIG_U16( sig_signing_type , S_SIG_SIGNING_TYPE ) #endif CONFIG_U32_RANGE(sig_validity_interval , S_SIG_VALIDITY_INTERVAL , SIGNATURE_VALIDITY_INTERVAL_MIN , SIGNATURE_VALIDITY_INTERVAL_MAX ) /* 7 to 366 days = 30 */ // doc CONFIG_U32_RANGE(sig_validity_regeneration , S_SIG_VALIDITY_REGENERATION, SIGNATURE_VALIDITY_REGENERATION_MIN , SIGNATURE_VALIDITY_REGENERATION_MAX) /* 24 hours to 168 hours */ // doc CONFIG_U32_RANGE(sig_validity_jitter , S_SIG_VALIDITY_JITTER , SIGNATURE_VALIDITY_JITTER_MIN , SIGNATURE_VALIDITY_JITTER_MAX ) /* 0 to 86400 = 3600*/ // doc CONFIG_ALIAS(sig_jitter, sig_validity_jitter) // doc #endif CONFIG_U32_RANGE(axfr_max_record_by_packet , S_AXFR_MAX_RECORD_BY_PACKET , AXFR_RECORD_BY_PACKET_MIN , AXFR_RECORD_BY_PACKET_MAX ) // doc CONFIG_U32_RANGE(axfr_max_packet_size , S_AXFR_PACKET_SIZE_MAX , AXFR_PACKET_SIZE_MIN , AXFR_PACKET_SIZE_MAX ) // doc CONFIG_BOOL(axfr_compress_packets , S_AXFR_COMPRESS_PACKETS ) // doc CONFIG_BOOL(axfr_strict_authority , S_AXFR_STRICT_AUTHORITY) // doc CONFIG_U32_RANGE(axfr_retry_delay , S_AXFR_RETRY_DELAY , AXFR_RETRY_DELAY_MIN , AXFR_RETRY_DELAY_MAX ) // doc CONFIG_U32(axfr_retry_jitter , S_AXFR_RETRY_JITTER ) // doc CONFIG_U32_RANGE(axfr_memory_threshold , S_AXFR_MEMORY_THREHOLD, AXFR_MEMORY_THREHOLD_MIN, AXFR_MEMORY_THREHOLD_MAX) CONFIG_U32_RANGE(axfr_retry_failure_delay_multiplier, S_AXFR_RETRY_FAILURE_DELAY_MULTIPLIER, AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MIN, AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX) // doc CONFIG_U32_RANGE(axfr_retry_failure_delay_max, S_AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX, AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX_MIN, AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX_MAX) // doc CONFIG_U32_RANGE(worker_backlog_queue_size , S_SERVER_RW_BACKLOG_QUEUE_SIZE, SERVER_RW_BACKLOG_QUEUE_SIZE_MIN, SERVER_RW_BACKLOG_QUEUE_SIZE_MAX ) // doc CONFIG_S32(set_nofile, "-1") CONFIG_BOOL(check_policies, "0") #if HAS_EVENT_DYNAMIC_MODULE CONFIG_STRING_ARRAY(dynamic_modules, NULL,128) CONFIG_ALIAS(module, dynamic_modules) #endif CONFIG_BOOL(hidden_master, "0") // doc #if DEBUG CONFIG_BOOL(print_config, "0") // debug build only, prints the loaded configuration #endif //CONFIG_U32_RANGE(multimaster_ /* alias, aliased */ CONFIG_ALIAS(port, server_port) // doc CONFIG_ALIAS(version, version_chaos) // doc CONFIG_ALIAS(hostname, hostname_chaos) // doc CONFIG_ALIAS(serverid, serverid_chaos) // doc CONFIG_ALIAS(chrootpath, chroot_path) // doc CONFIG_ALIAS(configfile, config_file) // cmdline CONFIG_ALIAS(keyspath, keys_path) // doc CONFIG_ALIAS(datapath, data_path) // doc CONFIG_ALIAS(xfrpath, xfr_path) // doc CONFIG_ALIAS(logpath, log_path) // doc CONFIG_ALIAS(pidpath, pid_path) CONFIG_ALIAS(pidfile, pid_file) // doc CONFIG_ALIAS(daemonize, daemon) // doc //CONFIG_ALIAS(zone_save_thread_count, zone_store_thread_count) CONFIG_ALIAS(axfr_maxrecordbypacket, axfr_max_record_by_packet) // doc CONFIG_ALIAS(axfr_maxpacketsize, axfr_max_packet_size) // doc CONFIG_ALIAS(axfr_compresspackets, axfr_compress_packets) // doc #if DNSCORE_HAS_DNSSEC_SUPPORT CONFIG_ALIAS(signature_validity_interval, sig_validity_interval) CONFIG_ALIAS(signature_regeneration, sig_validity_regeneration) CONFIG_ALIAS(signature_jitter, sig_validity_jitter) #endif CONFIG_ALIAS(xfr_maxrecordbypacket, axfr_max_record_by_packet) // doc CONFIG_ALIAS(xfr_maxpacketsize, axfr_max_packet_size) // doc CONFIG_ALIAS(xfr_compresspackets, axfr_compress_packets) // doc CONFIG_ALIAS(xfr_retry_delay, axfr_retry_delay) // doc CONFIG_ALIAS(xfr_retry_jitter, axfr_retry_jitter) // doc CONFIG_ALIAS(xfr_retry_failure_delay_multiplier, axfr_retry_failure_delay_multiplier) // doc CONFIG_ALIAS(xfr_retry_failure_delay_max, axfr_retry_failure_delay_max) // doc CONFIG_ALIAS(user, uid) // doc CONFIG_ALIAS(group, gid) // doc CONFIG_ALIAS(max_tcp_connections, max_tcp_queries) // doc CONFIG_ALIAS(network_model_worker_backlog_size, worker_backlog_queue_size) CONFIG_END(config_main_desc) #undef CONFIG_TYPE /** * Note : *dirp has been mallocated */ static ya_result config_main_verify_and_update_directory(const char *base_path, char **dirp) { char fullpath[PATH_MAX]; if(dirp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } char *dir = *dirp; if(dir == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } ya_result fullpath_len = snprintf(fullpath, sizeof(fullpath),"/%s/%s", base_path, dir); if(FAIL(fullpath_len)) { return fullpath_len; } bool dirsep = TRUE; int j = 1; for(int i = 1; i <= fullpath_len; i++) { char c = fullpath[i]; if(c == '/') { if(!dirsep) { fullpath[j++] = c; } dirsep = TRUE; } else { fullpath[j++] = fullpath[i]; dirsep = FALSE; } } struct stat ds; if(stat(fullpath, &ds) < 0) { int err = errno; ttylog_err("error: '%s': %s", fullpath, strerror(err)); return MAKE_ERRNO_ERROR(err); } if((ds.st_mode & S_IFMT) != S_IFDIR) { ttylog_err("error: '%s' is not a directory", dir); return INVALID_PATH; } ya_result ret; if(FAIL(ret = access_check(fullpath, ACCESS_CHECK_READWRITE))) { ttylog_err("error: '%s' is not writable as (%d:%d): %r", fullpath, getuid(), getgid(), ret); return ret; } free(dir); #ifndef WIN32 *dirp = strdup(fullpath); chroot_manage_path(dirp, fullpath, FALSE); #endif return SUCCESS; } static ya_result config_main_verify_and_update_file(const char *base_path, char **dirp) { if(dirp == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } char *p = *dirp; if(p == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } char *e = p + strlen(p) - 1; while((*e != '/') && (e > p)) { e--; } if((*e == '/') || (e == p)) { char filename[PATH_MAX]; if(*e == '/') { *e = '\0'; e++; strcpy_ex(filename, e, sizeof(filename)); *e = '\0'; } else { strcpy_ex(filename, e, sizeof(filename)); *e = '\0'; } ya_result ret; if(ISOK(ret = config_main_verify_and_update_directory(base_path, dirp))) { size_t pathlen = strlen(*dirp); memmove(&filename[pathlen + 1], filename, strlen(filename) + 1); memcpy(filename, *dirp, pathlen); filename[pathlen] = '/'; #ifndef WIN32 chroot_unmanage_path(dirp); #endif free(*dirp); *dirp = NULL; #ifndef WIN32 *dirp = strdup(filename); chroot_manage_path(dirp, filename, FALSE); #endif return SUCCESS; } else { return ret; } } return SUCCESS; } #if DNSCORE_HAS_TCP_MANAGER static ya_result config_main_section_postprocess_tcp_manager_register_callback(const char* itf_name, const socketaddress* sa, void* data) { (void)itf_name; (void)data; socklen_t sa_len; if(sa->sa.sa_family == AF_INET) { sa_len = sizeof(sa->sa4); tcp_manager_host_register(sa, sa_len, g_config->max_secondary_tcp_queries); } else if(sa->sa.sa_family == AF_INET6) { sa_len = sizeof(sa->sa6); tcp_manager_host_register(sa, sa_len, g_config->max_secondary_tcp_queries); } return SUCCESS; } #else static ya_result config_main_section_postprocess_clients_register_callback(const char* itf_name, const socketaddress* sa, void* data) { (void)itf_name; (void)data; if((sa->sa.sa_family == AF_INET) || (sa->sa.sa_family == AF_INET6)) { server_tcp_client_register(&sa->ss, g_config->max_secondary_tcp_queries); } return SUCCESS; } #endif static ya_result config_main_section_postprocess(struct config_section_descriptor_s *csd) { (void)csd; const dnscore_meminfo_t *mi = dnscore_meminfo_get(NULL); u32 port = 0; u32 cpu_per_core = (sys_has_hyperthreading())?2:1; int ret; #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200112L char tmp[PATH_MAX]; #endif #if DNSCORE_HAS_TCP_MANAGER /** * Sets the allowed connections total for all unregistered connections. */ tcp_manager_connection_max(g_config->max_tcp_queries); for(host_address *ha = g_config->known_hosts; ha != NULL; ha = ha->next) { if((ha->version == HOST_ADDRESS_IPV4) || (ha->version == HOST_ADDRESS_IPV6)) { network_interfaces_forall(config_main_section_postprocess_tcp_manager_register_callback, NULL); } } #else for(host_address *ha = g_config->known_hosts; ha != NULL; ha = ha->next) { if((ha->version == HOST_ADDRESS_IPV4) || (ha->version == HOST_ADDRESS_IPV6)) { network_interfaces_forall(config_main_section_postprocess_clients_register_callback, NULL); } } #endif g_server_context.worker_backlog_queue_size = g_config->worker_backlog_queue_size; if(FAIL(parse_u32_check_range(g_config->server_port, &port, 1, MAX_U16, BASE_10))) { port = DNS_DEFAULT_PORT; ttylog_err("config: main: wrong dns port set in main '%s', defaulted to %d", g_config->server_port, port); } g_config->server_port_value = port; if(g_config->hostname_chaos == NULL) { #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200112L if(gethostname(tmp, sizeof(tmp)) == 0) { g_config->hostname_chaos = strdup(tmp); } else { osformatln(termerr,"config: main: unable to get hostname: %r", ERRNO_ERROR); g_config->hostname_chaos = strdup("not disclosed"); } #else g_config->hostname_chaos = strdup("not disclosed"); #endif } if(g_config->thread_affinity_multiplier == 0) { g_config->thread_affinity_multiplier = cpu_per_core; } class_ch_set_hostname(g_config->hostname_chaos); class_ch_set_id_server(g_config->serverid_chaos); class_ch_set_version(g_config->version_chaos); host_address_set_default_port_value(g_config->listen, ntohs(port)); host_address_set_default_port_value(g_config->do_not_listen, ntohs(port)); host_address_set_port_value(g_config->transfer_source, 0); if(g_config->max_tcp_queries_per_address > g_config->max_tcp_queries) { ttylog_warn("config: main: max_tcp_queries_per_address higher than max_tcp_queries (%i)", g_config->max_tcp_queries); g_config->max_tcp_queries_per_address = g_config->max_tcp_queries; } if(g_config->max_secondary_tcp_queries > g_config->max_tcp_queries) { ttylog_warn("config: main: max_secondary_tcp_queries higher than max_tcp_queries (%i)", g_config->max_tcp_queries); g_config->max_secondary_tcp_queries = g_config->max_tcp_queries; } #ifndef WIN32 if(g_config->server_flags & SERVER_FL_CHROOT) { uid_t euid = geteuid(); if(euid != 0) { ttylog_err("config: main: chroot has been enabled but euid is not root (%i != 0)", (int)euid); return INVALID_STATE_ERROR; } } else // disables the base-path/chroot-path feature { if(strcmp(g_config->chroot_path, "/") != 0) { free(g_config->chroot_path); g_config->chroot_path = strdup("/"); chroot_set_path(g_config->chroot_path); } } #endif message_edns0_setmaxsize(g_config->edns0_max_size); g_config->total_interfaces = host_address_count(g_config->listen); if(g_config->total_interfaces > MAX_INTERFACES) { ttylog_err("error: more than %d listening addresses defined.", MAX_INTERFACES); return CONFIG_TOO_MANY_HOSTS; } #ifndef SO_REUSEPORT if(g_config->network_model == 1) { #if 0 /* fix */ #else ttylog_err("warning: network-model 1 requires SO_REUSEPORT which is not available on this system. Reducing worker units to 1"); g_config->thread_count_by_address = 1; #endif } #endif g_config->axfr_retry_jitter = BOUND(AXFR_RETRY_JITTER_MIN, g_config->axfr_retry_jitter, g_config->axfr_retry_delay); #if DATABASE_ZONE_RRSIG_THREAD_POOL g_config->dnssec_thread_count = BOUND(1, g_config->dnssec_thread_count, sys_get_cpu_count()); #endif if(g_config->cpu_count_override > 0) { sys_set_cpu_count(g_config->cpu_count_override); } if(g_config->thread_count_by_address == 0) { ttylog_err("config: single thread engine has been removed, thread-count-by-address set to 1"); g_config->thread_count_by_address = 1; } if(g_config->thread_count_by_address < 0) { g_config->thread_count_by_address = MAX(sys_get_cpu_count() / cpu_per_core, 1); } else if((g_config->thread_count_by_address > (s32)sys_get_cpu_count())) { g_config->thread_count_by_address = MAX(sys_get_cpu_count() / cpu_per_core, 1); ttylog_warn("config: bounding down thread-count-by-address to the number of physical CPUs (%d)", g_config->thread_count_by_address); } if(mi->program_memory_limit > 0) { const s64 estimated_usage_for_one_thread = (SERVER_POOL_BUFFER_SIZE + sizeof(message_data_with_buffer) + 0x8000 + 0x20000); const double estimated_threshold = 0.50; const s64 tcp_queries_soft_limit = 1024; s64 estimated_current_memory_usage = 0; s64 estimated_thread_count = g_config->max_tcp_queries + g_config->thread_count_by_address; s64 estimated_memory_usage = estimated_thread_count * estimated_usage_for_one_thread + estimated_current_memory_usage; double estimated_memory_usage_ratio = estimated_memory_usage; estimated_memory_usage_ratio /= mi->program_memory_limit; if(estimated_memory_usage_ratio > estimated_threshold) { ttylog_warn("config: estimated memory usage by both UDP and TCP threads seems high compared to the memory available."); ttylog_warn("config: the program may be killed by OOM without notice."); ttylog_warn("config: this doesn't take into account the memory used to load the zones."); s32 cpu_count = sys_get_cpu_count(); s64 suggested_thread_count_by_address = cpu_count; if(g_config->thread_count_by_address > cpu_count) { ttylog_warn("config: maybe reduce the thread-count-by-address from %i to %i", g_config->thread_count_by_address, suggested_thread_count_by_address); } double reverse = estimated_threshold * mi->program_memory_limit; reverse /= estimated_usage_for_one_thread; s64 suggested_max_tcp_queries = MAX(((s64)reverse) - suggested_thread_count_by_address, 1); ttylog_warn("config: reducing the max-tcp-queries from %i to %lli will disable this warning", g_config->max_tcp_queries, suggested_max_tcp_queries); if(suggested_max_tcp_queries > tcp_queries_soft_limit) { ttylog_warn("config: in practice, a max-tcp-queries value of %lli is plenty", tcp_queries_soft_limit); } } } g_config->tcp_query_min_rate_us = 0.000001 * g_config->tcp_query_min_rate; message_set_minimum_troughput_default(g_config->tcp_query_min_rate_us); #if DNSCORE_HAS_DNSSEC_SUPPORT #if DATABASE_ZONE_RRSIG_THREAD_POOL g_config->dnssec_thread_count = BOUND(1, g_config->dnssec_thread_count, sys_get_cpu_count()); #endif #if CONFIG_SIGNATURE_TYPE_CONFIGURABLE if(!IS_TYPE_PRIVATE(g_config->sig_signing_type)) { ttylog_err("error: signing type is not in the accepted range: %hx", g_config->sig_signing_type); return CONFIG_WRONG_SIG_TYPE; } #endif if(g_config->sig_validity_interval > SIGNATURE_VALIDITY_INTERVAL_MAX) { ttylog_err("error: signature validity interval too high"); return CONFIG_WRONG_SIG_VALIDITY; } if(g_config->sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S * 2 > g_config->sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S) { ttylog_err("error: default signature regeneration is more than half the interval (%ds * 2 > %ds)", g_config->sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S, g_config->sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S); return CONFIG_WRONG_SIG_REGEN; } #endif /// @note config_main_verify_and_update_directory updates the folder with the base_path /** * * @note All base paths are updated with the chroot variable so it does not * need to be added all the time. * */ #ifndef WIN32 const char *base_path = g_config->chroot_path; #else const char* base_path = "C:\\"; #endif if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->data_path))) { return ret; } if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->keys_path))) { return ret; } if((g_config->server_flags & SERVER_FL_LOG_FILE_DISABLED) == 0) { if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->log_path))) { return ret; } } if(FAIL(ret = config_main_verify_and_update_file(base_path, &g_config->pid_file))) { return ret; } g_config->reloadable = TRUE; #ifndef WIN32 if((g_config->server_flags & SERVER_FL_CHROOT) != 0) { if(FAIL(chroot_manage_path(&g_config->config_file, g_config->config_file, FALSE))) { log_warn("config file '%s' will not be accessible within the chroot jail '%s' : config reload will not work", g_config->config_file, base_path); g_config->reloadable = FALSE; } } #endif if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->xfr_path))) { return ret; } #if ZDB_HAS_DNSSEC_SUPPORT dnssec_keystore_setpath(g_config->keys_path); journal_set_xfr_path(g_config->xfr_path); #endif #if HAS_EVENT_DYNAMIC_MODULE if(ptr_vector_last_index(&g_config->dynamic_modules) >= 0) { log_debug("config file: loading modules"); for(int i = 0; i <= ptr_vector_last_index(&g_config->dynamic_modules); ++i) { const char *cmd = ptr_vector_get(&g_config->dynamic_modules, i); if(ISOK(ret = dynamic_module_handler_load_from_command(cmd))) { log_info("config file: loaded %s", cmd); } else { log_err("config file: failed to load %s", cmd); return ret; } } } #endif if((logger_get_uid() != g_config->uid) || (logger_get_gid() != g_config->gid)) { logger_set_uid(g_config->uid); logger_set_gid(g_config->gid); logger_reopen(); } return SUCCESS; } ya_result config_register_main(s32 priority) { MALLOC_OBJECT_OR_DIE(g_config, config_data, YGCONFIG_TAG); ZEROMEMORY(g_config, sizeof(config_data)); g_config->gid = getgid(); g_config->uid = getuid(); #if HAS_EVENT_DYNAMIC_MODULE ptr_vector_init(&g_config->dynamic_modules); #endif const char *section_name = "main"; ya_result return_code = config_register_struct(section_name, config_main_desc, g_config, priority); if(ISOK(return_code)) { // hook a new finaliser before the standard one config_section_descriptor_s *section_desc = config_section_get_descriptor(section_name); config_section_descriptor_vtbl_s *vtbl = (config_section_descriptor_vtbl_s*)section_desc->vtbl; vtbl->postprocess = config_main_section_postprocess; } return return_code; } void config_unregister_main() { //chroot_unmanage_all(); config_data *g_config = config_unregister_struct("main", config_main_desc); free(g_config); } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config_zone.c0000644000000000000000000000013214505005533021337 xustar000000000000000030 mtime=1695812443.517997585 30 atime=1695812445.784030039 30 ctime=1695812495.616743743 yadifa-2.6.5-11201/sbin/yadifad/config_zone.c0000664000374500037450000003506514505005533021312 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup config Configuration handling * @ingroup yadifad * @brief * * @{ */ #include "server-config.h" #include #include #include #include #include "config_error.h" #include #include "confs.h" #include "zone.h" #include "database-service.h" #include "zone-signature-policy.h" /* * */ extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #define DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS 0 #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS #pragma message("WARNING: DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS enabled !") #endif extern zone_data_set database_zone_desc; /******************** Zones *************************/ static value_name_table zone_type_enum_table[]= { #if ZDB_HAS_MASTER_SUPPORT {ZT_MASTER, ZT_STRING_MASTER}, {ZT_MASTER, ZT_STRING_PRIMARY}, #endif {ZT_SLAVE, ZT_STRING_SLAVE}, {ZT_SLAVE, ZT_STRING_SECONDARY}, {0, NULL} }; #if ZDB_HAS_DNSSEC_SUPPORT static value_name_table dnssec_enum[]= { {ZONE_DNSSEC_FL_NOSEC , "none" }, {ZONE_DNSSEC_FL_NOSEC , "no" }, {ZONE_DNSSEC_FL_NOSEC , "off" }, {ZONE_DNSSEC_FL_NOSEC , "0" }, {ZONE_DNSSEC_FL_NSEC , "nsec" }, {ZONE_DNSSEC_FL_NSEC3 , "nsec3" }, {ZONE_DNSSEC_FL_NSEC3_OPTOUT, "nsec3-optout"}, {0, NULL} }; #endif /* Table with the parameters that can be set in the config file * zone containers */ #define CONFIG_TYPE zone_desc_s CONFIG_BEGIN(config_section_zone_desc) CONFIG_STRING(domain, NULL) CONFIG_STRING(file_name, NULL) CONFIG_PATH(keys_path, NULL) CONFIG_HOST_LIST(masters, NULL) CONFIG_HOST_LIST(notifies, NULL) CONFIG_HOST_LIST(transfer_source, NULL) CONFIG_ENUM(type, NULL, zone_type_enum_table) #if ZDB_HAS_ACL_SUPPORT CONFIG_ACL(allow_query, NULL) CONFIG_ACL(allow_update, NULL) CONFIG_ACL(allow_transfer, NULL) CONFIG_ACL(allow_update_forwarding, NULL) CONFIG_ACL(allow_notify, NULL) CONFIG_ACL(allow_control, NULL) #endif // master CONFIG_FLAG32(notify_auto , S_ZONE_NOTIFY_AUTO, flags, ZONE_FLAG_NOTIFY_AUTO) CONFIG_FLAG32(drop_before_load, S_ZONE_FLAG_DROP_BEFORE_LOAD, flags, ZONE_FLAG_DROP_BEFORE_LOAD) CONFIG_FLAG32(no_master_updates , S_ZONE_NO_MASTER_UPDATES, flags, ZONE_FLAG_NO_MASTER_UPDATES) #if ZDB_HAS_MASTER_SUPPORT CONFIG_FLAG32(true_multimaster, S_ZONE_FLAG_TRUE_MULTIMASTER, flags, ZONE_FLAG_TRUE_MULTIMASTER) CONFIG_FLAG32(maintain_dnssec, S_ZONE_FLAG_MAINTAIN_DNSSEC, flags, ZONE_FLAG_MAINTAIN_DNSSEC) //CONFIG_FLAG32(maintain_zone_before_mount, "1", flags, ZONE_FLAG_MAINTAIN_ZONE_BEFORE_MOUNT) // used nowhere #endif CONFIG_FLAG32(load_local_first, "0", flags, ZONE_FLAG_PRIORITISE_LOCAL_SOURCE) CONFIG_U32_RANGE(notify.retry_count, S_NOTIFY_RETRY_COUNT, NOTIFY_RETRY_COUNT_MIN, NOTIFY_RETRY_COUNT_MAX) CONFIG_U32_RANGE(notify.retry_period, S_NOTIFY_RETRY_PERIOD, NOTIFY_RETRY_PERIOD_MIN, NOTIFY_RETRY_PERIOD_MAX) CONFIG_U32_RANGE(notify.retry_period_increase, S_NOTIFY_RETRY_PERIOD_INCREASE, NOTIFY_RETRY_PERIOD_INCREASE_MIN, NOTIFY_RETRY_PERIOD_INCREASE_MAX) CONFIG_U8(multimaster_retries, S_MULTIMASTER_RETRIES) #if DNSCORE_HAS_DNSSEC_SUPPORT #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT #if ZDB_HAS_MASTER_SUPPORT CONFIG_DNSSEC_POLICY(dnssec_policy) #endif CONFIG_U32_RANGE(signature.sig_validity_interval, S_S32_VALUE_NOT_SET, SIGNATURE_VALIDITY_INTERVAL_MIN, SIGNATURE_VALIDITY_INTERVAL_MAX) CONFIG_U32_RANGE(signature.sig_validity_regeneration, S_S32_VALUE_NOT_SET, SIGNATURE_VALIDITY_REGENERATION_MIN, SIGNATURE_VALIDITY_REGENERATION_MAX) CONFIG_U32_RANGE(signature.sig_validity_jitter, S_S32_VALUE_NOT_SET, SIGNATURE_VALIDITY_JITTER_MIN, SIGNATURE_VALIDITY_JITTER_MAX) #if ZDB_HAS_MASTER_SUPPORT CONFIG_FLAG32(rrsig_nsupdate_allowed, S_ZONE_FLAG_RRSIG_NSUPDATE_ALLOWED, flags, ZONE_FLAG_RRSIG_NSUPDATE_ALLOWED) #endif CONFIG_ALIAS(signature_validity_interval, signature.sig_validity_interval) CONFIG_ALIAS(signature_regeneration, signature.sig_validity_regeneration) CONFIG_ALIAS(signature_jitter, signature.sig_validity_jitter) #endif CONFIG_ENUM(dnssec_mode, S_ZONE_DNSSEC_DNSSEC, dnssec_enum) #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT CONFIG_ALIAS(signature.sig_jitter, sig_validity_jitter) #endif CONFIG_ALIAS(dnssec,dnssec_mode) CONFIG_ALIAS(rrsig_push_allowed, rrsig_nsupdate_allowed) #endif CONFIG_U32_RANGE(journal_size_kb, S_JOURNAL_SIZE_KB_DEFAULT, S_JOURNAL_SIZE_KB_MIN, S_JOURNAL_SIZE_KB_MAX) #if DNSCORE_HAS_CTRL && DNSCORE_HAS_DYNAMIC_PROVISIONING //CONFIG_U8(ctrl_flags, "0") // SHOULD ONLY BE IN THE DYNAMIC CONTEXT CONFIG_BYTES(dynamic_provisioning, "AAA=", sizeof(dynamic_provisioning_s)) CONFIG_HOST_LIST(slaves, NULL) #endif // HAS_CTRL /* CONFIG ALIAS: alias , aliased-real-name */ CONFIG_ALIAS(also_notify,notifies) CONFIG_ALIAS(file,file_name) CONFIG_ALIAS(keyspath, keys_path) CONFIG_ALIAS(journal_size,journal_size_kb) CONFIG_ALIAS(master,masters) CONFIG_ALIAS(notify,notifies) CONFIG_ALIAS(auto_notify,notify_auto) CONFIG_ALIAS(primary,masters) CONFIG_ALIAS(primaries,masters) CONFIG_ALIAS(true_multiprimary, true_multimaster) CONFIG_ALIAS(multiprimary_retries, multimaster_retires) CONFIG_ALIAS(no_primary_updates, no_master_updates) CONFIG_END(config_section_zone_desc) #undef CONFIG_TYPE #include #include #include #if DNSCORE_HAS_TCP_MANAGER #include #endif #include "zone_desc.h" static ya_result config_section_zone_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } static ya_result config_section_zone_start(struct config_section_descriptor_s *csd) { if(csd->base != NULL) { return INVALID_STATE_ERROR; } zone_desc_s *zone_desc = zone_alloc(); csd->base = zone_desc; #if CONFIG_SETTINGS_DEBUG formatln("config: section: zone: start"); #endif return SUCCESS; } static ya_result config_section_zone_filter_accept(zone_desc_s *unused, void *unused_params) { (void)unused; (void)unused_params; return 1; // ACCEPT } static config_section_zone_filter_callback *config_section_zone_filter = config_section_zone_filter_accept; static void *config_section_zone_filter_params = NULL; void config_section_zone_set_filter(config_section_zone_filter_callback *cb, void *p) { if(cb == NULL) { config_section_zone_filter = config_section_zone_filter_accept; config_section_zone_filter_params = NULL; } else { config_section_zone_filter = cb; config_section_zone_filter_params = p; } } static ya_result config_section_zone_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: zone: stop"); #endif // NOP zone_desc_s *zone_desc = (zone_desc_s*)csd->base; ya_result return_code; // ensure the descriptor is valid if(ISOK(return_code = zone_complete_settings(zone_desc))) { zone_setdefaults(zone_desc); if(logger_is_running()) { log_debug("config: %{dnsname}: zone section parsed", zone_origin(zone_desc)); } #if ZDB_HAS_MASTER_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT if(zone_rrsig_nsupdate_allowed(zone_desc) && (zone_desc->dnssec_policy != NULL)) { if(logger_is_running()) { log_err("config: %{dnsname}: policies and allowing RRSIG over dynamic updates are mutually exclusive.", zone_origin(zone_desc)); } else { formatln("config: %{dnsname}: policies and allowing RRSIG over dynamic updates are mutually exclusive.", zone_origin(zone_desc)); } return_code = INVALID_STATE_ERROR; } #endif for(host_address *ha = zone_desc->notifies; ha != NULL; ha = ha->next) { socketaddress sa; #if DNSCORE_HAS_TCP_MANAGER socklen_t sa_len = host_address2sockaddr(ha, &sa); tcp_manager_host_register(&sa, sa_len, g_config->max_secondary_tcp_queries); #else server_tcp_client_register(&sa.ss, g_config->max_secondary_tcp_queries); #endif } if((zone_desc->transfer_source == NULL) && (g_config->transfer_source != NULL)) { zone_desc->transfer_source = host_address_copy_list(g_config->transfer_source); } // load the descriptor (most likely offline) #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS zone_desc->signature.sig_validity_interval = 1; zone_desc->signature.sig_validity_jitter = 5; zone_desc->signature.sig_validity_regeneration = 1; #endif if(config_section_zone_filter(zone_desc, config_section_zone_filter_params) == 1) { if(logger_is_running()) { log_debug("config: %{dnsname}: sending zone to service", zone_origin(zone_desc)); } database_zone_desc_load(zone_desc); } else { zone_desc_s *current_zone_desc = zone_acquirebydnsname(zone_origin(zone_desc)); if(current_zone_desc != NULL) { if(logger_is_running()) { log_debug("config: %{dnsname}: clearing original zone drop status", zone_origin(zone_desc)); } zone_lock(current_zone_desc, ZONE_LOCK_REPLACE_DESC); zone_clear_status(current_zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD); zone_unlock(current_zone_desc, ZONE_LOCK_REPLACE_DESC); zone_release(current_zone_desc); } zone_release(zone_desc); } } else { zone_release(zone_desc); } csd->base = NULL; return return_code; } static ya_result config_section_zone_postprocess(struct config_section_descriptor_s *csd) { (void)csd; return SUCCESS; } static ya_result config_section_zone_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { zone_desc_s *zone_desc = (zone_desc_s*)csd->base; zone_release(zone_desc); #if DEBUG csd->base = NULL; #endif } free(csd); } return SUCCESS; } static ya_result config_section_zone_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_zone_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { if(key != NULL) { return INVALID_ARGUMENT_ERROR; } // for all zones, print table of the zone ptr_set_iterator *iterp; if(*context == NULL) { zone_set_lock(&database_zone_desc); // unlock checked MALLOC_OBJECT_OR_DIE(iterp, ptr_set_iterator, GENERIC_TAG); ptr_set_iterator_init(&database_zone_desc.set, iterp); *context = iterp; } else { iterp = (ptr_set_iterator*)*context; } if(ptr_set_iterator_hasnext(iterp)) { ptr_node *zone_node = ptr_set_iterator_next_node(iterp); zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value; config_section_struct_print(csd, zone_desc, os); } else { zone_set_unlock(&database_zone_desc); free(iterp); *context = NULL; } return SUCCESS; } static const config_section_descriptor_vtbl_s config_section_zone_descriptor_vtbl = { "zone", config_section_zone_desc, // no table config_section_zone_set_wild, config_section_zone_print_wild, config_section_zone_init, config_section_zone_start, config_section_zone_stop, config_section_zone_postprocess, config_section_zone_finalize }; ya_result config_register_zone(const char *null_or_key_name, s32 priority) { //null_or_key_name = "zone"; (void)null_or_key_name; config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_zone_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // scan-build false positive: either it is freed, either it is stored in a global collection } void config_zone_print(zone_desc_s *zone_desc, output_stream *os) { config_section_descriptor_s desc = {zone_desc, &config_section_zone_descriptor_vtbl}; config_section_struct_print(&desc, zone_desc, os); } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/confs.c0000644000000000000000000000013214505005533020147 xustar000000000000000030 mtime=1695812443.321994778 30 atime=1695812445.781029996 30 ctime=1695812495.618743772 yadifa-2.6.5-11201/sbin/yadifad/confs.c0000664000374500037450000005410414505005533020115 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup config Configuration handling * @ingroup yadifad * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include #include #ifndef WIN32 #include #include #endif #if DNSCORE_HAS_DNSSEC_SUPPORT #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #if DNSCORE_HAS_DNSSEC_SUPPORT #include #endif #define ZDB_JOURNAL_CODE 1 #include #include "buildinfo.h" extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "zone.h" #include "server.h" #include "confs.h" #include "database-service.h" #include "server_error.h" #include "config_error.h" #include #define CONFSDSP_TAG 0x50534453464e4f43 #define CONFSPL_TAG 0x4c5053464e4f43 /* * 2011/10/18 : EDF: disabling the debug because it makes the legitimate error output unreadable. */ #undef DEBUGLNF #undef DEBUGF #undef OSDEBUG #undef LDEBUG #undef OSLDEBUG #define DEBUGLNF(...) #define DEBUGF(...) #define OSDEBUG(...) #define LDEBUG(...) #define OSLDEBUG(...) #ifndef NAME_MAX #define NAME_MAX 1024 #endif struct logger_name_handle_s { const char *name; logger_handle **handlep; }; extern logger_handle* g_system_logger; extern logger_handle* g_database_logger; extern logger_handle* g_dnssec_logger; extern logger_handle* g_zone_logger; extern logger_handle* g_server_logger; extern logger_handle* g_statistics_logger; extern logger_handle* g_queries_logger; extern logger_handle* g_acl_logger; #if HAS_EVENT_DYNAMIC_MODULE extern logger_handle* g_module_logger; #endif static const struct logger_name_handle_s logger_name_handles[] = { {"system", &g_system_logger}, {"database", &g_database_logger}, #if DNSCORE_HAS_DNSSEC_SUPPORT {"dnssec", &g_dnssec_logger}, #endif {"zone", &g_zone_logger}, {"server", &g_server_logger}, {"stats", &g_statistics_logger}, {"queries", &g_queries_logger}, {"acl", &g_acl_logger}, #if HAS_EVENT_DYNAMIC_MODULE {"module", &g_module_logger}, #endif {NULL, NULL} }; CMDLINE_BEGIN(yadifad_cmdline) CMDLINE_SECTION("main") CMDLINE_OPT("config",'c',"config_file") CMDLINE_HELP("", "sets the configuration file to use (default: " S_CONFIGDIR S_CONFIGFILE ")") #if DEBUG CMDLINE_BOOL("print-config", 0, "print_config") #endif CMDLINE_BOOL("daemon", 'd', "daemon") CMDLINE_HELP("", "overrides the daemon setting, enables it") CMDLINE_BOOL_NOT("nodaemon", 0, "daemon") CMDLINE_HELP("", "overrides the daemon setting, disables it") CMDLINE_BOOL("log", 'L', "log_from_start") CMDLINE_HELP("", "immediately starts logging on stdout") CMDLINE_OPT("uid", 'u', "uid") CMDLINE_HELP("", "overrides the uid setting") CMDLINE_OPT("gid", 'g', "gid") CMDLINE_HELP("", "overrides the gid setting") CMDLINE_OPT("port", 'P', "server_port") CMDLINE_HELP("", "overrides the server-port setting") CMDLINE_BOOL("check-policies", 0, "check_policies") CMDLINE_HELP("", "checks the policies times are valid for the next few years") CMDLINE_BLANK() CMDLINE_VERSION_HELP(yadifad_cmdline) CMDLINE_BLANK() CMDLINE_END(yadifad_cmdline) static const char *default_channel = "stdout default"; void config_logger_setdefault() { logger_start(); output_stream stdout_os; logger_channel *stdout_channel; fd_output_stream_attach(&stdout_os, dup_ex(1)); stdout_channel = logger_channel_alloc(); logger_channel_stream_open(&stdout_os, FALSE, stdout_channel); logger_channel_register(default_channel, stdout_channel); for(const struct logger_name_handle_s *name_handle = logger_name_handles; name_handle->name != NULL; name_handle++) { logger_handle_create(name_handle->name, name_handle->handlep); #if !DEBUG logger_handle_add_channel(name_handle->name, MSG_PROD_MASK, default_channel); #else logger_handle_add_channel(name_handle->name, MSG_ALL_MASK, default_channel); #endif } #if DEBUG log_debug("logging to stdout"); #endif } void config_logger_cleardefault() { for(const struct logger_name_handle_s *name_handle = logger_name_handles; name_handle->name != NULL; name_handle++) { logger_handle_remove_channel(name_handle->name, default_channel); } logger_channel_unregister(default_channel); } void yadifad_print_usage(const char *name) { formatln("%s [-c configurationfile] [...]\n", name); cmdline_print_help(yadifad_cmdline, 16, 28, " : ", 48, termout); } static void yadifad_print_authors() { print("\n" "\t\tYADIFAD authors:\n" "\t\t---------------\n" "\t\t\n" "\t\tGery Van Emelen\n" "\t\tEric Diaz Fernandez\n" "\n" "\t\tContact: " PACKAGE_BUGREPORT "\n" ); flushout(); } static void yadifad_show_version(u8 level) { switch(level) { case 1: osformatln(termout, "%s %s (%s)\n", PROGRAM_NAME, PROGRAM_VERSION, RELEASEDATE); break; case 2: #if HAS_BUILD_TIMESTAMP && defined(__DATE__) osformatln(termout, "%s %s (released %s, compiled %s)\n\nbuild settings: %s\n", PROGRAM_NAME, PROGRAM_VERSION, RELEASEDATE, __DATE__, BUILD_OPTIONS); #else osformatln(termout, "%s %s (released %s)\n\nbuild settings: %s\n", PROGRAM_NAME, PROGRAM_VERSION, RELEASEDATE, BUILD_OPTIONS); #endif break; case 3: #if HAS_BUILD_TIMESTAMP && defined(__DATE__) osformatln(termout, "%s %s (released %s, compiled %s)\n", PROGRAM_NAME, PROGRAM_VERSION, RELEASEDATE, __DATE__); #else osformatln(termout, "%s %s (released %s)\n", PROGRAM_NAME, PROGRAM_VERSION, RELEASEDATE); #endif yadifad_print_authors(); break; default: osformat(termout, "\nYou want to know too much!\n\n"); break; } flushout(); } /** @brief Initialize the config file with the standard settings * * @param[out] config * * @retval OK */ ya_result config_register_main(s32 priority); #if DNSCORE_HAS_ACL_SUPPORT ya_result acl_config_register(const char *null_or_acl_name, s32 priority); #endif ya_result config_register_zone(const char *null_or_key_name, s32 priority); #if DNSCORE_HAS_CTRL ya_result config_register_control(s32 priority); #endif #if HAS_RRL_SUPPORT ya_result config_register_rrl(s32 priority); #endif #if DNSCORE_HAS_NSID_SUPPORT ya_result config_register_nsid(s32 priority); #endif ya_result config_register_dnssec_policy(const char *null_or_key_name, s32 priority); ya_result yadifad_config_init() { ya_result return_code; if(dnscore_get_active_features() & DNSCORE_LOGGER) { for(const struct logger_name_handle_s *name_handle = logger_name_handles; name_handle->name != NULL; name_handle++) { logger_handle_create(name_handle->name, name_handle->handlep); } } if(FAIL(return_code = config_init())) { return return_code; } // to handle version & help int priority = 0; if(FAIL(return_code = config_register_cmdline(priority++))) { return return_code; } #if DNSCORE_HAS_TSIG_SUPPORT if(FAIL(return_code = config_register_key(NULL, priority++))) { return return_code; } #endif #if DNSCORE_HAS_ACL_SUPPORT if(FAIL(return_code = acl_config_register(NULL, priority++))) { return return_code; } #endif #if ZDB_HAS_MASTER_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && HAS_DNSSEC_SUPPORT if(FAIL(return_code = config_register_dnssec_policy(NULL, priority))) { return return_code; } #endif priority += 5; if(FAIL(return_code = config_register_main(priority++))) { return return_code; } if(FAIL(return_code = config_register_logger(NULL, NULL,priority))) // 5 & 6 { return return_code; } priority += 2; #if DNSCORE_HAS_CTRL if(FAIL(return_code = config_register_control(priority++))) { return return_code; } #endif if(FAIL(return_code = config_register_zone(NULL, priority++))) { return return_code; } #if HAS_RRL_SUPPORT if(FAIL(return_code = config_register_rrl(priority++))) { return return_code; } #endif #if DNSCORE_HAS_NSID_SUPPORT if(FAIL(return_code = config_register_nsid(priority++))) { return return_code; } #endif return return_code; } static bool yadifad_config_cmdline_callback_stop_processing = FALSE; static ya_result yadifad_config_cmdline_callback(const struct cmdline_desc_s *desc, const char *arg_name, void *callback_owned) { (void)desc; (void)callback_owned; if(strcmp(arg_name, "--") == 0) { yadifad_config_cmdline_callback_stop_processing = TRUE; return CMDLINE_ARG_STOP_PROCESSING_FLAG_OPTIONS; } if(yadifad_config_cmdline_callback_stop_processing) { return SUCCESS; } else { formatln("error parsing command line argument: '%s'", arg_name); return ERROR; } } /** * There is an issue using buffer as a an input because there is no rewind feature (yet) * So at the second pass, the reader fails with a bogus error message. * * affected: ./sbin/yadifad/yadifad -d * outputs: cmdline: config error: command-line: 3: '
': No such file or directory * * @param argc * @param argv * @return */ ya_result yadifad_config_cmdline(int argc, char **argv) { input_stream config_is; config_error_s cfgerr; config_error_reset(&cfgerr); ya_result return_code; config_set_source(CONFIG_SOURCE_HIGHEST); int argc_error; if(FAIL(return_code = cmdline_parse(yadifad_cmdline, argc, argv, yadifad_config_cmdline_callback, NULL, &config_is, &argc_error))) { if(argc_error > 0) { formatln("command line: %r at %s", return_code, argv[argc_error]); } else { formatln("command line: %r", return_code); } flushout(); return return_code; } config_set_source(CONFIG_SOURCE_CMDLINE); u32 cmdline_buffer_size = bytearray_input_stream_size(&config_is); u8* cmdline_buffer = bytearray_input_stream_detach(&config_is); input_stream_close(&config_is); if(FAIL(return_code = config_read_from_buffer((const char*)cmdline_buffer, cmdline_buffer_size, "command-line", &cfgerr))) { if(cfgerr.file[0] != '\0') { formatln("command line: '%s': %r", cfgerr.line, return_code); flushout(); } free(cmdline_buffer); return return_code; } free(cmdline_buffer); return_code = 0; if(cmdline_version_get() > 0) { yadifad_show_version(cmdline_version_get()); return_code++; } if(cmdline_help_get()) { yadifad_print_usage(argv[0]); return_code++; } config_set_source(CONFIG_SOURCE_DEFAULT); if(return_code == 0) { if(ISOK(return_code = config_value_set_to_default("main", "config_file", &cfgerr))) { return_code = 0; } else { if(cfgerr.file[0] != '\0') { formatln("%s: %r", cfgerr.file, return_code); flushout(); } else { // should never happen formatln("error: %r", return_code); flushout(); } } } return return_code; } ya_result yadifad_config_read(const char *config_file) { config_error_s cfgerr; config_error_reset(&cfgerr); ya_result return_code = SUCCESS; char configuration_file_path[PATH_MAX]; // if the passed value is a pointer into a configuration structure, // there is a risk that the value is freed and replaced by a different one // => bad // so a copy is done first if(database_zone_try_reconfigure_enable()) { file_mtime_set_t *file_mtime_set = file_mtime_set_get_for_file(g_config->config_file); if(!file_mtime_set_modified(file_mtime_set)) { formatln("configuration files from '%s' appears unchanged", g_config->config_file); return SUCCESS; // no change } file_mtime_set_clear(file_mtime_set); strcpy_ex(configuration_file_path, config_file, sizeof(configuration_file_path)); struct config_source_s sources[1]; config_source_set_file(&sources[0], configuration_file_path, CONFIG_SOURCE_FILE); return_code = config_read_from_sources(sources, 1, &cfgerr); if(FAIL(return_code)) { if(cfgerr.file[0] != '\0') { formatln("%s: config error: %s: %u: '%s': %r", config_file, cfgerr.file, cfgerr.line_number, cfgerr.line, return_code); } } database_zone_reconfigure_disable(); } else { formatln("could not read configuration: already reading a configuration"); } return return_code; } ya_result yadifad_config_finalize() { ya_result return_code = SUCCESS; config_set_source(CONFIG_SOURCE_DEFAULT); // disable loggers without any channel output logger_flush(); for(const struct logger_name_handle_s *name_handle = logger_name_handles; name_handle->name != NULL; name_handle++) { if(logger_handle_count_channels(name_handle->name) == 0) { logger_handle_close(name_handle->name); } } #if DEBUG if(g_config->print_config) { config_print(termout); } #endif return return_code; } ya_result config_read_zones() { return FEATURE_NOT_IMPLEMENTED_ERROR; // not implemented } ya_result yadifad_config_update(const char *config_file) { if(dnscore_shuttingdown()) { log_try_debug("yadifad_config_update(%s) cancelled by shutdown", config_file); return STOPPED_BY_APPLICATION_SHUTDOWN; } log_try_debug("yadifad_config_update(%s) started", config_file); config_error_s cfgerr; config_error_reset(&cfgerr); ya_result return_code = CONFIG_IS_BUSY; if(database_zone_try_reconfigure_enable()) { file_mtime_set_t *file_mtime_set = file_mtime_set_get_for_file(g_config->config_file); if(!file_mtime_set_modified(file_mtime_set)) { log_info("configuration files from '%s' appears unchanged", g_config->config_file); database_zone_reconfigure_disable(); return SUCCESS; // no change } file_mtime_set_clear(file_mtime_set); journal_close_unused(); database_set_drop_after_reload_for_set(NULL); config_set_source(CONFIG_SOURCE_FILE); #if DNSCORE_HAS_TSIG_SUPPORT tsig_serial_next(); #endif if(ISOK(return_code = config_read_section(config_file, &cfgerr, "key"))) { if(ISOK(return_code = config_read_section(config_file, &cfgerr, "zone"))) { log_info("%s: key and zone sections read", config_file); if(ISOK(return_code = config_read_section(config_file, &cfgerr, "main"))) { logger_flush(); logger_channel_close_all(); if(ISOK(return_code = config_read_section(config_file, &cfgerr, "channels"))) { if(ISOK(return_code = config_read_section(config_file, &cfgerr, "loggers"))) { } else if(return_code == SERVICE_ALREADY_INITIALISED) { return_code = SUCCESS; } } } else { if(cfgerr.file[0] != '\0') { ttylog_err("%s: config error: %s: %u: '%s': %r", config_file, cfgerr.file, cfgerr.line_number, cfgerr.line, return_code); } else { ttylog_err("
: %r", return_code); } } } else { if(cfgerr.file[0] != '\0') { ttylog_err("%s: config error: %s: %u: '%s': %r", config_file, cfgerr.file, cfgerr.line_number, cfgerr.line, return_code); } else { ttylog_err(": %r", return_code); } } } else { if(cfgerr.file[0] != '\0') { ttylog_err("%s: config error: %s: %u: '%s': %r", config_file, cfgerr.file, cfgerr.line_number, cfgerr.line, return_code); } else { ttylog_err(": %r", return_code); } } database_zone_reconfigure_do_drop_and_disable(ISOK(return_code)); #if DNSCORE_HAS_DNSSEC_SUPPORT dnssec_keystore_reload(); #endif } else { log_try_debug("previous reconfigure still running, postponed to run right after"); database_zone_postpone_reconfigure_all(); } log_try_debug("yadifad_config_update(%s): %r", config_file, return_code); return return_code; } static ya_result yadifad_config_update_zone_filter(zone_desc_s *zone_desc, void *params) { ptr_set *fqdn_set = (ptr_set*)params; if((fqdn_set == NULL) || (ptr_set_find(fqdn_set, zone_origin(zone_desc)) != NULL)) { return 1; } else { return 0; } } ya_result yadifad_config_update_zone(const char *config_file, const ptr_set *fqdn_set) { if(fqdn_set != NULL) { log_debug("yadifad_config_update_zone(%s, ) started", config_file); } else { log_debug("yadifad_config_update_zone(%s, ALL) started", config_file); } config_error_s cfgerr; config_error_reset(&cfgerr); ya_result return_code = CONFIG_IS_BUSY; if(database_zone_try_reconfigure_enable()) { database_set_drop_after_reload_for_set(fqdn_set); config_set_source(CONFIG_SOURCE_FILE); #if DNSCORE_HAS_TSIG_SUPPORT tsig_serial_next(); #endif if(ISOK(return_code = config_read_section(config_file, &cfgerr, "key"))) { config_section_zone_set_filter(yadifad_config_update_zone_filter, (void*)fqdn_set); // the filter will not modify the fqdn return_code = config_read_section(config_file, &cfgerr, "zone"); config_section_zone_set_filter(NULL, NULL); if(ISOK(return_code)) { log_info("%s: key and a some zone sections read", config_file); } else { if(cfgerr.file[0] != '\0') { ttylog_err("%s: config error: %s: %u: '%s': %r", config_file, cfgerr.file, cfgerr.line_number, cfgerr.line, return_code); } else { ttylog_err("%r", return_code); } } } else { if(cfgerr.file[0] != '\0') { ttylog_err("%s: config error: %s: %u: '%s': %r", config_file, cfgerr.file, cfgerr.line_number, cfgerr.line, return_code); } else { ttylog_err("%r", return_code); } } database_zone_reconfigure_do_drop_and_disable(ISOK(return_code)); } else { log_debug("previous reconfigure still running, postponed to run right after"); if(fqdn_set != NULL) { database_zone_postpone_reconfigure_zone(fqdn_set); } else { database_zone_postpone_reconfigure_zones(); } } log_debug("yadifad_config_update_zone(%s, ...): %r", config_file, return_code); return return_code; } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-desc-load.c0000644000000000000000000000013214505005533025043 xustar000000000000000030 mtime=1695812443.499997326 30 atime=1695812445.783030024 30 ctime=1695812495.620743801 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-desc-load.c0000664000374500037450000004576614505005533025027 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include "database-service.h" #include "notify.h" #include "zone-signature-policy.h" #include "zone.h" #if DNSCORE_HAS_CTRL #include "ctrl.h" #include "zone-signature-policy.h" #endif #define MODULE_MSG_HANDLE g_server_logger extern logger_handle *g_server_logger; extern zone_data_set database_zone_desc; void database_load_zone_desc(zone_desc_s *zone_desc) { yassert(zone_desc != NULL); log_debug1("database_load_zone_desc(%{dnsname}@%p=%i)", zone_origin(zone_desc), zone_desc, zone_desc->rc); s32 err = zone_register(&database_zone_desc, zone_desc); if(ISOK(err)) { log_info("zone: %{dnsname}: %p: config: registered", zone_origin(zone_desc), zone_desc); zone_lock(zone_desc, ZONE_LOCK_LOAD_DESC); zone_set_status(zone_desc, ZONE_STATUS_REGISTERED); zone_clear_status(zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD); zone_unlock(zone_desc, ZONE_LOCK_LOAD_DESC); // newly registered zone // used to be message->origin if(database_service_started()) { database_zone_load(zone_origin(zone_desc)); // before this I should set the file name #if ZDB_HAS_MASTER_SUPPORT if(zone_desc->type == ZT_MASTER) { } else #endif { } } } else { switch(err) { case DATABASE_ZONE_MISSING_DOMAIN: { log_err("zone: ?: %p: config: no domain set (not loaded)", zone_desc); if(zone_get_status(zone_desc) & ZONE_STATUS_PROCESSING) { log_err("zone: ?: %p: is processed by %s (releasing)", zone_desc, database_service_operation_get_name(zone_desc->last_processor)); } zone_release(zone_desc); break; } case DATABASE_ZONE_MISSING_MASTER: { log_err("zone: %{dnsname}: %p: config: slave but no master setting (not loaded)", zone_origin(zone_desc), zone_desc); if(zone_get_status(zone_desc) & ZONE_STATUS_PROCESSING) { log_err("zone: ?: %p: is processed by %s (releasing)", zone_desc, database_service_operation_get_name(zone_desc->last_processor)); } zone_release(zone_desc); break; } case DATABASE_ZONE_CONFIG_CLONE: // Exact copy { log_debug("zone: %{dnsname}: %p: config: has already been set (same settings)", zone_origin(zone_desc), zone_desc); zone_desc_s* current = zone_acquirebydnsname(zone_origin(zone_desc)); zone_lock(current, ZONE_LOCK_REPLACE_DESC); zone_clear_status(current, ZONE_STATUS_DROP_AFTER_RELOAD); zone_unlock(current, ZONE_LOCK_REPLACE_DESC); zone_release(current); // whatever has been decided above, loading the zone file (if it changed) should be queued database_zone_load(zone_origin(zone_desc)); zone_release(zone_desc); break; } case DATABASE_ZONE_CONFIG_DUP: // Not an exact copy { log_debug("zone: %{dnsname}: %p: config: has already been set (different settings)", zone_origin(zone_desc), zone_desc); // basically, most of the changes require a stop, restart of // any task linked to the zone // so let's make this a rule, whatever changed notify_clear(zone_origin(zone_desc)); zone_desc_s *current_zone_desc = zone_acquirebydnsname(zone_origin(zone_desc)); #if DNSCORE_HAS_DYNAMIC_PROVISIONING host_address *notify_slaves_then_delete = NULL; host_address *notify_slaves = NULL; #endif if(current_zone_desc != zone_desc) { zone_lock(current_zone_desc, ZONE_LOCK_REPLACE_DESC); if(zone_get_status(current_zone_desc) & ZONE_STATUS_PROCESSING) { log_err("zone: ?: %p: is processed by %s (overwriting)", zone_desc, database_service_operation_get_name(zone_desc->last_processor)); } free(current_zone_desc->file_name); current_zone_desc->file_name = zone_desc->file_name; zone_desc->file_name = NULL; // masters : log_debug7("updating %p (%u) with %p (%u): masters", current_zone_desc, current_zone_desc->lock_owner, zone_desc, zone_desc->lock_owner); if(host_address_list_equals(current_zone_desc->masters, zone_desc->masters)) { host_address_delete_list(zone_desc->masters); } else { host_address_delete_list(current_zone_desc->masters); current_zone_desc->masters = zone_desc->masters; } zone_desc->masters = NULL; // notifies : log_debug7("updating %p (%u) with %p (%u): notifies", current_zone_desc, current_zone_desc->lock_owner, zone_desc, zone_desc->lock_owner); if(host_address_list_equals(current_zone_desc->notifies, zone_desc->notifies)) { host_address_delete_list(zone_desc->notifies); } else { host_address_delete_list(current_zone_desc->notifies); current_zone_desc->notifies = zone_desc->notifies; } zone_desc->notifies = NULL; if(host_address_list_equals(current_zone_desc->transfer_source, zone_desc->transfer_source)) { host_address_delete_list(zone_desc->transfer_source); } else { host_address_delete_list(current_zone_desc->transfer_source); current_zone_desc->transfer_source = zone_desc->transfer_source; } zone_desc->transfer_source = NULL; #if DNSCORE_HAS_DYNAMIC_PROVISIONING log_debug7("updating %p (%u) with %p (%u): slaves", current_zone_desc, current_zone_desc->lock_owner, zone_desc, zone_desc->lock_owner); if(host_address_list_equals(current_zone_desc->slaves, zone_desc->slaves)) { #if ZDB_HAS_MASTER_SUPPORT if((current_zone_desc->type == ZT_MASTER) || (zone_desc->type == ZT_MASTER)) { notify_slaves_then_delete = zone_desc->slaves; } else #endif { host_address_delete_list(zone_desc->slaves); } } else { #if ZDB_HAS_MASTER_SUPPORT if(current_zone_desc->type == ZT_MASTER) { notify_slaves_then_delete = current_zone_desc->slaves; } else { host_address_delete_list(current_zone_desc->slaves); } if(zone_desc->type == ZT_MASTER) { notify_slaves = zone_desc->slaves; } #else host_address_delete_list(current->slaves); #endif current_zone_desc->slaves = zone_desc->slaves; } zone_desc->slaves = NULL; #endif // type : ? log_debug7("updating %p (%u) with %p (%u): type", current_zone_desc, current_zone_desc->lock_owner, zone_desc, zone_desc->lock_owner); current_zone_desc->type = zone_desc->type; #if DNSCORE_HAS_ACL_SUPPORT // ac : apply the new one, update the zone access log_debug7("updating %p (%u) with %p (%u): ac@%p with ac@%p", current_zone_desc, current_zone_desc->lock_owner, zone_desc, zone_desc->lock_owner, ¤t_zone_desc->ac, &zone_desc->ac); #if DEBUG log_debug7("old@%p:", current_zone_desc); log_debug7(" notify@%p",current_zone_desc->ac.allow_notify.ipv4.items); log_debug7(" query@%p",current_zone_desc->ac.allow_query.ipv4.items); log_debug7(" transfer@%p",current_zone_desc->ac.allow_transfer.ipv4.items); log_debug7(" update@%p",current_zone_desc->ac.allow_update.ipv4.items); log_debug7("forwarding@%p",current_zone_desc->ac.allow_update_forwarding.ipv4.items); log_debug7(" control@%p",current_zone_desc->ac.allow_control.ipv4.items); log_debug7("new@%p:", zone_desc); log_debug7(" notify@%p",zone_desc->ac.allow_notify.ipv4.items); log_debug7(" query@%p",zone_desc->ac.allow_query.ipv4.items); log_debug7(" transfer@%p",zone_desc->ac.allow_transfer.ipv4.items); log_debug7(" update@%p",zone_desc->ac.allow_update.ipv4.items); log_debug7("forwarding@%p",zone_desc->ac.allow_update_forwarding.ipv4.items); log_debug7(" control@%p",zone_desc->ac.allow_control.ipv4.items); #endif acl_unmerge_access_control(¤t_zone_desc->ac); acl_access_control_clear(¤t_zone_desc->ac); memcpy(¤t_zone_desc->ac, &zone_desc->ac, sizeof(access_control)); ZEROMEMORY(&zone_desc->ac, sizeof(access_control)); #endif // notify : reset, restart log_debug7("updating %p (%u) with %p (%u): notify", current_zone_desc, current_zone_desc->lock_owner, zone_desc, zone_desc->lock_owner); memcpy(¤t_zone_desc->notify, &zone_desc->notify, sizeof(zone_notify_s)); #if DNSCORE_HAS_DNSSEC_SUPPORT #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT // signature : reset, restart log_debug7("updating %p (%u) with %p (%u): signature", current_zone_desc, current_zone_desc->lock_owner, zone_desc, zone_desc->lock_owner); memcpy(¤t_zone_desc->signature, &zone_desc->signature, sizeof(zone_signature_s)); #endif // dnssec_mode : drop everything related to the zone, load the new config log_debug7("updating %p (%u) with %p (%u): dnssec_mode", current_zone_desc, current_zone_desc->lock_owner, zone_desc, zone_desc->lock_owner); current_zone_desc->dnssec_mode = zone_desc->dnssec_mode; #endif // refresh : update the "alarms" log_debug7("updating %p (%u) with %p (%u): refresh", current_zone_desc, current_zone_desc->lock_owner, zone_desc, zone_desc->lock_owner); memcpy(¤t_zone_desc->refresh, &zone_desc->refresh, sizeof(zone_refresh_s)); #if HAS_DYNAMIC_PROVISIONING // dynamic_provisioning : ? log_debug7("updating %p (%u) with %p (%u): dynamic_provisioning", current_zone_desc, current_zone_desc->lock_owner, zone_desc, zone_desc->lock_owner); memcpy(¤t_zone_desc->dynamic_provisioning, &zone_desc->dynamic_provisioning, sizeof(dynamic_provisioning_s)); #endif // slaves : update the list zone_unlock(current_zone_desc, ZONE_LOCK_REPLACE_DESC); } // whatever has been decided above, loading the zone file should be queued database_zone_load(zone_origin(zone_desc)); #if DNSCORE_HAS_DYNAMIC_PROVISIONING // if asking for a load of the zone_data on a master should trigger a notify of its slaves log_debug7("handling dynamic provisioning"); if(!host_address_empty(notify_slaves_then_delete)) { log_debug("zone load desc: %{dnsname}: notifying slaves: %{hostaddrlist}", zone_origin(zone_desc), notify_slaves_then_delete); notify_host_list(current_zone_desc, notify_slaves_then_delete, CLASS_CTRL); notify_slaves_then_delete = NULL; } if(!host_address_empty(notify_slaves)) { log_debug("zone load desc: %{dnsname}: notifying slaves: %{hostaddrlist}", zone_origin(zone_desc), notify_slaves); host_address *notify_slaves_copy = host_address_copy_list(notify_slaves); notify_host_list(current_zone_desc, notify_slaves_copy, CLASS_CTRL); notify_slaves = NULL; } #endif #if ZDB_HAS_MASTER_SUPPORT && HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT if(current_zone_desc->dnssec_policy != zone_desc->dnssec_policy) { log_info("zone: %{dnsname}: %p: config: dnssec-policy modified", zone_origin(zone_desc), zone_desc); if(zone_desc->dnssec_policy != NULL) { if(current_zone_desc->dnssec_policy != NULL) { log_warn("zone: %{dnsname}: %p: config: changing dnssec-policy at runtime (%s to %s)", zone_origin(zone_desc), zone_desc, current_zone_desc->dnssec_policy->name, zone_desc->dnssec_policy->name); if(current_zone_desc->dnssec_policy->denial != zone_desc->dnssec_policy->denial) { log_warn("zone: %{dnsname}: %p: config: modifications of the dnssec-policy denial setting may be ignored", zone_origin(zone_desc), zone_desc); } dnssec_policy_release(current_zone_desc->dnssec_policy); current_zone_desc->dnssec_policy = dnssec_policy_acquire_from_name(zone_desc->dnssec_policy->name); } else { log_info("zone: %{dnsname}: %p: config: dnssec-policy %s enabled", zone_origin(zone_desc), zone_desc, zone_desc->dnssec_policy->name); current_zone_desc->dnssec_policy = dnssec_policy_acquire_from_name(zone_desc->dnssec_policy->name); } } else { log_warn("zone: %{dnsname}: %p: config: removing policy at runtime", zone_origin(zone_desc), zone_desc); dnssec_policy_release(current_zone_desc->dnssec_policy); current_zone_desc->dnssec_policy = NULL; } } #endif if(current_zone_desc != zone_desc) { log_debug7("destroying temporary zone descriptor @%p", zone_desc); zone_release(zone_desc); } zone_clear_status(current_zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD); zone_release(current_zone_desc); break; } // DUP default: { log_err("zone: %{dnsname}: %p: failed to register", zone_origin(zone_desc), zone_desc); break; } } // switch } log_debug1("database_load_zone_desc(%p) done", zone_desc); } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-desc-unload.c0000644000000000000000000000013214505005533025406 xustar000000000000000030 mtime=1695812443.501997355 30 atime=1695812445.783030024 30 ctime=1695812495.623743844 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-desc-unload.c0000664000374500037450000001427114505005533025355 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include "zone.h" #include "database-service.h" #define MODULE_MSG_HANDLE g_server_logger extern logger_handle *g_server_logger; extern zone_data_set database_zone_desc; void database_service_zone_desc_unload(zone_desc_s *zone_desc) { // Ensure that the zone is not mounted yassert(zone_desc != NULL); log_debug1("database_service_zone_desc_unload(%{dnsname}@%p=%i)", zone_origin(zone_desc), zone_desc, zone_desc->rc); log_info("zone: %{dnsname}: %p: will unregister", zone_origin(zone_desc), zone_desc); if(FAIL(zone_lock(zone_desc, ZONE_LOCK_DESC_UNLOAD))) { log_err("zone: %{dnsname}: %p: config: failed to lock zone settings", zone_origin(zone_desc), zone_desc); return; } if((zone_get_status(zone_desc) & ZONE_STATUS_REGISTERED) == 0) { log_err("zone: %{dnsname}: %p: config: is not registered", zone_origin(zone_desc), zone_desc); zone_clear_status(zone_desc, ZONE_STATUS_PROCESSING); zone_unlock(zone_desc, ZONE_LOCK_DESC_UNLOAD); return; } if(database_zone_desc_is_mounted(zone_origin(zone_desc))) { // mounted : unmount and unload, then try again #if DEBUG database_zone_desc_is_mounted(zone_origin(zone_desc)); #endif yassert(zone_has_loaded_zone(zone_desc)); if(zone_has_loaded_zone(zone_desc)) { log_info("zone: %{dnsname}: %p: config: zone is mounted: unmounting", zone_origin(zone_desc), zone_desc); zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_UNMOUNT, NULL, TRUE); zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_UNLOAD, NULL, TRUE); // default zone } else { log_warn("zone: %{dnsname}: %p: config: zone is mounted but not referenced in its descriptor", zone_origin(zone_desc), zone_desc); } zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_DESC_UNLOAD, NULL, TRUE); zone_clear_status(zone_desc, ZONE_STATUS_PROCESSING); zone_unlock(zone_desc, ZONE_LOCK_DESC_UNLOAD); } else { /* * Remove the zone desc from the registered zones * Remove the zone desc from any alarm/task * Garbage the zone desc (new tool I have to make that mostly answers the dyn-prov-del issue) * ... * At some point in the future, free/destroy the zone desc */ log_info("zone: %{dnsname}: %p: config: unregistering", zone_origin(zone_desc), zone_desc); u32 queue_size = bpqueue_size(&zone_desc->commands); if(queue_size > 0) { log_warn("zone: %{dnsname}: %p: config: still has %i commands in the queue", zone_origin(zone_desc), zone_desc, queue_size); } zone_unlock(zone_desc, ZONE_LOCK_DESC_UNLOAD); zone_desc_s *zone_unregistered_desc = zone_unregister(&database_zone_desc, zone_origin(zone_desc)); if(zone_desc == zone_unregistered_desc) { zone_clear_status(zone_desc, ZONE_STATUS_REGISTERED); zone_release(zone_desc); } else { log_err("zone: %{dnsname}: %p: config: the registered descriptor is %p", zone_origin(zone_desc), zone_desc, zone_unregistered_desc); if(zone_unregistered_desc != NULL) { zone_release(zone_unregistered_desc); } else { log_err("zone: %{dnsname}: %p: config: not registered at all", zone_origin(zone_desc), zone_desc); } } log_info("zone: %{dnsname}: unregistered", zone_origin(zone_desc)); zone_clear_status(zone_desc, ZONE_STATUS_PROCESSING); zone_set_status(zone_desc, ZONE_STATUS_MARKED_FOR_DESTRUCTION); } log_debug1("database_service_zone_desc_unload(%p) done", zone_desc); } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-download.c0000644000000000000000000000013214505005533025017 xustar000000000000000030 mtime=1695812443.491997212 30 atime=1695812445.783030024 30 ctime=1695812495.625743872 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-download.c0000664000374500037450000006064414505005533024773 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - download db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include #include #include #define ZDB_JOURNAL_CODE 1 #include #include "database-service.h" #include "axfr.h" #include "ixfr.h" #define MODULE_MSG_HANDLE g_server_logger /**********************************************************************************************************************/ #define DSZDLPRM_TAG 0x4d52504c445a5344 #define ARBITRARY_REFRESH_VALUE 3600 // seconds struct database_service_zone_download_parms_s { u16 qtype; u8 origin[MAX_DOMAIN_LENGTH]; }; typedef struct database_service_zone_download_parms_s database_service_zone_download_parms_s; static ya_result database_service_zone_download_xfr(u16 qtype, const u8 *origin) { ya_result return_value; #if DEBUG log_debug("database_service_zone_download_xfr(%{dnstype},%{dnsname})", &qtype, origin); #endif zone_desc_s *zone_desc = zone_acquirebydnsname(origin); host_address *servers = NULL; u32 loaded_serial = ~0; u32 loaded_refresh = ~0; u16 transfer_type = 0; bool may_try_next_master = FALSE; /* * If the zone descriptor (config) exists and it can be locked by the loader ... */ if(zone_desc == NULL) { log_debug1("database_service_zone_download_thread: no zone settings for '%{dnsname}'", origin); return INVALID_STATE_ERROR; } log_debug1("database_service_zone_download_thread: locking zone '%{dnsname}' for loading", origin); // locks the descriptor with the loader identity if(FAIL(return_value = zone_lock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC))) { log_debug1("database_service_zone_download_thread: failed to lock zone settings for '%{dnsname}'", origin); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return return_value; } if(zone_desc->type != ZT_SLAVE) { log_warn("database_service_zone_download_thread: zone '%{dnsname}' is not a slave", origin); zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return return_value; } const u32 must_be_off = ZONE_STATUS_DOWNLOADING_XFR_FILE | ZONE_STATUS_DOWNLOADED | ZONE_STATUS_LOAD | ZONE_STATUS_LOADING; if((zone_get_status(zone_desc) & must_be_off) != 0) { zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); log_debug1("database_service_zone_download_thread: invalid status for '%{dnsname}'", origin); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return INVALID_STATE_ERROR; } if(dnscore_shuttingdown()) { zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); log_debug("zone download: zone download cancelled by shutdown"); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return STOPPED_BY_APPLICATION_SHUTDOWN; } zone_set_status(zone_desc, ZONE_STATUS_DOWNLOADING_XFR_FILE); bool is_multimaster = zone_is_multimaster(zone_desc); bool is_true_multimaster = zone_is_true_multimaster(zone_desc); bool force_load = (zone_desc->flags & ZONE_FLAG_DROP_CURRENT_ZONE_ON_LOAD) != 0; zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); bool retry; do { retry = FALSE; zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, origin); // ACQUIRES (obviously) if(zone != NULL) { soa_rdata soa; zdb_zone_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); return_value = zdb_zone_getsoa(zone, &soa); // zone is locked zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); if(ISOK(return_value)) { u32 local_serial; local_serial = soa.serial; log_debug("database_service_zone_download_thread: serial of %{dnsname} on the server is %d", origin, local_serial); u32 master_serial; zone_lock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); host_address *zone_desc_masters = host_address_copy_list(zone_desc->masters); zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); return_value = message_query_serial(origin, zone_desc_masters , &master_serial); host_address_delete_list(zone_desc_masters); if(ISOK(return_value)) { log_debug("database_service_zone_download_thread: serial of %{dnsname} on the master is %d", origin, master_serial); // compare serials if(!force_load && serial_le(master_serial, local_serial)) { if(serial_lt(master_serial, local_serial)) { log_warn("database_service_zone_download_thread: serial of %{dnsname} is lower on the master", origin); } log_debug("database_service_zone_download_thread: serial of %{dnsname} is not lower than the one on the master", origin); zone_lock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); zone_clear_status(zone_desc, ZONE_STATUS_DOWNLOADING_XFR_FILE|ZONE_STATUS_PROCESSING); zone_desc->refresh.refreshed_time = time(NULL); zone_desc->refresh.retried_time = zone_desc->refresh.refreshed_time; u32 next_refresh = zone_desc->refresh.refreshed_time + soa.refresh; log_debug("database: refresh: %{dnsname}: zone didn't need a refresh, next refresh currently scheduled for %T", origin, next_refresh); database_zone_refresh_maintenance_wih_zone(zone, next_refresh); zdb_zone_release(zone); database_fire_zone_downloaded(origin, TYPE_NONE, local_serial, SUCCESS); zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); zone_release(zone_desc); return SUCCESS; } } else { log_warn("database: could not get the serial of %{dnsname} from the master @%{hostaddr}: %r", zone_origin(zone_desc), zone_desc->masters, return_value); } } } if(dnscore_shuttingdown()) { log_debug("zone download: zone download cancelled by shutdown (loop)"); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return STOPPED_BY_APPLICATION_SHUTDOWN; } // get ready with the download of the AXFR/IXFR zone_lock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); servers = host_address_copy_list(zone_desc->masters); zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); loaded_serial = ~0; transfer_type = 0; may_try_next_master = FALSE; switch(qtype) { case TYPE_AXFR: { log_info("slave: %{dnsname} AXFR query to the master", origin); if(ISOK(return_value = axfr_query_ex(servers, origin, &loaded_serial, &loaded_refresh))) { zone_lock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); zone_desc->refresh.refreshed_time = time(NULL); zone_desc->multimaster_failures = 0; zone_set_status(zone_desc, ZONE_STATUS_DOWNLOADED); zone_desc->download_failure_count = 0; zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); u32 next_refresh = zone_desc->refresh.refreshed_time + loaded_refresh; database_zone_refresh_maintenance_wih_zone(zone, next_refresh); transfer_type = (u16)return_value; /// @note comes from axfr_query_master_ex, take care not overwriting it if(transfer_type != 0) { log_info("slave: %{dnsname}: got %{dnstype} from master at %{hostaddr}, serial is %u", origin, &qtype, servers, loaded_serial); } } else { if(return_value != STOPPED_BY_APPLICATION_SHUTDOWN) { log_err("slave: %{dnsname}: axfr query error from master at %{hostaddr}: %r", origin, servers, return_value); } may_try_next_master = is_multimaster; zone_lock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); ++zone_desc->download_failure_count; zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); } break; } case TYPE_IXFR: { log_info("slave: %{dnsname}: IXFR query to the master", origin); if(zone == NULL) { log_err("slave: %{dnsname}: zone is not in the database", origin); return_value = ZDB_ERROR_ZONE_NOT_IN_DATABASE; break; } if(zdb_zone_isinvalid(zone)) { zdb_zone *current_zone = zdb_acquire_zone_read_from_fqdn(g_config->database, origin); // ACQUIRES (obviously) if(zone != current_zone) { retry = TRUE; } else { log_err("slave: %{dnsname}: cannot start an incremental transfer from an invalid zone", origin); } zdb_zone_release(current_zone); return_value = ZDB_ERROR_ZONE_INVALID; break; } if((zone_desc->flags & ZONE_FLAG_NO_MASTER_UPDATES) == 0) { return_value = ixfr_query(servers, zone, &loaded_serial); if(ISOK(return_value) || (return_value == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY)) { zone_lock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); zone_desc->refresh.refreshed_time = time(NULL); zone_desc->multimaster_failures = 0; zone_desc->download_failure_count = 0; zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); transfer_type = (u16)return_value; if(ISOK(return_value) && (transfer_type != 0)) { log_info("slave: %{dnsname}: got %{dnstype} from master at %{hostaddr}, new serial is %u", origin, &qtype, servers, loaded_serial); } // the stream query may have been cut by the journal because it was full (or one of the many equivalent states) // the zone needs to be stored on disk so the journal can go further if(return_value == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { zdb_zone_info_background_store_zone(zone->origin); } else { soa_rdata soa; u32 next_refresh; zdb_zone_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); return_value = zdb_zone_getsoa(zone, &soa); // zone is locked zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); if(ISOK(return_value)) { next_refresh = zone_desc->refresh.refreshed_time + soa.refresh; } else { log_warn("slave: %{dnsname}: ixfr query error from master at %{hostaddr}: there was an issue getting the refresh value from the SOA: %r (defaulting to %i)", origin, servers, return_value, ARBITRARY_REFRESH_VALUE); next_refresh = zone_desc->refresh.refreshed_time + ARBITRARY_REFRESH_VALUE; } database_zone_refresh_maintenance_wih_zone(zone, next_refresh); } return_value = SUCCESS; } else if(return_value == MAKE_DNSMSG_ERROR(RCODE_NOTIMP)) { log_warn("slave: %{dnsname}: ixfr query error from master at %{hostaddr}: it does not support incremental transfers and does not falls back to AXFR, switching to AXFR", origin, servers); qtype = TYPE_AXFR; retry = TRUE; } else { if(return_value != STOPPED_BY_APPLICATION_SHUTDOWN) { if(IS_DNS_ERROR_CODE(return_value)) { log_notice("slave: %{dnsname}: ixfr query error from master at %{hostaddr}: %r", origin, servers, return_value); } else { log_warn("slave: %{dnsname}: ixfr query error from master at %{hostaddr}: %r", origin, servers, return_value); } } may_try_next_master = is_multimaster; zone_lock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); ++zone_desc->download_failure_count; zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); } } else { log_info("slave: master updates for domain %{dnsname} disabled by configuration", origin); loaded_serial = 0; } // else XFRs to the master are disabled break; } default: { log_err("slave: %{dnsname}: %{hostaddr} gave unexpected answer of type %{dnstype}", servers, &qtype, origin); break; } } // switch(qtype) if(zone != NULL) { zdb_zone_release(zone); } } while(retry); if(dnscore_shuttingdown()) { log_debug("zone download: zone download cancelled by shutdown (rearm)"); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return STOPPED_BY_APPLICATION_SHUTDOWN; } zone_lock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); zone_clear_status(zone_desc, ZONE_STATUS_DOWNLOADING_XFR_FILE|ZONE_STATUS_PROCESSING); if(!may_try_next_master) { database_fire_zone_downloaded(origin, transfer_type, loaded_serial, return_value); if(FAIL(return_value)) { random_ctx rndctx = thread_pool_get_random_ctx(); u32 jitter = random_next(rndctx); if(g_config->axfr_retry_jitter > 0) { jitter %= g_config->axfr_retry_jitter; } time_t next_try = time(NULL) + g_config->axfr_retry_delay + jitter + MIN(zone_desc->download_failure_count * g_config->axfr_retry_failure_delay_multiplier, g_config->axfr_retry_failure_delay_max); if(qtype == TYPE_AXFR) { log_warn("slave: %{dnsname}: master %{hostaddr} failed to answer AXFR query for domain retrying at %T", origin, servers, next_try); database_zone_axfr_query_at(zone_origin(zone_desc), next_try); // should not be lower than 5 } else { log_warn("slave: %{dnsname}: master %{hostaddr} failed to answer IXFR query for domain retrying at %T", origin, servers, next_try); database_zone_ixfr_query_at(zone_origin(zone_desc), next_try); // should not be lower than 5 } } // else success } else // failure + multimaster { random_ctx rndctx = thread_pool_get_random_ctx(); u32 jitter = random_next(rndctx); if(g_config->axfr_retry_jitter > 0) { jitter %= g_config->axfr_retry_jitter; } time_t next_try = time(NULL) + g_config->axfr_retry_delay + jitter; if(zone_desc->multimaster_failures < zone_desc->multimaster_retries) { next_try += MIN(zone_desc->download_failure_count * g_config->axfr_retry_failure_delay_multiplier, g_config->axfr_retry_failure_delay_max); if(zone_desc->multimaster_failures < MAX_U8) { ++zone_desc->multimaster_failures; } if(qtype == TYPE_AXFR) { log_warn("slave: %{dnsname}: master %{hostaddr} failed to answer AXFR query for domain retrying at %T (retry %u)", origin, servers, next_try, zone_desc->multimaster_failures); database_zone_axfr_query_at(zone_origin(zone_desc), next_try); // should not be lower than 5 } else { log_warn("slave: %{dnsname}: master %{hostaddr} failed to answer IXFR query for domain retrying at %T (retry %u)", origin, servers, next_try, zone_desc->multimaster_failures); database_zone_ixfr_query_at(zone_origin(zone_desc), next_try); // should not be lower than 5 } } else { // next master host_address_list_roll(&zone_desc->masters); zone_desc->multimaster_failures = 0; if(is_true_multimaster) { char file_name[PATH_MAX]; log_warn("slave: %{dnsname}: master %{hostaddr} failed to answer query for domain, will load a new zone with master %{hostaddr} at %T", origin, servers, zone_desc->masters, next_try); /// @note 20160623 edf -- true multimaster : destroying local zone is the only way to go journal_truncate(origin); // delete zone file, axfr file, journal snformat(file_name, sizeof(file_name), "%s%s", g_config->data_path, zone_desc->file_name); log_debug("slave: %{dnsname}: deleting '%s'", origin, file_name); unlink(file_name); if(ISOK(return_value = zdb_zone_path_get_provider()( origin, file_name, sizeof(file_name) - 6, ZDB_ZONE_PATH_PROVIDER_AXFR_FILE|ZDB_ZONE_PATH_PROVIDER_MKDIR))) { log_debug("slave: %{dnsname}: deleting '%s'", origin, file_name); unlink(file_name); } zone_desc->flags |= ZONE_FLAG_DROP_CURRENT_ZONE_ON_LOAD; database_zone_axfr_query_at(zone_origin(zone_desc), next_try); } else { if(qtype == TYPE_AXFR) { log_warn("slave: %{dnsname}: master %{hostaddr} failed to answer AXFR query for domain trying with master %{hostaddr} at %T", origin, servers, zone_desc->masters, next_try); database_zone_axfr_query_at(zone_origin(zone_desc), next_try); } else if(qtype == TYPE_IXFR) { log_warn("slave: %{dnsname}: master %{hostaddr} failed to answer IXFR query for domain trying with master %{hostaddr} at %T", origin, servers, zone_desc->masters, next_try); database_zone_ixfr_query_at(zone_origin(zone_desc), next_try); } } } } // all branches leading to this point are setting an alarm to try again in case of failure zone_unlock(zone_desc, ZONE_LOCK_DOWNLOAD_DESC); #if DEBUG log_debug("database_service_zone_download_thread(%{dnstype},%{dnsname}) done", &qtype, origin); #endif zone_release(zone_desc); host_address_delete_list(servers); return SUCCESS; } static void* database_service_zone_download_thread(void *parms) { #if DEBUG log_debug("database_service_zone_download_thread(%p)", parms); #endif database_service_zone_download_parms_s *database_service_zone_download_parms = (database_service_zone_download_parms_s*)parms; if(!dnscore_shuttingdown()) { const u8 *origin = database_service_zone_download_parms->origin; u16 qtype = database_service_zone_download_parms->qtype; database_service_zone_download_xfr(qtype, origin); } free(database_service_zone_download_parms); database_service_zone_download_parms = NULL; return NULL; } void database_service_zone_axfr_query(const u8 *origin) { #if DEBUG log_debug("database_service_zone_axfr_query(%{dnsname})", origin); #endif database_service_zone_download_parms_s *parm; MALLOC_OBJECT_OR_DIE(parm, database_service_zone_download_parms_s, DSZDLPRM_TAG); parm->qtype = TYPE_AXFR; dnsname_copy(parm->origin, origin); database_service_zone_download_queue_thread(database_service_zone_download_thread, parm, NULL, "database_service_zone_download_thread"); } void database_service_zone_ixfr_query(const u8 *origin) { #if DEBUG log_debug("database_service_zone_ixfr_query(%{dnsname})", origin); #endif database_service_zone_download_parms_s *parm; MALLOC_OBJECT_OR_DIE(parm, database_service_zone_download_parms_s, DSZDLPRM_TAG); parm->qtype = TYPE_IXFR; dnsname_copy(parm->origin, origin); database_service_zone_download_queue_thread(database_service_zone_download_thread, parm, NULL, "database_service_zone_download_thread"); } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-freeze.c0000644000000000000000000000013214505005533024470 xustar000000000000000030 mtime=1695812443.545997985 30 atime=1695812445.785030053 30 ctime=1695812495.627743901 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-freeze.c0000664000374500037450000001073514505005533024440 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include "zone.h" #include "server.h" #define MODULE_MSG_HANDLE g_server_logger /**********************************************************************************************************************/ void database_service_zone_freeze(zone_desc_s *zone_desc) { ya_result return_value; #if DEBUG log_debug("database_service_zone_freeze(%{dnsname}@%p=%i)", zone_origin(zone_desc), zone_desc, zone_desc->rc); #endif if(zone_desc == NULL) { log_err("zone freeze: NULL zone"); return; } log_debug1("database_service_zone_freeze: locking zone '%{dnsname}' for freezing", zone_origin(zone_desc)); if(FAIL(return_value = zone_lock(zone_desc, ZONE_LOCK_FREEZE))) { log_err("database_service_zone_freeze: failed to lock zone settings for '%{dnsname}'", zone_origin(zone_desc)); return; } zdb_zone *zone = zone_get_loaded_zone(zone_desc); // ACQUIRES if(zone == NULL) { log_err("zone freeze: no zone loaded for '%{dnsname}'", zone_origin(zone_desc)); zone_clear_status(zone_desc, ZONE_STATUS_PROCESSING); log_debug1("database_service_zone_freeze: unlocking zone '%{dnsname}' for freezing", zone_origin(zone_desc)); zone_unlock(zone_desc, ZONE_LOCK_FREEZE); return; } // This REALLY is the simple reader lock. This operation does not interfere // with readers, only with writers. There is no point preventing queries // in the database while setting the zone read-only. zdb_zone_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); if(zdb_zone_is_frozen(zone)) { log_warn("zone freeze: %{dnsname} already frozen", zone->origin); } zdb_zone_set_frozen(zone); zdb_zone_release_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); log_info("zone freeze: %{dnsname}", zone_origin(zone_desc)); zone_set_status(zone_desc, ZONE_STATUS_FROZEN); zone_clear_status(zone_desc, ZONE_STATUS_PROCESSING); log_debug1("database_service_zone_freeze: unlocking zone '%{dnsname}' for freezing", zone_origin(zone_desc)); zone_unlock(zone_desc, ZONE_LOCK_FREEZE); } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-load.c0000644000000000000000000000013114505005533024126 xustar000000000000000030 mtime=1695812443.510997484 30 atime=1695812445.783030024 29 ctime=1695812495.62974393 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-load.c0000664000374500037450000022515214505005533024100 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #define ZDB_JOURNAL_CODE 1 #include "server-config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if ZDB_HAS_DNSSEC_SUPPORT #include #endif #include "database-service.h" #include "ixfr.h" #include "zone-source.h" #include "notify.h" #include #if DNSCORE_HAS_CTRL #include "ctrl.h" #include "database-service-zone-resignature.h" #endif #define MODULE_MSG_HANDLE g_server_logger /**********************************************************************************************************************/ #define DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS 0 #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS #pragma message("WARNING: DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS enabled !") #endif typedef ya_result database_zone_load_loader(zdb *db, zone_desc_s *zone_desc, struct zdb_zone_load_parms *zone_load_parms); #define DSZLDPRM_TAG 0x4d5250444c5a5344 struct database_service_zone_load_parms_s { zdb *db; zone_desc_s *zone_desc; database_zone_load_loader *loader; bool start_maintenance_asap; }; typedef struct database_service_zone_load_parms_s database_service_zone_load_parms_s; static database_service_zone_load_parms_s* database_zone_load_parms_alloc(zdb *db, zone_desc_s *zone_desc, database_zone_load_loader *loader) { database_service_zone_load_parms_s *parm; ZALLOC_OBJECT_OR_DIE( parm, database_service_zone_load_parms_s, DSZLDPRM_TAG); parm->db = db; parm->zone_desc = zone_desc; parm->loader = loader; return parm; } void database_zone_load_parms_free(database_service_zone_load_parms_s *parm) { #if DEBUG memset(parm, 0xff, sizeof(database_service_zone_load_parms_s)); #endif ZFREE_OBJECT(parm); } #if ZDB_HAS_MASTER_SUPPORT /** * Loads a MASTER zone file from disc into memory. * Returns a pointer to the zone structure. * The zone still has to be "mounted" in the database * * @param db a pointer to the database * @param zone_desc the zone configuration * @param zone_load_parms pointer to a uninitialised struct zdb_zone_load_parms * @return */ static ya_result database_load_zone_master(zdb *db, zone_desc_s *zone_desc, struct zdb_zone_load_parms *zone_load_parms) // returns with RC++ { #if DEBUG log_debug("database_load_zone_master(%p,%p,%p)", db, zone_desc, zone_load_parms); #endif if(dnscore_shuttingdown()) { log_debug("zone load: master zone load cancelled by shutdown"); zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_PROCESSED, NULL, TRUE); return STOPPED_BY_APPLICATION_SHUTDOWN; } s64 zone_load_begin = timeus(); zone_lock(zone_desc, ZONE_LOCK_LOAD); if(zone_desc->type != ZT_MASTER) { zone_unlock(zone_desc, ZONE_LOCK_LOAD); log_err("zone load: tried to load a non-master zone as a master"); return ZONE_LOAD_MASTER_TYPE_EXPECTED; } if(zone_desc->file_name == NULL) { zone_unlock(zone_desc, ZONE_LOCK_LOAD); log_err("zone load: no file defined for master zone section (not loaded)"); return ZONE_LOAD_MASTER_ZONE_FILE_UNDEFINED; } if(zone_load_parms == NULL) { zone_unlock(zone_desc, ZONE_LOCK_LOAD); log_err("zone load: invalid use"); return UNEXPECTED_NULL_ARGUMENT_ERROR; } zone_reader zr; zdb_zone *zone_pointer_out; ya_result return_value; u32 zone_file_soa_serial; #if ZDB_HAS_DNSSEC_SUPPORT u32 zone_desc_dnssec_mode; #endif bool is_drop_before_load; bool zr_opened = FALSE; bool zone_file_soa_serial_set = FALSE; bool rrsig_push_allowed = FALSE; u8 zone_desc_origin[MAX_DOMAIN_LENGTH]; char file_name[PATH_MAX]; char zone_desc_file_name[PATH_MAX]; #if ZDB_HAS_DNSSEC_SUPPORT zone_desc_dnssec_mode = zone_desc->dnssec_mode << ZDB_ZONE_DNSSEC_SHIFT; #endif is_drop_before_load = zone_is_drop_before_load(zone_desc); rrsig_push_allowed = zone_rrsig_nsupdate_allowed(zone_desc); dnsname_copy(zone_desc_origin, zone_origin(zone_desc)); strcpy_ex(zone_desc_file_name, zone_desc->file_name, sizeof(zone_desc_file_name)); zone_unlock(zone_desc, ZONE_LOCK_LOAD); /* * _ Open the zone file/source * _ Load the zone * (do the NSEC/NSEC3 pre-processing) * _ Close the zone file/source * _ Apply the ACLs * _ Schedule an NSEC/NSEC3 verify/update. (Here ?) */ /* Avoid cpy & cat : overrun potential */ if(zone_desc->file_name[0] != '/') { snformat(file_name, sizeof(file_name), "%s%s", g_config->data_path, zone_desc->file_name); } else { strcpy_ex(file_name, zone_desc->file_name, sizeof(file_name)); } // get the serial number from the file to avoid useless work zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(db, zone_desc_origin); // ACQUIRES if(zone != NULL) { if(!zdb_zone_isinvalid(zone)) { log_debug("zone load: preparing to load '%s'", file_name); // first, get the serial of the zone file if(ISOK(return_value = zone_reader_text_open(file_name, &zr))) { resource_record rr; zone_reader_text_set_origin(&zr, zone_desc_origin); zr_opened = TRUE; resource_record_init(&rr); if(ISOK(return_value = zone_reader_read_record(&zr, &rr))) { if(dnsname_equals(zone_desc_origin, rr.name)) { if(rr.type == TYPE_SOA) { return_value = rr_soa_get_serial(zone_reader_rdata(rr), zone_reader_rdata_size(rr), &zone_file_soa_serial); if(ISOK(return_value)) { zone_file_soa_serial_set = TRUE; log_debug("zone load: '%s' serial from file is %u", zone_domain(zone_desc), zone_file_soa_serial); } zone_reader_unread_record(&zr, &rr); // no need to open the file/stream again } else { return_value = ZDB_READER_FIRST_RECORD_NOT_SOA; } } else { return_value = ZDB_READER_ANOTHER_DOMAIN_WAS_EXPECTED; } resource_record_freecontent(&rr); } } if(FAIL(return_value)) // if return_value is NOT an error, zone_file_soa_serial is set { zdb_zone_release(zone); // undo zdb_acquire_zone_read_from_fqdn zone = NULL; if(zr_opened) { zone_reader_close(&zr); } s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; log_err("zone load: cannot read master zone file '%s': %r (%9.6fs)", file_name, return_value, load_time); return return_value; } // at this point the zone reader is opened and zone_file_soa_serial is set // from here, zone_file_soa_serial can only be set u32 zone_serial = ~0; zdb_zone_lock(zone, ZDB_ZONE_MUTEX_LOAD); if(!zdb_zone_isinvalid(zone)) { return_value = zdb_zone_getserial(zone, &zone_serial); // zone is locked zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_LOAD); if(ISOK(return_value)) { if(serial_ge(zone_serial, zone_file_soa_serial)) /// @note cppcheck false positive on zone_file_soa_serial { zone_reader_close(&zr); s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; log_debug("zone load: %{dnsname}: db serial >= file serial '%s' (%u >= %u): no need to load (%9.6fs)", zone_desc_origin, file_name, zone_serial, zone_file_soa_serial, load_time); zdb_zone_load_parms_init(zone_load_parms, NULL, zone_origin(zone_desc), 0); zone_load_parms->out_zone = zone; return SUCCESS; // zone is not NULL } } else { log_err("zone load: unable to retrieve the serial of the loaded zone: %r", return_value); } zdb_zone_release(zone); zone = NULL; } else { zdb_zone_release_unlock(zone, ZDB_ZONE_MUTEX_LOAD); log_debug1("zone load: instance of the zone in the database is invalid: %r", return_value); } zone = NULL; // from this point zone cannot be read // at this point, the file is about to be loaded. It is the right time to test the drop-before-load flag if(is_drop_before_load) { // the zone is loaded and is valid, we need to drop it // so we unmount it (replacing it by the dummy) // then we ask for loading it again zone_lock(zone_desc, ZONE_LOCK_LOAD); zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_UNMOUNT, NULL, TRUE); zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_LOAD, NULL, TRUE); zone_unlock(zone_desc, ZONE_LOCK_LOAD); zone_reader_close(&zr); s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; log_info("zone load: '%s' load requires the zone to be dropped first (%9.6fs)", zone_domain(zone_desc), load_time); zdb_zone_load_parms_init(zone_load_parms, NULL, zone_origin(zone_desc), 0); return ZDB_READER_ALREADY_LOADED; } } else // zone in db is the invalid placeholder, simply open the file { log_debug1("zone load: '%s' zone@%p in the database is a placeholder", zone_domain(zone_desc), zone); zdb_zone_release(zone); zone = NULL; if(FAIL(return_value = zone_reader_text_open(file_name, &zr))) { s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; log_err("zone load: '%s' could not open file '%s': %r (%9.6fs)", zone_domain(zone_desc), file_name, return_value, load_time); return return_value; } } } else { // *zone == NULL, simply open the file if(FAIL(return_value = zone_reader_text_open(file_name, &zr))) { s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; log_err("zone load: '%s' could not open file '%s': %r (%9.6fs)", zone_domain(zone_desc), file_name, return_value, load_time); return return_value; } } log_info("zone load: loading '%s'", file_name); /// @note edf : DO NOT USE the flag "MOUNT ON LOAD" HERE zone_reader_text_set_origin(&zr, zone_desc_origin); // the journal MUST be closed, else we way have a situation where // the journal is linked to another instance of the zone #if ZDB_ZONE_HAS_JNL_REFERENCE if(zone_desc->loaded_zone != NULL) { if(zone_desc->loaded_zone->journal != NULL) { journal_close(zone_desc->loaded_zone->journal); } } #endif u16 zone_load_flags = ZDB_ZONE_REPLAY_JOURNAL; #if ZDB_HAS_DNSSEC_SUPPORT if(zone_maintains_dnssec(zone_desc)) { zone_load_flags |= zone_desc_dnssec_mode; } else { zone_load_flags |= ZDB_ZONE_NO_MAINTENANCE; } #endif zdb_zone_load_parms_init(zone_load_parms, &zr, zone_desc_origin, zone_load_flags); return_value = zdb_zone_load_ex(zone_load_parms); zone_reader_close(&zr); if(ISOK(return_value)) { } else { zone_pointer_out = NULL; } if(ISOK(return_value)) { zone_pointer_out = zdb_zone_load_parms_zone_get(zone_load_parms); zdb_zone_set_rrsig_push_allowed(zone_pointer_out, rrsig_push_allowed); if(rrsig_push_allowed) { log_info("zone load: '%s' allows RRSIG pushing", zone_domain(zone_desc)); } #if ZDB_HAS_DNSSEC_SUPPORT u32 real_dnssec_mode; if(zdb_zone_has_nsec3_optout_chain(zone_pointer_out)) { real_dnssec_mode = ZDB_ZONE_NSEC3_OPTOUT; } else if(zdb_zone_has_nsec3_chain(zone_pointer_out)) { real_dnssec_mode = ZDB_ZONE_NSEC3; } else if(zdb_zone_has_nsec_chain(zone_pointer_out)) { real_dnssec_mode = ZDB_ZONE_NSEC; } else { real_dnssec_mode = ZDB_ZONE_NOSEC; } zdb_zone_double_lock(zone_pointer_out, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); zdb_packed_ttlrdata *nsecchainstate = zdb_record_find(&zone_pointer_out->apex->resource_record_set, TYPE_NSECCHAINSTATE); zdb_packed_ttlrdata *nsec3chainstate = zdb_record_find(&zone_pointer_out->apex->resource_record_set, TYPE_NSEC3CHAINSTATE); zdb_packed_ttlrdata *nsec3paramqueued = zdb_record_find(&zone_pointer_out->apex->resource_record_set, TYPE_NSEC3PARAMQUEUED); #if DEBUG log_debug("NSECCHAINSTATE: %i NSEC3CHAINSTATE: %i NSEC3PARAMQUEUED: %i", nsecchainstate != NULL, nsec3chainstate != NULL, nsec3paramqueued != NULL); logger_flush(); #endif if(nsec3chainstate != NULL) { // NSEC3 operations were ongoing on the database, resume them if(real_dnssec_mode != ZDB_ZONE_NSEC) { if(real_dnssec_mode == ZDB_ZONE_NOSEC) { // set to NSEC3 optout, start maintenance ASAP } else // NSEC3 (optin/optout) { // start maintenance ASAP } } else { // conflict : delete the state } } else if(nsec3paramqueued != NULL) { // an NSEC3PARAM was being added, setup maintenance for it if(real_dnssec_mode != ZDB_ZONE_NSEC) { if(real_dnssec_mode == ZDB_ZONE_NOSEC) { // set to NSEC3 optout, start maintenance ASAP database_apply_nsec3paramqueued(zone_pointer_out, nsec3paramqueued, ZDB_ZONE_MUTEX_LOAD); real_dnssec_mode = ZDB_ZONE_NSEC3_OPTOUT; } else // NSEC3 (optin/optout) { // start maintenance ASAP database_apply_nsec3paramqueued(zone_pointer_out, nsec3paramqueued, ZDB_ZONE_MUTEX_LOAD); } } else { // conflict : delete the state } } else if(nsecchainstate != NULL) { // NSEC operations were ongoing on the database, resume them if(!((real_dnssec_mode == ZDB_ZONE_NSEC3) || (real_dnssec_mode == ZDB_ZONE_NSEC3_OPTOUT))) { if(real_dnssec_mode == ZDB_ZONE_NOSEC) { // set to NSEC optout, start maintenance ASAP real_dnssec_mode = ZDB_ZONE_NSEC3_OPTOUT; } else { // start maintenance ASAP } } else { // conflict : delete the state } } zdb_zone_double_unlock(zone_pointer_out, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_LOAD); if(real_dnssec_mode != zone_desc_dnssec_mode) { log_debug("zone load: dnssec mode set to %i", real_dnssec_mode); zone_load_flags &= ~zone_desc_dnssec_mode; zone_desc_dnssec_mode = real_dnssec_mode; zone_load_flags |= zone_desc_dnssec_mode; } #endif if(!zone_file_soa_serial_set) { // zone is locked (technically needlessly) else integrity checks would abort zdb_zone_lock(zone_pointer_out, ZDB_ZONE_MUTEX_LOAD); return_value = zdb_zone_getserial(zone_pointer_out, &zone_file_soa_serial); // zone is locked zdb_zone_unlock(zone_pointer_out, ZDB_ZONE_MUTEX_LOAD); if(ISOK(return_value)) { //log_err("zone load: could not get the zone serial from the loaded zone '%s': %r", zone_domain(zone_desc), return_value); log_debug("zone load: '%s' serial from file is %u", zone_domain(zone_desc), zone_file_soa_serial); } else { log_err("zone load: could not get the zone serial from the loaded zone '%s': %r", zone_domain(zone_desc), return_value); zone_file_soa_serial = 0; } } /* * zone_pointer_out must be mounted */ zone_lock(zone_desc, ZONE_LOCK_LOAD); zone_desc->stored_serial = zone_file_soa_serial; #if ZDB_HAS_ACL_SUPPORT /* * Setup the ACL filter function & configuration */ zone_pointer_out->acl = &zone_desc->ac; /* The extension points to the ACL */ zone_pointer_out->query_access_filter = acl_get_query_access_filter(&zone_desc->ac.allow_query); #endif #if ZDB_HAS_DNSSEC_SUPPORT #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT if((zone_load_flags & ZDB_ZONE_DNSSEC_MASK) != ZDB_ZONE_NOSEC) { /* * Setup the validity period and the jitter */ zone_pointer_out->sig_validity_regeneration_seconds = zone_desc->signature.sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S; zone_pointer_out->sig_validity_interval_seconds = zone_desc->signature.sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S; zone_pointer_out->sig_validity_jitter_seconds = zone_desc->signature.sig_validity_jitter * SIGNATURE_VALIDITY_JITTER_S; #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS zone_pointer_out->sig_validity_regeneration_seconds = 90; zone_pointer_out->sig_validity_interval_seconds = 180; zone_pointer_out->sig_validity_jitter_seconds = 5; #endif static const u8 dnssec_flag_to_maintain_mode[4] = {0, ZDB_ZONE_MAINTAIN_NSEC, ZDB_ZONE_MAINTAIN_NSEC3, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT}; u8 maintain_mode = 0; if(zone_maintains_dnssec(zone_desc)) { if(zone_desc->dnssec_mode != ZONE_DNSSEC_FL_NOSEC) { maintain_mode = dnssec_flag_to_maintain_mode[zone_desc->dnssec_mode]; } else { if(zdb_zone_has_nsec_chain(zone_pointer_out)) { maintain_mode = ZDB_ZONE_MAINTAIN_NSEC; } else if(zdb_zone_has_nsec3_optout_chain(zone_pointer_out)) { maintain_mode = ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT; } else if(zdb_zone_has_nsec3_chain(zone_pointer_out)) { maintain_mode = ZDB_ZONE_MAINTAIN_NSEC3; } } zone_set_maintain_mode(zone_pointer_out, maintain_mode); zdb_zone_set_maintained(zone_pointer_out, TRUE); if(maintain_mode != 0) { if(zone_pointer_out->progressive_signature_update.earliest_signature_expiration < MAX_S32) { database_zone_update_signatures(zone_pointer_out->origin, zone_desc, zone_pointer_out); } } } // all keys for the zone have already been loaded into the keystore // at this point, these keys have to be compared to the ones in the zone file zdb_zone_double_lock(zone_pointer_out, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); // SMART SIGNING zdb_zone_update_keystore_keys_from_zone(zone_pointer_out, ZDB_ZONE_MUTEX_DYNUPDATE); zdb_zone_double_unlock(zone_pointer_out, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); if(zdb_sanitize_is_good(zone_load_parms, real_dnssec_mode)) { // there is no need to do a maintenance log_info("zone load: %{dnsname}: maintenance not required", zone_origin(zone_desc)); } else { log_info("zone load: %{dnsname}: maintenance may be required", zone_origin(zone_desc)); zdb_zone_set_flags(zone_pointer_out, ZDB_ZONE_MAINTENANCE_ON_MOUNT); } if(zone_load_parms->state & ZDB_ZONE_LOAD_STATE_SANITIZE_SUMMARY_NSEC3_CHAIN_FIXED) { zdb_zone_set_store_clear_journal_after_mount(zone_pointer_out); } u32 now = time(NULL); zone_desc->refresh.refreshed_time = now; zone_desc->refresh.retried_time = now; // switch back with the invalid (schedule that ST) s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; log_info("zone load: '%s' loaded (%9.6fs)", zone_domain(zone_desc), load_time); zone_unlock(zone_desc, ZONE_LOCK_LOAD); return_value = SUCCESS; } else // not a DNSSEC zone { zone_pointer_out->sig_validity_regeneration_seconds = zone_desc->signature.sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S; zone_pointer_out->sig_validity_interval_seconds = zone_desc->signature.sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S; zone_pointer_out->sig_validity_jitter_seconds = zone_desc->signature.sig_validity_jitter * SIGNATURE_VALIDITY_JITTER_S; zone_unlock(zone_desc, ZONE_LOCK_LOAD); return_value = SUCCESS; } #else // !HAS_RRSIG_MANAGEMENT_SUPPORT #pragma message("EDF: zone_pointer_out->sig_validity_regeneration_seconds should not exist") zone_unlock(zone_desc, ZONE_LOCK_LOAD); return_value = SUCCESS; #endif // HAS_RRSIG_MANAGEMENT_SUPPORT #else // ! ZDB_HAS_DNSSEC_SUPPORT zone_unlock(zone_desc, ZONE_LOCK_LOAD); return_value = SUCCESS; #endif // ZDB_HAS_DNSSEC_SUPPORT } else { zone_pointer_out = NULL; s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; if(return_value == ZDB_READER_ALREADY_LOADED) { log_info("zone load: '%s' loaded already (%9.6fs)", zone_domain(zone_desc), load_time); } else { if(return_value != STOPPED_BY_APPLICATION_SHUTDOWN) { log_err("zone load: '%s' not loaded: %r (%9.6fs)", zone_domain(zone_desc), return_value, load_time); } else { log_debug("zone load: '%s' load cancelled by shutdown", zone_domain(zone_desc)); } } } if(FAIL(return_value)) { log_info("zone load: '%s' finalizing because of %r", zone_domain(zone_desc), return_value); zdb_zone_load_parms_finalize(zone_load_parms); } return return_value; } #endif ya_result database_zone_reader_axfr_open_with_fqdn(zone_reader *dst, const u8 *origin) { ya_result ret; char file_path[PATH_MAX]; if(ISOK(ret = zdb_zone_path_get_provider()( origin, file_path, sizeof(file_path) - 6, ZDB_ZONE_PATH_PROVIDER_AXFR_FILE|ZDB_ZONE_PATH_PROVIDER_MKDIR))) { log_debug("opening '%s' for reading", file_path); ret = zone_reader_axfr_open(dst, file_path); } return ret; } static ya_result database_get_ixfr_answer_type(const u8 *zone_desc_origin, const host_address *zone_desc_masters, u32 ttl, u16 soa_rdata_size, const u8* soa_rdata) { /* * Start an IXFR query */ input_stream is; output_stream os; ya_result return_value; message_data_with_buffer ixfr_query_buff; message_data *ixfr_query = message_data_with_buffer_init(&ixfr_query_buff); log_debug("zone load: %{dnsname}: incremental change query to the master", zone_desc_origin); //u16 answer_type[2]; u32 answer_serial[2]; u32 answer_idx = 0; u32 current_serial; #if DEBUG //memset(answer_type,0x5a,sizeof(answer_type)); memset(answer_serial,0x5a,sizeof(answer_serial)); memset(¤t_serial,0x5a,sizeof(current_serial)); #endif if(FAIL(return_value = rr_soa_get_serial(soa_rdata, soa_rdata_size, ¤t_serial))) { return return_value; } if(database_server_down_cache_query(zone_desc_masters)) { return_value = ECONNREFUSED; } else { if(ISOK(return_value = ixfr_start_query(zone_desc_masters, zone_desc_origin, ttl, soa_rdata, soa_rdata_size, &is, &os, ixfr_query))) { u8 record_wire[1024]; /* * Read the answer (first message anyway) * Look for the answer type in it. */ u16 query_id = message_get_id(ixfr_query); int fd = fd_input_stream_get_filedescriptor(&is); tcp_set_recvtimeout(fd, 3, 0); /* 3 seconds read timeout */ do // loop that reads TCP messages { u16 tcp_len; // no speed rate limitation from the master ! if(FAIL(return_value = readfully(fd, &tcp_len, 2))) { break; } if(return_value != 2) { if(answer_idx == 0) { if(return_value == 0) { return_value = ANSWER_UNEXPECTED_EOF; // the master closed the stream before answering anything } else { log_warn("zone load: %{dnsname}: %{hostaddr}: answered %i bytes when 2 were expected", zone_desc_origin, zone_desc_masters, return_value); } } else { if(return_value > 0) { log_warn("zone load: %{dnsname}: %{hostaddr}: answered %i bytes when either 2 or none were expected", zone_desc_origin, zone_desc_masters, return_value); } } break; } tcp_len = ntohs(tcp_len); if(FAIL(return_value = readfully(fd, message_get_buffer(ixfr_query), tcp_len))) { log_err("zone load: %{dnsname}: %{hostaddr}: failed to read next TCP message (%u bytes): %r", zone_desc_origin, zone_desc_masters, tcp_len, return_value); break; } message_set_size(ixfr_query, return_value); if(return_value < DNS_HEADER_LENGTH + 1 + 4) { return_value = ANSWER_NOT_ACCEPTABLE; log_err("zone load: %{dnsname}: %{hostaddr}: master answer is too short: %r", zone_desc_origin, zone_desc_masters, return_value); break; } /** * check the ID, check the error code * */ u16 answer_id = message_get_id(ixfr_query); if(query_id != answer_id) { return_value = ANSWER_NOT_ACCEPTABLE; log_err("zone load: %{dnsname}: %{hostaddr}: master answer ID does not match query ID (q:%hd != a:%hd)", zone_desc_origin, zone_desc_masters, query_id, answer_id); break; } if(message_get_rcode(ixfr_query) != RCODE_NOERROR) { return_value = MAKE_DNSMSG_ERROR(message_get_rcode(ixfr_query)); log_err("zone load: %{dnsname}: %{hostaddr}: master answer with error: %r", zone_desc_origin, zone_desc_masters, return_value); break; } u16 answer_count = message_get_answer_count(ixfr_query); if(answer_count == 0) { return_value = ANSWER_NOT_ACCEPTABLE; log_err("zone load: %{dnsname}: %{hostaddr}: master gave empty answer: %r", zone_desc_origin, zone_desc_masters, return_value); break; } u8 error_code = message_get_rcode(ixfr_query); if(error_code != RCODE_OK) { return_value = MAKE_DNSMSG_ERROR(error_code); // error_code is an rcode log_err("zone load: %{dnsname}: %{hostaddr}: master answered with error code: %r", zone_desc_origin, zone_desc_masters, return_value); break; } /* read the query record */ packet_unpack_reader_data pr; packet_reader_init_from_message_at(&pr, ixfr_query, DNS_HEADER_LENGTH); u16 query_count = message_get_query_count(ixfr_query); if(query_count == 1) { if(FAIL(return_value = packet_reader_read_zone_record(&pr, record_wire, sizeof(record_wire)))) { log_err("zone load: %{dnsname}: %{hostaddr}: failed to read next zone record: %r", zone_desc_origin, zone_desc_masters, return_value); break; } } else { return_value = ANSWER_NOT_ACCEPTABLE; //break; } /* read the next answer */ for(;(answer_count > 0) && (answer_idx < 2); answer_count--) { if(FAIL(return_value = packet_reader_read_record(&pr, record_wire, sizeof(record_wire)))) { log_err("zone load: %{dnsname}: %{hostaddr}: failed to read next record: %r", zone_desc_origin, zone_desc_masters, return_value); break; } u8 *p = record_wire + dnsname_len(record_wire); u16 rtype = GET_U16_AT(*p); if(rtype != TYPE_SOA) { if(answer_idx == 0) // first record should be an SOA (AXFR or IXFR) { // not an XFR log_err("zone load: %{dnsname}: %{hostaddr}: master did not answer with an XFR (expected SOA, got %{dnstype})", zone_desc_origin, zone_desc_masters, &rtype); return_value = ANSWER_NOT_ACCEPTABLE; break; } if(answer_idx == 1) // second record may be an SOA (IXFR, or a limit case of an AXFR with two SOA) { // not an IXFR (but most likely an AXFR) log_debug("zone load: %{dnsname}: %{hostaddr}: master did not answer with an IXFR (expected SOA, got %{dnstype})", zone_desc_origin, zone_desc_masters, &rtype); return_value = SUCCESS; break; } } p += 8; u16 rdata_size = ntohs(GET_U16_AT(*p)); p += 2; u32 serial; if(FAIL(return_value = rr_soa_get_serial(p, rdata_size, &serial))) { log_err("zone load: %{dnsname}: %{hostaddr}: failed to get serial from SOA record: %r", zone_desc_origin, zone_desc_masters, return_value); break; } answer_serial[answer_idx] = serial; // p += rdata_size; answer_idx++; } if((answer_idx == 1) && (answer_serial[0] == current_serial)) { break; } } while((answer_idx < 2) && ISOK(return_value)); input_stream_close(&is); output_stream_close(&os); } else { database_server_down_cache_add(zone_desc_masters); } } if(FAIL(return_value)) { log_err("zone load: %{dnsname}: %{hostaddr}: failed to get update from the master: %r", zone_desc_origin, zone_desc_masters, return_value); answer_idx = 0; } switch(answer_idx) { case 0: { /* no SOA returned */ log_info("zone load: %{dnsname}: %{hostaddr}: query to the master failed: %r", zone_desc_origin, zone_desc_masters, return_value); break; } case 1: { /* one AXFR returned */ if(serial_gt(answer_serial[0], current_serial)) { log_info("zone load: %{dnsname}: %{hostaddr}: master offers full zone transfer with serial %d", zone_desc_origin, zone_desc_masters, answer_serial[0]); return_value = TYPE_AXFR; } else { log_info("zone load: %{dnsname}: %{hostaddr}: master has the same serial %d", zone_desc_origin, zone_desc_masters, answer_serial[0]); return_value = SUCCESS; } break; } case 2: { if(answer_serial[0] == answer_serial[1]) // limit case { log_info("zone load: %{dnsname}: %{hostaddr}: master offers an empty zone with serial %d", zone_desc_origin, zone_desc_masters, answer_serial[0]); return_value = TYPE_AXFR; } else { log_info("zone load: %{dnsname}: %{hostaddr}: master offers incremental changes from serial %u to serial %d", zone_desc_origin, zone_desc_masters, answer_serial[1], answer_serial[0]); return_value = TYPE_IXFR; } break; } } return return_value; } static ya_result database_load_zone_slave(zdb *db, zone_desc_s *zone_desc, struct zdb_zone_load_parms *zone_load_parms) // returns with RC++ { #if DEBUG log_debug("database_load_zone_slave(%p,%p,%p)", db, zone_desc, zone_load_parms); #endif if(dnscore_shuttingdown()) { log_debug("zone load: %{dnsname}: slave zone load cancelled by shutdown", zone_origin(zone_desc)); zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_PROCESSED, NULL, TRUE); return STOPPED_BY_APPLICATION_SHUTDOWN; } zone_lock(zone_desc, ZONE_LOCK_LOAD); if(zone_desc->type != ZT_SLAVE) { zone_unlock(zone_desc, ZONE_LOCK_LOAD); log_debug("zone load: %{dnsname}: zone is not slave", zone_origin(zone_desc)); return ZONE_LOAD_SLAVE_TYPE_EXPECTED; } /** * Load only the SOA * ask for an IXFR * If the answer is IXFR store it as an incremental (so it will be loaded later) * If the answer is an AXFR the current files are irrelevant : destroy and load the axfr:w * */ zone_reader zr; zdb_zone *current_zone; zdb_zone *zone_pointer_out; host_address *zone_desc_masters; s64 zone_load_begin = timeus(); zone_source file_source = ZONE_SOURCE_INIT("file"); zone_source axfr_source = ZONE_SOURCE_INIT("axfr"); zone_source db_source = ZONE_SOURCE_INIT("db"); zone_source master_source = ZONE_SOURCE_INIT("master"); //bool journal_available = FALSE; bool file_opened = FALSE; zone_source *best_source = &master_source; ya_result return_value; u32 ttl = 0; //u16 rdata_size = 0; bool is_drop_before_load; bool has_file_name; u8 zone_desc_origin[MAX_DOMAIN_LENGTH]; //u8 rdata[MAX_SOA_RDATA_LENGTH]; char file_name[PATH_MAX]; char zone_desc_file_name[PATH_MAX]; zdb_zone_load_parms_init(zone_load_parms, NULL, zone_origin(zone_desc), 0); zdb_zone **zone = &zone_load_parms->out_zone; *zone = NULL; is_drop_before_load = zone_is_drop_before_load(zone_desc); zone_desc_masters = host_address_copy_list(zone_desc->masters); dnsname_copy(zone_desc_origin, zone_origin(zone_desc)); log_debug("zone load: %{dnsname}: loading slave zone", zone_desc_origin); has_file_name = (zone_desc->file_name != NULL); if(has_file_name) { strcpy_ex(zone_desc_file_name, zone_desc->file_name, sizeof(zone_desc_file_name)); } bool force_load = (zone_desc->flags & ZONE_FLAG_DROP_CURRENT_ZONE_ON_LOAD) != 0; current_zone = zdb_acquire_zone_read_from_fqdn(db, zone_desc_origin); // ACQUIRES zone_unlock(zone_desc, ZONE_LOCK_LOAD); if(!force_load) { if(current_zone != NULL) { if(!zdb_zone_invalid(current_zone)) { u32 current_serial; zdb_zone_lock(current_zone, ZDB_ZONE_MUTEX_LOAD); return_value = zdb_zone_getserial(current_zone, ¤t_serial); // zone is locked zdb_zone_unlock(current_zone, ZDB_ZONE_MUTEX_LOAD); if(ISOK(return_value)) { log_debug("zone load: %{dnsname}: in database with serial %d", zone_desc_origin, current_serial); zone_source_set(&db_source, ZONE_SOURCE_EXISTS|ZONE_SOURCE_LOADED); zone_source_set_serial(&db_source, current_serial); best_source = &db_source; } else { log_err("zone load: %{dnsname}: unable to get current serial: %r", zone_desc_origin, return_value); zdb_zone_release(current_zone); current_zone = NULL; } } else { log_debug("zone load: %{dnsname}: invalid in database", zone_desc_origin); zdb_zone_release(current_zone); current_zone = NULL; } } } #if DEBUG memset(&zr, 0x5a, sizeof(zr)); //memset(rdata, 0x5a, sizeof(rdata)); memset(file_name, 0x5a, sizeof(file_name)); #endif /* * FILE * This part is supposed to see if there is a RELEVANT text file */ if(has_file_name && (zone_desc_file_name[0] != '\0')) { snformat(file_name, sizeof(file_name), "%s%s", g_config->data_path, zone_desc_file_name); log_debug("zone load: %{dnsname}: zone file is '%s'", zone_desc_origin, file_name); if(ISOK(return_value = zone_reader_text_open(file_name, &zr))) { log_debug("zone load: %{dnsname}: checking serial in '%s'", zone_desc_origin, file_name); if(ISOK(return_value = zdb_zone_get_soa(&zr, &file_source.rdata_size, &file_source.rdata[0]))) { if(ISOK(zone_source_update_serial_from_soa(&file_source))) { zone_source_set(&file_source, ZONE_SOURCE_EXISTS | ZONE_SOURCE_LOCALE); log_debug("zone load: %{dnsname}: serial in local copy '%s' is %u", zone_desc_origin, file_name, file_source.serial); // if template_zone, the file CANNOT be written back to disk if(!zone_reader_canwriteback(&zr)) { zone_source_set(&file_source, ZONE_SOURCE_TEMPLATE); } } else { log_err("zone load: %{dnsname}: could not get the serial of the SOA from '%s': %r", zone_desc_origin, file_name, return_value); } } else { const char *message = zone_reader_get_last_error_message(&zr); if(message == NULL) { log_err("zone load: %{dnsname}: could not get SOA from '%s': %r", zone_desc_origin, file_name, return_value); } else { log_err("zone load: %{dnsname}: could not get SOA from '%s': %s: %r", zone_desc_origin, file_name, message, return_value); } } zone_reader_close(&zr); } else { if(zone_desc->type != ZT_SLAVE) { log_err("zone load: %{dnsname}: could not open zone file '%s': %r", zone_desc_origin, file_name, return_value); } else { log_debug("zone load: %{dnsname}: could not open zone file '%s': %r", zone_desc_origin, file_name, return_value); } } } else { log_debug("zone load: %{dnsname}: no file name set for zone file", zone_desc_origin); } /* * AXFR : the serial returned here does not takes the journal into account if the boolean is set to FALSE * This part is supposed to see if there is a RELEVANT axfr file */ if(ISOK(return_value = database_zone_reader_axfr_open_with_fqdn(&zr, zone_desc_origin))) { log_debug("zone load: %{dnsname}: found an AXFR image", zone_desc_origin); if(ISOK(return_value = zdb_zone_get_soa(&zr, &axfr_source.rdata_size, &axfr_source.rdata[0]))) { if(ISOK(zone_source_update_serial_from_soa(&axfr_source))) { zone_source_set(&axfr_source, ZONE_SOURCE_EXISTS | ZONE_SOURCE_LOCALE); log_debug("zone load: %{dnsname}: serial in AXFR image is %u", zone_desc_origin, axfr_source.serial); } } else { const char *message = zone_reader_get_last_error_message(&zr); if(message == NULL) { log_err("zone load: %{dnsname}: could not get SOA from AXFR file: %r", zone_desc_origin, return_value); } else { log_err("zone load: %{dnsname}: could not get SOA from AXFR file: %s: %r", zone_desc_origin, message, return_value); } } zone_reader_close(&zr); } else { log_debug("zone load: %{dnsname}: could not open AXFR file: %r", zone_desc_origin, return_value); } /* * check if both types are relevant * * disable the lowest serial or the AXFR one if they are equal * */ if(zone_source_exists(&axfr_source) || zone_source_exists(&file_source)) { /* choose the best one */ best_source = zone_source_get_best(&axfr_source, &file_source); if(!force_load) { log_debug("zone load: %{dnsname}: so far, best source is %s", zone_desc_origin, best_source->type_name); u32 serial_from = 0; u32 serial_to = 0; ya_result ret; if(ISOK(ret = journal_serial_range(zone_desc_origin, &serial_from, &serial_to))) { log_debug("zone load: %{dnsname}: journal covers serials %u to %u", zone_desc_origin, serial_from, serial_to); if(serial_ge(best_source->serial, serial_from)) { if(serial_lt(best_source->serial, serial_to)) { // the best source must be local, let's update the serial to what it should reach using the journal best_source->serial = serial_to; } else { // the journal is useless : delete it journal_truncate(zone_desc_origin); } } else { // the journal is in the future, and useless : delete it and take an axfr journal_truncate(zone_desc_origin); } } else if(ZDB_JOURNAL_SHOULD_NOT_BE_USED(ret)) { log_err("zone load: %{dnsname}: journal wasn't usable", zone_desc_origin); } // compare the db (the loaded zone) with the best source // parameter order is important, if they are equal, the left one is returned #if DEBUG log_info("zone load: %{dnsname}: best external source is %s (%i)", zone_desc_origin, best_source->type_name, best_source->serial); #endif best_source = zone_source_get_best(&db_source, best_source); #if DEBUG log_info("zone load: %{dnsname}: best overall source is %s (%i)", zone_desc_origin, best_source->type_name, best_source->serial); #endif } else { #if DEBUG log_info("zone load: %{dnsname}: forced load", zone_desc_origin); #endif } } else { log_debug("zone load: %{dnsname}: no local source available", zone_desc_origin); // note: the best_source is pointing to the master } #if DEBUG log_info("zone load: %{dnsname}: source %s: base=%i serial=%i", zone_desc_origin, file_source.type_name, file_source.base_serial, file_source.serial); log_info("zone load: %{dnsname}: source %s: base=%i serial=%i", zone_desc_origin, axfr_source.type_name, axfr_source.base_serial, axfr_source.serial); log_info("zone load: %{dnsname}: source %s: base=%i serial=%i", zone_desc_origin, db_source.type_name, db_source.base_serial, db_source.serial); log_info("zone load: %{dnsname}: source %s: base=%i serial=%i", zone_desc_origin, master_source.type_name, master_source.base_serial, master_source.serial); #endif // Retrieve the serial on the master, if we are allowed to bool dont_probe_the_primary = ((zone_desc->flags & ZONE_FLAG_NO_MASTER_UPDATES) != 0); if(!dont_probe_the_primary) { if(zone_desc->flags & ZONE_FLAG_PRIORITISE_LOCAL_SOURCE) { if(!zone_source_has_flags(&db_source, ZONE_SOURCE_EXISTS|ZONE_SOURCE_LOADED)) { if(zone_source_has_flags(best_source, ZONE_SOURCE_EXISTS | ZONE_SOURCE_LOCALE)) { dont_probe_the_primary = TRUE; } } } } if(!dont_probe_the_primary && zone_source_has_flags(best_source, ZONE_SOURCE_LOCALE)) { // a fail here would mean something horribly wrong is going on with the journal ... u32 master_serial; if(!database_server_down_cache_query(zone_desc_masters)) { if(ISOK(return_value = message_query_serial(zone_desc_origin, zone_desc_masters, &master_serial))) { log_debug("zone load: %{dnsname}: master %{hostaddr} has serial %u", zone_desc_origin, zone_desc_masters, master_serial); zone_source_set(&master_source, ZONE_SOURCE_EXISTS | ZONE_SOURCE_REMOTE); zone_source_set_serial(&master_source, master_serial); } else { log_err("zone load: %{dnsname}: unable to get the serial from the master at %{hostaddr}: %r", zone_desc_origin, zone_desc_masters, return_value); database_server_down_cache_add(zone_desc_masters); } } if(zone_source_compare(best_source, &master_source) >= 0) { // we can reach locally at least what the master is giving us log_debug("zone load: %{dnsname}: no need to download the zone from the master", zone_desc_origin); } else { // see how the master would give us the incremental changes if(ISOK(return_value = database_get_ixfr_answer_type(zone_desc_origin, zone_desc_masters, ttl, best_source->rdata_size, &best_source->rdata[0]))) { if(return_value == TYPE_AXFR) { // the zone we have is a wrong start log_debug("zone load: %{dnsname}: the master answered to the IXFR by an AXFR", zone_desc_origin); zone_source_unset(&axfr_source, ZONE_SOURCE_EXISTS); zone_source_unset(&file_source, ZONE_SOURCE_EXISTS); best_source = &master_source; xfr_delete_axfr(zone_desc_origin); journal_truncate(zone_desc_origin); } else { #if DEBUG log_info("zone load: %{dnsname}: the master answered with an IXFR", zone_desc_origin, best_source->type_name, best_source->serial); #endif } // else we did got an IXFR. Starting by loading the local zone file + journal should be more efficient. } else { log_err("zone load: %{dnsname}: IXFR query to %{hostaddr} failed with: %r", zone_desc_origin, zone_desc_masters, return_value); } } } /* * Now ask to the master for an IXFR that we will interrupt. * After a few retries, load the current zone. */ if(best_source == &axfr_source) { log_info("zone load: %{dnsname}: loading AXFR file in '%s'", zone_desc_origin, g_config->xfr_path); file_opened = TRUE; if(FAIL(return_value = database_zone_reader_axfr_open_with_fqdn(&zr, zone_desc_origin))) { log_err("zone load: %{dnsname}: unexpectedly unable to load AXFR file in '%s'", zone_desc_origin, g_config->xfr_path); zone_source_unset(&axfr_source, ZONE_SOURCE_EXISTS); file_opened = FALSE; // cleanup xfr_delete_axfr(zone_desc_origin); journal_truncate(zone_desc_origin); } } else if(best_source == &file_source) { log_info("zone load: %{dnsname}: loading file '%s'", zone_desc_origin, file_name); file_opened = TRUE; if(FAIL(return_value = zone_reader_text_open(file_name, &zr))) { log_err("zone load: %{dnsname}: unexpectedly unable to load '%s'", zone_desc_origin, file_name); zone_source_unset(&file_source, ZONE_SOURCE_EXISTS); file_opened = FALSE; } } /* * _ Open the zone file/source * _ Load the zone * (do the NSEC/NSEC3 pre-processing) * _ Close the zone file/source * _ Apply the ACLs * _ Schedule an NSEC/NSEC3 verify/update. (Here ?) */ if(file_opened) { // at this point, the file is about to be loaded. It is the right time to test the drop-before-load flag if(!((current_zone != NULL) && is_drop_before_load)) { /* Avoid cpy & cat : overrun potential */ // the journal MUST be closed, else we way have a situation where // the journal is linked to another instance of the zone #if ZDB_ZONE_HAS_JNL_REFERENCE if(zone_desc->loaded_zone != NULL) { if(zone_desc->loaded_zone->journal != NULL) { journal_close(zone_desc->loaded_zone->journal); } } #endif return_value = zdb_zone_load(db, &zr, &zone_pointer_out, zone_desc_origin, ZDB_ZONE_REPLAY_JOURNAL|ZDB_ZONE_IS_SLAVE); zone_reader_handle_error(&zr, return_value); zone_reader_close(&zr); u32 now = time(NULL); zone_lock(zone_desc, ZONE_LOCK_LOAD); // if the source base serial is different from the source serial, then the journal has been played and the zone is "dirty" if(zone_source_has_flags(best_source, ZONE_SOURCE_TEMPLATE)) { log_info("zone load: %{dnsname}: source is marked as a template (%s)", zone_desc_origin, best_source->type_name); zone_set_status(zone_desc, ZONE_STATUS_TEMPLATE_SOURCE_FILE); } zone_desc->refresh.refreshed_time = now; zone_desc->refresh.retried_time = now; if(ISOK(return_value)) { if((best_source->base_serial != best_source->serial) || (best_source == &axfr_source)) { // if we didn't load the zone file, so mark it so a dump will actually dump its content into a text zone file //zone_set_modified(zone_desc); // candidate for removal (probably, although the AXFR case must be handled) zdb_zone_set_status(zone_pointer_out, ZDB_ZONE_STATUS_MODIFIED); } zone_desc->flags &= ~ZONE_FLAG_DROP_CURRENT_ZONE_ON_LOAD; #if ZDB_HAS_ACL_SUPPORT /* * Setup the ACL filter function & configuration */ zone_pointer_out->acl = &zone_desc->ac; /* The extension points to the ACL */ zone_pointer_out->query_access_filter = acl_get_query_access_filter(&zone_desc->ac.allow_query); #endif #if DNSCORE_HAS_DNSSEC_SUPPORT /* * Setup the validity period and the jitter */ zone_pointer_out->sig_validity_interval_seconds = MAX_S32;/*zone->sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S */; zone_pointer_out->sig_validity_jitter_seconds = 0;/*zone->sig_validity_jitter * SIGNATURE_VALIDITY_JITTER_S */; #endif zone_desc->stored_serial = best_source->base_serial; *zone = zone_pointer_out; zone_unlock(zone_desc, ZONE_LOCK_LOAD); host_address_delete_list(zone_desc_masters); if(current_zone != NULL) { zdb_zone_release(current_zone); // current_zone = NULL ... } s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; log_info("zone load: %{dnsname}: loaded: %r (%9.6fs)", zone_desc_origin, return_value, load_time); return return_value; } else { switch(return_value) { case ZDB_READER_ALREADY_LOADED: { log_warn("zone load: %{dnsname}: failed because it was loaded already", zone_desc_origin); break; } case ZDB_ERROR_ICMTL_NOTFOUND: { log_info("zone load: %{dnsname}: no journal to replay", zone_desc_origin); return_value = SUCCESS; break; } case UNABLE_TO_COMPLETE_FULL_READ: { log_err("zone load: %{dnsname}: the zone file or the journal are likely corrupted: %r", zone_desc_origin, return_value); if(best_source == &file_source) { log_info("zone load: %{dnsname}: deleting local copy of the zone (%s)", zone_desc_origin, file_name); unlink(file_name); log_info("zone load: %{dnsname}: deleting journal", zone_desc_origin); journal_truncate(zone_desc_origin); //file_opened = FALSE; } else if(best_source == &axfr_source) { log_info("zone load: %{dnsname}: deleting local image of the zone", zone_desc_origin); xfr_delete_axfr(zone_desc_origin); log_info("zone load: %{dnsname}: deleting journal", zone_desc_origin); journal_truncate(zone_desc_origin); } best_source = &master_source; break; } default: { if(return_value != STOPPED_BY_APPLICATION_SHUTDOWN) { log_err("zone load: %{dnsname}: an error occurred while loading the zone or journal: %r", zone_desc_origin, return_value); } if(best_source == &file_source) { log_info("zone load: %{dnsname}: deleting local copy of the zone (%s)", zone_desc_origin, file_name); unlink(file_name); log_info("zone load: %{dnsname}: deleting journal", zone_desc_origin); journal_truncate(zone_desc_origin); //file_opened = FALSE; } else if(best_source == &axfr_source) { log_info("zone load: %{dnsname}: deleting local image of the zone", zone_desc_origin); xfr_delete_axfr(zone_desc_origin); log_info("zone load: %{dnsname}: deleting journal", zone_desc_origin); journal_truncate(zone_desc_origin); } best_source = &master_source; break; } } } zone_unlock(zone_desc, ZONE_LOCK_LOAD); } else { // the zone is loaded and is valid, we need to drop it // so we unmount it (replacing it by the dummy) // then we ask for loading it again zone_reader_close(&zr); zone_lock(zone_desc, ZONE_LOCK_LOAD); zone_set_status(zone_desc, ZONE_STATUS_LOAD_AFTER_DROP); zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_UNMOUNT, NULL, TRUE); //zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_LOAD, NULL, TRUE); zone_unlock(zone_desc, ZONE_LOCK_LOAD); host_address_delete_list(zone_desc_masters); if(current_zone != NULL) { zdb_zone_release(current_zone); // current_zone = NULL ... } s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; log_info("zone load: %{dnsname}: load requires the zone to be dropped first (%9.6fs)", zone_desc_origin, load_time); return ZDB_READER_ALREADY_LOADED; } } else if(current_zone != NULL) { zdb_zone_lock(current_zone, ZDB_ZONE_MUTEX_LOAD); #if ZDB_HAS_ACL_SUPPORT /* * Setup the ACL filter function & configuration */ current_zone->acl = &zone_desc->ac; /* The extension points to the ACL */ current_zone->query_access_filter = acl_get_query_access_filter(&zone_desc->ac.allow_query); #endif #if DNSCORE_HAS_DNSSEC_SUPPORT /* * Setup the validity period and the jitter (slave) */ current_zone->sig_validity_interval_seconds = MAX_S32;/*zone->sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S */; current_zone->sig_validity_jitter_seconds = 0;/*zone->sig_validity_jitter * SIGNATURE_VALIDITY_JITTER_S */; #endif zdb_zone_unlock(current_zone, ZDB_ZONE_MUTEX_LOAD); *zone = current_zone; s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; log_info("zone load: %{dnsname}: keeping the already loaded zone (%9.6fs)", zone_desc_origin, load_time); return_value = SUCCESS; current_zone = NULL; } if(current_zone != NULL) { zdb_zone_release(current_zone); current_zone = NULL; } if(best_source == &master_source) { /** * Set a placeholder zone. Marked as invalid. * * The AXFR mechanism is as follow: * * There is MUST ALWAYS be a zone for an existing config. * That zone can be a fake one marked as invalid, or a real one that requires some processing. * Here we have a fake one so it will be straightforward: * The fake is set in place. * The AXFR will be tried and made. * When it succeeds, since the zone is invalid, the AXFR will be loaded and will be scheduled for a swap & destroy * On other cases, the AXFR would first be tested for serial THEN ignored and the invalid zone would be scheduled for a swap-back * OR * the invalid zone will be scheduled for a multiple-stage delete (ST) * then the AXFR will be loaded and will be scheduled for a swap & destroy * */ s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; if((zone_desc->flags & ZONE_FLAG_NO_MASTER_UPDATES) == 0) { if(!file_opened) { log_info("zone load: %{dnsname}: asking for an AXFR from %{hostaddr} (%9.6fs)", zone_desc_origin, zone_desc_masters, load_time); database_zone_axfr_query(zone_desc_origin); } else { time_t axfr_epoch = time(NULL); axfr_epoch += g_config->axfr_retry_delay; axfr_epoch += rand() % (g_config->axfr_retry_jitter|1); log_info("zone load: %{dnsname}: will ask for an AXFR from %{hostaddr} (%9.6fs) at %T", zone_desc_origin, zone_desc_masters, load_time, axfr_epoch); database_zone_axfr_query_at(zone_desc_origin, axfr_epoch); } } else { log_info("zone load: %{dnsname}: prevented by configuration to ask an AXFR from %{hostaddr} (%9.6fs)", zone_desc_origin, zone_desc_masters, load_time); } return_value = ZRE_NO_VALID_FILE_FOUND; if(*zone != NULL) { zdb_zone_release(*zone); *zone = NULL; } } else { s64 zone_load_end = timeus(); double load_time = zone_load_end - zone_load_begin; load_time /= ONE_SECOND_US_F; log_info("zone load: %{dnsname}: load done: %r (%9.6fs)", zone_desc_origin, return_value, load_time); } host_address_delete_list(zone_desc_masters); return return_value; } /** * * The thread loads the zone in the background then notifies the service that the zone has been loaded (or failed to load) * * @param parms * @return */ static void* database_service_zone_load_thread(void *parms) { database_service_zone_load_parms_s *database_zone_load_parms = (database_service_zone_load_parms_s *)parms; const u32 must_be_off = ZONE_STATUS_DROP | ZONE_STATUS_DROPPING | \ ZONE_STATUS_SAVING_ZONE_FILE | ZONE_STATUS_SAVING_AXFR_FILE | \ ZONE_STATUS_SIGNATURES_UPDATING | ZONE_STATUS_DYNAMIC_UPDATE | \ ZONE_STATUS_DYNAMIC_UPDATING| ZONE_STATUS_LOAD_AFTER_DROP; zone_desc_s *zone_desc = database_zone_load_parms->zone_desc; #if DEBUG log_debug1("database_service_zone_load_thread(%{dnsname}@%p=%i)", zone_origin(zone_desc), zone_desc, zone_desc->rc); #endif yassert(zone_desc != NULL); zone_lock(zone_desc, ZONE_LOCK_LOAD); if((zone_get_status(zone_desc) & must_be_off) != 0) { log_err("zone load: conflicting status: %08x instead of 0", (zone_get_status(zone_desc) & must_be_off)); database_zone_load_parms_free(database_zone_load_parms); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return NULL; } zone_set_status(zone_desc, ZONE_STATUS_LOADING); zone_unlock(zone_desc, ZONE_LOCK_LOAD); struct zdb_zone_load_parms zone_load_parms; memset(&zone_load_parms, 0, sizeof(zone_load_parms)); ya_result return_code = database_zone_load_parms->loader(database_zone_load_parms->db, zone_desc, &zone_load_parms); // RC = 1 // notify the fact that the zone has been loaded (or not) if(ISOK(return_code)) { zdb_zone *zone = zdb_zone_load_parms_zone_detach(&zone_load_parms); yassert(zone != NULL); // in the zone settings, replace the one in the loaded field by the new one zone_lock(zone_desc, ZONE_LOCK_LOAD); zdb_zone *old_zone = zone_set_loaded_zone(zone_desc, zone); // RC = 1 ++ (2) zone_unlock(zone_desc, ZONE_LOCK_LOAD); if(old_zone == zone) { log_debug7("%{dnsname}@%p: zone@%p was already loaded", zone_origin(zone_desc), zone_desc, zone); return_code = 0; } else { log_debug7("%{dnsname}@%p: loaded zone@%p (was %p)", zone_origin(zone_desc), zone_desc, zone, old_zone); return_code = 1; } if(old_zone != NULL) { zdb_zone_release(old_zone); old_zone = NULL; } zone_lock(zone_desc, ZONE_LOCK_LOAD); zone_clear_status(zone_desc, ZONE_STATUS_LOAD|ZONE_STATUS_LOADING|ZONE_STATUS_DOWNLOADED|ZONE_STATUS_PROCESSING); zone_unlock(zone_desc, ZONE_LOCK_LOAD); database_fire_zone_loaded(zone_desc, zone, return_code); /// @note 20190917 edf -- Patch submitted through github by kolbma /// This avoids a crash that would happen if the loader would /// returns a successful code but with a NULL zone. /// Altough the real issue is in the loader, keeping this safeguard here is worth it. if(zone != NULL) { zdb_zone_release(zone); } zdb_zone_load_parms_finalize(&zone_load_parms); #if DEBUG zone = NULL; #endif } else { if(!((return_code == ZRE_NO_VALID_FILE_FOUND) && (zone_desc->type == ZT_SLAVE))) { if(return_code != STOPPED_BY_APPLICATION_SHUTDOWN) { log_err("zone load: %{dnsname}: error loading: %r", zone_origin(zone_desc), return_code); } else { log_debug("zone load: %{dnsname}: loading cancelled by shutdown", zone_origin(zone_desc)); } } else { log_info("zone load: %{dnsname}: slave zone requires download from the master", zone_origin(zone_desc)); } #if DEBUG if(zone_load_parms.out_zone != NULL) { log_err("zone load: %{dnsname}: zone_load_parms is not expected to be set when an error is returned", zone_origin(zone_desc)); } #endif zone_lock(zone_desc, ZONE_LOCK_LOAD); zone_clear_status(zone_desc, ZONE_STATUS_LOAD|ZONE_STATUS_LOADING|ZONE_STATUS_DOWNLOADED|ZONE_STATUS_PROCESSING); zone_unlock(zone_desc, ZONE_LOCK_LOAD); database_fire_zone_loaded(zone_desc, NULL, return_code); zdb_zone_load_parms_finalize(&zone_load_parms); } database_zone_load_parms_free(database_zone_load_parms); zone_release(zone_desc); return NULL; } ya_result database_service_zone_load(zone_desc_s *zone_desc) { if(zone_desc == NULL) { log_err("database_service_zone_load(NULL)"); return UNEXPECTED_NULL_ARGUMENT_ERROR; } log_debug1("database_service_zone_load(%{dnsname}@%p=%i)", zone_origin(zone_desc), zone_desc, zone_desc->rc); log_debug1("database_service_zone_load: locking zone '%{dnsname}' for loading", zone_origin(zone_desc)); if(FAIL(zone_lock(zone_desc, ZONE_LOCK_LOAD))) { log_err("database_service_zone_load: failed to lock zone settings for '%{dnsname}'", zone_origin(zone_desc)); return INVALID_STATE_ERROR; // this happens when the zone is on its way out } const u8 *origin = zone_origin(zone_desc); /* * Invalidate the zone * Empty the current zone if any */ /* * If the zone descriptor (config) exists and it can be locked by the loader ... */ // locks the descriptor with the loader identity if(zone_get_status(zone_desc) & (ZONE_STATUS_LOAD|ZONE_STATUS_LOADING)) { // already loading #if DEBUG zone_desc_log(MODULE_MSG_HANDLE, MSG_DEBUG1, zone_desc, "database_service_zone_load"); #endif log_err("database_service_zone_load: '%{dnsname}' already loading", origin); zone_unlock(zone_desc, ZONE_LOCK_LOAD); return ERROR; } zdb *db = g_config->database; // wait #if ZDB_HAS_MASTER_SUPPORT if(zone_desc->type == ZT_MASTER) { /* * load master ? * => load the file * => schedule the xchg with the invalidated zone */ zone_set_status(zone_desc, ZONE_STATUS_LOAD); zone_clear_status(zone_desc, ZONE_STATUS_STARTING_UP); zone_acquire(zone_desc); database_service_zone_load_parms_s *database_zone_load_parms = database_zone_load_parms_alloc(db, zone_desc, database_load_zone_master); database_service_zone_load_queue_thread(database_service_zone_load_thread, database_zone_load_parms, NULL, "database_zone_load_thread"); } else #endif if(zone_desc->type == ZT_SLAVE) { /* * load slave * * if no file/axfr is available => axfr (responsible to requeue the load) and continue * * if file/axfr is available => load the file/axfr * * => schedule the xchg with the invalidated zone * */ zone_set_status(zone_desc, ZONE_STATUS_LOAD); zone_clear_status(zone_desc, ZONE_STATUS_STARTING_UP|ZONE_STATUS_DOWNLOADED); zone_acquire(zone_desc); database_service_zone_load_parms_s *database_zone_load_parms = database_zone_load_parms_alloc(db, zone_desc, database_load_zone_slave); database_service_zone_load_queue_thread(database_service_zone_load_thread, database_zone_load_parms, NULL, "database_zone_load_thread"); } else /* not master nor slave */ { /* other types */ log_err("zone load: unknown zone type"); zone_clear_status(zone_desc, ZONE_STATUS_LOAD|ZONE_STATUS_LOADING|ZONE_STATUS_DOWNLOADED|ZONE_STATUS_PROCESSING); } log_debug1("database_service_zone_load: unlocking zone '%{dnsname}' for loading", origin); zone_unlock(zone_desc, ZONE_LOCK_LOAD); return SUCCESS; } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-mount.c0000644000000000000000000000013214505005533024352 xustar000000000000000030 mtime=1695812443.325994835 30 atime=1695812445.781029996 30 ctime=1695812495.631743958 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-mount.c0000664000374500037450000001715514505005533024325 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include #include #include #include "database-service.h" #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_DNSSEC_SUPPORT #include "database-service-zone-resignature.h" #endif #include "notify.h" #define MODULE_MSG_HANDLE g_server_logger void database_service_zone_mount(zone_desc_s *zone_desc) { ya_result return_value; #if DEBUG log_debug("database_service_zone_mount(%{dnsname}@%p=%i)", zone_origin(zone_desc), zone_desc, zone_desc->rc); #endif if(zone_desc == NULL) { log_err("zone NULL: tried to mount NULL zone"); return; } log_debug1("%{dnsname}: locking for mounting (database_service_zone_mount)", zone_origin(zone_desc)); if(FAIL(return_value = zone_lock(zone_desc, ZONE_LOCK_MOUNT))) { log_err("%{dnsname}: failed to lock zone settings for (database_service_zone_mount)", zone_origin(zone_desc)); return; } zone_set_status(zone_desc, ZONE_STATUS_MOUNTING); zdb_zone *zone = zone_get_loaded_zone(zone_desc); // RC++, because we get to keep a reference if(zone == NULL) { log_err("%{dnsname}: no zone loaded that could be mounted", zone_origin(zone_desc)); zone_clear_status(zone_desc, ZONE_STATUS_STARTING_UP|ZONE_STATUS_MOUNTING|ZONE_STATUS_PROCESSING); database_fire_zone_mounted(zone_desc, NULL, ERROR); zone_unlock(zone_desc, ZONE_LOCK_MOUNT); return; } log_info("%{dnsname}: mount", zone_origin(zone_desc)); /* * If the zone descriptor (config) exists and it can be locked by the loader ... */ u32 now = time(NULL); zone_desc->refresh.refreshed_time = now; zone_desc->refresh.retried_time = now; log_debug1("%{dnsname}: locking zone for mounting (database_service_zone_mount)", zone->origin); // locks the descriptor with the loader identity #if DEBUG zone_desc_log(MODULE_MSG_HANDLE, MSG_DEBUG1, zone_desc, "database_service_zone_mount"); #endif zdb *db = g_config->database; #if DNSCORE_HAS_ACL_SUPPORT zone->acl = &zone_desc->ac; zone->query_access_filter = acl_get_query_access_filter(&zone_desc->ac.allow_query); #endif zdb_zone *old_zone = zdb_set_zone(db, zone); // RC++, because the zone is put into the database log_debug2("%{dnsname}: previous zone @%p, new zone @%p", zone->origin, old_zone, zone); bool send_notify_to_slaves = TRUE; if(old_zone != NULL) { if(zone != old_zone) { // there is already a different zone mounted log_debug2("%{dnsname}: locking previous zone to invalidate and swap", zone->origin); zdb_zone_lock(old_zone, ZDB_ZONE_MUTEX_REPLACE); // set old zone as invalid zdb_zone_set_invalid(old_zone); zdb_zone_unlock(old_zone, ZDB_ZONE_MUTEX_REPLACE); log_debug2("%{dnsname}: unlocking previous zone", zone->origin); } else { log_debug2("%{dnsname}: tried to mount a zone in place of itself (%p is %p) (database_service_zone_mount)", zone->origin, old_zone, zone); send_notify_to_slaves = FALSE; } zdb_zone_release(old_zone); } // if(send_notify_to_slaves) { #if ZDB_HAS_MASTER_SUPPORT if(zone_desc->type == ZT_MASTER) { log_debug("%{dnsname}: will notify slaves", zone_origin(zone_desc)); notify_slaves(zone_origin(zone_desc)); // RC++ } else #endif if(zone_desc->type == ZT_SLAVE) { log_debug("%{dnsname}: will notify explicit slaves", zone_origin(zone_desc)); if(notify_has_candidates_for_zone(zone_desc)) { notify_slaves(zone_origin(zone_desc)); // RC++ } if(((zone_desc->flags & ZONE_FLAG_NO_MASTER_UPDATES) == 0)) { if(zone_desc->masters != NULL) { log_debug("%{dnsname}: querying changes to the master at %{hostaddr}", zone_origin(zone_desc), zone_desc->masters); database_zone_ixfr_query(zone_origin(zone_desc)); } else { log_err("%{dnsname}: no master set", zone_origin(zone_desc)); } } } // else nothing to do } else { log_debug("%{dnsname}: no need to send notify to slaves", zone_origin(zone_desc)); } #if DNSCORE_HAS_DNSSEC_SUPPORT && DNSCORE_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT if(zone_desc->type == ZT_MASTER) { if(zone_maintains_dnssec(zone_desc)) { if(zdb_zone_is_maintained(zone)) { database_service_zone_dnskey_set_alarms(zone); } } } #endif zone_clear_status(zone_desc, ZONE_STATUS_STARTING_UP|ZONE_STATUS_MOUNTING|ZONE_STATUS_PROCESSING); database_fire_zone_mounted(zone_desc, zone, SUCCESS); // RC++ zdb_zone_release(zone); // RC-- zone = NULL; log_debug1("%{dnsname}: unlocking zone for mounting (database_service_zone_mount)", zone_origin(zone_desc)); zone_unlock(zone_desc, ZONE_LOCK_MOUNT); } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-store.c0000644000000000000000000000013214505005533024344 xustar000000000000000030 mtime=1695812443.522997656 30 atime=1695812445.784030039 30 ctime=1695812495.633743987 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-store.c0000664000374500037450000003430114505005533024307 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include #include #include #define ZDB_JOURNAL_CODE 1 #include #include "zone.h" #include "server.h" #include "database-service.h" #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT #include "database-service-zone-resignature.h" #include "database-service-zone-download.h" #endif #define MODULE_MSG_HANDLE g_server_logger /** * Saves a zone in the current thread using the provided locks (0 meaning: do not try to lock) * Not locking puts the responsibility of the lock to the caller as having this code running * without any lock whatsoever on the descriptor/zone will give undefined results, a.k.a : crash. * * @param zone_desc * @param desclockowner * @param zonelockowner * @return */ ya_result database_service_zone_store_ex(zone_desc_s *zone_desc, u8 desclockowner, u8 zonelockowner, u8 flags) { // not implemented yet log_debug("zone store: %{dnsname}@%p#%i", zone_origin(zone_desc), zone_desc, zone_desc->rc); // for all modified zones descriptors // if the file source is defined AND the source is not a template // if the zone is valid // save the text representation of the zone to the disk //bool must_be_on = ZONE_STATUS_READONLY|ZONE_STATUS_MODIFIED; bool save_unmodified = flags & DATABASE_SERVICE_ZONE_SAVE_UNMODIFIED; bool will_resume_maintenance = FALSE; // bool ignore_shutdown = flags & DATABASE_SERVICE_ZONE_SAVE_IGNORE_SHUTDOWN; const u32 must_be_off = ZONE_STATUS_TEMPLATE_SOURCE_FILE | ZONE_STATUS_STARTING_UP | ZONE_STATUS_LOADING | ZONE_STATUS_MOUNTING | ZONE_STATUS_UNMOUNTING | ZONE_STATUS_DROPPING | ZONE_STATUS_SAVING_ZONE_FILE | ZONE_STATUS_SAVING_AXFR_FILE | ZONE_STATUS_SIGNATURES_UPDATING | ZONE_STATUS_DYNAMIC_UPDATING | /*ZONE_STATUS_DOWNLOADING_XFR_FILE |*/ ZONE_STATUS_UNREGISTERING; if(desclockowner != 0) { zone_lock(zone_desc, desclockowner); } if(zone_desc->file_name == NULL) { log_notice("zone store: %{dnsname}: has no source file set", zone_origin(zone_desc)); zone_clear_status(zone_desc, ZONE_STATUS_SAVETO_ZONE_FILE|ZONE_STATUS_SAVING_ZONE_FILE|ZONE_STATUS_PROCESSING); if(desclockowner != 0) { zone_unlock(zone_desc, desclockowner); } database_fire_zone_processed(zone_desc); zone_release(zone_desc); return INVALID_STATE_ERROR; } if((zone_get_status(zone_desc) & ZONE_STATUS_TEMPLATE_SOURCE_FILE) != 0) { log_notice("zone store: %{dnsname}: source is a template", zone_origin(zone_desc)); zone_clear_status(zone_desc, ZONE_STATUS_SAVETO_ZONE_FILE|ZONE_STATUS_SAVING_ZONE_FILE|ZONE_STATUS_PROCESSING); if(desclockowner != 0) { zone_unlock(zone_desc, desclockowner); } database_fire_zone_processed(zone_desc); zone_release(zone_desc); return INVALID_STATE_ERROR; } if((zone_get_status(zone_desc) & must_be_off) != 0) { log_info("zone store: %{dnsname}: cannot be stored at this time (%08x & %08x = %08x)", zone_origin(zone_desc), zone_get_status(zone_desc), must_be_off, zone_get_status(zone_desc) & must_be_off); zone_clear_status(zone_desc, ZONE_STATUS_SAVETO_ZONE_FILE|ZONE_STATUS_SAVING_ZONE_FILE|ZONE_STATUS_PROCESSING); if(desclockowner != 0) { zone_unlock(zone_desc, desclockowner); } database_fire_zone_processed(zone_desc); zone_release(zone_desc); return INVALID_STATE_ERROR; } zone_set_status(zone_desc, ZONE_STATUS_SAVING_ZONE_FILE); zdb *db = g_config->database; zdb_zone *zone; if(zonelockowner != 0) { zone = zdb_acquire_zone_read_lock_from_fqdn(db, zone_origin(zone_desc), zonelockowner); // ACQUIRES & LOCKS } else { zone = zdb_acquire_zone_read_from_fqdn(db, zone_origin(zone_desc)); // ACQUIRES } ya_result ret = ZDB_ERROR_ZONE_NOT_IN_DATABASE; // no zone acquired (could not acquire zone error code) if(zone != NULL) { if(!save_unmodified) { bool modified = zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_MODIFIED; if(!modified) { if(zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_NEED_REFRESH) { if(!dnscore_shuttingdown()) { log_info("zone store: %{dnsname}: will resume interrupted transfer", zone_origin(zone_desc)); database_service_zone_ixfr_query(zone->origin); } zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_NEED_REFRESH); } if(zonelockowner != 0) { zdb_zone_release_unlock(zone, zonelockowner); } else { zdb_zone_release(zone); } log_debug("zone store: %{dnsname}: hasn't been modified", zone_origin(zone_desc)); if((zone_get_status(zone_desc) & ZONE_STATUS_MUST_CLEAR_JOURNAL) != 0) { log_info("zone store: %{dnsname}: clearing journal", zone_origin(zone_desc)); journal_truncate(zone_origin(zone_desc)); } zone_clear_status(zone_desc, ZONE_STATUS_SAVETO_ZONE_FILE|ZONE_STATUS_SAVING_ZONE_FILE|ZONE_STATUS_PROCESSING|ZONE_STATUS_MUST_CLEAR_JOURNAL); if(desclockowner != 0) { zone_unlock(zone_desc, desclockowner); } database_fire_zone_processed(zone_desc); zone_release(zone_desc); return SUCCESS; } } if(zdb_zone_isvalid(zone)) { char file_name[PATH_MAX]; snformat(file_name, sizeof(file_name), "%s/%s", g_config->data_path, zone_desc->file_name); log_info("zone store: %{dnsname}: storing zone to file '%s'", zone_origin(zone_desc), file_name); ret = zdb_zone_write_text_file(zone, file_name, flags); // zone is locked, clears the modified flag when successful if(ISOK(ret)) { zdb_zone_getserial(zone, &zone_desc->stored_serial); // zone is locked bool clear_journal = zone_get_status(zone_desc) & ZONE_STATUS_MUST_CLEAR_JOURNAL; if(clear_journal) { log_info("zone store: %{dnsname}: clearing journal", zone_origin(zone_desc)); journal_truncate(zone_origin(zone_desc)); zone_clear_status(zone_desc, ZONE_STATUS_MUST_CLEAR_JOURNAL); } log_info("zone store: %{dnsname}: stored zone to file '%s'", zone_origin(zone_desc), file_name); if(zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_NEED_REFRESH) { log_info("zone store: %{dnsname}: will resume interrupted transfer", zone_origin(zone_desc)); database_service_zone_ixfr_query(zone->origin); zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_NEED_REFRESH); } } else { if(ret != STOPPED_BY_APPLICATION_SHUTDOWN) { log_err("zone store: %{dnsname}: failed to store as '%s': %r", zone_origin(zone_desc), file_name, ret); } else { log_debug("zone store: %{dnsname}: cancelled by shutdown", zone_origin(zone_desc)); } } } else { log_err("zone store: %{dnsname}: cannot be stored because its current instance in the database is marked as invalid", zone_origin(zone_desc)); } #if ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT if(ISOK(ret)) { if(zdb_zone_is_maintenance_paused(zone)) // not locking { log_info("zone store: %{dnsname}: resuming zone maintenance", zone_origin(zone_desc)); zdb_zone_set_maintenance_paused(zone, FALSE); // light locking will_resume_maintenance = TRUE; } } #endif if(zonelockowner != 0) { zdb_zone_release_unlock(zone, zonelockowner); } else { zdb_zone_release(zone); } #if DEBUG zone = NULL; #endif } // if zone != NULL ... // zdb_unlock(db, ZDB_MUTEX_READER); zone_clear_status(zone_desc, ZONE_STATUS_SAVETO_ZONE_FILE|ZONE_STATUS_SAVING_ZONE_FILE|ZONE_STATUS_PROCESSING); #if ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT if(will_resume_maintenance) { ya_result internal_ret; if(ISOK(internal_ret = database_service_zone_dnssec_maintenance_lock_for(zone_desc, desclockowner))) { log_info("zone store: %{dnsname}: resuming zone maintenance", zone_origin(zone_desc)); } else { log_info("zone store: %{dnsname}: failed to resume zone maintenance: %r", zone_origin(zone_desc), internal_ret); } } #endif if(desclockowner != 0) { zone_unlock(zone_desc, desclockowner); // desclockowner = 0; /// @note the zone_desc is not locked anymore after this point } database_fire_zone_processed(zone_desc); zone_release(zone_desc); return ret; } static void* database_service_zone_store_thread(void *params) { zone_desc_s *zone_desc = (zone_desc_s*)params; database_service_zone_store_ex(zone_desc, ZONE_LOCK_SAVE, ZDB_ZONE_MUTEX_SIMPLEREADER, DATABASE_SERVICE_ZONE_SAVE_DEFAULTS); return NULL; } /** * * Triggers the standard background save of a zone * * @param zone_desc * @return */ ya_result database_service_zone_store(zone_desc_s *zone_desc) { if(zone_desc == NULL) { log_err("database_service_zone_store(NULL)"); return ERROR; } const u8 *origin = zone_origin(zone_desc); log_debug1("database_service_zone_store(%{dnsname}@%p=%i)", origin, zone_desc, zone_desc->rc); log_debug1("database_service_zone_store: locking zone '%{dnsname}' for saving", zone_origin(zone_desc)); if(FAIL(zone_lock(zone_desc, ZONE_LOCK_SAVE))) { log_err("database_service_zone_store: failed to lock zone settings for '%{dnsname}'", origin); return ERROR; } log_debug("zone store: %{dnsname}", origin); /* * Invalidate the zone * Empty the current zone if any */ /* * If the zone descriptor (config) exists and it can be locked by the saveer ... */ // locks the descriptor with the saveer identity if(zone_get_status(zone_desc) & (ZONE_STATUS_SAVETO_ZONE_FILE|ZONE_STATUS_SAVING_ZONE_FILE)) { // already saving #if DEBUG zone_desc_log(MODULE_MSG_HANDLE, MSG_DEBUG1, zone_desc, "database_service_zone_store"); #endif log_debug("database_service_zone_store: '%{dnsname}' already busy storing", origin); zone_unlock(zone_desc, ZONE_LOCK_SAVE); return ERROR; } zone_set_status(zone_desc, ZONE_STATUS_SAVETO_ZONE_FILE); zone_acquire(zone_desc); database_service_zone_store_queue_thread(database_service_zone_store_thread, zone_desc, NULL, "database_zone_store_thread"); log_debug1("database_service_zone_store: unlocking zone '%{dnsname}' for storage", origin); zone_unlock(zone_desc, ZONE_LOCK_SAVE); return SUCCESS; } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-unfreeze.c0000644000000000000000000000013114505005533025032 xustar000000000000000029 mtime=1695812443.49599727 30 atime=1695812445.783030024 30 ctime=1695812495.635744015 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-unfreeze.c0000664000374500037450000001074714505005533025006 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include "zone.h" #include "server.h" #define MODULE_MSG_HANDLE g_server_logger /**********************************************************************************************************************/ void database_service_zone_unfreeze(zone_desc_s *zone_desc) { ya_result return_value; #if DEBUG log_debug("database_service_zone_unfreeze(%{dnsname}@%p=%i)", zone_origin(zone_desc), zone_desc, zone_desc->rc); #endif if(zone_desc == NULL) { log_err("zone freeze: NULL zone"); return; } log_debug1("database_service_zone_unfreeze: locking zone '%{dnsname}' for unfreezing", zone_origin(zone_desc)); if(FAIL(return_value = zone_lock(zone_desc, ZONE_LOCK_UNFREEZE))) { log_err("database_service_zone_unfreeze: failed to lock zone settings for '%{dnsname}'", zone_origin(zone_desc)); return; } zdb_zone *zone = zone_get_loaded_zone(zone_desc); // RC++ if(zone == NULL) { log_err("zone freeze: no zone loaded for '%{dnsname}'", zone_origin(zone_desc)); zone_clear_status(zone_desc, ZONE_STATUS_PROCESSING); log_debug1("database_service_zone_unfreeze: unlocking zone '%{dnsname}' for unfreezing", zone_origin(zone_desc)); zone_unlock(zone_desc, ZONE_LOCK_UNFREEZE); return; } // This REALLY is the simple reader lock. This operation does not interfere // with readers, only with writers. There is no point preventing queries // in the database while setting the zone read-only. zdb_zone_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); if(!zdb_zone_is_frozen(zone)) { log_warn("zone freeze: %{dnsname} already unfrozen", zone->origin); } zdb_zone_clear_frozen(zone); zdb_zone_release_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); log_info("zone unfreeze: %{dnsname}", zone_origin(zone_desc)); zone_clear_status(zone_desc, ZONE_STATUS_FROZEN|ZONE_STATUS_PROCESSING); log_debug1("database_service_zone_unfreeze: unlocking zone '%{dnsname}' for unfreezing", zone_origin(zone_desc)); zone_unlock(zone_desc, ZONE_LOCK_UNFREEZE); } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-unload.c0000644000000000000000000000013214505005533024472 xustar000000000000000030 mtime=1695812443.511997499 30 atime=1695812445.783030024 30 ctime=1695812495.637744044 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-unload.c0000664000374500037450000001446714505005533024450 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include "database-service.h" #define MODULE_MSG_HANDLE g_server_logger /**********************************************************************************************************************/ #define DSZZUPRM_TAG 0x4d5250555a5a5344 struct database_service_zone_unload_parms_s { zone_desc_s *zone_desc; zdb_zone *zone; }; typedef struct database_service_zone_unload_parms_s database_service_zone_unload_parms_s; static void* database_service_zone_unload_thread(void *parms) { database_service_zone_unload_parms_s *database_service_zone_unload_parms = (database_service_zone_unload_parms_s*)parms; zdb_zone *zone = database_service_zone_unload_parms->zone; u8 origin[MAX_DOMAIN_LENGTH]; if(zone->origin != NULL) { dnsname_copy(origin, zone->origin); } else { memcpy(origin, "\004NULL", 6); } log_debug("database-service: %{dnsname}: releasing old instance of zone", origin); log_debug7("database-service: %{dnsname}: rc=%i", origin, zone->rc); zdb_zone_release(zone); zone = NULL; zdb_zone_garbage_run(); zone_release(database_service_zone_unload_parms->zone_desc); free(database_service_zone_unload_parms); return NULL; } /** * Replace a zone by another * The replaced zone will be destroyed as soon as it is not referenced yet * @param zone_desc * @param zone the zone to unload, note that it has been acquired for the call and must be released */ void database_service_zone_unload(zone_desc_s *zone_desc, zdb_zone *zone) { log_debug("database_service_zone_unload(%{dnsname}@%p=%i,%{dnsname})", zone_origin(zone_desc), zone_desc, zone_desc->rc, (zone != NULL)?zone->origin:(const u8*)"\004NULL"); zdb_zone *work_zone = NULL; if(zone != NULL) { work_zone = zone; // zone will be released by the thread zone_lock(zone_desc, ZONE_LOCK_UNLOAD); if(zone == zone_desc->loaded_zone) // UNLOAD { log_warn("database_service_zone_unload: forced unload of %p = loaded_zone", zone); log_debug7("database_service_zone_unload: %{dnsname}@%p: loaded_zone@%p (was %p)", zone_origin(zone_desc), zone_desc, NULL, zone_desc->loaded_zone); // UNLOAD zdb_zone_release(zone_desc->loaded_zone); zone_desc->loaded_zone = NULL; // UNLOAD } // else the zone in the descriptor has changed : don't touch it zone_unlock(zone_desc, ZONE_LOCK_UNLOAD); } else { zone_lock(zone_desc, ZONE_LOCK_UNLOAD); work_zone = zone_desc->loaded_zone; // UNLOAD log_debug7("database_service_zone_unload: %{dnsname}@%p: loaded_zone@%p (was %p)", zone_origin(zone_desc), zone_desc, NULL, zone_desc->loaded_zone); // UNLOAD if(zone_desc->loaded_zone != NULL) { // the zone we are about to unload will be released by the thread //zdb_zone_release(zone_desc->loaded_zone); zone_desc->loaded_zone = NULL; // UNLOAD } zone_unlock(zone_desc, ZONE_LOCK_UNLOAD); } if(work_zone != NULL) { database_service_zone_unload_parms_s *parm; MALLOC_OBJECT_OR_DIE(parm, database_service_zone_unload_parms_s, DSZZUPRM_TAG); parm->zone_desc = zone_desc; parm->zone = work_zone; zone_acquire(zone_desc); database_service_zone_unload_queue_thread(database_service_zone_unload_thread, parm, NULL, "database_service_zone_unload_thread"); } else { log_debug7("database_service_zone_unload: %{dnsname}@%p: nothing to unload", zone_origin(zone_desc), zone_desc); } zone_lock(zone_desc, ZONE_LOCK_UNLOAD); zone_clear_status(zone_desc, ZONE_STATUS_PROCESSING); zone_unlock(zone_desc, ZONE_LOCK_UNLOAD); } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-unmount.c0000644000000000000000000000013214505005533024715 xustar000000000000000030 mtime=1695812443.534997828 30 atime=1695812445.784030039 30 ctime=1695812495.639744073 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-unmount.c0000664000374500037450000001177314505005533024670 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include #include #include #include "database-service.h" #include "notify.h" #define MODULE_MSG_HANDLE g_server_logger void database_service_zone_unmount(zone_desc_s *zone_desc) { ya_result return_value; if(zone_desc == NULL) { log_err("database_service_zone_unmount(NULL)"); return; } log_debug1("database_service_zone_unmount(%{dnsname}@%p=%i)", zone_origin(zone_desc), zone_desc, zone_desc->rc); log_debug1("database_service_zone_unmount: locking zone '%{dnsname}' for unmounting", zone_origin(zone_desc)); // locks the descriptor with the loader identity if(FAIL(return_value = zone_lock(zone_desc, ZONE_LOCK_UNMOUNT))) { log_err("database_service_zone_unmount: failed to lock zone settings for '%{dnsname}'", zone_origin(zone_desc)); return; } const u8 *origin = zone_origin(zone_desc); log_info("zone unmount: %{dnsname}", origin); zone_set_status(zone_desc, ZONE_STATUS_UNMOUNTING); /* * Find the zone * * Invalidate the zone * * Set the zone pointer in the label to NULL * * Queue the zone for unload */ zdb *db; notify_clear(zone_origin(zone_desc)); #if DEBUG zone_desc_log(MODULE_MSG_HANDLE, MSG_DEBUG1, zone_desc, "database_service_zone_unmount"); #endif db = g_config->database; zdb_zone *old_zone = zdb_remove_zone_from_dnsname(db, origin); if(old_zone != NULL) { log_debug2("database_service_zone_unmount: zone %{dnsname} @%p removed from the database", origin, old_zone); database_zone_unload(old_zone); // RC should mostly be one at this point zdb_zone_release(old_zone); // it's now the responsibility of database_zone_unload to drop the zone } else { log_debug2("database_service_zone_unmount: zone %{dnsname} not found in the database", origin); } if((zone_get_status(zone_desc) & ZONE_STATUS_LOAD_AFTER_DROP) != 0) { zdb_zone *invalid_zone = zdb_zone_create(zone_origin(zone_desc)); // RC = 1 zdb_zone_invalidate(invalid_zone); zdb_zone *old_zone = zdb_set_zone(db, invalid_zone); // RC ++ yassert(old_zone == NULL); (void)old_zone; zdb_zone_release(invalid_zone); } zone_clear_status(zone_desc, ZONE_STATUS_STARTING_UP|ZONE_STATUS_UNMOUNTING|ZONE_STATUS_PROCESSING); log_debug1("database_service_zone_unmount: unlocking zone '%{dnsname}' for unmounting", origin); database_fire_zone_unmounted(zone_desc); zone_unlock(zone_desc, ZONE_LOCK_UNMOUNT); } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service.c0000644000000000000000000000013114505005533022240 xustar000000000000000030 mtime=1695812443.481997069 29 atime=1695812445.78203001 30 ctime=1695812495.642744116 yadifa-2.6.5-11201/sbin/yadifad/database-service.c0000664000374500037450000025651414505005533022220 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #define DATABASE_SERVICE_C 1 #include "server-config.h" #define DATABASE_ZONE_RRSIG_THREAD_POOL 0 // now obsolete #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ZDB_JOURNAL_CODE 1 #include #include #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "database-service.h" #include "database-service-zone-desc-load.h" #include "database-service-zone-desc-unload.h" #include "database-service-zone-load.h" #include "database-service-zone-unload.h" #include "database-service-zone-mount.h" #include "database-service-zone-unmount.h" #include "database-service-zone-download.h" #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_DNSSEC_SUPPORT #include "database-service-zone-resignature.h" #include "zone-signature-policy.h" #endif #include "database-service-zone-freeze.h" #include "database-service-zone-unfreeze.h" #include "database-service-zone-store.h" #include "server.h" #include "notify.h" #include "ixfr.h" #if DNSCORE_HAS_CTRL #include "ctrl.h" #endif #include "zone-signature-policy.h" #include "server_error.h" #include "zone_desc.h" #include "config_error.h" #ifndef HAS_DYNUPDATE_DIFF_ENABLED #error "HAS_DYNUPDATE_DIFF_ENABLED not defined" #endif #define DBLOADQ_TAG 0x5144414f4c4244 #define DBMSGCB_TAG 0x424347534d4244 //#define DATABASE_SERVICE_QUEUE_SIZE 0x4000 #define DATABASE_SERVICE_QUEUE_SIZE 0x1000000 #define DATABASE_SERVICE_DOWNLOAD_QUEUE_SIZE 0x10000 #define DATABASE_SERVICE_LOAD_QUEUE_SIZE 0x10000 #define DATABASE_SERVICE_UNLOAD_QUEUE_SIZE 0x10000 #define DATABASE_SERVICE_STORE_QUEUE_SIZE 0x10000 #define DATABASE_SERVICE_RESIGN_QUEUE_SIZE 0x10000 #define DATABASE_SERVICE_CALLBACK_QUEUE_SIZE 0x1000 #if DEBUG #define DATABASE_SERVICE_BENCH_MESSAGES_PER_SECOND 1 #else #define DATABASE_SERVICE_BENCH_MESSAGES_PER_SECOND 0 #endif static void database_callback_run(database_message *message); static void database_clear_drop_after_reload(); static void database_do_drop_after_reload(); static struct service_s database_handler = UNINITIALIZED_SERVICE; static async_queue_s database_handler_queue; static bool database_handler_initialised = FALSE; static int database_service(struct service_worker_s *worker); /* Zone file variables */ zone_data_set database_zone_desc = {PTR_SET_DNSNAME_EMPTY, GROUP_MUTEX_INITIALIZER, 0}; /* Zones meant to be merged with zones */ static struct thread_pool_s *database_zone_load_thread_pool = NULL; static struct thread_pool_s *database_zone_store_thread_pool = NULL; static struct thread_pool_s *database_zone_unload_thread_pool = NULL; static struct thread_pool_s *database_zone_download_thread_pool = NULL; static struct thread_pool_s *database_callback_thread_pool = NULL; static ptr_set database_server_down_cache_set = PTR_SET_HOST_ADDRESS_EMPTY; static mutex_t database_server_down_cache_set_mtx = MUTEX_INITIALIZER; static s64 database_server_down_cache_timeout_us = ONE_SECOND_US; bool database_server_down_cache_query(const host_address *ha) { bool ret = FALSE; mutex_lock(&database_server_down_cache_set_mtx); ptr_node *node = ptr_set_find(&database_server_down_cache_set, ha); if(node != NULL) { s64 now = timeus(); s64 last_probe = node->value_s64; if(now - last_probe < database_server_down_cache_timeout_us) { ret = TRUE; // the node exist and hasn't expired } else { host_address *ha_key = node->key; ptr_set_delete(&database_server_down_cache_set, ha_key); host_address_delete(ha_key); } } mutex_unlock(&database_server_down_cache_set_mtx); return ret; } void database_server_down_cache_add(const host_address *ha) { mutex_lock(&database_server_down_cache_set_mtx); ptr_node *node = ptr_set_insert(&database_server_down_cache_set, (host_address*)ha); if(node != NULL) { s64 now = timeus(); node->key = host_address_copy(ha); node->value_s64 = now; } mutex_unlock(&database_server_down_cache_set_mtx); } #if ZDB_HAS_DNSSEC_SUPPORT #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT static struct thread_pool_s *database_zone_resignature_thread_pool = NULL; #if DATABASE_ZONE_RRSIG_THREAD_POOL static struct thread_pool_s *database_zone_rrsig_thread_pool = NULL; #endif #endif #endif static const u8 database_all_origins[] = "\003ALL\005ZONES"; static const char* database_service_operation[DATABASE_SERVICE_OPERATION_COUNT]= { "NOTHING", "ZONE-DESC-LOAD", "ZONE-DESC-UNLOAD", "ZONE-LOAD", "ZONE-LOADED-EVENT", "ZONE-MOUNT", "ZONE-MOUNTED-EVENT", "ZONE-UNMOUNT", "ZONE-UNMOUNTED-EVENT", "ZONE-UNLOAD", "ZONE-UNLOADED-EVENT", "ZONE-SAVE-TEXT", "ZONE-QUERY-AXFR", "ZONE-QUERY-IXFR", "ZONE-DOWNLOADED-EVENT", "SET-DROP-AFTER-RELOAD", "CLEAR-DROP-AFTER-RELOAD", "DO-DROP-AFTER-RELOAD", "ZONE-RECONFIGURE-BEGIN", "ZONE-RECONFIGURE-END", "ZONE-UPDATE-SIGNATURES", "ZONE-FREEZE", "ZONE-UNFREEZE", "ZONE-PROCESS", "CALLBACK" }; static smp_int database_reconfigure_enable_count = SMP_INT_INITIALIZER; const char* database_service_operation_get_name(u32 id) { if(id < DATABASE_SERVICE_OPERATION_COUNT) { return database_service_operation[id]; } return "?"; } static database_message * database_load_message_alloc(const u8 *origin, u8 type) { database_message *message; ZALLOC_OBJECT_OR_DIE(message, database_message, DBLOADQ_TAG); ZEROMEMORY(message, sizeof(database_message)); message->origin = dnsname_dup(origin); message->payload.type = type; return message; } static void database_load_message_free(database_message *message) { if(message != NULL) { dnsname_free(message->origin); ZFREE_OBJECT(message); } } /**********************************************************************************************************************/ static void database_service_finalize_destroy_threadpools(); ya_result database_service_init() { int err = SERVICE_ALREADY_INITIALISED; if(!database_handler_initialised) { #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT if(FAIL(err = database_service_zone_resignature_init())) { return err; } #endif if(database_zone_load_thread_pool == NULL) { database_zone_load_thread_pool = thread_pool_init_ex(g_config->zone_load_thread_count, DATABASE_SERVICE_LOAD_QUEUE_SIZE, "dbload"); if(database_zone_load_thread_pool == NULL) { return SERVICE_INITIALISATION_ERROR; } } if(database_zone_store_thread_pool == NULL) { database_zone_store_thread_pool = thread_pool_init_ex(g_config->zone_store_thread_count, DATABASE_SERVICE_STORE_QUEUE_SIZE, "dbstore"); if(database_zone_store_thread_pool == NULL) { database_service_finalize_destroy_threadpools(); return SERVICE_INITIALISATION_ERROR; } } if(database_zone_unload_thread_pool == NULL) { database_zone_unload_thread_pool = thread_pool_init_ex(1, DATABASE_SERVICE_UNLOAD_QUEUE_SIZE, "dbunload"); if(database_zone_unload_thread_pool == NULL) { database_service_finalize_destroy_threadpools(); return SERVICE_INITIALISATION_ERROR; } } if(database_zone_download_thread_pool == NULL) { database_zone_download_thread_pool = thread_pool_init_ex(g_config->zone_download_thread_count, DATABASE_SERVICE_DOWNLOAD_QUEUE_SIZE, "dbdownld"); if(database_zone_download_thread_pool == NULL) { database_service_finalize_destroy_threadpools(); return SERVICE_INITIALISATION_ERROR; } } if(database_callback_thread_pool == NULL) { database_callback_thread_pool = thread_pool_init_ex(1, DATABASE_SERVICE_CALLBACK_QUEUE_SIZE, "callback"); /// @note thread count MUST be set to 1 if(database_callback_thread_pool == NULL) { database_service_finalize_destroy_threadpools(); return SERVICE_INITIALISATION_ERROR; } } #if ZDB_HAS_DNSSEC_SUPPORT #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT if(database_zone_resignature_thread_pool == NULL) { database_zone_resignature_thread_pool = thread_pool_init_ex((!g_config->hidden_master)?1:8, DATABASE_SERVICE_RESIGN_QUEUE_SIZE, "dbresign"); /// @note thread count MUST be set to 1 if(database_zone_resignature_thread_pool == NULL) { database_service_finalize_destroy_threadpools(); return SERVICE_INITIALISATION_ERROR; } } #if DATABASE_ZONE_RRSIG_THREAD_POOL if(database_zone_rrsig_thread_pool == NULL) { database_zone_rrsig_thread_pool = thread_pool_init_ex(/*g_config->dnssec_thread_count + 1*/2, 32, "dbrrsig"); if(database_zone_rrsig_thread_pool == NULL) { database_service_finalize_destroy_threadpools(); return SERVICE_INITIALISATION_ERROR; } } #endif #endif #endif async_message_pool_init(); if(ISOK(err = service_init_ex(&database_handler, database_service, "DBsrvice", 1))) { async_queue_init(&database_handler_queue, DATABASE_SERVICE_QUEUE_SIZE, 1, /*100000*/1, "dbsrvice"); database_handler_initialised = TRUE; } } return err; } bool database_service_started() { return database_handler_initialised && !service_stopped(&database_handler); } ya_result database_service_start() { int err = SERVICE_ALREADY_INITIALISED; if(database_handler_initialised) { if(service_stopped(&database_handler)) { err = service_start(&database_handler); } } return err; } ya_result database_service_stop() { int err = SERVICE_NOT_INITIALISED; if(database_handler_initialised) { if(!service_stopped(&database_handler)) { err = service_stop(&database_handler); service_wait(&database_handler); } } return err; } static void database_service_message_clear(database_message *message); static void database_service_finalize_destroy_threadpools() { if(database_zone_load_thread_pool != NULL) { thread_pool_destroy(database_zone_load_thread_pool); database_zone_load_thread_pool = NULL; } if(database_zone_store_thread_pool != NULL) { thread_pool_destroy(database_zone_store_thread_pool); database_zone_store_thread_pool = NULL; } if(database_zone_unload_thread_pool != NULL) { thread_pool_destroy(database_zone_unload_thread_pool); database_zone_unload_thread_pool = NULL; } if(database_zone_download_thread_pool != NULL) { thread_pool_destroy(database_zone_download_thread_pool); database_zone_download_thread_pool = NULL; } if(database_callback_thread_pool != NULL) { thread_pool_destroy(database_callback_thread_pool); database_callback_thread_pool = NULL; } #if ZDB_HAS_DNSSEC_SUPPORT #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT if(database_zone_resignature_thread_pool != NULL) { thread_pool_destroy(database_zone_resignature_thread_pool); database_zone_resignature_thread_pool = NULL; } #if DATABASE_ZONE_RRSIG_THREAD_POOL if(database_zone_rrsig_thread_pool != NULL) { thread_pool_destroy(database_zone_rrsig_thread_pool); database_zone_rrsig_thread_pool = NULL; } #endif #endif #endif } ya_result database_service_finalize() { int err = SUCCESS; if(database_handler_initialised) { #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT database_service_zone_resignature_finalize(); #endif zone_set_lock(&database_zone_desc); // unlock checked ptr_set_iterator iter; ptr_set_iterator_init(&database_zone_desc.set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value; zone_lock(zone_desc, ZONE_LOCK_UNLOAD); zdb_zone *zone = zone_get_loaded_zone(zone_desc); if(zone != NULL) { alarm_close(zone->alarm_handle); zone->alarm_handle = ALARM_HANDLE_INVALID; zdb_zone_release(zone); } zone_unlock(zone_desc, ZONE_LOCK_UNLOAD); } zone_set_unlock(&database_zone_desc); err = database_service_stop(); database_service_finalize_destroy_threadpools(); service_finalize(&database_handler); while(!async_queue_empty(&database_handler_queue)) { async_message_s *async = async_message_next(&database_handler_queue); database_message *message = (database_message*)async->args; if(message != NULL) { log_debug("clearing message on %{dnsname}", message->origin); database_service_message_clear(message); database_load_message_free(message); } else { log_debug("clearing empty message"); } async_message_release(async); } async_queue_finalize(&database_handler_queue); database_service_run_garbage_collector(); /// destroy all the descs log_debug("dropping zone settings"); zone_free_all(&database_zone_desc); database_handler_initialised = FALSE; } return err; } /**********************************************************************************************************************/ bool database_origin_is_mounted(const u8 *origin) { // get the zone // look if it is valid or not zdb *db = g_config->database; bool mounted = FALSE; zdb_lock(db, ZDB_MUTEX_READER); zdb_zone_label *zone_label = zdb_zone_label_find_from_dnsname_nolock(db, origin); if(zone_label != NULL) { zdb_zone *zone = zone_label->zone; // OK (ARC) mounted = zdb_zone_isvalid(zone); } zdb_unlock(db, ZDB_MUTEX_READER); return mounted; } bool database_zone_desc_is_mounted(const u8 *origin) { // get the origin // get the zone // look if it is valid or not bool mounted = database_origin_is_mounted(origin); return mounted; } static void database_service_set_drop_after_reload() { zone_set_lock(&database_zone_desc); // unlock checked ptr_set_iterator iter; ptr_set_iterator_init(&database_zone_desc.set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value; zone_set_status(zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD); } zone_set_unlock(&database_zone_desc); } static void database_service_set_drop_after_reload_for_set(const ptr_set *fqdn_set) { if(fqdn_set != NULL) { zone_set_lock(&database_zone_desc); // unlock checked ptr_set_iterator iter; ptr_set_iterator_init(fqdn_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *fqdn_node = ptr_set_iterator_next_node(&iter); ptr_node *zone_node = ptr_set_find(&database_zone_desc.set, fqdn_node->key); if(zone_node != NULL) { zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value; if(zone_desc != NULL) { zone_set_status(zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD); if(zone_desc->loaded_zone != NULL) { #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT zdb_zone_set_maintained(zone_desc->loaded_zone, zdb_rr_label_flag_isclear(zone_desc->loaded_zone->apex, ZDB_ZONE_IS_SLAVE)); #else // the preprocessor exclusion could go around the 'if' but // I'd rather keep this as a "what to do when a zone has been loaded" marker #endif } } } } zone_set_unlock(&database_zone_desc); } else { database_service_set_drop_after_reload(); } } static void database_service_clear_drop_after_reload() { zone_set_lock(&database_zone_desc); // unlock checked ptr_set_iterator iter; ptr_set_iterator_init(&database_zone_desc.set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value; zone_clear_status(zone_desc, ZONE_STATUS_DROP_AFTER_RELOAD); } zone_set_unlock(&database_zone_desc); } static void database_service_do_drop_after_reload() { log_debug1("database_service_do_drop_after_reload()"); zone_set_lock(&database_zone_desc); // unlock checked ptr_set_iterator iter; ptr_set_iterator_init(&database_zone_desc.set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value; if((zone_get_status(zone_desc) & ZONE_STATUS_DROP_AFTER_RELOAD) != 0) { // drop the zone & zone desc log_debug2("database_service_do_drop_after_reload: queuing %{dnsname} for unload", zone_origin(zone_desc)); database_zone_desc_unload(zone_origin(zone_desc)); } } zone_set_unlock(&database_zone_desc); log_debug1("database_service_do_drop_after_reload() done"); } static ya_result database_service_process_command(zone_desc_s *zone_desc, zone_command_s* command) { ya_result ret = SUCCESS; switch(command->id) { case DATABASE_SERVICE_ZONE_DESC_UNLOAD: { database_service_zone_desc_unload(zone_desc); break; } case DATABASE_SERVICE_ZONE_LOAD: { database_service_zone_load(zone_desc); break; } case DATABASE_SERVICE_ZONE_MOUNT: { database_service_zone_mount(zone_desc); break; } case DATABASE_SERVICE_ZONE_UNMOUNT: { database_service_zone_unmount(zone_desc); break; } case DATABASE_SERVICE_ZONE_UNLOAD: { database_service_zone_unload(zone_desc, command->parm.zone); break; } #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT case DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES: { ret = database_service_zone_dnssec_maintenance(zone_desc); break; } #endif case DATABASE_SERVICE_ZONE_FREEZE: { database_service_zone_freeze(zone_desc); break; } case DATABASE_SERVICE_ZONE_UNFREEZE: { database_service_zone_unfreeze(zone_desc); break; } case DATABASE_SERVICE_ZONE_SAVE_TEXT: { if(ISOK(ret = zone_lock(zone_desc, ZONE_LOCK_SAVE))) { if(command->parm.ptr != NULL) { zone_set_status(zone_desc, ZONE_STATUS_MUST_CLEAR_JOURNAL); } zone_unlock(zone_desc, ZONE_LOCK_SAVE); database_service_zone_store(zone_desc); // text } else { log_err("database_service_zone_store: failed to lock zone settings for '%{dnsname}'", zone_origin(zone_desc)); } break; } case DATABASE_SERVICE_ZONE_PROCESSED: { break; } default: { ret = INVALID_STATE_ERROR; log_err("unexpected command %d", command->id); } } return ret; } static void database_service_message_clear_free_fqdn_node(ptr_node *node) { dnsname_zfree(node->key); } static void database_service_message_clear(database_message *message) { switch(message->payload.type) { case DATABASE_SERVICE_ZONE_DESC_LOAD: { zone_release(message->payload.zone_desc_load.zone_desc); message->payload.zone_desc_load.zone_desc = NULL; break; } case DATABASE_SERVICE_ZONE_DESC_UNLOAD: case DATABASE_SERVICE_ZONE_LOAD: case DATABASE_SERVICE_ZONE_UNLOAD: case DATABASE_SERVICE_ZONE_FREEZE: case DATABASE_SERVICE_ZONE_UNFREEZE: case DATABASE_SERVICE_QUERY_AXFR: case DATABASE_SERVICE_QUERY_IXFR: { break; } case DATABASE_SERVICE_SET_DROP_AFTER_RELOAD: { if(message->payload.drop_after_reload.do_subset) { ptr_set_callback_and_destroy(&message->payload.drop_after_reload.zone_set, database_service_message_clear_free_fqdn_node); } break; } case DATABASE_SERVICE_DO_DROP_AFTER_RELOAD: { break; } case DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES: { if(message->payload.zone_update_signatures.expected_zone != NULL) { zdb_zone_release(message->payload.zone_update_signatures.expected_zone); message->payload.zone_update_signatures.expected_zone = NULL; } zone_release(message->payload.zone_update_signatures.expected_zone_desc); message->payload.zone_update_signatures.expected_zone_desc = NULL; break; } case DATABASE_SERVICE_ZONE_LOADED_EVENT: { if(message->payload.zone_loaded_event.zone != NULL) { zdb_zone_release(message->payload.zone_loaded_event.zone); message->payload.zone_loaded_event.zone = NULL; } break; } case DATABASE_SERVICE_ZONE_MOUNTED_EVENT: { if(message->payload.zone_mounted_event.zone != NULL) { zdb_zone_release(message->payload.zone_mounted_event.zone); message->payload.zone_mounted_event.zone = NULL; } zone_release(message->payload.zone_mounted_event.zone_desc); message->payload.zone_mounted_event.zone_desc = NULL; break; } case DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT: { zone_release(message->payload.zone_unmounted_event.zone_desc); message->payload.zone_unmounted_event.zone_desc = NULL; break; } case DATABASE_SERVICE_ZONE_UNLOADED_EVENT: { zone_release(message->payload.zone_unloaded_event.zone_desc); message->payload.zone_unloaded_event.zone_desc = NULL; break; } case DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT: default: { break; } case DATABASE_SERVICE_ZONE_SAVE_TEXT: case DATABASE_SERVICE_ZONE_PROCESSED: { break; } case DATABASE_SERVICE_CALLBACK: { message->payload.callback.callback(message->payload.callback.args, TRUE); break; } } } #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT static zone_desc_s * database_service_on_update_zone_signatures_event(database_message *message) { // desc zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); // current zone desc is the one we wanted to update the signatures on ? if(zone_desc != NULL) { if(zone_desc == message->payload.zone_update_signatures.expected_zone_desc) { zone_lock(zone_desc, ZONE_LOCK_SERVICE); zdb_zone *zone = zone_get_loaded_zone(zone_desc); // RC++ zone_unlock(zone_desc, ZONE_LOCK_SERVICE); if(zone != NULL) { // zone is the one we wanted to update the signatures on ? if(zone == message->payload.zone_update_signatures.expected_zone) { // check log_debug("database: %{dnsname}: zone signature triggered", zone_origin(zone_desc)); zone_enqueue_command(zone_desc, DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES, NULL, FALSE); } else { log_warn("database: %{dnsname}: zone signature triggered for another instance of the zone, ignoring", zone_origin(zone_desc)); zone_release(zone_desc); zone_desc = NULL; } zdb_zone_release(zone); #if DEBUG zone = NULL; #endif } } else { log_warn("database: %{dnsname}: zone signature triggered for another instance of the zone settings, ignoring", zone_origin(message->payload.zone_update_signatures.expected_zone_desc)); zone_release(zone_desc); #if DEBUG zone_desc = NULL; #endif } } else // zone_desc == NULL ie: shutdown, reconfigure { log_warn("database: %{dnsname}: zone signature triggered but zone settings are not available, ignoring", zone_origin(message->payload.zone_update_signatures.expected_zone_desc)); } zdb_zone_release(message->payload.zone_update_signatures.expected_zone); message->payload.zone_update_signatures.expected_zone = NULL; zone_release(message->payload.zone_update_signatures.expected_zone_desc); message->payload.zone_update_signatures.expected_zone_desc = NULL; return zone_desc; } #endif static zone_desc_s* database_service_on_zone_mounted_event(database_message* message) { // desc zone_desc_s *zone_desc = message->payload.zone_mounted_event.zone_desc; if(ISOK(message->payload.zone_mounted_event.result_code)) { log_info("database: %{dnsname}: zone successfully mounted", message->origin); #if ZDB_HAS_MASTER_SUPPORT && ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT if(zone_desc->type == ZT_MASTER) { if((message->payload.zone_mounted_event.zone != NULL) && zdb_zone_is_store_clear_journal_after_mount(message->payload.zone_mounted_event.zone)) { database_zone_store_ex(message->origin, TRUE); zdb_zone_clear_store_clear_journal_after_mount(message->payload.zone_mounted_event.zone); } // verify policies ya_result ret; if(ISOK(ret = zone_policy_process(zone_desc))) { log_debug("database: %{dnsname}: on-mount policy process done", message->origin); } else { log_err("database: %{dnsname}: on-mount policy process failed: %r", message->origin, ret); } if((message->payload.zone_mounted_event.zone != NULL) && zdb_zone_is_maintained(message->payload.zone_mounted_event.zone)) { if(zone_maintains_dnssec(zone_desc)) { if(message->payload.zone_mounted_event.zone != NULL) { zdb_zone_lock(message->payload.zone_mounted_event.zone, ZDB_ZONE_MUTEX_SIMPLEREADER); const zdb_packed_ttlrdata *dnskey_rrset = zdb_record_find(&message->payload.zone_mounted_event.zone->apex->resource_record_set, TYPE_DNSKEY); // zone is locked zdb_zone_unlock(message->payload.zone_mounted_event.zone, ZDB_ZONE_MUTEX_SIMPLEREADER); if(dnskey_rrset != NULL) { log_info("database: %{dnsname}: signature maintenance initialisation", message->origin); if((zdb_zone_get_flags(message->payload.zone_mounted_event.zone) & ZDB_ZONE_MAINTENANCE_ON_MOUNT) != 0) { message->payload.zone_mounted_event.zone->progressive_signature_update.earliest_signature_expiration = 0; database_zone_update_signatures( message->origin, message->payload.zone_mounted_event.zone_desc, message->payload.zone_mounted_event.zone ); } } else { log_info("database: %{dnsname}: signature maintenance postponed until keys are activated", message->origin); } } else { log_debug("database: %{dnsname}: no zone passed with mount event", message->origin); } } else { log_info("database: %{dnsname}: signature maintenance disabled", message->origin); } } } else // ... else slave ? #endif if(zone_desc->type == ZT_SLAVE) { #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT zdb_zone *zone = message->payload.zone_mounted_event.zone; u8 zone_dnssec_type = zone_policy_guess_dnssec_type(zone); switch(zone_dnssec_type) { case ZONE_DNSSEC_FL_NOSEC: log_debug("database: %{dnsname}: slave zone is not DNSSEC", message->origin); break; case ZONE_DNSSEC_FL_NSEC: log_debug("database: %{dnsname}: slave zone is NSEC", message->origin); break; case ZONE_DNSSEC_FL_NSEC3: log_debug("database: %{dnsname}: slave zone is NSEC3", message->origin); break; case ZONE_DNSSEC_FL_NSEC3_OPTOUT: log_debug("database: %{dnsname}: slave zone is NSEC3 OPT-OUT", message->origin); break; } zone_dnssec_status_update(zone); #endif database_zone_refresh_maintenance(g_config->database, message->origin, 0); // means next refresh from now // database_zone_refresh_maintenance_wih_zone(zone_desc->loaded_zone, 0); } } else { log_err("database: %{dnsname}: failed to mount the zone: %r", message->origin, message->payload.zone_mounted_event.result_code); } if(message->payload.zone_mounted_event.zone != NULL) { zdb_zone_clear_flags(message->payload.zone_mounted_event.zone, ZDB_ZONE_MAINTENANCE_ON_MOUNT); zdb_zone_release(message->payload.zone_mounted_event.zone); message->payload.zone_mounted_event.zone = NULL; } // do NOT release zone_desc message->payload.zone_mounted_event.zone_desc = NULL; // do not release zone_desc because we will try to push the event return zone_desc; } static zone_desc_s* database_service_on_zone_loaded_event(database_message *message) { // desc zone_desc_s *zone_desc = message->payload.zone_loaded_event.zone_desc; if(ISOK(message->payload.zone_loaded_event.result_code)) { if(message->payload.zone_loaded_event.result_code == 1) { log_info("database: %{dnsname}: zone successfully loaded", message->origin); if((message->payload.zone_mounted_event.zone != NULL) && zdb_zone_is_store_clear_journal_after_mount(message->payload.zone_mounted_event.zone)) { journal_truncate(zone_origin(zone_desc)); } zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_MOUNT, NULL, FALSE); } else { log_debug("database: %{dnsname}: there was no need to load the zone", message->origin); } } else if((message->payload.zone_loaded_event.result_code == ZRE_NO_VALID_FILE_FOUND) && (zone_desc->type == ZT_SLAVE)) { log_debug("database: %{dnsname}: no local copy of the zone is available: download required", message->origin); } else { if(message->payload.zone_loaded_event.result_code != STOPPED_BY_APPLICATION_SHUTDOWN) { log_err("database: %{dnsname}: failed to load the zone: %r", message->origin, message->payload.zone_loaded_event.result_code); } else { log_debug("database: %{dnsname}: zone load cancelled by shutdown", message->origin); } } if(message->payload.zone_loaded_event.zone != NULL) { zdb_zone_release(message->payload.zone_loaded_event.zone); message->payload.zone_loaded_event.zone = NULL; } return zone_desc; } static zone_desc_s* database_service_on_zone_unmounted_event(database_message *message) { // desc (both) zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); log_info("database: %{dnsname}: zone successfully unmounted", message->origin); zone_release(message->payload.zone_unmounted_event.zone_desc); message->payload.zone_unmounted_event.zone_desc = NULL; return zone_desc; } static zone_desc_s * database_service_on_zone_desc_unload(database_message *message) { zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); if(zone_desc != NULL) { if((zone_get_status(zone_desc) & ZONE_STATUS_UNREGISTERING) == 0) { zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_DESC_UNLOAD, NULL, FALSE); zone_set_status(zone_desc, ZONE_STATUS_UNREGISTERING); } else { log_debug("database: %{dnsname}: cannot unload configuration: zone already unregistering", message->origin); } } else { log_debug("database: %{dnsname}: cannot unload configuration: zone is not registered", message->origin); } return zone_desc; } static zone_desc_s* database_service_on_zone_load(database_message *message) { zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); if(zone_desc != NULL) { log_debug("database: %{dnsname}: load, @%p", message->origin, zone_desc); if((zone_get_status(zone_desc) & (ZONE_STATUS_LOAD|ZONE_STATUS_LOADING)) == 0) { zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_LOAD, NULL, FALSE); } else { log_debug("database: %{dnsname}: ignoring load command for: already loading", message->origin); } } else { log_debug("database: %{dnsname}: cannot load: zone is not configured", message->origin); } return zone_desc; } static zone_desc_s * database_service_on_service_zone_unload(database_message *message) { zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); if(zone_desc != NULL) { // zone has been acquired for this call // references are passed to the command zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_UNLOAD, message->payload.zone_unload.zone, TRUE); message->payload.zone_unload.zone = NULL; } else { if(message->payload.zone_unload.zone != NULL) { zdb_zone_release(message->payload.zone_unload.zone); message->payload.zone_unload.zone = NULL; } log_debug("database: %{dnsname}: cannot unload: zone is not configured", message->origin); } return zone_desc; } static zone_desc_s * database_service_on_zone_freeze(database_message *message) { zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); if(zone_desc != NULL) { zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_FREEZE, NULL, FALSE); } else { log_err("database: %{dnsname}: cannot freeze: zone is not configured", message->origin); } return zone_desc; } static zone_desc_s* database_service_on_zone_unfreeze(database_message *message) { zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); if(zone_desc != NULL) { zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_UNFREEZE, NULL, FALSE); } else { log_err("database: %{dnsname}: cannot unfreeze: zone is not configured", message->origin); } return zone_desc; } static zone_desc_s* database_service_on_zone_store_text(database_message *message) { zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); if(zone_desc != NULL) { zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_SAVE_TEXT, (message->payload.zone_store.clear)?(void*)1:(void*)0, FALSE); } else { log_err("database: %{dnsname}: cannot write to disk as text: zone is not configured", message->origin); } return zone_desc; } static zone_desc_s* database_service_on_zone_downloaded_event(database_message *message) { zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); if(ISOK(message->payload.zone_downloaded_event.result_code)) { //log_info("database: %{dnsname}: zone successfully downloaded (%{dnstype})", message->origin, &message->payload.zone_downloaded_event.download_type); if(message->payload.zone_downloaded_event.download_type != TYPE_NONE) { log_info("database: %{dnsname}: zone successfully downloaded", message->origin); if(message->payload.zone_downloaded_event.download_type == TYPE_AXFR) { database_zone_load(message->origin); // the downloaded file can now be loaded } } } else { log_err("database: %{dnsname}: failed to download the zone: %r", message->origin, message->payload.zone_downloaded_event.result_code); } return zone_desc; } static zone_desc_s * database_service_on_zone_unloaded_event(database_message *message) { zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); if(ISOK(message->payload.zone_unloaded_event.result_code)) { log_info("database: %{dnsname}: zone successfully unloaded", message->origin); } else { log_err("database: %{dnsname}: failed to unload the zone: %r", message->origin, message->payload.zone_unloaded_event.result_code); } zone_release(message->payload.zone_unloaded_event.zone_desc); message->payload.zone_unloaded_event.zone_desc = NULL; return zone_desc; } static zone_desc_s* database_serice_on_zone_processed(database_message *message) { zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); if(zone_desc != NULL) { log_debug("database: %{dnsname}: processing done", message->origin); } else { log_debug("database: %{dnsname}: processed zone is not configured", message->origin); } return zone_desc; } static void database_service_zone_destroyed_callback(const u8 *origin) { log_debug("database: %{dnsname}: memory freed", origin); zone_desc_s *zone_desc = zone_acquirebydnsname(origin); if(zone_desc != NULL) { zone_lock(zone_desc, ZONE_LOCK_LOAD); if((zone_get_status(zone_desc) & ZONE_STATUS_LOAD_AFTER_DROP) != 0) { zone_clear_status(zone_desc, ZONE_STATUS_LOAD_AFTER_DROP); // load the zone //database_service_zone_load(zone_desc); //zone_lock(zone_desc, ZONE_LOCK_LOAD); //zone_enqueue_command(zone_desc, DATABASE_SERVICE_ZONE_LOAD, NULL, TRUE); //zone_unlock(zone_desc, ZONE_LOCK_LOAD); database_zone_load(origin); } zone_unlock(zone_desc, ZONE_LOCK_LOAD); } } static int database_service(struct service_worker_s *worker) { zone_desc_s *zone_desc = NULL; #if DATABASE_SERVICE_BENCH_MESSAGES_PER_SECOND u64 sbmps_epoch_us = timeus(); u32 sbmps_count = 0; #endif /* * while the program is running */ log_info("database: service starting"); zdb_zone_dnssec_keys_refresh(); log_info("database: service started"); bool running; zdb_zone_garbage_run_callback_add(database_service_zone_destroyed_callback); while((running = service_should_run(worker)) || !async_queue_empty(&database_handler_queue)) { if(!zdb_zone_garbage_empty()) { // do a zdb_zone_garbage_run in the background if(thread_pool_queue_size(database_zone_unload_thread_pool) == 0) { database_service_run_garbage_collector(); } } /* * dequeue command */ zone_desc = NULL; async_message_s *async = async_message_next(&database_handler_queue); if(async == NULL) { continue; } database_message *message = (database_message*)async->args; if(message == NULL) { log_err("database: NULL message"); continue; } #if DATABASE_SERVICE_BENCH_MESSAGES_PER_SECOND { u64 now = timeus(); if(now - sbmps_epoch_us >= ONE_SECOND_US) { double mps = sbmps_count; mps *= ONE_SECOND_US_F; mps /= (now - sbmps_epoch_us); log_info("database: %12.3f msg/s", mps); sbmps_epoch_us = now; sbmps_count = 0; } sbmps_count++; } #endif #if DEBUG if(message->payload.type < DATABASE_SERVICE_OPERATION_COUNT) { log_debug("database: %{dnsname}: dequeued operation %s", message->origin, database_service_operation[message->payload.type]); } else { log_debug("database: %{dnsname}: dequeued operation #%d", message->origin, message->payload.type); } #endif /* * NULL => shutdown the thread */ if(!running) { switch(message->payload.type) { case DATABASE_SERVICE_ZONE_DESC_LOAD: case DATABASE_SERVICE_ZONE_DESC_UNLOAD: case DATABASE_SERVICE_ZONE_LOAD: case DATABASE_SERVICE_ZONE_UNLOAD: case DATABASE_SERVICE_ZONE_FREEZE: case DATABASE_SERVICE_ZONE_UNFREEZE: case DATABASE_SERVICE_QUERY_AXFR: case DATABASE_SERVICE_QUERY_IXFR: case DATABASE_SERVICE_SET_DROP_AFTER_RELOAD: case DATABASE_SERVICE_DO_DROP_AFTER_RELOAD: case DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES: case DATABASE_SERVICE_ZONE_LOADED_EVENT: case DATABASE_SERVICE_ZONE_MOUNTED_EVENT: case DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT: case DATABASE_SERVICE_ZONE_UNLOADED_EVENT: case DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT: case DATABASE_SERVICE_CALLBACK: default: { log_debug("database: shutting down: cleaning message %i", message->payload.type); database_service_message_clear(message); database_load_message_free(message); async_message_release(async); continue; } case DATABASE_SERVICE_ZONE_SAVE_TEXT: case DATABASE_SERVICE_ZONE_PROCESSED: { log_debug("database: shutting down: not ignoring message %i", message->payload.type); break; } } } /* * load command ? */ switch(message->payload.type) { case DATABASE_SERVICE_ZONE_DESC_LOAD: { // desc database_load_zone_desc(message->payload.zone_desc_load.zone_desc); // foreground zone_release(message->payload.zone_desc_load.zone_desc); message->payload.zone_desc_load.zone_desc = NULL; break; } // DISPATCH TO THE ZONE DESCRIPTOR case DATABASE_SERVICE_ZONE_DESC_UNLOAD: { zone_desc = database_service_on_zone_desc_unload(message); break; } case DATABASE_SERVICE_ZONE_LOAD: { zone_desc = database_service_on_zone_load(message); break; } case DATABASE_SERVICE_ZONE_UNLOAD: { zone_desc = database_service_on_service_zone_unload(message); break; } case DATABASE_SERVICE_ZONE_FREEZE: { zone_desc = database_service_on_zone_freeze(message); break; } case DATABASE_SERVICE_ZONE_UNFREEZE: { zone_desc = database_service_on_zone_unfreeze(message); break; } case DATABASE_SERVICE_ZONE_SAVE_TEXT: { zone_desc = database_service_on_zone_store_text(message); break; } case DATABASE_SERVICE_QUERY_AXFR: { // no desc database_service_zone_axfr_query(message->origin); // background, triggers 'downloaded' event break; } case DATABASE_SERVICE_QUERY_IXFR: { // no desc database_service_zone_ixfr_query(message->origin); // background, triggers 'downloaded' event break; } case DATABASE_SERVICE_SET_DROP_AFTER_RELOAD: { // no desc // ZONE_STATUS_DROP_AFTER_RELOAD if(message->payload.drop_after_reload.do_subset) { database_service_set_drop_after_reload_for_set(&message->payload.drop_after_reload.zone_set); // foreground if(message->payload.drop_after_reload.do_subset) { ptr_set_callback_and_destroy(&message->payload.drop_after_reload.zone_set, database_service_message_clear_free_fqdn_node); } } else { database_service_set_drop_after_reload(); } break; } case DATABASE_SERVICE_DO_DROP_AFTER_RELOAD: { // no desc database_service_do_drop_after_reload(); // foreground break; } case DATABASE_SERVICE_CLEAR_DROP_AFTER_RELOAD: { database_service_clear_drop_after_reload(); // foreground break; } // #if ZDB_HAS_DNSSEC_SUPPORT #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT case DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES: { zone_desc = database_service_on_update_zone_signatures_event(message); break; } #endif #endif // ZDB_HAS_DNSSEC_SUPPORT // EVENTS case DATABASE_SERVICE_ZONE_LOADED_EVENT: { zone_desc = database_service_on_zone_loaded_event(message); break; } case DATABASE_SERVICE_ZONE_MOUNTED_EVENT: { zone_desc = database_service_on_zone_mounted_event(message); break; } case DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT: { zone_desc = database_service_on_zone_unmounted_event(message); break; } case DATABASE_SERVICE_ZONE_UNLOADED_EVENT: { zone_desc = database_service_on_zone_unloaded_event(message); break; } case DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT: { zone_desc = database_service_on_zone_downloaded_event(message); break; } case DATABASE_SERVICE_ZONE_PROCESSED: { zone_desc = database_serice_on_zone_processed(message); break; } case DATABASE_SERVICE_CALLBACK: { log_debug("database: queuing %s callback from %llT", message->payload.callback.name, message->payload.callback.timestamp); database_callback_run(message); break; } default: { break; } } if(zone_desc != NULL) { ya_result ret; if(FAIL(ret = zone_lock(zone_desc, ZONE_LOCK_SERVICE))) { log_err("database: %{dnsname}: unable to lock zone: %r", message->origin, ret); } #if DEBUG log_debug("database: %{dnsname}: zone status: %x", message->origin, zone_get_status(zone_desc)); #endif while((zone_get_status(zone_desc) & ZONE_STATUS_PROCESSING) == 0) { #if DEBUG zone_desc_log(g_server_logger, LOG_DEBUG, zone_desc, "database-service"); #endif zone_command_s* command = zone_dequeue_command(zone_desc); if(command != NULL) { zone_set_status(zone_desc, ZONE_STATUS_PROCESSING); zone_desc->last_processor = command->id; log_debug("database: %{dnsname}: processing zone @%p (%s)", message->origin, zone_desc, database_service_operation_get_name(zone_desc->last_processor)); zone_unlock(zone_desc, ZONE_LOCK_SERVICE); if(ISOK(ret = database_service_process_command(zone_desc, command))) { if(FAIL(zone_lock(zone_desc, ZONE_LOCK_SERVICE))) { log_err("database: %{dnsname}: zone cannot be locked", message->origin); } } else { if((ret != FEATURE_NOT_SUPPORTED) && (ret != SERVICE_ALREADY_RUNNING)) { log_err("database: %{dnsname}: cannot execute command: %08x: %r", message->origin, command->id, ret); } else { log_debug("database: %{dnsname}: cannot execute command: %08x: %r", message->origin, command->id, ret); } if(FAIL(ret = zone_lock(zone_desc, ZONE_LOCK_SERVICE))) { log_err("database: %{dnsname}: unable to re-lock zone following an internal error: %r", message->origin, ret); } zone_clear_status(zone_desc, ZONE_STATUS_PROCESSING); } zone_command_free(command); } else { if(zone_get_status(zone_desc) & ZONE_STATUS_MARKED_FOR_DESTRUCTION) { log_debug("database: %{dnsname}: zone @%p is marked for destruction", zone_origin(zone_desc), zone_desc); } if(!(zone_get_status(zone_desc) & ZONE_STATUS_PROCESSING)) { zone_desc->last_processor = 0; } break; } } #if DEBUG log_debug("database: %{dnsname}: zone @%p is processed by %s", message->origin, zone_desc, database_service_operation_get_name(zone_desc->last_processor)); #endif zone_unlock(zone_desc, ZONE_LOCK_SERVICE); zone_release(zone_desc); #if DEBUG zone_desc = NULL; #endif } database_load_message_free(message); async_message_release(async); } zdb_zone_garbage_run_callback_remove(database_service_zone_destroyed_callback); service_set_stopping(worker); log_info("database: service stopped"); return 0; } void database_load_all_zones() { u8 buffer[4096]; // builds a set of names to load, batch loads the names // iterates the above process until there are no names left to load zone_set_lock(&database_zone_desc); // unlock checked ptr_node *node = ptr_set_get_first(&database_zone_desc.set); for(;;) { u8 *name = buffer; const u8 *last = NULL; for(; node != NULL; node = ptr_set_node_next(node)) { zone_desc_s *zone_desc = (zone_desc_s *)node->value; int name_len = dnsname_len(zone_origin(zone_desc)); if(name_len > (&buffer[sizeof(buffer)] - name)) { break; } memcpy(name, zone_origin(zone_desc), name_len); last = name; name += name_len; } zone_set_unlock(&database_zone_desc); if(last == NULL) { // no name has been inserted : nothing more to do break; } name = buffer; for(;;) { database_zone_load(name); if(name == last) { break; } name += dnsname_len(name); } zone_set_lock(&database_zone_desc); // unlock checked // get back the last name node = ptr_set_find(&database_zone_desc.set, last); if(node != NULL) { // and get the one that follows node = ptr_set_node_next(node); } } } void database_zone_load(const u8 *origin) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_LOAD", origin); database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_LOAD); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT static void database_zone_update_signatures_common(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone) { database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES); zone_acquire(expected_zone_desc); zdb_zone_acquire(expected_zone); message->payload.zone_update_signatures.expected_zone_desc = expected_zone_desc; message->payload.zone_update_signatures.expected_zone = expected_zone; async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_zone_update_signatures_resume(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES (resume)", origin); database_zone_update_signatures_common(origin, expected_zone_desc, expected_zone); } void database_zone_update_signatures(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone) { if(expected_zone->progressive_signature_update.earliest_signature_expiration >= MAX_S32) // can only be == as it's an s32 { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES ignored", origin); return; } log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES", origin); if(zdb_zone_set_maintenance_queued(expected_zone)) { database_zone_update_signatures_common(origin, expected_zone_desc, expected_zone); } else { #if DEBUG log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES ignored (already queued)", origin); #endif } } void database_zone_update_signatures_allow_queue(const u8 *origin, zone_desc_s *expected_zone_desc, zdb_zone *expected_zone) { log_debug("database: %{dnsname}: maintenance done", expected_zone->origin); (void)origin; (void)expected_zone_desc; (void)expected_zone; } static ya_result database_zone_update_signatures_alarm(void *args_, bool cancel) { zdb_zone *zone = (zdb_zone*)args_; if(!cancel) { zone_desc_s *zone_desc = zone_acquirebydnsname(zone->origin); if(zone_desc != NULL) { log_debug("database: %{dnsname}: maintenance triggered by time", zone->origin); database_zone_update_signatures(zone->origin, zone_desc, zone); zone_release(zone_desc); } } zdb_zone_release(zone); return SUCCESS; } /** * * Sets an alarm to enqueue a zone maintenance at a given time (best effort) * * @param zone * @param at */ void database_zone_update_signatures_at(zdb_zone *zone, u32 at) { log_debug("database: %{dnsname}: will enqueue operation DATABASE_SERVICE_UPDATE_ZONE_SIGNATURES at %T", zone->origin, at); zdb_zone_acquire(zone); alarm_event_node *event = alarm_event_new( // update signatures at, ALARM_KEY_ZONE_SIGNATURE_UPDATE, database_zone_update_signatures_alarm, zone, ALARM_DUP_REMOVE_LATEST, "database-service-zone-maintenance"); alarm_set(zone->alarm_handle, event); } #endif void database_zone_unload(zdb_zone *zone) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_UNLOAD", zone->origin); zdb_zone_acquire(zone); database_message *message = database_load_message_alloc(zone->origin, DATABASE_SERVICE_ZONE_UNLOAD); message->payload.zone_unload.zone = zone; async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_zone_freeze(const u8 *origin) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_FREEZE", origin); database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_FREEZE); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_zone_unfreeze(const u8 *origin) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_UNFREEZE", origin); database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_UNFREEZE); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_zone_store_ex(const u8 *origin, bool clear) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_SAVE_TEXT (clear=%i)", origin, clear); database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_SAVE_TEXT); async_message_s *async = async_message_alloc(); async->id = message->payload.type; message->payload.zone_store.clear = clear; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_zone_store(const u8 *origin) { database_zone_store_ex(origin, FALSE); } void database_zone_desc_load(zone_desc_s *zone_desc) { if(zone_desc != NULL) { log_debug("database: %{dnsname}: loading settings", zone_origin(zone_desc)); #if DEBUG zone_desc_log(MODULE_MSG_HANDLE, LOG_DEBUG, zone_desc, "database_zone_desc_load"); #endif if(service_started(&database_handler)) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_DESC_LOAD", zone_origin(zone_desc)); database_message *message = database_load_message_alloc(zone_origin(zone_desc), DATABASE_SERVICE_ZONE_DESC_LOAD); zone_acquire(zone_desc); message->payload.zone_desc_load.zone_desc = zone_desc; async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } else { log_debug("database: %{dnsname}: loading setting with offline database", zone_origin(zone_desc)); database_load_zone_desc(zone_desc); } } else { log_err("database: loading settings asked for NULL settings"); } } void database_zone_desc_unload(const u8 *origin) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_DESC_UNLOAD", origin); database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_DESC_UNLOAD); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_zone_axfr_query(const u8 *origin) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_AXFR", origin); database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_QUERY_AXFR); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } static ya_result database_zone_axfr_query_alarm(void *args, bool cancel) { async_message_s* async = (async_message_s*)args; database_message* message = (database_message*)async->args; if(!cancel) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_AXFR (alarm)", message->origin); async_message_call(&database_handler_queue, async); } else { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_AXFR cancelled (alarm)", message->origin); database_load_message_free((database_message*)async->args); async_message_release(async); } return SUCCESS; } void database_zone_axfr_query_at(const u8 *origin, time_t at) { log_debug("database: %{dnsname}: will enqueue operation DATABASE_SERVICE_QUERY_AXFR at %T", origin, at); zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, origin); if(zone == NULL) { log_warn("database: %{dnsname}: arming AXFR query: zone not in database", origin); return; } database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_QUERY_AXFR); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; alarm_event_node *event = alarm_event_new( // axfr query at, ALARM_KEY_ZONE_AXFR_QUERY, database_zone_axfr_query_alarm, async, ALARM_DUP_REMOVE_LATEST, "database-zone-axfr-query-alarm"); alarm_set(zone->alarm_handle, event); zdb_zone_release(zone); } void database_zone_ixfr_query(const u8 *origin) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_IXFR", origin); database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_QUERY_IXFR); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } static ya_result database_zone_ixfr_query_alarm(void *args, bool cancel) { async_message_s* async = (async_message_s*)args; database_message* message = (database_message*)async->args; if(!cancel) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_IXFR (alarm)", message->origin); async_message_call(&database_handler_queue, async); } else { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_QUERY_IXFR cancelled (alarm)", message->origin); database_load_message_free((database_message*)async->args); async_message_release(async); } return SUCCESS; } void database_zone_ixfr_query_at(const u8 *origin, time_t at) { log_debug("database: %{dnsname}: will enqueue operation DATABASE_SERVICE_QUERY_IXFR at %T", origin, at); zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, origin); if(zone == NULL) { log_warn("database: %{dnsname}: arming IXFR query: zone not in database", origin); return; } database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_QUERY_IXFR); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; alarm_event_node *event = alarm_event_new( // ixfr query at, ALARM_KEY_ZONE_AXFR_QUERY, database_zone_ixfr_query_alarm, async, ALARM_DUP_REMOVE_LATEST, "database-zone-ixfr-query-alarm"); alarm_set(zone->alarm_handle, event); zdb_zone_release(zone); } #define DATABASE_ZONE_RECONFIGURE_ALL 3 #define DATABASE_ZONE_RECONFIGURE_ZONES 2 #define DATABASE_ZONE_RECONFIGURE_ZONE 1 // keys+zones (a.k.a everything), zones, zone static smp_int database_zone_reconfigure_queued = SMP_INT_INITIALIZER; static ptr_set database_zone_reconfigure_fqdn = PTR_SET_DNSNAME_EMPTY; bool database_zone_is_reconfigure_enabled() { return smp_int_get(&database_reconfigure_enable_count) > 0; } bool database_zone_try_reconfigure_enable() { bool ret = smp_int_setifequal(&database_reconfigure_enable_count, 0, 1); if(ret) { log_info("database: reconfigure started"); } else { log_info("database: reconfigure already running"); } return ret; } static void database_zone_postpone_reconfigure_fqdn_destroy_cb(ptr_node *node) { dnsname_zfree(node->key); node->key = NULL; node->value = NULL; } static void database_zone_postpone_reconfigure_fqdn_destroy() { ptr_set_callback_and_destroy(&database_zone_reconfigure_fqdn, database_zone_postpone_reconfigure_fqdn_destroy_cb); } void database_zone_postpone_reconfigure_all() { log_info("database: postponing reconfigure all"); mutex_lock(&database_zone_reconfigure_queued.mutex); database_zone_reconfigure_queued.value = DATABASE_ZONE_RECONFIGURE_ALL; database_zone_postpone_reconfigure_fqdn_destroy(); mutex_unlock(&database_zone_reconfigure_queued.mutex); } void database_zone_postpone_reconfigure_zones() { log_info("database: postponing reconfigure zones"); mutex_lock(&database_zone_reconfigure_queued.mutex); if(database_zone_reconfigure_queued.value < DATABASE_ZONE_RECONFIGURE_ZONES) { database_zone_reconfigure_queued.value = DATABASE_ZONE_RECONFIGURE_ZONES; database_zone_postpone_reconfigure_fqdn_destroy(); } mutex_unlock(&database_zone_reconfigure_queued.mutex); } void database_zone_postpone_reconfigure_zone(const ptr_set *fqdn_set) { log_info("database: postponing reconfigure of a set of zones"); mutex_lock(&database_zone_reconfigure_queued.mutex); if(database_zone_reconfigure_queued.value <= DATABASE_ZONE_RECONFIGURE_ZONE) { database_zone_reconfigure_queued.value = DATABASE_ZONE_RECONFIGURE_ZONE; ptr_set_iterator iter; ptr_set_iterator_init(fqdn_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *src_node = ptr_set_iterator_next_node(&iter); ptr_node *node = ptr_set_insert(&database_zone_reconfigure_fqdn, src_node->key); if(node->value == NULL) { node->key = dnsname_zdup((const u8*)src_node->key); node->value = node->key; } } } mutex_unlock(&database_zone_reconfigure_queued.mutex); } static void database_service_config_update_callback(void *args_, bool delete_only) { (void)args_; if(!delete_only) { log_debug("database: try running postponed reconfigure"); yadifad_config_update(g_config->config_file); } } void database_service_config_update() { log_debug("database: will run postponed reconfigure"); database_post_callback(database_service_config_update_callback, NULL, "reconfigure-update-all"); } static void database_service_config_update_all_zones_callback(void *args_, bool delete_only) { (void)args_; if(!delete_only) { log_debug("database: try running postponed reconfigure all zones"); yadifad_config_update_zone(g_config->config_file, NULL); } } void database_service_config_update_all_zones() { log_debug("database: will run postponed reconfigure all zones"); database_post_callback(database_service_config_update_all_zones_callback, NULL, "reconfigure-update-all-zones"); } static void database_service_config_update_zones_callback(void *args_, bool delete_only) { ptr_set fqdn_set = {args_, ptr_set_dnsname_node_compare}; if(!delete_only) { log_debug("database: try running postponed reconfigure some zones"); yadifad_config_update_zone(g_config->config_file, &fqdn_set); } ptr_set_callback_and_destroy(&fqdn_set, database_zone_postpone_reconfigure_fqdn_destroy_cb); } void database_service_config_update_zones(ptr_set *fqdn_set) { yassert(fqdn_set->compare == ptr_set_dnsname_node_compare); log_debug("database: running postponed reconfigure of a set of zones"); database_post_callback(database_service_config_update_zones_callback, fqdn_set->root, "reconfigure-update-some-zones"); } void database_zone_reconfigure_disable() { log_info("database: reconfigure done"); mutex_lock(&database_zone_reconfigure_queued.mutex); int queue = database_zone_reconfigure_queued.value; database_zone_reconfigure_queued.value = 0; ptr_set fqdn_set = database_zone_reconfigure_fqdn; // move the tree database_zone_reconfigure_fqdn.root = NULL; mutex_unlock(&database_zone_reconfigure_queued.mutex); // a copy of the queue and the fqdns is ready smp_int_set(&database_reconfigure_enable_count, 0); switch(queue) { case DATABASE_ZONE_RECONFIGURE_ALL: { database_service_config_update(); break; } case DATABASE_ZONE_RECONFIGURE_ZONES: { database_service_config_update_all_zones(); break; } case DATABASE_ZONE_RECONFIGURE_ZONE: default: { if(!ptr_set_isempty(&fqdn_set)) { database_service_config_update_zones(&fqdn_set); } break; } } ptr_set_callback_and_destroy(&fqdn_set, database_zone_postpone_reconfigure_fqdn_destroy_cb); } void database_set_drop_after_reload_for_set(const ptr_set* set) { log_debug("database: enqueue operation DATABASE_SERVICE_SET_DROP_AFTER_RELOAD of a subset"); database_message *message = database_load_message_alloc(database_all_origins, DATABASE_SERVICE_SET_DROP_AFTER_RELOAD); if(set != NULL) { message->payload.drop_after_reload.zone_set.root = NULL; message->payload.drop_after_reload.zone_set.compare = ptr_set_dnsname_node_compare; message->payload.drop_after_reload.do_subset = TRUE; ptr_set_iterator iter; ptr_set_iterator_init(set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_insert(&message->payload.drop_after_reload.zone_set, ptr_set_iterator_next_node(&iter)->key); node->key = dnsname_zdup(node->key); } } else { message->payload.drop_after_reload.do_subset = FALSE; } async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } static void database_clear_drop_after_reload() { log_debug("database: enqueue operation DATABASE_SERVICE_CLEAR_DROP_AFTER_RELOAD"); database_message *message = database_load_message_alloc(database_all_origins, DATABASE_SERVICE_CLEAR_DROP_AFTER_RELOAD); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } static void database_do_drop_after_reload() { log_debug("database: enqueue operation DATABASE_SERVICE_DO_DROP_AFTER_RELOAD"); database_message *message = database_load_message_alloc(database_all_origins, DATABASE_SERVICE_DO_DROP_AFTER_RELOAD); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } /// Chain of events: reconfigure end (last part) static void database_zone_reconfigure_disable_when_processed_part2(void *args_, bool delete_only) { (void)args_; (void)delete_only; database_zone_reconfigure_disable(); } /// Chain of events: reconfigure end (first part) static void database_zone_reconfigure_disable_when_processed_part1(void *args_, bool delete_only) { if(!delete_only) { if(args_ != NULL) { log_info("database: will drop marked zones not defined in current configuration"); database_do_drop_after_reload(); } else { log_info("database: will clear drop marked zone status"); database_clear_drop_after_reload(); } } else { log_info("database: deleting event ?"); } database_post_callback(database_zone_reconfigure_disable_when_processed_part2, NULL, "reconfigure-queue-disable"); } /** * Chain of events: reconfigure end (init) * * When the database will have finished processing the queue at its current state, a callback handling drop-after-reload will be called * Then, after this handling has been done, the reconfigure mode will be disabled (enabling configure again) * * @param do_drop_after_reload */ void database_zone_reconfigure_do_drop_and_disable(bool do_drop_after_reload) { if(do_drop_after_reload) { log_debug("database: will run reconfigure do drop and disable"); } else { log_debug("database: will run reconfigure clear drop and disable"); } void *args = do_drop_after_reload?(void*)1:(void*)0; database_post_callback(database_zone_reconfigure_disable_when_processed_part1, args, "reconfigure-queue-handle-drop-after-reload"); } void database_fire_zone_loaded(zone_desc_s *zone_desc, zdb_zone *zone, ya_result result_code) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_LOADED_EVENT (%r)", zone_origin(zone_desc), result_code); database_message *message = database_load_message_alloc(zone_origin(zone_desc), DATABASE_SERVICE_ZONE_LOADED_EVENT); zone_acquire(zone_desc); if(zone != NULL) { zdb_zone_acquire(zone); } message->payload.zone_loaded_event.zone_desc = zone_desc; message->payload.zone_loaded_event.zone = zone; message->payload.zone_loaded_event.result_code = result_code; async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_fire_zone_mounted(zone_desc_s *zone_desc, zdb_zone *zone, ya_result result_code) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_MOUNTED_EVENT (%r)", zone_origin(zone_desc), result_code); database_message *message = database_load_message_alloc(zone_origin(zone_desc), DATABASE_SERVICE_ZONE_MOUNTED_EVENT); zone_acquire(zone_desc); if(zone != NULL) { zdb_zone_acquire(zone); } message->payload.zone_mounted_event.zone_desc = zone_desc; message->payload.zone_mounted_event.zone = zone; message->payload.zone_mounted_event.result_code = result_code; async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_fire_zone_unloaded(zdb_zone *zone, ya_result result_code) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_UNLOADED_EVENT (%r)", zone->origin, result_code); database_message *message = database_load_message_alloc(zone->origin, DATABASE_SERVICE_ZONE_UNLOADED_EVENT); zdb_zone_acquire(zone); message->payload.zone_unloaded_event.zone = zone; message->payload.zone_unloaded_event.result_code = result_code; async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_fire_zone_unmounted(zone_desc_s *zone_desc) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT", zone_origin(zone_desc)); database_message *message = database_load_message_alloc(zone_origin(zone_desc), DATABASE_SERVICE_ZONE_UNMOUNTED_EVENT); zone_acquire(zone_desc); message->payload.zone_unmounted_event.zone_desc = zone_desc; async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_fire_zone_processed(zone_desc_s *zone_desc) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_PROCESSED", zone_origin(zone_desc)); database_message *message = database_load_message_alloc(zone_origin(zone_desc), DATABASE_SERVICE_ZONE_PROCESSED); async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_post_callback(database_message_callback_function callback, void *args, const char * const name) { log_debug("database: enqueue operation DATABASE_SERVICE_CALLBACK %s", name); database_message *message = database_load_message_alloc(database_all_origins, DATABASE_SERVICE_CALLBACK); message->payload.callback.callback = callback; message->payload.callback.args = args; message->payload.callback.timestamp = timeus(); message->payload.callback.name = name; async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_fire_zone_downloaded(const u8 *origin, u16 qtype, u32 serial, ya_result result_code) { if(ISOK(result_code)) { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT type=%{dnstype} serial=%u (%r)", origin, &qtype, serial, result_code); } else { log_debug("database: %{dnsname}: enqueue operation DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT (%r)", origin, result_code); } database_message *message = database_load_message_alloc(origin, DATABASE_SERVICE_ZONE_DOWNLOADED_EVENT); message->payload.zone_downloaded_event.download_type = qtype; message->payload.zone_downloaded_event.serial = serial; message->payload.zone_downloaded_event.result_code = result_code; async_message_s *async = async_message_alloc(); async->id = message->payload.type; async->args = message; async->handler = NULL; async->handler_args = NULL; async_message_call(&database_handler_queue, async); } void database_service_zone_load_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname) { thread_pool_enqueue_call(database_zone_load_thread_pool, func, parm, counter, categoryname); } void database_service_zone_store_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char *categoryname) { thread_pool_enqueue_call(database_zone_store_thread_pool, func, parm, counter, categoryname); } void database_service_zone_unload_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname) { thread_pool_enqueue_call(database_zone_unload_thread_pool, func, parm, counter, categoryname); } static void* database_service_run_garbage_collector_thread(void *parms_) { (void)parms_; zdb_zone_garbage_run(); return NULL; } void database_service_run_garbage_collector() { if(database_zone_unload_thread_pool != NULL) { thread_pool_enqueue_call(database_zone_unload_thread_pool, database_service_run_garbage_collector_thread, NULL, NULL, "garbage"); } } static void* database_callback_thread(void *parms_) { database_message_callback_s *callback = (database_message_callback_s*)parms_; if(callback->type == DATABASE_SERVICE_CALLBACK) { log_debug("database: executing %s callback from %llT", callback->name, callback->timestamp); callback->callback(callback->args, FALSE); ZFREE_OBJECT(callback); } else { log_err("database: got an invalid callback"); } return NULL; } static void database_callback_run(database_message *message) { database_message_callback_s *cb; ZALLOC_OBJECT_OR_DIE(cb, database_message_callback_s, DBMSGCB_TAG); *cb = message->payload.callback; thread_pool_enqueue_call(database_callback_thread_pool, database_callback_thread, cb, NULL, "callback"); } // void database_service_zone_download_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname) { thread_pool_enqueue_call(database_zone_download_thread_pool, func, parm, counter, categoryname); } #if ZDB_HAS_DNSSEC_SUPPORT #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT void database_service_zone_resignature_queue_thread(thread_pool_function func, void *parm, thread_pool_task_counter *counter, const char* categoryname) { thread_pool_enqueue_call(database_zone_resignature_thread_pool, func, parm, counter, categoryname); } #endif #endif void database_service_create_invalid_zones() { zone_set_lock(&database_zone_desc); // unlock checked if(!ptr_set_isempty(&database_zone_desc.set)) { ptr_set_iterator iter; ptr_set_iterator_init(&database_zone_desc.set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value; zdb_zone *invalid_zone = zdb_zone_create(zone_origin(zone_desc)); // RC = 1 zdb_zone_invalidate(invalid_zone); zdb_zone *old_zone = zdb_set_zone(g_config->database, invalid_zone); // RC ++ yassert(old_zone == NULL); (void)old_zone; zdb_zone_release(invalid_zone); } } zone_set_unlock(&database_zone_desc); } bool database_service_is_running() { return service_started(&database_handler); } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database.c0000644000000000000000000000013214505005533020603 xustar000000000000000030 mtime=1695812443.521997642 30 atime=1695812445.784030039 30 ctime=1695812495.644744144 yadifa-2.6.5-11201/sbin/yadifad/database.c0000664000374500037450000022431114505005533020550 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include #include #include #include #include #include #include #if ZDB_HAS_DNSSEC_SUPPORT #include #endif #include #include #include #if HAS_DYNUPDATE_SUPPORT #include #endif #include #include #include #include #include #include #include #include #include #include "server.h" #include "database.h" #include "database-service.h" #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_DNSSEC_SUPPORT #include "database-service-zone-resignature.h" #endif #include "server_error.h" #include "config_error.h" #include "notify.h" #include "zone.h" #include "zone_desc.h" #if HAS_RRL_SUPPORT #include "rrl.h" #endif #include "dnsdb/dynupdate-diff.h" #ifndef HAS_DYNUPDATE_DIFF_ENABLED #error "HAS_DYNUPDATE_DIFF_ENABLED not defined" #endif #define DBSCHEDP_TAG 0x5044454843534244 #define DBREFALP_TAG 0x504c414645524244 #define DNSSEC_KEY_PARAMETERS_TAG 0x4d5059454b534e44 #define MODULE_MSG_HANDLE g_server_logger typedef struct database_zone_refresh_alarm_args database_zone_refresh_alarm_args; struct database_zone_refresh_alarm_args { const u8 *origin; }; /* Zone file variables */ extern zone_data_set database_zone_desc; /*------------------------------------------------------------------------------ * FUNCTIONS */ static zdb_zone_path_provider_callback *database_zone_path_next_provider = NULL; static zdb_zone_info_provider_callback *database_info_next_provider = NULL; /** * The hash function that gives a number from an ASCIIZ string * * @param p ASCIIZ string * * @return the hash */ static u32 database_zone_path_provider_name_hash(const u8 *p) { u32 h = 0; u32 c; u8 s = 0; do { c = toupper(*p++); c &= 0x3f; h += c << (s & 15); h += 97; s += 13; } while(c != 0); return h; } /** * * Returns the hashed folder path for a zone. * * @param data_path the target buffer for the data path * @param data_path_size the target buffer size * @param base_data_path the base folder * @param origin the origin of the zone * * @return */ static ya_result database_zone_path_provider_get_hashed_name(char *data_path, u32 data_path_size, const char *base_data_path, const u8 *origin) { u32 h = database_zone_path_provider_name_hash(origin); return snformat(data_path, data_path_size, "%s/%02x/%02x", base_data_path, h & 0xff, (h >> 8) & 0xff); } static ya_result database_zone_path_provider(const u8* domain_fqdn, char *path_buffer, u32 path_buffer_size, u32 flags) { ya_result ret = ZDB_ERROR_ZONE_NOT_IN_DATABASE; #if DEBUG char *original_path_buffer = path_buffer; u32 original_flags = flags; original_path_buffer[0] = '\0'; #endif char *suffix = ""; if((flags & ZDB_ZONE_PATH_PROVIDER_RNDSUFFIX) != 0) { flags &= ~ZDB_ZONE_PATH_PROVIDER_RNDSUFFIX; suffix = ".part"; } zone_desc_s *zone_desc = zone_acquirebydnsname(domain_fqdn); if(zone_desc != NULL) { if((zone_desc->file_name == NULL) || (g_config->data_path == NULL)) { zone_release(zone_desc); log_err("database: path provider: zone file name or data path not set"); return INVALID_STATE_ERROR; } const char *base_data_path = (zone_desc->file_name[0] != '/')?g_config->data_path:""; switch(flags & ~ZDB_ZONE_PATH_PROVIDER_MKDIR) { case ZDB_ZONE_PATH_PROVIDER_ZONE_PATH: { if(ISOK(ret = snformat(path_buffer, path_buffer_size, "%s%s", base_data_path, zone_desc->file_name))) { int n = ret; while(n > 0) { if(path_buffer[n] == '/') { path_buffer[n] = '\0'; break; } n--; } if((flags & ZDB_ZONE_PATH_PROVIDER_MKDIR) != 0) { ya_result err = mkdir_ex(path_buffer, 0750, 0); if(FAIL(err) && (err != MAKE_ERRNO_ERROR(EEXIST))) { log_err("database: zone path mkdir: could not create '%s': %r", path_buffer, err); } //flags &= ~ZDB_ZONE_PATH_PROVIDER_MKDIR; } } break; } case ZDB_ZONE_PATH_PROVIDER_ZONE_FILE: { if(ISOK(ret = snformat(path_buffer, path_buffer_size, "%s%s%s", base_data_path, zone_desc->file_name, suffix))) { if((flags & ZDB_ZONE_PATH_PROVIDER_MKDIR) != 0) { ya_result err = mkdir_ex(path_buffer, 0750, MKDIR_EX_PATH_TO_FILE); if(FAIL(err) && (err != MAKE_ERRNO_ERROR(EEXIST))) { log_err("database: zone file mkdir: could not create '%s': %r", path_buffer, err); } //flags &= ~ZDB_ZONE_PATH_PROVIDER_MKDIR; } } break; } case ZDB_ZONE_PATH_PROVIDER_AXFR_PATH: { if(g_config->xfr_path != NULL) { if(ISOK(ret = database_zone_path_provider_get_hashed_name(path_buffer, path_buffer_size, g_config->xfr_path, domain_fqdn))) { if((flags & ZDB_ZONE_PATH_PROVIDER_MKDIR) != 0) { ya_result err = mkdir_ex(path_buffer, 0750, 0); if(FAIL(err) && (err != MAKE_ERRNO_ERROR(EEXIST))) { log_err("database: axfr path mkdir: could not create '%s': %r", path_buffer, err); } //flags &= ~ZDB_ZONE_PATH_PROVIDER_MKDIR; } } } else { log_err("database: path provider: transfer base path not set"); ret = INVALID_STATE_ERROR; } break; } case ZDB_ZONE_PATH_PROVIDER_AXFR_FILE: { if(ISOK(ret = database_zone_path_provider_get_hashed_name(path_buffer, path_buffer_size, g_config->xfr_path, domain_fqdn))) { if((flags & ZDB_ZONE_PATH_PROVIDER_MKDIR) != 0) { ya_result err = mkdir_ex(path_buffer, 0750, 0); if(FAIL(err) && (err != MAKE_ERRNO_ERROR(EEXIST))) { log_err("database: axfr file mkdir: could not create '%s': %r", path_buffer, err); } //flags &= ~ZDB_ZONE_PATH_PROVIDER_MKDIR; } s32 path_size = ret; path_buffer += ret; path_buffer_size -= ret; if(ISOK(ret = snformat(path_buffer, path_buffer_size, "/%{dnsname}.axfr%s", domain_fqdn, suffix))) { ret += path_size; } } break; } case ZDB_ZONE_PATH_PROVIDER_DNSKEY_PATH: { if(zone_desc->keys_path != NULL) { if(zone_desc->keys_path[0] != '/') { ret = snformat(path_buffer, path_buffer_size, "%s/%s", g_config->data_path, zone_desc->keys_path); } else { ret = snformat(path_buffer, path_buffer_size, "%s", zone_desc->keys_path); } } else { ret = snformat(path_buffer, path_buffer_size, "%s/", g_config->keys_path); } break; } default: { ret = database_zone_path_next_provider(domain_fqdn, path_buffer, path_buffer_size, flags); break; } } zone_release(zone_desc); } #if DEBUG log_debug("path-provider: %{dnsname}: %02x: path='%s': %r", domain_fqdn, original_flags, original_path_buffer, ret); #endif return ret; } static ya_result database_info_provider(const u8 *origin, zdb_zone_info_provider_data *data, u32 flags) { ya_result ret = ZONE_NOT_DEFINED; switch(flags) { case ZDB_ZONE_INFO_PROVIDER_STORED_SERIAL: { // get the zone desc and check zone_desc_s *zone_desc = zone_acquirebydnsname(origin); if(zone_desc != NULL) { data->_u32 = zone_desc->stored_serial; zone_release(zone_desc); ret = SUCCESS; } break; } case ZDB_ZONE_INFO_PROVIDER_MAX_JOURNAL_SIZE: { // get the zone desc and check zone_desc_s *zone_desc = zone_acquirebydnsname(origin); if(zone_desc != NULL) { yassert(zone_desc->journal_size_kb <= 8388608); u64 max_size = zone_desc->journal_size_kb; if(max_size > 0) { // the size has been set by the admin max_size *= 1024; } else if(data->_u64 != 0) { // the caller gave the half the wire size of the zone max_size = data->_u64; } else { // nothing has been set, we have to look for the current mounted zone for its wire size zone_lock(zone_desc, ZONE_LOCK_LOAD); zdb_zone *zone = zone_get_loaded_zone(zone_desc); zone_unlock(zone_desc, ZONE_LOCK_LOAD); if(zone != NULL) { max_size = zone->wire_size >> 1; zdb_zone_release(zone); } else { // no zone found, return the default size max_size = DATABASE_JOURNAL_MINIMUM_SIZE; } } zone_release(zone_desc); if(max_size < DATABASE_JOURNAL_MINIMUM_SIZE) { max_size = DATABASE_JOURNAL_MINIMUM_SIZE; } if(max_size > MAX_U32) // current limitation { max_size = MAX_U32; } log_debug("database: %{dnsname} journal size set to %uKB", origin, max_size >> 10); data->_u64 = max_size; ret = SUCCESS; } break; } case ZDB_ZONE_INFO_PROVIDER_ZONE_TYPE: { // get the zone desc and check zone_desc_s *zone_desc = zone_acquirebydnsname(origin); if(zone_desc != NULL) { data->_u8 = (u8)zone_desc->type; zone_release(zone_desc); ret = SUCCESS; } break; } case ZDB_ZONE_INFO_PROVIDER_STORE_TRIGGER: { database_zone_store(origin); ret = SUCCESS; break; } case ZDB_ZONE_INFO_PROVIDER_STORE_NOW: { zone_desc_s *zone_desc = zone_acquirebydnsname(origin); if(zone_desc != NULL) { ret = database_service_zone_store_ex(zone_desc, 0, data->_u8, DATABASE_SERVICE_ZONE_SAVE_IGNORE_SHUTDOWN); } else { ret = ZONE_NOT_DEFINED; } break; } case ZDB_ZONE_INFO_PROVIDER_STORE_IN_PROGRESS: { zone_desc_s *zone_desc = zone_acquirebydnsname(origin); if(zone_desc != NULL) { bool saving = (zone_get_status(zone_desc) & (ZONE_STATUS_SAVETO_ZONE_FILE|ZONE_STATUS_SAVING_ZONE_FILE)) != 0; zone_release(zone_desc); ret = saving?1:0; } else { ret = ZONE_NOT_DEFINED; } break; } default: { ret = database_info_next_provider(origin, data, flags); break; } } return ret; } /** * Initialises the database. * Ensures the libraries features are matched. * */ void database_init() { zdb_init(); dnscore_reset_timer(); database_zone_path_next_provider = zdb_zone_path_get_provider(); zdb_zone_path_set_provider(database_zone_path_provider); database_info_next_provider = zdb_zone_info_get_provider(); zdb_zone_info_set_provider(database_info_provider); } void database_finalize() { zdb_zone_path_set_provider(NULL); zdb_zone_info_set_provider(NULL); zdb_finalize(); } /** @brief Remove the zones from the database, * but do not remove the database file * * @param[in] database * @param[in] zone * * @retval OK */ ya_result database_clear_zones(zdb *database, zone_data_set *dset) { dnsname_vector fqdn_vector; zone_set_lock(dset); // unlock checked ptr_set_iterator iter; ptr_set_iterator_init(&dset->set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value; dnsname_to_dnsname_vector(zone_origin(zone_desc), &fqdn_vector); zdb_zone *myzone = zdb_remove_zone(database, &fqdn_vector); if(myzone != NULL) { zdb_zone_release(myzone); } } zone_set_unlock(dset); return OK; } /** @brief Creates the (IN) database * * Starts to load the content. * * @param[out] database pointer to a pointer to the database * * @return an error code */ /** * @NOTE THIS IS SUPPOSED TO BE RUN BEFORE THE SERVER STARTS ! */ ya_result database_startup(zdb **database) { ya_result return_code; zdb* db; /* ------------------------------------------------------------ */ if(g_config->data_path == NULL) { return CONFIG_ZONE_ERR; } *database = NULL; database_init(); /* Inits the db, starts the threads of the pool, resets the timer */ MALLOC_OBJECT_OR_DIE(db, zdb, ZDBCLASS_TAG); zdb_create(db); // add all the registered zones as invalid *database = db; database_service_create_invalid_zones(); #if ZDB_HAS_DNSSEC_SUPPORT dnssec_keystore_reload(); #endif if(ISOK(return_code = database_service_start())) { database_load_all_zones(); } return return_code; } #if HAS_DYNUPDATE_SUPPORT #if ZDB_HAS_DNSSEC_SUPPORT struct dnssec_key_parameters_s { const u8 *fqdn; u16 tag; u16 flags; u8 algorithm; }; typedef struct dnssec_key_parameters_s dnssec_key_parameters_t; /** * Adds key parameters from keys in the zone to a vector */ void database_add_key_parameters_from_zone(zdb_zone *zone, ptr_vector *keys) { const zdb_packed_ttlrdata *dnskey_rrset = zdb_zone_get_dnskey_rrset(zone); // zone is locked if(dnskey_rrset != NULL) { do { dnssec_key_parameters_t *parameters; ZALLOC_OBJECT_OR_DIE(parameters, dnssec_key_parameters_t, DNSSEC_KEY_PARAMETERS_TAG); parameters->fqdn = zone->origin; parameters->tag = DNSKEY_TAG(*dnskey_rrset); parameters->flags = DNSKEY_FLAGS(*dnskey_rrset); parameters->algorithm = DNSKEY_ALGORITHM(*dnskey_rrset); ptr_vector_append(keys, parameters); dnskey_rrset = dnskey_rrset->next; } while(dnskey_rrset != NULL); } } /** * Adds key parameters from keys added by the message to a vector. * Adds key parameters from keys removed by the message to a vector, removes said keys from the "added" vector. */ ya_result database_add_key_parameters_from_message(zdb_zone *zone, message_data *mesg, ptr_vector *keys, ptr_vector *removed_keys) { packet_unpack_reader_data pr; ya_result ret = SUCCESS; packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_skip_section(&pr, 0))) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(FAIL(packet_reader_skip_section(&pr, 1))) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } // scan for added DNSKEY for(u16 records = message_get_authority_count(mesg); records > 0; --records) { struct type_class_ttl_rdlen tctr; u8 fqdn[MAX_DOMAIN_LENGTH]; if(FAIL(ret = packet_reader_read_fqdn(&pr ,fqdn, sizeof(fqdn)))) { break; } if(FAIL(ret = packet_reader_read(&pr, &tctr, 10))) // exact { break; } tctr.rdlen = ntohs(tctr.rdlen); if(tctr.qclass == CLASS_IN) { // load it if(tctr.qtype == TYPE_DNSKEY) { const void *rdata = packet_reader_get_current_ptr_const(&pr, tctr.rdlen); if(rdata != NULL) { dnssec_key_parameters_t *parameters; ZALLOC_OBJECT_OR_DIE(parameters, dnssec_key_parameters_t, DNSSEC_KEY_PARAMETERS_TAG); parameters->fqdn = zone->origin; parameters->tag = dnskey_get_tag_from_rdata(rdata, tctr.rdlen); parameters->flags = dnskey_get_flags_from_rdata(rdata); parameters->algorithm = dnskey_get_algorithm_from_rdata(rdata); ptr_vector_append(keys, parameters); } else { // short read: // ret = UNEXPECTED_EOF; break; } } } else if(tctr.qclass == CLASS_NONE) { if(tctr.qtype == TYPE_DNSKEY) { const void *rdata = packet_reader_get_current_ptr_const(&pr, tctr.rdlen); if(rdata != NULL) { for(int i = 0; i <= ptr_vector_last_index(keys); ++i) { dnssec_key_parameters_t parameters; parameters.fqdn = zone->origin; // useless parameters.tag = dnskey_get_tag_from_rdata(rdata, tctr.rdlen); parameters.flags = dnskey_get_flags_from_rdata(rdata); parameters.algorithm = dnskey_get_algorithm_from_rdata(rdata); dnssec_key_parameters_t *key_i = (dnssec_key_parameters_t*)ptr_vector_get(keys, i); if((key_i->fqdn == parameters.fqdn) && (key_i->tag == parameters.tag) && (key_i->flags == parameters.flags) && (key_i->algorithm == parameters.algorithm)) { // found a match ptr_vector_remove_at(keys, i); ptr_vector_append(removed_keys, key_i); } } } } } else if(tctr.qclass == CLASS_ANY) { if(tctr.qtype == TYPE_DNSKEY) { ptr_vector_append_vector(keys, removed_keys); ptr_vector_clear(keys); } } if(FAIL(ret = packet_reader_skip(&pr, tctr.rdlen))) { break; } } return ret; } /** * Loads the private keys (and public keys, of course) whose parameters are listed in the vector. */ ya_result database_ensure_private_keys_from_key_parameters_vector(zdb_zone *zone, ptr_vector *keys) { ya_result ret; int ksk_count = 0; int zsk_count = 0; int new_count = 0; for(int i = 0; i <= ptr_vector_last_index(keys); ++i) { dnssec_key_parameters_t *key_i = (dnssec_key_parameters_t*)ptr_vector_get(keys, i); dnssec_key *key = NULL; if(ISOK(ret = dnssec_keystore_load_private_key_from_parameters(key_i->algorithm, key_i->tag, key_i->flags, key_i->fqdn, &key))) // key properly released { new_count += ret; if(key_i->flags == DNSKEY_FLAGS_KSK) { ++ksk_count; } else if(key_i->flags == DNSKEY_FLAGS_ZSK) { ++zsk_count; } else { // the key is of no use } dnskey_release(key); } else { // only complain if KSKs RRSIGs are not meant to be pushed if( !( (key_i->flags == DNSKEY_FLAGS_KSK) && zdb_zone_get_rrsig_push_allowed(zone) ) ) { log_warn("database: update: unable to load the private key 'K%{dnsname}+%03d+%05hd': %r", zone->origin, key_i->algorithm, key_i->tag, ret); } } } ret = new_count; if(zsk_count == 0) { log_err("database: update: unable to load any of the ZSK private keys of zone %{dnsname}", zone->origin); ret = DNSSEC_ERROR_RRSIG_NOUSABLEKEYS; } if(ksk_count == 0) { if(!zdb_zone_get_rrsig_push_allowed(zone)) { log_warn("database: update: unable to load any of the KSK private keys of zone %{dnsname}", zone->origin); } else { log_debug("database: update: unable to load any of the KSK private keys of zone %{dnsname}", zone->origin); } } return ret; } void dnssec_key_parameters_vector_destroy(ptr_vector *keys) { for(int i = 0; i <= ptr_vector_last_index(keys); ++i) { dnssec_key_parameters_t *key_i = (dnssec_key_parameters_t*)ptr_vector_get(keys, i); ZFREE_OBJECT(key_i); } ptr_vector_destroy(keys); } /** * Loads private keys for the zone. * Returns the number of keys loaded or an error code. */ ya_result database_zone_ensure_private_keys(zdb_zone *zone) { ya_result return_code; /* * Fetch all private keys */ log_debug("database: update: checking DNSKEY availability"); const zdb_packed_ttlrdata *dnskey_rrset = zdb_zone_get_dnskey_rrset(zone); // zone is locked int ksk_count = 0; int zsk_count = 0; int new_count = 0; if(dnskey_rrset != NULL) { do { u16 flags = DNSKEY_FLAGS(*dnskey_rrset); u8 algorithm = DNSKEY_ALGORITHM(*dnskey_rrset); u16 tag = DNSKEY_TAG(*dnskey_rrset); // note: expensive dnssec_key *key = NULL; if(ISOK(return_code = dnssec_keystore_load_private_key_from_parameters(algorithm, tag, flags, zone->origin, &key))) // key properly released { // if return_code is 0, nothing new was loaded new_count += return_code; if(flags == DNSKEY_FLAGS_KSK) { ++ksk_count; } else if(flags == DNSKEY_FLAGS_ZSK) { ++zsk_count; } else { // the key is of no use } dnskey_release(key); } else { // only complain if KSKs RRSIGs are not meant to be pushed if( !( (flags == DNSKEY_FLAGS_KSK) && zdb_zone_get_rrsig_push_allowed(zone) ) ) { log_warn("database: update: unable to load the private key 'K%{dnsname}+%03d+%05hd': %r", zone->origin, algorithm, tag, return_code); } } dnskey_rrset = dnskey_rrset->next; } while(dnskey_rrset != NULL); return_code = new_count; if(zsk_count == 0) { log_err("database: update: unable to load any of the ZSK private keys of zone %{dnsname}", zone->origin); return_code = DNSSEC_ERROR_RRSIG_NOUSABLEKEYS; } if(ksk_count == 0) { if(!zdb_zone_get_rrsig_push_allowed(zone)) { log_warn("database: update: unable to load any of the KSK private keys of zone %{dnsname}", zone->origin); } else { log_debug("database: update: unable to load any of the KSK private keys of zone %{dnsname}", zone->origin); } } } else { log_err("database: update: there are no private keys in the zone %{dnsname}", zone->origin); return_code = DNSSEC_ERROR_RRSIG_NOZONEKEYS; } return return_code; } /** * Scans added DNSKEYs from the message, load their private keys. * Returns the number of keys added or an error code. */ ya_result database_zone_ensure_private_keys_from_message(message_data *mesg) { packet_unpack_reader_data pr; dnssec_key *key; ya_result ret = SUCCESS; s32 new_key_added = 0; bool all_keys_removed = FALSE; packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_skip_section(&pr, 0))) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } if(FAIL(packet_reader_skip_section(&pr, 1))) { return MAKE_DNSMSG_ERROR(RCODE_FORMERR); } // scan for added DNSKEY for(u16 records = message_get_authority_count(mesg); records > 0; --records) { struct type_class_ttl_rdlen tctr; u8 fqdn[MAX_DOMAIN_LENGTH]; if(FAIL(ret = packet_reader_read_fqdn(&pr ,fqdn, sizeof(fqdn)))) { break; } if(FAIL(ret = packet_reader_read(&pr, &tctr, 10))) // exact { break; } tctr.rdlen = ntohs(tctr.rdlen); if(tctr.qclass == CLASS_IN) { // load it if(tctr.qtype == TYPE_DNSKEY) { const void *rdata = packet_reader_get_current_ptr_const(&pr, tctr.rdlen); if(rdata != NULL) { if(ISOK(ret = dnssec_keystore_load_private_key_from_rdata(rdata, tctr.rdlen, fqdn, &key))) { log_info("database: update: update will be adding 'K%{dnsname}+%03d+%05hd': %r", fqdn, ntohs(dnskey_get_flags(key)), dnskey_get_tag_const(key), ret); new_key_added += ret; dnskey_release(key); } } else { // short read: ret = UNEXPECTED_EOF; break; } } } else if(tctr.qclass == CLASS_ANY) { if(tctr.qtype == TYPE_DNSKEY) { all_keys_removed = TRUE; } } if(FAIL(ret = packet_reader_skip(&pr, tctr.rdlen))) { break; } } // if at least one key was added, return the count, else if there is an error, return it, else return 0 return (new_key_added > 0)?new_key_added:(all_keys_removed)?0x40000000:FAIL(ret)?ret:0; } #endif // ZDB_ZONE_MUTEX_DYNUPDATE ya_result database_apply_nsec3paramqueued(zdb_zone *zone, zdb_packed_ttlrdata *rrset, u8 lock_owner) { ya_result ret = SUCCESS; if(rrset != NULL) { const u8 *rdata = ZDB_PACKEDRECORD_PTR_RDATAPTR(rrset); u32 rdata_size = ZDB_PACKEDRECORD_PTR_RDATASIZE(rrset); u8 algorithm = NSEC3PARAM_RDATA_ALGORITHM(rdata); u16 iterations = NSEC3PARAM_RDATA_ITERATIONS(rdata); const u8 *salt = NSEC3PARAM_RDATA_SALT(rdata); u8 salt_len = NSEC3PARAM_RDATA_SALT_LEN(rdata); u8 optout = ((zone_get_maintain_mode(zone) & ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT) == ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT)?1:0; if(ISOK(ret = nsec3_zone_set_status(zone, lock_owner, algorithm, optout, iterations, salt, salt_len, NSEC3_ZONE_ENABLED|NSEC3_ZONE_GENERATING))) { dynupdate_message dmsg; packet_unpack_reader_data reader; dynupdate_message_init(&dmsg, zone->origin, CLASS_IN); dynupdate_message_del_record(&dmsg, zone->origin, TYPE_NSEC3PARAMQUEUED, 0, rdata_size, rdata); dynupdate_message_set_reader(&dmsg, &reader); u16 count = dynupdate_message_get_count(&dmsg); packet_reader_skip(&reader, DNS_HEADER_LENGTH); // checked below packet_reader_skip_fqdn(&reader); // checked below packet_reader_skip(&reader, 4); // checked below ret = dynupdate_diff(zone, &reader, count, lock_owner, DYNUPDATE_DIFF_RUN); if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { // trigger a background store of the zone zdb_zone_info_background_store_zone(zone->origin); } dynupdate_message_finalize(&dmsg); } } return ret; } ya_result database_update(zdb *database, message_data *mesg) { ya_result ret; u16 count; /* u16 qdcount; */ packet_unpack_reader_data pr; dnsname_vector name; zdb_zone *zone; u8 wire[MAX_DOMAIN_LENGTH + 10 + 65535]; ret = FP_NOZONE_FOUND; zone_desc_s *zone_desc = zone_acquirebydnsname(message_get_canonised_fqdn(mesg)); if(zone_desc != NULL) { bool need_to_notify_slaves = FALSE; #if ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT bool database_service_zone_dnssec_maintenance_start = FALSE; #endif zone_lock(zone_desc, ZONE_LOCK_DYNUPDATE); switch(zone_desc->type) { case MASTER: { #if ZDB_HAS_MASTER_SUPPORT message_set_answer(mesg); /* * Unpack the query */ packet_reader_init_from_message(&pr, mesg); /* qdcount = message_get_query_count(mesg); */ dnsname_to_dnsname_vector(message_get_canonised_fqdn(mesg), &name); zone = zdb_acquire_zone_read_double_lock(database, &name, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); if(zone != NULL && !zdb_zone_invalid(zone)) { /* * If the zone is marked as: * _ frozen * _ updating * _ signing * _ dumping * => don't do it */ if(!zdb_zone_is_frozen(zone)) { #if DNSCORE_HAS_ACL_SUPPORT if(ACL_REJECTED(acl_check_access_filter(mesg, &zone_desc->ac.allow_update))) { /* notauth */ zdb_zone_release_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); zone_unlock(zone_desc, ZONE_LOCK_DYNUPDATE); zone_release(zone_desc); log_info("database: update: %{dnsname} not authorised", zone->origin); message_set_status(mesg, FP_ACCESS_REJECTED); message_update_answer_status(mesg); #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) /* NOTE: the TSIG information is in mesg */ { tsig_sign_answer(mesg); } #endif return ACL_UPDATE_REJECTED; } #endif // HAS_ACL_SUPPORT /* * If the zone is DNSSEC and we don't have all the keys or don't know how to use them : SERVFAIL */ ret = SUCCESS; #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT ya_result message_dnskey_load_code = 0; ya_result zone_dnskey_load_code = 0; ya_result ks_dnskey_load_code = 0; if(zdb_zone_is_maintained(zone) || zdb_zone_is_maintenance_paused(zone)) { if(zone_maintains_dnssec(zone_desc)) { // load all the private part of the keys in the zone #if !MAINTAIN_ONLY_AT_DIFF_AND_REPLAY bool needs_a_maintenance = FALSE; #endif // the early cull optimisation is integrated in all log_* calls, // message_log doesn't automatically benefit from it LOGGER_EARLY_CULL_PREFIX(MSG_DEBUG) message_log(MODULE_MSG_HANDLE, MSG_DEBUG, mesg); #if 1 // new way ptr_vector required_key_parameters; ptr_vector deleted_key_parameters; ptr_vector_init(&required_key_parameters); ptr_vector_init(&deleted_key_parameters); log_debug("database: update: %{dnsname}: looking for key(s) from the zone", zone->origin); database_add_key_parameters_from_zone(zone, &required_key_parameters); #if DEBUG for(int i = 0; i <= ptr_vector_last_index(&required_key_parameters); ++i) { dnssec_key_parameters_t *key_i = (dnssec_key_parameters_t*)ptr_vector_get(&required_key_parameters, i); log_info("database: update: %{dnsname}: <= K%{dnsname}+%03d+%05hd (%i)", zone->origin, key_i->fqdn, key_i->algorithm, key_i->tag, ntohs(key_i->flags)); } #endif log_debug("database: update: %{dnsname}: looking for key(s) updates from the update", zone->origin); ret = database_add_key_parameters_from_message(zone, mesg, &required_key_parameters, &deleted_key_parameters); if(FAIL(ret)) { log_info("database: update: %{dnsname}: couldn't get key parameters from message", zone->origin); } #if DEBUG for(int i = 0; i <= ptr_vector_last_index(&required_key_parameters); ++i) { dnssec_key_parameters_t *key_i = (dnssec_key_parameters_t*)ptr_vector_get(&required_key_parameters, i); log_info("database: update: %{dnsname}: => K%{dnsname}+%03d+%05hd (%i)", zone->origin, key_i->fqdn, key_i->algorithm, key_i->tag, ntohs(key_i->flags)); } for(int i = 0; i <= ptr_vector_last_index(&deleted_key_parameters); ++i) { dnssec_key_parameters_t *key_i = (dnssec_key_parameters_t*)ptr_vector_get(&deleted_key_parameters, i); log_info("database: update: %{dnsname}: -> K%{dnsname}+%03d+%05hd (%i)", zone->origin, key_i->fqdn, key_i->algorithm, key_i->tag, ntohs(key_i->flags)); } #endif ret = database_ensure_private_keys_from_key_parameters_vector(zone, &required_key_parameters); #if !MAINTAIN_ONLY_AT_DIFF_AND_REPLAY if(!ptr_vector_isempty(&deleted_key_parameters) || (ret > 0)) { needs_a_maintenance = TRUE; } #endif dnssec_key_parameters_vector_destroy(&deleted_key_parameters); dnssec_key_parameters_vector_destroy(&required_key_parameters); #else // old way log_debug("database: update: %{dnsname}: looking for new key(s) from the update", zone->origin); if((message_dnskey_load_code = database_zone_ensure_private_keys_from_message(mesg)) >/*=*/ 0) { if(message_dnskey_load_code > 0) { log_info("database: update: %{dnsname}: new key(s) from the update", zone->origin); } #if !MAINTAIN_ONLY_AT_DIFF_AND_REPLAY needs_a_maintenance = TRUE; #endif } else { log_debug("database: update: %{dnsname}: looking for new key(s) from the zone", zone->origin); if((zone_dnskey_load_code = database_zone_ensure_private_keys(zone)) > 0) // is locked { log_info("database: update: %{dnsname}: new key(s) from the zone", zone->origin); #if !MAINTAIN_ONLY_AT_DIFF_AND_REPLAY needs_a_maintenance = TRUE; #endif } else if(zone_dnskey_load_code <= 0) { // scan directories to find new keys log_debug("database: update: %{dnsname}: new key(s) from keystore (which will not happen anymore)", zone->origin); if((ks_dnskey_load_code = dnssec_keystore_reload_domain(zone->origin)) > 0) { log_info("database: update: %{dnsname}: new key(s) from keystore", zone->origin); #if !MAINTAIN_ONLY_AT_DIFF_AND_REPLAY needs_a_maintenance = TRUE; #endif } } } #endif // old way #if !MAINTAIN_ONLY_AT_DIFF_AND_REPLAY if(needs_a_maintenance) // if something was loaded on the first try, and no error occurred { log_info("database: update: %{dnsname}: updating events over key timings", zone->origin); if(zdb_zone_is_maintenance_paused(zone)) { log_info("database: update: %{dnsname}: maintenance resumed", zone->origin); zdb_zone_set_maintenance_paused(zone, FALSE); } // SMART SIGNING zdb_zone_update_keystore_keys_from_zone(zone, ZDB_ZONE_MUTEX_DYNUPDATE); database_service_zone_dnskey_set_alarms(zone); // we are in a ZT_MASTER case } else { if(ISOK(message_dnskey_load_code) && ISOK(zone_dnskey_load_code) && ISOK(ks_dnskey_load_code)) { log_debug("database: update: %{dnsname}: no new private key loaded", zone->origin); } else { if(FAIL(message_dnskey_load_code)) { log_warn("database: update: %{dnsname}: could not find private key file(s) for DNSKEY record(s) added by the update message: %r", zone->origin, message_dnskey_load_code); } if(FAIL(zone_dnskey_load_code)) { log_warn("database: update: %{dnsname}: could not find private key file(s) for DNSKEY records(s) already in the zone: %r", zone->origin, zone_dnskey_load_code); } if(FAIL(ks_dnskey_load_code)) { log_warn("database: update: %{dnsname}: could not find private key file(s) for keys in the keyring: %r", zone->origin, ks_dnskey_load_code); } // log_err("database: update: %{dnsname}: could not find any usable key", zone->origin); } } #endif // MAINTAIN_ONLY_AT_DIFF_AND_REPLAY } else { log_warn("database: update: cannot update %{dnsname} because DNSSEC maintenance has been disabled on the zone", zone->origin); ret = RCODE_ERROR_CODE(RCODE_SERVFAIL); message_set_status(mesg, FP_RCODE_SERVFAIL); } } #endif // ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT if(ISOK(ret)) { // The reader is positioned after the header : read the QR section u16 query_count = message_get_query_count(mesg); if(query_count > 0) { do { if(FAIL(ret = packet_reader_read_zone_record(&pr, wire, sizeof(wire)))) { break; } } while(--query_count > 0); } else { ret = SUCCESS; } if(ISOK(ret)) { // The zone is known with the previous record. // Since I'm just testing the update per se, I'll ignore this. count = message_get_prerequisite_count(mesg); // The reader is positioned after the QR section, read AN section // from this point, the zone is single-locked log_debug("database: update: %{dnsname}: processing %d prerequisites", zone_origin(zone_desc), count); if(ISOK(ret = dynupdate_check_prerequisites(zone, &pr, count))) { count = message_get_update_count(mesg); #if ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT /* * Dry run the update for the section * (so the DB will not be broken if the query is bogus) */ u8 zone_maintain_mode_prev = zone_get_maintain_mode(zone); if((zone_maintain_mode_prev == ZDB_ZONE_MAINTAIN_NOSEC) && ((message_dnskey_load_code > 0) || (zone_dnskey_load_code > 0) || (ks_dnskey_load_code > 0))) { zone->sig_validity_regeneration_seconds = zone_desc->signature.sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S; zone->sig_validity_interval_seconds = zone_desc->signature.sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S; zone->sig_validity_jitter_seconds = zone_desc->signature.sig_validity_jitter * SIGNATURE_VALIDITY_JITTER_S; } #endif if(ISOK(ret = dynupdate_diff(zone, &pr, count, ZDB_ZONE_MUTEX_DYNUPDATE, DYNUPDATE_DIFF_RUN|DYNUPDATE_DIFF_EXTERNAL))) { #if ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT u8 zone_maintain_mode_now = zone_get_maintain_mode(zone); #if DEBUG log_info("database: update: %{dnsname}: DEBUG: code = %08x, mmp=%i, mmn=%i, m=%i, p=%i", zone_origin(zone_desc), ret, (int)zone_maintain_mode_prev, (int)zone_maintain_mode_now, (int)zdb_zone_is_maintained(zone), (int)zdb_zone_is_maintenance_paused(zone)); #endif // if there was no maintenance and now there is, ... if((zone_maintain_mode_prev == 0) && (zone_maintain_mode_now != 0)) { log_info("database: update: %{dnsname}: DEBUG: maintenance mode enabled", zone_origin(zone_desc)); // if the zone was not maintained and the zone maintenance is not paused, then the maintenance needs to be activated if(!zdb_zone_is_maintained(zone) && !zdb_zone_is_maintenance_paused(zone)) { log_info("database: update: %{dnsname}: DEBUG: not maintained and not maintenance paused => maintenance will start", zone_origin(zone_desc)); log_debug("database: update: %{dnsname}: zone had no maintenance mode but is now %u and is not maintained: activating maintenance", zone_origin(zone_desc), zone_maintain_mode_now); zdb_zone_set_maintained(zone, TRUE); database_service_zone_dnssec_maintenance_start = TRUE; } } else if((ret & (DYNUPDATE_DIFF_RETURN_DNSKEY_UPDATED|DYNUPDATE_DIFF_RETURN_DNSKEY_ADDED)) == (DYNUPDATE_DIFF_RETURN_DNSKEY_UPDATED|DYNUPDATE_DIFF_RETURN_DNSKEY_ADDED)) { zdb_zone_set_maintained(zone, TRUE); zdb_zone_set_maintenance_paused(zone, FALSE); database_service_zone_dnskey_set_alarms(zone); // we are in a ZT_MASTER case log_info("database: update: %{dnsname}: DEBUG: key updated and added => maintenance will start", zone_origin(zone_desc)); database_service_zone_dnssec_maintenance_start = zdb_zone_is_maintained(zone); } else if((ret & (DYNUPDATE_DIFF_RETURN_DNSKEY_UPDATED|DYNUPDATE_DIFF_RETURN_DNSKEY_REMOVED)) == (DYNUPDATE_DIFF_RETURN_DNSKEY_UPDATED|DYNUPDATE_DIFF_RETURN_DNSKEY_REMOVED)) { zdb_zone_set_maintained(zone, TRUE); zdb_zone_set_maintenance_paused(zone, FALSE); log_info("database: update: %{dnsname}: DEBUG: key updated and removed => maintenance will start", zone_origin(zone_desc)); database_service_zone_dnssec_maintenance_start = zdb_zone_is_maintained(zone); } else if(ret & DYNUPDATE_DIFF_RETURN_NSEC3PARAM) { zdb_zone_set_maintained(zone, TRUE); zdb_zone_set_maintenance_paused(zone, FALSE); database_service_zone_dnssec_maintenance_start = zdb_zone_is_maintained(zone); } #endif need_to_notify_slaves = TRUE; } else { if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { // trigger a background store of the zone zdb_zone_info_background_store_zone(zone->origin); } message_set_error_status_from_result(mesg, ret); } } else { /* * ZONE CANNOT BE UPDATED (prerequisites not met) */ log_warn("database: update: %{dnsname}: prerequisites not met", message_get_canonised_fqdn(mesg)); message_set_error_status_from_result(mesg, ret); } zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); zdb_zone_release(zone); zone = NULL; } else { message_set_status(mesg, FP_RCODE_FORMERR); zdb_zone_release_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); } } else { /* * ZONE CANNOT BE UPDATED (missing private keys) */ message_set_status(mesg, FP_CANNOT_DYNUPDATE); zdb_zone_release_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); } } else { /* * ZONE CANNOT BE UPDATED (frozen) */ message_set_status(mesg, FP_CANNOT_DYNUPDATE); zdb_zone_release_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); } } else { // zone is null or invalid // if not null, it is double-locked for ZDB_ZONE_MUTEX_SIMPLEREADER and ZDB_ZONE_MUTEX_DYNUPDATE /** * 2136: * * if any RR's NAME is not * within the zone specified in the Zone Section, signal NOTZONE to the * requestor. * */ if(zone == NULL) { message_set_status(mesg, FP_UPDATE_UNKNOWN_ZONE); } else { zdb_zone_release_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); message_set_status(mesg, FP_INVALID_ZONE); } } #else log_err("database: update: %{dnsname}: zone seen as a master but master mode is not supported in this build", zone_origin(zone_desc)); #endif break; } case SLAVE: { /* * UPDATE FORWARDING * * TCP -> TCP * UDP -> TCP or UDP * * So this implementation will always to TCP * * Open a connection to the master. * Create a duplicate of the message changing only the ID * I CANNOT EDIT THE SAME MESSAGE BECAUSE OF THE POSSIBLE TSIG * TSIG if needed. * Send the message. * Wait for the answer and retry if needed. * Forward back the answer to the caller. */ #if DNSCORE_HAS_ACL_SUPPORT if(!ACL_REJECTED(acl_check_access_filter(mesg, &zone_desc->ac.allow_update_forwarding))) { random_ctx rndctx = thread_pool_get_random_ctx(); u16 id = (u16)random_next(rndctx); message_data_with_buffer forward_query_buff; message_data *forward_query = message_data_with_buffer_init(&forward_query_buff); message_make_query(forward_query, id, (const u8*)"", 0, 0); /* just initialise a basic query */ memcpy(message_get_buffer(forward_query), message_get_buffer_const(mesg), message_get_size(mesg)); message_set_size(forward_query, message_get_size(mesg)); // if no TSIG or succeeded in TSIGing the message ... #if DNSCORE_HAS_TSIG_SUPPORT if((zone_desc->masters->tsig == NULL) || ISOK(ret = message_sign_query(forward_query, zone_desc->masters->tsig))) { #endif // send a TCP query to the master if(ISOK(ret = message_query_tcp(forward_query, zone_desc->masters))) { memcpy(message_get_buffer(mesg), message_get_buffer_const(forward_query), message_get_size(forward_query)); message_set_size(mesg, message_get_size(forward_query)); message_set_status(mesg, message_get_status(forward_query)); } else { message_set_status(mesg, FP_RCODE_SERVFAIL); ret = RCODE_ERROR_CODE(RCODE_SERVFAIL); message_make_error(mesg, ret); } #if DNSCORE_HAS_TSIG_SUPPORT } #endif } else #endif { message_set_status(mesg, FP_CANNOT_DYNUPDATE); ret = FP_CANNOT_DYNUPDATE; message_make_error(mesg, ret); } break; } default: { message_set_status(mesg, FP_CANNOT_DYNUPDATE); ret = FP_CANNOT_DYNUPDATE; message_make_error(mesg, ret); break; } } // end switch zone_unlock(zone_desc, ZONE_LOCK_DYNUPDATE); #if ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT if(database_service_zone_dnssec_maintenance_start) { log_info("database: update: %{dnsname}: DEBUG: maintenance starting", zone_origin(zone_desc)); zone = zdb_acquire_zone_read_double_lock(database, &name, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); if(zone != NULL && !zdb_zone_invalid(zone)) { u32 zone_status = zdb_zone_get_status(zone); if(zone_status & ZDB_ZONE_STATUS_GENERATE_CHAIN) { // enable NSEC3 mode if((zone_get_maintain_mode(zone) & ZDB_ZONE_MAINTAIN_NSEC3) != 0) { //u8 optout, u16 iterations, const u8 *salt, u8 salt_len, u8 status); zdb_packed_ttlrdata *rrset = zdb_record_find(&zone->apex->resource_record_set, TYPE_NSEC3PARAMQUEUED); database_apply_nsec3paramqueued(zone, rrset, ZDB_ZONE_MUTEX_DYNUPDATE); } else { nsec_zone_set_status(zone, ZDB_ZONE_MUTEX_DYNUPDATE, NSEC_ZONE_ENABLED|NSEC_ZONE_GENERATING); } } zdb_zone_release_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); zone = NULL; } database_service_zone_dnssec_maintenance(zone_desc); } #endif if(need_to_notify_slaves) { notify_slaves(zone_origin(zone_desc)); } zone_release(zone_desc); } else { /* zone is not even known by the configuration */ message_set_status(mesg, FP_UPDATE_UNKNOWN_ZONE); } message_set_rcode(mesg, message_get_status(mesg)); #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) { log_debug("database: update: %{dnsname}: signing reply", message_get_canonised_fqdn(mesg)); tsig_sign_answer(mesg); } #endif return (finger_print)ret; } #endif /** @brief Close the database * * @param[in] database * * @retval OK * @retval NOK */ ya_result database_shutdown(zdb *database) { if(database == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT||DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT||DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT||DNSCORE_HAS_MMAP_DEBUG_SUPPORT formatln("database_shutdown(%p) begin", database); debug_stat(DEBUG_STAT_TAGS|DEBUG_STAT_MMAP); zalloc_print_stats(&__termout__); flushout(); flusherr(); #endif database_service_stop(); if(database != NULL) { zdb_destroy(database); free(database); } database_finalize(); g_config->database = NULL; #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT||DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT||DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT||DNSCORE_HAS_MMAP_DEBUG_SUPPORT formatln("database_shutdown(%p) done", database); debug_stat(DEBUG_STAT_SIZES|DEBUG_STAT_TAGS|DEBUG_STAT_DUMP|DEBUG_STAT_WALK|DEBUG_STAT_MMAP); zalloc_print_stats(&__termout__); flushout(); flusherr(); #endif return SUCCESS; } /** * * @param zone_desc * @return */ static ya_result database_zone_refresh_next_master(zone_desc_s *zone_desc) { if(zone_desc->masters != NULL && zone_desc->masters->next != NULL) { ya_result ret = 2; zone_lock(zone_desc, ZONE_LOCK_SERVICE); host_address *head = zone_desc->masters; host_address *move_to_end = head; host_address *node = head->next; while(node->next != NULL) { ++ret; node = node->next; } node->next = move_to_end; move_to_end->next = NULL; zone_desc->masters = head; zone_unlock(zone_desc, ZONE_LOCK_SERVICE); return ret; } else { return 1; } } static ya_result database_zone_refresh_alarm(void *args, bool cancel) { database_zone_refresh_alarm_args *sszra = (database_zone_refresh_alarm_args*)args; if(cancel) { free((char*)sszra->origin); #if DEBUG memset(sszra, 0xff, sizeof(database_zone_refresh_alarm_args)); #endif free(sszra); return SUCCESS; } const u8 *origin = sszra->origin; zdb *db = g_config->database; zdb_zone *zone; ya_result return_value; u32 now = 0; u32 next_alarm_epoch = 0; soa_rdata soa; log_debug("database: refresh: %{dnsname}", origin); zone_desc_s *zone_desc = zone_acquirebydnsname(origin); if(zone_desc == NULL) { log_err("database: refresh: %{dnsname}: zone not found", origin); free((char*)sszra->origin); free(sszra); return ZONE_NOT_DEFINED; } zone = zdb_acquire_zone_read_from_fqdn(db, zone_origin(zone_desc)); if(zone != NULL) { /** * check if the zone is locked. postpone if it is */ if(zdb_zone_trylock(zone, ZDB_ZONE_MUTEX_REFRESH)) { if(FAIL(return_value = zdb_zone_getsoa(zone, &soa))) // zone is locked { zdb_zone_release(zone); /* * No SOA ? It's critical */ free(sszra); log_quit("database: refresh: %{dnsname}: get SOA: %r", origin, return_value); return return_value; } now = time(NULL); // defines 3 epoch printers (to be used with %w) u32 rf = zone_desc->refresh.refreshed_time; u32 rt = zone_desc->refresh.retried_time; u32 un = zone_desc->refresh.zone_update_next_time; log_debug("database: refresh: %{dnsname}: refreshed=%T retried=%T next=%T refresh=%i retry=%i expire=%i", origin, rf, rt, un, soa.refresh, soa.retry, soa.expire ); // if the last time refreshed is at or after the last time we retried if(zone_desc->refresh.refreshed_time >= zone_desc->refresh.retried_time) { // then we are not retrying ... // if now is after the last refreshed time + the refresh time if(now >= zone_desc->refresh.refreshed_time + soa.refresh) { // then do a refresh log_info("database: refresh: %{dnsname}: refresh", origin); zone_desc->refresh.retried_time = zone_desc->refresh.refreshed_time + 1; // next time we will check for the refresh status will be now + retry ... next_alarm_epoch = now + soa.retry; database_zone_ixfr_query(zone_origin(zone_desc)); } else { // next time we will check for the refresh status will be now + refresh ... log_info("database: refresh: %{dnsname}: refresh in %d seconds", origin, zone_desc->refresh.refreshed_time + soa.refresh - now); next_alarm_epoch = zone_desc->refresh.refreshed_time + soa.refresh; } } else { // else we are retrying ... if(now < zone_desc->refresh.refreshed_time + soa.expire) { // then we have not expired yet ... // next time we will check for the refresh status will be now + retry ... next_alarm_epoch = now + soa.retry; if(now >= zone_desc->refresh.retried_time + soa.retry) { // then do a retry ... log_info("database: refresh: %{dnsname}: retry", origin); database_zone_ixfr_query(zone_origin(zone_desc)); } else { log_debug("database: refresh: %{dnsname}: it's not time to retry yet", origin); } } else { // else the zone is not authoritative anymore log_warn("database: refresh: %{dnsname}: zone has expired", origin); // if it's a multi-master setup, go to the next one in the list // else mark the zone as being invalid if(database_zone_refresh_next_master(zone_desc) > 1) { next_alarm_epoch = time(NULL); log_warn("database: refresh: %{dnsname}: master has changed to %{hostaddr}", origin, zone_desc->masters); database_zone_refresh_maintenance(db, origin, next_alarm_epoch); } else { zdb_zone_set_invalid(zone); } } } zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_REFRESH); } else { log_info("database: refresh: %{dnsname}: zone has already been locked, will retry layer", origin); next_alarm_epoch = time(NULL) + 2; } zdb_zone_release(zone); } else { log_err("database: refresh: %{dnsname}: zone is not mounted", origin); } if(next_alarm_epoch != 0) { /* * The alarm rang but nothing has been done */ log_debug("database: refresh: %{dnsname}: re-arming the alarm for %T", origin, next_alarm_epoch); database_zone_refresh_maintenance(db, origin, next_alarm_epoch); } else { log_debug("database: refresh: %{dnsname}: alarm will not be re-armed", origin); } free((char*)sszra->origin); #if DEBUG memset(sszra, 0xff, sizeof(database_zone_refresh_alarm_args)); #endif free(sszra); zone_release(zone_desc); return SUCCESS; } ya_result database_zone_refresh_maintenance_wih_zone(zdb_zone* zone, u32 next_alarm_epoch) { if((zone != NULL) && zdb_zone_valid(zone)) { /* * Get the SOA from the zone */ /* * Check the last refresh time * If we need to refresh, then do it * If we failed, check when the next time to do it is * If we failed too much, check if we still are authoritative */ zdb_zone_lock(zone, ZDB_ZONE_MUTEX_REFRESH); /* here ! */ u32 now = time(NULL); ya_result return_value; soa_rdata soa; if(next_alarm_epoch == 0) { if(FAIL(return_value = zdb_zone_getsoa(zone, &soa))) // zone is locked { /* * No SOA ? It's critical */ zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_REFRESH); /* here ! */ log_err("database_zone_refresh_maintenance: get soa: %r", return_value); exit(EXIT_FAILURE); } next_alarm_epoch = now + soa.refresh; } database_zone_refresh_alarm_args *sszra; MALLOC_OBJECT_OR_DIE(sszra, database_zone_refresh_alarm_args, DBREFALP_TAG); sszra->origin = dnsname_dup(zone->origin); alarm_event_node *event = alarm_event_new( // zone refresh next_alarm_epoch, ALARM_KEY_ZONE_REFRESH, database_zone_refresh_alarm, sszra, ALARM_DUP_REMOVE_LATEST, "database-zone-refresh-alarm"); alarm_set(zone->alarm_handle, event); zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_REFRESH); } else { /* * The zone has not been loaded (yet) */ if(zone != NULL) { log_debug("database_zone_refresh_maintenance: called on an invalid zone: %{dnsname}", zone->origin); } else { log_debug("database_zone_refresh_maintenance: called on a NULL zone"); } } return SUCCESS; } ya_result database_zone_refresh_maintenance(zdb *database, const u8 *origin, u32 next_alarm_epoch) { ya_result ret = SUCCESS; // no zone, no issue doing maintenance log_debug("database: refresh %{dnsname}: refresh maintenance for zone at %T", origin, next_alarm_epoch); zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(database, origin); if(zone != NULL) { ret = database_zone_refresh_maintenance_wih_zone(zone, next_alarm_epoch); zdb_zone_release(zone); } return ret; } ya_result database_store_zone_to_disk(zone_desc_s *zone_desc) { database_zone_store(zone_origin(zone_desc)); return SUCCESS; } ya_result database_store_all_zones_to_disk() { /* * for all zones * put them in an array * while the array is not empty * for every zone in the array * try to freeze zone (lock) * if it worked, wait that it is frozen, then unfreeze it and remove it from the array * */ ya_result batch_return_value = 0; if(g_config->database == NULL) { return INVALID_STATE_ERROR; } zone_set_lock(&database_zone_desc); // unlock checked ptr_set_iterator iter; ptr_set_iterator_init(&database_zone_desc.set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value; if(zone_is_obsolete(zone_desc)) { continue; } database_store_zone_to_disk(zone_desc); } zone_set_unlock(&database_zone_desc); return batch_return_value; } bool database_are_all_zones_stored_to_disk() { bool can_unload; can_unload = TRUE; zone_set_lock(&database_zone_desc); // unlock checked ptr_set_iterator iter; ptr_set_iterator_init(&database_zone_desc.set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value; if(zone_is_obsolete(zone_desc)) { continue; } if(zone_issavingfile(zone_desc)) { can_unload = FALSE; break; } } zone_set_unlock(&database_zone_desc); return can_unload; } void database_wait_all_zones_stored_to_disk() { while(!database_are_all_zones_stored_to_disk()) { log_info("database: still busy writing zone files: shutdown postponed"); sleep(1); } } void database_disable_all_zone_store_to_disk() { zone_set_lock(&database_zone_desc); // unlock checked ptr_set_iterator iter; ptr_set_iterator_init(&database_zone_desc.set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value; if(zone_is_obsolete(zone_desc)) { continue; } zone_setsavingfile(zone_desc, FALSE); } zone_set_unlock(&database_zone_desc); } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ixfr.c0000644000000000000000000000013214505005533020007 xustar000000000000000030 mtime=1695812443.526997713 30 atime=1695812445.784030039 30 ctime=1695812495.646744173 yadifa-2.6.5-11201/sbin/yadifad/ixfr.c0000664000374500037450000006321414505005533017757 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #include "server-config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if DNSCORE_HAS_TCP_MANAGER #include #endif #include #include #include #include #include #include #include "server.h" #include "ixfr.h" #include "confs.h" #include "notify.h" #include "dnssec-policy.h" #include "database-service-zone-download.h" extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger /** * * Handle an IXFR query from a slave. */ #if DNSCORE_HAS_TCP_MANAGER ya_result ixfr_process(message_data *mesg, tcp_manager_socket_context_t *sctx) #else ya_result ixfr_process(message_data *mesg, int sockfd) #endif { /* * Start an IXFR "writer" thread * Give it the tcp fd * It will store the IXFR for the current database snapshot on the disk if it does not exist yet (writers blocked) * It will then open the stored file and stream it to the tcp fd (writers freed) * ACL/TSIG is not taken in account yet. */ zdb_zone *zone; const u8 *fqdn = message_get_canonised_fqdn(mesg); u32 fqdn_len = dnsname_len(fqdn); if(fqdn_len > MAX_DOMAIN_LENGTH) { #if DNSCORE_HAS_TCP_MANAGER tcp_manager_context_release(sctx); tcp_manager_close(sctx); #endif return DOMAIN_TOO_LONG; } ya_result return_value = SUCCESS; if((zone = zdb_acquire_zone_read_from_fqdn(g_config->database, fqdn)) != NULL) { if(zdb_zone_valid(zone)) { #if ZDB_HAS_ACL_SUPPORT access_control *ac = zone->acl; if(!ACL_REJECTED(acl_check_access_filter(mesg, &ac->allow_transfer))) { #endif /* * Before doing more work, check the serials. */ u32 query_serial; if(ISOK(return_value = message_ixfr_query_get_serial(mesg, &query_serial))) { u32 zone_serial; zdb_zone_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); return_value = zdb_zone_getserial(zone, &zone_serial); // zone is locked zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); if(ISOK(return_value)) { if(serial_lt(query_serial, zone_serial)) { // reply with the relevant XFR stream #if DNSCORE_HAS_TCP_MANAGER zdb_zone_answer_ixfr(zone, mesg, sctx, NULL, NULL, g_config->axfr_max_packet_size, g_config->axfr_max_record_by_packet, g_config->axfr_compress_packets); tcp_manager_context_release(sctx); // sctx has been acquired by the xfr call #else zdb_zone_answer_ixfr(zone, mesg, sockfd, NULL, NULL, g_config->axfr_max_packet_size, g_config->axfr_max_record_by_packet, g_config->axfr_compress_packets); #endif zdb_zone_release(zone); return SUCCESS; } else { /* already up-to-date */ log_info("ixfr: %{dnsname}: already up-to-date at serial %u", message_get_canonised_fqdn(mesg), zone_serial); // answer with the SOA packet_writer pc; packet_writer_init(&pc, message_get_buffer(mesg), DNS_HEADER_LENGTH + fqdn_len + 2 + 2, message_get_buffer_size(mesg)); // valid use of message_get_buffer_size() const u8 *soa_rdata; u32 soa_ttl; u16 soa_rdata_size; zdb_zone_lock(zone, ZDB_ZONE_MUTEX_XFR); zdb_zone_getsoa_ttl_rdata(zone, &soa_ttl, &soa_rdata_size, &soa_rdata); // zone is locked zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_XFR); packet_writer_add_fqdn(&pc, &(message_get_buffer_const(mesg)[DNS_HEADER_LENGTH])); packet_writer_add_u16(&pc, TYPE_SOA); packet_writer_add_u16(&pc, CLASS_IN); packet_writer_add_u32(&pc, ntohl(soa_ttl)); packet_writer_add_rdata(&pc, TYPE_SOA, soa_rdata, soa_rdata_size); message_set_authoritative_answer(mesg); message_set_query_answer_authority_additional_counts_ne(mesg, NETWORK_ONE_16, NETWORK_ONE_16, 0, 0); message_set_size(mesg, packet_writer_get_offset(&pc)); message_set_status(mesg, FP_XFR_UP_TO_DATE); } } else { /* broken zone */ log_info("ixfr: %{dnsname}: broken zone", message_get_canonised_fqdn(mesg)); message_set_status(mesg, FP_XFR_BROKENZONE); } } else { log_info("ixfr: %{dnsname}: unable to fetch serial from message: %r", message_get_canonised_fqdn(mesg), return_value); message_set_status(mesg, FP_XFR_QUERYERROR); } #if ZDB_HAS_ACL_SUPPORT } else { /* notauth */ log_info("ixfr: %{dnsname}: not authorised", message_get_canonised_fqdn(mesg)); message_set_status(mesg, FP_XFR_REFUSED); } #endif } // else !ZDB_ZONE_VALID(zone) else { log_debug("ixfr: %{dnsname}: the acquired zone is not valid", message_get_canonised_fqdn(mesg)); message_set_status(mesg, FP_INVALID_ZONE); } zdb_zone_release(zone); } else { /* zone not found */ log_info("ixfr: %{dnsname}: zone not found", message_get_canonised_fqdn(mesg)); message_set_status(mesg, FP_XFR_REFUSED); } if(message_get_status(mesg) != FP_XFR_UP_TO_DATE) { message_make_error(mesg, message_get_status(mesg)); } #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) { message_sign_answer(mesg); } #endif #if DNSCORE_HAS_TCP_MANAGER int sockfd = tcp_manager_socket(sctx); #endif ya_result send_ret; #if DNSCORE_HAS_TCP_MANAGER send_ret = message_send_tcp(mesg, sockfd); #else send_ret = message_update_length_send_tcp_with_default_minimum_throughput(mesg, sockfd); #endif if(ISOK(send_ret)) { #if DNSCORE_HAS_TCP_MANAGER tcp_manager_write_update(sctx, send_ret); #endif } else { log_err("ixfr: %{dnsname}: could not send error message: %r (%{sockaddr})", message_get_canonised_fqdn(mesg), send_ret, message_get_sender(mesg)); } yassert((sockfd < 0)||(sockfd >2)); #if DNSCORE_HAS_TCP_MANAGER tcp_manager_context_release(sctx); #else shutdown(sockfd, SHUT_RDWR); close_ex(sockfd); #endif return return_value; } /** * Connects to the server and sends an IXFR query with the given parameters. * In case of success the input and output streams are tcp streams to the server, ready to read the answer * In case of error the streams are undefined * * @param servers * @param origin * @param ttl * @param rdata * @param rdata_size * @param is * @param os * @return */ ya_result ixfr_start_query(const host_address *servers, const u8 *origin, u32 ttl, const u8 *soa_rdata, u16 soa_rdata_size, input_stream *is, output_stream *os, message_data *ixfr_queryp) { /** * Create the IXFR query packet */ ya_result return_value; u32 serial; if(FAIL(return_value = rr_soa_get_serial(soa_rdata, soa_rdata_size, &serial))) { log_err("ixfr: %{dnsname}: error with the SOA: %r", origin, return_value); return return_value; } random_ctx rndctx = thread_pool_get_random_ctx(); u16 id = (u16)random_next(rndctx); log_info("ixfr: %{dnsname}: %{hostaddr}: sending query from serial %i", origin, servers, serial); message_make_ixfr_query(ixfr_queryp, id, origin, ttl, soa_rdata_size, soa_rdata); #if DNSCORE_HAS_TSIG_SUPPORT if(servers->tsig != NULL) { log_info("ixfr: %{dnsname}: %{hostaddr}: transfer will be signed with key '%{dnsname}'", origin, servers, servers->tsig->name); message_sign_query(ixfr_queryp, servers->tsig); } #endif /** * Send UDP, read UDP (or timeout) * if error, AXFR will be needed * if truncated, TCP will be needed */ /* * connect & send */ host_address *transfer_source = zone_transfer_source_copy(origin); host_address *current_transfer_source; current_transfer_source = transfer_source; return_value = zone_transfer_source_tcp_connect(servers, ¤t_transfer_source, is, os, g_config->xfr_connect_timeout); if(ISOK(return_value)) { #if DEBUG log_debug("ixfr_start_query: write: sending %d bytes to %{hostaddr}", message_get_size(ixfr_queryp) + 2, servers); log_memdump_ex(g_server_logger, LOG_DEBUG, message_get_buffer_const(ixfr_queryp), message_get_size(ixfr_queryp), 16, OSPRINT_DUMP_HEXTEXT); #endif if(ISOK(return_value = message_write_tcp(ixfr_queryp, os))) { output_stream_flush(os); int fd = fd_input_stream_get_filedescriptor(is); tcp_set_sendtimeout(fd, 30, 0); tcp_set_recvtimeout(fd, 30, 0); return SUCCESS; } input_stream_close(is); output_stream_close(os); } else { if((transfer_source != NULL) && (current_transfer_source == NULL)) { log_warn("ixfr: %{dnsname}: %{hostaddr}: could not find a valid bind point to query a transfer from", origin, servers); } else { log_info("ixfr: %{dnsname}: %{hostaddr}: stream connection failed: %r", origin, servers, return_value); } } return return_value; } /** * * Send an IXFR query to a master and handle the answer (loads the zone). */ ya_result ixfr_query(const host_address *servers, zdb_zone *zone, u32 *out_loaded_serial) { /* * Background: * * Build an ixfr query message * Send it to the master * Wait for the answer * Copy the answer in a file * Load the zone from the file * * Foreground: * * Attach the zone to the database. */ /* * IXFR query */ ya_result return_value; u32 current_serial; u32 ttl; u16 rdata_size; const u8 *rdata; zdb_zone_lock(zone, ZDB_ZONE_MUTEX_XFR); if(FAIL(return_value = zdb_zone_getserial(zone, ¤t_serial))) // zone is locked { zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_XFR); return return_value; // will return ZDB_ERROR_NOSOAATAPEX if the zone is invalid } if(FAIL(return_value = zdb_zone_getsoa_ttl_rdata(zone, &ttl, &rdata_size, &rdata))) // zone is locked { zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_XFR); return return_value; } zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_XFR); if(dnscore_shuttingdown()) { return STOPPED_BY_APPLICATION_SHUTDOWN; } input_stream is; output_stream os; message_data_with_buffer mesg_buff; message_data *mesg = message_data_with_buffer_init(&mesg_buff); /** * start the IXFR query */ if(ISOK(return_value = ixfr_start_query(servers, zone->origin, ttl, rdata, rdata_size, &is, &os, mesg))) { xfr_copy_flags xfr_flags = XFR_ALLOW_BOTH | XFR_CURRENT_SERIAL_SET | ((g_config->axfr_strict_authority)? 0: XFR_LOOSE_AUTHORITY); input_stream xfris; if(ISOK(return_value = xfr_input_stream_init(&xfris, zone->origin, &is, mesg, current_serial, xfr_flags))) { switch(xfr_input_stream_get_type(&xfris)) { case TYPE_AXFR: log_info("ixfr: %{dnsname}: %{hostaddr}: server answered with AXFR", zone->origin, servers); FALLTHROUGH // fall through case TYPE_ANY: // this is an AXFR { char data_path[PATH_MAX]; if(FAIL(return_value = zdb_zone_path_get_provider()(zone->origin, data_path, sizeof(data_path), ZDB_ZONE_PATH_PROVIDER_AXFR_PATH|ZDB_ZONE_PATH_PROVIDER_MKDIR))) { log_err("ixfr: %{dnsname}: unable to create directory '%s' : %r", zone->origin, data_path, return_value); return return_value; } /* delete axfr files */ zdb_zone_lock(zone, ZDB_ZONE_MUTEX_XFR); bool have_writing_rights = !zdb_zone_get_set_dumping_axfr(zone); zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_XFR); if(have_writing_rights) { xfr_delete_axfr(zone->origin); /* delete journal file */ log_info("ixfr: %{dnsname}: %{hostaddr}: deleting journal", zone->origin, servers); zdb_zone_journal_delete(zone); log_info("ixfr: %{dnsname}: %{hostaddr}: loading AXFR stream from server", zone->origin, servers); if(ISOK(return_value = xfr_copy(&xfris, g_config->xfr_path, FALSE))) { if(out_loaded_serial != NULL) { *out_loaded_serial = xfr_input_stream_get_serial(&xfris); } } else { log_warn("ixfr: %{dnsname}: %{hostaddr}: AXFR stream copy in '%s' failed: %r", zone->origin, servers, g_config->xfr_path, return_value); } zdb_zone_lock(zone, ZDB_ZONE_MUTEX_XFR); zdb_zone_clear_dumping_axfr(zone); zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_XFR); } else { // zone is already being dumped log_debug("ixfr: %{dnsname}: cannot AXFR: zone already marked as being dumped", zone->origin); } break; } case TYPE_IXFR: { log_info("ixfr: %{dnsname}: %{hostaddr}: writing stream into the journal", zone->origin, servers); while(!dnscore_shuttingdown()) { return_value = zdb_zone_journal_append_ixfr_stream(zone, &xfris); if(ISOK(return_value) || (return_value == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY)) { u32 ixfr_from_serial; ya_result ret; if(return_value == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { if(dnscore_shuttingdown()) { return_value = STOPPED_BY_APPLICATION_SHUTDOWN; break; } #if DEBUG log_info("ixfr: %{dnsname}: the zone needs to be stored on disk. Another IXFR query will be scheduled. (shutdown == %i)", zone->origin, dnscore_shuttingdown()); #else log_info("ixfr: %{dnsname}: the zone needs to be stored on disk. Another IXFR query will be scheduled.", zone->origin); #endif // if we got some journal if(ISOK(ret = zdb_zone_journal_get_serial_range(zone, &ixfr_from_serial, out_loaded_serial))) { // if the journal doesn't contain new updates, give up for now if(serial_ge(current_serial, *out_loaded_serial)) { log_debug("ixfr: %{dnsname}: did not download a single new update in the journal", zone->origin); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_NEED_REFRESH); break; } } } if(dnscore_shuttingdown()) { return_value = STOPPED_BY_APPLICATION_SHUTDOWN; break; } if(ISOK(ret = zdb_zone_journal_get_serial_range(zone, &ixfr_from_serial, out_loaded_serial))) { u32 expected_serial = xfr_input_stream_get_serial(&xfris); #if DEBUG log_debug("ixfr: %{dnsname}: journal_append_ixfr_stream returned %r", zone->origin, return_value); #endif log_info("ixfr: %{dnsname}: replaying journal (%u;%u)", zone->origin, ixfr_from_serial, *out_loaded_serial); #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT u8 prev_zone_dnssec_type = zone_policy_guess_dnssec_type(zone); #endif if(ISOK(ret = zdb_icmtl_replay(zone))) // no signature maintenance here { log_info("ixfr: %{dnsname}: journal replayed %i pages", zone->origin, ret); // zone_set_status(zone_desc); #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT u8 zone_dnssec_type = zone_policy_guess_dnssec_type(zone); if(prev_zone_dnssec_type != zone_dnssec_type) { switch(zone_dnssec_type) { case ZONE_DNSSEC_FL_NOSEC: log_debug("ixfr: %{dnsname}: slave zone is not DNSSEC", zone->origin); break; case ZONE_DNSSEC_FL_NSEC: log_debug("ixfr: %{dnsname}: slave zone is NSEC", zone->origin); break; case ZONE_DNSSEC_FL_NSEC3: log_debug("ixfr: %{dnsname}: slave zone is NSEC3", zone->origin); break; case ZONE_DNSSEC_FL_NSEC3_OPTOUT: log_debug("ixfr: %{dnsname}: slave zone is NSEC3 OPT-OUT", zone->origin); break; } zone_dnssec_status_update(zone); } #endif } else { return_value = ret; log_err("ixfr: %{dnsname}: journal replay returned %r", zone->origin, return_value); } if(return_value != ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { if(ISOK(ret) && serial_lt(*out_loaded_serial, expected_serial)) { // should redo an IXFR asap if(!dnscore_shuttingdown()) { log_info("ixfr: %{dnsname}: loaded serial %u below expected serial (%u): querying IXFR again", zone->origin, *out_loaded_serial, expected_serial); database_service_zone_ixfr_query(zone->origin); } } else { zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_NEED_REFRESH); } } else { zdb_zone_set_status(zone, ZDB_ZONE_STATUS_NEED_REFRESH); } } else { log_warn("ixfr: %{dnsname}: could not get the serial range of the journal: %r", zone->origin, return_value); } } else { if(return_value == ZDB_JOURNAL_SERIAL_OUT_OF_KNOWN_RANGE) { /// @note 20161018 edf -- we are slave, so it's OK log_warn("ixfr: %{dnsname}: %{hostaddr}: no continuity with the journal, resetting", zone->origin, servers); // hole in the journal : reset zdb_zone_journal_delete(zone); } else { log_err("ixfr: %{dnsname}: %{hostaddr}: failed to write the stream into the journal: %r", zone->origin, servers, return_value); } } break; // for } break; } default: { return_value = RCODE_ERROR_CODE(RCODE_FORMERR); break; } } log_debug("ixfr: %{dnsname}: closing stream", zone->origin); input_stream_close(&xfris); if(ISOK(return_value)) { log_debug("ixfr: %{dnsname}: notifying implicit and explicit slaves", zone->origin); notify_slaves(zone->origin); } } else { if(return_value == ZONE_ALREADY_UP_TO_DATE) { return_value = SUCCESS; } else { log_info("ixfr: %{dnsname}: transfer from master failed: %r", zone->origin, return_value); } } input_stream_close(&is); output_stream_close(&os); } return return_value; } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/log_query.c0000644000000000000000000000013214505005533021045 xustar000000000000000030 mtime=1695812443.318994734 30 atime=1695812445.781029996 30 ctime=1695812495.648744202 yadifa-2.6.5-11201/sbin/yadifad/log_query.c0000664000374500037450000002252114505005533021011 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logging Server logging * @ingroup yadifad * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "server-config.h" #include #include "log_query.h" #include "server_context.h" /******************************************************************************************************************* * * QUERY LOG SPECIALISED FUNCTIONS * ******************************************************************************************************************/ #define LOG_QUERY_C_ logger_handle* g_queries_logger = LOGGER_HANDLE_SINK; log_query_function* log_query = log_query_yadifa; void log_query_set_mode(u32 mode) { switch(mode) { case 1: log_query = log_query_yadifa; break; case 2: log_query = log_query_bind; break; case 3: log_query = log_query_both; break; default: log_query = log_query_none; break; } } static u8 log_query_add_du16(char *dest, u16 v) { u8 idx = 8; char tmp[8]; do { char c = (v%10) + '0'; v /= 10; tmp[--idx] = c; } while(v != 0); memcpy(dest, &tmp[idx], 8 - idx); return 8 - idx; } static const char __hexa__[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; static u8 log_query_add_xu16(char *dest, u16 v) { dest[0] = __hexa__[(v>>4)&0xf]; dest[1] = __hexa__[v&0xf]; dest[2] = __hexa__[(v>>12)&0xf]; dest[3] = __hexa__[(v>>8)&0xf]; return 4; } void log_query_bind(int socket_fd, message_data *mesg) { if(g_queries_logger == NULL) { return; } char *buffer; const char *class_name; const char *type_name; char query_text[1024]; buffer = query_text; memcpy(buffer, "client ", 7); buffer+=7; u16 port = 0; switch(message_get_sender_sa(mesg)->sa_family) { case AF_INET: { const struct sockaddr_in *ipv4 = message_get_sender_sa4(mesg); if(inet_ntop(ipv4->sin_family, &ipv4->sin_addr, buffer, 64) != NULL) { buffer += strlen(buffer); *buffer++ = '#'; port = ntohs(ipv4->sin_port); } break; } case AF_INET6: { const struct sockaddr_in6 *ipv6 = message_get_sender_sa6(mesg); if(inet_ntop(ipv6->sin6_family, &ipv6->sin6_addr, buffer, 64) != NULL) { buffer += strlen(buffer); *buffer++ = '#'; port = ntohs(ipv6->sin6_port); } break; } } buffer += log_query_add_du16(buffer, port); memcpy(buffer, ": query: ", 9); buffer += 9; buffer += dnsname_to_cstr(buffer, message_get_canonised_fqdn(mesg)); *buffer++ = ' '; class_name = dns_class_get_name(message_get_query_class(mesg)); if(class_name != NULL) { strcpy(buffer, class_name); // the buffer is big enough buffer += strlen(class_name); } else { memcpy(buffer, "CLASS", 5); buffer += 5; buffer += log_query_add_du16(buffer, message_get_query_class(mesg)); } *buffer++ = ' '; type_name = dns_type_get_name(message_get_query_type(mesg)); if(type_name != NULL) { strcpy(buffer, type_name); // the buffer is big enough buffer += strlen(type_name); } else { memcpy(buffer, "TYPE", 4); buffer += 4; buffer += log_query_add_du16(buffer, message_get_query_type(mesg)); } *buffer++ = ' '; *buffer++ = message_has_recursion_desired(mesg)?'+':'-'; #if DNSCORE_HAS_TSIG_SUPPORT if(message_tsig_get_key(mesg) != NULL) { *buffer++ = 'S'; } #endif if(message_is_edns0(mesg)) { *buffer++ = 'E'; } if(message_get_protocol(mesg) == IPPROTO_TCP) { *buffer++ = 'T'; } if(message_has_rcode_ext_dnssec(mesg)) { *buffer++ = 'D'; } if(message_has_checking_disabled(mesg)) { *buffer++ = 'C'; } *buffer++ = ' '; *buffer++ = '('; buffer += server_context_append_socket_name(buffer, socket_fd); *buffer++ = ')'; *buffer = '\0'; logger_handle_msg_text_ext(g_queries_logger, MSG_INFO, query_text, buffer - query_text, " queries: info: ", 16, LOGGER_MESSAGE_TIMEMS|LOGGER_MESSAGE_PREFIX); } void log_query_yadifa(int socket_fd, message_data *mesg) { (void)socket_fd; if(g_queries_logger == NULL) { return; } char *buffer; const char *class_name; const char *type_name; char query_text[1024]; buffer = query_text; memcpy(buffer, "query [", 7); buffer+=7; buffer += log_query_add_xu16(buffer, message_get_id(mesg)); *buffer++ = ']'; *buffer++ = ' '; *buffer++ = '{'; *buffer++ = message_has_recursion_desired(mesg)?'+':'-'; #if DNSCORE_HAS_TSIG_SUPPORT *buffer++ = (message_tsig_get_key(mesg) != NULL)? 'S':'-'; #else *buffer++ = '-'; #endif *buffer++ = message_is_edns0(mesg)?'E':'-'; *buffer++ = (message_get_protocol(mesg) == IPPROTO_TCP)?'T':'-'; *buffer++ = message_has_rcode_ext_dnssec(mesg)?'D':'-'; *buffer++ = message_has_checking_disabled(mesg)?'C':'-'; *buffer++ = '}'; *buffer++ = ' '; buffer += dnsname_to_cstr(buffer, message_get_canonised_fqdn(mesg)); *buffer++ = ' '; class_name = dns_class_get_name(message_get_query_class(mesg)); if(class_name != NULL) { strcpy(buffer, class_name); // the buffer is big enough buffer += strlen(class_name); } else { memcpy(buffer, "CLASS", 5); buffer += 5; buffer += log_query_add_du16(buffer, message_get_query_class(mesg)); } *buffer++ = ' '; type_name = dns_type_get_name(message_get_query_type(mesg)); if(type_name != NULL) { strcpy(buffer, type_name); // the buffer is big enough buffer += strlen(type_name); } else { memcpy(buffer, "TYPE", 4); buffer += 4; buffer += log_query_add_du16(buffer, message_get_query_type(mesg)); } *buffer++ = ' '; *buffer++ = '('; u16 port = 0; switch(message_get_sender_sa(mesg)->sa_family) { case AF_INET: { const struct sockaddr_in *ipv4 = message_get_sender_sa4(mesg); if(inet_ntop(ipv4->sin_family, &ipv4->sin_addr, buffer, 64) != NULL) { buffer += strlen(buffer); *buffer++ = '#'; port = ntohs(ipv4->sin_port); } break; } case AF_INET6: { const struct sockaddr_in6 *ipv6 = message_get_sender_sa6(mesg); if(inet_ntop(ipv6->sin6_family, &ipv6->sin6_addr, buffer, 64) != NULL) { buffer += strlen(buffer); *buffer++ = '#'; port = ntohs(ipv6->sin6_port); } break; } } buffer += log_query_add_du16(buffer, port); *buffer++ = ')'; *buffer = '\0'; logger_handle_msg_text(g_queries_logger, MSG_INFO, query_text, buffer - query_text); } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/log_statistics.c0000644000000000000000000000013014505005533022070 xustar000000000000000030 mtime=1695812443.473996954 29 atime=1695812445.78203001 29 ctime=1695812495.65074423 yadifa-2.6.5-11201/sbin/yadifad/log_statistics.c0000664000374500037450000002054614505005533022043 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup logging Server logging * @ingroup yadifad * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "server-config.h" #define LOG_STATISTICS_C_ #include "log_statistics.h" logger_handle* g_statistics_logger = LOGGER_HANDLE_SINK; void log_statistics_legend() { logger_handle_msg(g_statistics_logger, MSG_INFO, "statistics legend: \n" "\n" "input: \n" "\n" "\tin : input count \n" "\tqr : query count \n" "\tni : notify count \n" "\tup : update count \n" "\tdr : dropped count \n" "\tst : total bytes sent (simple queries only) \n" "\tun : undefined opcode count \n" "\trf : referral count\n" "\tax : axfr query count \n" "\tix : ixfr query count \n" "\tov : (tcp) connection overflow \n" "\n" "output:\n" "\n" "\tOK : NOERROR answer count \n" "\tFE : FORMERR answer count \n" "\tSF : SERVFAIL answer count \n" "\tNE : NXDOMAIN answer count \n" "\tNI : NOTIMP answer count \n" "\tRE : REFUSED answer count \n" "\tXD : YXDOMAIN answer count \n" "\tXR : YXRRSET answer count \n" "\tNR : NXRRSET answer count \n" "\tNA : NOTAUTH answer count \n" "\tNZ : NOTZONE answer count \n" "\tBV : BADVERS answer count \n" "\tBS : BADSIG answer count \n" "\tBK : BADKEY answer count \n" "\tBT : BADTIME answer count \n" "\tBM : BADMODE answer count \n" "\tBN : BADNAME answer count \n" "\tBA : BADALG answer count \n" "\tTR : BADTRUNC answer count\n" #if HAS_RRL_SUPPORT "\n" "rrl:\n" "\n" "\tsl : truncated answer count\n" "\tdr : dropped answer count\n" #endif ); } void log_statistics(server_statistics_t *server_statistics) { #if DEBUG zone_dump_allocated(); #endif logger_handle_msg(g_statistics_logger, MSG_INFO, "udp (in=%llu qr=%llu ni=%llu up=%llu " "dr=%llu st=%llu un=%llu " "rf=%llu" ") " "tcp (in=%llu qr=%llu ni=%llu up=%llu " "dr=%llu st=%llu un=%llu " "rf=%llu " "ax=%llu ix=%llu ov=%llu) " "udpa (OK=%llu FE=%llu SF=%llu NE=%llu " "NI=%llu RE=%llu XD=%llu XR=%llu " "NR=%llu NA=%llu NZ=%llu BV=%llu " "BS=%llu BK=%llu BT=%llu BM=%llu " "BN=%llu BA=%llu TR=%llu) " "tcpa (OK=%llu FE=%llu SF=%llu NE=%llu " "NI=%llu RE=%llu XD=%llu XR=%llu " "NR=%llu NA=%llu NZ=%llu BV=%llu " "BS=%llu BK=%llu BT=%llu BM=%llu " "BN=%llu BA=%llu TR=%llu) " #if HAS_RRL_SUPPORT "rrl (sl=%llu dr=%llu)" #endif , // udp server_statistics->udp_input_count, server_statistics->udp_queries_count, server_statistics->udp_notify_input_count, server_statistics->udp_updates_count, server_statistics->udp_dropped_count, server_statistics->udp_output_size_total, server_statistics->udp_undefined_count, server_statistics->udp_referrals_count, // tcp server_statistics->tcp_input_count, server_statistics->tcp_queries_count, server_statistics->tcp_notify_input_count, server_statistics->tcp_updates_count, server_statistics->tcp_dropped_count, server_statistics->tcp_output_size_total, server_statistics->tcp_undefined_count, server_statistics->tcp_referrals_count, server_statistics->tcp_axfr_count, server_statistics->tcp_ixfr_count, server_statistics->tcp_overflow_count, // udp fp server_statistics->udp_fp[RCODE_NOERROR], server_statistics->udp_fp[RCODE_FORMERR], server_statistics->udp_fp[RCODE_SERVFAIL], server_statistics->udp_fp[RCODE_NXDOMAIN], server_statistics->udp_fp[RCODE_NOTIMP], server_statistics->udp_fp[RCODE_REFUSED], server_statistics->udp_fp[RCODE_YXDOMAIN], server_statistics->udp_fp[RCODE_YXRRSET], server_statistics->udp_fp[RCODE_NXRRSET], server_statistics->udp_fp[RCODE_NOTAUTH], server_statistics->udp_fp[RCODE_NOTZONE], server_statistics->udp_fp[RCODE_BADVERS], server_statistics->udp_fp[RCODE_BADSIG], server_statistics->udp_fp[RCODE_BADKEY], server_statistics->udp_fp[RCODE_BADTIME], server_statistics->udp_fp[RCODE_BADMODE], server_statistics->udp_fp[RCODE_BADNAME], server_statistics->udp_fp[RCODE_BADALG], server_statistics->udp_fp[RCODE_BADTRUNC], // tcp fp server_statistics->tcp_fp[RCODE_NOERROR], server_statistics->tcp_fp[RCODE_FORMERR], server_statistics->tcp_fp[RCODE_SERVFAIL], server_statistics->tcp_fp[RCODE_NXDOMAIN], server_statistics->tcp_fp[RCODE_NOTIMP], server_statistics->tcp_fp[RCODE_REFUSED], server_statistics->tcp_fp[RCODE_YXDOMAIN], server_statistics->tcp_fp[RCODE_YXRRSET], server_statistics->tcp_fp[RCODE_NXRRSET], server_statistics->tcp_fp[RCODE_NOTAUTH], server_statistics->tcp_fp[RCODE_NOTZONE], server_statistics->tcp_fp[RCODE_BADVERS], server_statistics->tcp_fp[RCODE_BADSIG], server_statistics->tcp_fp[RCODE_BADKEY], server_statistics->tcp_fp[RCODE_BADTIME], server_statistics->tcp_fp[RCODE_BADMODE], server_statistics->tcp_fp[RCODE_BADNAME], server_statistics->tcp_fp[RCODE_BADALG], server_statistics->tcp_fp[RCODE_BADTRUNC] #if HAS_RRL_SUPPORT , server_statistics->rrl_slip, server_statistics->rrl_drop #endif ); } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/notify.c0000644000000000000000000000013214505005533020347 xustar000000000000000030 mtime=1695812443.527997728 30 atime=1695812445.784030039 30 ctime=1695812495.652744259 yadifa-2.6.5-11201/sbin/yadifad/notify.c0000664000374500037450000024705314505005533020324 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup yadifad * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "server-config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "notify.h" #include "zone.h" #include "database-service.h" #include "server.h" #include "server_error.h" #define NOTIFY_DETAILED_LOG 0 #define NOTIFY_CLEANUP_DUMP 0 #define NOTIFY_RECEIVE_TIMEOUT_SECONDS 2 #ifndef NOTIFY_DETAILED_LOG #if DEBUG #define NOTIFY_DETAILED_LOG 1 #else #define NOTIFY_DETAILED_LOG 0 #endif #endif #if NOTIFY_DETAILED_LOG #pragma message("WARNING: NOTIFY_DETAILED_LOG is not set to 0") #endif #if DNSCORE_HAS_CTRL #include "ctrl.h" #endif #define NOTFYMSG_TAG 0x47534d5946544f4e #define MESGDATA_TAG 0x415441444753454d /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #define NOTIFY_MESSAGE_TYPE_NOTIFY 1 #define NOTIFY_MESSAGE_TYPE_ANSWER 2 #define NOTIFY_MESSAGE_TYPE_DOMAIN 3 #define NOTIFY_MESSAGE_TYPE_CLEAR 4 #define MESSAGE_QUERY_TIMEOUT 3 #define MESSAGE_QUERY_TRIES 3 #define MESSAGE_QUERY_TIMEOUT_US (MESSAGE_QUERY_TIMEOUT * 1000000) static struct thread_pool_s *notify_thread_pool = NULL; static int send_socket4 = -1; static int send_socket6 = -1; static struct service_s notify_handler = UNINITIALIZED_SERVICE; static async_queue_s notify_handler_queue; static volatile bool notify_service_initialised = FALSE; typedef struct message_query_summary message_query_summary; #define MSGQSUMR_TAG 0x524d55535147534d struct message_query_summary { host_address *host; message_query_summary *next; /* this pointer is used to list the items, ie: for deletion */ // to discard s64 expire_epoch_us; // for answers, id has to be kept u16 id; // for answers, ip/port should be kept but they are already in the host list (sa.sa4,sa.sa6,addrlen) // times we send the udp packet before giving up s8 tries; // for signed answers, these have to be kept u8 mac_size; // mesg->tsig.mac_size; u8 fqdn[256]; u8 mac[64]; // mesg->tsig.mac; }; static void message_query_summary_init(message_query_summary *mqs, u16 id, host_address *host, const message_data *mesg) { yassert(mqs != NULL); // key mqs->host = host_address_copy(host); mqs->next = NULL; mqs->expire_epoch_us = timeus() + MESSAGE_QUERY_TIMEOUT_US; mqs->id = id; // payload mqs->tries = MESSAGE_QUERY_TRIES; dnsname_copy(mqs->fqdn, message_get_canonised_fqdn(mesg)); #if DNSCORE_HAS_TSIG_SUPPORT mqs->mac_size = message_tsig_mac_get_size(mesg); if(mqs->mac_size > 0) { message_tsig_mac_copy(mesg, mqs->mac); } #endif } static void message_query_summary_clear(message_query_summary *mqs) { #if DEBUG log_debug("notify: clearing query for %{hostaddr}", mqs->host); #endif host_address_delete(mqs->host); #if DEBUG memset(mqs, 0xfe, sizeof(message_query_summary)); #endif } static void message_query_summary_delete(message_query_summary *mqs) { #if DEBUG log_debug("notify: deleting query for %{hostaddr}", mqs->host); #endif message_query_summary_clear(mqs); ZFREE_OBJECT(mqs); } static s32 message_query_summary_compare(const void* va, const void* vb) { message_query_summary *a = (message_query_summary*)va; message_query_summary *b = (message_query_summary*)vb; s32 d; d = (s32)a->id - (s32)b->id; if(d == 0) { d = host_address_compare(a->host, b->host); if(d == 0) { d = dnsname_compare(a->fqdn, b->fqdn); } } return d; } typedef struct notify_message notify_message; struct notify_message_domain { u8 type; }; struct notify_message_clear { u8 type; }; struct notify_message_notify { u8 type; u8 repeat_countdown; u8 repeat_period; u8 repeat_period_increase; u32 epoch; host_address *hosts_list; /* 64 bits aligned */ #if DNSCORE_HAS_TSIG_SUPPORT message_tsig tsig; #endif u16 ztype; u16 zclass; }; struct notify_message_answer { u8 type; u8 rcode; bool aa; u8 r2; host_address *host; message_data *message; /* only used if the message is signed */ }; struct notify_message { u8 *origin; union { u8 type; struct notify_message_notify notify; struct notify_message_answer answer; struct notify_message_domain domain; struct notify_message_clear clear; } payload; }; static bool notify_slaves_convert_domain_to_notify(notify_message *notifymsg); /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ static notify_message* notify_message_newinstance(const u8* origin, u8 type) { notify_message *notifymsg; ZALLOC_OBJECT_OR_DIE(notifymsg, notify_message, NOTFYMSG_TAG); notifymsg->origin = dnsname_zdup(origin); notifymsg->payload.type = type; #if DEBUG log_debug("notify_message_newinstance({%{dnsname}@%p, %i}@%p)", notifymsg->origin, notifymsg->origin, notifymsg->payload.type, notifymsg); #endif return notifymsg; } /** * * Queue a message telling a slave has answered to a notify * * @param origin the domain of the zone * @param sa the address of the source * @param rcode rcode part of the query * @param aa aa flag value in the query */ static void notify_slaveanswer(const message_data *mesg) { #if NOTIFY_DETAILED_LOG log_debug("notify_slaveanswer(%{dnsname} %{sockaddr})", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); #endif if(dnscore_shuttingdown()) { return; } if(notify_service_initialised) { #if DNSCORE_HAS_TSIG_SUPPORT const struct tsig_item *mesg_tsig_key = message_tsig_get_key(mesg); // pointer to the structure used for TSIG, to be used in relevant cases message_data *clone = NULL; if(mesg_tsig_key != NULL) { clone = message_dup(mesg); if(clone == NULL) { return; // BUFFER_WOULD_OVERFLOW; } } #endif const u8 *origin = message_get_canonised_fqdn(mesg); const socketaddress *sa = message_get_sender(mesg); u8 rcode = message_get_rcode(mesg); bool aa = message_isauthoritative(mesg); notify_message *notifymsg = notify_message_newinstance(origin, NOTIFY_MESSAGE_TYPE_ANSWER); notifymsg->payload.answer.rcode = rcode; notifymsg->payload.answer.aa = aa; ZALLOC_OBJECT_OR_DIE(notifymsg->payload.answer.host, host_address, HOSTADDR_TAG); host_address_set_with_sockaddr(notifymsg->payload.answer.host, sa); #if DNSCORE_HAS_TSIG_SUPPORT // if there is a TSIG ... if(message_tsig_get_key(mesg) != NULL) { notifymsg->payload.answer.message = clone; notifymsg->payload.answer.host->tsig = mesg_tsig_key; } else { notifymsg->payload.answer.message = NULL; notifymsg->payload.answer.host->tsig = NULL; } #endif async_message_s *async = async_message_alloc(); async->id = 0; async->args = notifymsg; async->handler = NULL; async->handler_args = NULL; async_message_call(¬ify_handler_queue, async); } else { log_err("notify: service not initialised"); } } static bool notify_masterquery_read_soa(const u8 *origin, packet_unpack_reader_data *reader, u32 *serial) { ya_result return_value; u8 tmp[MAX_DOMAIN_LENGTH]; /* read and expect an SOA */ if(ISOK(packet_reader_read_fqdn(reader, tmp, sizeof(tmp)))) { if(dnsname_equals(tmp, origin)) { struct type_class_ttl_rdlen tctr; if(packet_reader_read(reader, &tctr, 10) == 10) // exact { if((tctr.qtype == TYPE_SOA) && (tctr.qclass == CLASS_IN)) { if(ISOK(return_value = packet_reader_skip_fqdn(reader))) { if(ISOK(return_value = packet_reader_skip_fqdn(reader))) { if(packet_reader_read(reader, tmp, 4) == 4) // exact { *serial = ntohl(GET_U32_AT_P(tmp)); return TRUE; } } } } } } } return FALSE; } #define NTFYMQTA_TAG 0x4154514d5946544e struct notify_masterquery_thread_args { u8 *origin; u32 serial; bool serial_set; }; typedef struct notify_masterquery_thread_args notify_masterquery_thread_args; static void * notify_masterquery_thread(void *args_) { notify_masterquery_thread_args *args = (notify_masterquery_thread_args*)args_; /* get the zone descriptor for that domain */ zone_desc_s *zone_desc = zone_acquirebydnsname(args->origin); ya_result return_value; if(zone_desc == NULL) { log_err("notify: slave: %{dnsname}: zone not configured", args->origin); dnsname_zfree(args->origin); ZFREE_OBJECT(args); return NULL; } mutex_lock(&zone_desc->lock); zone_clear_status(zone_desc, ZONE_STATUS_NOTIFIED); mutex_unlock(&zone_desc->lock); log_debug("notify: slave: %{dnsname}: processing notify from master", args->origin); /* do an SOA query to the master to retrieve the serial (wait) */ if(!args->serial_set) { log_debug("notify: slave: %{dnsname}: querying the master at %{hostaddr} for SOA", args->origin, zone_desc->masters); zone_lock(zone_desc, ZONE_LOCK_READONLY); host_address *zone_desc_masters = host_address_copy_list(zone_desc->masters); zone_unlock(zone_desc, ZONE_LOCK_READONLY); return_value = message_query_serial(args->origin, zone_desc_masters, &args->serial); host_address_delete_list(zone_desc_masters); if(ISOK(return_value)) // multi-master { args->serial_set = TRUE; log_debug("notify: slave: %{dnsname}: the master at %{hostaddr} has serial %u", args->origin, zone_desc->masters, args->serial); } else { /* we didn't got the serial */ log_debug("notify: slave: %{dnsname}: SOA query to the master at %{hostaddr} failed: %r", args->origin, zone_desc->masters, return_value); // this will fall-back to doing an XFR } } else { log_debug("notify: slave: %{dnsname}: the master at %{hostaddr} has serial %u", args->origin, zone_desc->masters, args->serial); } u32 current_serial; /* get the zone of the domain */ zdb_zone *dbzone = zdb_acquire_zone_read_from_fqdn(g_config->database, args->origin); if(dbzone != NULL) { /* lock it for the XFR (it's a writer, so no other writer allowed) */ log_debug("notify: slave: %{dnsname}: trying to lock for a transfer", args->origin); if(zdb_zone_trylock(dbzone, ZDB_ZONE_MUTEX_XFR)) { /* get the current serial of the zone */ if(ISOK(zdb_zone_getserial(dbzone, ¤t_serial))) // zone is locked { log_debug("notify: slave: %{dnsname}: current serial is %u", args->origin, current_serial); /* * If the serial on the "master" is lower, * nothing has to be done except a note on the log. * * If we didn't got the serial of course, we can only ask to the master. */ if(args->serial_set) { if(serial_lt(args->serial, current_serial)) { /* do nothing at all */ log_debug("notify: slave: %{dnsname}: serial on this slave is higher (%u) than on the notification from master (%u)", zone_origin(zone_desc), current_serial, args->serial); } else if(serial_gt(args->serial, current_serial)) { /* download (and apply) the incremental change */ log_info("notify: slave: %{dnsname}: scheduling an IXFR from %u", zone_origin(zone_desc), current_serial); database_zone_ixfr_query(zone_origin(zone_desc)); } else { /* nothing to do but mark the zone as being refreshed */ log_info("notify: slave: %{dnsname}: serial matches the masters' (%u)", zone_origin(zone_desc), current_serial); zdb_zone_clear_invalid(dbzone); zone_desc->refresh.refreshed_time = zone_desc->refresh.retried_time = time(NULL); zdb_zone_release_unlock(dbzone, ZDB_ZONE_MUTEX_XFR); /* MUST be unlocked here because ... */ database_zone_refresh_maintenance(g_config->database, zone_origin(zone_desc), 0); /* ... this will try to lock */ dnsname_zfree(args->origin); ZFREE_OBJECT(args); log_debug("notify: slave: %{dnsname}: master notify processing done", zone_origin(zone_desc)); zone_release(zone_desc); return NULL; } } else { log_warn("notify: slave: %{dnsname}: the serial of the master has not been obtained, trying an incremental transfer", zone_origin(zone_desc)); database_zone_ixfr_query(zone_origin(zone_desc)); } } else // no soa at apex ... zone needs to be downloaded ... { // the zone is a placeholder if((zone_get_status(zone_desc) & (ZONE_STATUS_LOAD|ZONE_STATUS_LOADING|ZONE_STATUS_DOWNLOADED)) == 0) { log_debug("notify: slave: %{dnsname}: downloading a new copy of the zone", args->origin); database_zone_axfr_query(zone_origin(zone_desc)); } else { log_debug("notify: slave: %{dnsname}: still busy loading the zone", args->origin); } } zdb_zone_release_unlock(dbzone, ZDB_ZONE_MUTEX_XFR); } else // could not lock with ZDB_ZONE_MUTEX_XFR { /* * The zone has been locked already ? give up ... */ mutex_lock(&dbzone->lock_mutex); u8 dbzone_lock_owner = dbzone->lock_owner; mutex_unlock(&dbzone->lock_mutex); log_info("notify: slave: %{dnsname}: already locked (%x)", args->origin, dbzone_lock_owner); zdb_zone_release(dbzone); database_zone_refresh_maintenance(g_config->database, args->origin, time(NULL) + 5); } } else { /* * Ask for an AXFR of the zone */ log_info("notify: slave: %{dnsname}: scheduling an AXFR", zone_origin(zone_desc)); database_zone_axfr_query(zone_origin(zone_desc)); } /* AXFR */ dnsname_zfree(args->origin); ZFREE_OBJECT(args); log_debug("notify: slave: %{dnsname}: master notify processing done", zone_origin(zone_desc)); zone_release(zone_desc); return NULL; } /** * The purely network part of the sending of a notify udp packet * * @param ha destination, TSIG supported * @param msgdata a message to be used for message construction * @param id the message id * @param origin origin * @param ntype type * @param nclass class * @return */ static ya_result notify_send(host_address* ha, message_data *mesg, u16 id, const u8 *origin, u16 ntype, u16 nclass) { #if DEBUG log_debug("notify: send(%{hostaddr}, %p, %hx, %{dnsname}, %{dnstype}, %{dnsclass})", ha, mesg, id, origin, &ntype, &nclass); #endif socketaddress sa; ya_result return_code; message_make_notify(mesg, id, origin, ntype, nclass); #if DNSCORE_HAS_TSIG_SUPPORT if(ha->tsig != NULL) { if(FAIL(return_code = message_sign_query(mesg, ha->tsig))) { log_err("notify: %{dnsname}: unable to sign message for %{sockaddr} with key %{dnsname}: %r", origin, &sa, ha->tsig->name, return_code); return return_code; } } #endif if(ISOK(return_code = host_address2sockaddr(ha, &sa))) { #if DNSCORE_HAS_TSIG_SUPPORT if(ha->tsig == NULL) { #endif #if !DEBUG log_debug("notify: %{dnsname}: notifying %{sockaddr}", origin, &sa.sa); #else log_info("notify: %{dnsname}: notifying %{sockaddr} with %{dnstype} %{dnsclass} (debug)", origin, &sa.sa, &ntype, &nclass); #endif #if DNSCORE_HAS_TSIG_SUPPORT } else { #if !DEBUG log_debug("notify: %{dnsname}: notifying %{sockaddr} (key=%{dnsname})", origin, &sa.sa, ha->tsig->name); #else log_info("notify: %{dnsname}: notifying %{sockaddr} (key=%{dnsname}) with (%{dnstype} %{dnsclass}) (debug)", origin, &sa.sa, ha->tsig->name, &ntype, &nclass); #endif } #endif int s = -1; int addrlen; switch(sa.sa.sa_family) { case AF_INET: { s = send_socket4; addrlen = sizeof(sa.sa4); break; } case AF_INET6: { s = send_socket6; addrlen = sizeof(sa.sa6); break; } } if(s >= 0) { // s >= 0 => addrlen is initialised #if DEBUG log_debug("notify: sendto(%d, %p, %d, %d, %{sockaddr}, %d)", s, message_get_buffer_const(mesg), message_get_size(mesg), 0, (struct sockaddr*)&sa.sa, addrlen); log_memdump_ex(g_server_logger, MSG_DEBUG5, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT); #endif if(ISOK(return_code = sendto(s, message_get_buffer_const(mesg), message_get_size(mesg), 0, &sa.sa, addrlen))) { log_debug("notify: %{dnsname}: sent %i bytes to %{sockaddr}", origin, message_get_size(mesg), &sa.sa); } else { int err = errno; if(err != ENOTSOCK) { log_err("notify: %{dnsname}: failed to send notify to %{sockaddr}: %r", origin, &sa.sa, MAKE_ERRNO_ERROR(err)); } } } else { return_code = MAKE_ERRNO_ERROR(ENOTSOCK); // wrong socket // if we cannot get the reply, no point trying to send the query log_err("notify: %{dnsname}: no listening interface can receive from %{sockaddr}", origin, &sa.sa); } } else { log_err("notify: %{dnsname}: unable to convert '%{hostaddr}' to an address", origin, ha); } return return_code; } /** * * Uses a thread to handle the notify from the master (notify_masterquery_thread) * * The message is a NOTIFY SOA IN * The reader points into the buffer of the message and is exactly after the Q section. * * * @param database the database * @param mesg the message * @param reader packet reader into the above message, positioned right after the Q section * * @return an error code */ static ya_result notify_process_masterquery_in_enqueue(const message_data *mesg, packet_unpack_reader_data *reader) { ya_result return_value; u32 serial = 0; // to silence gcc : this was not a bug bool serial_set = FALSE; if(message_get_answer_count_ne(mesg) != 0) { serial_set = notify_masterquery_read_soa(message_get_canonised_fqdn(mesg), reader, &serial); } notify_masterquery_thread_args *args; ZALLOC_OBJECT_OR_DIE( args, notify_masterquery_thread_args, NTFYMQTA_TAG); args->origin = dnsname_zdup(message_get_canonised_fqdn(mesg)); args->serial = serial; args->serial_set = serial_set; return_value = thread_pool_enqueue_call(notify_thread_pool, notify_masterquery_thread, args, NULL, "notify: slave"); return return_value; } static ya_result notify_process_masterquery_in(message_data *mesg, packet_unpack_reader_data *reader) { zone_desc_s *zone_desc; ya_result return_value = SUCCESS; zone_desc = zone_acquirebydnsname(message_get_canonised_fqdn(mesg)); if(zone_desc != NULL) { message_set_authoritative_answer(mesg); if(zone_desc->type == ZT_SLAVE) { if(message_has_tsig(mesg)) { log_info("notify: slave: %{dnsname}: %{sockaddr} sent a notification query, class %{dnsclass}, key %{dnsname}", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg), message_get_query_class_ptr(mesg), message_tsig_get_name(mesg)); } else { log_info("notify: slave: %{dnsname}: %{sockaddr} sent a notification query, class %{dnsclass}", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg), message_get_query_class_ptr(mesg)); } #if ZDB_HAS_ACL_SUPPORT if(ACL_REJECTED(acl_check_access_filter(mesg, &zone_desc->ac.allow_notify))) { /* notauth */ if(message_has_tsig(mesg)) { log_notice("notify: slave: %{dnsname}: %{sockaddr} key %{dnsname}: not authorised", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg), message_tsig_get_name(mesg)); } else { log_notice("notify: slave: %{dnsname}: %{sockaddr}: not authorised", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); } message_set_status(mesg, FP_NOTIFY_REJECTED); message_update_answer_status(mesg); zone_release(zone_desc); return ACL_NOTIFY_REJECTED; } #endif if(!zone_isfrozen(zone_desc)) { mutex_lock(&zone_desc->lock); u32 zone_status_notified = zone_get_set_status(zone_desc, ZONE_STATUS_NOTIFIED); mutex_unlock(&zone_desc->lock); if(zone_status_notified == 0) { return_value = notify_process_masterquery_in_enqueue(mesg, reader); // thread-safe } // else it's already enqueued for notification } else { log_info("notify: slave: %{dnsname}: %{sockaddr}: zone is frozen", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); } } /* type = SLAVE */ else { /* type = MASTER ? */ // note: a slave can also be a master ... do not cut this log_info("notify: %{dnsname}: %{sockaddr}: host sent a notification query for master zone ", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); message_set_status(mesg, FP_SLAVE_NOTIFIES_MASTER); return_value = NOTIFY_QUERY_TO_MASTER; } } else { log_notice("notify: %{dnsname}: %{sockaddr}: host sent a notification query for an unknown zone", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); message_set_status(mesg, FP_NOTIFY_UNKNOWN_ZONE); return_value = NOTIFY_QUERY_TO_UNKNOWN; } message_update_answer_status(mesg); zone_release(zone_desc); return return_value; } /** @brief Handle a notify from the master (or another slave) * * @param database : the database * @param mesg : the input message * * @retval OK * @retval NOK */ ya_result notify_process(message_data *mesg) { /* rfc1996 * 3.7: * A NOTIFY request has QDCOUNT>0, ANCOUNT>=0, AUCOUNT>=0, * ADCOUNT>=0. If ANCOUNT>0, then the answer section represents an * unsecure hint at the new RRset for this */ if(!message_isquery(mesg)) { /* * It's an answer from a slave (we are the master) * It works if we are the master for the zone AND we sent a notify. * Else we discard. */ log_debug1("notify: %{dnsname}: %{sockaddr}: processing notification reply", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); notify_slaveanswer(mesg); // thread-safe return SUCCESS; } else { /* * It's a notification by the "master" ... (or in the case of an AXFR/CTRL a request to be notified of all dynamic zones) * It works if we are a slave for the zone. * Else we discard. */ ya_result return_value; log_debug1("notify: %{dnsname}: %{sockaddr}: processing notification", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); message_set_answer(mesg); packet_unpack_reader_data pr; packet_reader_init_from_message(&pr, mesg); u8 tmp[MAX_DOMAIN_LENGTH]; if(ISOK(return_value = packet_reader_read_fqdn(&pr, tmp, sizeof(tmp)))) { u16 qtype; if(ISOK(return_value = packet_reader_read_u16(&pr, &qtype))) { u16 qclass; if(ISOK(return_value = packet_reader_read_u16(&pr, &qclass))) { switch(qclass) { case CLASS_IN: { /* * Master sent an notify for the IN class */ notify_process_masterquery_in(mesg, &pr); break; } default: { message_make_error(mesg, FP_NOT_SUPP_CLASS); break; } } } } } #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) /* NOTE: the TSIG information is in mseg */ { tsig_sign_answer(mesg); } #endif return return_value; } } static void notify_message_free(notify_message *notifymsg) { if(notifymsg == NULL) { return; } #if DEBUG log_debug("notify_message_free({%{dnsname}@%p, %i}@%p)", notifymsg->origin, notifymsg->origin, notifymsg->payload.type, notifymsg); #endif if(notifymsg->origin != NULL) { dnsname_zfree(notifymsg->origin); notifymsg->origin = NULL; } switch(notifymsg->payload.type) { case NOTIFY_MESSAGE_TYPE_NOTIFY: { host_address_delete_list(notifymsg->payload.notify.hosts_list); break; } case NOTIFY_MESSAGE_TYPE_ANSWER: { #if DEBUG log_debug("notify_message_free(%p) host_address_delete(%p)", notifymsg, notifymsg->payload.answer.host); debug_log_stacktrace(g_server_logger, MSG_DEBUG7, "notify_message_free:host_address_delete"); #endif host_address_delete(notifymsg->payload.answer.host); if(notifymsg->payload.answer.message != NULL) { message_free(notifymsg->payload.answer.message); // message_data => message_free } break; } case NOTIFY_MESSAGE_TYPE_DOMAIN: { break; } case NOTIFY_MESSAGE_TYPE_CLEAR: { break; } default: { log_debug("notify_message_free(%p) invalid notify message type %x", notifymsg, notifymsg->payload.type); debug_log_stacktrace(g_server_logger, MSG_DEBUG7, "notify_message_free:host_address_delete"); break; } } #if DEBUG memset(notifymsg, 0xff, sizeof(notify_message)); #endif ZFREE_OBJECT(notifymsg); } static int notify_process_dnsname_compare(const void *node_a, const void *node_b) { const u8 *m_a = (const u8*)node_a; const u8 *m_b = (const u8*)node_b; return dnsname_compare(m_a, m_b); } static void notify_ipv4_receiver_service(struct service_worker_s *worker) { log_info("notify: notification service IPv4 receiver started (socket %i)", send_socket4); message_data *mesg = message_new_instance(); tcp_set_recvtimeout(send_socket4, NOTIFY_RECEIVE_TIMEOUT_SECONDS, 0); /* half a second for UDP is a lot ... */ while(service_should_run(worker)) { ya_result ret; message_recv_udp_reset(mesg); message_reset_control_size(mesg); if(message_recv_udp(mesg, send_socket4) > 0) { // process slave answer if(ISOK(ret = message_process_lenient(mesg))) { #if NOTIFY_DETAILED_LOG log_debug("notify_ipv4_receiver_service(%{dnsname} %{sockaddr})", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); #endif notify_slaveanswer(mesg); } else { log_err("notify_ipv4_receiver_service: processing message: %r", ret); } } else { ret = ERRNO_ERROR; if((ret == MAKE_ERRNO_ERROR(EAGAIN)) || (ret == MAKE_ERRNO_ERROR(EINTR))) { #if NOTIFY_DETAILED_LOG log_debug("notify_ipv4_receiver_service: %r", ret); #endif } else { log_err("notify_ipv4_receiver_service: %r", ret); sleep(1); } } } message_free(mesg); log_info("notify: notification service IPv4 receiver stopped"); } static void notify_ipv6_receiver_service(struct service_worker_s *worker) { log_info("notify: notification service IPv6 receiver started (socket %i)", send_socket6); message_data *mesg = message_new_instance(); tcp_set_recvtimeout(send_socket6, NOTIFY_RECEIVE_TIMEOUT_SECONDS, 0); /* half a second for UDP is a lot ... */ while(service_should_run(worker)) { ya_result ret; message_recv_udp_reset(mesg); if(message_recv_udp(mesg, send_socket6) > 0) { // process slave answer if(ISOK(ret = message_process_lenient(mesg))) { #if NOTIFY_DETAILED_LOG log_debug("notify_ipv6_receiver_service(%{dnsname} %{sockaddr})", message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); #endif notify_slaveanswer(mesg); } else { log_err("notify_ipv6_receiver_service: processing message: %r", ret); } } else { ret = ERRNO_ERROR; if((ret == MAKE_ERRNO_ERROR(EAGAIN)) || (ret == MAKE_ERRNO_ERROR(EINTR))) { #if NOTIFY_DETAILED_LOG log_debug("notify_ipv6_receiver_service: %r", ret); #endif } else { log_err("notify_ipv6_receiver_service: %r", ret); sleep(1); } } } message_free(mesg); log_info("notify: notification service IPv6 receiver stopped"); } struct notify_service_context { ptr_set notifications_being_sent; ptr_set notify_queries_not_answered_yet; ptr_vector todelete; random_ctx rnd; message_data *mesg; s64 last_current_queries_cleanup_epoch_us; s64 service_loop_begin_us; }; static void notify_service_context_init(struct notify_service_context *ctx) { #if NOTIFY_DETAILED_LOG log_debug("notify_service_context_init(%p)", ctx); #endif ctx->mesg = message_new_instance(); ctx->rnd = thread_pool_get_random_ctx(); ctx->notifications_being_sent.root = NULL; ctx->notifications_being_sent.compare = notify_process_dnsname_compare; ctx->notify_queries_not_answered_yet.root = NULL; ctx->notify_queries_not_answered_yet.compare = message_query_summary_compare; ctx->last_current_queries_cleanup_epoch_us = 0; ptr_vector_init_empty(&ctx->todelete); ctx->service_loop_begin_us = timeus(); } static void notify_service_context_manage_pending_notifications(struct notify_service_context *ctx) { // cleanup start #if NOTIFY_DETAILED_LOG log_debug("notify_service_context_manage_pending_notifications(%p)", ctx); #endif // what happens in here should not interfere with the rest of the function s64 tus = ctx->service_loop_begin_us; if(!ptr_set_isempty(&ctx->notify_queries_not_answered_yet) && (tus >= ctx->last_current_queries_cleanup_epoch_us)) { /* create a list of expired message_query_summary */ #if NOTIFY_CLEANUP_DUMP log_debug("notify: cleaning up expired notifications"); #endif message_query_summary head; head.next = NULL; message_query_summary *current_queries_to_clear = &head; ctx->last_current_queries_cleanup_epoch_us = tus; if(ptr_set_isempty(&ctx->notify_queries_not_answered_yet)) { /* find them using an iterator */ ptr_set_iterator current_queries_iter; ptr_set_iterator_init(&ctx->notify_queries_not_answered_yet, ¤t_queries_iter); while(ptr_set_iterator_hasnext(¤t_queries_iter)) { ptr_node *node = ptr_set_iterator_next_node(¤t_queries_iter); message_query_summary *mqs = (message_query_summary*)node->value; #if NOTIFY_DETAILED_LOG log_debug("notify: domain=%{dnsname} slave=%{hostaddr} expires=%llT tries=%i", mqs->fqdn, mqs->host, mqs->expire_epoch_us, mqs->tries); #endif if(ctx->last_current_queries_cleanup_epoch_us > mqs->expire_epoch_us) { #if NOTIFY_DETAILED_LOG log_debug("notify: domain=%{dnsname} slave=%{hostaddr} expires=%llT tries=%i: current try expired", mqs->fqdn, mqs->host, mqs->expire_epoch_us, mqs->tries); #endif #if DEBUG double expired_since = ctx->last_current_queries_cleanup_epoch_us - mqs->expire_epoch_us; expired_since /= ONE_SECOND_US_F; #endif if(--mqs->tries <= 0) { #if NOTIFY_DETAILED_LOG log_debug("notify: domain=%{dnsname} slave=%{hostaddr} expires=%llT tries=%i: expired", mqs->fqdn, mqs->host, mqs->expire_epoch_us, mqs->tries); #endif bool give_up = TRUE; zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, mqs->fqdn); // RC++ if(zone != NULL) { if((zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_WILL_NOTIFY_AGAIN) != 0) { #if DEBUG log_debug("notify: query (%hx) %{dnsname} to %{hostaddr} expired %f seconds ago but was re-armed", mqs->id, mqs->fqdn, mqs->host, expired_since); #endif give_up = FALSE; zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY_AGAIN); mqs->expire_epoch_us = tus + MESSAGE_QUERY_TIMEOUT_US; mqs->tries = MESSAGE_QUERY_TRIES; notify_send(mqs->host, ctx->mesg, mqs->id, mqs->fqdn, TYPE_SOA, CLASS_IN); } else { #if NOTIFY_DETAILED_LOG log_debug("notify: domain=%{dnsname} slave=%{hostaddr} expires=%llT tries=%i: notification status cleared", mqs->fqdn, mqs->host, mqs->expire_epoch_us, mqs->tries); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY); } zdb_zone_release(zone); } if(give_up) { #if DEBUG log_debug("notify: query (%hx) %{dnsname} to %{hostaddr} expired %f seconds ago, giving up", mqs->id, mqs->fqdn, mqs->host, expired_since); #endif current_queries_to_clear->next = mqs; current_queries_to_clear = mqs; } } else { #if NOTIFY_DETAILED_LOG log_debug("notify: domain=%{dnsname} slave=%{hostaddr} expires=%llT tries=%i: will try again", mqs->fqdn, mqs->host, mqs->expire_epoch_us, mqs->tries); #endif #if DEBUG log_debug("notify: query (%hx) %{dnsname} to %{hostaddr} expired %f seconds ago retrying (%i times remaining)", mqs->id, mqs->fqdn, mqs->host, expired_since, mqs->tries); #endif mqs->expire_epoch_us = tus + MESSAGE_QUERY_TIMEOUT_US; // send the message again notify_send(mqs->host, ctx->mesg, mqs->id, mqs->fqdn, TYPE_SOA, CLASS_IN); } } #if DEBUG else { log_debug("notify: query (%hx) %{dnsname} to %{hostaddr} still in flight", mqs->id, mqs->fqdn, mqs->host); } #endif } /* once the tree has been scanned, destroy every node listed */ current_queries_to_clear = head.next; if(current_queries_to_clear != NULL) { do { message_query_summary* mqs = current_queries_to_clear; #if DEBUG log_debug("notify: clearing query (%hx) %{dnsname} to %{hostaddr}", mqs->id, mqs->fqdn, mqs->host); #endif current_queries_to_clear = current_queries_to_clear->next; ptr_set_delete(&ctx->notify_queries_not_answered_yet, mqs); zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, mqs->fqdn); // RC++ if(zone != NULL) { zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY); zdb_zone_release(zone); } message_query_summary_delete(mqs); } while(current_queries_to_clear != NULL); } #if DEBUG else { #if NOTIFY_CLEANUP_DUMP log_debug("notify: no queries to clear"); #endif } #endif } // if !ptr_set_isempty(¤t_queries) #if DEBUG else { #if NOTIFY_CLEANUP_DUMP log_debug("notify: no unanswered queries"); #endif } #endif } #if DEBUG else { if(ptr_set_isempty(&ctx->notify_queries_not_answered_yet)) { #if NOTIFY_CLEANUP_DUMP log_debug("notify: no notification queries needs to be answered"); #endif } if(tus < ctx->last_current_queries_cleanup_epoch_us) { #if NOTIFY_CLEANUP_DUMP float dt = (ctx->last_current_queries_cleanup_epoch_us - tus) / 1000LL; dt /= 1000.0f; log_debug("notify: still %.3fus before cleaning up times out", dt); #endif } #if NOTIFY_CLEANUP_DUMP if(ctx->last_current_queries_cleanup_epoch_us > 0) { log_debug("notify: no timeout to handle (expect next at %llT)", ctx->last_current_queries_cleanup_epoch_us); } else { log_debug("notify: no timeout to handle"); } #endif } #endif if((ctx->last_current_queries_cleanup_epoch_us < tus) && (ctx->last_current_queries_cleanup_epoch_us > 0)) { ctx->last_current_queries_cleanup_epoch_us += MESSAGE_QUERY_TIMEOUT_US; } // cleanup end } static void notify_service_context_process_next_message(struct notify_service_context *ctx, notify_message *notifymsg) { switch(notifymsg->payload.type) { case NOTIFY_MESSAGE_TYPE_CLEAR: { ptr_node *node = ptr_set_find(&ctx->notifications_being_sent, notifymsg->origin); if(node != NULL) { #if NOTIFY_DETAILED_LOG log_debug("notify_service_context_process_next_message(%{dnsname} : clear)", notifymsg->origin); #endif notify_message *zone_message = (notify_message*)node->value; if(zone_message != NULL) { #if !DEBUG log_debug("notify: %{dnsname}: removing slaves notifications", notifymsg->origin); #else log_info("notify: %{dnsname}: removing slaves notifications (%p) (debug)", notifymsg->origin, notifymsg); #endif zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, notifymsg->origin); // RC++ if(zone != NULL) { #if DEBUG log_debug("notify: %{dnsname}: clearing notification status for zone", notifymsg->origin); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY|ZDB_ZONE_STATUS_WILL_NOTIFY_AGAIN); zdb_zone_release(zone); } else { log_err("notify: %{dnsname}: could not un-mark zone as queue for notification: zone not found ?", notifymsg->origin); } ptr_set_delete(&ctx->notifications_being_sent, notifymsg->origin); notify_message_free(zone_message); } else { #if NOTIFY_DETAILED_LOG log_debug("notify_service_context_process_next_message(%{dnsname} : nothing to clear)", notifymsg->origin); #endif } } notify_message_free(notifymsg); break; } case NOTIFY_MESSAGE_TYPE_DOMAIN: { #if !DEBUG log_debug("notify: %{dnsname}: notifying slaves by domain", notifymsg->origin); #else log_info("notify: %{dnsname}: notifying slaves by domain (%p) (debug)", notifymsg->origin, notifymsg); #endif if(!notify_slaves_convert_domain_to_notify(notifymsg)) { #if !DEBUG log_debug("notify: %{dnsname}: failed to notify slaves by domain", notifymsg->origin); #else log_info("notify: %{dnsname}: failed to notify slaves by domain (%p) (debug)", notifymsg->origin, notifymsg); #endif zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, notifymsg->origin); // RC++ if(zone != NULL) { #if DEBUG log_debug("notify: %{dnsname}: clearing notification status for zone", notifymsg->origin); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY|ZDB_ZONE_STATUS_WILL_NOTIFY_AGAIN); zdb_zone_release(zone); } else { log_err("notify: %{dnsname}: could not un-mark zone as queue for notification: zone not found ?", notifymsg->origin); } // failed notify_message_free(notifymsg); break; } } FALLTHROUGH // fall through case NOTIFY_MESSAGE_TYPE_NOTIFY: { #if !DEBUG log_debug("notify: %{dnsname}: notifying slaves", notifymsg->origin); #else log_info("notify: %{dnsname}: notifying slaves with %{dnstype} %{dnsclass} (debug)", notifymsg->origin, ¬ifymsg->payload.notify.ztype, ¬ifymsg->payload.notify.zclass); #endif host_address **ha_prev = ¬ifymsg->payload.notify.hosts_list; host_address *ha = *ha_prev; while(ha != NULL) // resolve all domain names in the list, replace them with the resolved address { if(ha->version == HOST_ADDRESS_DNAME) { /* resolve */ char name[MAX_DOMAIN_LENGTH + 1]; dnsname_to_cstr(name, ha->ip.dname.dname); socketaddress sa; ya_result ret = gethostaddr(name, g_config->server_port_value, &sa.sa, 0); if(ISOK(ret)) { #if DEBUG log_info("notify: %{dnsname}: notifying slave %{hostaddr} (debug)", notifymsg->origin, ha); #endif host_address ha; host_address_set_with_sockaddr(&ha, &sa); host_address_append_host_address(notifymsg->payload.notify.hosts_list, &ha); } else { log_warn("notify: %{dnsname}: unable to resolve %{dnsname}: %r", notifymsg->origin, ha->ip.dname.dname, ret); } *ha_prev = ha->next; host_address_delete(ha); } else { ha_prev = &ha->next; } ha = *ha_prev; } /* * The current queue has been resolved. */ /** * The list has to replace the current one for message->origin (because it's starting again) */ #if DEBUG log_debug("notify: queuing notifications for %{dnsname}", notifymsg->origin); #endif ptr_node *node = ptr_set_insert(&ctx->notifications_being_sent, notifymsg->origin); if(node->value != NULL) { #if DEBUG log_info("notify: %{dnsname}: notifying slave %{hostaddr}: replacing previous message (debug)", notifymsg->origin, ha); #endif notify_message* old_message = (notify_message*)node->value; // get the old value node->key = notifymsg->origin; // (same key but the old pointer is about to be deleted) node->value = notifymsg; // set the new value notify_message_free(old_message); // destroy the old value. notify_zones does not contains it anymore } else { node->value = notifymsg; } // ready to send zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, notifymsg->origin); // RC++ if(zone != NULL) { #if DEBUG log_debug("notify: %{dnsname}: clearing notification status for zone", notifymsg->origin); #endif zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY); zdb_zone_release(zone); } else { log_err("notify: %{dnsname}: could not un-mark zone as queue for notification: zone not found ?", notifymsg->origin); } notifymsg->payload.notify.epoch = time(NULL); break; } case NOTIFY_MESSAGE_TYPE_ANSWER: { log_debug("notify: %{dnsname}: answer from slave at %{hostaddr}", notifymsg->origin, notifymsg->payload.answer.host); ptr_node *node = ptr_set_find(&ctx->notifications_being_sent, notifymsg->origin); if(node != NULL) { notify_message *notify_zones_notifymsg = (notify_message*)node->value; if(notify_zones_notifymsg != NULL) { /* * Look for the entry and remove it */ /* notifymsg->payload.answer.tsig ... */ /* all's good so remove the notify query from the list */ if(host_address_list_contains_host(notify_zones_notifymsg->payload.notify.hosts_list, notifymsg->payload.answer.host)) { host_address *ha; #if DNSCORE_HAS_TSIG_SUPPORT ha = notifymsg->payload.answer.host; message_query_summary tmp; if(ha->tsig != NULL) { u16 id = message_get_id(notifymsg->payload.answer.message); message_query_summary_init(&tmp, id, ha, notifymsg->payload.answer.message); // try to find the exact match ptr_node *node = ptr_set_find(&ctx->notify_queries_not_answered_yet, &tmp); message_query_summary_clear(&tmp); if(node == NULL) { /* most likely a timeout */ log_notice("notify: %{dnsname}: %{hostaddr}: unexpected answer: could not find a matching query for notification answer with id %04hx", notifymsg->origin, notifymsg->payload.answer.host, id); // delete notifymsg notify_message_free(notifymsg); break; } message_query_summary *mqs = (message_query_summary*)node->value; if(mqs != NULL) { // verify the signature ya_result return_value; if(FAIL(return_value = tsig_verify_answer(notifymsg->payload.answer.message, mqs->mac, mqs->mac_size))) { // if everything is good, then proceed log_notice("notify: %{dnsname}: %{hostaddr}: TSIG signature verification failed: %r", notifymsg->origin, notifymsg->payload.answer.host, return_value); // delete notifymsg notify_message_free(notifymsg); break; } message_free(notifymsg->payload.answer.message); // message_data => message_free notifymsg->payload.answer.message = NULL; ptr_set_delete(&ctx->notify_queries_not_answered_yet, mqs); message_query_summary_delete(mqs); } else // this should never happen { log_err("notify: %{dnsname}: %{hostaddr}: invalid internal state", notifymsg->origin, notifymsg->payload.answer.host); ptr_set_delete(&ctx->notify_queries_not_answered_yet, &tmp); } } /* end of TSIG verification, with success*/ #endif ha = host_address_remove_host_address(¬ify_zones_notifymsg->payload.notify.hosts_list, notifymsg->payload.answer.host); host_address_delete(ha); if(notifymsg->payload.answer.rcode == RCODE_OK) { if(notifymsg->payload.answer.aa) /// @note 20190712 edf -- this 8383 { log_debug("notify: %{dnsname}: answer from slave at %{hostaddr} confirmed", notifymsg->origin, notifymsg->payload.answer.host); zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, notifymsg->origin); // RC++ if(zone != NULL) { #if DEBUG log_debug("notify: %{dnsname}: clearing notification status for zone", notifymsg->origin); #endif if((zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_WILL_NOTIFY_AGAIN) != 0) { // resend } zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY|ZDB_ZONE_STATUS_WILL_NOTIFY_AGAIN); zdb_zone_release(zone); } else { log_err("notify: %{dnsname}: could not un-mark zone as queue for notification: zone not found ?", notifymsg->origin); } } else { log_notice("notify: %{dnsname}: %{hostaddr}: no AA in answer", notifymsg->origin, notifymsg->payload.answer.host); } } else { log_warn("notify: %{dnsname}: %{hostaddr}: answered with %r", notifymsg->origin, notifymsg->payload.answer.host, MAKE_DNSMSG_ERROR(notifymsg->payload.answer.rcode)); } } else { log_notice("notify: %{dnsname}: %{hostaddr}: unexpected answer: host is not on the currently notified list", notifymsg->origin, notifymsg->payload.answer.host); } if(notify_zones_notifymsg->payload.notify.hosts_list == NULL) { ptr_set_delete(&ctx->notifications_being_sent, notify_zones_notifymsg->origin); notify_message_free(notify_zones_notifymsg); } } else // msg = NULL { log_notice("notify: %{dnsname}: %{hostaddr}: unexpected answer", notifymsg->origin, notifymsg->payload.answer.host); ptr_set_delete(&ctx->notifications_being_sent, notifymsg->origin); } } else { log_debug("notify: %{dnsname}: %{hostaddr}: unexpected answer: no pending notifications for the zone", notifymsg->origin, notifymsg->payload.answer.host); } // delete notifymsg notify_message_free(notifymsg); break; } #if DEBUG default: { log_err("notify: unknown notifymsg type %i", notifymsg->payload.type); break; } #endif } /* switch notifymsg type */ } #if DEBUG atomic_bool notify_no_notification_notified = FALSE; #endif static void notify_service_context_send_notifications(struct notify_service_context *ctx) { #if DEBUG if(ptr_set_isempty(&ctx->notifications_being_sent)) { if(!atomic_load(¬ify_no_notification_notified)) { log_debug("notify: no notification to send"); atomic_store(¬ify_no_notification_notified, TRUE); } return; } else { log_debug("notify: sending notifications"); atomic_store(¬ify_no_notification_notified, FALSE); } #endif time_t now = time(NULL); int total_sent = 0; ptr_set_iterator notifications_being_sent_iter; ptr_set_iterator_init(&ctx->notifications_being_sent, ¬ifications_being_sent_iter); while(ptr_set_iterator_hasnext(¬ifications_being_sent_iter)) { ptr_node *notify_zone_node = ptr_set_iterator_next_node(¬ifications_being_sent_iter); notify_message *notifymsg = notify_zone_node->value; if(notifymsg->payload.notify.epoch > now) { #if DEBUG log_debug("notify: notify_send(, %p, , %{dnsname}, %{dnstype}, %{dnsclass}) should happend after %T", ctx->mesg, notifymsg->origin, ¬ifymsg->payload.notify.ztype, ¬ifymsg->payload.notify.zclass, notifymsg->payload.notify.epoch); #endif continue; } if(dnscore_shuttingdown()) { ptr_vector_append(&ctx->todelete, notifymsg); continue; } bool had_failures = FALSE; for(host_address *ha = notifymsg->payload.notify.hosts_list; ha != NULL; ) // for all slaves to be notified { /* * Send an UDP packet to the ha */ u16 id = random_next(ctx->rnd); #if DEBUG log_debug("notify: notify_send(%{hostaddr}, %p, %hx, %{dnsname}, %{dnstype}, %{dnsclass}) repeat=%i, repeat-increase=%i", ha, ctx->mesg, id, notifymsg->origin, ¬ifymsg->payload.notify.ztype, ¬ifymsg->payload.notify.zclass, (int)notifymsg->payload.notify.repeat_countdown, (int)notifymsg->payload.notify.repeat_period_increase ); #endif ya_result ret = notify_send(ha, ctx->mesg, id, notifymsg->origin, notifymsg->payload.notify.ztype, notifymsg->payload.notify.zclass); host_address *ha_next = ha->next; if(ISOK(ret)) { ++total_sent; message_query_summary* mqs; ZALLOC_OBJECT_OR_DIE( mqs, message_query_summary, MSGQSUMR_TAG); message_query_summary_init(mqs, id, ha, ctx->mesg); ptr_node *node = ptr_set_insert(&ctx->notify_queries_not_answered_yet, mqs); if(node->value != NULL) { // destroy this mqs #if DEBUG log_debug("notify: node %{hostaddr}[%04x] already exists, replacing", mqs->host, mqs->id); #endif message_query_summary_delete(node->value); node->key = mqs; } #if DEBUG else { log_debug("notify: node %{hostaddr}[%04x] added to current queries", mqs->host, mqs->id); } #endif node->value = mqs; } else // remove it { log_warn("notify: %{dnsname} could not send notification to %{hostaddr}", notifymsg->origin, ha); host_address *rem_ha = host_address_remove_host_address(¬ifymsg->payload.notify.hosts_list, ha); if(rem_ha != NULL) { host_address_delete(rem_ha); } had_failures = TRUE; } ha = ha_next; } if(had_failures) { #if DEBUG log_debug("notify: notify_send(, %p, , %{dnsname}, %{dnstype}, %{dnsclass}) did not fully succeed", ctx->mesg, notifymsg->origin, ¬ifymsg->payload.notify.ztype, ¬ifymsg->payload.notify.zclass); #endif zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, notifymsg->origin); // RC++ if(zone == NULL) { zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY); zdb_zone_release(zone); } // try later } else { #if DEBUG log_debug("notify: notify_send(, %p, , %{dnsname}, %{dnstype}, %{dnsclass}) all notifications sent", ctx->mesg, notifymsg->origin, ¬ifymsg->payload.notify.ztype, ¬ifymsg->payload.notify.zclass); #endif } /* decrease the countdown or remove it from the collection */ if(notifymsg->payload.notify.repeat_countdown > 0) { --notifymsg->payload.notify.repeat_countdown; /* ensure there is no overload */ u16 rp = notifymsg->payload.notify.repeat_period + notifymsg->payload.notify.repeat_period_increase; if(rp > 255) /* minutes, 8 bits */ { rp = 255; } notifymsg->payload.notify.repeat_period = (u8)rp; notifymsg->payload.notify.epoch = now + notifymsg->payload.notify.repeat_period * 60; // repeat_period is minutes } else { ptr_vector_append(&ctx->todelete, notifymsg); } } notify_message **notifymsgp = (notify_message**)ctx->todelete.data; for(s32 idx = 0; idx <= ctx->todelete.offset; idx++) { notify_message *notifymsg = notifymsgp[idx]; ptr_set_delete(&ctx->notifications_being_sent, notifymsg->origin); notify_message_free(notifymsg); } ptr_vector_clear(&ctx->todelete); #if DEBUG if(total_sent > 0) { log_debug("notify: %i notifications sent", total_sent); } #endif } static void notify_service_context_wait(struct notify_service_context *ctx) { for(;;) { s64 service_loop_end_us = timeus(); if(service_loop_end_us < ctx->service_loop_begin_us) { service_loop_end_us = ctx->service_loop_begin_us; } s64 remaining = ONE_SECOND_US - (service_loop_end_us - ctx->service_loop_begin_us); if(remaining <= 0) { break; } usleep(service_loop_end_us - ctx->service_loop_begin_us); } } static void notify_service_context_finalize(struct notify_service_context *ctx) { ptr_set_iterator iter; u32 total_count; u32 count; total_count = 0; count = 0; ptr_set_iterator_init(&ctx->notifications_being_sent, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); //host_address *ha = (host_address*)node->key; notify_message* message = (notify_message*)node->value; // get the old value if(message != NULL) { notify_message_free(message); // destroy the message node->key = NULL; // (same key but the old pointer is about to be deleted) node->value = NULL; // set the new value count++; } total_count++; } log_debug("notify: cleared %u messages", count); if(count != total_count) { log_notice("notify: %u messages were empty", total_count - count); } ptr_set_destroy(&ctx->notifications_being_sent); total_count = 0; count = 0; ptr_set_iterator_init(&ctx->notify_queries_not_answered_yet, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); message_query_summary* mqs = (message_query_summary*)node->value; if(mqs != NULL) { message_query_summary_delete(mqs); count++; } total_count++; } log_debug("notify: cleared %u summaries", count); if(count != total_count) { log_notice("notify: %u summaries were empty", total_count - count); } ptr_set_destroy(&ctx->notify_queries_not_answered_yet); ptr_vector_destroy(&ctx->todelete); if(ctx->mesg != NULL) { message_free(ctx->mesg); // message_data ctx->mesg = NULL; } } static int notify_service(struct service_worker_s *worker) { /* * Resolve the names and replace them by their IP * * Remove the sender * * Remove myself * * Store (merge?) the queue for the current serial, replace an existing one. * * Update the serial on the queue for each answer ? * * */ if(worker->worker_index == 1) { notify_ipv4_receiver_service(worker); return SUCCESS; } if(worker->worker_index == 2) { notify_ipv6_receiver_service(worker); return SUCCESS; } log_info("notify: notification service started"); struct notify_service_context ctx; notify_service_context_init(&ctx); /* */ log_debug("notify: notification service main loop reached"); while(service_should_run(worker) || !async_queue_empty(¬ify_handler_queue)) { ctx.service_loop_begin_us = timeus(); notify_service_context_manage_pending_notifications(&ctx); #if DEBUG if(dnscore_shuttingdown()) { log_info("notify: dnscore is shutting down. should_run: %i, queue_empty: %i (debug)", service_should_run(worker), async_queue_empty(¬ify_handler_queue)); } #endif s64 loop_start = timeus(); s64 loop_now = loop_start; s64 loop_count = 0; bool long_accumulation = FALSE; #if NOTIFY_CLEANUP_DUMP bool no_message_in_queue = FALSE; #endif bool is_shutting_down = !service_should_run(worker); // the loop will always enter at least once once do { /* current_queries tree cleanup */ async_message_s *async = async_message_next(¬ify_handler_queue); if(async == NULL) /*if no message is in the queue, proceed to next step */ { #if NOTIFY_CLEANUP_DUMP no_message_in_queue = TRUE; #endif break; } notify_message *notifymsg = (notify_message*)async->args; if(notifymsg == NULL) /*if no message is in the queue, proceed to next step (probably irrelevant) */ { async_message_release(async); #if NOTIFY_CLEANUP_DUMP no_message_in_queue = TRUE; #endif break; } // if dnscore is shutting down, release the message if(is_shutting_down || dnscore_shuttingdown()) { #if DEBUG log_info("notify: releasing messages (debug)"); #endif notify_message_free(notifymsg); async_message_release(async); is_shutting_down = TRUE; loop_start = loop_now; continue; } ++loop_count; notify_service_context_process_next_message(&ctx, notifymsg); async_message_release(async); } // for(;;) while((long_accumulation = ( ((loop_now = timeus()) - loop_start) >= ONE_SECOND_US))); /* * For all entries in the queue, send a notify to the ones that need to be repeated */ if(long_accumulation) { log_debug("notify: notification service accumulated queries for %fms (%lli queries)", ((1.0 * (loop_now - loop_start)) / 1000.0), loop_count); } #if NOTIFY_CLEANUP_DUMP if(no_message_in_queue) { log_debug1("notify: notification service has no more messages queued"); } #endif if(is_shutting_down) { log_debug("notify: notification service will shutdown"); break; } notify_service_context_send_notifications(&ctx); notify_service_context_wait(&ctx); } service_set_stopping(worker); notify_service_context_finalize(&ctx); log_info("notify: notification service stopped"); return 0; } /** * Sends a notify to all the slave for a given domain name: * * _ Get the zone * _ Create an empty list * _ If notify-auto, add all the IPs of all the NS at the apex of the zone to the list. * _ Add all the also-notify IPs to the list * _ Queue the list to the notify service * * @param origin */ void notify_slaves(const u8 *origin) { if(dnscore_shuttingdown()) { return; } if(!notify_service_initialised) { log_warn("notify: %{dnsname}: notification service has not been initialised", origin); return; } zdb *db = g_config->database; zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(db, origin); // RC++ if((zone == NULL) || zdb_zone_invalid(zone)) { if(zone != NULL) { zdb_zone_release(zone); } log_warn("notify: %{dnsname}: notify called on an invalid zone", origin); return; } // zdb_zone_set_status returns the status before the parameter is added if((zdb_zone_set_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY) & ZDB_ZONE_STATUS_WILL_NOTIFY) != 0) { // zone was already marked for notification log_debug("notify: %{dnsname}: already marked for notification", origin); zdb_zone_set_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY_AGAIN); zdb_zone_release(zone); // the release should only be done now as 'origin' may be passed from the zone return; } log_debug("notify: %{dnsname}: slaves notifications will be sent", origin); notify_message *notifymsg = notify_message_newinstance(origin, NOTIFY_MESSAGE_TYPE_DOMAIN); zdb_zone_release(zone); // RC-- async_message_s *async = async_message_alloc(); async->id = 0; async->args = notifymsg; async->handler = NULL; async->handler_args = NULL; async_message_call(¬ify_handler_queue, async); } static ya_result notify_slaves_alarm(void *args_, bool cancel) { u8 *origin = (u8*)args_; if(!dnscore_shuttingdown()) { if(notify_service_initialised && !cancel) { log_debug("notify: %{dnsname}: delayed retry", origin); notify_message *notifymsg = notify_message_newinstance(origin, NOTIFY_MESSAGE_TYPE_DOMAIN); async_message_s *async = async_message_alloc(); async->id = 0; async->args = notifymsg; async->handler = NULL; async->handler_args = NULL; async_message_call(¬ify_handler_queue, async); } else { zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(g_config->database, origin); // RC++ if(zone != NULL) { zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY); zdb_zone_release(zone); } else { log_err("notify: %{dnsname}: alarm-cancel: could not un-mark zone as queue for notification: zone not found ?", origin); } } } dnsname_zfree(origin); return SUCCESS; } bool notify_has_candidates_for_zone(zone_desc_s *zone_desc) { return (zone_ismaster(zone_desc) && zone_is_auto_notify(zone_desc)) || (zone_desc->notifies != NULL); } /** * * @param origin */ static bool notify_slaves_convert_domain_to_notify(notify_message *message) { if(message->payload.type == NOTIFY_MESSAGE_TYPE_NOTIFY) { return TRUE; } if(!notify_service_initialised) { return FALSE; } if(message->payload.type != NOTIFY_MESSAGE_TYPE_DOMAIN) { return FALSE; } /* * Build a list of IPs to contact * The master in the SOA must not be in this list * The current server must not be in this list * * Once the list is done, launch a thread that will periodically retry anybody in this list until the list is empty * * The list should be mutexed * The list should be in a by-origin collection * The list should be rebuild for each new notification (because the zone could have changed) */ zdb *db = g_config->database; zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(db, message->origin); // RC++ if((zone == NULL) || zdb_zone_invalid(zone) || !notify_service_initialised) { if(zone != NULL) { zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY); zdb_zone_release(zone); } if(notify_service_initialised) { log_debug("notify: %{dnsname}: zone temporarily unavailable", message->origin); } return FALSE; } zone_desc_s *zone_desc = zone_acquirebydnsname(message->origin); if(zone_desc == NULL) { zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY); zdb_zone_release(zone); log_err("notify: %{dnsname}: zone not configured", message->origin); return FALSE; } host_address list; #if DEBUG memset(&list, 0xff, sizeof(list)); #endif list.next = NULL; list.version = HOST_ADDRESS_NONE; bool lock_failed = FALSE; /* no need to set TSIG */ if(zone_ismaster(zone_desc) && zone_is_auto_notify(zone_desc)) { if(zdb_zone_trylock_wait(zone, ONE_SECOND_US, ZDB_ZONE_MUTEX_SIMPLEREADER)) //if(zdb_zone_trylock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER)) { // get the SOA zdb_packed_ttlrdata *soa = zdb_record_find(&zone->apex->resource_record_set, TYPE_SOA); // zone is locked // get the NS zdb_packed_ttlrdata *ns = zdb_record_find(&zone->apex->resource_record_set, TYPE_NS); // zone is locked // get the IPs for each NS but the one in the SOA u8 *soa_mname = ZDB_PACKEDRECORD_PTR_RDATAPTR(soa); u32 soa_mname_size = dnsname_len(soa_mname); for(zdb_packed_ttlrdata *nsp = ns; nsp != NULL; nsp = nsp->next) { u32 ns_dname_size = ZDB_PACKEDRECORD_PTR_RDATASIZE(nsp); u8 *ns_dname = ZDB_PACKEDRECORD_PTR_RDATAPTR(nsp); if(ns_dname_size == soa_mname_size) { if(memcmp(ns_dname, soa_mname, soa_mname_size) == 0) // scan-build false positive: soa_mname cannot be NULL { continue; } } // valid candidate : append IP addresses if(zdb_append_ip_records_with_port_ne(db, ns_dname, &list, htons(g_config->server_port_value)) <= 0) // zone is locked { // If no IP has been found, they will have to be resolved using the system ... later host_address_append_dname(&list, ns_dname, htons(g_config->server_port_value)); } } zdb_zone_release_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); } else { log_debug("notify: %{dnsname}: zone already locked", message->origin); lock_failed = TRUE; zdb_zone_release(zone); } } else { zdb_zone_release(zone); } // at this point I have the list of every IP I could find along with names I cannot resolve. // note that we don't need to care about the changes in the database : it would mean a new // notify and this one would be discarded if(!lock_failed && ISOK(zone_try_lock_wait(zone_desc, ONE_SECOND_US, ZONE_LOCK_READONLY))) { log_debug("notify: %{dnsname}: preparing notification", message->origin); const host_address *also_notifies = zone_desc->notifies; while(also_notifies != NULL) { host_address_append_host_address(&list, also_notifies); //copy made also_notifies = also_notifies->next; } // It's separate from the DB push the lot thread from the pool if(list.next != NULL) { message->payload.type = NOTIFY_MESSAGE_TYPE_NOTIFY; message->payload.notify.hosts_list = list.next; message->payload.notify.repeat_countdown = zone_desc->notify.retry_count; /* 10 times */ message->payload.notify.repeat_period = zone_desc->notify.retry_period; /* 1 minute */ message->payload.notify.repeat_period_increase = zone_desc->notify.retry_period_increase; /* 1 minute */ message->payload.notify.ztype = TYPE_SOA; message->payload.notify.zclass = CLASS_IN; } else { log_debug("notify: %{dnsname}: preparing notification: host list empty", message->origin); } zone_unlock(zone_desc, ZONE_LOCK_READONLY); } else { // could not lock the zone right away : delay a bit log_debug("notify: %{dnsname}: delaying notification", message->origin); zdb_zone *zone = zdb_acquire_zone_read_from_fqdn(db, message->origin); // RC++ if(zone != NULL) { if(!zdb_zone_invalid(zone)) { alarm_event_node *event = alarm_event_new( // slave notification time(NULL), ALARM_KEY_ZONE_NOTIFY_SLAVES, notify_slaves_alarm, dnsname_zdup(message->origin), ALARM_DUP_REMOVE_LATEST, "notify slaves"); alarm_set(zone->alarm_handle, event); } else { // if the message is ignored, will-notify status must be cleared zdb_zone_clear_status(zone, ZDB_ZONE_STATUS_WILL_NOTIFY); log_warn("notify: %{dnsname}: (temporarily) invalid zone, notify slaves request will remain ignored", message->origin); } zdb_zone_release(zone); } else { // could not get the zone anymore log_warn("notify: %{dnsname}: could not acquire the zone, notify slaves request will remain ignored", message->origin); } } zone_release(zone_desc); return message->payload.type == NOTIFY_MESSAGE_TYPE_NOTIFY; } /** * Stops all notification for zone with origin * * @param origin */ void notify_clear(const u8 *origin) { notify_message *notifymsg = notify_message_newinstance(origin, NOTIFY_MESSAGE_TYPE_CLEAR); async_message_s *async = async_message_alloc(); async->id = 0; async->args = notifymsg; async->handler = NULL; async->handler_args = NULL; async_message_call(¬ify_handler_queue, async); } ya_result notify_service_init() { int err = SUCCESS; if(!notify_service_initialised) { int workers = 2; if((send_socket4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { log_err("notify: no usable IPv4 socket bound"); return ERRNO_ERROR; } fd_setcloseonexec(send_socket4); if((send_socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { log_warn("notify: no usable IPv6 socket bound"); } else { fd_setcloseonexec(send_socket6); ++workers; } if(notify_thread_pool == NULL) { if((notify_thread_pool = thread_pool_init_ex(10, 4096, "notify-tp")) == NULL) { close_ex(send_socket4); send_socket4 = -1; close_ex(send_socket6); send_socket6 = -1; return THREAD_CREATION_ERROR; } } if(ISOK(err = service_init_ex(¬ify_handler, notify_service, "yadifad-notify", workers ))) { async_queue_init(¬ify_handler_queue, 10000000, 1, 1, "notify"); // note: it's implemented as a linked list notify_service_initialised = TRUE; } } return err; } /** * Starts the notify service thread */ ya_result notify_service_start() { int err = SERVICE_NOT_INITIALISED; if(notify_service_initialised) { if(service_stopped(¬ify_handler)) { err = service_start(¬ify_handler); } } return err; } void notify_wait_servicing() { if(notify_service_initialised) { if(!service_stopped(¬ify_handler)) { service_wait_servicing(¬ify_handler); } } } /** * Stops the notify service thread */ ya_result notify_service_stop() { int err = SERVICE_NOT_INITIALISED; if(notify_service_initialised) { if(!service_stopped(¬ify_handler)) { err = service_stop(¬ify_handler); service_wait(¬ify_handler); } } return err; } ya_result notify_service_finalize() { int err = SUCCESS; if(notify_service_initialised) { notify_service_initialised = FALSE; if(send_socket4 >= 0) { shutdown(send_socket4, SHUT_RDWR); } if(send_socket6 >= 0) { shutdown(send_socket6, SHUT_RDWR); } err = notify_service_stop(); service_finalize(¬ify_handler); /* once the tree has been scanned, destroy every node listed */ while(!async_queue_empty(¬ify_handler_queue)) { async_message_s *async = async_message_next(¬ify_handler_queue); if(async == NULL) /* if no message is in the queue, proceed to next step */ { break; } notify_message *msg = (notify_message*)async->args; /* if no message is in the queue, proceed to next step (probably irrelevant) */ notify_message_free(msg); async_message_release(async); } async_queue_finalize(¬ify_handler_queue); if(notify_thread_pool != NULL) { thread_pool_destroy(notify_thread_pool); notify_thread_pool = NULL; } if(send_socket4 >= 0) { close_ex(send_socket4); send_socket4 = -1; } if(send_socket6 >= 0) { close_ex(send_socket6); send_socket6 = -1; } } return err; } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/poll-util.c0000644000000000000000000000013114505005533020757 xustar000000000000000030 mtime=1695812443.469996897 29 atime=1695812445.78203001 30 ctime=1695812495.654744288 yadifa-2.6.5-11201/sbin/yadifad/poll-util.c0000664000374500037450000001144014505005533020722 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "server-config.h" #include #include #include "server.h" #if !DNSCORE_HAS_TCP_MANAGER #include "poll-util.h" #define MODULE_MSG_HANDLE g_server_logger /******************************************************************************************************************* * * TCP USAGE LIMITS * ******************************************************************************************************************/ /** * This code maintains the limit on the tcp sockets */ static nfds_t tcp_fds_count = 0; static nfds_t tcp_fds_idx = 0; static struct pollfd *tcp_fds = NULL; void poll_free() { tcp_fds_count = 0; tcp_fds_idx = 0; free(tcp_fds); tcp_fds = NULL; } void poll_alloc(nfds_t count) { if(tcp_fds != NULL) { if(count != tcp_fds_count) { poll_free(); } } struct pollfd* ret; size_t bytes = sizeof(struct pollfd) * count; MALLOC_OR_DIE(struct pollfd*, ret, bytes, POLLFDBF_TAG); ZEROMEMORY(ret, bytes); for(nfds_t i = 0; i < count; i++) { ret[i].events = POLLIN|POLLHUP/*|POLLNVAL*/; // could be set to 0, POLLNVAL is implicit // VS false positive (nonsense) } tcp_fds = ret; tcp_fds_count = count; } bool poll_add(int fd) { if(tcp_fds_idx < tcp_fds_count) { tcp_fds[tcp_fds_idx].fd = fd; tcp_fds[tcp_fds_idx].revents = 0; tcp_fds_idx++; return TRUE; } else { return FALSE; } } int poll_update() { int n = poll(tcp_fds, tcp_fds_idx, 0); if(n > 0) { // got hits #if DEBUG int changes = 0; #endif for(nfds_t i = 0; i < tcp_fds_idx; ++i) { #if DEBUG log_notice("poll_update: [%3i] %i (%4x %4x) (debug)", i, tcp_fds[i].fd, tcp_fds[i].events, tcp_fds[i].revents); #endif if(tcp_fds[i].revents != 0) { // lose it #if DEBUG log_debug("poll_update: releasing %i (%4x %4x)", tcp_fds[i].fd, tcp_fds[i].events, tcp_fds[i].revents); ++changes; #endif --tcp_fds_idx; if(tcp_fds_idx != i) { #if DEBUG log_debug("poll_update: replacing with %i (%4x %4x)", tcp_fds[tcp_fds_idx].fd, tcp_fds[tcp_fds_idx].events, tcp_fds[tcp_fds_idx].revents); #endif tcp_fds[i] = tcp_fds[tcp_fds_idx]; --i; } } } #if DEBUG if(n != changes) { log_debug("poll_update: warning : did expect %i changes, got %i", n, changes); } #endif return tcp_fds_idx; } else if(n < 0) { #if DEBUG log_debug("tcp: poll failed: %r", ERRNO_ERROR); #endif return tcp_fds_idx; } else { // timeout #if DEBUG log_debug("tcp: poll timed out"); #endif return tcp_fds_idx; } } #else // not used #endifyadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/process_class_ch.c0000644000000000000000000000013214505005533022354 xustar000000000000000030 mtime=1695812443.505997413 30 atime=1695812445.783030024 30 ctime=1695812495.656744316 yadifa-2.6.5-11201/sbin/yadifad/process_class_ch.c0000664000374500037450000002101514505005533022315 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #include "server-config.h" #include #include #include #include #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "process_class_ch.h" #include "confs.h" #define CHVRSION_TAG 0x4e4f495352564843 #define CHHOSTNM_TAG 0x4d4e54534f484843 #define CHIDSVR_TAG 0x52565344494843 extern logger_handle* g_server_logger; /* * The TXT CH record wire. Only the first 10 bytes will be taken. */ static u8 chaos_txt_stub[10] = { 0xc0, 0x0c, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00 }; static u8 *version_txt = NULL; static u8 *hostname_txt = NULL; static u8 *id_server_txt = NULL; void class_ch_set_hostname(const char *name) { if(name != NULL) { size_t name_len = MIN(strlen(name), 255); u8* tmp; MALLOC_OR_DIE(u8*, tmp, 13 + name_len, CHHOSTNM_TAG); memcpy(tmp, chaos_txt_stub, 10); // VS false positive (nonsense) SET_U16_AT(tmp[10], htons(name_len + 1)); tmp[12] = (u8)name_len; memcpy(&tmp[13], name, name_len); u8 *old = hostname_txt; hostname_txt = tmp; free(old); } else { u8 *old = hostname_txt; hostname_txt = NULL; free(old); } } void class_ch_set_version(const char *name) { if(name != NULL) { size_t name_len = MIN(strlen(name), 255); u8* tmp; MALLOC_OR_DIE(u8*, tmp, 13 + name_len, CHVRSION_TAG); memcpy(tmp, chaos_txt_stub, 10); // VS false positive (nonsense) SET_U16_AT(tmp[10], htons(name_len + 1)); tmp[12] = (u8)name_len; memcpy(&tmp[13], name, name_len); u8 *old = version_txt; version_txt = tmp; free(old); } else { u8 *old = version_txt; version_txt = NULL; free(old); } } void class_ch_set_id_server(const char *name) { if(name != NULL) { size_t name_len = MIN(strlen(name), 255); u8* tmp; MALLOC_OR_DIE(u8*, tmp, 13 + name_len, CHIDSVR_TAG); memcpy(tmp, chaos_txt_stub, 10); // VS false positive (nonsense) SET_U16_AT(tmp[10], htons(name_len + 1)); tmp[12] = (u8)name_len; memcpy(&tmp[13], name, name_len); u8 *old = id_server_txt; id_server_txt = tmp; free(old); } else { u8 *old = id_server_txt; id_server_txt = NULL; free(old); } } /* * The SOA CH record wire. */ static u8 chaos_soa[5*8 + 7] = { 0xc0, 0x0c, 0x00, 0x06, 0x00, 0x03, 0x00, 0x01, 0x51, 0x80, 0x00, 0x23, 0xc0, 0x0c, 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0xc0, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x00, 0x00, 0x1c, 0x20, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51, 0x80 }; /* * The NS CH record wire. */ static u8 chaos_ns[1*8 + 6] = { 0xc0, 0x0c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x0c }; static void chaos_make_message(message_data *mesg, const u8* record_wire, u32 record_wire_len) { u16 t = message_get_query_type(mesg); u16 an = 0; u16 au = 0; /* set the flags */ message_set_authoritative_answer(mesg); message_apply_mask(mesg, QR_BITS|AA_BITS|RD_BITS, 0); u8 *p = message_get_buffer_limit(mesg); if(t == TYPE_TXT || t == TYPE_ANY) { memcpy(p, record_wire, record_wire_len); p += record_wire_len; an++; } if(t == TYPE_SOA || t == TYPE_ANY) { memcpy(p, chaos_soa, sizeof(chaos_soa)); p += sizeof(chaos_soa); message_set_answer_count_ne(mesg, NETWORK_ONE_16); an++; } memcpy(p, chaos_ns, sizeof(chaos_ns)); p += sizeof(chaos_ns); if(t == TYPE_ANY || t == TYPE_NS) { an++; } else { au++; } message_set_answer_count(mesg, an); message_set_authority_count(mesg, au); if(message_is_edns0(mesg)) { u16 edns0_maxsize = g_config->edns0_max_size; u32 rcode_ext = message_get_rcode_ext(mesg); p[ 0] = 0; p[ 1] = 0; p[ 2] = 0x29; p[ 3] = edns0_maxsize>>8; p[ 4] = edns0_maxsize; p[ 5] = (message_get_status(mesg) >> 4); p[ 6] = rcode_ext >> 16; p[ 7] = rcode_ext >> 8; p[ 8] = rcode_ext; #if DNSCORE_HAS_NSID_SUPPORT if(!message_has_nsid(mesg)) { p[ 9] = 0; p[10] = 0; p += EDNS0_RECORD_SIZE; } else { p += EDNS0_RECORD_SIZE - 2; memcpy(p, edns0_rdatasize_nsid_option_wire, edns0_rdatasize_nsid_option_wire_size); p += edns0_rdatasize_nsid_option_wire_size; } #else p[ 9] = 0; p[10] = 0; p += EDNS0_RECORD_SIZE; #endif message_set_additional_count_ne(mesg, NETWORK_ONE_16); } message_set_size(mesg, p - message_get_buffer_const(mesg)); } void class_ch_process(message_data *mesg) { ya_result return_value; u8 qname[MAX_DOMAIN_LENGTH]; #if DNSCORE_HAS_ACL_SUPPORT if(ACL_REJECTED(acl_check_access_filter(mesg, &g_config->ac->allow_query))) { message_set_status(mesg, FP_ACCESS_REJECTED); message_transform_to_error(mesg); return; } #endif packet_unpack_reader_data purd; packet_reader_init_from_message(&purd, mesg); if(FAIL(return_value = packet_reader_read_fqdn(&purd, qname, sizeof(qname)))) { /* oops */ log_err("chaos: error reading query: %r", return_value); return; } /* version */ if((id_server_txt != NULL) && dnsname_equals_ignorecase((const u8*)"\002id\006server", qname)) { chaos_make_message(mesg, id_server_txt, 12 + ntohs(GET_U16_AT(id_server_txt[10]))); } else if((hostname_txt != NULL) && dnslabel_equals_ignorecase_left((const u8*)"\010hostname", qname)) { chaos_make_message(mesg, hostname_txt, 12 + ntohs(GET_U16_AT(hostname_txt[10]))); } else if((version_txt != NULL) && dnslabel_equals_ignorecase_left((const u8*)"\007version", qname)) { chaos_make_message(mesg, version_txt, 12 + ntohs(GET_U16_AT(version_txt[10]))); } else { /* REFUSED */ message_set_status(mesg, FP_NOZONE_FOUND); message_transform_to_error(mesg); } #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) /* NOTE: the TSIG information is in mesg */ { tsig_sign_answer(mesg); } #endif } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server-sm.c0000644000000000000000000000013214505005533020762 xustar000000000000000030 mtime=1695812443.540997914 30 atime=1695812445.785030053 30 ctime=1695812495.658744345 yadifa-2.6.5-11201/sbin/yadifad/server-sm.c0000664000374500037450000005425514505005533020737 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup server Server * @ingroup yadifad * @brief multithreaded reader-writer server * * Multiples threads for UDP on a different socket per interface. * One thread per interface for TCP, dispatching accepts to worker threads. (for now) * * One weakness: every single test of a similar mechanism shows that this is MUCH slower than the simple "mt" model. * * This is tested in hope that although the maximum throughput will be reduced, no packets will be lost * in case of long DB locks. * * As a side note, it is trivial that a different model of database would also solve the issue. * The most obvious one being using two zones images, alternating the visible and edited one. * This solution is of course unacceptable for a big zone as it greatly increases the resident memory usage. * * * @{ */ // keep this order --> #include "server-config.h" #ifndef WIN32 #ifndef __USE_GNU #define __USE_GNU 1 #endif #define _GNU_SOURCE 1 #include #endif #if defined __FreeBSD__ #include #include typedef cpuset_t cpu_set_t; #endif // <-- keep this order #include "server_context.h" #include #include #include #include #include #include #include #include #include #include #include #include #define ZDB_JOURNAL_CODE 1 #include #if ZDB_HAS_LOCK_DEBUG_SUPPORT #include "dnsdb/zdb-zone-lock-monitor.h" #endif #include "server.h" #include "log_query.h" #include "rrl.h" #include "process_class_ch.h" #include "notify.h" #include "log_statistics.h" #include "signals.h" #include "dynupdate_query_service.h" #if HAS_EVENT_DYNAMIC_MODULE #include "dynamic-module-handler.h" #endif #define TRY_EPOLL 0 #define TRY_POLL 0 #if TRY_EPOLL #include #endif #if TRY_POLL #include #endif #define SVRPLBIN_TAG 0x4e49424c50525653 #define SVRPLBOT_TAG 0x544f424c50525653 #define SSMPOOLB_TAG 0x424c4f4f504d5353 // allow an external definition of the backlog queue size and L1 parameters #define NETWORK_THREAD_CONTEXT_FAST_MESSAGE_COUNT 3 // do NOT change this value #ifndef SERVER_SM_L1_DATA_LINE_ALIGNED_SIZE #define SERVER_SM_L1_DATA_LINE_ALIGNED_SIZE 128 #define SERVER_SM_L1_DATA_LINE_ALIGNED_SHIFT 7 #define SERVER_SM_PACKETS_AT_ONCE 1 #elif ((1 << SERVER_SM_L1_DATA_LINE_ALIGNED_SHIFT) != SERVER_SM_L1_DATA_LINE_ALIGNED_SIZE) #error "2^" TOSTRING(SERVER_SM_L1_DATA_LINE_ALIGNED_SHIFT) " != " TOSTRING(SERVER_SM_L1_DATA_LINE_ALIGNED_SIZE) " : please fix" #endif // DEBUG build: log debug level 5 of incoming wire #define DUMP_UDP_SM_RECEIVED_WIRE 0 // DEBUG build: log debug 5 of outgoing wire #define DUMP_UDP_SM_OUTPUT_WIRE 0 extern logger_handle* g_statistics_logger; #define RWNTCTXS_TAG 0x53585443544e5752 #define RWNTCTX_TAG 0x585443544e5752 // note: MODULE_MSG_HANDLE is defined in server_error.h struct network_thread_context_s { network_thread_context_base_t base; // should be aligned with 64 mutex_t mtx; cond_t cond; // should be aligned with 64 #ifndef WIN32 server_statistics_t statistics __attribute__ ((aligned (SERVER_SM_L1_DATA_LINE_ALIGNED_SIZE))); #else server_statistics_t statistics; #endif }; typedef struct network_thread_context_s network_thread_context_s; static network_thread_context_s* network_thread_context_new_instance(size_t backlog_queue_slots, struct service_worker_s *worker, u16 sockfd_idx) { network_thread_context_s *ctx; (void)backlog_queue_slots; size_t network_thread_context_real_size = sizeof(network_thread_context_s); ctx = (network_thread_context_s*)malloc(network_thread_context_real_size); if(ctx == NULL) { return NULL; } memset(ctx, 0, sizeof(network_thread_context_s)); ctx->base.worker = worker; ctx->base.idx = sockfd_idx; ctx->base.sockfd = g_server_context.udp_socket[sockfd_idx]; //ctx->base.must_stop = FALSE; // implicit with the memset ctx->base.statisticsp = &ctx->statistics; mutex_init(&ctx->mtx); cond_init(&ctx->cond); return ctx; } static void network_thread_context_delete(network_thread_context_s *ctx) { if(ctx != NULL) { cond_finalize(&ctx->cond); mutex_destroy(&ctx->mtx); free(ctx); } } struct network_thread_context_array { network_thread_context_s **contextes; size_t listen_count; size_t reader_by_fd; size_t backlog_queue_slots; }; typedef struct network_thread_context_array network_thread_context_array; static void network_thread_context_array_finalize(network_thread_context_array *ctxa) { for(size_t listen_idx = 0, sockfd_idx = 0; listen_idx < ctxa->listen_count; ++listen_idx) { for(u32 r = 0; r < ctxa->reader_by_fd; r++) { network_thread_context_s *ctx = ctxa->contextes[sockfd_idx]; if(ctx != NULL) { log_debug("network_thread_context_array_finalize: %u/%u sockfd %i and thread %p/worker %u", (u32)listen_idx, (u32)ctxa->listen_count, sockfd_idx, ctx->base.worker->tid, ctx->base.worker->worker_index); network_thread_context_delete(ctx); } else { log_debug("network_thread_context_array_finalize: %u/%u sockfd %i had no context", (u32)listen_idx, (u32)ctxa->listen_count, sockfd_idx); } ++sockfd_idx; } } free(ctxa->contextes); } static ya_result network_thread_context_array_init(network_thread_context_array *ctxa, size_t listen_count, size_t reader_by_fd, size_t backlog_queue_slots, struct service_worker_s *worker) { network_thread_context_s **contextes; MALLOC_OBJECT_ARRAY(contextes, network_thread_context_s*, listen_count * reader_by_fd, RWNTCTXS_TAG); // the memory allocation macro without _OR_DIE suffix will not abort on insufficient memory if(contextes == NULL) { return MAKE_ERRNO_ERROR(ENOMEM); } memset(contextes, 0, listen_count * reader_by_fd * sizeof(network_thread_context_s*)); // there is no leak, the pointer is right there: ctxa->contextes = contextes; ctxa->listen_count = listen_count; ctxa->reader_by_fd = reader_by_fd; ctxa->backlog_queue_slots = backlog_queue_slots; for(size_t listen_idx = 0, sockfd_idx = 0; listen_idx < listen_count; ++listen_idx) { for(u32 r = 0; r < reader_by_fd; r++) { network_thread_context_s *ctx; ctx = network_thread_context_new_instance(backlog_queue_slots, worker, sockfd_idx); if(ctx == NULL) { network_thread_context_array_finalize(ctxa); return MAKE_ERRNO_ERROR(ENOMEM); } log_debug("network_thread_context_array_init: %u/%u idx=%i and thread %p/worker %u", (u32)listen_idx, (u32)listen_count, sockfd_idx, worker->tid, worker->worker_index); contextes[sockfd_idx] = ctx; /* * Update the select read set for the current interface (udp + tcp) */ ++sockfd_idx; } } return SUCCESS; } static void server_sm_set_cpu_affinity(int index) { #if HAS_PTHREAD_SETAFFINITY_NP int cpu_count = sys_get_cpu_count(); if(cpu_count < 0) { cpu_count = 1; } int affinity_with = g_config->thread_affinity_base + (index * g_config->thread_affinity_multiplier); affinity_with += affinity_with / cpu_count; affinity_with %= cpu_count; log_info("server-sm: worker setting affinity with virtual cpu %i", affinity_with); #if __NetBSD__ cpuset_t* mycpu = cpuset_create(); if(mycpu != NULL) { cpuset_zero(mycpu); cpuset_set((cpuid_t)affinity_with, mycpu); if(pthread_setaffinity_np(thread_self(), cpuset_size(mycpu), mycpu) != 0) { #pragma message("TODO: report errors") // NetBSD } cpuset_destroy(mycpu); } else { } #elif defined(WIN32) #pragma message("TODO: implement") // WIN32 #else cpu_set_t mycpu; CPU_ZERO(&mycpu); CPU_SET(affinity_with, &mycpu); pthread_setaffinity_np(thread_self(), sizeof(cpu_set_t), &mycpu); #endif #else (void)index; #endif } static void* server_sm_udp_worker_thread(void *parms) { struct network_thread_context_s *ctx = (struct network_thread_context_s*)parms; u64 *local_statistics_udp_input_count = (u64*)&ctx->statistics.udp_input_count; ctx->base.idr = thread_self(); int fd = ctx->base.sockfd; log_debug("server_sm_udp_worker_thread(%i, %i): started", ctx->base.idx, fd); socketaddress sa; socklen_t sa_len = sizeof(sa); getsockname(fd, &sa.sa, &sa_len); log_info("waiting for udp messages for %{sockaddr}", &sa); server_sm_set_cpu_affinity(ctx->base.idx); u8 *pool_buffer; size_t pool_buffer_size = 65536; MALLOC_OBJECT_ARRAY_OR_DIE(pool_buffer, u8, pool_buffer_size, SSMPOOLB_TAG); message_data *mesg; mesg = message_new_instance(); message_set_pool_buffer(mesg, pool_buffer, pool_buffer_size); message_reset_control(mesg); tcp_set_recvtimeout(fd, 1, 0); for(;;) { #if DEBUG log_debug("server_sm_udp_worker_thread(%i, %i): recvmsg", ctx->base.idx, fd); #endif message_recv_udp_reset(mesg); message_reset_control_size(mesg); ya_result ret = message_recv_udp(mesg, fd); #if DEBUG log_debug("server_sm_udp_worker_thread(%i, %i): recvmsg: %i", ctx->base.idx, fd, ret); #endif if(FAIL(ret)) { #if DEBUG int err = ERRNO_ERROR; log_debug("message_recv_udp %i returned %i : %r", fd, ret, err); #endif if(service_should_reconfigure_or_stop(ctx->base.worker)) { log_debug("server_sm_udp_receiver_thread(%i, %i): will stop (reconfigure or stop)", ctx->base.idx, fd); break; } continue; } #if DEBUG log_debug("server_sm_udp_worker_thread: received %u packets (DEBUG)", ret); #endif local_statistics_udp_input_count++; #if DEBUG mesg->recv_us = timeus(); log_debug("server_sm_udp_worker_thread: recvfrom: got %d bytes from %{sockaddr}", message_get_size(mesg), message_get_sender_sa(mesg)); #if DUMP_UDP_SM_RECEIVED_WIRE log_memdump_ex(g_server_logger, MSG_DEBUG5, mesg->buffer, n, 16, OSPRINT_DUMP_HEXTEXT); #endif #endif s32 dest_port = sockaddr_inet_port(message_get_sender_sa(mesg)); if(dest_port > 0) { ya_result ret = server_process_message_udp((network_thread_context_base_t*)ctx, mesg); if(ISOK(ret)) { // that message will be replied to ret = message_send_udp(mesg, fd); if(ISOK(ret)) { ctx->statistics.udp_output_size_total += ret; } else { log_err("server-sm: could not reply though UDP (socket %i): %r", fd, ret); } } else { if(ret == SUCCESS_DROPPED) // should rename to SUCCESS_IGNORE { // ignore #if DEBUG if(message_get_size(mesg) > 0) { log_debug("server_sm_udp_worker_thread: good-dropped %d bytes from %{sockaddr}", message_get_size(mesg), message_get_sender_sa(mesg)); message_log(MODULE_MSG_HANDLE, LOG_INFO, mesg); } #endif } else if(ret == STOPPED_BY_APPLICATION_SHUTDOWN) { #if DEBUG log_debug("server_sm_udp_worker_thread: STOPPED_BY_APPLICATION_SHUTDOWN ?"); #endif if(service_should_reconfigure_or_stop(ctx->base.worker)) { #if DEBUG log_debug("server_sm_udp_worker_thread: STOPPED_BY_APPLICATION_SHUTDOWN !"); #endif /* * GOTO! * * Break out of two loops */ goto server_sm_udp_worker_thread_end; } } else { // something happened #if DEBUG log_debug("server_sm_udp_worker_thread: bad-dropped %d bytes from %{sockaddr}", message_get_size(mesg), message_get_sender_sa(mesg)); message_log(MODULE_MSG_HANDLE, LOG_INFO, mesg); #endif } } } else if(dest_port == 0) { log_err("server-sm: error replying to message %04hx %{dnsname} %{dnstype} from %{sockaddr}: invalid destination port", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), mesg->_msghdr.msg_name); } else // if(dest_port < 0) { log_err("server-sm: error replying to message %04hx %{dnsname} %{dnstype} invalid IP family", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg)); } } // for "ever" loop server_sm_udp_worker_thread_end: #if DEBUG log_debug("server_sm_udp_worker_thread(%i, %i): stopping", ctx->base.idx, fd); #endif #if TRY_EPOLL close_ex(epoll_fd); #endif free(pool_buffer); message_set_pool_buffer(mesg, NULL, pool_buffer_size); message_free(mesg); #if DEBUG log_debug("server_sm_udp_worker_thread(%i, %i): stopped", ctx->base.idx, fd); #endif return NULL; } static server_statistics_t server_statistics_sum; ya_result server_sm_query_loop(struct service_worker_s *worker) { ya_result ret; if(g_config->total_interfaces == 0 ) { return INVALID_STATE_ERROR; } if(g_server_context.tcp_socket_count <= 0) { return INVALID_STATE_ERROR; } if(g_server_context.listen_count <= 0) { return INVALID_STATE_ERROR; } log_query_set_mode(g_config->queries_log_type); bool log_statistics_enabled = (g_statistics_logger != NULL) && (g_config->server_flags & SERVER_FL_STATISTICS) != 0; log_debug("server-sm: statistics are %s", (log_statistics_enabled)?"enabled":"disabled"); if(log_statistics_enabled) { log_statistics_legend(); } /* There's a timeout each second, for checking the SA_SHUTDOWN flag */ /** * For each interface ... */ s32 reader_by_fd = g_server_context.udp_socket_count / g_server_context.udp_unit_per_interface; s32 cpu_count = sys_get_cpu_count(); if(reader_by_fd > cpu_count) { log_warn("server-sm: using too many threads per address is counter-productive on highly loaded systems (%d > %d)", reader_by_fd, cpu_count); } u64 server_run_loop_rate_tick = 0; u32 previous_tick = 0; log_info("server-sm: UDP working threads to be spawned: %i", (int)g_server_context.udp_interface_count * (int)g_server_context.udp_unit_per_interface); struct thread_pool_s *server_udp_thread_pool = thread_pool_init_ex(g_server_context.udp_interface_count * g_server_context.udp_unit_per_interface, 1, "svrudpmm"); if(server_udp_thread_pool == NULL) { log_err("server-sm: unable to allocate working threads pool"); return THREAD_CREATION_ERROR; } size_t backlog_queue_slots = g_server_context.worker_backlog_queue_size; network_thread_context_array ctxa; if(FAIL(ret = network_thread_context_array_init(&ctxa, g_server_context.udp_interface_count, g_server_context.udp_unit_per_interface, backlog_queue_slots, worker))) { log_err("server-sm: unable to allocate context: %r", ret); return ret; } thread_pool_task_counter running_threads_counter; thread_pool_counter_init(&running_threads_counter, 0); server_statistics_t **statistics_array = NULL; u32 statistics_array_size = g_server_context.udp_interface_count * g_server_context.udp_unit_per_interface; MALLOC_OBJECT_ARRAY_OR_DIE(statistics_array, server_statistics_t*, statistics_array_size, GENERIC_TAG); u32 initialised_context_indexes = 0; for(u32 udp_interface_index = 0; udp_interface_index < g_server_context.udp_interface_count; ++udp_interface_index) { for(u32 unit_index = 0; unit_index < g_server_context.udp_unit_per_interface; unit_index++) { network_thread_context_s *ctx = ctxa.contextes[initialised_context_indexes]; statistics_array[initialised_context_indexes] = &ctxa.contextes[initialised_context_indexes]->statistics; yassert(ctx != NULL); log_info("server-sm: thread #%i of UDP interface: %{sockaddr} using socket %i", unit_index, g_server_context.udp_interface[udp_interface_index]->ai_addr, ctx->base.sockfd); log_debug("server_sm_query_loop: pooling #%d=%d fd=%d", initialised_context_indexes, ctx->base.idx, ctx->base.sockfd); if(FAIL(ret = thread_pool_enqueue_call(server_udp_thread_pool, server_sm_udp_worker_thread, ctx, &running_threads_counter, "server-sm-udp"))) { log_err("server-sm: unable to schedule task : %r", ret); service_stop(worker->service); break; } /* * Update the select read set for the current interface (udp + tcp) */ ++initialised_context_indexes; } if(FAIL(ret)) { break; } } if(ISOK(ret)) { log_info("server-sm: UDP threads up"); server_tcp_accept_loop(worker, statistics_array, statistics_array_size); } else { log_err("server-sm: initialisation failed"); } free(statistics_array); #if DEBUG { s32 threads_still_running_count = thread_pool_counter_get_value(&running_threads_counter); log_info("threads_still_running_count = %i", threads_still_running_count); } #endif log_info("server-sm: stopping the threads"); bool can_stop; do { for(u32 udp_interface_index = 0, context_index = 0; udp_interface_index < g_server_context.udp_interface_count; ++udp_interface_index) { for(u32 unit_index = 0; unit_index < g_server_context.udp_unit_per_interface; unit_index++) { if(context_index >= initialised_context_indexes) // only happens in case of a critical error { break; } network_thread_context_s *ctx = ctxa.contextes[context_index]; if(ctx != NULL) { ctx->base.must_stop = TRUE; } ++context_index; } } s32 threads_still_running_count = thread_pool_counter_get_value(&running_threads_counter); log_debug("server-sm: threads_still_running_count = %i", threads_still_running_count); can_stop = (threads_still_running_count == 0); } while(!can_stop); thread_pool_counter_destroy(&running_threads_counter); /* * Close all zone alarm handles * Close database alarm handle */ log_info("server-sm: cleaning up: stopping thread pool"); thread_pool_destroy(server_udp_thread_pool); server_udp_thread_pool = NULL; log_info("server-sm: cleaning up: releasing context"); network_thread_context_array_finalize(&ctxa); log_info("server-sm: stopped", getpid_ex()); return SUCCESS; } ya_result server_sm_context_init(int workers_per_interface) { g_server_context.thread_per_udp_worker_count = 1; // set in stone g_server_context.thread_per_tcp_worker_count = 1; // set in stone g_server_context.udp_unit_per_interface = MAX(workers_per_interface , 1); g_server_context.tcp_unit_per_interface = 1; #ifdef SO_REUSEPORT g_server_context.reuse = 1; #else if(g_server_context.udp_unit_per_interface > 1) { log_warn("system does not support SO_REUSEPORT, downgrading UDP unit per interface from %i to 1", g_server_context.udp_unit_per_interface); g_server_context.udp_unit_per_interface = 1; } g_server_context.reuse = 0; #endif g_server_context.ready = 1; return SUCCESS; } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server.c0000644000000000000000000000013214505005533020345 xustar000000000000000030 mtime=1695812443.525997699 30 atime=1695812445.784030039 30 ctime=1695812495.660744374 yadifa-2.6.5-11201/sbin/yadifad/server.c0000664000374500037450000022464114505005533020320 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup server Server * @ingroup yadifad * @brief Server initialisation and launch * * Starts server * * @{ */ #define SERVER_C_ /** @note: here we define the variable that is holding the default logger handle for the current source file * Such a handle should NEVER been set in an include file. */ #include "server-config.h" #include #include #include #include #include #include #include #include #include #include #if DNSCORE_HAS_TCP_MANAGER #include #endif logger_handle *g_server_logger = LOGGER_HANDLE_SINK; #define MODULE_MSG_HANDLE g_server_logger #include "signals.h" #include "database-service.h" #include "log_query.h" #if !DNSCORE_HAS_TCP_MANAGER #include "poll-util.h" #endif #include "server-sm.h" #include "server-rw.h" #if __linux__ && HAVE_SENDMMSG #include "server-mm.h" #endif #include "notify.h" #include "server_context.h" #include "axfr.h" #include "ixfr.h" #include "process_class_ch.h" #if HAS_DYNUPDATE_SUPPORT #include "dynupdate_query_service.h" #endif #if DNSCORE_HAS_CTRL #include "ctrl.h" #include "ctrl_query.h" #endif #if HAS_RRL_SUPPORT #include "rrl.h" #endif #if HAS_EVENT_DYNAMIC_MODULE #include "dynamic-module-handler.h" #endif /** * 20210922 edf -- this appears to be more efficient. It may be enabled for production builds after thorough testing. */ #define SERVER_TCP_USE_LAZY_MAPPING 0 #define NETWORK_AUTO_RECONFIGURE_COUNTDOWN_DEFAULT 10 #define SVRPOOLB_TAG 0x424c4f4f50525653 // DEBUG build: log debug 5 of incoming wire #define DUMP_TCP_RECEIVED_WIRE 0 // DEBUG build: log debug 5 of outgoing wire #define DUMP_TCP_OUTPUT_WIRE 0 struct server_process_tcp_thread_parm { #if DNSCORE_HAS_TCP_MANAGER tcp_manager_socket_context_t *sctx; #else //zdb *database; socketaddress sa; socklen_t addr_len; int sockfd; #endif int svr_sockfd; }; typedef struct server_process_tcp_thread_parm server_process_tcp_thread_parm; #if SERVER_TCP_USE_LAZY_MAPPING struct tcp_thread_memory_s { //server_process_tcp_thread_parm parm; message_data_with_buffer message_data __attribute__((aligned(64))); u8 pool_buffer[SERVER_POOL_BUFFER_SIZE] __attribute__((aligned(4096))); u8 padding_buffer[0x8000] __attribute__((aligned(4096))); }; typedef struct tcp_thread_memory_s tcp_thread_memory_t; #endif static struct thread_pool_s *server_tcp_thread_pool = NULL; struct thread_pool_s *server_disk_thread_pool = NULL; #if SERVER_TCP_USE_LAZY_MAPPING static tcp_thread_memory_t *tcp_thread_memory = NULL; static u32 thread_memory_size = 0; #endif #include "server.h" #include "log_statistics.h" #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER static debug_bench_s debug_accept; static debug_bench_s debug_accept_reject; static debug_bench_s debug_server_process_tcp_task; static debug_bench_s debug_tcp_reply; static debug_bench_s debug_tcp_read_size; static debug_bench_s debug_tcp_read_message; #endif server_statistics_t server_statistics; static bool server_statistics_initialised = FALSE; volatile int program_mode = SA_CONT; /** @note must be volatile */ #if !__linux__ || !HAVE_SENDMMSG static ya_result server_notsupported_query_loop() { log_err("Model is not supported on this architecture."); return FEATURE_NOT_SUPPORTED; } static ya_result server_notsupported_context_init(int workers_per_interface) { (void)workers_per_interface; log_err("Model is not supported on this architecture."); return FEATURE_NOT_SUPPORTED; } #endif static struct server_desc_s server_type[] = { { server_sm_context_init, server_sm_query_loop, "single message per syscall resolve" }, { server_rw_context_init, server_rw_query_loop, "multithreaded deferred resolve" }, #if __linux__ && HAVE_SENDMMSG { server_mm_context_init, server_mm_query_loop, "multiple message per syscall resolve" }, #else { server_notsupported_context_init, server_notsupported_query_loop, "multiple message per syscall resolve (not supported)" }, #endif { NULL, NULL, "none"} }; #if DNSCORE_HAS_TCP_MANAGER /** * Wrapper function to send the message and log an eventual error * * @param mesg * @param sockfd */ static inline ya_result server_tcp_reply(message_data *mesg, tcp_manager_socket_context_t *sctx) { ssize_t ret = ERROR; #if DEBUG log_debug("tcp: %{sockaddr}: replying %i bytes", message_get_sender_sa(mesg), message_get_size(mesg)); #endif tcp_manager_write_update(sctx, 0); int fd = tcp_manager_socket(sctx); if(fd >= 0) { ret = message_send_tcp(mesg, fd); if(ISOK(ret)) { tcp_manager_write_update(sctx, ret); #if DEBUG log_debug("tcp: %{sockaddr}: replied %i bytes", message_get_sender_sa(mesg), message_get_size(mesg)); #endif } else { log_err("tcp: %{sockaddr}: could not reply (%i bytes): %r", message_get_sender_sa(mesg), message_get_size(mesg), (ya_result)ret); } } else { #if DEBUG log_debug("tcp: %{sockaddr}: could not reply (%i bytes): connection closed", message_get_sender_sa(mesg), message_get_size(mesg)); #endif } return (ya_result)ret; } /** * Wrapper function to make an error message, then send it and log an eventual error * * @param mesg * @param sockfd */ static inline ya_result server_tcp_reply_error(message_data *mesg, tcp_manager_socket_context_t *sctx, u16 error_code) { ssize_t ret = ERROR; log_debug("tcp: %{sockaddr}: replying %i bytes (error code %i)", message_get_sender_sa(mesg), message_get_size(mesg), error_code); if(ISOK(ret = message_make_error_and_reply_tcp_with_default_minimum_throughput(mesg, error_code, tcp_manager_socket(sctx)))) { tcp_manager_write_update(sctx, ret); #if DEBUG log_debug("tcp: %{sockaddr}: replied %i bytes (error code %i)", message_get_sender_sa(mesg), message_get_size(mesg), error_code); #endif } else { log_err("tcp: %{sockaddr}: could not reply error code %u (%i bytes): %r", message_get_sender_sa(mesg), message_get_size(mesg), error_code, (ya_result)ret); } return (ya_result)ret; } #else /** * Wrapper function to send the message and log an eventual error * * @param mesg * @param sockfd */ static error_state_t server_tcp_reply_error_state = ERROR_STATE_INITIALIZER; static inline ya_result server_tcp_reply(message_data *mesg, int sockfd) { #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER u64 bench = debug_bench_start(&debug_tcp_reply); #endif ssize_t ret; if(ISOK(ret = message_update_length_send_tcp_with_default_minimum_throughput(mesg, sockfd))) { error_state_clear_locked(&server_tcp_reply_error_state, NULL, 0, NULL); } else { if(error_state_log_locked(&server_tcp_reply_error_state, ret)) { log_err("tcp: could not answer: %r", (ya_result)ret); } } #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER debug_bench_stop(&debug_tcp_reply, bench); #endif return (ya_result)ret; } /** * Wrapper function to make an error message, then send it and log an eventual error * * @param mesg * @param sockfd */ static inline ya_result server_tcp_reply_error(message_data *mesg, int sockfd, u16 error_code) { ssize_t ret; if(ISOK(ret = message_make_error_and_reply_tcp_with_default_minimum_throughput(mesg, error_code, sockfd))) { error_state_clear_locked(&server_tcp_reply_error_state, NULL, 0, NULL); } else { if(error_state_log_locked(&server_tcp_reply_error_state, ret)) { log_err("tcp: could not answer: %r", (ya_result)ret); } } return (ya_result)ret; } #endif /******************************************************************************************************************* * * TCP protocol * ******************************************************************************************************************/ #if !DNSCORE_HAS_TCP_MANAGER static ptr_set ip_to_tcp_client_set = {NULL, sockaddr_storage_compare_ip}; static mutex_t ip_to_tcp_client_set_mtx = MUTEX_INITIALIZER; static ptr_set ip_to_tcp_query_set = {NULL, sockaddr_storage_compare_ip}; static mutex_t ip_to_tcp_query_set_mtx = MUTEX_INITIALIZER; void server_tcp_client_register(const struct sockaddr_storage* sa, s64 connections_max) { mutex_lock(&ip_to_tcp_client_set_mtx); ptr_node *node = ptr_set_insert(&ip_to_tcp_client_set, (struct sockaddr_storage*)sa); if(node->key == sa) { struct sockaddr_storage *ssp; ZALLOC_OBJECT_OR_DIE(ssp, struct sockaddr_storage, GENERIC_TAG); sockaddr_storage_copy(ssp, sa); node->key = ssp; } node->value_s64 = connections_max; mutex_unlock(&ip_to_tcp_client_set_mtx); } s64 server_tcp_client_connections_max(const struct sockaddr_storage* sa, s64 default_value) { s64 ret; mutex_lock(&ip_to_tcp_client_set_mtx); ptr_node *node = ptr_set_find(&ip_to_tcp_client_set, sa); if(node != NULL) { ret = node->value_s64; } else { ret = default_value; } mutex_unlock(&ip_to_tcp_client_set_mtx); return ret; } #if 0 static u32 server_tcp_queries_for_ip_count(struct sockaddr* sa) { u32 ret = 0; mutex_lock(&ip_to_tcp_query_set_mtx); ptr_node *node = ptr_set_find(&ip_to_tcp_query_set, sa); if(node != NULL) { ret = (u32)node->value_u64; } mutex_unlock(&ip_to_tcp_query_set_mtx); return ret; } static void server_tcp_queries_for_ip_increment(struct sockaddr_storage* sa) { mutex_lock(&ip_to_tcp_query_set_mtx); ptr_node *node = ptr_set_insert(&ip_to_tcp_query_set, sa); if(node->value_s64 > 0) { ++node->value_s64; } else { struct sockaddr_storage *ssp; ZALLOC_OBJECT_OR_DIE(ssp, struct sockaddr_storage, GENERIC_TAG); node->key = ssp; node->value_s64 = 0; } mutex_unlock(&ip_to_tcp_query_set_mtx); } #endif static bool server_tcp_queries_for_ip_increment_if_less(struct sockaddr_storage* sa, s64 max_value) { bool ret = TRUE; mutex_lock(&ip_to_tcp_query_set_mtx); ptr_node *node = ptr_set_insert(&ip_to_tcp_query_set, sa); if(node->value_s64 > 0) { if(node->value_s64 < max_value) { ++node->value_s64; } else { ret = FALSE; } } else { struct sockaddr_storage *ssp; ZALLOC_OBJECT_OR_DIE(ssp, struct sockaddr_storage, GENERIC_TAG); sockaddr_storage_copy(ssp, sa); node->key = ssp; node->value_s64 = 1; } mutex_unlock(&ip_to_tcp_query_set_mtx); return ret; } static void server_tcp_queries_for_ip_decrement(struct sockaddr_storage* sa) { mutex_lock(&ip_to_tcp_query_set_mtx); ptr_node *node = ptr_set_find(&ip_to_tcp_query_set, sa); if(node->value_s64 > 1) { --node->value_s64; } else { struct sockaddr_storage *ssp = node->key; ptr_set_delete(&ip_to_tcp_query_set, ssp); ZFREE_OBJECT(ssp); } mutex_unlock(&ip_to_tcp_query_set_mtx); } #endif /** \brief Does the tcp processing * * When pselect has an TCP request, this function reads the tcp packet, * processes dns packet and send reply * * @param[in,out] mesg * * @retval OK * @return status of message is written in message_get_status(mesg) */ #if DNSCORE_HAS_TCP_MANAGER static int server_process_tcp_task(message_data *mesg, tcp_manager_socket_context_t *sctx, u16 svr_sockfd) #else static int server_process_tcp_task(message_data *mesg, int sockfd, u16 svr_sockfd) #endif { ya_result ret = SUCCESS; u16 dns_query_len; ssize_t received = 0; ssize_t next_message_size; #if DEBUG int log_only_sockfd; #if DNSCORE_HAS_TCP_MANAGER log_only_sockfd = tcp_manager_socket(sctx); #else log_only_sockfd = sockfd; #endif #endif #if DEBUG log_debug("tcp: processing %{sockaddr} (socket %i )", message_get_sender_sa(mesg), log_only_sockfd); #endif int loop_count = 0; #if DNSCORE_HAS_TCP_MANAGER tcp_manager_set_recvtimeout(sctx, 3, 0); tcp_manager_set_sendtimeout(sctx, 3, 0); /* tcp_manager_set_nodelay(sctx, FALSE); tcp_manager_set_cork(sctx, TRUE); */ #else tcp_set_recvtimeout(sockfd, 1, 0); tcp_set_sendtimeout(sockfd, 1, 0); tcp_set_nodelay(sockfd, FALSE); tcp_set_cork(sockfd, TRUE); #endif /** @note do a full read, not one that can be interrupted or deliver only a part of what we need (readfully) */ s64 time_start; for(;;) { time_start = timeus(); #if DEBUG log_debug("tcp: waiting for length prefix, loop %i", loop_count); #endif #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER u64 bench = debug_bench_start(&debug_tcp_read_size); #endif #if DNSCORE_HAS_TCP_MANAGER // tcp_manager_cancellable(sctx); // tells that it's about to wait for something new next_message_size = tcp_manager_read_fully(sctx, (u8*)&dns_query_len, 2); #else next_message_size = readfully_limited_ex(sockfd, &dns_query_len, 2, 3000000, g_config->tcp_query_min_rate_us); #endif #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER debug_bench_stop(&debug_tcp_read_size, bench); #endif if(next_message_size != 2) { s64 time_stop = timeus(); s64 d = MAX(time_stop - time_start, 0); double s = d / ONE_SECOND_US_F; if(next_message_size < 0) { ret = (ya_result)next_message_size; if(ret != MAKE_ERRNO_ERROR(EBADF)) { log_debug("tcp: %{sockaddr}: loop %i: length prefix not received after %5.3fs: %r", message_get_sender_sa(mesg), loop_count, s, ret); } else { log_info("tcp: %{sockaddr}: loop %i: length prefix not received after %5.3fs: connection closed", message_get_sender_sa(mesg), loop_count, s); } } else { ret = MAKE_ERRNO_ERROR(ETIMEDOUT); #if DEBUG log_debug("tcp: %{sockaddr}: loop %i: length prefix not received after %5.3fs (%x)", message_get_sender_sa(mesg), loop_count, s, next_message_size); #endif } break; } ++loop_count; #if DEBUG log_debug("tcp: %{sockaddr}: loop %i", message_get_sender_sa(mesg), loop_count); #endif u16 native_dns_query_len = ntohs(dns_query_len); if(native_dns_query_len == 0) { log_notice("tcp: %{sockaddr}: message size is 0", message_get_sender_sa(mesg)); ret = UNPROCESSABLE_MESSAGE; break; } if(dnscore_shuttingdown()) { ret = STOPPED_BY_APPLICATION_SHUTDOWN; break; } /** * read with an expected rate */ #if DEBUG log_debug("tcp: %{sockaddr}: waiting for %i bytes", message_get_sender_sa(mesg), native_dns_query_len); #endif #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER bench = debug_bench_start(&debug_tcp_read_message); #endif #if DNSCORE_HAS_TCP_MANAGER received = tcp_manager_read_fully(sctx, message_get_buffer(mesg), native_dns_query_len); #else received = readfully_limited_ex(sockfd, message_get_buffer(mesg), native_dns_query_len, 3000000, g_config->tcp_query_min_rate_us); #endif #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER debug_bench_stop(&debug_tcp_read_message, bench); #endif if(received != native_dns_query_len) { if(ISOK(received)) { log_notice("tcp: %{sockaddr}: message read: received %d bytes but %hd were expected", message_get_sender_sa(mesg), received, native_dns_query_len); } else { log_notice("tcp: %{sockaddr}: message read: %r", message_get_sender_sa(mesg), ERRNO_ERROR); } message_set_size(mesg, 0); #if DNSCORE_HAS_TCP_MANAGER // #else tcp_set_abortive_close(sockfd); #endif ret = UNPROCESSABLE_MESSAGE; break; } #if DNSCORE_HAS_TCP_MANAGER // nothing #else tcp_set_nodelay(sockfd, TRUE); tcp_set_cork(sockfd, FALSE); #endif message_set_size(mesg, received); bool received_query = message_isquery(mesg); #if DEBUG log_debug("tcp: %{sockaddr}: received %i bytes", message_get_sender_sa(mesg), native_dns_query_len); #endif #if DEBUG #if DUMP_TCP_RECEIVED_WIRE log_memdump_ex(g_server_logger, MSG_DEBUG5, message_get_buffer(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT); #endif #endif message_set_protocol(mesg, IPPROTO_TCP); switch(message_get_opcode(mesg)) { case OPCODE_QUERY: { if(ISOK(ret = message_process_query(mesg))) { message_edns0_clear_undefined_flags(mesg); message_reset_buffer_size(mesg); switch(message_get_query_class(mesg)) { case CLASS_IN: { log_query(svr_sockfd, mesg); if(message_get_query_type(mesg) == TYPE_AXFR) { /* * Start an AXFR "writer" thread * Give it the tcp fd * It will store the current AXFR on the disk if it does not exist yet (writers blocked) * It will then open the stored file and stream it back to the tcp fd (writers freed) * ACL/TSIG is not taken in account yet. */ TCPSTATS(tcp_axfr_count++); #if DNSCORE_HAS_TCP_MANAGER ret = axfr_process(mesg, sctx); #else ret = axfr_process(mesg, sockfd); #endif #if DEBUG log_debug("tcp: %{sockaddr}: axfr_process done : %r", message_get_sender_sa(mesg), ret); #endif return ret; /* AXFR PROCESSING: process then closes: all in background */ } if(message_get_query_type(mesg) == TYPE_IXFR) { /* * Start an IXFR "writer" thread * Give it the tcp fd * It will either send the incremental changes (stored on the disk), either answer with an AXFR * ACL/TSIG is not taken in account yet. */ TCPSTATS(tcp_ixfr_count++); #if DNSCORE_HAS_TCP_MANAGER ret = ixfr_process(mesg, sctx); #else ret = ixfr_process(mesg, sockfd); #endif #if DEBUG log_debug("tcp: %{sockaddr}: ixfr_process done : %r", message_get_sender_sa(mesg), ret); #endif return ret; /* IXFR PROCESSING: process then closes: all in background */ } #if DEBUG log_debug("tcp: %{sockaddr}: querying database", message_get_sender_sa(mesg)); #endif /* * This query must go through the task channel. */ database_query(g_config->database, mesg); #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply(mesg, sctx); #else ret = server_tcp_reply(mesg, sockfd); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_queries_count++); TCPSTATS_FIELD(tcp_referrals_count += message_get_referral(mesg)); TCPSTATS_FIELD(tcp_fp[message_get_status(mesg)]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); break; } // case query IN case CLASS_CH: { log_query(svr_sockfd, mesg); class_ch_process(mesg); #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply(mesg, sctx); #else ret = server_tcp_reply(mesg, sockfd); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_queries_count++); TCPSTATS_FIELD(tcp_fp[message_get_status(mesg)]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); break; } default: { #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply_error(mesg, sctx, FP_NOT_SUPP_CLASS); #else ret = server_tcp_reply_error(mesg, sockfd, FP_NOT_SUPP_CLASS); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_queries_count++); TCPSTATS_FIELD(tcp_fp[FP_NOT_SUPP_CLASS]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); break; } } // query class } // if message process succeeded else // an error occurred : no query to be done at all { log_warn("query [%04hx] from %{sockaddr} error %i : %r", ntohs(message_get_id(mesg)), message_get_sender_sa(mesg), message_get_status(mesg), ret); if(ret == UNPROCESSABLE_MESSAGE && (g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE)) { log_memdump_ex(MODULE_MSG_HANDLE, MSG_WARNING, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_BUFFER); } // note: message_isquery(mesg) => INVALID_MESSAGE if( (ret != INVALID_MESSAGE) && (((g_config->server_flags & SERVER_FL_ANSWER_FORMERR) != 0) || (message_get_status(mesg) != RCODE_FORMERR)) && received_query ) { if(!message_has_tsig(mesg) && (message_get_status(mesg) != FP_RCODE_NOTAUTH)) { message_transform_to_error(mesg); } #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply(mesg, sctx); #else ret = server_tcp_reply(mesg, sockfd); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_queries_count++); TCPSTATS_FIELD(tcp_fp[message_get_status(mesg)]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); } else { TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_queries_count++); TCPSTATS_FIELD(tcp_dropped_count++); TCPSTATS_UNLOCK(); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_agressive_close(sockfd, 1); #endif } } break; } // case query case OPCODE_NOTIFY: { if(ISOK(ret = message_process(mesg))) { message_reset_buffer_size(mesg); switch(message_get_query_class(mesg)) { case CLASS_IN: { // a master sent a notify using TCP ... notify_process(mesg); #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply(mesg, sctx); #else ret = server_tcp_reply(mesg, sockfd); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_notify_input_count++); TCPSTATS_FIELD(tcp_fp[message_get_status(mesg)]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); break; } default: { #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply_error(mesg, sctx, FP_NOT_SUPP_CLASS); #else ret = server_tcp_reply_error(mesg, sockfd, FP_NOT_SUPP_CLASS); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_notify_input_count++); TCPSTATS_FIELD(tcp_fp[FP_NOT_SUPP_CLASS]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); break; } } // notify class } // if message process succeeded else // an error occurred : no query to be done at all { log_warn("notify [%04hx] from %{sockaddr} error %i : %r", ntohs(message_get_id(mesg)), message_get_sender_sa(mesg), message_get_status(mesg), ret); if(ret == UNPROCESSABLE_MESSAGE && (g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE)) { log_memdump_ex(MODULE_MSG_HANDLE, MSG_WARNING, message_get_buffer(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_BUFFER); } if( (ret != INVALID_MESSAGE) && ((message_get_status(mesg) != RCODE_FORMERR) || ((g_config->server_flags & SERVER_FL_ANSWER_FORMERR) != 0)) && received_query) { if(!message_has_tsig(mesg) && (message_get_status(mesg) != FP_RCODE_NOTAUTH)) { message_transform_to_error(mesg); } #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply(mesg, sctx); #else ret = server_tcp_reply(mesg, sockfd); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_notify_input_count++); TCPSTATS_FIELD(tcp_fp[message_get_status(mesg)]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); } else { TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_notify_input_count++); TCPSTATS_FIELD(tcp_dropped_count++); TCPSTATS_UNLOCK(); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_agressive_close(sockfd, 1); #endif } } break; } // case notify case OPCODE_UPDATE: { if(ISOK(ret = message_process(mesg))) { message_edns0_clear_undefined_flags(mesg); switch(message_get_query_class(mesg)) { case CLASS_IN: { /* * _ Post an update on the scheduler * _ wait for the end of the update * _ proceed */ /** * @note It's the responsibility of the called function (or one of its callees) to ensure * this does not take much time and thus to trigger a background task with the * scheduler if needed. */ #if HAS_DYNUPDATE_SUPPORT if(message_get_query_type(mesg) == TYPE_SOA) { log_info("update [%04hx] %{dnsname} from %{sockaddr}", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); } else { log_info("update [%04hx] %{dnsname} %{dnstype} from %{sockaddr}", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_sender_sa(mesg)); } if(FAIL(database_update(g_config->database, mesg))) { if(message_get_status(mesg) == RCODE_NOERROR) { message_set_status(mesg, FP_RCODE_SERVFAIL); } } #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply(mesg, sctx); #else ret = server_tcp_reply(mesg, sockfd); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_updates_count++); TCPSTATS_FIELD(tcp_fp[message_get_status(mesg)]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); #else #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply_error(mesg, sctx, FP_FEATURE_DISABLED); #else ret = server_tcp_reply_error(mesg, sockfd, FP_FEATURE_DISABLED); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_fp[FP_FEATURE_DISABLED]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); #endif break; } // update class IN default: { #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply_error(mesg, sctx, FP_NOT_SUPP_CLASS); #else ret = server_tcp_reply_error(mesg, sockfd, FP_NOT_SUPP_CLASS); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_updates_count++); TCPSTATS_FIELD(tcp_fp[FP_NOT_SUPP_CLASS]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); break; } } // update class } // if message process succeeded else // an error occurred : no query to be done at all { log_warn("update [%04hx] from %{sockaddr} error %i : %r", ntohs(message_get_id(mesg)), message_get_sender_sa(mesg), message_get_status(mesg), ret); if(g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE) { log_memdump_ex(MODULE_MSG_HANDLE, MSG_WARNING, message_get_buffer(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_BUFFER); } if( (ret != INVALID_MESSAGE) && (((g_config->server_flags & SERVER_FL_ANSWER_FORMERR) != 0) || (message_get_status(mesg) != RCODE_FORMERR)) && received_query) { if(!message_has_tsig(mesg) && (message_get_status(mesg) != FP_RCODE_NOTAUTH)) { message_transform_to_error(mesg); } #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply(mesg, sctx); #else ret = server_tcp_reply(mesg, sockfd); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_updates_count++); TCPSTATS_FIELD(tcp_fp[message_get_status(mesg)]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); } else { TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_updates_count++); TCPSTATS_FIELD(tcp_dropped_count++); TCPSTATS_UNLOCK(); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_agressive_close(sockfd, 1); #endif } } break; } // case update #if DNSCORE_HAS_CTRL case OPCODE_CTRL: { #if DNSCORE_HAS_TCP_MANAGER int sockfd = tcp_manager_socket(sctx); #endif if(ctrl_query_is_listened(sockfd)) { // note: ctrl_message_process contains reply code ret = ctrl_message_process(mesg); if(ret != SUCCESS_DROPPED) { #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply(mesg, sctx); #else ret = server_tcp_reply(mesg, sockfd); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_queries_count++); // ? TCPSTATS_FIELD(tcp_fp[message_get_status(mesg)]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); } else { TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_dropped_count++); TCPSTATS_UNLOCK(); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_agressive_close(sockfd, 1); #endif } } else { // this IP/port is not configured to listen CTRL queries TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_dropped_count++); TCPSTATS_UNLOCK(); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_agressive_close(sockfd, 1); #endif } break; } // case ctrl #endif // HAS_CTRL default: { log_warn("unknown opcode %x [%04hx] from %{sockaddr} error: %r", message_get_opcode(mesg), ntohs(message_get_id(mesg)), message_get_sender_sa(mesg), MAKE_DNSMSG_ERROR(FP_NOT_SUPP_OPC)); log_notice("opcode-%i (%04hx) [%02x|%02x] QC=%hu AN=%hu NS=%hu AR=%hu : %r (%r) (%{sockaddrip}) size=%hu", (u32)(message_get_opcode(mesg) >> OPCODE_SHIFT), ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), message_get_query_count(mesg), // QC message_get_answer_count(mesg), // AC message_get_authority_count(mesg), // NS message_get_additional_count(mesg), // AR MAKE_DNSMSG_ERROR(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); ret = message_process_lenient(mesg); if(message_get_status(mesg) == RCODE_OK) // else a TSIG may have some complain { message_set_status(mesg, FP_RCODE_NOTIMP); message_update_answer_status(mesg); #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) { tsig_sign_answer(mesg); } #endif } if(g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE) { log_memdump_ex(MODULE_MSG_HANDLE, MSG_WARNING, message_get_buffer(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_BUFFER); } if((message_get_status(mesg) != RCODE_FORMERR) || ((g_config->server_flags & SERVER_FL_ANSWER_FORMERR) != 0)) { if(!message_has_tsig(mesg) && (message_get_status(mesg) != FP_RCODE_NOTAUTH)) { message_edns0_clear_undefined_flags(mesg); message_transform_to_error(mesg); } #if DNSCORE_HAS_TCP_MANAGER ret = server_tcp_reply(mesg, sctx); #else ret = server_tcp_reply(mesg, sockfd); #endif TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_undefined_count++); TCPSTATS_FIELD(tcp_fp[message_get_status(mesg)]++); if(ISOK(ret)) { TCPSTATS_FIELD(tcp_output_size_total += ret); } TCPSTATS_UNLOCK(); } else { TCPSTATS_LOCK(); TCPSTATS_FIELD(tcp_undefined_count++); TCPSTATS_FIELD(tcp_dropped_count++); TCPSTATS_UNLOCK(); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_agressive_close(sockfd, 1); #endif } } } // switch operation code if(FAIL(ret)) { #if DEBUG log_debug("tcp: %{sockaddr}: failed with : %r", message_get_sender_sa(mesg), ret); #endif break; } } // while received bytes if(loop_count > 0) { // If the next message size is not 2, then we didn't had to expect a message if(next_message_size == 2) { // If we have got an error while receiving (tcp too slow), then abort the connection if(ISOK(received)) { #if !DNSCORE_HAS_TCP_MANAGER tcp_set_agressive_close(sockfd, 1); #endif } else { log_notice("tcp: %{sockaddr} message #%i processing failed: %r", message_get_sender_sa(mesg), loop_count, received); #if !DNSCORE_HAS_TCP_MANAGER tcp_set_abortive_close(sockfd); #endif } } else { // We processed at least one message but this last one was either // non-existent, or truncated, or too slow : // // We give it a second and we close. #if !DNSCORE_HAS_TCP_MANAGER tcp_set_agressive_close(sockfd, 1); #endif } s64 time_stop = timeus(); s64 d = MAX(time_stop - time_start, 0); double s = d / ONE_SECOND_US_F; log_debug("tcp: %{sockaddr}: loop %i took %5.3fs", message_get_sender_sa(mesg), loop_count, s); } else { s64 time_stop = timeus(); s64 d = MAX(time_stop - time_start, 0); double s = d / ONE_SECOND_US_F; if(next_message_size < 0) { log_notice("tcp: %{sockaddr}: connection didn't sent the message size after %5.3fs: %r", message_get_sender_sa(mesg), s, next_message_size); } else if(next_message_size > 0) // a.k.a : 1 { log_notice("tcp: %{sockaddr}: connection didn't sent the message size after %5.3fs", message_get_sender_sa(mesg), s); } else { log_notice("tcp: %{sockaddr}: connection closed after %5.3fs", message_get_sender_sa(mesg), s); } #if !DNSCORE_HAS_TCP_MANAGER tcp_set_abortive_close(sockfd); #endif } #if DEBUG #if DNSCORE_HAS_TCP_MANAGER log_debug("tcp: %{sockaddr} closing socket %i, loop %i", message_get_sender_sa(mesg), tcp_manager_socket(sctx), loop_count); #else log_debug("tcp: %{sockaddr} closing socket %i, loop %i", message_get_sender_sa(mesg), sockfd, loop_count); #endif #endif #if DNSCORE_HAS_TCP_MANAGER if(FAIL(ret)) { // should close tcp_manager_context_close_and_release(sctx); } else { tcp_manager_context_release(sctx); /// @note don't : tcp_manager_close(sctx); } #else shutdown(sockfd, SHUT_RDWR); close_ex(sockfd); #endif return ret; } static void* server_process_tcp_thread(void* parm) { #if DEBUG log_debug("tcp: begin"); #endif server_process_tcp_thread_parm* tcp_parm = (server_process_tcp_thread_parm*)parm; size_t pool_buffer_size = SERVER_POOL_BUFFER_SIZE; // 128KB u8 *pool_buffer; #if SERVER_TCP_USE_LAZY_MAPPING u32 thread_index = thread_pool_thread_index_get(); tcp_thread_memory_t *thread_memory = &tcp_thread_memory[thread_index]; message_data *mesg = message_data_with_buffer_init(&thread_memory->message_data); // tcp pool_buffer = &thread_memory->pool_buffer[0]; #else message_data_with_buffer mesg_buff; #if DEBUG memset(&mesg_buff, 0xff, sizeof(mesg_buff)); #endif message_data *mesg = message_data_with_buffer_init(&mesg_buff); // tcp MALLOC_OBJECT_ARRAY_OR_DIE(pool_buffer, u8, pool_buffer_size, SVRPOOLB_TAG); #endif message_set_pool_buffer(mesg, pool_buffer, pool_buffer_size); #if DNSCORE_HAS_TCP_MANAGER message_copy_sender_from_sa(mesg, tcp_manager_sockaddr(tcp_parm->sctx), tcp_manager_socklen(tcp_parm->sctx)); #else message_copy_sender_from_sa(mesg, &tcp_parm->sa.sa, tcp_parm->addr_len); #endif #if DEBUG log_debug("tcp: processing stream from %{sockaddr}", message_get_sender_sa(mesg)); #endif #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER u64 bench = debug_bench_start(&debug_server_process_tcp_task); #endif #if DNSCORE_HAS_TCP_MANAGER server_process_tcp_task(mesg, tcp_parm->sctx, tcp_parm->svr_sockfd); #else server_process_tcp_task(mesg, tcp_parm->sockfd, tcp_parm->svr_sockfd); #endif #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER debug_bench_stop(&debug_server_process_tcp_task, bench); #endif #if SERVER_TCP_USE_LAZY_MAPPING formatln("thread: %p: madvise(%p, %d = %x, MADV_DONTNEED)", pthread_self(), thread_memory, (sizeof(tcp_thread_memory_t) + 4095) & ~4095, (sizeof(tcp_thread_memory_t) + 4095) & ~4095); madvise(thread_memory, (sizeof(tcp_thread_memory_t) + 4095) & ~4095, MADV_DONTNEED); #else free(pool_buffer); #endif #if !DNSCORE_HAS_TCP_MANAGER server_tcp_queries_for_ip_decrement(&tcp_parm->sa.ss); #endif ZFREE_OBJECT(tcp_parm); #if DEBUG log_debug("tcp: end"); #endif return NULL; } static error_state_t server_process_tcp_error_state = ERROR_STATE_INITIALIZER; ya_result server_process_tcp_init() { #if SERVER_TCP_USE_LAZY_MAPPING if(thread_memory_size == 0) { u32 thread_count = thread_pool_get_size(server_tcp_thread_pool); u32 tmp_thread_memory_size = thread_count * sizeof(tcp_thread_memory_t); void *tmp_tcp_thread_memory = mmap(NULL, tmp_thread_memory_size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); if(tmp_tcp_thread_memory == MAP_FAILED) { return ERRNO_ERROR; } #if DEBUG u8 *tcp_thread_memory_ptr = (u8*)tmp_tcp_thread_memory; for(u64 i = 0; i < tmp_thread_memory_size; i += 4096) { tcp_thread_memory_ptr[i] = 1; } madvise(tmp_tcp_thread_memory, tmp_thread_memory_size, MADV_DONTNEED); #endif tcp_thread_memory = (tcp_thread_memory_t*)tmp_tcp_thread_memory; thread_memory_size = tmp_thread_memory_size; return SUCCESS; } else { return INVALID_STATE_ERROR; } #else return SUCCESS; #endif } void server_process_tcp_finalize() { #if SERVER_TCP_USE_LAZY_MAPPING if(thread_memory_size > 0) { munmap(tcp_thread_memory, thread_memory_size); thread_memory_size = 0; tcp_thread_memory = NULL; } #endif } void server_tcp_allocate_poll(struct pollfd **pollfdsp, unsigned int *pollfds_sizep) { assert((pollfdsp != NULL) && (pollfds_sizep != NULL)); struct pollfd *pollfds; unsigned int pollfds_size = 0; pollfds = (struct pollfd*)malloc(sizeof(struct pollfd) * g_server_context.tcp_socket_count); ZEROMEMORY(pollfds, sizeof(struct pollfd) * g_server_context.tcp_socket_count); for(u32 i = 0; i < g_server_context.tcp_socket_count; ++i) { int sockfd = g_server_context.tcp_socket[i]; if(sockfd >= 0) { pollfds[pollfds_size].fd = sockfd; pollfds[pollfds_size].events = POLLIN; ++pollfds_size; } else { log_err("server-mm: invalid socket value (%i) in tcp listening sockets", sockfd); } } *pollfdsp = pollfds; *pollfds_sizep = pollfds_size; } void server_tcp_accept_loop(struct service_worker_s *worker, server_statistics_t **statistics_array, u32 statistics_array_size) { ya_result ret; struct pollfd *pollfds; unsigned int pollfds_size; server_tcp_allocate_poll(&pollfds, &pollfds_size); u64 server_run_loop_rate_tick = 0; u32 previous_tick = 0; u32 server_run_loop_timeout_countdown = g_config->statistics_max_period; bool log_statistics_enabled = (g_statistics_logger != NULL) && (g_config->server_flags & SERVER_FL_STATISTICS) != 0; static server_statistics_t server_statistics_sum; log_info("server-tcp: running"); while(!service_should_reconfigure_or_stop(worker)) { server_statistics.input_loop_count++; ret = poll(pollfds, pollfds_size, 1000); // timeout is 1000 ms if(ret > 0) { /* * ret is the number of entries to check */ for(u32 i = 0; i < pollfds_size; ++i) { if(pollfds[i].revents & POLLIN) { pollfds[i].revents = 0; server_tcp_process(pollfds[i].fd); server_statistics.loop_rate_counter++; } if(--ret == 0) { break; } } } else /* ret <= 0 */ { if(ret == -1) { int err = errno; if((err != EINTR) && (err != EBADF)) { /** * From the man page, what we can expect is EBADF (bug) EINVAL (bug) or ENOMEM (critical) * So I we can kill and notify. */ log_err("server-mm: poll: %r", ERRNO_ERROR); } /*else if(err == EBADF) { break; }*/ } /*else if(dnscore_shuttingdown()) { break; }*/ /* ret == 0 => no fd set at all and no error => timeout */ server_run_loop_timeout_countdown--; server_statistics.input_timeout_count++; } #if HAS_RRL_SUPPORT rrl_cull(); #endif #if ZDB_HAS_LOCK_DEBUG_SUPPORT zdb_zone_lock_monitor_log(); #endif #if ZDB_HAS_OLD_MUTEX_DEBUG_SUPPORT zdb_zone_lock_set_monitor(); #endif /* handles statistics logging */ if(log_statistics_enabled) { u32 tick = dnscore_timer_get_tick(); if((tick - previous_tick) >= g_config->statistics_max_period) { u64 now = timems(); u64 delta = now - server_run_loop_rate_tick; if(delta > 0) { /* log_info specifically targeted to the g_statistics_logger handle */ server_statistics.loop_rate_elapsed = delta; memcpy(&server_statistics_sum, &server_statistics, sizeof(server_statistics_t)); for(u32 i = 0; i < statistics_array_size; ++i) { server_statistics_t *stats = statistics_array[i]; assert(stats != NULL); server_statistics_sum.input_loop_count += stats->input_loop_count; /* server_statistics_sum.input_timeout_count += stats->input_timeout_count; */ server_statistics_sum.udp_output_size_total += stats->udp_output_size_total; server_statistics_sum.udp_referrals_count += stats->udp_referrals_count; server_statistics_sum.udp_input_count += stats->udp_input_count; server_statistics_sum.udp_dropped_count += stats->udp_dropped_count; server_statistics_sum.udp_queries_count += stats->udp_queries_count; server_statistics_sum.udp_notify_input_count += stats->udp_notify_input_count; server_statistics_sum.udp_updates_count += stats->udp_updates_count; server_statistics_sum.udp_undefined_count += stats->udp_undefined_count; #if HAS_RRL_SUPPORT server_statistics_sum.rrl_slip += stats->rrl_slip; server_statistics_sum.rrl_drop += stats->rrl_drop; #endif for(u32 j = 0; j < SERVER_STATISTICS_ERROR_CODES_COUNT; j++) { server_statistics_sum.udp_fp[j] += stats->udp_fp[j]; } } #if HAS_EVENT_DYNAMIC_MODULE if(dynamic_module_statistics_interface_chain_available()) { dynamic_module_on_statistics_update(&server_statistics_sum, now); } #endif log_statistics(&server_statistics_sum); server_run_loop_rate_tick = now; server_run_loop_timeout_countdown = g_config->statistics_max_period; server_statistics.loop_rate_counter = 0; #if DEBUG #if HAS_ZALLOC_STATISTICS_SUPPORT zalloc_print_stats(termout); #endif #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT || DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT || DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT || DNSCORE_HAS_MMAP_DEBUG_SUPPORT debug_stat(DEBUG_STAT_TAGS|DEBUG_STAT_MMAP); // do NOT enable the dump #endif debug_bench_logdump_all(); #endif #if DNSCORE_HAS_LIBC_MALLOC_DEBUG_SUPPORT debug_malloc_hook_caller_dump(); #endif } previous_tick = tick; } } // if log_statistics_enabled } free(pollfds); } void server_tcp_process(int sockfd) { server_process_tcp_thread_parm* parm; /* * AFAIK there are two relevant fields in mesg at this point: addr & sockfd * After the accept only the sockfd is relevant */ /* I know I'm already in an #if with the same condition but I want to mark * the code I've c&p from the original do_tcp_process */ #if DEBUG log_debug("server_process_tcp_thread_start begin"); #endif #if DNSCORE_HAS_TCP_MANAGER ya_result ret; tcp_manager_socket_context_t* sctx = (tcp_manager_socket_context_t*)(intptr)0x5a5a5a5a; if((ret = tcp_manager_accept(sockfd, &sctx)) >= 0) { TCPSTATS(tcp_input_count++); error_state_clear(&server_process_tcp_error_state, MODULE_MSG_HANDLE, MSG_NOTICE, "tcp: accept call"); assert(sctx != NULL); log_debug("server_process_tcp: scheduling job"); ZALLOC_OBJECT_OR_DIE(parm, server_process_tcp_thread_parm, TPROCPRM_TAG); parm->sctx = sctx; parm->svr_sockfd = sockfd; thread_pool_enqueue_call(server_tcp_thread_pool, server_process_tcp_thread, parm, NULL, "server_process_tcp_thread_start"); } else { if((ret & 0xffff0000) == ERRNO_ERROR_BASE) { if(error_state_log(&server_process_tcp_error_state, ret)) { log_err("tcp: accept returned %r", MAKE_ERRNO_ERROR(ret)); } } log_debug("server_process_tcp: %r", ret); TCPSTATS(tcp_overflow_count++); } #else socklen_t addr_len; socketaddress addr; addr_len = sizeof(addr); int current_tcp = poll_update(); /** * @note we MAY want to accept & close before rejecting. But in case of a DOS we lose. * here we will just ignore until it's possible to do something about it (or it's cancelled) * */ if(current_tcp >= g_config->max_tcp_queries) { log_debug("tcp: rejecting: already %d/%d handled", current_tcp, g_config->max_tcp_queries); #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER u64 bench = debug_bench_start(&debug_accept_reject); #endif int rejected_fd = accept(sockfd, &addr.sa, &addr_len); #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER debug_bench_stop(&debug_accept_reject, bench); #endif tcp_set_abortive_close(rejected_fd); close_ex(rejected_fd); TCPSTATS(tcp_overflow_count++); #if DEBUG log_debug("server_process_tcp_thread_start end (with an error)"); #endif return; } ZALLOC_OBJECT_OR_DIE(parm, server_process_tcp_thread_parm, TPROCPRM_TAG); /* don't test -1, test < 0 instead (test + js instead of add + stall + jz */ for(;;) { #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER u64 bench = debug_bench_start(&debug_accept); #endif parm->sockfd = accept(sockfd, &addr.sa, &addr_len); #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER debug_bench_stop(&debug_accept, bench); #endif if(parm->sockfd >= 0) { break; } int err = errno; if(err != EINTR) { err = MAKE_ERRNO_ERROR(err); if(error_state_log(&server_process_tcp_error_state, err)) { log_err("tcp: accept returned %r", err); } ZFREE_OBJECT(parm); #if DEBUG log_debug("server_process_tcp_thread_start end (with an error)"); #endif return; } } error_state_clear(&server_process_tcp_error_state, MODULE_MSG_HANDLE, MSG_NOTICE, "tcp: accept call"); #if DEBUG if(addr_len > sizeof(union socketaddress)) { log_err("tcp: addr_len = %i, max allowed is %i", addr_len, MAX(sizeof(struct sockaddr_in),sizeof(struct sockaddr_in6))); TCPSTATS(tcp_overflow_count++); tcp_set_abortive_close(parm->sockfd); close_ex(parm->sockfd); ZFREE_OBJECT(parm); log_debug("server_process_tcp_thread_start end (with an error)"); return; } #endif s64 max_connections = server_tcp_client_connections_max(&addr.ss, g_config->max_tcp_queries_per_address); if(!server_tcp_queries_for_ip_increment_if_less(&addr.ss, max_connections)) { log_debug("tcp: %{sockaddr} has too many active connections", &parm->sa); TCPSTATS(tcp_overflow_count++); tcp_set_abortive_close(parm->sockfd); close_ex(parm->sockfd); ZFREE_OBJECT(parm); #if DEBUG log_debug("server_process_tcp_thread_start end (with an error)"); #endif return; } memcpy(&parm->sa, &addr, addr_len); parm->addr_len = addr_len; parm->svr_sockfd = sockfd; if(poll_add(parm->sockfd)) { TCPSTATS(tcp_input_count++); log_debug("tcp: using slot %d/%d", current_tcp + 1 , g_config->max_tcp_queries); /* * And here is the AXFR change: if it's an AXFR, then we need to ensure that * _ we are allowed (TSIG, time limit between two AXFR "milestones", ...) * _ we have the AXFR file ready and if not, fork to generate it * * The thread is launched anyway and waits for the file with the right serial to be generated. * When the file is finally available, it is sent to the caller. * * If it's not an AXFR, then we do as ever. */ #if DEBUG log_debug("server_process_tcp_thread_start scheduling job"); #endif thread_pool_enqueue_call(server_tcp_thread_pool, server_process_tcp_thread, parm, NULL, "server_process_tcp_thread_start"); } else { log_debug("tcp: no available slots (%d used)", g_config->max_tcp_queries); server_tcp_queries_for_ip_decrement(&parm->sa.ss); #if DEBUG log_debug("server_process_tcp_thread_start tcp overflow (poll)"); #endif TCPSTATS(tcp_overflow_count++); tcp_set_abortive_close(parm->sockfd); close_ex(parm->sockfd); ZFREE_OBJECT(parm); } #endif #if DEBUG log_debug("server_process_tcp_thread_start end"); #endif } /******************************************************************************************************************* * * Server init, load, start, stop and exit * ******************************************************************************************************************/ static struct service_s server_service_handler = UNINITIALIZED_SERVICE; static bool server_handler_initialised = FALSE; static ya_result server_network_init() { ya_result ret; // this sets-up variables in g_server_context for(int i = 0; server_type[i].name != NULL; ++i) { if(i == g_config->network_model) { log_info("spawning %s", server_type[g_config->network_model].name); if(FAIL(ret = server_type[g_config->network_model].context_init(g_config->thread_count_by_address))) { log_err("network model '%s' cannot be initialised: %r", server_type[g_config->network_model].name, ret); break; } log_info("using %i working modules per UDP interface (%i threads per UDP module)", g_server_context.udp_unit_per_interface, g_server_context.thread_per_udp_worker_count); log_info("using %i working modules per TCP interface (%i threads per TCP module)", g_server_context.tcp_unit_per_interface, g_server_context.thread_per_tcp_worker_count); ret = server_context_create(); return ret; } } log_err("couldn't not set network model %i: not supported", g_config->network_model); if(g_config->network_model != 0) { g_config->network_model = 0; log_warn("switching to network model %i (%s)", g_config->network_model, server_type[g_config->network_model].name); ret = server_network_init(); return ret; } else { return FEATURE_NOT_SUPPORTED; } } /** @brief Startup server with all its processes * * Never returns. Ends with the program. */ static ya_result server_run(struct service_worker_s *worker) { ya_result ret = server_type[g_config->network_model].loop(worker); return ret; } static int server_service_apply_configuration() { int ret; if(ISOK(ret = server_network_init())) { if((server_tcp_thread_pool != NULL) && (((int)thread_pool_get_size(server_tcp_thread_pool) != g_config->max_tcp_queries))) { // the thread-pool size is wrong ya_result return_code; server_process_tcp_finalize(); if(FAIL(return_code = thread_pool_resize(server_tcp_thread_pool, g_config->max_tcp_queries))) { return return_code; } server_process_tcp_init(); if(return_code != g_config->max_tcp_queries) { log_err("could not properly set the TCP handlers"); return INVALID_STATE_ERROR; } } if((server_tcp_thread_pool == NULL) && (g_config->max_tcp_queries > 0)) { u32 max_thread_pool_size = thread_pool_get_max_thread_per_pool_limit(); if(max_thread_pool_size < (u32)g_config->max_tcp_queries) { log_warn("updating the maximum thread pool size to match the number of TCP queries (from %i to %i)", max_thread_pool_size, g_config->max_tcp_queries); thread_pool_set_max_thread_per_pool_limit(g_config->max_tcp_queries); } server_tcp_thread_pool = thread_pool_init_ex(g_config->max_tcp_queries, g_config->max_tcp_queries * 2, "svrtcp"); if(server_tcp_thread_pool == NULL) { log_err("tcp thread pool init failed"); return THREAD_CREATION_ERROR; } server_process_tcp_init(); } if(server_disk_thread_pool == NULL) { server_disk_thread_pool = thread_pool_init_ex(4, 64, "diskio"); if(server_disk_thread_pool == NULL) { log_warn("disk thread pool init failed"); return THREAD_CREATION_ERROR; } } #if DEBUG OSDEBUG(termout, "I come to serve ...\n"); log_info("I come to serve ..."); /** I could not resist ... */ #endif /* Initialises the TCP usage limit structure (It's global and defined at the beginning of server.c */ #if !DNSCORE_HAS_TCP_MANAGER poll_alloc(g_config->max_tcp_queries); #endif log_debug("thread count by address: %i", g_config->thread_count_by_address); } return ret; } void server_context_destroy(); static void server_service_deconfigure() { /* Proper shutdown. All this could be simply dropped since it takes time for "nothing". * But it's good to check that nothing is broken. */ #if DEBUG log_info("server_service_deconfigure()"); #endif server_context_close(); if((server_tcp_thread_pool != NULL) && (g_config->max_tcp_queries > 0)) { log_info("destroying TCP pool"); thread_pool_destroy(server_tcp_thread_pool); server_tcp_thread_pool = NULL; server_process_tcp_finalize(); } if(server_disk_thread_pool != NULL) { log_info("destroying disk pool"); thread_pool_destroy(server_disk_thread_pool); server_disk_thread_pool = NULL; } #if !DNSCORE_HAS_TCP_MANAGER poll_free(); #endif log_info("clearing server context"); /* Clear config struct and close all fd's */ server_context_stop(); log_info("destroying server context"); server_context_destroy(); } static int server_service_main(struct service_worker_s *worker) { ya_result ret = SUCCESS; server_process_message_udp_set_database(g_config->database); service_set_servicing(worker); log_info("server starting with pid %lu", getpid_ex()); #if HAS_RRL_SUPPORT // Sets the RRL rrl_init(); #endif // initialises the statistics if(!server_statistics_initialised) { server_statistics_initialised = TRUE; ZEROMEMORY(&server_statistics, sizeof(server_statistics_t)); mutex_init(&server_statistics.mtx); } #if HAS_EVENT_DYNAMIC_MODULE dynamic_module_settings(); #endif if(g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE) { log_info("unprocessable messages will be dumped to the logs as hexadecimal"); } else { log_info("unprocessable messages will not be dumped to the logs as hexadecimal"); } if(g_config->server_flags & SERVER_FL_ANSWER_FORMERR) { log_info("format-broken messages will be replied to"); } else { log_info("format-broken messages will not be replied to"); } /* * If not FE, or if we answer FE * * ... && (message_is_query(mesg) ??? and if there the query number is > 0 ??? */ bool reconfigure = TRUE; s64 network_setup_complain_last = 0; bool network_worked_once = FALSE; int network_auto_reconfigure_countdown = NETWORK_AUTO_RECONFIGURE_COUNTDOWN_DEFAULT; while(service_should_run(worker)) { if(reconfigure) // because we may not really have to reconfigure { if(ISOK(ret = server_service_apply_configuration())) { log_info("server setup ready"); network_worked_once = TRUE; service_clear_reconfigure(worker); #if HAS_EVENT_DYNAMIC_MODULE dynamic_module_settings(); #endif } else { s64 now = timeus(); if(ret == MAKE_ERRNO_ERROR(EPIPE)) { log_err("socket server connection broken"); dnscore_shutdown(); break; } if(ret == MAKE_ERRNO_ERROR(ENFILE)) { u32 count = host_address_count(g_config->listen) * g_config->thread_count_by_address; log_err("insufficient file open limit. It should be bigger than %u", count + 1024); dnscore_shutdown(); break; } if((now - network_setup_complain_last) > ONE_SECOND_US * 60) { log_err("failed to setup the network: %r", ret); network_setup_complain_last = now; if(!network_worked_once) { if((ret == MAKE_ERRNO_ERROR(EADDRINUSE)) || (ret == MAKE_ERRNO_ERROR(EADDRNOTAVAIL)) || (ret == MAKE_ERRNO_ERROR(EPERM))) { dnscore_shutdown(); break; } } else { ret = SUCCESS; // } } server_service_deconfigure(); if(ret == THREAD_CREATION_ERROR) { log_err("it's likely that the number of allowed TCP connection (%i) is beyond this system capabilities", g_config->max_tcp_queries); dnscore_shutdown(); break; } if(ret == MAKE_ERRNO_ERROR(EADDRNOTAVAIL)) { if(!network_worked_once && (socket_server_uid() != 0)) { log_err("yadifad hasn't been started as root. This network error is irrecoverable: stopping the server"); dnscore_shutdown(); break; } else { if(--network_auto_reconfigure_countdown == 0) { network_auto_reconfigure_countdown = NETWORK_AUTO_RECONFIGURE_COUNTDOWN_DEFAULT; if(ISOK(yadifad_config_update(g_config->config_file))) { logger_reopen(); if(!server_context_matches_config()) { log_try_debug1("network configuration has changed"); server_service_reconfigure(); } else { log_try_debug1("network configuration has not changed"); } } } } } service_clear_reconfigure(worker); /// @todo 20210304 edf -- instead of a sleep, wait for a reconfigured/shutdown event sleep(1); // used to pace the system if something wrong happens continue; } } network_setup_complain_last = 0; if(FAIL(ret = server_run(worker))) { log_err("failed to start the server workers: %r", ret); dnscore_shutdown(); break; } if(!service_should_run(worker)) { server_service_deconfigure(); break; } /// reconfigure = TRUE; /// check if configuration has changed (difficult before cfgv3) if(reconfigure) { server_service_deconfigure(); } } #if HAS_RRL_SUPPORT rrl_finalize(); #endif service_set_stopping(worker); return ret; } /** * Initialises the DNS server service. * * @return */ ya_result server_service_init() { ya_result ret = SERVICE_ALREADY_INITIALISED; #if DNSCORE_HAS_TCP_MANAGER tcp_manager_init(); #endif if(!server_handler_initialised && ISOK(ret = service_init_ex(&server_service_handler, server_service_main, "yadifad", 1))) { error_register(SUCCESS_DROPPED, "DROPPED"); #if DEBUG_BENCH_FD && !DNSCORE_HAS_TCP_MANAGER debug_bench_register(&debug_accept, "accept"); debug_bench_register(&debug_accept_reject, "accept-reject"); debug_bench_register(&debug_server_process_tcp_task, "process_tcp_task"); debug_bench_register(&debug_tcp_reply, "tcp_reply"); debug_bench_register(&debug_tcp_read_size, "tcp_read_size"); debug_bench_register(&debug_tcp_read_message, "tcp_read_message"); #endif server_handler_initialised = TRUE; } return ret; } bool server_service_started() { return server_handler_initialised && !service_stopped(&server_service_handler); } ya_result server_service_start() { int err = SERVICE_NOT_INITIALISED; if(server_handler_initialised) { if(service_stopped(&server_service_handler)) { err = service_start(&server_service_handler); } } return err; } ya_result server_service_start_and_wait() { int ret = SERVICE_NOT_INITIALISED; if(server_handler_initialised) { if(service_stopped(&server_service_handler)) { ret = service_start_and_wait(&server_service_handler); } } return ret; } ya_result server_service_wait() { int ret = SERVICE_NOT_INITIALISED; if(server_handler_initialised) { if(ISOK(ret = service_wait_servicing(&server_service_handler))) { ret = SERVICE_NOT_RUNNING; if(service_servicing(&server_service_handler)) { ret = service_wait(&server_service_handler); } } } return ret; } ya_result server_service_stop_nowait() { int err = SERVICE_NOT_INITIALISED; if(server_handler_initialised) { err = SERVICE_NOT_RUNNING; #if HAS_DYNUPDATE_SUPPORT dynupdate_query_service_reset(); #endif if(!service_stopped(&server_service_handler)) { err = service_stop(&server_service_handler); } } return err; } ya_result server_service_stop() { int err = SERVICE_NOT_INITIALISED; if(server_handler_initialised) { err = SERVICE_NOT_RUNNING; #if HAS_DYNUPDATE_SUPPORT dynupdate_query_service_reset(); #endif if(!service_stopped(&server_service_handler)) { err = service_stop(&server_service_handler); service_wait(&server_service_handler); } } return err; } ya_result server_service_reconfigure() { int err = SERVICE_NOT_INITIALISED; if(server_handler_initialised) { err = SERVICE_NOT_RUNNING; if(!service_stopped(&server_service_handler)) { #if HAS_DYNUPDATE_SUPPORT dynupdate_query_service_reset(); #endif err = service_reconfigure(&server_service_handler); } } return err; } ya_result server_service_finalize() { int err = SERVICE_NOT_INITIALISED; if(server_handler_initialised) { err = server_service_stop(); service_finalize(&server_service_handler); server_handler_initialised = FALSE; } return err; } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server_context.c0000644000000000000000000000013214505005533022111 xustar000000000000000030 mtime=1695812443.503997384 30 atime=1695812445.783030024 30 ctime=1695812495.663744417 yadifa-2.6.5-11201/sbin/yadifad/server_context.c0000664000374500037450000012040614505005533022056 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server Server * @ingroup yadifad * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #define SERVER_CONTEXT_C 1 #include "server-config.h" #include #include #include #include #include #include #include #include #include #include #include #include "server_context.h" #include "server.h" #define ITFNAME_TAG 0x454d414e465449 extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #define SCTXSOCK_TAG 0x4b434f5358544353 #define HAS_SOCKET_SERVER 1 struct itf_name { char *name; u8 name_len; }; static ptr_vector server_context_socket_name = PTR_VECTOR_EMPTY; static volatile bool config_update_network_done = FALSE; server_context_s g_server_context = SERVER_CONTEXT_INITIALISER; static void server_context_addresses_allocate() { assert(g_server_context.udp_interface_count > 0); MALLOC_OBJECT_ARRAY_OR_DIE(g_server_context.udp_interface, struct addrinfo*, g_server_context.udp_interface_count, ADDRINFO_TAG); memset(g_server_context.udp_interface, 0, sizeof(struct addrinfo**) * g_server_context.udp_interface_count); assert(g_server_context.tcp_interface_count > 0); MALLOC_OBJECT_ARRAY_OR_DIE(g_server_context.tcp_interface, struct addrinfo*, g_server_context.tcp_interface_count, ADDRINFO_TAG); memset(g_server_context.tcp_interface, 0, sizeof(struct addrinfo**) * g_server_context.tcp_interface_count); assert(g_server_context.udp_socket_count > 0); MALLOC_OBJECT_ARRAY_OR_DIE(g_server_context.udp_socket, int, g_server_context.udp_socket_count, SCTXSOCK_TAG); memset(g_server_context.udp_socket, 0xff, sizeof(int) * g_server_context.udp_socket_count); g_server_context.tcp_socket_count = g_server_context.tcp_interface_count * g_server_context.tcp_unit_per_interface; //if(server_context.reuse) server_context.tcp_socket_count *= server_context.tcp_unit_per_interface; assert(g_server_context.tcp_socket_count > 0); MALLOC_OBJECT_ARRAY_OR_DIE(g_server_context.tcp_socket, int, g_server_context.tcp_socket_count, SCTXSOCK_TAG); memset(g_server_context.tcp_socket, 0xff, sizeof(int) * g_server_context.tcp_socket_count); } #if 0 static void server_context_addresses_udp_remove_at(u32 index) { if((g_server_context.udp_interface_count == 0) || (index >= g_server_context.udp_interface_count)) { return; } if(g_server_context.udp_interface_count == 1) { g_server_context.udp_interface_count = 0; g_server_context.udp_socket_count = 0; free(g_server_context.udp_interface); g_server_context.udp_interface = NULL; free(g_server_context.udp_socket); g_server_context.udp_socket = NULL; return; } u32 new_udp_interface_count = g_server_context.udp_interface_count - 1; u32 new_udp_socket_count = new_udp_interface_count; free(g_server_context.udp_interface[index]); g_server_context.udp_interface[index] = NULL; struct addrinfo **new_udp_interface; MALLOC_OBJECT_ARRAY_OR_DIE(new_udp_interface, struct addrinfo*, new_udp_interface_count, ADDRINFO_TAG); memcpy(new_udp_interface, g_server_context.udp_interface, sizeof(struct addrinfo**) * index); memcpy(&new_udp_interface[index], &g_server_context.udp_interface[index + 1], sizeof(struct addrinfo**) * (new_udp_interface_count - index)); if(g_server_context.udp_socket[index] >= 0) { close_ex(g_server_context.udp_socket[index]); g_server_context.udp_socket[index] = -1; } int *new_udp_socket; MALLOC_OBJECT_ARRAY_OR_DIE(new_udp_socket, int, new_udp_socket_count, SCTXSOCK_TAG); memcpy(new_udp_socket, g_server_context.udp_socket, sizeof(int) * index); memcpy(&new_udp_socket[index], &g_server_context.udp_socket[index + 1], sizeof(int) * (new_udp_socket_count - index)); struct addrinfo **old_udp_interface = g_server_context.udp_interface; int *old_udp_socket = g_server_context.udp_socket; g_server_context.udp_interface = new_udp_interface; g_server_context.udp_socket = new_udp_socket; g_server_context.udp_interface_count = new_udp_interface_count; g_server_context.udp_socket_count = new_udp_socket_count; free(old_udp_socket); free(old_udp_interface); } static void server_context_addresses_udp_append(u32 count) { if(count == 0) { return; } u32 new_udp_interface_count = g_server_context.udp_interface_count + count; u32 new_udp_socket_count = new_udp_interface_count; struct addrinfo **new_udp_interface; MALLOC_OBJECT_ARRAY_OR_DIE(new_udp_interface, struct addrinfo*, new_udp_interface_count, ADDRINFO_TAG); memcpy(new_udp_interface, g_server_context.udp_interface, sizeof(struct addrinfo**) * g_server_context.udp_interface_count); memset(&new_udp_interface[g_server_context.udp_interface_count], 0, sizeof(struct addrinfo**) * (new_udp_interface_count - g_server_context.udp_interface_count)); int *new_udp_socket; MALLOC_OBJECT_ARRAY_OR_DIE(new_udp_socket, int, new_udp_socket_count, SCTXSOCK_TAG); memcpy(new_udp_socket, g_server_context.udp_socket, sizeof(int) * g_server_context.udp_socket_count); memset(&new_udp_socket[g_server_context.udp_socket_count], 0xff, sizeof(int) * (new_udp_socket_count - g_server_context.udp_socket_count)); struct addrinfo **old_udp_interface = g_server_context.udp_interface; int *old_udp_socket = g_server_context.udp_socket; g_server_context.udp_interface = new_udp_interface; g_server_context.udp_socket = new_udp_socket; g_server_context.udp_interface_count = new_udp_interface_count; g_server_context.udp_socket_count = new_udp_socket_count; free(old_udp_socket); free(old_udp_interface); } static void server_context_addresses_udp_insert_at(u32 index) { if(index > g_server_context.udp_interface_count) { return; } if(index == g_server_context.udp_interface_count) { server_context_addresses_udp_append(1); return; } u32 new_udp_interface_count = g_server_context.udp_interface_count + 1; u32 new_udp_socket_count = new_udp_interface_count; struct addrinfo **new_udp_interface; MALLOC_OBJECT_ARRAY_OR_DIE(new_udp_interface, struct addrinfo*, new_udp_interface_count, ADDRINFO_TAG); memcpy(new_udp_interface, g_server_context.udp_interface, sizeof(struct addrinfo**) * index); new_udp_interface[index] = NULL; memcpy(&new_udp_interface[index + 1], &g_server_context.udp_interface[index], sizeof(struct addrinfo**) * (g_server_context.udp_interface_count - index)); int *new_udp_socket; MALLOC_OBJECT_ARRAY_OR_DIE(new_udp_socket, int, new_udp_socket_count, SCTXSOCK_TAG); memcpy(new_udp_socket, g_server_context.udp_socket, sizeof(int) * index); new_udp_socket[index] = -1; memcpy(&new_udp_socket[index + 1], &g_server_context.udp_socket[index], sizeof(int) * (g_server_context.udp_socket_count - index)); struct addrinfo **old_udp_interface = g_server_context.udp_interface; int *old_udp_socket = g_server_context.udp_socket; g_server_context.udp_interface = new_udp_interface; g_server_context.udp_socket = new_udp_socket; g_server_context.udp_interface_count = new_udp_interface_count; g_server_context.udp_socket_count = new_udp_socket_count; free(old_udp_socket); free(old_udp_interface); } static void server_context_addresses_tcp_remove_at(u32 index) { if((g_server_context.tcp_interface_count == 0) || (index >= g_server_context.tcp_interface_count)) { return; } if(g_server_context.tcp_interface_count == 1) { g_server_context.tcp_interface_count = 0; g_server_context.tcp_socket_count = 0; free(g_server_context.tcp_interface); g_server_context.tcp_interface = NULL; free(g_server_context.tcp_socket); g_server_context.tcp_socket = NULL; return; } u32 new_tcp_interface_count = g_server_context.tcp_interface_count - 1; u32 new_tcp_socket_count = new_tcp_interface_count * g_server_context.tcp_unit_per_interface; free(g_server_context.tcp_interface[index]); g_server_context.tcp_interface[index] = NULL; struct addrinfo **new_tcp_interface; MALLOC_OBJECT_ARRAY_OR_DIE(new_tcp_interface, struct addrinfo*, new_tcp_interface_count, ADDRINFO_TAG); memcpy(new_tcp_interface, g_server_context.tcp_interface, sizeof(struct addrinfo**) * index); memcpy(&new_tcp_interface[index], &g_server_context.tcp_interface[index + 1], sizeof(struct addrinfo**) * (new_tcp_interface_count - index)); if(g_server_context.tcp_socket[index] >= 0) { close_ex(g_server_context.tcp_socket[index]); g_server_context.tcp_socket[index] = -1; } int *new_tcp_socket; MALLOC_OBJECT_ARRAY_OR_DIE(new_tcp_socket, int, new_tcp_socket_count, SCTXSOCK_TAG); memcpy(new_tcp_socket, g_server_context.tcp_socket, sizeof(int) * index); memcpy(&new_tcp_socket[index], &g_server_context.tcp_socket[index + 1], sizeof(int) * (new_tcp_socket_count - index)); struct addrinfo **old_tcp_interface = g_server_context.tcp_interface; int *old_tcp_socket = g_server_context.tcp_socket; g_server_context.tcp_interface = new_tcp_interface; g_server_context.tcp_socket = new_tcp_socket; g_server_context.tcp_interface_count = new_tcp_interface_count; g_server_context.tcp_socket_count = new_tcp_socket_count; free(old_tcp_socket); free(old_tcp_interface); } static void server_context_addresses_tcp_append(u32 count) { if(count == 0) { return; } u32 new_tcp_interface_count = g_server_context.tcp_interface_count + count; u32 new_tcp_socket_count = new_tcp_interface_count * g_server_context.tcp_unit_per_interface; struct addrinfo **new_tcp_interface; MALLOC_OBJECT_ARRAY_OR_DIE(new_tcp_interface, struct addrinfo*, new_tcp_interface_count, ADDRINFO_TAG); memcpy(new_tcp_interface, g_server_context.tcp_interface, sizeof(struct addrinfo**) * g_server_context.tcp_interface_count); memset(&new_tcp_interface[g_server_context.tcp_interface_count], 0, sizeof(struct addrinfo**) * (new_tcp_interface_count - g_server_context.tcp_interface_count)); int *new_tcp_socket; MALLOC_OBJECT_ARRAY_OR_DIE(new_tcp_socket, int, new_tcp_socket_count, SCTXSOCK_TAG); memcpy(new_tcp_socket, g_server_context.tcp_socket, sizeof(int) * g_server_context.tcp_socket_count); memset(&new_tcp_socket[g_server_context.tcp_socket_count], 0xff, sizeof(int) * (new_tcp_socket_count - g_server_context.tcp_socket_count)); struct addrinfo **old_tcp_interface = g_server_context.tcp_interface; int *old_tcp_socket = g_server_context.tcp_socket; g_server_context.tcp_interface = new_tcp_interface; g_server_context.tcp_socket = new_tcp_socket; g_server_context.tcp_interface_count = new_tcp_interface_count; g_server_context.tcp_socket_count = new_tcp_socket_count; free(old_tcp_socket); free(old_tcp_interface); } #endif static void server_context_socket_name_free_cb(void *p) { struct itf_name* itf = (struct itf_name*)p; if(itf != NULL) { free(itf->name); free(itf); } } static void server_context_socket_name_ensure(u16 s) { ptr_vector_ensures(&server_context_socket_name, s + 1); for(s32 i = ptr_vector_size(&server_context_socket_name); i < ptr_vector_capacity(&server_context_socket_name); i++) { struct itf_name *tmp; MALLOC_OBJECT_OR_DIE(tmp, struct itf_name, ITFNAME_TAG); tmp->name = NULL; tmp->name_len = 0; ptr_vector_set(&server_context_socket_name, i, tmp); } server_context_socket_name.offset = MAX(s, server_context_socket_name.offset); } static void server_context_set_socket_name_to(u16 s, const char *text) { server_context_socket_name_ensure(s); #if DEBUG log_debug("socket #%d is named '%s'", s, text); #endif struct itf_name *tmp = server_context_socket_name.data[s]; if(tmp->name != NULL) { free(tmp->name); } tmp->name = strdup(text); tmp->name_len = strlen(text); } static void server_context_set_socket_name(u16 s, struct sockaddr *sa) { char buffer[64]; switch(sa->sa_family) { case AF_INET: { struct sockaddr_in *ipv4 = (struct sockaddr_in*)sa; if(inet_ntop(ipv4->sin_family, &ipv4->sin_addr, buffer, sizeof(buffer)) == NULL) { strcpy(buffer, "ipv4?"); // big enough } break; } case AF_INET6: { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6*)sa; if(inet_ntop(ipv6->sin6_family, &ipv6->sin6_addr, buffer, sizeof(buffer)) == NULL) { strcpy(buffer, "ipv6?"); // big enough } break; } default: { strcpy(buffer, "?"); // big enough break; } } server_context_set_socket_name_to(s, buffer); } /** * Appends the name of the socket s to the buffer. * The buffer has to be big enough, no size test is performed. * * @param buffer * @param s * * @return the length of the name */ u32 server_context_append_socket_name(char *buffer, u16 s) { if(s < server_context_socket_name.size) { struct itf_name *tmp = server_context_socket_name.data[s]; memcpy(buffer, tmp->name, tmp->name_len); return tmp->name_len; } else { return 0; } } /** * Closes all server sockets (UDP/TCP) */ void server_context_close() { ya_result ret; log_info("closing sockets"); if(g_server_context.udp_socket != NULL) { for(u32 i = 0; i < g_server_context.udp_socket_count; ++i) { if(g_server_context.udp_socket[i] != -1) { if(ISOK(ret = fd_getsockettype(g_server_context.udp_socket[i]))) { close_ex(g_server_context.udp_socket[i]); } else { #if 0 /* fix */ #else log_debug("server: could not close UDP socket %i: %r", g_server_context.udp_socket[i], ret); #endif } g_server_context.udp_socket[i] = -1; } } } if(g_server_context.tcp_socket != NULL) { for(u32 i = 0; i < g_server_context.tcp_socket_count; ++i) { if(g_server_context.tcp_socket[i] != -1) { if(ISOK(ret = fd_getsockettype(g_server_context.tcp_socket[i]))) { close_ex(g_server_context.tcp_socket[i]); } else { #if 0 /* fix */ #else log_debug("server: could not close TCP socket %i: %r", g_server_context.tcp_socket[i], ret); #endif } } g_server_context.tcp_socket[i] = -1; } } } /** \brief Closes all sockets and remove pid file * * @param[in] config * @param[in] server_context * * @retval OK * @return otherwise log_quit will stop the program */ void server_context_stop() { /* ------------------------------------------------------------ */ /** * @note It takes too much time to properly release the database for big zones. * All this to release the memory to the system anyway. * It is thus better to skip this. * The database unload should only be used for scripting & debugging (if the database structure is corrupted for any reason, * the unload will crash) * * database_finalize does NOT release the memory of the database, it just destroys threads */ #if DEBUG log_info("server_context_stop()"); #endif server_context_close(); if(g_server_context.udp_interface != NULL) { for(u32 i = 0; i < g_server_context.udp_interface_count; ++i) { if(g_server_context.udp_interface[i] != NULL) { free(g_server_context.udp_interface[i]->ai_addr); free(g_server_context.udp_interface[i]); // not obtained through getaddrinfo g_server_context.udp_interface[i] = NULL; //memset(&g_server_context.udp_interface[i], 0, sizeof(g_server_context.udp_interface[i])); } } } if(g_server_context.tcp_interface != NULL) { for(u32 i = 0; i < g_server_context.tcp_interface_count; ++i) { if(g_server_context.tcp_interface[i] != NULL) { free(g_server_context.tcp_interface[i]->ai_addr); free(g_server_context.tcp_interface[i]); // not obtained through getaddrinfo g_server_context.tcp_interface[i] = NULL; //memset(&g_server_context.tcp_interface[i], 0, sizeof(g_server_context.tcp_interface[i])); } } } ptr_vector_callback_and_clear(&server_context_socket_name, server_context_socket_name_free_cb); ptr_vector_destroy(&server_context_socket_name); free(g_server_context.tcp_socket); g_server_context.tcp_socket = NULL; g_server_context.tcp_socket_count = 0; free(g_server_context.udp_socket); g_server_context.udp_socket = NULL; g_server_context.udp_socket_count = 0; free(g_server_context.tcp_interface); g_server_context.tcp_interface = NULL; g_server_context.tcp_interface_count = 0; free(g_server_context.udp_interface); g_server_context.udp_interface = NULL; g_server_context.udp_interface_count = 0; if(g_server_context.listen != NULL) { for(u32 i = 0; i < g_server_context.listen_count; ++i) { host_address_delete(g_server_context.listen[i]); } free(g_server_context.listen); g_server_context.listen = NULL; } g_server_context.listen_count = 0; g_server_context.udp_unit_per_interface = 0; g_server_context.tcp_unit_per_interface = 0; g_server_context.thread_per_udp_worker_count = 1; g_server_context.thread_per_tcp_worker_count = 1; g_server_context.reuse = 0; g_server_context.ready = 0; config_update_network_done = FALSE; /* Let the scheduler-bound tasks finish to communicate (else they will block trying) */ #ifdef NEBUG log_debug("cleaning up"); logger_flush(); #endif /** @note: server_context_clear has to free server_context struct */ } /** \brief Initialize sockets and copy the config parameters into server_context_t * * @param[in] config * @param[out] server_context * * @retval OK * @return otherwise log_quit will stop the program */ // ai_family ai_addr ai_addrlen // count * (data_len, data) #if HAS_SOCKET_SERVER static int server_context_new_socket(struct addrinfo *addr, int sock_type, bool reuse_port) { #if !defined(SO_REUSEPORT) if(reuse_port) { log_err("reuseport has been requested but this feature is not available"); return FEATURE_NOT_SUPPORTED; // feature not available on this system } #endif ya_result ret; socket_server_opensocket_s ctx; if(FAIL(ret = socket_server_opensocket_init(&ctx, addr, sock_type))) { return ret; } const int on = 1; //socket_server_opensocket_setopt(socket_server_opensocket_s *ctx, int level, int optname, void* opt, socklen_t optlen) if(addr->ai_family == AF_INET6) { //static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; //const struct sockaddr_in6 *addr_v6 = (const struct sockaddr_in6*)addr->ai_addr->sa_data; //is_any = memcmp(&addr_v6->sin6_addr, &in6addr_any, 16) == 0; socket_server_opensocket_setopt(&ctx, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); if(sock_type == SOCK_DGRAM) { /* * @note https://stackoverflow.com/questions/46353380/invalid-argument-error-for-sendmsg-on-some-freebsd-systems * It turns out FreeBSD is very picky when it allows the use of IP_SENDSRCADDR on a UDP socket. * If the socket is bound to INADDR_ANY my code works fine. If the socket is bound to a single IP, * then sendmsg() returns EINVAL (invalid argument). * * ... * * Note that it's not the issue that has been reported 202102xx on GitHub. */ #if __FreeBSD__ if(addr_info_is_any(addr)) { #endif socket_server_opensocket_setopt_ignore_error(&ctx, IPPROTO_IP, DSTADDR_SOCKOPT, &on, sizeof(on)); #if __FreeBSD__ } #endif // #if __FreeBSD__ if(addr_info_is_any(addr)) { socket_server_opensocket_setopt_ignore_error(&ctx, IPPROTO_IPV6, DSTADDR_SOCKOPT, &on, sizeof(on)); } #else socket_server_opensocket_setopt(&ctx, IPPROTO_IPV6, DSTADDR_SOCKOPT, &on, sizeof(on)); #endif // socket_server_opensocket_setopt_ignore_result(&ctx, IPPROTO_IPV6, DSTADDR6_SOCKOPT, &on, sizeof(on)); #if WIN32 #else socket_server_opensocket_setopt(&ctx, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); #endif } } else { const struct sockaddr_in *addr_v4 = (const struct sockaddr_in*)addr->ai_addr->sa_data; bool is_any = (addr_v4->sin_addr.s_addr == INADDR_ANY); if(sock_type == SOCK_DGRAM) { if(is_any) { socket_server_opensocket_setopt(&ctx, IPPROTO_IP, DSTADDR_SOCKOPT, &on, sizeof(on)); } } } socket_server_opensocket_setopt(&ctx, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); #if defined(SO_REUSEPORT) if(reuse_port) { socket_server_opensocket_setopt(&ctx, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)); } #endif #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT) /* * @note 20190315 edf -- patch received 20190323 from daisuke.higashi@gmail.com * modified to go through the socket server */ /* * Linux 3.15 has IP_PMTUDISC_OMIT which makes sockets * ignore PMTU information and send packets with DF=0. * Fragmentation is allowed if and only if the packet * size exceeds the outgoing interface MTU or the packet * encounters smaller MTU link in network. * This mitigates DNS fragmentation attacks by preventing * forged PMTU information. * FreeBSD already has same semantics without setting * the option. */ if(sock_type == SOCK_DGRAM) { int action_omit = IP_PMTUDISC_OMIT; socket_server_opensocket_setopt(&ctx, IPPROTO_IP, IP_MTU_DISCOVER, &action_omit, sizeof(action_omit)); } #endif /* IP_MTU_DISCOVER && IP_PMTUDISC_OMIT */ int sockfd = socket_server_opensocket_open(&ctx); if(sockfd >= 0) { fd_setcloseonexec(sockfd); } else { if(YA_ERROR_BASE(sockfd) == ERRNO_ERROR_BASE) { errno = YA_ERROR_CODE(sockfd); } } return sockfd; } #else static int server_context_new_socket(struct addrinfo *udp_addr, int family, bool reuse_port) { ya_result ret; int sockfd; static const int on = 1; if(FAIL(sockfd = socket(udp_addr->ai_family, family, 0))) { ret = ERRNO_ERROR; ttylog_err("failed to create socket %{sockaddr}: %r", udp_addr->ai_addr, ret); return ret; } /** * Associate the name of the interface to the socket */ /** * This is distribution/system dependent. With this we ensure that IPv6 will only listen on IPv6 addresses. */ if(udp_addr->ai_family == AF_INET6) { if(FAIL(setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&on, sizeof(on)))) { ret = ERRNO_ERROR; ttylog_err("failed to force IPv6 on %{sockaddr}: %r", udp_addr->ai_addr, ret); close(sockfd); return ret; } if(family == SOCK_DGRAM) { if(FAIL(setsockopt(sockfd , IPPROTO_IPV6, DSTADDR6_SOCKOPT, &on, sizeof(on)))) { ret = ERRNO_ERROR; ttylog_err("failed to setup alias handling on %{sockaddr}: %r", udp_addr->ai_addr, ret); close(sockfd); return ret; } socket_server_opensocket_setopt(&ctx, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); } } else { if(family == SOCK_DGRAM) { if(FAIL(setsockopt(sockfd , IPPROTO_IP, DSTADDR_SOCKOPT, &on, sizeof(on)))) { ret = ERRNO_ERROR; ttylog_err("failed to setup alias handling on %{sockaddr}: %r", udp_addr->ai_addr, ret); close(sockfd); return ret; } } } if(FAIL(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on)))) { ret = ERRNO_ERROR; ttylog_err("failed to reuse address %{sockaddr}: %r", udp_addr->ai_addr, ret); close(sockfd); return ret; } if(reuse_port) { #ifdef SO_REUSEPORT if(FAIL(setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (void *) &on, sizeof(on)))) { ret = ERRNO_ERROR; ttylog_err("failed to use reuse feature: %r", ret); close(sockfd); return ret; } #else return MAKE_ERRNO_ERROR(ENOTSUP); #endif } if(family == SOCK_DGRAM) { setsockopt(sockfd, IPPROTO_IP, DSTADDR_SOCKOPT, &on, sizeof(on)); #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT) /* * @note 20190315 edf -- patch received 20190323 from daisuke.higashi@gmail.com */ /* * Linux 3.15 has IP_PMTUDISC_OMIT which makes sockets * ignore PMTU information and send packets with DF =0. * Fragmentation is allowed if and only if the packet * size exceeds the outgoing interface MTU or the packet * encounters smaller MTU link in network. * This mitigates DNS fragmentation attacks by preventing * forged PMTU information. * FreeBSD already has same semantics without setting * the option. */ int action_omit = IP_PMTUDISC_OMIT; (void)setsockopt(sockfd, IPPROTO_IP,IP_MTU_DISCOVER, &action_omit, sizeof(action_omit)); #endif /* IP_MTU_DISCOVER && IP_PMTUDISC_OMIT */ } if(FAIL(bind(sockfd, (struct sockaddr*)udp_addr->ai_addr, udp_addr->ai_addrlen))) { ret = ERRNO_ERROR; ttylog_err("failed to bind address %{sockaddr}e: %r", udp_addr->ai_addr, ret); close(sockfd); return ret; } return sockfd; } #endif void server_context_destroy(); static ya_result server_context_create_append_all_ipv4_callback(const char* itf_name, const socketaddress* sa, void* data) { (void)itf_name; ya_result ret = SUCCESS; host_address *ha_list = (host_address *)data; if(sa->sa.sa_family == AF_INET) { ret = host_address_append_sockaddr_with_port(ha_list, sa, ha_list->port); } return ret; } static ya_result server_context_create_append_all_ipv6_callback(const char* itf_name, const socketaddress* sa, void* data) { (void)itf_name; ya_result ret = SUCCESS; host_address *ha_list = (host_address *)data; if(sa->sa.sa_family == AF_INET6) { u16 first_bits = GET_U16_AT(sa->sa6.sin6_addr); if((first_bits & NU16(0xffc0)) != NU16(0xfe80)) { ret = host_address_append_sockaddr_with_port(ha_list, sa, ha_list->port); } } return ret; } host_address* server_context_get_real_listen_addresses_from_config() { ya_result ret; if((g_config == NULL) || (g_config->listen == NULL)) { log_err("There is no listen address list instance."); return NULL; } host_address *real_listen = host_address_copy_list(g_config->listen); for(host_address *ha = real_listen; ha != NULL; ha = ha->next) { log_debug("configured to listen to %{hostaddr}", ha); } for(host_address *ha = g_config->do_not_listen; ha != NULL; ha = ha->next) { log_debug("configured to not listen to %{hostaddr}", ha); } // if ANY addresses need to be splitted, do it bool split_any = !host_address_empty(g_config->do_not_listen); if(split_any) { for(host_address *ha = real_listen; ha != NULL; ) { if(host_address_is_any(ha)) { log_debug("listen address %{hostaddr} will be divided into interfaces", ha); host_address *removed = host_address_remove_host_address(&real_listen, ha); // the dummy is needed in case the above operation completely empties the list host_address list_head_with_default_port; ZEROMEMORY(&list_head_with_default_port, sizeof(list_head_with_default_port)); list_head_with_default_port.next = real_listen; if(ha->port != 0) { list_head_with_default_port.port = ha->port; } else { list_head_with_default_port.port = ntohs(g_config->server_port_value); } // split if(ha->version == HOST_ADDRESS_IPV4) { ret = network_interfaces_forall(server_context_create_append_all_ipv4_callback, &list_head_with_default_port); } else if(ha->version == HOST_ADDRESS_IPV6) { ret = network_interfaces_forall(server_context_create_append_all_ipv6_callback, &list_head_with_default_port); } else { ret = INVALID_ARGUMENT_ERROR; } real_listen = list_head_with_default_port.next; if(FAIL(ret)) { log_err("an unexpected error occurred while scanning the network interfaces: %r. Because of this, some addresses may be missing.", ret); } host_address_delete(removed); ha = real_listen; } else { ha = ha->next; } } for(host_address *ha = real_listen; ha != NULL; ha = ha->next) { log_debug("divided to listen to %{hostaddr}", ha); } } // remove duplicates for(host_address *ha = real_listen; ha != NULL; ha = ha->next) { if(ha->next != NULL) { host_address *removed; for(;;) { removed = host_address_remove_host_address(&ha->next, ha); if(removed == NULL) { break; } log_debug("removed %{hostaddr} from the listen list (duplicate)", removed); host_address_delete(removed); } } } for(host_address *ha = real_listen; ha != NULL; ha = ha->next) { log_debug("compacted to listen to %{hostaddr}", ha); } // remove do-not-listen addresses for(host_address *ha = g_config->do_not_listen; ha != NULL; ha = ha->next) { for(;;) { host_address *removed = host_address_remove_host_address(&real_listen, ha); if(removed == NULL) { break; } log_debug("removed %{hostaddr} from the listen list (excluded)", removed); host_address_delete(removed); } } return real_listen; } int server_context_create() { ya_result ret = SUCCESS; if(g_server_context.ready == 0) { return INVALID_STATE_ERROR; // unacceptable } if(config_update_network_done) { return SUCCESS; } #ifndef SO_REUSEPORT int total_udp_socket_count_for_interface = g_server_context.udp_socket_count / g_server_context.udp_interface_count; /* * If the system does not support SO_REUSEPORT and only one socket is open per interface, then it's not a problem : * We just have to disable the reuse request and proceed. */ if(g_server_context.reuse) { if(total_udp_socket_count_for_interface == 1) { g_server_context.reuse = FALSE; } else { return INVALID_STATE_ERROR; // unacceptable } } #endif config_update_network_done = TRUE; log_info("setting network up"); host_address *real_listen = server_context_get_real_listen_addresses_from_config(); for(host_address *ha = real_listen; ha != NULL; ha = ha->next) { log_info("will listen to %{hostaddr}", ha); } g_server_context.listen_count = host_address_count(real_listen); logger_flush(); // Copy stuff from the config file and command line options MALLOC_OBJECT_ARRAY_OR_DIE(g_server_context.listen, host_address*, g_server_context.listen_count, HOSTADDR_TAG); { host_address *ha = real_listen; for(u32 i = 0; i < g_server_context.listen_count; ++i, ha = ha->next) { assert(ha != NULL); g_server_context.listen[i] = host_address_copy(ha); /// note: 20151207 edf -- a copy should be the way to go } } host_address_delete_list(real_listen); real_listen = NULL; g_server_context.udp_interface_count = g_server_context.listen_count; g_server_context.tcp_interface_count = g_server_context.listen_count; g_server_context.udp_socket_count = g_server_context.udp_interface_count; if(g_server_context.reuse) { g_server_context.udp_socket_count *= g_server_context.udp_unit_per_interface; // times workers } if(g_server_context.worker_backlog_queue_size < 4096) { g_server_context.worker_backlog_queue_size = 4096; } server_context_addresses_allocate(); int udp_sockfd_idx = 0; int tcp_sockfd_idx = 0; for(u32 intf_idx = 0; intf_idx < g_server_context.listen_count; ++intf_idx) { host_address *ha = g_server_context.listen[intf_idx]; // VS false positive: it's kind of nonsense /* Warning C6385 Reading invalid data from 'g_server_context.listen': the readable size is 'sizeof(host_address *)*((g_server_context.listen_count))' bytes, but '16' bytes may be read.yadifa line 708 */ host_address2addrinfo(ha, &g_server_context.udp_interface[intf_idx]); host_address2addrinfo(ha, &g_server_context.tcp_interface[intf_idx]); /* The host_address list has an IPv4/IPv6 address and a port */ // udp { struct addrinfo *udp_addr = g_server_context.udp_interface[intf_idx]; for(u32 n = 0; n < g_server_context.udp_unit_per_interface; ++n) { int sockfd; log_debug("UDP listener socket for %{sockaddr} will be opened %s", udp_addr->ai_addr, (g_server_context.reuse)?"(REUSEPORT)":""); if(ISOK(sockfd = server_context_new_socket(udp_addr, SOCK_DGRAM, g_server_context.reuse))) { server_context_set_socket_name(sockfd, (struct sockaddr*)udp_addr->ai_addr); g_server_context.udp_socket[udp_sockfd_idx++] = sockfd; log_info("UDP listener socket ready for %{sockaddr}: %i %s", udp_addr->ai_addr, sockfd, (g_server_context.reuse)?"(REUSEPORT)":""); } else { ret = sockfd; ttylog_err("UDP listener failed to listen to %{sockaddr}: %r", udp_addr->ai_addr, ret); server_context_destroy(); return ret; } } } // tcp { struct addrinfo *tcp_addr = g_server_context.tcp_interface[intf_idx]; log_debug("TCP listener socket for %{sockaddr} will be opened", tcp_addr->ai_addr); for(u32 n = 0; n < g_server_context.tcp_unit_per_interface; ++n) { int sockfd; if(ISOK(sockfd = server_context_new_socket(tcp_addr, SOCK_STREAM, FALSE))) { fd_setcloseonexec(sockfd); server_context_set_socket_name(sockfd, (struct sockaddr*)tcp_addr->ai_addr); /* For TCP only, listen to it... */ if(FAIL(listen(sockfd, g_config->tcp_queue_size))) { ret = ERRNO_ERROR; ttylog_err("TCP listener failed to listen to %{sockaddr}: %r", tcp_addr->ai_addr, ret); server_context_destroy(); return ret; } #if defined(SOL_TCP) && defined(TCP_FASTOPEN) int queue_size = g_config->tcp_queue_size; setsockopt(sockfd, SOL_TCP, TCP_FASTOPEN, &queue_size, sizeof(queue_size)); #endif g_server_context.tcp_socket[tcp_sockfd_idx++] = sockfd; log_info("TCP listener socket ready for %{sockaddr}: %i", tcp_addr->ai_addr, sockfd); } else { server_context_destroy(); return sockfd; } } } } return SUCCESS; } void server_context_destroy() { server_context_stop(); } bool server_context_matches_config() { /** * If the number of addresses is the same and * if all the addresses defined in the configuration are matching one address in the context * then the configuration are matched. */ host_address *real_listen = host_address_copy_list(g_config->listen); u32 interfaces_count = host_address_count(real_listen); if(g_server_context.listen_count != interfaces_count) { host_address_delete_list(real_listen); return FALSE; } for(u32 i = 0; i < g_server_context.listen_count; ++i) { bool match = FALSE; host_address *ha = real_listen; while(ha != NULL) { if(host_address_equals(g_server_context.listen[i], ha)) { match = TRUE; break; } ha = ha->next; } if(!match) { host_address_delete_list(real_listen); return FALSE; } } host_address_delete_list(real_listen); return TRUE; } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server_process_message_udp.c0000644000000000000000000000013214505005533024457 xustar000000000000000030 mtime=1695812443.538997885 30 atime=1695812445.784030039 30 ctime=1695812495.665744445 yadifa-2.6.5-11201/sbin/yadifad/server_process_message_udp.c0000664000374500037450000010563214505005533024430 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ // keep this order --> #include "server-config.h" #include #include #include "server.h" #include "process_class_ch.h" #include "dynupdate_query_service.h" #include "notify.h" #if DNSCORE_HAS_CTRL #include "ctrl_notify.h" #endif #include "log_query.h" #include "log_statistics.h" static zdb *database = NULL; void server_process_message_udp_set_database(zdb *db) { database = db; } int server_process_message_udp(network_thread_context_base_t *ctx, message_data *mesg) { server_statistics_t * const local_statistics = ctx->statisticsp; local_statistics->udp_input_count++; ya_result ret; int fd = ctx->sockfd; #if DEBUG log_debug("server_process_message_udp(%i, %i)", ctx->idx, fd); #endif switch(message_get_opcode(mesg)) { case OPCODE_QUERY: { if(ISOK(ret = message_process_query(mesg))) { message_edns0_clear_undefined_flags(mesg); switch(message_get_query_class(mesg)) { case CLASS_IN: { log_query(ctx->sockfd, mesg); local_statistics->udp_queries_count++; switch(message_get_query_type(mesg)) { default: { #if HAS_RRL_SUPPORT ya_result rrl = database_query_with_rrl(database, mesg); local_statistics->udp_referrals_count += message_get_referral(mesg); local_statistics->udp_fp[message_get_status(mesg)]++; switch(rrl) { case RRL_SLIP: { local_statistics->rrl_slip++; break; } case RRL_DROP: { local_statistics->rrl_drop++; return SUCCESS_DROPPED; } case RRL_PROCEED_DROP: { local_statistics->rrl_drop++; break; } } #else database_query(database, mesg); local_statistics->udp_referrals_count += message_get_referral(mesg); local_statistics->udp_fp[message_get_status(mesg)]++; #endif break; } case TYPE_IXFR: // reply with a truncate to force a TCP query { message_set_truncated_answer(mesg); message_set_query_answer_authority_additional_counts_ne(mesg, 0, 0, 0, 0); message_set_size(mesg, DNS_HEADER_LENGTH); local_statistics->udp_fp[FP_IXFR_UDP]++; break; } case TYPE_AXFR: case TYPE_OPT: { message_make_error(mesg, FP_INCORR_PROTO); local_statistics->udp_fp[FP_INCORR_PROTO]++; break; } } // switch query type break; } // query class IN case CLASS_CH: { class_ch_process(mesg); // thread-safe local_statistics->udp_fp[message_get_status(mesg)]++; break; } // query class CH default: { message_set_status(mesg, FP_NOT_SUPP_CLASS); message_transform_to_error(mesg); #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) /* NOTE: the TSIG information is in mesg */ { tsig_sign_answer(mesg); } #endif local_statistics->udp_fp[FP_NOT_SUPP_CLASS]++; break; } } // query class } // if message process succeeded else ... else // an error occurred : no query to be done at all { if(message_get_query_count_ne(mesg) == NETWORK_ONE_16) { const u8 *canonized_fqdn = message_get_canonised_fqdn(mesg); if((ret != TSIG_BADTIME) && (ret != TSIG_BADSIG)) // BADKEY doesn't set the time nor the name { if(dnsname_verify_charspace(canonized_fqdn)) { log_notice("query (%04hx) [%02x|%02x] %{dnsname} %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), canonized_fqdn, message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } else { log_notice("query (%04hx) [%02x|%02x] %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } } else { s64 epoch = message_tsig_get_epoch(mesg); s64 fudge = message_tsig_get_fudge(mesg); if(dnsname_verify_charspace(canonized_fqdn)) { if(message_has_tsig(mesg)) { log_notice("query (%04hx) [%02x|%02x] %{dnsname} %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu key=%{dnsname} epoch=%lli (%T) +-%llis", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), canonized_fqdn, message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg), message_tsig_get_name(mesg), epoch, epoch, fudge); } else { log_notice("query (%04hx) [%02x|%02x] %{dnsname} %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), canonized_fqdn, message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } } else { if(message_has_tsig(mesg)) { log_notice("query (%04hx) [%02x|%02x] %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu key=%{dnsname} epoch=%lli (%T) +-%llis", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg), message_tsig_get_name(mesg), epoch, epoch, fudge); } else { log_notice("query (%04hx) [%02x|%02x] %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } } } } else { log_notice("query (%04hx) [%02x|%02x] QC=%hu AN=%hu NS=%hu AR=%hu : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), message_get_query_count(mesg), // QC message_get_answer_count(mesg), // AC message_get_authority_count(mesg), // NS message_get_additional_count(mesg), // AR RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } local_statistics->udp_fp[message_get_status(mesg)]++; if((ret == UNPROCESSABLE_MESSAGE) && (g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE)) { log_memdump_ex(MODULE_MSG_HANDLE, MSG_WARNING, message_get_buffer(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_BUFFER); } /* * If not FE, or if we answer FE * * ... && (message_is_query(mesg) ??? and if there the query number is > 0 ??? */ if( (ret != INVALID_MESSAGE) && ((message_get_status(mesg) != RCODE_FORMERR) || ((g_config->server_flags & SERVER_FL_ANSWER_FORMERR) != 0))) { message_edns0_clear_undefined_flags(mesg); if(!message_has_tsig(mesg) && (message_get_status(mesg) != FP_RCODE_NOTAUTH)) { message_transform_to_error(mesg); } } else { local_statistics->udp_dropped_count++; return SUCCESS_DROPPED; } } break; } // case query case OPCODE_NOTIFY: { if(ISOK(ret = message_process(mesg))) { message_edns0_clear_undefined_flags(mesg); switch(message_get_query_class(mesg)) { case CLASS_IN: { ya_result return_value; local_statistics->udp_notify_input_count++; log_info("notify (%04hx) %{dnsname} (%{sockaddr})", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_sender_sa(mesg)); bool answer = message_isanswer(mesg); return_value = notify_process(mesg); // thread-safe local_statistics->udp_fp[message_get_status(mesg)]++; if(FAIL(return_value)) { log_err("notify (%04hx) %{dnsname} failed : %r", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), return_value); if(answer) { return SUCCESS_DROPPED; } if(!message_has_tsig(mesg)) { message_transform_to_error(mesg); } break; } else { if(answer) { return SUCCESS_DROPPED; } } break; } // notify class IN default: { log_warn("notify [%04hx] %{dnsname} %{dnstype} %{dnsclass} (%{sockaddrip}) : unsupported class", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), message_get_sender_sa(mesg)); message_make_error(mesg, FP_NOT_SUPP_CLASS); local_statistics->udp_fp[FP_NOT_SUPP_CLASS]++; break; } } // notify class } // if message process succeeded else // an error occurred : no query to be done at all { if(message_get_query_count_ne(mesg) == NETWORK_ONE_16) { const u8 *canonized_fqdn = message_get_canonised_fqdn(mesg); if(canonized_fqdn != NULL) { if((ret != TSIG_BADTIME) && (ret != TSIG_BADSIG)) // BADKEY doesn't set the time nor the name { log_notice("notify (%04hx) [%02x|%02x] %{dnsname} %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), canonized_fqdn, message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } else { s64 epoch = message_tsig_get_epoch(mesg); s64 fudge = message_tsig_get_fudge(mesg); if(message_has_tsig(mesg)) { log_notice("notify (%04hx) [%02x|%02x] %{dnsname} %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu key=%{dnsname} epoch=%lli (%T) +-%llis", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), canonized_fqdn, message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg), message_tsig_get_name(mesg), epoch, epoch, fudge); } else { log_notice("notify (%04hx) [%02x|%02x] %{dnsname} %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), canonized_fqdn, message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } } } else { log_notice("notify (%04hx) [%02x|%02x] ? %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } } else { log_notice("notify (%04hx) [%02x|%02x] QC=%hu AN=%hu NS=%hu AR=%hu : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), message_get_query_count(mesg), // QC message_get_answer_count(mesg), // AC message_get_authority_count(mesg), // NS message_get_additional_count(mesg), // AR RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } local_statistics->udp_fp[message_get_status(mesg)]++; if(ret == UNPROCESSABLE_MESSAGE && (g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE)) { log_memdump_ex(MODULE_MSG_HANDLE, MSG_WARNING, message_get_buffer(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_BUFFER); } /* * If not FE, or if we answer FE * * ... && (message_is_query(mesg) ??? and if there the query number is > 0 ??? */ if( (ret != INVALID_MESSAGE) && ((message_get_status(mesg) != RCODE_FORMERR) || ((g_config->server_flags & SERVER_FL_ANSWER_FORMERR) != 0))) { message_edns0_clear_undefined_flags(mesg); if(!message_has_tsig(mesg) && (message_get_status(mesg) != FP_RCODE_NOTAUTH)) { message_transform_to_error(mesg); } } else { local_statistics->udp_dropped_count++; return SUCCESS_DROPPED; } } break; } // case notify case OPCODE_UPDATE: { if(ISOK(ret = message_process(mesg))) { message_edns0_clear_undefined_flags(mesg); switch(message_get_query_class(mesg)) { case CLASS_IN: { #if HAS_DYNUPDATE_SUPPORT /** * @note It's the responsibility of the called function (or one of its callees) to ensure * this does not take much time and thus to trigger a background task with the * scheduler if needed. */ local_statistics->udp_updates_count++; if(ISOK(dynupdate_query_service_enqueue(database, mesg, fd))) { return SUCCESS_DROPPED; // NOT break; the processing will be handled in another thread } else { log_warn("update [%04hx] %{dnsname} %{dnstype} %{dnsclass} (%{sockaddrip}) : cannot enqueue the update message", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), message_get_sender_sa(mesg)); message_make_error(mesg, FP_RCODE_SERVFAIL); local_statistics->udp_fp[FP_RCODE_SERVFAIL]++; return SUCCESS; // needs to be >= 0: the server will send the SERVFAIL message } #else message_make_error(mesg, FP_FEATURE_DISABLED); local_statistics->udp_fp[FP_FEATURE_DISABLED]++; break; #endif } // update class IN default: { log_warn("update [%04hx] %{dnsname} %{dnstype} %{dnsclass} (%{sockaddrip}) : unsupported class", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), message_get_sender_sa(mesg)); message_make_error(mesg, FP_NOT_SUPP_CLASS); local_statistics->udp_fp[FP_NOT_SUPP_CLASS]++; break; } } // update class } // if message process succeeded else // an error occurred : no query to be done at all { if(message_get_query_count_ne(mesg) == NETWORK_ONE_16) { const u8 *canonized_fqdn = message_get_canonised_fqdn(mesg); if(canonized_fqdn != NULL) { if((ret != TSIG_BADTIME) && (ret != TSIG_BADSIG)) // BADKEY doesn't set the time nor the name { log_notice("update (%04hx) [%02x|%02x] %{dnsname} %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), canonized_fqdn, message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } else { s64 epoch = message_tsig_get_epoch(mesg); s64 fudge = message_tsig_get_fudge(mesg); if(message_has_tsig(mesg)) { log_notice("update (%04hx) [%02x|%02x] %{dnsname} %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu key=%{dnsname} epoch=%lli (%T) +-%llis", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), canonized_fqdn, message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg), message_tsig_get_name(mesg), epoch, epoch, fudge); } else { log_notice("update (%04hx) [%02x|%02x] %{dnsname} %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), canonized_fqdn, message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } } } else { log_notice("update (%04hx) [%02x|%02x] ? %{dnstype} %{dnsclass} : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), RCODE_ERROR_CODE(message_get_status(mesg)), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } } else { log_notice("update (%04hx) [%02x|%02x] QC=%hu AN=%hu NS=%hu AR=%hu : %r (%r) (%{sockaddrip}) size=%hu", ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), message_get_query_count(mesg), // QC message_get_answer_count(mesg), // AC message_get_authority_count(mesg), // NS message_get_additional_count(mesg), // AR RCODE_ERROR_CODE(message_get_status(mesg)), ret, message_get_sender_sa(mesg), message_get_size_u16(mesg)); } local_statistics->udp_fp[message_get_status(mesg)]++; if((ret == UNPROCESSABLE_MESSAGE) && (g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE)) { log_memdump_ex(MODULE_MSG_HANDLE, MSG_WARNING, message_get_buffer(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_BUFFER); } /* * If not FE, or if we answer FE * * ... && (message_is_query(mesg) ??? and if there the query number is > 0 ??? */ if( (ret != INVALID_MESSAGE) && ((message_get_status(mesg) != RCODE_FORMERR) || ((g_config->server_flags & SERVER_FL_ANSWER_FORMERR) != 0))) { message_edns0_clear_undefined_flags(mesg); if(!message_has_tsig(mesg) && (message_get_status(mesg) != FP_RCODE_NOTAUTH)) { message_transform_to_error(mesg); } } else { local_statistics->udp_dropped_count++; return SUCCESS; } } break; } // case update case (15<worker) || (ctx->must_stop)) // will fallthrough on purpose { return STOPPED_BY_APPLICATION_SHUTDOWN; } FALLTHROUGH } default: { log_notice("opcode-%i (%04hx) [%02x|%02x] QC=%hu AN=%hu NS=%hu AR=%hu (%{sockaddrip}) size=%hu", (u32)(message_get_opcode(mesg) >> OPCODE_SHIFT), ntohs(message_get_id(mesg)), message_get_flags_hi(mesg),message_get_flags_lo(mesg), message_get_query_count(mesg), // QC message_get_answer_count(mesg), // AC message_get_authority_count(mesg), // NS message_get_additional_count(mesg), // AR message_get_sender_sa(mesg), message_get_size_u16(mesg)); message_process_lenient(mesg); if(message_get_status(mesg) == RCODE_OK) // else a TSIG may have some complain { message_set_status(mesg, FP_RCODE_NOTIMP); message_update_answer_status(mesg); #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) { tsig_sign_answer(mesg); } #endif } local_statistics->udp_undefined_count++; if(ctx->must_stop) { return STOPPED_BY_APPLICATION_SHUTDOWN; // shutdown } if(g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE) { log_memdump_ex(MODULE_MSG_HANDLE, MSG_WARNING, message_get_buffer(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_BUFFER); } if((message_get_status(mesg) != RCODE_FORMERR) || ((g_config->server_flags & SERVER_FL_ANSWER_FORMERR) != 0)) { if(!message_has_tsig(mesg) && (message_get_status(mesg) != FP_RCODE_NOTAUTH)) { message_edns0_clear_undefined_flags(mesg); message_transform_to_error(mesg); } } else { local_statistics->udp_dropped_count++; return SUCCESS; } } } return SUCCESS; } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/signals.c0000644000000000000000000000013214505005533020477 xustar000000000000000030 mtime=1695812443.518997599 30 atime=1695812445.784030039 30 ctime=1695812495.667744474 yadifa-2.6.5-11201/sbin/yadifad/signals.c0000664000374500037450000001564314505005533020452 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #define _GNU_SOURCE 1 #include #include #include #include #include #if defined(__linux__) || defined(__gnu_hurd__) #define _GNU_SOURCE 1 //#include #include #include #elif defined(__sun) #include #endif #include #include #include #include #include #include #include #include "signals.h" #include "server_context.h" #include "server.h" #if DNSCORE_HAS_RRSIG_MANAGEMENT_SUPPORT && DNSCORE_HAS_DNSSEC_SUPPORT #include "database-service-zone-resignature.h" #endif #define MODULE_MSG_HANDLE g_server_logger #define MAXTRACE 128 #define LOGGER_REOPEN_MIN_PERIOD_US 1000000 ya_result database_store_all_zones_to_disk(); /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ static volatile time_t signal_task_logger_handle_reopen_last_active = 0; static void signal_task_reconfigure_reopen_log() { // TRY debug as else there is a risk of deadlock log_try_debug1("signal_task_reconfigure_reopen_log()"); u64 now = timeus(); if(now - signal_task_logger_handle_reopen_last_active > LOGGER_REOPEN_MIN_PERIOD_US) { signal_task_logger_handle_reopen_last_active = now; log_try_debug1("signal_task_reconfigure_reopen_log(): setting the sink"); logger_sink(); if(g_config->reloadable) { log_try_debug1("signal_task_reconfigure_reopen_log(): reloading configuration"); yadifad_config_update(g_config->config_file); } else { // TRY error as else there is a risk of deadlock log_try_err("cannot reopen configuration file(s): '%s' is outside of jail", g_config->config_file); } #if DEBUG log_try_debug1("signal_task_reconfigure_reopen_log(): reopening log files"); #endif logger_reopen(); if(!server_context_matches_config()) { log_try_debug1("network configuration has changed"); server_service_reconfigure(); } else { log_try_debug1("network configuration has not changed"); } #if DNSCORE_HAS_DNSSEC_SUPPORT && DNSCORE_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT database_service_zone_dnskey_set_alarms_on_all_zones(); #endif } #if DEBUG else { double dt = LOGGER_REOPEN_MIN_PERIOD_US - (now - signal_task_logger_handle_reopen_last_active); dt /= ONE_SECOND_US_F; log_try_debug1("signal_task_reconfigure_reopen_log(): ignore for %.3fs", dt); } #endif // TRY debug as else there is a risk of deadlock log_try_debug1("signal_task_reconfigure_reopen_log(): end"); } /***/ static void signal_task_database_store_all_zones_to_disk() { log_debug("signal_task_database_store_all_zones_to_disk()"); if(g_config->database != NULL) { database_store_all_zones_to_disk(); } log_debug("signal_task_database_store_all_zones_to_disk(): end"); } /**/ static void signal_task_shutdown() { #if DEBUG log_info("signal_task_shutdown()"); #else log_debug("signal_task_shutdown()"); #endif program_mode = SA_SHUTDOWN; if(!dnscore_shuttingdown()) { dnscore_shutdown(); program_mode = SA_SHUTDOWN; socket_server_finalize(); //notify_service_stop(); server_service_stop(); server_context_close(); #if DEBUG log_debug("stopping program"); #endif } log_debug("signal_task_shutdown(): end"); } static void signal_hup(u8 signum) { (void)signum; // that was a bad idea as logs may be full and this is the only way // to save the situation : // log_info("signal: HUP"); if(!dnscore_shuttingdown()) { signal_task_reconfigure_reopen_log(); } } static void signal_usr1(u8 signum) { (void)signum; log_info("signal: USR1"); if(!dnscore_shuttingdown()) { signal_task_database_store_all_zones_to_disk(); } } static void signal_usr2(u8 signum) { (void)signum; } static void signal_int(u8 signum) { (void)signum; log_info("signal: INT"); signal_task_shutdown(); signal_handler_stop(); #if DEBUG logger_flush(); #endif } static void signal_term(u8 signum) { (void)signum; log_info("signal: TERM"); signal_task_shutdown(); signal_handler_stop(); #if DEBUG logger_flush(); #endif } void signal_setup() { signal_handler_set(SIGHUP, signal_hup); signal_handler_set(SIGUSR1, signal_usr1); signal_handler_set(SIGUSR2, signal_usr2); signal_handler_set(SIGINT, signal_int); signal_handler_set(SIGTERM, signal_term); } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/zone.c0000644000000000000000000000013214505005533020012 xustar000000000000000030 mtime=1695812443.504997398 30 atime=1695812445.783030024 30 ctime=1695812495.669744502 yadifa-2.6.5-11201/sbin/yadifad/zone.c0000664000374500037450000017313514505005533017766 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup zone Routines for zone_data struct * @ingroup yadifad * @brief zone functions * * Implementation of routines for the zone_data struct * - add * - adjust * - init * - parse * - print * - remove database * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include /* or netinet/in.h */ #include #include #include #include #include #include #if DEBUG #include #endif #include // else we get a chicken-egg issue on the following include #if ZDB_HAS_DNSSEC_SUPPORT #include #include "dnssec-policy.h" #include #include #endif #include "server.h" #include "zone.h" #include "server_error.h" #include "config_error.h" #include "database-service.h" #include "zone-signature-policy.h" #define ZONEDATA_TAG 0x41544144454e4f5a #define ZDORIGIN_TAG 0x4e494749524f445a #define DEBUG_ARC 0 #ifndef NAME_MAX #define NAME_MAX 1024 #endif #define MODULE_MSG_HANDLE g_server_logger /* Zone file variables */ extern zone_data_set database_zone_desc; static mutex_t zone_desc_rc_mtx = MUTEX_INITIALIZER; #if DEBUG static u64_set zone_desc_tracked_set = U64_SET_EMPTY; static u64 zone_desc_next_id = 0; #endif static const char* type_to_name[4] = { "hint", "master", "slave", "stub" }; static const char *dnssec_to_name[4] = { "nosec", "nsec", "nsec3", "nsec3-optout" }; /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ void zone_set_lock(zone_data_set *dset) { group_mutex_lock(&dset->lock, GROUP_MUTEX_READ); } void zone_set_unlock(zone_data_set *dset) { group_mutex_unlock(&dset->lock, GROUP_MUTEX_READ); } void zone_set_writer_lock(zone_data_set *dset) { group_mutex_lock(&dset->lock, GROUP_MUTEX_WRITE); } void zone_set_writer_unlock(zone_data_set *dset) { group_mutex_unlock(&dset->lock, GROUP_MUTEX_WRITE); } #if HAS_DYNAMIC_PROVISIONING bool zone_data_is_clone(zone_desc_s *desc) { return (desc != NULL) && ((desc->dynamic_provisioning.flags & ZONE_CTRL_FLAG_CLONE) != 0); } #endif static int zone_dnsname_compare(const void *node_a, const void *node_b) { const u8 *m_a = (const u8*)node_a; const u8 *m_b = (const u8*)node_b; return dnsname_compare(m_a, m_b); } void zone_init(zone_data_set *dset) { dset->set.root = NULL; dset->set.compare = zone_dnsname_compare; group_mutex_init(&dset->lock); } void zone_finalize(zone_data_set *dset) { group_mutex_destroy(&dset->lock); dset->set.root = NULL; dset->set.compare = zone_dnsname_compare; } /** @brief Initializing zone_data variable * * The function not only initialize a new zone_data struct, but if needed * will add the struct to the linked list * * @param[in,out] dst the new zone_data struct * * @retval OK */ zone_desc_s * zone_alloc() { zone_desc_s *zone_desc; /* Alloc & clear zone_data structure */ ZALLOC_OBJECT_OR_DIE( zone_desc, zone_desc_s, ZONEDATA_TAG); ZEROMEMORY(zone_desc, sizeof(zone_desc_s)); bpqueue_init(&zone_desc->commands); mutex_init(&zone_desc->lock); cond_init(&zone_desc->lock_cond); zone_desc->qclass = CLASS_IN; #if ZDB_HAS_DNSSEC_SUPPORT #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT zone_desc->signature.sig_validity_interval = MAX_S32; zone_desc->signature.sig_validity_regeneration = MAX_S32; /* * The validity of newly generated signature will be off by at most this */ zone_desc->signature.sig_validity_jitter = MAX_S32; zone_desc->signature.scheduled_sig_invalid_first = MAX_S32; #if ZDB_HAS_MASTER_SUPPORT ptr_set_init(&zone_desc->dnssec_policy_processed_key_suites); zone_desc->dnssec_policy_processed_key_suites.compare = ptr_set_asciizp_node_compare; #endif #endif #endif zone_desc->rc = 1; #if DEBUG zone_desc->instance_time_us = timeus(); mutex_lock(&zone_desc_rc_mtx); zone_desc->instance_id = zone_desc_next_id++; u64_node* node = u64_set_insert(&zone_desc_tracked_set, zone_desc->instance_id); node->value = zone_desc; mutex_unlock(&zone_desc_rc_mtx); #endif log_debug6("new: ?@%p", zone_desc); return zone_desc; } /** \brief * Frees a zone data * * @param[in] src is a * to the zone data */ zone_desc_s * zone_clone(zone_desc_s *zone_desc) { zone_desc_s *clone = zone_alloc(); memcpy(clone, zone_desc, sizeof(zone_desc_s)); clone->masters = host_address_copy_list(zone_desc->masters); clone->notifies = host_address_copy_list(zone_desc->notifies); clone->transfer_source = host_address_copy_list(zone_desc->transfer_source); #if DNSCORE_HAS_ACL_SUPPORT /* acl_unmerge_access_control(&zone_setup->ac, &g_config->ac); COMMENTED OUT acl_access_control_clear(&zone_setup->ac); COMMENTED OUT */ #endif /* Free memory */ clone->domain = strdup(zone_domain(zone_desc)); clone->file_name = strdup(zone_desc->file_name); clone->_origin = dnsname_dup(zone_origin(zone_desc)); clone->rc = 1; #if DNSCORE_HAS_DNSSEC_SUPPORT && DNSCORE_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT if(clone->dnssec_policy != NULL) { dnssec_policy_acquire(clone->dnssec_policy); } #endif log_debug6("clone: %{dnsname}@%p of @%p rc=%i", zone_origin(zone_desc), clone, zone_desc, zone_desc->rc); return clone; } void zone_acquire(zone_desc_s *zone_desc) { mutex_lock(&zone_desc_rc_mtx); #if DEBUG && DEBUG_ARC s32 old_rc = zone_desc->rc; s32 rc = #endif ++zone_desc->rc; mutex_unlock(&zone_desc_rc_mtx); #if DEBUG && DEBUG_ARC log_debug6("acquire: %{dnsname}@%p rc=%i", zone_origin(zone_desc), zone_desc, rc); char prefix[80]; snformat(prefix, sizeof(prefix), "acquire: %{dnsname}@%p", zone_origin(zone_desc), zone_desc); log_debug7("%s: RC from %i to %i", prefix, old_rc, rc); debug_log_stacktrace(g_server_logger, MSG_DEBUG7, prefix); #endif } void zone_dump_allocated() { #if DEBUG mutex_lock(&zone_desc_rc_mtx); u64_set_iterator iter; u64_set_iterator_init(&zone_desc_tracked_set, &iter); while(u64_set_iterator_hasnext(&iter)) { u64_node *node = u64_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s*)node->value; u32 status_flags = zone_get_status(zone_desc); format_writer status_flags_fw = {zone_desc_status_flags_long_format, &status_flags}; log_debug1("zone dump: %p #%llu, %llu, rc=%u, %{dnsname} status=%w",zone_desc, zone_desc->instance_id, zone_desc->instance_time_us, zone_desc->rc, zone_origin(zone_desc), &status_flags_fw); } mutex_unlock(&zone_desc_rc_mtx); #else // not implemented #endif } /** * * Decrements reference and eventually destroys the zone desc * * @param zone_desc */ void zone_release(zone_desc_s *zone_desc) { // note: the zone MUST be locked by the caller if(zone_desc != NULL) { mutex_lock(&zone_desc_rc_mtx); #if DEBUG && DEBUG_ARC s32 old_rc = zone_desc->rc; #endif s32 rc = --zone_desc->rc; mutex_unlock(&zone_desc_rc_mtx); #if DEBUG && DEBUG_ARC log_debug6("release: %{dnsname}@%p rc=%i", zone_origin(zone_desc), zone_desc, rc); char prefix[80]; snformat(prefix, sizeof(prefix), "release: %{dnsname}@%p", zone_origin(zone_desc), zone_desc); log_debug7("%s: RC from %i to %i", prefix, old_rc, rc); debug_log_stacktrace(g_server_logger, MSG_DEBUG7, prefix); #endif if(rc <= 0) { log_debug7("zone_free(%p): '%s' (%i)", zone_desc, zone_domain(zone_desc), rc); if(zone_desc->loaded_zone != NULL) { alarm_close(zone_desc->loaded_zone->alarm_handle); zone_desc->loaded_zone->alarm_handle = ALARM_HANDLE_INVALID; zdb_zone_release(zone_desc->loaded_zone); zone_desc->loaded_zone = NULL; } #if DEBUG log_debug7("zone_free(%p): '%s' #%llu %llu", zone_desc, zone_domain(zone_desc), zone_desc->instance_id, zone_desc->instance_time_us); mutex_lock(&zone_desc_rc_mtx); u64_set_delete(&zone_desc_tracked_set, zone_desc->instance_id); mutex_unlock(&zone_desc_rc_mtx); #endif host_address_delete_list(zone_desc->masters); zone_desc->masters = NULL; host_address_delete_list(zone_desc->notifies); zone_desc->notifies = NULL; host_address_delete_list(zone_desc->transfer_source); zone_desc->transfer_source = NULL; #if DNSCORE_HAS_DNSSEC_SUPPORT && DNSCORE_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT if(zone_desc->dnssec_policy != NULL) { dnssec_policy_release(zone_desc->dnssec_policy); zone_desc->dnssec_policy = NULL; } #endif #if DNSCORE_HAS_ACL_SUPPORT acl_unmerge_access_control(&zone_desc->ac); acl_access_control_clear(&zone_desc->ac); #endif // Free the memory free(zone_desc->domain); free(zone_desc->file_name); free(zone_desc->_origin); cond_finalize(&zone_desc->lock_cond); mutex_destroy(&zone_desc->lock); #if DEBUG memset(zone_desc, 0xfe, sizeof(zone_desc_s)); #endif ZFREE_OBJECT(zone_desc); } } } void zone_remove_all_matching(zone_data_set *dset, zone_data_matching_callback *matchcallback) { if(dset != NULL) { zone_set_lock(dset); // unlock checked ptr_vector candidates = PTR_VECTOR_EMPTY; ptr_set_iterator iter; ptr_set_iterator_init(&dset->set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value; if(zone_desc != NULL) { if(matchcallback(zone_desc)) { ptr_vector_append(&candidates, zone_desc); } } } for(s32 i = 0; i <= candidates.offset; i++) { zone_desc_s *zone_desc = (zone_desc_s*)candidates.data[i]; ptr_set_delete(&dset->set, zone_origin(zone_desc)); zone_release(zone_desc); } ptr_vector_destroy(&candidates); zone_set_unlock(dset); } } #if 1 // NOT USED /** \brief Frees all elements of the collection * * @param[in] src the collection * * @return NONE */ void zone_free_all(zone_data_set *dset) { if(dset != NULL) { zone_set_lock(dset); // unlock checked ptr_set_iterator iter; ptr_set_iterator_init(&dset->set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value; if(zone_desc != NULL) { #if DEBUG // status should be idle mutex_lock(&zone_desc_rc_mtx); s32 rc = zone_desc->rc; mutex_unlock(&zone_desc_rc_mtx); #if DEBUG zone_lock(zone_desc, ZONE_LOCK_LOAD); zdb_zone *zone = zone_set_loaded_zone(zone_desc, NULL); if(zone != NULL) { zdb_zone_release(zone); } zone_unlock(zone_desc, ZONE_LOCK_LOAD); #endif if(rc != 1) { if(rc > 0) { log_debug5("zone: warning, zone %{dnsname} has RC=%i", zone_origin(zone_desc), rc); } else { log_debug5("zone: warning, zone ? has RC=%i", rc); } } #endif zone_release(zone_desc); } } ptr_set_destroy(&dset->set); zone_set_unlock(dset); } } #endif ya_result zone_complete_settings(zone_desc_s *zone_desc) { // type if(zone_desc->type == ZT_SLAVE) { if(zone_desc->masters == NULL /* || address_matched(zone_desc->masters, g_config->listen, g_config->port) */) { return DATABASE_ZONE_MISSING_MASTER; } } #if ZDB_HAS_MASTER_SUPPORT else if(zone_desc->type == ZT_MASTER) { if(zone_desc->file_name == NULL || zone_desc->file_name[0] == '\0') { return ZONE_LOAD_MASTER_ZONE_FILE_UNDEFINED; } } #endif else // zone type is not supported { return DATABASE_ZONE_MISSING_TYPE; } // origin if(zone_origin(zone_desc) == NULL) { if(zone_desc->domain == NULL) { return DATABASE_ZONE_MISSING_DOMAIN; } // else the origin can be set from the domain // set the domain to lower case char *p = zone_desc->domain; while(*p != 0) { *p = tolower(*p); p++; } ya_result return_code; MALLOC_OR_DIE(u8*, zone_desc->_origin, strlen(zone_domain(zone_desc)) + 2, ZDORIGIN_TAG); if(FAIL(return_code = cstr_to_dnsname(zone_desc->_origin, zone_domain(zone_desc)))) { free(zone_desc->_origin); zone_desc->_origin = NULL; return return_code; } } #if DNSCORE_HAS_ACL_SUPPORT // acl acl_merge_access_control(&zone_desc->ac, g_config->ac); #endif #if ZDB_HAS_DNSSEC_SUPPORT if(zone_desc->keys_path != NULL) { dnssec_keystore_add_domain(zone_origin(zone_desc), zone_desc->keys_path); } #endif return SUCCESS; } #define ZONE_DESC_COMPARE_FIELD_PTR(field_a_, field_b_, comparator_, flag_) \ if(field_a_ != field_b_) \ { \ if((field_a_ != NULL) && (field_b_ != NULL)) \ { \ if(comparator_(field_a_, field_b_) != 0) \ { \ return_code |= flag_; \ } \ } \ else \ { \ return_code |= flag_; \ } \ } #define ZONE_DESC_EQUALS_FIELD_PTR(field_a_, field_b_, comparator_, flag_) \ if(field_a_ != field_b_) \ { \ if((field_a_ != NULL) && (field_b_ != NULL)) \ { \ if(!comparator_(field_a_, field_b_)) \ { \ return_code |= flag_; \ } \ } \ else \ { \ return_code |= flag_; \ } \ } s32 zone_desc_match(const zone_desc_s *a, const zone_desc_s *b) { u32 return_code = 0; if(a == b) { return 0; } if((a == NULL) || (b == NULL)) { return MIN_S32; } ZONE_DESC_COMPARE_FIELD_PTR(a->_origin, b->_origin, dnsname_compare, ZONE_DESC_MATCH_ORIGIN); ZONE_DESC_COMPARE_FIELD_PTR(zone_domain(a),zone_domain(b),strcmp, ZONE_DESC_MATCH_DOMAIN); if((a->file_name != NULL) && (b->file_name != NULL)) { ZONE_DESC_COMPARE_FIELD_PTR(a->file_name,b->file_name,strcmp, ZONE_DESC_MATCH_FILE_NAME); } else if(a->file_name != b->file_name) { return_code |= ZONE_DESC_MATCH_FILE_NAME; } ZONE_DESC_EQUALS_FIELD_PTR(a->masters,b->masters,host_address_list_equals, ZONE_DESC_MATCH_MASTERS); ZONE_DESC_EQUALS_FIELD_PTR(a->notifies,b->notifies,host_address_list_equals, ZONE_DESC_MATCH_NOTIFIES); ZONE_DESC_EQUALS_FIELD_PTR(a->transfer_source,b->transfer_source,host_address_list_equals, ZONE_DESC_MATCH_TRANSFERSOURCE); #if DNSCORE_HAS_DNSSEC_SUPPORT && DNSCORE_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT if(a->dnssec_policy != b->dnssec_policy) { return_code |= ZONE_DESC_MATCH_DNSSEC_POLICIES; } #endif #if DNSCORE_HAS_ACL_SUPPORT if(!acl_address_control_equals(&a->ac, &b->ac)) { return_code |= ZONE_DESC_MATCH_ACL; } #endif #if DNSCORE_HAS_CTRL && DNSCORE_HAS_DYNAMIC_PROVISIONING if(memcmp(&a->dynamic_provisioning, &b->dynamic_provisioning, sizeof(dynamic_provisioning_s)) != 0) { return_code |= ZONE_DESC_MATCH_DYNAMIC; } ZONE_DESC_EQUALS_FIELD_PTR(a->slaves,b->slaves,host_address_list_equals, ZONE_DESC_MATCH_SLAVES); #endif /* if(memcmp(&a->refresh, &b->refresh, sizeof(zone_data_refresh)) != 0) { return_code |= ZONE_DESC_MATCH_REFRESH; } */ if(memcmp(&a->notify, &b->notify, sizeof(zone_notify_s)) != 0) { return_code |= ZONE_DESC_MATCH_NOTIFY; } #if DNSCORE_HAS_DNSSEC_SUPPORT if(a->dnssec_mode != b->dnssec_mode) { return_code |= ZONE_DESC_MATCH_DNSSEC_MODE; } #endif if(a->type != b->type) { return_code |= ZONE_DESC_MATCH_TYPE; } return return_code; } /** * Adds the zone in the collection (if it's not there already) * The zone must have at least it's domain set */ ya_result zone_register(zone_data_set *dset, zone_desc_s *zone_desc) { zone_complete_settings(zone_desc); if(zone_origin(zone_desc) == NULL) { if(zone_desc->domain == NULL) { log_err("config: zone: ?: no domain set (not loaded)", zone_domain(zone_desc)); return DATABASE_ZONE_MISSING_DOMAIN; } } zone_set_writer_lock(dset); ptr_node *zone_desc_node = ptr_set_find(&dset->set, zone_origin(zone_desc)); if(zone_desc_node != NULL) { // already known zone_desc_s *current_zone_desc = (zone_desc_s*)zone_desc_node->value; s32 zone_desc_match_bitmap = ~0; if(current_zone_desc == zone_desc) { // already log_debug("zone: %{dnsname} has already been set", zone_origin(zone_desc)); zone_set_writer_unlock(dset); return SUCCESS; } else if((zone_desc_match_bitmap = zone_desc_match(zone_desc, current_zone_desc)) == 0) { // already log_debug("zone: %{dnsname} has already been set this way", zone_origin(zone_desc)); zone_set_writer_unlock(dset); return DATABASE_ZONE_CONFIG_CLONE; } else { /* * compare the zones are decide (overwrite or replace ?) * * if the zones are equals : no operation * if the zones differs ... * ask for a reload of the desc * */ log_err("zone: %{dnsname} has been set in two different way (bitmap=%08x) (ignoring duplicate)", zone_origin(zone_desc), zone_desc_match_bitmap); zone_set_writer_unlock(dset); return DATABASE_ZONE_CONFIG_DUP; } } else { log_debug("zone: %{dnsname} is a new zone", zone_origin(zone_desc)); zone_desc->_status_flags = ZONE_STATUS_STARTING_UP; } if(zone_desc->type == ZT_SLAVE) { log_debug1("zone: %{dnsname} is a slave, verifying master settings", zone_origin(zone_desc)); if(zone_desc->masters == NULL /* || address_matched(zone_desc->masters, g_config->listen, g_config->port) */) { zone_set_writer_unlock(dset); log_err("zone: %{dnsname} has no master setting (not loaded)", zone_origin(zone_desc)); free(zone_desc->_origin); zone_desc->_origin = NULL; return DATABASE_ZONE_MISSING_MASTER; } log_debug("zone: %{dnsname} is a slave, master is %{hostaddr}", zone_origin(zone_desc), zone_desc->masters); } ya_result return_value; ptr_node *node = ptr_set_insert(&dset->set, zone_desc->_origin); if(node->value == NULL) { //log_info("zone: the zone %{dnsname} has been registered", zone_origin(zone_desc)); node->value = zone_desc; ++dset->set_count; return_value = SUCCESS; } else { // already //log_err("zone: the zone %{dnsname} has already been set", zone_origin(zone_desc)); free(zone_desc->_origin); zone_desc->_origin = NULL; return_value = DATABASE_ZONE_CONFIG_DUP; } zone_set_writer_unlock(dset); return return_value; } /** * Removes the zone with the given origin from the collection. * Returns a pointer to the zone. (The caller may destroy it if * he wants) */ zone_desc_s * zone_unregister(zone_data_set *dset, const u8 *origin) { zone_desc_s *zone_desc = NULL; zone_set_writer_lock(dset); ptr_node *node = ptr_set_find(&dset->set, origin); if(node != NULL) { zone_desc = (zone_desc_s*)node->value; if(zone_desc != NULL) { ptr_set_delete(&dset->set, origin); --dset->set_count; } } zone_set_writer_unlock(dset); return zone_desc; } /** * returns the zone_data from the zone config that's just after the name * in lexicographic order * * @param name * @return */ zone_desc_s* zone_getafterdnsname(const u8 *name) { zone_desc_s *zone_desc = NULL; zone_set_lock(&database_zone_desc); // unlock checked ptr_node *zone_node = ptr_set_find(&database_zone_desc.set, name); if(zone_node != NULL) { zone_node = ptr_set_node_next(zone_node); if(zone_node != NULL) { zone_desc = (zone_desc_s*)zone_node->value; zone_acquire(zone_desc); } } zone_set_unlock(&database_zone_desc); return zone_desc; } zone_desc_s* zone_acquirebydnsname(const u8 *name) { zone_desc_s *zone_desc = NULL; zone_set_lock(&database_zone_desc); // unlock checked ptr_node *zone_node = ptr_set_find(&database_zone_desc.set, name); if(zone_node != NULL) { zone_desc = (zone_desc_s*)zone_node->value; zone_acquire(zone_desc); } zone_set_unlock(&database_zone_desc); return zone_desc; } void zone_setloading(zone_desc_s *zone_desc, bool v) { const u32 mask = ZONE_STATUS_LOADING; if(v) { zone_set_status(zone_desc, mask); } else { zone_clear_status(zone_desc, mask); } } void zone_setmustsavefile(zone_desc_s *zone_desc, bool v) { const u32 mask = ZONE_STATUS_SAVETO_ZONE_FILE; if(v) { zone_set_status(zone_desc, mask); } else { zone_clear_status(zone_desc, mask); } } void zone_setmustsaveaxfr(zone_desc_s *zone_desc, bool v) { const u32 mask = ZONE_STATUS_SAVETO_AXFR_FILE; if(v) { zone_set_status(zone_desc, mask); } else { zone_clear_status(zone_desc, mask); } } void zone_setsavingfile(zone_desc_s *zone_desc, bool v) { const u32 mask = ZONE_STATUS_SAVING_ZONE_FILE; if(v) { zone_set_status(zone_desc, mask); } else { zone_clear_status(zone_desc, mask); } } void zone_setsavingaxfr(zone_desc_s *zone_desc, bool v) { const u32 mask = ZONE_STATUS_SAVING_AXFR_FILE; if(v) { zone_set_status(zone_desc, mask); } else { zone_clear_status(zone_desc, mask); } } void zone_setstartingup(zone_desc_s *zone_desc, bool v) { const u32 mask = ZONE_STATUS_STARTING_UP; if(v) { zone_set_status(zone_desc, mask); } else { zone_clear_status(zone_desc, mask); } } bool zone_isidle(zone_desc_s *zone_desc) { return (zone_get_status(zone_desc) & ZONE_STATUS_BUSY) == 0; } bool zone_isfrozen(zone_desc_s *zone_desc) { return (zone_get_status(zone_desc) & ZONE_STATUS_FROZEN) != 0; } bool zone_isloading(zone_desc_s *zone_desc) { return ((zone_get_status(zone_desc) & ZONE_STATUS_LOADING) != 0); } bool zone_mustsavefile(zone_desc_s *zone_desc) { return ((zone_get_status(zone_desc) & ZONE_STATUS_SAVETO_ZONE_FILE) != 0); } bool zone_mustsaveaxfr(zone_desc_s *zone_desc) { return ((zone_get_status(zone_desc) & ZONE_STATUS_SAVETO_AXFR_FILE) != 0); } bool zone_issavingfile(zone_desc_s *zone_desc) { return ((zone_get_status(zone_desc) & ZONE_STATUS_SAVING_ZONE_FILE) != 0); } bool zone_issavingaxfr(zone_desc_s *zone_desc) { return ((zone_get_status(zone_desc) & ZONE_STATUS_SAVING_AXFR_FILE) != 0); } bool zone_isstartingup(zone_desc_s *zone_desc) { return ((zone_get_status(zone_desc) & ZONE_STATUS_STARTING_UP) != 0); } bool zone_isdynamicupdating(zone_desc_s *zone_desc) { return ((zone_get_status(zone_desc) & ZONE_STATUS_DYNAMIC_UPDATING) != 0); } bool zone_canbeedited(zone_desc_s *zone_desc) { return ((zone_get_status(zone_desc) & (ZONE_STATUS_STARTING_UP|ZONE_STATUS_DYNAMIC_UPDATING|ZONE_STATUS_SAVING_AXFR_FILE|ZONE_STATUS_SAVING_ZONE_FILE|ZONE_STATUS_LOADING)) == 0); } bool zone_ismaster(zone_desc_s *zone_desc) { return zone_desc->type == ZT_MASTER; } ya_result zone_wait_unlocked(zone_desc_s *zone_desc) { log_debug6("zone_wait_unlocked(%{dnsname}@%p) ...", zone_origin(zone_desc), zone_desc); mutex_lock(&zone_desc->lock); if((zone_desc->lock_owner_count | zone_desc->lock_wait_count) != 0) { do { cond_wait(&zone_desc->lock_cond, &zone_desc->lock); } while((zone_desc->lock_owner_count | zone_desc->lock_wait_count) != 0); } log_debug6("zone_wait_unlocked(%{dnsname}@%p) done", zone_origin(zone_desc), zone_desc); cond_notify(&zone_desc->lock_cond); mutex_unlock(&zone_desc->lock); return SUCCESS; } bool zone_is_obsolete(zone_desc_s *zone_desc) { bool r; mutex_lock(&zone_desc->lock); r = ((zone_desc->lock_owner_count | zone_desc->lock_wait_count) == 0) && ((zone_get_status(zone_desc) & (ZONE_STATUS_UNREGISTERING|ZONE_STATUS_MARKED_FOR_DESTRUCTION)) != 0); cond_notify(&zone_desc->lock_cond); mutex_unlock(&zone_desc->lock); return r; } ya_result zone_try_lock(zone_desc_s *zone_desc, u8 owner_id) { #if DEBUG log_debug6("zone_try_lock(%{dnsname}@%p, %u", zone_origin(zone_desc), zone_desc, owner_id); debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_DEBUG6, "zone_try_lock"); #endif ya_result return_value = LOCK_TIMEOUT; mutex_lock(&zone_desc->lock); if((zone_desc->lock_owner == ZONE_LOCK_NOBODY) || (zone_desc->lock_owner == owner_id)) { zone_desc->lock_owner = owner_id & 0x7f; zone_desc->lock_owner_count++; return_value = owner_id; } cond_notify(&zone_desc->lock_cond); mutex_unlock(&zone_desc->lock); return return_value; } ya_result zone_lock(zone_desc_s *zone_desc, u8 owner_id) { ya_result return_value = LOCK_FAILED; #if DEBUG log_debug6("zone_lock(%{dnsname}@%p, %02x)", zone_origin(zone_desc), zone_desc, owner_id); debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_DEBUG6, "zone_lock"); #endif mutex_lock(&zone_desc->lock); if((zone_desc->lock_owner != ZONE_LOCK_NOBODY) && (zone_desc->lock_owner != owner_id)) { zone_desc->lock_wait_count++; do { cond_wait(&zone_desc->lock_cond, &zone_desc->lock); } while((zone_desc->lock_owner != ZONE_LOCK_NOBODY) && (zone_desc->lock_owner != owner_id)); zone_desc->lock_wait_count--; } zone_desc->lock_owner = owner_id & 0x7f; zone_desc->lock_owner_count++; return_value = owner_id; #if ZONE_LOCK_HAS_OWNER_ID zone_desc->lock_last_owner_tid = thread_self(); #endif if((owner_id & 0x80) == 0) { cond_notify(&zone_desc->lock_cond); } mutex_unlock(&zone_desc->lock); return return_value; } ya_result zone_try_lock_wait(zone_desc_s *zone_desc, u64 usec, u8 owner_id) { ya_result return_value = LOCK_FAILED; #if DEBUG log_debug6("zone_try_lock_wait(%{dnsname}@%p, %llu, %02x)", zone_origin(zone_desc), zone_desc, usec, owner_id); debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_DEBUG6, "zone_try_lock_wait"); #endif mutex_lock(&zone_desc->lock); if((zone_desc->lock_owner != ZONE_LOCK_NOBODY) && (zone_desc->lock_owner != owner_id)) { zone_desc->lock_wait_count++; s64 start = timeus(); do { cond_timedwait(&zone_desc->lock_cond, &zone_desc->lock, usec); s64 now = timeus(); if(now - start >= (s64)usec) { cond_notify(&zone_desc->lock_cond); mutex_unlock(&zone_desc->lock); return LOCK_TIMEOUT; } } while((zone_desc->lock_owner != ZONE_LOCK_NOBODY) && (zone_desc->lock_owner != owner_id)); zone_desc->lock_wait_count--; } zone_desc->lock_owner = owner_id & 0x7f; zone_desc->lock_owner_count++; return_value = owner_id; #if ZONE_LOCK_HAS_OWNER_ID zone_desc->lock_last_owner_tid = thread_self(); #endif if((owner_id & 0x80) == 0) { cond_notify(&zone_desc->lock_cond); } mutex_unlock(&zone_desc->lock); return return_value; } void zone_unlock(zone_desc_s *zone_desc, u8 owner_mark) { #if DEBUG log_debug6("zone_unlock(%{dnsname}@%p, %02x)", zone_origin(zone_desc), zone_desc, owner_mark); debug_log_stacktrace(MODULE_MSG_HANDLE, MSG_DEBUG6, "zone_unlock"); #endif mutex_lock(&zone_desc->lock); yassert(zone_desc->lock_owner == (owner_mark & 0x7f)); yassert(zone_desc->lock_owner_count > 0); if((--zone_desc->lock_owner_count) == 0) { zone_desc->lock_owner = ZONE_LOCK_NOBODY; } #if ZONE_LOCK_HAS_OWNER_ID thread_t tid = thread_self(); if(zone_desc->lock_last_owner_tid == tid) { zone_desc->lock_last_owner_tid = 0; } #endif cond_notify(&zone_desc->lock_cond); mutex_unlock(&zone_desc->lock); (void)owner_mark; // silence warning on NDEBUG builds } bool zone_islocked(zone_desc_s *zone_desc) { mutex_lock(&zone_desc->lock); bool ret = (zone_desc->lock_owner != ZONE_LOCK_NOBODY); mutex_unlock(&zone_desc->lock); return ret; } /** * Sets non-static values in a zone descriptor * * @param zone_desc */ void zone_setdefaults(zone_desc_s *zone_desc) { u32 port; if(FAIL(parse_u32_check_range(g_config->server_port, &port, 1, MAX_U16, BASE_10))) { port = DNS_DEFAULT_PORT; } zone_desc->_status_flags = ZONE_STATUS_STARTING_UP; #if DNSCORE_HAS_ACL_SUPPORT acl_merge_access_control(&zone_desc->ac, g_config->ac); #endif #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_DNSSEC_SUPPORT /* * The newly generated signatures will be valid for that amount of days */ if(zone_desc->signature.sig_validity_interval == MAX_S32) { zone_desc->signature.sig_validity_interval = MIN(g_config->sig_validity_interval, SIGNATURE_VALIDITY_INTERVAL_MAX); /* days */ } if(zone_desc->signature.sig_validity_regeneration == MAX_S32) { zone_desc->signature.sig_validity_regeneration = MIN(g_config->sig_validity_regeneration, SIGNATURE_VALIDITY_REGENERATION_MAX); } /* * The validity of newly generated signature will be off by at most this */ if(zone_desc->signature.sig_validity_jitter == MAX_S32) { zone_desc->signature.sig_validity_jitter = MIN(g_config->sig_validity_jitter, SIGNATURE_VALIDITY_JITTER_MAX); } /* * The first epoch when a signature will be marked as invalid. */ zone_desc->signature.sig_invalid_first = MAX_S32; zone_desc->signature.scheduled_sig_invalid_first = MAX_S32; #endif #if HAS_DYNAMIC_PROVISIONING memset(&zone_desc->dynamic_provisioning, 0, sizeof(dynamic_provisioning_s)); //zone->dynamic_provisioning.flags |= ZONE_CTRL_FLAG_GENERATE_ZONE; #endif zone_desc->notify.retry_count = atoi(S_NOTIFY_RETRY_COUNT); zone_desc->notify.retry_period = atoi(S_NOTIFY_RETRY_PERIOD) * 60; zone_desc->notify.retry_period_increase = atoi(S_NOTIFY_RETRY_PERIOD_INCREASE) * 60; host_address_set_default_port_value(zone_desc->masters, ntohs(port)); host_address_set_default_port_value(zone_desc->notifies, ntohs(port)); host_address_set_port_value(zone_desc->transfer_source, 0); // note: transfer_source ignores the port // seems incorrect here : acl_access_control_copy(&zone_desc->ac, &g_config->ac); } /** * Merges the settings of a zone into another zone descriptor. * * @param desc_zone_desc * @param src_zone_desc * @return 0 if the zone are equals * 1 if some parts have been edited * or an error code */ ya_result zone_setwithzone(zone_desc_s *desc_zone_desc, zone_desc_s *src_zone_desc) { bool changed = FALSE; if(desc_zone_desc->domain != NULL) { if(strcmp(zone_domain(desc_zone_desc), zone_domain(src_zone_desc)) != 0) { log_debug1("zone_setwithzone: domain does not match '%s'!='%s'", zone_domain(desc_zone_desc), zone_domain(src_zone_desc)); return INVALID_STATE_ERROR; } } else { desc_zone_desc->domain = strdup(zone_domain(src_zone_desc)); desc_zone_desc->qclass = src_zone_desc->qclass; desc_zone_desc->type = src_zone_desc->type; #if ZDB_HAS_DNSSEC_SUPPORT desc_zone_desc->dnssec_mode = src_zone_desc->dnssec_mode; #endif #if HAS_DYNAMIC_PROVISIONING desc_zone_desc->dynamic_provisioning.flags = desc_zone_desc->dynamic_provisioning.flags; #endif desc_zone_desc->_origin = dnsname_dup(zone_origin(src_zone_desc)); desc_zone_desc->_status_flags = src_zone_desc->_status_flags; if(src_zone_desc->file_name != NULL) { desc_zone_desc->file_name = strdup(src_zone_desc->file_name); } changed = TRUE; } #if DNSCORE_HAS_ACL_SUPPORT acl_access_control_copy(&desc_zone_desc->ac, &src_zone_desc->ac); #endif #if ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_DNSSEC_SUPPORT /* * The newly generated signatures will be valid for that amount of days */ if(desc_zone_desc->signature.sig_validity_interval != src_zone_desc->signature.sig_validity_interval) { desc_zone_desc->signature.sig_validity_interval = src_zone_desc->signature.sig_validity_interval; changed = TRUE; } if(desc_zone_desc->signature.sig_validity_regeneration != src_zone_desc->signature.sig_validity_regeneration) { desc_zone_desc->signature.sig_validity_regeneration = src_zone_desc->signature.sig_validity_regeneration; changed = TRUE; } if(desc_zone_desc->signature.sig_validity_jitter != src_zone_desc->signature.sig_validity_jitter) { desc_zone_desc->signature.sig_validity_jitter = src_zone_desc->signature.sig_validity_jitter; changed = TRUE; } /* * The first epoch when a signature will be marked as invalid. */ if(desc_zone_desc->signature.sig_invalid_first != src_zone_desc->signature.sig_invalid_first) { desc_zone_desc->signature.sig_invalid_first = src_zone_desc->signature.sig_invalid_first; changed = TRUE; } if(desc_zone_desc->signature.scheduled_sig_invalid_first != src_zone_desc->signature.scheduled_sig_invalid_first) { desc_zone_desc->signature.scheduled_sig_invalid_first = src_zone_desc->signature.scheduled_sig_invalid_first; changed = TRUE; } #endif #if HAS_DYNAMIC_PROVISIONING if(memcmp(&desc_zone_desc->dynamic_provisioning, &src_zone_desc->dynamic_provisioning, sizeof(dynamic_provisioning_s)) != 0) { memcpy(&desc_zone_desc->dynamic_provisioning, &src_zone_desc->dynamic_provisioning, sizeof(dynamic_provisioning_s)); changed = TRUE; } #endif if(desc_zone_desc->notify.retry_count != src_zone_desc->notify.retry_count) { desc_zone_desc->notify.retry_count = src_zone_desc->notify.retry_count; changed = TRUE; } if(desc_zone_desc->notify.retry_period != src_zone_desc->notify.retry_period) { desc_zone_desc->notify.retry_period = src_zone_desc->notify.retry_period; changed = TRUE; } if(desc_zone_desc->notify.retry_period_increase != src_zone_desc->notify.retry_period_increase) { desc_zone_desc->notify.retry_period_increase = src_zone_desc->notify.retry_period_increase; changed = TRUE; } if(desc_zone_desc->flags != src_zone_desc->flags) { desc_zone_desc->flags = src_zone_desc->flags; changed = TRUE; } changed |= host_address_update_host_address_list(&desc_zone_desc->masters, src_zone_desc->masters); changed |= host_address_update_host_address_list(&desc_zone_desc->notifies, src_zone_desc->notifies); changed |= host_address_update_host_address_list(&desc_zone_desc->transfer_source, src_zone_desc->transfer_source); changed |= host_address_update_host_address_list(&desc_zone_desc->slaves, src_zone_desc->slaves); if(src_zone_desc->file_name != NULL) { if(strcmp(desc_zone_desc->file_name, src_zone_desc->file_name) != 0) { free(desc_zone_desc->file_name); desc_zone_desc->file_name = strdup(src_zone_desc->file_name); changed = TRUE; } } #if ZDB_HAS_MASTER_SUPPORT && ZDB_HAS_DYNAMIC_PROVISIONING // master zone without a file name ... if((desc_zone_desc->file_name == NULL) && (desc_zone_desc->type == ZT_MASTER)) { desc_zone_desc->dynamic_provisioning.flags |= ZONE_CTRL_FLAG_GENERATE_ZONE; changed = TRUE; } #endif return (changed)?1:0; // 1 if changed, 0 is no operation performed } /** * * helper formatting tool to print the zone descriptor status flags as a chain of characters * * @param value * @param os * @param padding * @param pad_char * @param left_justified * @param reserved_for_method_parameters */ #ifdef SHORT_VERSION_IS_LESS_CLEAR /** * used by zone_desc_status_flags_format */ static const char status_letters[32] = "IclL" "MUdD" "zZaA" "sSeE" "RxX#" "f---" "T---" "ur/!"; static void zone_desc_status_flags_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u32 status = *((u32*)value); const char *p = status_letters; if(status == 0) { output_stream_write(os, (const u8*)"i", 1); } else { do { if(status & 1) { output_stream_write(os, p, 1); } p++; status >>= 1; } while(status != 0); } } #endif /** * used by zone_desc_status_flags_long_format */ static const char *status_words[32] = { //"IDLE", "STARTING-UP", // 0 "MODIFIED", "LOAD", "LOADING", "MOUNTING", "UNMOUNTING", // 5 "DROP", "DROPPING", "SAVETO-ZONE-FILE", "SAVING-ZONE-FILE", "SAVETO-AXFR-FILE", // 10 "SAVING-AXFR-FILE", "SIGNATURES-UPDATE", "SIGNATURES-UPDATING", "DYNAMIC-UPDATE", "DYNAMIC-UPDATING", // 15 "READONLY", "DOWNLOAD-XFR-FILE", "DOWNLOADING-XFR-FILE", "DROP-AFTER-RELOAD", "FROZEN", // 20 "?", "?", "?", "DOWNLOADED", "?", // 25 "?", "?", "ZONE-STATUS-UNREGISTERING", "REGISTERED", "MARKED-FOR-DESTRUCTION", "PROCESSING" }; void zone_desc_status_flags_long_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; u32 status = *((u32*)value); const char **p = status_words; if(status == 0) { output_stream_write(os, (const u8*)"IDLE", 4); } else { do { if(status & 1) { const char *word = *p; output_stream_write(os, word, strlen(word)); output_stream_write(os, (const char*)" ", 1); } p++; status >>= 1; } while(status != 0); } } #if DNSCORE_HAS_ACL_SUPPORT /** * * helper formatting tool to print the ACL fields of the zone descriptor * * @param value * @param os * @param padding * @param pad_char * @param left_justified * @param reserved_for_method_parameters */ static void zone_desc_ams_format(const void *value, output_stream *os, s32 padding, char pad_char, bool left_justified, void* reserved_for_method_parameters) { (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; address_match_set *ams = (address_match_set*)value; acl_address_match_set_to_stream(os, ams); } #endif void zone_desc_log(logger_handle* handle, u32 level, const zone_desc_s *zone_desc, const char *text) { if(text == NULL) { text = "NULL"; } if(zone_desc == NULL) { logger_handle_msg(handle, level, "%s: NULL", text); return; } logger_handle_msg(handle, level, "%s: %{dnsname} @%p '%s' file='%s'", text, FQDNNULL(zone_origin(zone_desc)), zone_desc, STRNULL(zone_domain(zone_desc)), STRNULL(zone_desc->file_name)); u32 status_flags = zone_get_status(zone_desc); //format_writer status_flags_fw = {zone_desc_status_flags_format, &status_flags}; format_writer status_flags_fw = {zone_desc_status_flags_long_format, &status_flags}; logger_handle_msg(handle, level, "%s: %{dnsname} status=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_flags_fw); #if ZDB_HAS_DNSSEC_SUPPORT logger_handle_msg(handle, level, "%s: %{dnsname} dnssec=%s type=%s flags=%x lock=%02hhx #olock=%d #wlock=%d", text, FQDNNULL(zone_origin(zone_desc)), zone_dnssec_to_name(zone_desc->dnssec_mode), zone_type_to_name(zone_desc->type), zone_desc->flags, zone_desc->lock_owner, zone_desc->lock_owner_count, zone_desc->lock_wait_count); #else logger_handle_msg(handle, level, "%s: %{dnsname} type=%s flags=%x lock=%02hhx #olock=%d #wlock=%d", text, FQDNNULL(zone_origin(zone_desc)), zone_type_to_name(zone_desc->type), zone_desc->flags, zone_desc->lock_owner, zone_desc->lock_owner_count, zone_desc->lock_wait_count); #endif logger_handle_msg(handle, level, "%s: %{dnsname} refreshed=%d retried=%d next=%d", text, FQDNNULL(zone_origin(zone_desc)), zone_desc->refresh.refreshed_time, zone_desc->refresh.retried_time, zone_desc->refresh.zone_update_next_time); #if ZDB_HAS_DNSSEC_SUPPORT && HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT u32 sig_invalid_first = zone_desc->signature.sig_invalid_first; u32 scheduled_sig_invalid_first = zone_desc->signature.scheduled_sig_invalid_first; logger_handle_msg(handle, level, "%s: %{dnsname} interval=%d jitter=%d regeneration=%d invalid=%T scheduled-update=%T", text, FQDNNULL(zone_origin(zone_desc)), zone_desc->signature.sig_validity_interval, zone_desc->signature.sig_validity_jitter, zone_desc->signature.sig_validity_regeneration, sig_invalid_first, scheduled_sig_invalid_first); if(zone_desc->dnssec_policy != NULL) { logger_handle_msg(handle, level, "%s: %{dnsname} dnssec-policy: '%s'", text, FQDNNULL(zone_origin(zone_desc)), STRNULL(zone_desc->dnssec_policy->name)); } else { logger_handle_msg(handle, level, "%s: %{dnsname} dnssec-policy: none", text, FQDNNULL(zone_origin(zone_desc))); } #endif logger_handle_msg(handle, level, "%s: %{dnsname} master=%{hostaddr}", text, FQDNNULL(zone_origin(zone_desc)), zone_desc->masters); logger_handle_msg(handle, level, "%s: %{dnsname} notified=%{hostaddrlist}", text, FQDNNULL(zone_origin(zone_desc)), zone_desc->notifies); logger_handle_msg(handle, level, "%s: %{dnsname} transfer-source=%{hostaddrlist}", text, FQDNNULL(zone_origin(zone_desc)), zone_desc->transfer_source); #if DNSCORE_HAS_ACL_SUPPORT format_writer status_ams_fw = {zone_desc_ams_format, &zone_desc->ac.allow_query}; logger_handle_msg(handle, level, "%s: %{dnsname} allow query=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw); status_ams_fw.value = &zone_desc->ac.allow_update; logger_handle_msg(handle, level, "%s: %{dnsname} allow update=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw); status_ams_fw.value = &zone_desc->ac.allow_update_forwarding; logger_handle_msg(handle, level, "%s: %{dnsname} allow update forwarding=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw); status_ams_fw.value = &zone_desc->ac.allow_transfer; logger_handle_msg(handle, level, "%s: %{dnsname} allow transfer=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw); status_ams_fw.value = &zone_desc->ac.allow_notify; logger_handle_msg(handle, level, "%s: %{dnsname} allow notify=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw); #endif #if HAS_DYNAMIC_PROVISIONING #if DNSCORE_HAS_ACL_SUPPORT status_ams_fw.value = &zone_desc->ac.allow_control; logger_handle_msg(handle, level, "%s: %{dnsname} allow control=%w", text, FQDNNULL(zone_origin(zone_desc)), &status_ams_fw); #endif logger_handle_msg(handle, level, "%s: %{dnsname} + dp v=%hx flags=%hx expire=%x refresh=%x retry=%x ts=%x:%x", text, FQDNNULL(zone_origin(zone_desc)), zone_desc->dynamic_provisioning.version, zone_desc->dynamic_provisioning.flags, zone_desc->dynamic_provisioning.expire, zone_desc->dynamic_provisioning.refresh, zone_desc->dynamic_provisioning.retry, zone_desc->dynamic_provisioning.timestamp, zone_desc->dynamic_provisioning.timestamp_lo); logger_handle_msg(handle, level, "%s: %{dnsname} + dp slaves=%{hostaddrlist}", text, FQDNNULL(zone_origin(zone_desc)), zone_desc->slaves); u32 command_count = zone_desc->commands.size; bpqueue_node_s *command_node = zone_desc->commands.first; for(u32 i = 0; i < command_count; i++) { zone_command_s *cmd = (zone_command_s*)command_node->data; logger_handle_msg(handle, level, "%s: %{dnsname} @%p & [%-2i] (%i) %s", text, FQDNNULL(zone_origin(zone_desc)), zone_desc, i, command_node->priority, database_service_operation_get_name(cmd->id)); command_node = command_node->next; } #endif } void zone_desc_log_all(logger_handle* handle, u32 level, zone_data_set *dset, const char *text) { zone_set_lock(dset); // unlock checked if(!ptr_set_isempty(&dset->set)) { ptr_set_iterator iter; ptr_set_iterator_init(&dset->set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value; zone_desc_log(handle, level, zone_desc, text); } zone_set_unlock(dset); } else { zone_set_unlock(dset); #if DEBUG log_debug("zone_desc_log_all: %s set is empty", text); #endif } } /** * * Calls the callback for all zone_desc. * * @param cb * @param args */ ya_result zone_desc_for_all(zone_desc_for_all_callback *cb, void *args) { ya_result ret = SUCCESS; zone_set_lock(&database_zone_desc); // unlock checked if(!ptr_set_isempty(&database_zone_desc.set)) { ptr_set_iterator iter; ptr_set_iterator_init(&database_zone_desc.set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s*)zone_node->value; if(FAIL(ret = cb(zone_desc, args))) { return ret; } } } zone_set_unlock(&database_zone_desc); return ret; } const char* zone_type_to_name(zone_type t) { if((t >= ZT_HINT) && (t <= ZT_STUB)) { return type_to_name[t]; } return "invalid"; } const char* zone_dnssec_to_name(u32 dnssec_flags) { dnssec_flags &= ZONE_DNSSEC_FL_MASK; if(dnssec_flags < 4) { return dnssec_to_name[dnssec_flags]; } return "invalid"; } void zone_enqueue_command(zone_desc_s *zone_desc, u32 id, void* parm, bool has_priority) { if(!has_priority && ((zone_get_status(zone_desc) & ZONE_STATUS_MARKED_FOR_DESTRUCTION) != 0)) { log_err("tried to queue to a zone marked for destruction"); return; } #if DEBUG log_debug("zone_desc: enqueue command %{dnsname}@%p=%i %c %s", zone_origin(zone_desc), zone_desc, zone_desc->rc, (has_priority)?'H':'L', database_service_operation_get_name(id)); #endif if(zone_desc->commands_bits & (1 << id)) { #if DEBUG log_debug("zone_desc: enqueue command %{dnsname}@%p=%i %c %s: already queued", zone_origin(zone_desc), zone_desc, zone_desc->rc, (has_priority)?'H':'L', database_service_operation_get_name(id)); #endif return; // already queued } zone_command_s *cmd; ZALLOC_OBJECT_OR_DIE( cmd, zone_command_s, ZONECMD_TAG); cmd->parm.ptr = parm; cmd->id = id; bpqueue_enqueue(&zone_desc->commands, cmd, (has_priority)?0:1); } zone_command_s* zone_dequeue_command(zone_desc_s *zone_desc) { zone_command_s *cmd = (zone_command_s*)bpqueue_dequeue(&zone_desc->commands); #if DEBUG if(cmd != NULL) { log_debug("zone_desc: dequeue command %{dnsname}@%p=%i - %s", zone_origin(zone_desc), zone_desc, zone_desc->rc, database_service_operation_get_name(cmd->id)); } else { log_debug("zone_desc: dequeue command %{dnsname}@%p=%i - NULL", zone_origin(zone_desc), zone_desc, zone_desc->rc); } #endif if(cmd != NULL) { zone_desc->commands_bits &= ~(1 << cmd->id); } return cmd; } void zone_command_free(zone_command_s *cmd) { ZFREE_OBJECT(cmd); } zdb_zone * zone_get_loaded_zone(zone_desc_s *zone_desc) { yassert(zone_islocked(zone_desc)); zdb_zone *zone = zone_desc->loaded_zone; // OK if(zone != NULL) { zdb_zone_acquire(zone); } return zone; } zdb_zone * zone_set_loaded_zone(zone_desc_s *zone_desc, zdb_zone *zone) { yassert(zone_islocked(zone_desc)); zdb_zone *old_zone = zone_desc->loaded_zone; // OK if(zone != NULL) { zdb_zone_acquire(zone); } zone_desc->loaded_zone = zone; // OK return old_zone; } bool zone_has_loaded_zone(zone_desc_s *zone_desc) { yassert(zone_islocked(zone_desc)); zdb_zone *zone = zone_desc->loaded_zone; // OK return zone != NULL; } void zone_set_status(zone_desc_s *zone_desc, u32 flags) { #if DEBUG log_debug("zone: %{dnsname}: %p: status %08x + %08x -> %08x", zone_origin(zone_desc), zone_desc, zone_desc->_status_flags, flags, zone_desc->_status_flags|flags); #endif zone_desc->_status_flags |= flags; } u32 zone_get_set_status(zone_desc_s *zone_desc, u32 flags) { #if DEBUG log_debug("zone: %{dnsname}: %p: status %08x + %08x -> %08x", zone_origin(zone_desc), zone_desc, zone_desc->_status_flags, flags, zone_desc->_status_flags|flags); #endif u32 ret = zone_desc->_status_flags & flags; zone_desc->_status_flags |= flags; return ret; } void zone_clear_status(zone_desc_s *zone_desc, u32 flags) { #if DEBUG log_debug("zone: %{dnsname}: %p: status %08x - %08x -> %08x", zone_origin(zone_desc), zone_desc, zone_desc->_status_flags, flags, zone_desc->_status_flags&~flags); #endif zone_desc->_status_flags &= ~flags; if((flags & ZONE_STATUS_PROCESSING) == 0) { // poke database_fire_zone_processed(zone_desc); } } u32 zone_get_status(const zone_desc_s *zone_desc) { return zone_desc->_status_flags; } host_address* zone_transfer_source_copy(const u8 *domain) { host_address *transfer_source; zone_desc_s *zone_desc = zone_acquirebydnsname(domain); if(zone_desc != NULL) { if(zone_desc->transfer_source != NULL) { transfer_source = host_address_copy_list(zone_desc->transfer_source); } else { transfer_source = NULL; } zone_release(zone_desc); } else if(g_config->transfer_source != NULL) { transfer_source = host_address_copy_list(g_config->transfer_source); } else { transfer_source = NULL; } return transfer_source; } ya_result zone_transfer_source_tcp_connect(const host_address *server, host_address **current_transfer_sourcep, input_stream *is, output_stream *os, int to_sec) { if((server == NULL) || (is == NULL) || (os == NULL) || (current_transfer_sourcep == NULL)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } host_address *current_transfer_source = *current_transfer_sourcep; ya_result ret; if(current_transfer_source == NULL) { log_debug("zone_transfer_source_tcp_connect: connection to %{hostaddr}", server); ret = tcp_input_output_stream_connect_host_address(server, is, os, to_sec); } else { ret = ERROR; // generic error for(;;) { if(current_transfer_source != NULL) { log_debug("zone_transfer_source_tcp_connect: connection to %{hostaddr} binding to %{hostaddr}", server, current_transfer_source); if(ISOK(ret = tcp_input_output_stream_connect_host_address_ex(server, is, os, current_transfer_source, g_config->xfr_connect_timeout))) { *current_transfer_sourcep = current_transfer_source; break; } if(!((ret == MAKE_ERRNO_ERROR(EADDRNOTAVAIL)) || (ret == MAKE_ERRNO_ERROR(EINVAL)))) { *current_transfer_sourcep = current_transfer_source; break; } current_transfer_source = current_transfer_source->next; while((current_transfer_source != NULL) && (server->version != current_transfer_source->version)) { current_transfer_source = current_transfer_source->next; } } else { log_warn("axfr: could not find a valid bind point to query a transfer from %{hostaddr}", server); *current_transfer_sourcep = NULL; break; } } } return ret; } #if ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT && ZDB_HAS_MASTER_SUPPORT void zone_dnssec_status_update(zdb_zone *zone) { u8 zone_dnssec_type = zone_policy_guess_dnssec_type(zone); u8 maintain_mode = zone_get_maintain_mode(zone); bool update_chain0 = FALSE; switch(zone_dnssec_type) { case ZONE_DNSSEC_FL_NOSEC: { if((maintain_mode & ZDB_ZONE_MAINTAIN_MASK) != 0) { zdb_rr_label_flag_and(zone->apex, ~(ZDB_RR_LABEL_NSEC | ZDB_RR_LABEL_NSEC3 | ZDB_RR_LABEL_NSEC3_OPTOUT)); zone_set_maintain_mode(zone, 0); } break; } case ZONE_DNSSEC_FL_NSEC: { if((maintain_mode & ZDB_ZONE_MAINTAIN_NSEC) == 0) { zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC); zdb_rr_label_flag_and(zone->apex, ~(ZDB_RR_LABEL_NSEC3 | ZDB_RR_LABEL_NSEC3_OPTOUT)); zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC); } break; } case ZONE_DNSSEC_FL_NSEC3: { if((maintain_mode & ZDB_ZONE_MAINTAIN_NSEC3) == 0) { zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC3); zdb_rr_label_flag_and(zone->apex, ~(ZDB_RR_LABEL_NSEC | ZDB_RR_LABEL_NSEC3_OPTOUT)); zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3); update_chain0 = TRUE; } break; } case ZONE_DNSSEC_FL_NSEC3_OPTOUT: { if((maintain_mode & ZDB_ZONE_MAINTAIN_NSEC3) == 0) { zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC3 | ZDB_RR_LABEL_NSEC3_OPTOUT); zdb_rr_label_flag_and(zone->apex, ~(ZDB_RR_LABEL_NSEC)); zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT); update_chain0 = TRUE; } break; } } if(update_chain0) { zdb_zone_lock(zone, ZDB_ZONE_MUTEX_LOAD); nsec3_zone_update_chain0_links(zone); zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_LOAD); } } u8 zone_policy_guess_dnssec_type(zdb_zone *zone) { u8 zone_dnssec_type = ZONE_DNSSEC_FL_NOSEC; if(zdb_zone_has_nsec_records(zone)) { zone_dnssec_type = ZONE_DNSSEC_FL_NSEC; } else if(zdb_zone_has_nsec3_records(zone)) { if(zdb_zone_has_nsec3_optout_chain(zone)) { zone_dnssec_type = ZONE_DNSSEC_FL_NSEC3_OPTOUT; } else { zone_dnssec_type = ZONE_DNSSEC_FL_NSEC3; } } return zone_dnssec_type; } bool zone_policy_key_suite_is_marked_processed(zone_desc_s *zone_desc, const struct dnssec_policy_key_suite *kr) { mutex_lock(&zone_desc->lock); ptr_node *node = ptr_set_find(&zone_desc->dnssec_policy_processed_key_suites, kr->name); mutex_unlock(&zone_desc->lock); return node != NULL; } bool zone_policy_key_suite_mark_processed(zone_desc_s *zone_desc, const struct dnssec_policy_key_suite *kr) { bool ret = FALSE; mutex_lock(&zone_desc->lock); ptr_node *node = ptr_set_insert(&zone_desc->dnssec_policy_processed_key_suites, kr->name); if(node->value != NULL) { node->value = (struct dnssec_policy_key_suite*)kr; ret = TRUE; } mutex_unlock(&zone_desc->lock); return ret; } void zone_policy_key_suite_unmark_processed(zone_desc_s *zone_desc, const struct dnssec_policy_key_suite *kr) { mutex_lock(&zone_desc->lock); ptr_set_delete(&zone_desc->dnssec_policy_processed_key_suites, kr->name); mutex_unlock(&zone_desc->lock); } #endif /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server-rw.c0000644000000000000000000000013114505005533020772 xustar000000000000000030 mtime=1695812443.474996968 29 atime=1695812445.78203001 30 ctime=1695812495.671744531 yadifa-2.6.5-11201/sbin/yadifad/server-rw.c0000664000374500037450000012634014505005533020743 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup server Server * @ingroup yadifad * @brief multithreaded reader-writer server * * Multiples threads for UDP on a different socket per interface. * One thread per interface for TCP, dispatching accepts to worker threads. (for now) * * One weakness: every single test of a similar mechanism shows that this is MUCH slower than the simple "mt" model. * * This is tested in hope that although the maximum throughput will be reduced, no packets will be lost * in case of long DB locks. * * As a side note, it is trivial that a different model of database would also solve the issue. * The most obvious one being using two zones images, alternating the visible and edited one. * This solution is of course unacceptable for a big zone as it greatly increases the resident memory usage. * * * @{ */ // keep this order --> #include "server-config.h" #ifndef WIN32 #ifndef __USE_GNU #define __USE_GNU 1 #endif #define _GNU_SOURCE 1 #include #endif #if defined __FreeBSD__ #include #include typedef cpuset_t cpu_set_t; #endif // <-- keep this order #include "server_context.h" #include #include #include #include #include #include #include #include #include #include #include #include #define ZDB_JOURNAL_CODE 1 #include #if ZDB_HAS_LOCK_DEBUG_SUPPORT #include "dnsdb/zdb-zone-lock-monitor.h" #endif #include "server.h" #include "log_query.h" #include "rrl.h" #include "process_class_ch.h" #include "notify.h" #include "log_statistics.h" #include "signals.h" #include "dynupdate_query_service.h" #if HAS_EVENT_DYNAMIC_MODULE #include "dynamic-module-handler.h" #endif #define SVRPLBIN_TAG 0x4e49424c50525653 #define SVRPLBOT_TAG 0x544f424c50525653 #if 1 // def SO_REUSEPORT // allow an external definition of the backlog queue size and L1 parameters #ifndef SERVER_RW_BACKLOG_QUEUE_SIZE //#define SERVER_RW_BACKLOG_QUEUE_SIZE 0x40000 // 256k slots : 16MB //#define SERVER_RW_BACKLOG_QUEUE_SIZE 0x80000 // 512k slots : 32MB #define SERVER_RW_BACKLOG_QUEUE_SIZE 0x4000 // 16k slots #endif #define NETWORK_THREAD_CONTEXT_FAST_MESSAGE_COUNT 3 // do NOT change this value #ifndef SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE #define SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE 128 #define SERVER_RW_L1_DATA_LINE_ALIGNED_SHIFT 7 //#define SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE 512 //#define SERVER_RW_L1_DATA_LINE_ALIGNED_SHIFT 9 #elif ((1 << SERVER_RW_L1_DATA_LINE_ALIGNED_SHIFT) != SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE) #error "2^" TOSTRING(SERVER_RW_L1_DATA_LINE_ALIGNED_SHIFT) " != " TOSTRING(SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE) " : please fix" #endif // DEBUG build: log debug 5 of incoming wire #define DUMP_UDP_RW_RECEIVED_WIRE 0 // DEBUG build: log debug 5 of outgoing wire #define DUMP_UDP_RW_OUTPUT_WIRE 0 extern logger_handle* g_statistics_logger; #define RWNTCTXS_TAG 0x53585443544e5752 #define RWNTCTX_TAG 0x585443544e5752 struct msg_hdr_s { union socketaddress_46 sa; u8 ctrl[MESSAGE_DATA_CONTROL_BUFFER_SIZE]; int blk_count; // 16 int msg_size; // 16 int sa_len; // 8 int ctrl_len; // 8 }; struct msg_data_s { struct msg_hdr_s hdr; u8 data[1]; // keep this 1 value }; typedef struct msg_data_s msg_data_s; union msg_cell_u { struct msg_data_s data; // this is an UNION, l1_data is there to specify the size u8 l1_data[SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE]; // L1 data cache line size, ensures the size is right }; typedef union msg_cell_u msg_cell_u; struct network_thread_context_s { network_thread_context_base_t base; thread_t idr; thread_t idw; // should be aligned with 64 #ifndef WIN32 volatile message_data *next_message __attribute__ ((aligned (SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE))); #else volatile message_data* next_message; #endif volatile msg_cell_u *backlog_enqueue;// __attribute__ ((aligned (SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE))); volatile const msg_cell_u *backlog_dequeue;// __attribute__ ((aligned (SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE))); msg_cell_u * backlog_queue_limit; // &backlog_queue[SERVER_RW_BACKLOG_QUEUE_SIZE]; mutex_t mtx; cond_t cond; // should be aligned with 64 #ifndef WIN32 server_statistics_t statistics __attribute__ ((aligned (SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE))); #else server_statistics_t statistics; #endif // should be aligned with 64 #ifndef WIN32 message_data_with_buffer in_message[NETWORK_THREAD_CONTEXT_FAST_MESSAGE_COUNT] __attribute__ ((aligned (SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE))); // used by the reader #else message_data_with_buffer in_message[NETWORK_THREAD_CONTEXT_FAST_MESSAGE_COUNT]; // used by the reader #endif message_data_with_buffer out_message; // used by the writer // should be aligned with 64 #ifndef WIN32 msg_cell_u backlog_queue[/*SERVER_RW_BACKLOG_QUEUE_SIZE*/ + 1] __attribute__ ((aligned (SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE))); #else msg_cell_u backlog_queue[/*SERVER_RW_BACKLOG_QUEUE_SIZE*/ +1]; #endif }; typedef struct network_thread_context_s network_thread_context_s; static network_thread_context_s* network_thread_context_new_instance(size_t backlog_queue_slots, struct service_worker_s *worker, u16 sockfd_idx) { network_thread_context_s *ctx; size_t network_thread_context_real_size = sizeof(network_thread_context_s) + sizeof(msg_cell_u) * backlog_queue_slots; ctx = (network_thread_context_s*)malloc(network_thread_context_real_size); if(ctx == NULL) { return NULL; } memset(ctx, 0, sizeof(network_thread_context_s)); ctx->base.worker = worker; ctx->base.idx = sockfd_idx; ctx->base.sockfd = g_server_context.udp_socket[sockfd_idx]; ctx->base.statisticsp = &ctx->statistics; ctx->backlog_enqueue = &ctx->backlog_queue[0]; ctx->backlog_dequeue = &ctx->backlog_queue[0]; ctx->backlog_queue_limit = &ctx->backlog_queue[backlog_queue_slots]; for(int i = 0; i < NETWORK_THREAD_CONTEXT_FAST_MESSAGE_COUNT; ++i) { message_data_with_buffer_init(&ctx->in_message[i]); // recv message_reset_control(&ctx->in_message[i].message); } message_data_with_buffer_init(&ctx->out_message); // recv reply message_reset_control(&ctx->out_message.message); ctx->backlog_queue_limit->data.hdr.blk_count = 0; // implicitely done by the memset, but I want to be absolutely clear about this ctx->backlog_queue_limit->data.hdr.msg_size = 0; mutex_init(&ctx->mtx); cond_init(&ctx->cond); return ctx; } static void network_thread_context_delete(network_thread_context_s *ctx) { if(ctx != NULL) { cond_finalize(&ctx->cond); mutex_destroy(&ctx->mtx); message_finalize(&ctx->out_message.message); for(int i = NETWORK_THREAD_CONTEXT_FAST_MESSAGE_COUNT - 1; i >= 0; --i) { message_finalize(&ctx->in_message[i].message); } free(ctx); } } struct network_thread_context_array { network_thread_context_s **contextes; size_t listen_count; size_t reader_by_fd; size_t backlog_queue_slots; }; typedef struct network_thread_context_array network_thread_context_array; static void network_thread_context_array_finalize(network_thread_context_array *ctxa) { for(size_t listen_idx = 0, sockfd_idx = 0; listen_idx < ctxa->listen_count; ++listen_idx) { for(u32 r = 0; r < ctxa->reader_by_fd; r++) { network_thread_context_s *ctx = ctxa->contextes[sockfd_idx]; if(ctx != NULL) { log_debug("network_thread_context_array_finalize: %u/%u sockfd %i and thread %p/worker %u", (u32)listen_idx, (u32)ctxa->listen_count, sockfd_idx, ctx->base.worker->tid, ctx->base.worker->worker_index); network_thread_context_delete(ctx); } else { log_debug("network_thread_context_array_finalize: %u/%u sockfd %i had no context", (u32)listen_idx, (u32)ctxa->listen_count, sockfd_idx); } ++sockfd_idx; } } free(ctxa->contextes); } static ya_result network_thread_context_array_init(network_thread_context_array *ctxa, size_t listen_count, size_t reader_by_fd, size_t backlog_queue_slots, struct service_worker_s *worker) { network_thread_context_s **contextes; MALLOC_OBJECT_ARRAY(contextes, network_thread_context_s*, listen_count * reader_by_fd, RWNTCTXS_TAG); // the memory allocation macro without _OR_DIE suffix will not abort on insufficient memory if(contextes == NULL) { return MAKE_ERRNO_ERROR(ENOMEM); } memset(contextes, 0, listen_count * reader_by_fd * sizeof(network_thread_context_s*)); // there is no leak, the pointer is right there: ctxa->contextes = contextes; ctxa->listen_count = listen_count; ctxa->reader_by_fd = reader_by_fd; ctxa->backlog_queue_slots = backlog_queue_slots; for(size_t listen_idx = 0, sockfd_idx = 0; listen_idx < listen_count; ++listen_idx) { for(u32 r = 0; r < reader_by_fd; r++) { network_thread_context_s *ctx; ctx = network_thread_context_new_instance(backlog_queue_slots, worker, sockfd_idx); if(ctx == NULL) { network_thread_context_array_finalize(ctxa); return MAKE_ERRNO_ERROR(ENOMEM); } contextes[sockfd_idx] = ctx; /* * Update the select read set for the current interface (udp + tcp) */ ++sockfd_idx; } } return SUCCESS; } static void server_rw_set_cpu_affinity(int index, int w0s1) { #if HAS_PTHREAD_SETAFFINITY_NP int cpu_count = sys_get_cpu_count(); if(cpu_count < 0) { cpu_count = 1; } int affinity_with = (g_config->thread_affinity_base + (index * 2 + w0s1) * g_config->thread_affinity_multiplier) % cpu_count; log_info("server-rw: receiver setting affinity with virtual cpu %i", affinity_with); #if __NetBSD__ cpuset_t* mycpu = cpuset_create(); if(mycpu != NULL) { cpuset_zero(mycpu); cpuset_set((cpuid_t)affinity_with, mycpu); if(pthread_setaffinity_np(thread_self(), cpuset_size(mycpu), mycpu) != 0) { #pragma message("TODO: report errors") // NetBSD } cpuset_destroy(mycpu); } else { } #elif defined(WIN32) #pragma message("TODO: implement") // WIN32 #else cpu_set_t mycpu; CPU_ZERO(&mycpu); CPU_SET(affinity_with, &mycpu); pthread_setaffinity_np(thread_self(), sizeof(cpu_set_t), &mycpu); #endif #else (void)index; (void)w0s1; #endif } static void* server_rw_udp_receiver_thread(void *parms) { struct network_thread_context_s *ctx = (struct network_thread_context_s*)parms; u64 *local_statistics_udp_input_count = (u64*)&ctx->statistics.udp_input_count; ctx->idr = thread_self(); ssize_t n; int fd = ctx->base.sockfd; int next_message_index = 0; // ^ 1 ^ 1 ... log_debug("server_rw_udp_receiver_thread(%i, %i): started", ctx->base.idx, fd); socketaddress sa; socklen_t sa_len = sizeof(sa); getsockname(fd, &sa.sa, &sa_len); log_info("waiting for udp messages for %{sockaddr}", &sa); server_rw_set_cpu_affinity(ctx->base.idx, 0); // const void *nullptr = NULL; tcp_set_recvtimeout(fd, 1, 0); for(;;) { message_data *mesg = &ctx->in_message[next_message_index].message; message_recv_udp_reset(mesg); message_reset_control_size(mesg); n = message_recv_udp(mesg, fd); if(n >= DNS_HEADER_LENGTH) { local_statistics_udp_input_count++; #if DEBUG mesg->recv_us = timeus(); log_debug("server_rw_udp_receiver_thread: recvfrom: got %d bytes from %{sockaddr}", n, message_get_sender_sa(mesg)); #if DUMP_UDP_RW_RECEIVED_WIRE log_memdump_ex(g_server_logger, MSG_DEBUG5, mesg->buffer, n, 16, OSPRINT_DUMP_HEXTEXT); #endif #endif #if __FreeBSD__ if(message_control_size(mesg) == 0) { message_clear_control(mesg); } #endif // now the trick: either direct queue, either delayed queue mutex_lock(&ctx->mtx); if(ctx->next_message == NULL) { // the sender has room for more // needs to be fast as this is the (most common) fast lane ctx->next_message = mesg; // notify the other side it has to do some job #if DEBUG mesg->pushed_us = timeus(); #endif cond_notify_one(&ctx->cond); mutex_unlock(&ctx->mtx); next_message_index = (next_message_index + 1) % NETWORK_THREAD_CONTEXT_FAST_MESSAGE_COUNT; // next_message is only set to NULL when the sender took the previous one // and it only takes the previous one when the backlog is empty // so ... #if DEBUG1 log_debug("server_rw_udp_receiver_thread(%i, %i): queued in the fast lane", ctx->base.idx, fd); #endif } else { // does not need to be fast (as we are already choking) // copy the bytes in the delayed queue (if there is room available, // else wait ... int blk_count = (message_get_size(mesg) + offsetof(struct msg_data_s, data) + SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE - 1) >> SERVER_RW_L1_DATA_LINE_ALIGNED_SHIFT; msg_cell_u *cell = (msg_cell_u *)ctx->backlog_enqueue; msg_cell_u *cell_next = cell + blk_count; if(cell >= ctx->backlog_dequeue) // we are on the last half { // can fill up to the end of the buffer const msg_cell_u *cell_limit = ctx->backlog_queue_limit; //&ctx->backlog_queue[SERVER_RW_BACKLOG_QUEUE_SIZE]; if(cell_next <= cell_limit) { // copy the content #if DEBUG log_debug("%i: push %04hx", fd, ntohs(message_get_id(mesg))); #endif // keep the relevant data from the message message_copy_sender_to_sa(mesg, &cell->data.hdr.sa.sa); cell->data.hdr.ctrl_len = message_copy_control(mesg, cell->data.hdr.ctrl, sizeof(cell->data.hdr.ctrl)); cell->data.hdr.msg_size = message_get_size(mesg); yassert(cell->data.hdr.msg_size <= 4096); // as none of the UDP test are that big (130 max) cell->data.hdr.blk_count = blk_count; cell->data.hdr.sa_len = message_get_sender_size(mesg); yassert((cell->data.hdr.sa_len > 0) && ((u32)cell->data.hdr.sa_len <= sizeof(struct sockaddr_in6))); message_copy_buffer(mesg, &cell->data.data, (blk_count * SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE) - offsetof(msg_data_s, data)); // if(cell_next == cell_limit) { if(ctx->backlog_dequeue > &ctx->backlog_queue[0]) { // loop cell_next = &ctx->backlog_queue[0]; } #if DEBUG else { // looping here would make the queue look empty : don't do it } #endif } #if DEBUG else { // the end hasn't been reached yet } #endif } else { // mark the cell as unused (a.k.a: looping) cell->data.hdr.msg_size = 0; // loop cell = &ctx->backlog_queue[0]; cell_next = cell + blk_count; // now update the limit and test for overflow const msg_cell_u *cell_limit = (const msg_cell_u *)ctx->backlog_dequeue; // we have to leave at least one block if(cell_next < cell_limit) { // copy the content // keep the relevant data from the message message_copy_sender_to_sa(mesg, &cell->data.hdr.sa.sa); cell->data.hdr.ctrl_len = message_copy_control(mesg, cell->data.hdr.ctrl, sizeof(cell->data.hdr.ctrl)); cell->data.hdr.msg_size = message_get_size(mesg); yassert(cell->data.hdr.msg_size <= 4096); // as none of the UDP test are that big (130 max) cell->data.hdr.blk_count = blk_count; cell->data.hdr.sa_len = message_get_sender_size(mesg); yassert((cell->data.hdr.sa_len > 0) && ((u32)cell->data.hdr.sa_len <= sizeof(struct sockaddr_in6))); message_copy_buffer(mesg, &cell->data.data, (blk_count * SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE) - offsetof(msg_data_s, data)); } else { cell_next = cell; // as the message is discarded } } } else // we are about to fill the buffer (soon) (cell < ctx->backlog_dequeue) { const msg_cell_u *cell_limit = (const msg_cell_u *)ctx->backlog_dequeue; // we have to leave at least one block if(cell_next < cell_limit) { // copy the content #if DEBUG log_debug("%i: push %04hx (<)", fd, ntohs(message_get_id(mesg))); #endif // keep the relevant data from the message message_copy_sender_to_sa(mesg, &cell->data.hdr.sa.sa); cell->data.hdr.ctrl_len = message_copy_control(mesg, cell->data.hdr.ctrl, sizeof(cell->data.hdr.ctrl)); cell->data.hdr.msg_size = message_get_size(mesg); yassert(cell->data.hdr.msg_size <= 4096); // as none of the UDP test are that big (130 max) cell->data.hdr.blk_count = blk_count; cell->data.hdr.sa_len = message_get_sender_size(mesg); yassert((cell->data.hdr.sa_len > 0) && ((u32)cell->data.hdr.sa_len <= sizeof(struct sockaddr_in6))); message_copy_buffer(mesg, &cell->data.data, (blk_count * SERVER_RW_L1_DATA_LINE_ALIGNED_SIZE) - offsetof(msg_data_s, data)); } else { cell_next = cell; // as the message is discarded #if DEBUG // full: lose it (?) log_debug("%i: full %04hx", fd, ntohs(message_get_id(mesg))); #endif } } ctx->backlog_enqueue = cell_next; cond_notify_one(&ctx->cond); mutex_unlock(&ctx->mtx); } } else if(n >= 0) { log_warn("server-rw: received %i bytes garbage from %{sockaddr} (%i)", n, message_get_sender_sa(mesg), fd); } else // n < 0 { int err = errno; if((err != EINTR) && (err != EAGAIN)) { /* * EAGAIN * Resource temporarily unavailable (may be the same value as EWOULDBLOCK) (POSIX.1) */ if(err != EBADF) { log_warn("server-rw: receiver: %r (%i)", MAKE_ERRNO_ERROR(err), fd); } // else we are shutting down log_debug("server_rw_udp_receiver_thread(%i, %i): recvfrom error: %r", ctx->base.idx, fd, MAKE_ERRNO_ERROR(err)); /* most likely: timeout/resource temporarily unavailable */ break; } if(service_should_reconfigure_or_stop(ctx->base.worker)) { log_debug("server_rw_udp_receiver_thread(%i, %i): will stop (reconfigure or stop)", ctx->base.idx, fd); break; } // else retry } } log_debug("server_rw_udp_receiver_thread(%i, %i): stopped", ctx->base.idx, fd); return NULL; } #if HAS_DYNUPDATE_SUPPORT /** * * Update MUST be delegated to the main thread (not an issue on the st model) * BUT the delegation requires all udp threads to stop * So it means that we cannot delegate from inside (else we get a deadlock) * So a thread must be started to handle the remainder of the processing * Said thread will delegate and send answer back to the client * * This implies I have to copy the message so the original structure can be used * for the next query. */ #endif ya_result server_rw_process_message_udp(struct network_thread_context_s *ctx, message_data *mesg) { ya_result ret; if(ISOK(ret = server_process_message_udp((network_thread_context_base_t*)ctx, mesg))) { if(ISOK(ret = message_send_udp(mesg, ctx->base.sockfd))) { ctx->statistics.udp_output_size_total += ret; } } return ret; } static void* server_rw_udp_sender_thread(void *parms) { struct network_thread_context_s *ctx = (struct network_thread_context_s*)parms; ctx->idw = thread_self(); log_debug("server_rw_udp_sender_thread(%i, %i): started", ctx->base.idx, ctx->base.sockfd); server_rw_set_cpu_affinity(ctx->base.idx, 1); size_t pool_buffer_size = 0x80000; u8 *pool_buffer_in; MALLOC_OBJECT_ARRAY_OR_DIE(pool_buffer_in, u8, pool_buffer_size, SVRPLBIN_TAG); u8 *pool_buffer_out; MALLOC_OBJECT_ARRAY_OR_DIE(pool_buffer_out, u8, pool_buffer_size, SVRPLBOT_TAG); for(int i = 0; i < NETWORK_THREAD_CONTEXT_FAST_MESSAGE_COUNT; ++i) { message_set_pool_buffer(&ctx->in_message[i].message, pool_buffer_in, pool_buffer_size); } message_set_pool_buffer(&ctx->out_message.message, pool_buffer_out, pool_buffer_size); for(;;) { #if DEBUG1 log_debug("server_rw_udp_sender_thread(%i, %i): dequeuing slow queries", ctx->base.idx, fd); #endif message_data *mesg; mutex_lock(&ctx->mtx); const msg_cell_u *cell = (const msg_cell_u*)ctx->backlog_dequeue; if(ctx->backlog_enqueue == cell) // empty backlog (the next to read is also the next to be filled) { // no item on the backlog #if DEBUG1 log_debug("server_rw_backlog_dequeue_message(%i, %i): dequeuing slow queries", ctx->base.idx, ctx->base.sockfd); #endif // wait for an item from the fastlane if((mesg = (message_data*)ctx->next_message) == NULL) { // no item, so wait for an event ... cond_timedwait(&ctx->cond, &ctx->mtx, ONE_SECOND_US); while((mesg = (message_data*)ctx->next_message) == NULL) { if(ctx->base.sockfd >= 0) { int tw = cond_timedwait(&ctx->cond, &ctx->mtx, ONE_SECOND_US); if(tw == ETIMEDOUT) { if(service_should_reconfigure_or_stop(ctx->base.worker)) { mutex_unlock(&ctx->mtx); free(pool_buffer_out); free(pool_buffer_in); log_debug("server_rw_udp_sender_thread(%i, %i): stopped (worker)", ctx->base.idx, ctx->base.sockfd); return NULL; } } #if DEBUG else { yassert(tw == 0); } #endif } else { mutex_unlock(&ctx->mtx); free(pool_buffer_out); free(pool_buffer_in); log_debug("server_rw_udp_sender_thread(%i, %i): stopped (wait->no-socket)", ctx->base.idx, ctx->base.sockfd); return NULL; // exit } } } // there was an item, and it's now on mesg : clear the fast lane slot ctx->next_message = NULL; mutex_unlock(&ctx->mtx); #if DEBUG mesg->popped_us = timeus(); log_debug("server-rw: look: %04hx %lluus %lluus (%i)", ntohs(message_get_id(mesg)), mesg->pushed_us - mesg->recv_us, mesg->popped_us - mesg->pushed_us, ctx->base.sockfd); #endif ya_result ret; if(FAIL(ret = server_rw_process_message_udp(ctx, mesg))) { if(ret != MAKE_ERRNO_ERROR(EBADF)) { if(ctx->base.sockfd >= 0) { if(ret == MAKE_ERRNO_ERROR(EINVAL)) { s32 dest_port = sockaddr_inet_port((struct sockaddr*)mesg->_msghdr.msg_name); // note dest_port is in network endian if(dest_port == 0) { log_err("server-rw: error replying to message %04hx %{dnsname} %{dnstype} from %{sockaddr}: invalid destination port", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), mesg->_msghdr.msg_name); } else if(dest_port < 0) { log_err("server-rw: error replying to message %04hx %{dnsname} %{dnstype} invalid IP family", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg)); } else { log_err("server-rw: error replying to message %04hx %{dnsname} %{dnstype} from %{sockaddr}: %r", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), mesg->_msghdr.msg_name, ret); } } #if DEBUG log_err("server-rw: look: %04hx: %r (%i)", ntohs(message_get_id(mesg)), ret, ctx->base.sockfd); if(mesg->_msghdr.msg_name != NULL) { log_err("server-rw: name %{sockaddr} (%llu)", mesg->_msghdr.msg_name, mesg->_msghdr.msg_namelen); } #ifndef WIN32 if(mesg->_msghdr.msg_control != NULL) { log_err("server-rw: control@%p (%llu)", mesg->_msghdr.msg_control, mesg->_msghdr.msg_controllen); log_memdump(MODULE_MSG_HANDLE, MSG_ERR, mesg->_msghdr.msg_control, mesg->_msghdr.msg_controllen, 32); } #else if(mesg->_msghdr.msg_control.buf != NULL) { log_err("server-rw: control@%p (%llu)", mesg->_msghdr.msg_control.buf, mesg->_msghdr.msg_control.len); log_memdump(MODULE_MSG_HANDLE, MSG_ERR, mesg->_msghdr.msg_control.buf, mesg->_msghdr.msg_control.len, 32); } #endif if(mesg->_msghdr.msg_iov != NULL) { log_err("server-rw: iov@%p (%i)", mesg->_msghdr.msg_iov, mesg->_msghdr.msg_iovlen); } if(mesg->_iovec.iov_base != NULL) { log_memdump(MODULE_MSG_HANDLE, MSG_ERR, mesg->_iovec.iov_base, mesg->_iovec.iov_len, 32); } log_err("server-rw: flags %x", mesg->_msghdr.msg_flags); #endif } else { log_err("server-rw: unexpected negative socket (%i)", ctx->base.sockfd); } message_reset_control(mesg); message_reset_buffer_size(mesg); } else { free(pool_buffer_out); free(pool_buffer_in); // log_debug("server_rw_udp_sender_thread(%i, %i): stopped (closed)", ctx->base.idx, fd); return NULL; } } } else // there are items on the backlog { const msg_cell_u *cell_limit = (const msg_cell_u *)ctx->backlog_enqueue; mutex_unlock(&ctx->mtx); // until we processed them all (cell until but not included to cell_limit) int loop_idx = 0; yassert(cell >= &ctx->backlog_queue[0] && cell <= ctx->backlog_queue_limit); if(cell > cell_limit) // go up to the end of the buffer (ctx->backlog_queue[SERVER_RW_BACKLOG_QUEUE_SIZE + 1]) { while(cell < ctx->backlog_queue_limit /*&ctx->backlog_queue[SERVER_RW_BACKLOG_QUEUE_SIZE]*/) { if(cell->data.hdr.msg_size == 0) // partial cell (which can only happen if there was no room anymore for a cell { break; } #if DEBUG u64 retrieve_start = timeus(); #endif mesg = &ctx->out_message.message; message_copy_sender_from_sa(mesg, &cell->data.hdr.sa.sa, cell->data.hdr.sa_len); #if DEBUG log_debug("%i: cell->data.hdr.ctrl_len=%i cell->data.hdr.blk_count=%i cell->data.hdr.blk_count=%i (>)", ctx->base.sockfd, cell->data.hdr.ctrl_len, cell->data.hdr.blk_count, cell->data.hdr.msg_size); #endif message_set_control(mesg, cell->data.hdr.ctrl, cell->data.hdr.ctrl_len); yassert(cell->data.hdr.msg_size < 65536); memcpy(message_get_buffer(mesg), &cell->data.data, cell->data.hdr.msg_size); message_set_size(mesg, cell->data.hdr.msg_size); #if DEBUG mesg->popped_us = timeus(); log_debug("%i: popd: %04hx %lluus (%i) (>)", ctx->base.sockfd, ntohs(message_get_id(mesg)), mesg->popped_us - retrieve_start, loop_idx); #endif ya_result ret; if(FAIL(ret = server_rw_process_message_udp(ctx, mesg))) { if(ret != MAKE_ERRNO_ERROR(EBADF)) { log_err("server-rw: could not process message %04hx (sock %i) (%r) (>)", ntohs(message_get_id(mesg)), ctx->base.sockfd, ret); if(g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE) { log_memdump_ex(MODULE_MSG_HANDLE, MSG_WARNING, message_get_buffer(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_BUFFER); } } } ++loop_idx; cell += cell->data.hdr.blk_count; yassert(cell >= &ctx->backlog_queue[0] && cell <= ctx->backlog_queue_limit); } cell = &ctx->backlog_queue[0]; } yassert(cell >= &ctx->backlog_queue[0] && cell <= ctx->backlog_queue_limit); while(cell < cell_limit) { #if DEBUG u64 retrieve_start = timeus(); #endif yassert(cell >= &ctx->backlog_queue[0] && cell <= ctx->backlog_queue_limit); mesg = &ctx->out_message.message; message_copy_sender_from_sa(mesg, &cell->data.hdr.sa.sa, cell->data.hdr.sa_len); log_debug("%i: cell->data.hdr.ctrl_len=%i", ctx->base.sockfd, cell->data.hdr.ctrl_len); message_set_control(mesg, cell->data.hdr.ctrl, cell->data.hdr.ctrl_len); memcpy(message_get_buffer(mesg), &cell->data.data, cell->data.hdr.msg_size); message_set_size(mesg, cell->data.hdr.msg_size); #if DEBUG mesg->popped_us = timeus(); log_debug("%i: popd: %04hx %lluus (%i)", ctx->base.sockfd, ntohs(message_get_id(mesg)), mesg->popped_us - retrieve_start, loop_idx); #endif ya_result ret; if(FAIL(ret = server_rw_process_message_udp(ctx, mesg))) { if(ret != MAKE_ERRNO_ERROR(EBADF)) { log_err("server-rw: could not process message %04hx (sock %i) (%r)", ntohs(message_get_id(mesg)), ctx->base.sockfd, ret); } } ++loop_idx; #if DEBUG const msg_cell_u *next_cell = cell + cell->data.hdr.blk_count; yassert((next_cell >= &ctx->backlog_queue[0]) && (next_cell <= ctx->backlog_queue_limit)); cell = next_cell; #else cell += cell->data.hdr.blk_count; yassert((cell >= &ctx->backlog_queue[0]) && (cell <= ctx->backlog_queue_limit)); #endif } yassert(cell >= &ctx->backlog_queue[0] && cell <= ctx->backlog_queue_limit); mutex_lock(&ctx->mtx); // cell ctx->backlog_dequeue = cell; mutex_unlock(&ctx->mtx); } } } static server_statistics_t server_statistics_sum; ya_result server_rw_query_loop(struct service_worker_s *worker) { ya_result ret; if(g_config->total_interfaces == 0 ) { return INVALID_STATE_ERROR; } if(g_server_context.tcp_socket_count <= 0) { return INVALID_STATE_ERROR; } if(g_server_context.listen_count <= 0) { return INVALID_STATE_ERROR; } log_query_set_mode(g_config->queries_log_type); bool log_statistics_enabled = (g_statistics_logger != NULL) && (g_config->server_flags & SERVER_FL_STATISTICS) != 0; log_debug("server-rw: statistics are %s", (log_statistics_enabled)?"enabled":"disabled"); if(log_statistics_enabled) { log_statistics_legend(); } /** * For each interface ... */ s32 reader_by_fd = g_server_context.udp_socket_count / g_server_context.udp_unit_per_interface; s32 cpu_count = sys_get_cpu_count(); if(reader_by_fd > cpu_count) { log_warn("server-rw: using too many threads per address is counter-productive on highly loaded systems (%d > %d)", reader_by_fd, cpu_count); } u64 server_run_loop_rate_tick = 0; u32 previous_tick = 0; log_info("server-rw: UDP working threads to be spawned: %i", (int)g_server_context.udp_interface_count * (int)g_server_context.udp_unit_per_interface * 2); struct thread_pool_s *server_udp_thread_pool = thread_pool_init_ex(g_server_context.udp_interface_count * g_server_context.udp_unit_per_interface * 2, 1, "svrudprw"); if(server_udp_thread_pool == NULL) { log_err("server-rw: unable to allocate working threads pool"); return THREAD_CREATION_ERROR; } size_t backlog_queue_slots = g_server_context.worker_backlog_queue_size; /* SERVER_RW_BACKLOG_QUEUE_SIZE*/; network_thread_context_array ctxa; if(FAIL(ret = network_thread_context_array_init(&ctxa, g_server_context.udp_interface_count, g_server_context.udp_unit_per_interface, backlog_queue_slots, worker))) { log_err("server-rw: unable to allocate context: %r", ret); return ret; } u32 initialised_context_indexes = 0; server_statistics_t **statistics_array = NULL; u32 statistics_array_size = g_server_context.udp_interface_count * g_server_context.udp_unit_per_interface; MALLOC_OBJECT_ARRAY_OR_DIE(statistics_array, server_statistics_t*, statistics_array_size, GENERIC_TAG); for(u32 udp_interface_index = 0; udp_interface_index < g_server_context.udp_interface_count; ++udp_interface_index) { for(u32 unit_index = 0; unit_index < g_server_context.udp_unit_per_interface; unit_index++) { network_thread_context_s *ctx = ctxa.contextes[initialised_context_indexes]; statistics_array[initialised_context_indexes] = &ctxa.contextes[initialised_context_indexes]->statistics; yassert(ctx != NULL); log_info("server-rw: thread #%i of UDP interface: %{sockaddr} using socket %i", unit_index, g_server_context.udp_interface[udp_interface_index]->ai_addr, ctx->base.sockfd); log_debug("server_rw_query_loop: pooling #%d=%d fd=%d", initialised_context_indexes, ctx->base.idx, ctx->base.sockfd); if(FAIL(ret = thread_pool_enqueue_call(server_udp_thread_pool, server_rw_udp_receiver_thread, ctx, NULL, "server-rw-recv"))) { log_err("server-rw: unable to schedule task : %r", ret); service_stop(worker->service); break; } if(FAIL(ret = thread_pool_enqueue_call(server_udp_thread_pool, server_rw_udp_sender_thread, ctx, NULL, "server-rw-send"))) { log_err("server-rw: unable to schedule task : %r", ret); service_stop(worker->service); mutex_lock(&ctx->mtx); cond_notify(&ctx->cond); mutex_unlock(&ctx->mtx); break; } /* * Update the select read set for the current interface (udp + tcp) */ ++initialised_context_indexes; } if(FAIL(ret)) { break; } } if(ISOK(ret)) { log_info("server-rw: UDP threads up"); server_tcp_accept_loop(worker, statistics_array, statistics_array_size); } else { log_err("server-rw: initialisation failed"); } free(statistics_array); log_info("server-rw: stopping the threads"); for(u32 udp_interface_index = 0, context_index = 0; udp_interface_index < g_server_context.udp_interface_count; ++udp_interface_index) { for(u32 unit_index = 0; unit_index < g_server_context.udp_unit_per_interface; unit_index++) { if(context_index >= initialised_context_indexes) // only happens in case of critical error { break; } network_thread_context_s *ctx = ctxa.contextes[context_index]; if(ctx != NULL) { log_info("thread #%i of UDP interface: %{sockaddr} using socket %i", unit_index, g_server_context.udp_interface[udp_interface_index]->ai_addr, ctx->base.sockfd); mutex_lock(&ctx->mtx); cond_notify(&ctx->cond); mutex_unlock(&ctx->mtx); } ++context_index; } } /* * Close all zone alarm handles * Close database alarm handle */ log_info("server-rw: cleaning up"); thread_pool_destroy(server_udp_thread_pool); server_udp_thread_pool = NULL; network_thread_context_array_finalize(&ctxa); log_info("server-rw: stopped", getpid_ex()); return SUCCESS; } ya_result server_rw_context_init(int workers_per_interface) { g_server_context.thread_per_udp_worker_count = 2; // set in stone g_server_context.thread_per_tcp_worker_count = 1; // set in stone g_server_context.udp_unit_per_interface = MAX(workers_per_interface , 1); g_server_context.tcp_unit_per_interface = 1; #ifdef SO_REUSEPORT g_server_context.reuse = 1; #else if(g_server_context.udp_unit_per_interface > 1) { log_warn("system does not support SO_REUSEPORT, downgrading UDP unit per interface from %i to 1", g_server_context.udp_unit_per_interface); g_server_context.udp_unit_per_interface = 1; } g_server_context.reuse = 0; #endif g_server_context.ready = 1; return SUCCESS; } #else // SO_REUSEPORT ya_result server_rw_query_loop() { log_err("SO_REUSEPORT is not supported on this architecture."); return FEATURE_NOT_SUPPORTED; } ya_result server_rw_context_init(int workers_per_interface) { log_err("SO_REUSEPORT is not supported on this architecture."); return FEATURE_NOT_SUPPORTED; } #endif // SO_REUSEPORT /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/server-mm.c0000644000000000000000000000013014505005533020752 xustar000000000000000030 mtime=1695812443.490997198 29 atime=1695812445.78203001 29 ctime=1695812495.67374456 yadifa-2.6.5-11201/sbin/yadifad/server-mm.c0000664000374500037450000010341214505005533020717 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** * @defgroup server Server * @ingroup yadifad * @brief multithreaded reader-writer server * * Multiples threads for UDP on a different socket per interface. * One thread per interface for TCP, dispatching accepts to worker threads. (for now) * * One weakness: every single test of a similar mechanism shows that this is MUCH slower than the simple "mt" model. * * This is tested in hope that although the maximum throughput will be reduced, no packets will be lost * in case of long DB locks. * * As a side note, it is trivial that a different model of database would also solve the issue. * The most obvious one being using two zones images, alternating the visible and edited one. * This solution is of course unacceptable for a big zone as it greatly increases the resident memory usage. * * * @{ */ // keep this order --> #include "server-config.h" #include #ifndef WIN32 #ifndef __USE_GNU #define __USE_GNU 1 #endif #define _GNU_SOURCE 1 #include #endif #if defined __FreeBSD__ #include #include typedef cpuset_t cpu_set_t; #endif // <-- keep this order #include "server_context.h" #include #include #include #include #include #include #include #include #include #include #include #include #define ZDB_JOURNAL_CODE 1 //#define THREAD_POOL_START_TIMEOUT (ONE_SECOND_US * 5) #define THREAD_POOL_START_TIMEOUT (ONE_SECOND_US * 30) #include #if ZDB_HAS_LOCK_DEBUG_SUPPORT #include "dnsdb/zdb-zone-lock-monitor.h" #endif #include "server.h" #include "log_query.h" #include "rrl.h" #include "process_class_ch.h" #include "notify.h" #include "log_statistics.h" #include "signals.h" #include "dynupdate_query_service.h" #if HAS_EVENT_DYNAMIC_MODULE #include "dynamic-module-handler.h" #endif #define TRY_EPOLL 0 #define TRY_POLL 0 #if TRY_EPOLL #include #endif #if TRY_POLL #include #endif #define SVRPLBIN_TAG 0x4e49424c50525653 #define SVRPLBOT_TAG 0x544f424c50525653 // allow an external definition of the backlog queue size and L1 parameters #define NETWORK_THREAD_CONTEXT_FAST_MESSAGE_COUNT 3 // do NOT change this value #ifndef SERVER_MM_L1_DATA_LINE_ALIGNED_SIZE #define SERVER_MM_L1_DATA_LINE_ALIGNED_SIZE 128 #define SERVER_MM_L1_DATA_LINE_ALIGNED_SHIFT 7 #define SERVER_MM_PACKETS_AT_ONCE 128 #elif ((1 << SERVER_MM_L1_DATA_LINE_ALIGNED_SHIFT) != SERVER_MM_L1_DATA_LINE_ALIGNED_SIZE) #error "2^" TOSTRING(SERVER_MM_L1_DATA_LINE_ALIGNED_SHIFT) " != " TOSTRING(SERVER_MM_L1_DATA_LINE_ALIGNED_SIZE) " : please fix" #endif // DEBUG build: log debug level 5 of incoming wire #define DUMP_UDP_RW_RECEIVED_WIRE 0 // DEBUG build: log debug 5 of outgoing wire #define DUMP_UDP_RW_OUTPUT_WIRE 0 extern logger_handle* g_statistics_logger; #define RWNTCTXS_TAG 0x53585443544e5752 #define RWNTCTX_TAG 0x585443544e5752 #define SMMMSGS_TAG 0x5347534d4d4d53 #define MMSGHDR_TAG 0x52444847534d4d // note: MODULE_MSG_HANDLE is defined in server_error.h struct network_thread_context_s { network_thread_context_base_t base; // should be aligned with 64 mutex_t mtx; cond_t cond; // should be aligned with 64 #ifndef WIN32 server_statistics_t statistics __attribute__ ((aligned (SERVER_MM_L1_DATA_LINE_ALIGNED_SIZE))); #else server_statistics_t statistics; #endif }; typedef struct network_thread_context_s network_thread_context_s; static network_thread_context_s* network_thread_context_new_instance(size_t backlog_queue_slots, struct service_worker_s *worker, u16 sockfd_idx) { network_thread_context_s *ctx; (void)backlog_queue_slots; size_t network_thread_context_real_size = sizeof(network_thread_context_s); ctx = (network_thread_context_s*)malloc(network_thread_context_real_size); if(ctx == NULL) { return NULL; } memset(ctx, 0, sizeof(network_thread_context_s)); ctx->base.worker = worker; ctx->base.idx = sockfd_idx; ctx->base.sockfd = g_server_context.udp_socket[sockfd_idx]; //ctx->base.must_stop = FALSE; // implicit with the memset ctx->base.statisticsp = &ctx->statistics; mutex_init(&ctx->mtx); cond_init(&ctx->cond); return ctx; } static void network_thread_context_delete(network_thread_context_s *ctx) { if(ctx != NULL) { cond_finalize(&ctx->cond); mutex_destroy(&ctx->mtx); free(ctx); } } struct network_thread_context_array { network_thread_context_s **contextes; size_t listen_count; size_t reader_by_fd; size_t backlog_queue_slots; }; typedef struct network_thread_context_array network_thread_context_array; static void network_thread_context_array_finalize(network_thread_context_array *ctxa) { for(size_t listen_idx = 0, sockfd_idx = 0; listen_idx < ctxa->listen_count; ++listen_idx) { for(u32 r = 0; r < ctxa->reader_by_fd; r++) { network_thread_context_s *ctx = ctxa->contextes[sockfd_idx]; if(ctx != NULL) { log_debug("network_thread_context_array_finalize: %u/%u sockfd %i and thread %p/worker %u", (u32)listen_idx, (u32)ctxa->listen_count, sockfd_idx, ctx->base.worker->tid, ctx->base.worker->worker_index); network_thread_context_delete(ctx); } else { log_debug("network_thread_context_array_finalize: %u/%u sockfd %i had no context", (u32)listen_idx, (u32)ctxa->listen_count, sockfd_idx); } ++sockfd_idx; } } free(ctxa->contextes); } static ya_result network_thread_context_array_init(network_thread_context_array *ctxa, size_t listen_count, size_t reader_by_fd, size_t backlog_queue_slots, struct service_worker_s *worker) { network_thread_context_s **contextes; MALLOC_OBJECT_ARRAY(contextes, network_thread_context_s*, listen_count * reader_by_fd, RWNTCTXS_TAG); // the memory allocation macro without _OR_DIE suffix will not abort on insufficient memory if(contextes == NULL) { return MAKE_ERRNO_ERROR(ENOMEM); } memset(contextes, 0, listen_count * reader_by_fd * sizeof(network_thread_context_s*)); // there is no leak, the pointer is right there: ctxa->contextes = contextes; ctxa->listen_count = listen_count; ctxa->reader_by_fd = reader_by_fd; ctxa->backlog_queue_slots = backlog_queue_slots; for(size_t listen_idx = 0, sockfd_idx = 0; listen_idx < listen_count; ++listen_idx) { for(u32 r = 0; r < reader_by_fd; r++) { network_thread_context_s *ctx; ctx = network_thread_context_new_instance(backlog_queue_slots, worker, sockfd_idx); if(ctx == NULL) { network_thread_context_array_finalize(ctxa); return MAKE_ERRNO_ERROR(ENOMEM); } log_debug("network_thread_context_array_init: %u/%u sockfd %i and thread %p/worker %u", (u32)listen_idx, (u32)listen_count, sockfd_idx, worker->tid, worker->worker_index); contextes[sockfd_idx] = ctx; /* * Update the select read set for the current interface (udp + tcp) */ ++sockfd_idx; } } return SUCCESS; } static void server_mm_set_cpu_affinity(int index) { #if HAS_PTHREAD_SETAFFINITY_NP int cpu_count = sys_get_cpu_count(); if(cpu_count < 0) { cpu_count = 1; } int affinity_with = g_config->thread_affinity_base + (index * g_config->thread_affinity_multiplier); affinity_with += affinity_with / cpu_count; affinity_with %= cpu_count; log_info("server-mm: worker setting affinity with virtual cpu %i", affinity_with); #if __NetBSD__ cpuset_t* mycpu = cpuset_create(); if(mycpu != NULL) { cpuset_zero(mycpu); cpuset_set((cpuid_t)affinity_with, mycpu); if(pthread_setaffinity_np(thread_self(), cpuset_size(mycpu), mycpu) != 0) { #pragma message("TODO: report errors") // NetBSD } cpuset_destroy(mycpu); } else { } #elif defined(WIN32) #pragma message("TODO: implement") // WIN32 #else cpu_set_t mycpu; CPU_ZERO(&mycpu); CPU_SET(affinity_with, &mycpu); pthread_setaffinity_np(thread_self(), sizeof(cpu_set_t), &mycpu); #endif #else (void)index; #endif } static void* server_mm_udp_worker_thread(void *parms) { struct network_thread_context_s *ctx = (struct network_thread_context_s*)parms; u64 *local_statistics_udp_input_count = (u64*)&ctx->statistics.udp_input_count; ctx->base.idr = thread_self(); int fd = ctx->base.sockfd; log_debug("server_mm_udp_worker_thread(%i, %i): started", ctx->base.idx, fd); socketaddress sa; socklen_t sa_len = sizeof(sa); getsockname(fd, &sa.sa, &sa_len); log_info("waiting for udp messages for %{sockaddr}", &sa); server_mm_set_cpu_affinity(ctx->base.idx); //struct timespec read_timeout = { 1, 0}; struct mmsghdr *udp_packets = NULL; struct mmsghdr *udp_packets_send = NULL; unsigned int udp_packets_count = SERVER_MM_PACKETS_AT_ONCE; const size_t packet_size = (g_config->edns0_max_size + 4095) & ~4095; #if !DNSCORE_HAS_MALLOC_DEBUG_SUPPORT u8 *packet_buffers = aligned_alloc(4096, udp_packets_count * packet_size); u8 *pool_buffers = aligned_alloc(4096, udp_packets_count * packet_size); #else // aligned_alloc isn't supported by the DNSCORE_HAS_MALLOC_DEBUG_SUPPORT feature u8 *packet_buffers = malloc(udp_packets_count * packet_size); u8 *pool_buffers = malloc(udp_packets_count * packet_size); #endif if(packet_buffers == NULL) { log_debug("server_mm_udp_worker_thread(%i, %i): out of memory", ctx->base.idx, fd); dnscore_shutdown(); return NULL; } message_data** messages; MALLOC_OBJECT_ARRAY_OR_DIE(messages, message_data*, udp_packets_count, SMMMSGS_TAG); MALLOC_OBJECT_ARRAY_OR_DIE(udp_packets, struct mmsghdr, udp_packets_count, MMSGHDR_TAG); MALLOC_OBJECT_ARRAY_OR_DIE(udp_packets_send, struct mmsghdr, udp_packets_count, MMSGHDR_TAG); for(u32 i = 0; i < udp_packets_count; ++i) { messages[i] = message_new_instance_ex(&packet_buffers[packet_size * i], packet_size); message_set_pool_buffer(messages[i], &pool_buffers[packet_size * i], packet_size); message_reset_control(messages[i]); message_copy_msghdr(messages[i], &udp_packets[i].msg_hdr); // udp_packets[i].msg_len = 0; } #if TRY_EPOLL struct epoll_event epoll_ev; memset(&epoll_ev, 0, sizeof(epoll_ev)); int epoll_fd = epoll_create1(EPOLL_CLOEXEC); epoll_ev.events = EPOLLIN|EPOLLHUP|EPOLLERR|EPOLLRDHUP|EPOLLRDBAND|EPOLLRDNORM|EPOLLET|EPOLLONESHOT; epoll_ev.data.fd = fd; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &epoll_ev); #endif #if TRY_POLL struct pollfd poll_fd; memset(&poll_fd, 0, sizeof(poll_fd)); poll_fd.events = POLLIN|POLLPRI|POLLHUP; poll_fd.fd = fd; #endif for(;;) { #if DEBUG log_debug("server_mm_udp_worker_thread(%i, %i): recvmmsg for %i packets", ctx->base.idx, fd, udp_packets_count); #endif #if TRY_EPOLL epoll_ev.events = EPOLLIN|EPOLLHUP|EPOLLERR|EPOLLRDHUP|EPOLLRDBAND|EPOLLRDNORM|EPOLLET|EPOLLONESHOT; int events = epoll_wait(epoll_fd, &epoll_ev, 1, -1); log_info("events=%i %r", events, ERRNO_ERROR); if(events <= 0) { if(service_should_reconfigure_or_stop(ctx->base.worker)) { log_debug("server_mm_udp_receiver_thread(%i, %i): will stop (reconfigure or stop)", ctx->base.idx, fd); break; } continue; } #endif #if TRY_POLL int events = poll(&poll_fd, 1, 1000); #if DEBUG log_info("events=%i %r (DEBUG)", events, ERRNO_ERROR); #endif if(events <= 0) { if(service_should_reconfigure_or_stop(ctx->base.worker)) { log_debug("server_mm_udp_receiver_thread(%i, %i): will stop (reconfigure or stop)", ctx->base.idx, fd); break; } continue; } #endif /// @note 20210107 edf -- recvmmsg timeout doesnt work as intended (cfr: man recvmmsg) /// a convoluted mechanism has been put in place to force getting out of the call when needed /// (search for "static const u8 dummy" in this file) int recvmmsg_ret = recvmmsg(fd, udp_packets, udp_packets_count, MSG_WAITFORONE, NULL /*&read_timeout*/); #if DEBUG log_debug("server_mm_udp_worker_thread(%i, %i): recvmmsg: %i", ctx->base.idx, fd, recvmmsg_ret); #endif if(recvmmsg_ret <= 0) { // note that due to an implementation detail (see BUGS in man recvmmsg) the errno code is unreliable int err = ERRNO_ERROR; #if DEBUG log_info("recvmmsg %i returned %i : %r", fd, recvmmsg_ret, err); #endif if(service_should_reconfigure_or_stop(ctx->base.worker)) { log_debug("server_mm_udp_receiver_thread(%i, %i): will stop (reconfigure or stop)", ctx->base.idx, fd); break; } if(recvmmsg_ret == 0) { continue; } else { log_err("server_mm_udp_worker_thread(%i, %i): recvmmsg: %r", ctx->base.idx, fd, err); break; } } int udp_packets_index = 0; #if DEBUG log_info("server_mm_udp_worker_thread: received %u packets (DEBUG)", recvmmsg_ret); #endif for(int i = 0; i < recvmmsg_ret; ++i) { message_data *mesg = messages[i]; unsigned int n = udp_packets[i].msg_len; if(n >= DNS_HEADER_LENGTH) { local_statistics_udp_input_count++; // this direct access to internals is not ideal, I have to fix that mesg->_msghdr.msg_namelen = udp_packets[i].msg_hdr.msg_namelen; mesg->_msghdr.msg_controllen = udp_packets[i].msg_hdr.msg_controllen; mesg->_msghdr.msg_iov->iov_len = udp_packets[i].msg_len; #if __FreeBSD__ #pragma message("Needs to be tested when FreeBSD supports this feature") if(mesg->_msghdr.msg_controllen == 0) { mesg->_msghdr.msg_control = NULL; } else { mesg->_msghdr.msg_control = mesg->_msghdr_control_buffer; } #endif #if DEBUG mesg->recv_us = timeus(); log_debug("server_mm_udp_worker_thread: recvfrom: got %d bytes from %{sockaddr}", n, message_get_sender_sa(mesg)); #if DUMP_UDP_RW_RECEIVED_WIRE log_memdump_ex(g_server_logger, MSG_DEBUG5, mesg->buffer, n, 16, OSPRINT_DUMP_HEXTEXT); #endif #endif s32 dest_port = sockaddr_inet_port(message_get_sender_sa(mesg)); if(dest_port > 0) { ya_result ret = server_process_message_udp((network_thread_context_base_t*)ctx, mesg); if(ISOK(ret)) { // that message will be replied to message_copy_msghdr(messages[i], &udp_packets_send[udp_packets_index].msg_hdr); ++udp_packets_index; } else { if(ret == SUCCESS_DROPPED) // should rename to SUCCESS_IGNORE { // ignore #if DEBUG log_info("server_mm_udp_worker_thread: good-dropped %d bytes from %{sockaddr}", n, message_get_sender_sa(mesg)); // DO NOT: message_log(MODULE_MSG_HANDLE, LOG_INFO, mesg); #endif } else if(ret == STOPPED_BY_APPLICATION_SHUTDOWN) { #if DEBUG log_info("server_mm_udp_worker_thread: STOPPED_BY_APPLICATION_SHUTDOWN ?"); #endif if(service_should_reconfigure_or_stop(ctx->base.worker)) { #if DEBUG log_info("server_mm_udp_worker_thread: STOPPED_BY_APPLICATION_SHUTDOWN !"); #endif /* * GOTO! * * Break out of two loops */ goto server_mm_udp_worker_thread_end; } } else { // something happened #if DEBUG log_info("server_mm_udp_worker_thread: bad-dropped %d bytes from %{sockaddr}", n, message_get_sender_sa(mesg)); message_log(MODULE_MSG_HANDLE, LOG_INFO, mesg); #endif } } } else if(dest_port == 0) { log_err("server-mm: error replying to message %04hx %{dnsname} %{dnstype} from %{sockaddr}: invalid destination port", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), mesg->_msghdr.msg_name); } else // if(dest_port < 0) { log_err("server-mm: error replying to message %04hx %{dnsname} %{dnstype} invalid IP family", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg)); }/* else { log_err("server-mm: error replying to message %04hx %{dnsname} %{dnstype} from %{sockaddr}: %r", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), mesg->_msghdr.msg_name, ret); }*/ } // end of the block if n > DNS_HEADER_LENGTH else { // discard } } // for all packets received loop if(udp_packets_index > 0) { struct mmsghdr *udp_packets_send_queue = udp_packets_send; #if DEBUG log_info("server_mm_udp_worker_thread: sending %u packets (DEBUG)", udp_packets_index); #endif for(;;) { int sendmmsg_ret = sendmmsg(fd, udp_packets_send_queue, udp_packets_index, 0); if(sendmmsg_ret >= 0) { #if DEBUG log_info("server_mm_udp_worker_thread: sent %u packets (DEBUG)", sendmmsg_ret); #endif for(int i = 0; i < sendmmsg_ret; ++i) { ctx->statistics.udp_output_size_total += udp_packets_send_queue[i].msg_hdr.msg_iov->iov_len; } udp_packets_index -= sendmmsg_ret; if(udp_packets_index <= 0) { break; } udp_packets_send_queue += sendmmsg_ret; } else { int err = errno; if(err != EINTR) { log_err("server_mm_udp_worker_thread: send failed: %r", MAKE_ERRNO_ERROR(err)); break; } } } } else { if(service_should_reconfigure_or_stop(ctx->base.worker)) { log_debug("server_mm_udp_receiver_thread(%i, %i): will stop (reconfigure or stop) (send)", ctx->base.idx, fd); break; } } for(int i = 0; i < recvmmsg_ret; ++i) { udp_packets[i].msg_hdr.msg_namelen = sizeof(((message_data*)NULL)->_sender); udp_packets[i].msg_hdr.msg_controllen = sizeof(((message_data*)NULL)->_msghdr_control_buffer); udp_packets[i].msg_hdr.msg_iov->iov_len = packet_size; udp_packets[i].msg_len = packet_size; } } // for "ever" loop server_mm_udp_worker_thread_end: #if DEBUG log_debug("server_mm_udp_worker_thread(%i, %i): stopping", ctx->base.idx, fd); #endif #if TRY_EPOLL close_ex(epoll_fd); #endif free(udp_packets_send); free(udp_packets); free(pool_buffers); free(packet_buffers); for(u32 i = 0; i < udp_packets_count; ++i) { message_free(messages[i]); } free(messages); #if DEBUG log_debug("server_mm_udp_worker_thread(%i, %i): stopped", ctx->base.idx, fd); #endif return NULL; } ya_result server_mm_query_loop(struct service_worker_s *worker) { ya_result ret; if(g_config->total_interfaces == 0 ) { return INVALID_STATE_ERROR; } if(g_server_context.tcp_socket_count <= 0) { return INVALID_STATE_ERROR; } if(g_server_context.listen_count <= 0) { return INVALID_STATE_ERROR; } log_query_set_mode(g_config->queries_log_type); bool log_statistics_enabled = (g_statistics_logger != NULL) && (g_config->server_flags & SERVER_FL_STATISTICS) != 0; log_debug("server-mm: statistics are %s", (log_statistics_enabled)?"enabled":"disabled"); if(log_statistics_enabled) { log_statistics_legend(); } s32 reader_by_fd = g_server_context.udp_socket_count / g_server_context.udp_unit_per_interface; s32 cpu_count = sys_get_cpu_count(); if(reader_by_fd > cpu_count) { log_warn("server-mm: using too many threads per address is counter-productive on highly loaded systems (%d > %d)", reader_by_fd, cpu_count); } u64 server_run_loop_rate_tick = 0; u32 previous_tick = 0; log_info("server-mm: UDP working threads to be spawned: %i", (int)g_server_context.udp_interface_count * (int)g_server_context.udp_unit_per_interface); struct thread_pool_s *server_udp_thread_pool = thread_pool_init_ex(g_server_context.udp_interface_count * g_server_context.udp_unit_per_interface, 1, "svrudpmm"); if(server_udp_thread_pool == NULL) { log_err("server-mm: unable to allocate working threads pool"); return THREAD_CREATION_ERROR; } size_t backlog_queue_slots = g_server_context.worker_backlog_queue_size; network_thread_context_array ctxa; if(FAIL(ret = network_thread_context_array_init(&ctxa, g_server_context.udp_interface_count, g_server_context.udp_unit_per_interface, backlog_queue_slots, worker))) { log_err("server-mm: unable to allocate context: %r", ret); return ret; } thread_pool_task_counter running_threads_counter; thread_pool_counter_init(&running_threads_counter, 0); server_statistics_t **statistics_array = NULL; u32 statistics_array_size = g_server_context.udp_interface_count * g_server_context.udp_unit_per_interface; MALLOC_OBJECT_ARRAY_OR_DIE(statistics_array, server_statistics_t*, statistics_array_size, GENERIC_TAG); u32 initialised_context_indexes = 0; for(u32 udp_interface_index = 0; udp_interface_index < g_server_context.udp_interface_count; ++udp_interface_index) { for(u32 unit_index = 0; unit_index < g_server_context.udp_unit_per_interface; unit_index++) { network_thread_context_s *ctx = ctxa.contextes[initialised_context_indexes]; statistics_array[initialised_context_indexes] = &ctxa.contextes[initialised_context_indexes]->statistics; yassert(ctx != NULL); ctx->base.must_stop = FALSE; log_info("server-mm: thread #%i of UDP interface: %{sockaddr} using socket %i", unit_index, g_server_context.udp_interface[udp_interface_index]->ai_addr, ctx->base.sockfd); log_debug("server_mm_query_loop: pooling #%d=%d fd=%d", initialised_context_indexes, ctx->base.idx, ctx->base.sockfd); if(FAIL(ret = thread_pool_enqueue_call(server_udp_thread_pool, server_mm_udp_worker_thread, ctx, &running_threads_counter, "server-mm-udp"))) { log_err("server-mm: unable to schedule task : %r", ret); service_stop(worker->service); break; } /* * Update the select read set for the current interface (udp + tcp) */ ++initialised_context_indexes; } if(FAIL(ret)) { break; } } if(ISOK(ret)) { log_info("server-mm: waiting for UDP threads"); ret = thread_pool_counter_wait_equal_with_timeout(&running_threads_counter, initialised_context_indexes, THREAD_POOL_START_TIMEOUT); if(FAIL(ret)) { s32 threads_running_count = thread_pool_counter_get_value(&running_threads_counter); log_err("server-mm: UDP threads spawn timed-out: expected %u thread but only %i spawned", initialised_context_indexes, threads_running_count); } } if(ISOK(ret)) { log_info("server-mm: UDP threads up"); server_tcp_accept_loop(worker, statistics_array, statistics_array_size); } else { log_err("server-mm: initialisation failed"); } free(statistics_array); { s32 threads_currently_running_count = thread_pool_counter_get_value(&running_threads_counter); log_debug("server-mm: threads_currently_running_count = %i", threads_currently_running_count); } log_info("server-mm: stopping the threads"); bool can_stop; do { for(u32 udp_interface_index = 0, context_index = 0; udp_interface_index < g_server_context.udp_interface_count; ++udp_interface_index) { for(u32 unit_index = 0; unit_index < g_server_context.udp_unit_per_interface; unit_index++) { if(context_index >= initialised_context_indexes) // only happens in case of a critical error { break; } network_thread_context_s *ctx = ctxa.contextes[context_index]; if(ctx != NULL) { ctx->base.must_stop = TRUE; } ++context_index; } } for(u32 udp_interface_index = 0, context_index = 0; udp_interface_index < g_server_context.udp_interface_count; ++udp_interface_index) { for(u32 unit_index = 0; unit_index < g_server_context.udp_unit_per_interface; unit_index++) { if(context_index >= initialised_context_indexes) // only happens in case of a critical error { break; } network_thread_context_s *ctx = ctxa.contextes[context_index]; if(ctx != NULL) { log_info("server-mm: thread #%i (%p) of UDP interface: %{sockaddr} using socket %i will be stopped", unit_index, ctx->base.worker->tid, g_server_context.udp_interface[udp_interface_index]->ai_addr, ctx->base.sockfd); // recvmmsg doesn't handle the timeout parameter in a very useful way (listed in the bugs section) // This unelegant code is a try to avoid using another system call to handle the issue. socketaddress *sa = (socketaddress*)g_server_context.udp_interface[udp_interface_index]->ai_addr; static const u8 dummy[12] = { 0xff, 0xff, 0xff, 0xff, // 15<sa.sa_family == AF_INET) { if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { for(;;) { log_debug("server-mm: thread #%i (%p) of UDPv4 interface: %{sockaddr} will be woken up by a message", unit_index, ctx->base.worker->tid, g_server_context.udp_interface[udp_interface_index]->ai_addr); int ret = sendto(sockfd, dummy, sizeof(dummy), 0, &sa->sa, sizeof(sa->sa4)); if(ret > 0) { break; } ret = ERRNO_ERROR; if(ret != MAKE_ERRNO_ERROR(EINTR)) { break; } } close_ex(sockfd); } } else if(sa->sa.sa_family == AF_INET6) { if((sockfd = socket(AF_INET6, SOCK_DGRAM, 0)) >= 0) { for(;;) { log_debug("server-mm: thread #%i (%p) of UDPv6 interface: %{sockaddr} will be woken up by a message", unit_index, ctx->base.worker->tid, g_server_context.udp_interface[udp_interface_index]->ai_addr); int ret = sendto(sockfd, dummy, sizeof(dummy), 0, &sa->sa, sizeof(sa->sa6)); if(ret > 0) { break; } ret = ERRNO_ERROR; if(ret != MAKE_ERRNO_ERROR(EINTR)) { break; } } close_ex(sockfd); } } mutex_lock(&ctx->mtx); cond_notify(&ctx->cond); mutex_unlock(&ctx->mtx); } ++context_index; } } s32 threads_still_running_count = thread_pool_counter_get_value(&running_threads_counter); log_debug("server-mm: threads_still_running_count = %i", threads_still_running_count); can_stop = (threads_still_running_count == 0); } while(!can_stop); thread_pool_counter_destroy(&running_threads_counter); /* * Close all zone alarm handles * Close database alarm handle */ log_info("server-mm: cleaning up: stopping thread pool"); thread_pool_destroy(server_udp_thread_pool); server_udp_thread_pool = NULL; log_info("server-mm: cleaning up: releasing context"); network_thread_context_array_finalize(&ctxa); log_info("server-mm: stopped", getpid_ex()); return SUCCESS; } ya_result server_mm_context_init(int workers_per_interface) { g_server_context.thread_per_udp_worker_count = 1; // set in stone g_server_context.thread_per_tcp_worker_count = 1; // set in stone g_server_context.udp_unit_per_interface = MAX(workers_per_interface , 1); g_server_context.tcp_unit_per_interface = 1; #ifdef SO_REUSEPORT g_server_context.reuse = 1; #else if(g_server_context.udp_unit_per_interface > 1) { log_warn("system does not support SO_REUSEPORT, downgrading UDP unit per interface from %i to 1", g_server_context.udp_unit_per_interface); g_server_context.udp_unit_per_interface = 1; } g_server_context.reuse = 0; #endif g_server_context.ready = 1; return SUCCESS; } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/dynamic-module-handler.c0000644000000000000000000000013214505005533023361 xustar000000000000000030 mtime=1695812443.493997241 30 atime=1695812445.783030024 30 ctime=1695812495.675744588 yadifa-2.6.5-11201/sbin/yadifad/dynamic-module-handler.c0000664000374500037450000005447214505005533023337 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "server-config.h" #define DYNAMIC_MODULE_HANDLER_C 1 #include #include #include #include #include #include "confs.h" struct dynamic_module_interface_chain; struct dynamic_module_dnskey_interface_chain; struct dynamic_module_interface_chain *g_dynamic_module_interface_chain = NULL; struct dynamic_module_dnskey_interface_chain *g_dynamic_module_dnskey_interface_chain = NULL; struct dynamic_module_statistics_interface_chain *g_dynamic_module_statistics_interface_chain = NULL; #include "dynamic-module-handler.h" #include "server.h" extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #define YDYNMOD_TAG 0x444f4d4e594459 #define YDYNMODA_TAG 0x41444f4d4e594459 #define YDYNMODI_TAG 0x49444f4d4e594459 #define YDYNMODK_TAG 0x4b444f4d4e594459 #define YDYNMODS_TAG 0x53444f4d4e594459 logger_handle *g_module_logger = LOGGER_HANDLE_SINK; #define CALLER_NAME "yadifad" struct dynamic_module { void *so; dynamic_module_interface_init *entry_point; char *path; struct dynamic_module_settings_args args; int rc; }; struct dynamic_module_interface_chain { struct dynamic_module_interface_chain *next; struct dynamic_module *module; struct dynamic_module_interface itf; }; struct dynamic_module_dnskey_interface_chain { struct dynamic_module_dnskey_interface_chain *next; struct dynamic_module *module; struct dynamic_module_dnskey_interface itf; }; struct dynamic_module_statistics_interface_chain { struct dynamic_module_statistics_interface_chain *next; struct dynamic_module *module; struct dynamic_module_statistics_interface itf; }; static ptr_set dynamic_module_set = PTR_SET_ASCIIZ_EMPTY; static mutex_t dynamic_module_mtx = MUTEX_INITIALIZER; /** * Trivial. */ ya_result dynamic_module_handler_init() { return SUCCESS; } /** * Trivial. */ ya_result dynamic_module_handler_finalize() { return SUCCESS; } /** * Loads a module given its full path name (with luck relative may work too ... so yes: full path) * Don't forget to take into account the choot. * * Modules should only be loaded AFTER the last fork. */ ya_result dynamic_module_handler_load(int argc, const char **argv) { if(argc <= 0) { return INVALID_ARGUMENT_ERROR; } const char *shared_object_path = argv[0]; log_debug("module: checking module '%s'", shared_object_path); ptr_node *node; mutex_lock(&dynamic_module_mtx); node = ptr_set_find(&dynamic_module_set, shared_object_path); if(node != NULL) { // already known mutex_unlock(&dynamic_module_mtx); return SUCCESS; } void *so = dlopen(shared_object_path, RTLD_NOLOAD); if(so == NULL) { so = dlopen(shared_object_path, RTLD_NOW/*|RTDL_LOCAL*/); if(so != NULL) { log_info("module: '%s': loaded", shared_object_path); // loaded // try to find the entry point void *f = dlsym(so, "module_interface_init"); if(f == NULL) { static const char suffix[] = "_interface_init"; char module_interface_init_name[48]; // get the last '/' const char *start = parse_skip_until_chars(shared_object_path, "/", 1); // get the first '.' const char *stop = parse_skip_until_chars(start, ".", 1); if(stop == start) { stop = start + strlen(start); } size_t len = stop - start; if(len <= sizeof(module_interface_init_name) - sizeof(suffix)) { memcpy(module_interface_init_name, start, len); memcpy(&module_interface_init_name[len], suffix, sizeof(suffix)); f = dlsym(so, module_interface_init_name); } } if(f == NULL) { mutex_unlock(&dynamic_module_mtx); log_err("module: '%s': failed to find the entry point", shared_object_path); dlclose(so); return INVALID_STATE_ERROR; } log_debug("module: '%s': got the entry point", shared_object_path); struct dynamic_module *module; MALLOC_OBJECT_OR_DIE(module, struct dynamic_module, YDYNMOD_TAG); MALLOC_OBJECT_ARRAY_OR_DIE(module->args.argv, char*, argc, YDYNMODA_TAG); module->so = so; #pragma message("You can safely ignore the pointer conversion warning. (To be safe, it's checked at runtime in the dnscore_arch_checkup() function.)") module->entry_point = (dynamic_module_interface_init*)f; module->path = strdup(shared_object_path); module->rc = 0; struct dynamic_module_settings_args *args = &module->args; args->sizeof_struct = sizeof(*args); args->argc = argc; memcpy(args->argv, argv, argc * sizeof(char*)); args->data_path = g_config->data_path; union dynamic_module_interfaces itfu; // DYNAMIC_MODULE_INTERFACE_ID { itfu.interface.sizeof_struct = sizeof(itfu.interface); if(ISOK(module->entry_point(DYNAMIC_MODULE_INTERFACE_ID, &itfu))) { // interface is supported log_debug("module: '%s': dynamic_module_interface is supported", shared_object_path); if(itfu.interface.on_startup == NULL) { itfu.interface.on_startup = dynamic_module_startup_callback_nop; } if(itfu.interface.on_settings_updated == NULL) { itfu.interface.on_settings_updated = dynamic_module_settings_callback_nop; } if(itfu.interface.on_shutdown == NULL) { itfu.interface.on_shutdown = dynamic_module_shutdown_callback_nop; } struct dynamic_module_interface_chain *ic; MALLOC_OBJECT_OR_DIE(ic, struct dynamic_module_interface_chain, YDYNMODI_TAG); ic->next = g_dynamic_module_interface_chain; ic->module = module; ++module->rc; memcpy(&ic->itf, &itfu.interface, sizeof(itfu.interface)); g_dynamic_module_interface_chain = ic; } else { log_debug("module: '%s': dynamic_module_interface is not supported", shared_object_path); } } // DYNAMIC_MODULE_DNSKEY_INTERFACE_ID { itfu.dnskey_interface.sizeof_struct = sizeof(itfu.dnskey_interface); if(ISOK(module->entry_point(DYNAMIC_MODULE_DNSKEY_INTERFACE_ID, &itfu))) { // interface is supported log_debug("module: '%s': dynamic_module_dnskey_interface is supported", shared_object_path); if(itfu.dnskey_interface.on_dnskey_created == NULL) { itfu.dnskey_interface.on_dnskey_created = dynamic_module_on_dnskey_callback_nop; } if(itfu.dnskey_interface.on_dnskey_publish == NULL) { itfu.dnskey_interface.on_dnskey_publish = dynamic_module_on_dnskey_callback_nop; } if(itfu.dnskey_interface.on_dnskey_activate == NULL) { itfu.dnskey_interface.on_dnskey_activate = dynamic_module_on_dnskey_callback_nop; } if(itfu.dnskey_interface.on_dnskey_revoke == NULL) { itfu.dnskey_interface.on_dnskey_revoke = dynamic_module_on_dnskey_callback_nop; } if(itfu.dnskey_interface.on_dnskey_inactive == NULL) { itfu.dnskey_interface.on_dnskey_inactive = dynamic_module_on_dnskey_callback_nop; } if(itfu.dnskey_interface.on_dnskey_delete == NULL) { itfu.dnskey_interface.on_dnskey_delete = dynamic_module_on_dnskey_callback_nop; } struct dynamic_module_dnskey_interface_chain *ic; MALLOC_OBJECT_OR_DIE(ic, struct dynamic_module_dnskey_interface_chain, YDYNMODK_TAG); ic->next = g_dynamic_module_dnskey_interface_chain; ic->module = module; ++module->rc; memcpy(&ic->itf, &itfu.dnskey_interface, sizeof(itfu.dnskey_interface)); g_dynamic_module_dnskey_interface_chain = ic; } else { log_debug("module: '%s': dynamic_module_dnskey_interface is not supported", shared_object_path); } } // DYNAMIC_MODULE_STATISTICS_ID { itfu.statistics_interface.sizeof_struct = sizeof(itfu.statistics_interface); if(ISOK(module->entry_point(DYNAMIC_MODULE_STATISTICS_ID, &itfu))) { // interface is supported log_debug("module: '%s': dynamic_module_statistics_interface is supported", shared_object_path); if(itfu.statistics_interface.on_statistics_update == NULL) { itfu.statistics_interface.on_statistics_update = dynamic_module_statistics_callback_nop; } struct dynamic_module_statistics_interface_chain *ic; MALLOC_OBJECT_OR_DIE(ic, struct dynamic_module_statistics_interface_chain, YDYNMODS_TAG); ic->next = g_dynamic_module_statistics_interface_chain; ic->module = module; ++module->rc; memcpy(&ic->itf, &itfu.statistics_interface, sizeof(itfu.statistics_interface)); g_dynamic_module_statistics_interface_chain = ic; } else { log_debug("module: '%s': dynamic_module_statistics_interface is not supported", shared_object_path); } } node = ptr_set_insert(&dynamic_module_set, module->path); node->key = module->path; node->value = module; mutex_unlock(&dynamic_module_mtx); return SUCCESS; } else { // failed to load ya_result ret = ERRNO_ERROR; mutex_unlock(&dynamic_module_mtx); log_err("module: '%s': failed to load: %s", shared_object_path, dlerror()); return ret; } } else { // already loaded, somehow ya_result ret = ERRNO_ERROR; mutex_unlock(&dynamic_module_mtx); log_err("module: '%s': already loaded (albeit not through this handler)", shared_object_path); return ret; } } ya_result dynamic_module_handler_load_from_command(const char *command) { //const char *command_limit = &command[strlen(command)]; int argc = 0; char *argv[128]; char tmp[PATH_MAX]; s32 n; for(;;) { if(argc == sizeof(argv) / sizeof(char*)) { n = -1; // too many parameters break; } n = parse_next_token(tmp, sizeof(tmp), command, " \t"); if(n <= 0) { break; } command += n; command = parse_skip_spaces(command); argv[argc++] = strdup(tmp); } ya_result ret; if(n >= 0) { ret = dynamic_module_handler_load(argc, (const char**)argv); } else { ret = INVALID_ARGUMENT_ERROR; // too many parameters } for(int i = 0; i < argc; ++i) { free(argv[i]); } return ret; } // interface void dynamic_module_startup() { struct dynamic_module_interface_chain *dc = g_dynamic_module_interface_chain; while(dc != NULL) { dc->itf.on_startup(); dc = dc->next; } } void dynamic_module_settings() { struct dynamic_module_interface_chain *dc = g_dynamic_module_interface_chain; if(dc != NULL) { do { dc->itf.on_settings_updated(&dc->module->args); dc = dc->next; } while(dc != NULL); } } void dynamic_module_shutdown() { struct dynamic_module_interface_chain *dc = g_dynamic_module_interface_chain; while(dc != NULL) { dc->itf.on_shutdown(); dc = dc->next; } } // dnskey_interface ya_result dynamic_module_on_dnskey_args_init(struct dynamic_module_on_dnskey_args *args, const dnssec_key *key, void *buffer, size_t buffer_size) { args->sizeof_struct = sizeof(*args); args->caller_name = CALLER_NAME; args->origin = dnskey_get_domain(key); args->rdata_size = key->vtbl->dnssec_key_rdatasize(key); if(args->rdata_size > buffer_size) { return BUFFER_WOULD_OVERFLOW; } key->vtbl->dnssec_key_writerdata(key, buffer, buffer_size); args->rdata = buffer; args->epoch_created = dnskey_get_created_epoch(key); args->epoch_publish = dnskey_get_publish_epoch(key); args->epoch_activate = dnskey_get_activate_epoch(key); args->epoch_revoke = 0; args->epoch_inactive = dnskey_get_inactive_epoch(key); args->epoch_delete = dnskey_get_delete_epoch(key); args->flags = dnskey_get_flags(key); args->tag = dnskey_get_tag_const(key); args->algorithm = dnskey_get_algorithm(key); return SUCCESS; } void dynamic_module_on_dnskey_args_finalize(struct dynamic_module_on_dnskey_args *args) { #if DEBUG ZEROMEMORY(args, sizeof(*args)); #else (void)args; #endif } void dynamic_module_on_dnskey_created(const dnssec_key *key) { struct dynamic_module_dnskey_interface_chain *dc = g_dynamic_module_dnskey_interface_chain; if(dc != NULL) { struct dynamic_module_on_dnskey_args args; char buffer[2048]; if(ISOK(dynamic_module_on_dnskey_args_init(&args, key, buffer, sizeof(buffer)))) { do { dc->itf.on_dnskey_created(&args); dc = dc->next; } while(dc != NULL); dynamic_module_on_dnskey_args_finalize(&args); } } } void dynamic_module_on_dnskey_publish(const dnssec_key *key) { struct dynamic_module_dnskey_interface_chain *dc = g_dynamic_module_dnskey_interface_chain; if(dc != NULL) { struct dynamic_module_on_dnskey_args args; char buffer[2048]; dynamic_module_on_dnskey_args_init(&args, key, buffer, sizeof(buffer)); do { dc->itf.on_dnskey_publish(&args); dc = dc->next; } while(dc != NULL); dynamic_module_on_dnskey_args_finalize(&args); } } void dynamic_module_on_dnskey_activate(const dnssec_key *key) { struct dynamic_module_dnskey_interface_chain *dc = g_dynamic_module_dnskey_interface_chain; if(dc != NULL) { struct dynamic_module_on_dnskey_args args; char buffer[2048]; dynamic_module_on_dnskey_args_init(&args, key, buffer, sizeof(buffer)); do { dc->itf.on_dnskey_activate(&args); dc = dc->next; } while(dc != NULL); dynamic_module_on_dnskey_args_finalize(&args); } } void dynamic_module_on_dnskey_revoke(const dnssec_key *key) { struct dynamic_module_dnskey_interface_chain *dc = g_dynamic_module_dnskey_interface_chain; if(dc != NULL) { struct dynamic_module_on_dnskey_args args; char buffer[2048]; dynamic_module_on_dnskey_args_init(&args, key, buffer, sizeof(buffer)); do { dc->itf.on_dnskey_revoke(&args); dc = dc->next; } while(dc != NULL); dynamic_module_on_dnskey_args_finalize(&args); } } void dynamic_module_on_dnskey_inactive(const dnssec_key *key) { struct dynamic_module_dnskey_interface_chain *dc = g_dynamic_module_dnskey_interface_chain; if(dc != NULL) { struct dynamic_module_on_dnskey_args args; char buffer[2048]; dynamic_module_on_dnskey_args_init(&args, key, buffer, sizeof(buffer)); do { dc->itf.on_dnskey_inactive(&args); dc = dc->next; } while(dc != NULL); dynamic_module_on_dnskey_args_finalize(&args); } } void dynamic_module_on_dnskey_delete(const dnssec_key *key) { struct dynamic_module_dnskey_interface_chain *dc = g_dynamic_module_dnskey_interface_chain; if(dc != NULL) { struct dynamic_module_on_dnskey_args args; char buffer[2048]; dynamic_module_on_dnskey_args_init(&args, key, buffer, sizeof(buffer)); do { dc->itf.on_dnskey_delete(&args); dc = dc->next; } while(dc != NULL); dynamic_module_on_dnskey_args_finalize(&args); } } void dynamic_module_on_statistics_update(server_statistics_t *st, u64 epoch) { struct dynamic_module_statistics_interface_chain *dc = g_dynamic_module_statistics_interface_chain; if(dc != NULL) { struct dynamic_module_statistics_args args; struct dynamic_module_statistics_args_buffers args_buffers; args.sizeof_struct = sizeof(args); args.epoch_us = epoch; args.input_loop_count = st->input_loop_count; args.input_timeout_count = st->input_timeout_count; args.loop_rate_counter = st->loop_rate_counter; args.loop_rate_elapsed = st->loop_rate_elapsed; args.udp_input_count = st->udp_input_count; args.udp_queries_count = st->udp_queries_count; args.udp_notify_input_count = st->udp_notify_input_count; args.udp_updates_count = st->udp_updates_count; args.udp_dropped_count = st->udp_dropped_count; args.udp_output_size_total = st->udp_output_size_total; args.udp_undefined_count = st->udp_undefined_count; args.udp_referrals_count = st->udp_referrals_count; args.tcp_input_count = st->tcp_input_count; args.tcp_queries_count = st->tcp_queries_count; args.tcp_notify_input_count = st->tcp_notify_input_count; args.tcp_updates_count = st->tcp_updates_count; args.tcp_dropped_count = st->tcp_dropped_count; args.tcp_output_size_total = st->tcp_output_size_total; args.tcp_undefined_count = st->tcp_undefined_count; args.tcp_referrals_count = st->tcp_referrals_count; args.tcp_axfr_count = st->tcp_axfr_count; args.tcp_ixfr_count = st->tcp_ixfr_count; args.tcp_overflow_count = st->tcp_overflow_count; args.rrl_slip = st->rrl_slip; args.rrl_drop = st->rrl_drop; args.udp_rcode_count = args_buffers.udp_rcode_buffer; args.tcp_rcode_count = args_buffers.tcp_rcode_buffer; args.udp_tsig_rcode_count = args_buffers.udp_tsig_rcode_buffer; args.tcp_tsig_rcode_count = args_buffers.tcp_tsig_rcode_buffer; args.rcode_count_size = DYNAMIC_MODULE_STATISTICS_RCODE_COUNT; args.tsig_rcode_count_size = DYNAMIC_MODULE_STATISTICS_TSIG_RCODE_COUNT; do { dc->itf.on_statistics_update(&args); dc = dc->next; } while(dc != NULL); } } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config-nsid.c0000644000000000000000000000013214505005533021237 xustar000000000000000030 mtime=1695812443.313994663 30 atime=1695812445.781029996 30 ctime=1695812495.677744617 yadifa-2.6.5-11201/sbin/yadifad/config-nsid.c0000664000374500037450000001322114505005533021200 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup config Configuration handling * @ingroup yadifad * @brief * * @{ */ #include "server-config.h" #include #include #include #include #include #include #include #include "server-config.h" extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #define NSIDNAME_TAG 0x454d414e4449534e #if DNSCORE_HAS_NSID_SUPPORT struct byte_array_s { u8 *bytes; u32 size; }; struct config_nsid_s { struct byte_array_s nsid; }; typedef struct config_nsid_s config_nsid_s; static ya_result config_set_byte_array(struct byte_array_s *dest, const u8 *bytes, u32 size) { if(dest->bytes != NULL) { log_warn("config: NSID has already been set, previous value overwritten"); if(dest->size != size) { free(dest->bytes); dest->bytes = NULL; dest->size = 0; } else // equal sizes { if(memcmp(dest->bytes, bytes, size) != 0) { memcpy(dest->bytes, bytes, size); } return SUCCESS; } } MALLOC_OR_DIE(u8*, dest->bytes, size, NSIDNAME_TAG); memcpy(dest->bytes, bytes, size); dest->size = size; return SUCCESS; } ya_result config_set_byte_array_from_ascii(const char *value, struct byte_array_s *dest, anytype settings) { (void)settings; ya_result return_code; return_code = config_set_byte_array(dest, (const u8*)value, strlen(value)); return return_code; } ya_result config_set_byte_array_from_hex(const char *value, struct byte_array_s *dest, anytype settings) { (void)settings; ya_result return_code; u32 value_len = strlen(value); u8 tmp[EDNS0_NSID_SIZE_MAX]; if(value_len > EDNS0_NSID_SIZE_MAX * 2) { return INVALID_ARGUMENT_ERROR; } return_code = base16_decode(value, value_len, tmp); if(ISOK(return_code)) { return_code = config_set_byte_array(dest, tmp, (u32)return_code); } return return_code; } #define CONFIG_TYPE config_nsid_s CONFIG_BEGIN(config_nsid_desc) {"ascii", offsetof(CONFIG_TYPE, nsid), (config_set_field_function*)config_set_byte_array_from_ascii, NULL,{._intptr=0}, sizeof(((CONFIG_TYPE*)0)->nsid), sizeof(((CONFIG_TYPE*)0)->nsid), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, {"hex", offsetof(CONFIG_TYPE, nsid), (config_set_field_function*)config_set_byte_array_from_hex, NULL,{._intptr=0}, sizeof(((CONFIG_TYPE*)0)->nsid), sizeof(((CONFIG_TYPE*)0)->nsid), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, //{"hostname", offsetof(CONFIG_TYPE, fieldname), (config_set_field_function*)config_set_search_or_domain, NULL,{._u8=RO_DOMAIN}, CONFIG_TABLE_SOURCE_NONE}, CONFIG_END(config_nsid_desc) #undef CONFIG_TYPE static config_nsid_s tmp_config_nsid = {{NULL, 0}}; static ya_result config_nsid_section_postprocess(struct config_section_descriptor_s *csd) { (void)csd; /* here check that the settings are right */ edns0_set_nsid(tmp_config_nsid.nsid.bytes, tmp_config_nsid.nsid.size); return SUCCESS; } ya_result config_register_nsid(s32 priority) { const char *section_name = "nsid"; ya_result return_code = config_register_struct(section_name, config_nsid_desc, &tmp_config_nsid, priority); if(ISOK(return_code)) { // hook a new finaliser before the standard one config_section_descriptor_s *section_desc = config_section_get_descriptor(section_name); config_section_descriptor_vtbl_s *vtbl = (config_section_descriptor_vtbl_s *)section_desc->vtbl; vtbl->postprocess = config_nsid_section_postprocess; } return return_code; } #endif /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config_control.c0000644000000000000000000000013114505005533022043 xustar000000000000000029 mtime=1695812443.31799472 30 atime=1695812445.781029996 30 ctime=1695812495.679744646 yadifa-2.6.5-11201/sbin/yadifad/config_control.c0000664000374500037450000000726714505005533022022 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup config Configuration handling * @ingroup yadifad * @brief * * @{ */ #include "server-config.h" #include #include #include #include #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #if DNSCORE_HAS_CTRL #include "ctrl.h" static config_control tmp_config_control = { NULL, TRUE }; static bool ctrl_registered = FALSE; #define CONFIG_TYPE config_control CONFIG_BEGIN(config_control_desc) CONFIG_BOOL(enabled, "1") CONFIG_HOST_LIST_EX(listen, NULL, CONFIG_HOST_LIST_FLAGS_DEFAULT,4) CONFIG_END(config_control_desc) #undef CONFIG_TYPE static ya_result config_control_section_postprocess(struct config_section_descriptor_s *csd) { (void)csd; /* here check that the settings are right */ host_address **hap = &tmp_config_control.listen; while(*hap != NULL) { host_address *ha = *hap; if(ha->port == 0) { ha->port = NU16(CTRL_PORT_DEFAULT); } hap = &ha->next; } ctrl_set_listen(tmp_config_control.listen); return SUCCESS; } ya_result config_register_control(s32 priority) { if(ctrl_registered) { return SUCCESS; } ctrl_registered = TRUE; const char *section_name = "control"; ya_result return_code = config_register_struct(section_name, config_control_desc, &tmp_config_control, priority); if(ISOK(return_code)) { // hook a new finaliser before the standard one config_section_descriptor_s *section_desc = config_section_get_descriptor(section_name); config_section_descriptor_vtbl_s *vtbl = (config_section_descriptor_vtbl_s *)section_desc->vtbl; vtbl->postprocess = config_control_section_postprocess; } return return_code; } #endif /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl.c0000644000000000000000000000013114505005533020002 xustar000000000000000030 mtime=1695812443.482997083 29 atime=1695812445.78203001 30 ctime=1695812495.681744674 yadifa-2.6.5-11201/sbin/yadifad/ctrl.c0000664000374500037450000001422314505005533017747 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #include "server-config.h" #include #include #include #include #include #include #include #include #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "server-config.h" #include "confs.h" #include "signals.h" #include #include #include "notify.h" #if DNSCORE_HAS_CTRL #include "ctrl_query.h" #include "ctrl.h" #include "database-service.h" extern logger_handle* g_server_logger; /* Zone file variables */ extern zone_data_set database_zone_desc; static config_control g_ctrl_config = { NULL, TRUE }; static error_state_t ctrl_tcp_reply_error_state = ERROR_STATE_INITIALIZER; static inline ya_result ctrl_tcp_reply(message_data *mesg, int sockfd) { ssize_t ret; if(ISOK(ret = message_update_length_send_tcp_with_default_minimum_throughput(mesg, sockfd))) { error_state_clear_locked(&ctrl_tcp_reply_error_state, NULL, 0, NULL); } else { if(error_state_log_locked(&ctrl_tcp_reply_error_state, ret)) { log_err("ctrl: tcp: could not answer: %r", (ya_result)ret); } } return (ya_result)ret; } static inline ya_result ctrl_tcp_reply_error(message_data *mesg, int sockfd, u16 error_code) { ssize_t ret; if(ISOK(ret = message_make_error_and_reply_tcp_with_default_minimum_throughput(mesg, error_code, sockfd))) { error_state_clear_locked(&ctrl_tcp_reply_error_state, NULL, 0, NULL); } else { if(error_state_log_locked(&ctrl_tcp_reply_error_state, ret)) { log_err("ctrl: tcp: could not answer: %r", (ya_result)ret); } } return (ya_result)ret; } void ctrl_set_listen(host_address* hosts) { if(g_ctrl_config.listen != NULL) { host_address_delete_list(g_ctrl_config.listen); } g_ctrl_config.listen = hosts; } host_address* ctrl_get_listen() { return g_ctrl_config.listen; } void ctrl_set_enabled(bool b) { g_ctrl_config.enabled = b; } bool ctrl_get_enabled() { return g_ctrl_config.enabled; } ya_result ctrl_message_process(message_data *mesg) { ya_result ret; bool received_query = message_isquery(mesg); if(ISOK(ret = message_process(mesg))) { switch(message_get_query_class(mesg)) { case CLASS_CTRL: { ctrl_query_process(mesg); break; } // ctrl class CTRL default: { log_warn("ctrl [%04hx] %{dnsname} %{dnstype} %{dnsclass} (%{sockaddrip}) : unsupported class", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), message_get_sender_sa(mesg)); message_set_status(mesg, FP_CLASS_NOTFOUND); message_transform_to_signed_error(mesg); break; } } // switch(class) } else // an error occurred : no query to be done at all { log_warn("ctrl [%04hx] from %{sockaddr} error %i : %r", ntohs(message_get_id(mesg)), message_get_sender_sa(mesg), message_get_status(mesg), ret); if((ret == INVALID_MESSAGE) && (g_config->server_flags & SERVER_FL_LOG_UNPROCESSABLE)) { log_memdump_ex(MODULE_MSG_HANDLE, MSG_WARNING, message_get_buffer(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_BUFFER); } if((ret != INVALID_MESSAGE) && (((g_config->server_flags & SERVER_FL_ANSWER_FORMERR) != 0) || message_get_status(mesg) != RCODE_FORMERR) && received_query ) { if(!message_has_tsig(mesg) && (message_get_status(mesg) != FP_RCODE_NOTAUTH)) { message_transform_to_error(mesg); } ret = SUCCESS; } else { ret = SUCCESS_DROPPED; } } return ret; } #endif // HAS_CTRL /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_query.c0000644000000000000000000000012714505005533021234 xustar000000000000000027 mtime=1695812443.546998 30 atime=1695812445.785030053 30 ctime=1695812495.683744703 yadifa-2.6.5-11201/sbin/yadifad/ctrl_query.c0000664000374500037450000010470314505005533021177 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #include "server-config.h" #include #include #include #include #include #include #include #include #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "confs.h" #include "signals.h" #include #if DNSCORE_HAS_CTRL #include "ctrl_zone.h" #include "log_query.h" #include "database-service.h" #include "notify.h" extern zone_data_set database_zone_desc; // CH fqdn TXT command // freeze zone // unfreeze zone // reload zone // load zone // drop zone /** * The q&d model used types for control. * * Do we want a script model ? A loop could make sense but I don't see a real practical use yet. * * for $z in (a,b,c,d){load $z} * if(whatever) {notify hostname} * * Do we want optional encryption ? (This may be interesting). * * ie: one may want to send a command with a TSIG through an unsafe network. * * If we use TXT we can simply have: * * script. TXT load this;foreach(a,b,c,d){drop $};if(whateverstatus){reload whatever} * key. TXT mycbckeyname * * */ /*****************************************************************************/ static ya_result ctrl_query_parse_no_parameters(packet_unpack_reader_data *pr) { (void)pr; return SUCCESS; } static ya_result ctrl_query_parse_bytes(packet_unpack_reader_data *pr, void *out, u32 out_size) { struct type_class_ttl_rdlen cmd_tctr; ya_result ret; if(FAIL(ret = packet_reader_skip_fqdn(pr))) { return ret; } if(FAIL(ret = packet_reader_read(pr, &cmd_tctr, 10))) // exact { return ret; } cmd_tctr.rdlen = ntohs(cmd_tctr.rdlen); if(cmd_tctr.rdlen <= out_size) { cmd_tctr.rdlen -= out_size; ret = packet_reader_read(pr, out, out_size); // exact return ret; } else { return BUFFER_WOULD_OVERFLOW; // not enough bytes } } /* * * rdata = "apple.com" * rdata = "apple.com" CH * rdata = "apple.com" CH "bla bla" * */ static ya_result ctrl_query_parse_fqdn_class_view(packet_unpack_reader_data *pr, u8 *fqdn, u32 fqdn_size, u16 *rclass, char *view, u32 view_size) { struct type_class_ttl_rdlen cmd_tctr; ya_result ret = 0; if(FAIL(ret = packet_reader_skip_fqdn(pr))) { return ret; } if(FAIL(ret = packet_reader_read(pr, &cmd_tctr, 10))) // exact { return ret; } cmd_tctr.rdlen = ntohs(cmd_tctr.rdlen); fqdn[0] = '\0'; *rclass = CLASS_IN; view[0] = '\0'; if(cmd_tctr.rdlen != 0) { u32 from = pr->offset; if(ISOK(ret = packet_reader_read_fqdn(pr, fqdn, fqdn_size))) { cmd_tctr.rdlen -= pr->offset -from; ya_result parameters = 1; if(cmd_tctr.rdlen > 2) { if(ISOK(ret = packet_reader_read(pr, rclass, 2))) // exact { ++parameters; cmd_tctr.rdlen -= 2; if(cmd_tctr.rdlen > 0) { u32 n = MIN(cmd_tctr.rdlen, view_size - 1); if(ISOK(ret = packet_reader_read(pr, view, n))) // exact { ++parameters; view[n] = '\0'; cmd_tctr.rdlen -= ret; } } } } if(ISOK(ret)) { if(cmd_tctr.rdlen == 0) { ret = parameters; } else { ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR); // must end on an exact match } } } } return ret; } static ya_result ctrl_query_parse_byte_fqdn_class_view(packet_unpack_reader_data *pr, u8* one_byte, u8 *fqdn, u32 fqdn_size, u16 *rclass, char *view, u32 view_size) { struct type_class_ttl_rdlen cmd_tctr; ya_result ret = 0; if(FAIL(ret = packet_reader_skip_fqdn(pr))) { return ret; } if(FAIL(ret = packet_reader_read(pr, &cmd_tctr, 10))) // exact { return ret; } cmd_tctr.rdlen = ntohs(cmd_tctr.rdlen); fqdn[0] = '\0'; *rclass = CLASS_IN; view[0] = '\0'; if(cmd_tctr.rdlen != 0) { u32 from = pr->offset; // read the byte if(ISOK(ret = packet_reader_read(pr, one_byte, 1))) { // read the fqdn if(ISOK(ret = packet_reader_read_fqdn(pr, fqdn, fqdn_size))) { // adjust the remaining bytes to process cmd_tctr.rdlen -= pr->offset - from; // if there is enough for a class ... if(cmd_tctr.rdlen > 2) { // read the class if(ISOK(ret = packet_reader_read(pr, rclass, 2))) { cmd_tctr.rdlen -= 2; // if there is something left it's the view parameter if(cmd_tctr.rdlen > 0) { u32 n = MIN(cmd_tctr.rdlen, view_size - 1); if(ISOK(ret = packet_reader_read(pr, view, n))) { view[n] = '\0'; } } } } else // the value can only be 0 else it's a format error { if(cmd_tctr.rdlen != 0) { return MAKE_RCODE_ERROR(RCODE_FORMERR); // the one forbidden value is 1 byte available } } } } return pr->offset - from; } else { if(cmd_tctr.rdlen == 0) { return 0; // nothing read } else { return ERROR; // not enough bytes } } } static void ctrl_query_server_shutdown_call() { program_mode = SA_SHUTDOWN; server_service_stop_nowait(); dnscore_shutdown(); } static void ctrl_query_server_shutdown(message_data *mesg) { packet_unpack_reader_data pr; ya_result return_code; u16 cmd_type; u16 cmd_class; packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_skip_fqdn(&pr))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } if(FAIL(packet_reader_read_u16(&pr, &cmd_type))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } return_code = packet_reader_read_u16(&pr, &cmd_class); u16 qc = message_get_query_count(mesg); u16 pc = message_get_answer_count(mesg); u16 an = message_get_authority_count(mesg); if(ISOK(return_code) && (qc == 1) && (pc == 0) && (an == 0) && (cmd_type == TYPE_CTRL_SRVSHUTDOWN) && (cmd_class == CLASS_CTRL)) { if(ISOK(return_code = ctrl_query_parse_no_parameters(&pr))) { log_info("ctrl: shutdown"); if(!ACL_REJECTED(acl_check_access_filter(mesg, &g_config->ac->allow_control))) { if(!dnscore_shuttingdown()) { log_debug("ctrl: shutdown: in progress"); ctrl_query_server_shutdown_call(); } else { log_info("ctrl: shutdown: already shutting down"); } } else { log_notice("ctrl: shutdown: rejected by ACL"); message_make_error(mesg, RCODE_REFUSED); } } else { log_notice("ctrl: shutdown: format error"); message_make_error(mesg, RCODE_FORMERR); } } else { log_notice("ctrl: shutdown: format error"); message_make_error(mesg, RCODE_FORMERR); } } static void ctrl_query_logger_reopen(message_data *mesg) { packet_unpack_reader_data pr; u16 cmd_type; u16 cmd_class; packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_skip_fqdn(&pr))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } if(FAIL(packet_reader_read_u16(&pr, &cmd_type))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } ya_result return_code = packet_reader_read_u16(&pr, &cmd_class); u16 qc = message_get_query_count(mesg); u16 pc = message_get_answer_count(mesg); u16 an = message_get_authority_count(mesg); if(ISOK(return_code) && (qc == 1) && (pc == 0) && (an == 0) && (cmd_type == TYPE_CTRL_SRVLOGREOPEN) && (cmd_class == CLASS_CTRL)) { if(ISOK(return_code = ctrl_query_parse_no_parameters(&pr))) { log_info("ctrl: logger reopen"); if(!ACL_REJECTED(acl_check_access_filter(mesg, &g_config->ac->allow_control))) { logger_reopen(); } else { log_notice("ctrl: logger reopen: rejected by ACL"); message_make_error(mesg, RCODE_REFUSED); } } else { log_notice("ctrl: logger reopen: format error"); message_make_error(mesg, RCODE_FORMERR); } } else { log_notice("ctrl: logger reopen: format error"); message_make_error(mesg, RCODE_FORMERR); } } static void ctrl_query_config_reload(message_data *mesg) { packet_unpack_reader_data pr; u16 cmd_type; u16 cmd_class; packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_skip_fqdn(&pr))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } if(FAIL(packet_reader_read_u16(&pr, &cmd_type))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } ya_result return_code = packet_reader_read_u16(&pr, &cmd_class); u16 qc = message_get_query_count(mesg); u16 pc = message_get_answer_count(mesg); u16 an = message_get_authority_count(mesg); if(ISOK(return_code) && (qc == 1) && (pc == 0) && (an == 0) && (cmd_type == TYPE_CTRL_SRVCFGRELOAD) && (cmd_class == CLASS_CTRL)) { if(ISOK(return_code = ctrl_query_parse_no_parameters(&pr))) { log_info("ctrl: config reload"); if(!ACL_REJECTED(acl_check_access_filter(mesg, &g_config->ac->allow_control))) { if(ISOK(yadifad_config_update(g_config->config_file))) { logger_reopen(); if(!server_context_matches_config()) { log_try_debug1("network configuration has changed"); server_service_reconfigure(); } else { log_try_debug1("network configuration has not changed"); } } } else { log_notice("ctrl: config reload: rejected by ACL"); message_make_error(mesg, RCODE_REFUSED); } } else { log_notice("ctrl: config reload: rejected by ACL"); message_make_error(mesg, RCODE_FORMERR); } } else { log_notice("ctrl: config reload: rejected by ACL"); message_make_error(mesg, RCODE_FORMERR); } } static void ctrl_query_log_query_enable(message_data *mesg) { packet_unpack_reader_data pr; u16 cmd_type; u16 cmd_class; packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_skip_fqdn(&pr))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } if(FAIL(packet_reader_read_u16(&pr, &cmd_type))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } ya_result return_code = packet_reader_read_u16(&pr, &cmd_class); u16 qc = message_get_query_count(mesg); u16 pc = message_get_answer_count(mesg); u16 an = message_get_authority_count(mesg); if(ISOK(return_code) && (qc == 1) && (pc == 1) && (an == 0) && (cmd_type == TYPE_CTRL_SRVQUERYLOG) && (cmd_class == CLASS_CTRL)) { u8 on_off = 0; if(ISOK(return_code = ctrl_query_parse_bytes(&pr, &on_off, 1))) { log_info("ctrl: log query: %hhu", on_off & 1); if(!ACL_REJECTED(acl_check_access_filter(mesg, &g_config->ac->allow_control))) { if((on_off & 1) != 0) { if(g_config->queries_log_type != 0) { log_query_set_mode(g_config->queries_log_type); } else { log_query_set_mode(1); // yadifa } } else { log_query_set_mode(0); // none } } else { log_notice("ctrl: log query: %s: rejected by ACL", (on_off&1)?"on":"off"); message_make_error(mesg, RCODE_REFUSED); } } else { log_notice("ctrl: log query: format error"); message_make_error(mesg, RCODE_FORMERR); } } else { log_notice("ctrl: log query: format error"); message_make_error(mesg, RCODE_FORMERR); } } static void ctrl_query_log_level(message_data *mesg) { packet_unpack_reader_data pr; u16 cmd_type; u16 cmd_class; packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_skip_fqdn(&pr))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } if(FAIL(packet_reader_read_u16(&pr, &cmd_type))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } ya_result return_code = packet_reader_read_u16(&pr, &cmd_class); u16 qc = message_get_query_count(mesg); u16 pc = message_get_answer_count(mesg); u16 an = message_get_authority_count(mesg); if(ISOK(return_code) && (qc == 1) && (pc == 1) && (an == 0) && (cmd_type == TYPE_CTRL_SRVLOGLEVEL) && (cmd_class == CLASS_CTRL)) { u8 level = 0; if(ISOK(return_code = ctrl_query_parse_bytes(&pr, &level, 1))) { log_info("ctrl: log level: %hhu", level); if(!ACL_REJECTED(acl_check_access_filter(mesg, &g_config->ac->allow_control))) { logger_set_level(level); } else { log_notice("ctrl: log level: rejected by ACL"); message_make_error(mesg, RCODE_REFUSED); } } else { log_info("ctrl: log level: format error"); message_make_error(mesg, RCODE_FORMERR); } } else { log_info("ctrl: log level: format error"); message_make_error(mesg, RCODE_FORMERR); } } /** * Freeze ONE zone * * @param mesg */ /** * * Apply a single command to all zones (that are controllable by the current sender) * * The proper way to handle all zones from an external command is to try them one by one * (because of the ACL) * * @param mesg */ static u16 ctrl_query_zone_apply_all(message_data *mesg, ya_result (*ctrl_zone_single)(zone_desc_s *, bool), const char* name) { u32 success_count = 0; u32 error_count = 0; log_info("ctrl: zone %s: all", name); zone_set_lock(&database_zone_desc); ptr_set_iterator iter; ptr_set_iterator_init(&database_zone_desc.set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *zone_node = ptr_set_iterator_next_node(&iter); zone_desc_s *zone_desc = (zone_desc_s *)zone_node->value; if(!ACL_REJECTED(acl_check_access_filter(mesg, &zone_desc->ac.allow_control))) { ya_result return_value; if(ISOK(return_value = ctrl_zone_single(zone_desc, FALSE))) { ++success_count; } else { ++error_count; } } else { // no need to handle this, it just means that the controller has no rights on this log_notice("ctrl: zone %s: all: rejected by ACL", name); } } zone_set_unlock(&database_zone_desc); log_info("ctrl: zone %s: all: %i successes, %i errors", name, success_count, error_count); if(success_count > 0) { // part was ok return RCODE_NOERROR; } else if(error_count > 0) { // part was wrong return RCODE_SERVFAIL; } else { // no zone accepts this controller return RCODE_REFUSED; } } /** * Decodes a command that applies for one or all zones optionally using an fqdn parameter * No parameter implies "all" */ static void ctrl_query_zone_with_fqdn_class_view(message_data *mesg, ya_result (*ctrl_zone_single)(zone_desc_s *, bool), u16 qtype, const char *name ) { packet_unpack_reader_data pr; u16 cmd_type; u16 cmd_class; u16 rclass = CLASS_IN; u8 fqdn[MAX_DOMAIN_LENGTH]; char view[32]; packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_skip_fqdn(&pr))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } if(FAIL(packet_reader_read_u16(&pr, &cmd_type))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } ya_result return_code = packet_reader_read_u16(&pr, &cmd_class); u16 qc = message_get_query_count(mesg); u16 pc = message_get_answer_count(mesg); u16 an = message_get_authority_count(mesg); u16 tmp_status = RCODE_FORMERR; if(ISOK(return_code) && (qc == 1) && (an == 0) && (cmd_type == qtype) && (cmd_class == CLASS_CTRL)) { if(pc == 1) { if(ISOK(return_code = ctrl_query_parse_fqdn_class_view(&pr, fqdn, sizeof(fqdn), &rclass, view, sizeof(view)))) { if(return_code > 0) { log_info("ctrl: zone %s: '%{dnsname}' %{dnsclass}", name, fqdn, &rclass); zone_desc_s* zone_desc = zone_acquirebydnsname(fqdn); tmp_status = RCODE_REFUSED; if(zone_desc != NULL) { if((rclass == zone_desc->qclass) && (view[0] == '\0')) { tmp_status = RCODE_NOTAUTH; if(!ACL_REJECTED(acl_check_access_filter(mesg, &zone_desc->ac.allow_control))) { ya_result return_value; if(ISOK(return_value = ctrl_zone_single(zone_desc, TRUE))) { tmp_status = RCODE_NOERROR; } else { tmp_status = return_value & 0x1f; } } else { log_notice("ctrl: zone %s: rejected by ACL", name); } } else { log_warn("ctrl: zone %s: zone '%{dnsname}' doesn't exist in class %{dnsclass}", name, fqdn, &rclass); } zone_release(zone_desc); } else { log_warn("ctrl: zone %s: zone '%{dnsname}' %{dnsclass} not found", name, fqdn, &rclass); } } else { tmp_status = ctrl_query_zone_apply_all(mesg, ctrl_zone_single, name); } } else { // an error occurred (FORMERR is already set) } } else if(pc == 0) // no parameter record { tmp_status = ctrl_query_zone_apply_all(mesg, ctrl_zone_single, name); } else { // an error occurred (FORMERR is already set) } } if(tmp_status != RCODE_NOERROR) { log_notice("ctrl: zone %s: failure (%s)", name, dns_message_rcode_get_name(tmp_status)); message_make_error(mesg, tmp_status); } } /** * Freeze zone(s) * * @param mesg */ static void ctrl_query_zone_freeze(message_data *mesg) { ctrl_query_zone_with_fqdn_class_view(mesg, ctrl_zone_freeze, TYPE_CTRL_ZONEFREEZE, "freeze"); } /** * Unfreeze zone(s) * * @param mesg */ static void ctrl_query_zone_unfreeze(message_data *mesg) { ctrl_query_zone_with_fqdn_class_view(mesg, ctrl_zone_unfreeze, TYPE_CTRL_ZONEUNFREEZE, "unfreeze"); } static void ctrl_query_zone_notify(message_data *mesg) { ctrl_query_zone_with_fqdn_class_view(mesg, ctrl_zone_notify, TYPE_CTRL_ZONENOTIFY, "notify"); } static void ctrl_query_zonereload(message_data *mesg) { ctrl_query_zone_with_fqdn_class_view(mesg, ctrl_zone_reload, TYPE_CTRL_ZONERELOAD, "reload"); } static void ctrl_query_zone_sync(message_data *mesg) { packet_unpack_reader_data pr; u16 cmd_type; u16 cmd_class; u16 rclass; u8 fqdn[MAX_DOMAIN_LENGTH]; char view[32]; packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_skip_fqdn(&pr))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } if(FAIL(packet_reader_read_u16(&pr, &cmd_type))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } ya_result return_code = packet_reader_read_u16(&pr, &cmd_class); u16 qc = message_get_query_count(mesg); u16 pc = message_get_answer_count(mesg); u16 an = message_get_authority_count(mesg); u16 tmp_status = RCODE_FORMERR; if(ISOK(return_code) && (qc == 1) && (an == 0) && (cmd_type == TYPE_CTRL_ZONESYNC) && (cmd_class == CLASS_CTRL)) { if(pc == 1) { u8 clean = 0; if(ISOK(return_code = ctrl_query_parse_byte_fqdn_class_view(&pr, &clean, fqdn, sizeof(fqdn), &rclass, view, sizeof(view)))) { if(return_code > 1) { log_info("ctrl: zone sync: clean=%hhu '%{dnsname}' %{dnsclass}", clean & 1, fqdn, &rclass); zone_desc_s* zone_desc = zone_acquirebydnsname(fqdn); tmp_status = RCODE_REFUSED; if(zone_desc != NULL) { if((rclass == zone_desc->qclass) && (view[0] == '\0')) { tmp_status = RCODE_NOTAUTH; if(!ACL_REJECTED(acl_check_access_filter(mesg, &zone_desc->ac.allow_control))) { tmp_status = ctrl_zone_sync(zone_desc, TRUE, (clean & 1) != 0); } else { log_notice("ctrl: zone sync: '%{dnsname}': rejected by ACL", fqdn); } } else { log_notice("ctrl: zone sync: zone '%{dnsname}' not found in class %{dnsclass}", fqdn, &rclass); } zone_release(zone_desc); } else { log_notice("ctrl: zone sync: zone '%{dnsname}' %{dnsclass} not found", fqdn, &rclass); } } else { tmp_status = ctrl_query_zone_apply_all(mesg, ctrl_zone_sync_noclean, "sync"); } } else { // some error (FORMERR already set) } } else if(pc == 0) { tmp_status = ctrl_query_zone_apply_all(mesg, ctrl_zone_sync_noclean, "sync"); } else { // some error (FORMERR already set) } } if(tmp_status != RCODE_NOERROR) { log_notice("ctrl: zone sync: failure (%s)", dns_message_rcode_get_name(tmp_status)); message_make_error(mesg, tmp_status); } } static void ctrl_query_zonecfgreload(message_data *mesg) { // This doesnt work in a do once/do all once way, hence ... // CANNOT: ctrl_query_zone_with_fqdn_class_view(mesg, ctrl_zone_notify, TYPE_CTRL_ZONECFGRELOAD, "config reload"); packet_unpack_reader_data pr; u16 cmd_type; u16 cmd_class; u16 rclass; u8 fqdn[MAX_DOMAIN_LENGTH]; char view[32]; packet_reader_init_from_message(&pr, mesg); if(FAIL(packet_reader_skip_fqdn(&pr))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } if(FAIL(packet_reader_read_u16(&pr, &cmd_type))) // shouldn't fail { log_info("ctrl: shutdown FORMERR"); return; } ya_result return_code = packet_reader_read_u16(&pr, &cmd_class); u16 qc = message_get_query_count(mesg); u16 pc = message_get_answer_count(mesg); u16 an = message_get_authority_count(mesg); u16 tmp_status = RCODE_FORMERR; if(ISOK(return_code) && (qc == 1) && (an == 0) && (cmd_type == TYPE_CTRL_ZONECFGRELOAD) && (cmd_class == CLASS_CTRL)) { if(pc == 1) { if(ISOK(return_code = ctrl_query_parse_fqdn_class_view(&pr, fqdn, sizeof(fqdn), &rclass, view, sizeof(view)))) { if(return_code > 0) { log_info("ctrl: zone config reload: '%{dnsname}' %{dnsclass}", fqdn, &rclass); zone_desc_s *zone_desc = zone_acquirebydnsname(fqdn); tmp_status = RCODE_REFUSED; if(zone_desc != NULL) { if((rclass == zone_desc->qclass) && (view[0] == '\0')) { tmp_status = RCODE_NOTAUTH; if(!ACL_REJECTED(acl_check_access_filter(mesg, &zone_desc->ac.allow_control))) { tmp_status = RCODE_SERVFAIL; // const_ptr_set_of_one is a quick and cheap way to generate constant ptr_set of a single element const_ptr_set_of_one fqdn_set; const_ptr_set_of_one_init(&fqdn_set, fqdn, fqdn, ptr_set_dnsname_node_compare); ya_result return_code = yadifad_config_update_zone(g_config->config_file, &fqdn_set.set); if(ISOK(return_code)) { // tmp_status = RCODE_NOERROR; zone_release(zone_desc); return; } } else { log_notice("ctrl: zone config reload: zone '%{dnsname}': rejected by ACL", fqdn); } } else { log_warn("ctrl: zone config reload: zone '%{dnsname}' doesn't exist in class %{dnsclass}", fqdn, &rclass); } zone_release(zone_desc); } else { log_warn("ctrl: zone config reload: zone '%{dnsname}' %{dnsclass} not found", fqdn, &rclass); } } else { log_info("ctrl: zone config reload: all"); tmp_status = RCODE_NOTAUTH; if(!ACL_REJECTED(acl_check_access_filter(mesg, &g_config->ac->allow_control))) { tmp_status = RCODE_SERVFAIL; ya_result return_code = yadifad_config_update_zone(g_config->config_file, NULL); if(ISOK(return_code)) { tmp_status = RCODE_NOERROR; } } else { log_notice("ctrl: zone config reload: all: rejected by ACL"); } } } else { log_warn("ctrl: zone config reload: zone '%{dnsname}' %{dnsclass} not found", fqdn, &rclass); } } else if(pc == 0) { log_info("ctrl: zone config reload: all"); tmp_status = RCODE_NOTAUTH; if(!ACL_REJECTED(acl_check_access_filter(mesg, &g_config->ac->allow_control))) { tmp_status = RCODE_SERVFAIL; ya_result return_code = yadifad_config_update_zone(g_config->config_file, NULL); if(ISOK(return_code)) { tmp_status = RCODE_NOERROR; } } else { log_notice("ctrl: zone config reload: all: rejected by ACL"); } } } if(tmp_status != RCODE_NOERROR) { message_make_error(mesg, tmp_status); } } bool ctrl_query_is_listened(int sockfd) { #if 0 /* fix */ #else (void)sockfd; return TRUE; #endif } void ctrl_query_process(message_data *mesg) { log_info("CTRL (%04hx) %{dnsname} %{dnstype}", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg)); if(!ctrl_get_enabled()) { message_make_error(mesg, RCODE_REFUSED); #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) /* NOTE: the TSIG information is in mesg */ { tsig_sign_answer(mesg); } #endif return; } if(message_get_canonised_fqdn(mesg)[0] != '\0') { message_make_error(mesg, RCODE_FORMERR); #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) /* NOTE: the TSIG information is in mesg */ { tsig_sign_answer(mesg); } #endif return; } message_set_answer(mesg); message_set_status(mesg, RCODE_NOERROR); // now can read the command switch(message_get_query_type(mesg)) { case TYPE_CTRL_SRVSHUTDOWN: { ctrl_query_server_shutdown(mesg); break; } case TYPE_CTRL_SRVLOGREOPEN: { ctrl_query_logger_reopen(mesg); break; } case TYPE_CTRL_SRVCFGRELOAD: { ctrl_query_config_reload(mesg); break; } case TYPE_CTRL_SRVQUERYLOG: { ctrl_query_log_query_enable(mesg); break; } case TYPE_CTRL_SRVLOGLEVEL: { ctrl_query_log_level(mesg); break; } case TYPE_CTRL_ZONEFREEZE: /* freeze */ { ctrl_query_zone_freeze(mesg); break; } case TYPE_CTRL_ZONEUNFREEZE: /* unfreeze */ { ctrl_query_zone_unfreeze(mesg); break; } case TYPE_CTRL_ZONESYNC: /* sync */ { ctrl_query_zone_sync(mesg); break; } case TYPE_CTRL_ZONENOTIFY: { ctrl_query_zone_notify(mesg); break; } case TYPE_CTRL_ZONERELOAD: { ctrl_query_zonereload(mesg); break; } case TYPE_CTRL_ZONECFGRELOAD: { ctrl_query_zonecfgreload(mesg); break; } default: { message_make_error(mesg, RCODE_NOTIMP); /* or do we drop ? */ break; } } /* switch qtype */ #if DNSCORE_HAS_TSIG_SUPPORT if(message_has_tsig(mesg)) /* NOTE: the TSIG information is in mesg */ { tsig_sign_answer(mesg); } #endif } #endif // HAS_CTRL /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_zone.c0000644000000000000000000000013214505005533021036 xustar000000000000000030 mtime=1695812443.513997527 30 atime=1695812445.783030024 30 ctime=1695812495.685744732 yadifa-2.6.5-11201/sbin/yadifad/ctrl_zone.c0000664000374500037450000001366314505005533021011 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #include "server-config.h" #include #include #include #include #include #include #include #include #include #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "confs.h" #include "signals.h" #include #include "database-service.h" #include "notify.h" #ifdef HAS_CTRL extern logger_handle* g_server_logger; extern zone_data_set database_zone_desc; ya_result ctrl_zone_freeze(zone_desc_s *zone_desc, bool dolock) { ya_result ret; if(dolock) { zone_set_lock(&database_zone_desc); } ret = MAKE_DNSMSG_ERROR(RCODE_SERVFAIL); if(zdb_zone_exists_from_dnsname(g_config->database, zone_origin(zone_desc))) { ret = SUCCESS; #if DEBUG log_debug("ctrl: zone freeze for %{dnsname}", zone_origin(zone_desc)); #endif database_zone_freeze(zone_origin(zone_desc)); } /* add the zone to the database */ if(dolock) { zone_set_unlock(&database_zone_desc); } return ret; } ya_result ctrl_zone_unfreeze(zone_desc_s *zone_desc, bool dolock) { ya_result ret; if(dolock) { zone_set_lock(&database_zone_desc); } ret = MAKE_DNSMSG_ERROR(RCODE_SERVFAIL); if(zdb_zone_exists_from_dnsname(g_config->database, zone_origin(zone_desc))) { ret = SUCCESS; #if DEBUG log_debug("ctrl: zone unfreeze for %{dnsname}", zone_origin(zone_desc)); #endif database_zone_unfreeze(zone_origin(zone_desc)); } /* add the zone to the database */ if(dolock) { zone_set_unlock(&database_zone_desc); } return ret; } ya_result ctrl_zone_sync(zone_desc_s *zone_desc, bool dolock, bool clear_journal) { ya_result ret; if(dolock) { zone_set_lock(&database_zone_desc); } ret = MAKE_DNSMSG_ERROR(RCODE_SERVFAIL); if(zdb_zone_exists_from_dnsname(g_config->database, zone_origin(zone_desc))) { if(zone_desc->loaded_zone != NULL) { ret = SUCCESS; database_zone_store_ex(zone_origin(zone_desc), clear_journal); } else { ret = MAKE_DNSMSG_ERROR(RCODE_SERVFAIL); } } if(dolock) { zone_set_unlock(&database_zone_desc); } return ret; } ya_result ctrl_zone_sync_doclean(zone_desc_s *zone_desc, bool dolock) { ya_result ret = ctrl_zone_sync(zone_desc, dolock, TRUE); return ret; } ya_result ctrl_zone_sync_noclean(zone_desc_s *zone_desc, bool dolock) { ya_result ret = ctrl_zone_sync(zone_desc, dolock, FALSE); return ret; } ya_result ctrl_zone_notify(zone_desc_s *zone_desc, bool dolock) { ya_result ret; if(dolock) { zone_set_lock(&database_zone_desc); } ret = MAKE_DNSMSG_ERROR(RCODE_REFUSED); if(zdb_zone_exists_from_dnsname(g_config->database, zone_origin(zone_desc))) { if(zone_desc->loaded_zone != NULL) { ret = SUCCESS; notify_slaves(zone_origin(zone_desc)); } else { ret = MAKE_DNSMSG_ERROR(RCODE_SERVFAIL); } } if(dolock) { zone_set_unlock(&database_zone_desc); } return ret; } ya_result ctrl_zone_reload(zone_desc_s *zone_desc, bool dolock) { ya_result ret; if(dolock) { zone_set_lock(&database_zone_desc); } ret = MAKE_DNSMSG_ERROR(RCODE_SERVFAIL); if(zdb_zone_exists_from_dnsname(g_config->database, zone_origin(zone_desc))) { ret = SUCCESS; database_zone_load(zone_origin(zone_desc)); } if(dolock) { zone_set_unlock(&database_zone_desc); } return ret; } #endif /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_notify.c0000644000000000000000000000013114505005533021372 xustar000000000000000030 mtime=1695812443.548998029 30 atime=1695812445.785030053 29 ctime=1695812495.68774476 yadifa-2.6.5-11201/sbin/yadifad/ctrl_notify.c0000664000374500037450000000515314505005533021341 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #include "server-config.h" #include #include #include #include #include #include #include #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "confs.h" #include "signals.h" #include #include "ctrl_query_message.h" #include "ctrl_query_axfr.h" #include "ctrl.h" #include "database-service.h" extern logger_handle* g_server_logger; /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_query_axfr.c0000644000000000000000000000013214505005533022250 xustar000000000000000030 mtime=1695812443.528997742 30 atime=1695812445.784030039 30 ctime=1695812495.689744789 yadifa-2.6.5-11201/sbin/yadifad/ctrl_query_axfr.c0000664000374500037450000000574214505005533022222 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ /** @note: here we define the variable that is holding the default logger handle for the current source file * Such a handle should NEVER been set in an include file. */ #include "server-config.h" #include "server-config.h" #if HAS_PTHREAD_SETNAME_NP #if DEBUG #define _GNU_SOURCE 1 #endif #endif #include #include "server-config.h" #include #include #include #include #include #include #include #include #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "confs.h" #include "signals.h" #include #include "zone_desc.h" #include "ctrl_query_axfr.h" #include "ctrl_query_message.h" #include "ctrl.h" #include "ctrl_zone.h" #include "database-service.h" /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_query_message.c0000644000000000000000000000013214505005533022734 xustar000000000000000030 mtime=1695812443.549998043 30 atime=1695812445.785030053 30 ctime=1695812495.691744818 yadifa-2.6.5-11201/sbin/yadifad/ctrl_query_message.c0000664000374500037450000000507514505005533022705 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #include "server-config.h" #include #include #include #include #include #include #include #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "confs.h" #include "signals.h" #include #include "database-service.h" #include "ctrl_query_message.h" #define TMP00001_TAG 0x3130303030504d54 /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/ctrl_update.c0000644000000000000000000000013114505005533021344 xustar000000000000000030 mtime=1695812443.319994749 30 atime=1695812445.781029996 29 ctime=1695812495.69474486 yadifa-2.6.5-11201/sbin/yadifad/ctrl_update.c0000664000374500037450000000513414505005533021312 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup server * @ingroup yadifad * @brief server * * Handles queries made in the CH class (ie: version.*) * * @{ */ /*----------------------------------------------------------------------------*/ #include "server-config.h" #include #include #include #include #include #include #include #include extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #include "confs.h" #include "signals.h" #include #include "ctrl_query_message.h" #include "ctrl_query_axfr.h" #include "ctrl.h" #include "database-service.h" #include "ctrl_zone.h" /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/rrl.c0000644000000000000000000000013214505005533017636 xustar000000000000000030 mtime=1695812443.514997542 30 atime=1695812445.783030024 30 ctime=1695812495.696744889 yadifa-2.6.5-11201/sbin/yadifad/rrl.c0000664000374500037450000007420514505005533017610 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup yadifad * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "server-config.h" #include #include #include #include #include #include #include #include #include #include #include #include "rrl.h" #include #include u32 zdb_query_message_update(message_data* message, const zdb_query_ex_answer* answer_set); extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #define EPOCH_PRECISION 6 #define ONE_SECOND_TICKS (1 << EPOCH_PRECISION) #define RRLITEM_TAG 0x4d4554494c5252 struct rrl_settings_s { u32 responses_per_second; // 5 u32 errors_per_second; // 5 u32 window; // 15 u32 slip; // 2 s32 max_table_size; // 10000 s32 min_table_size; // 1000 u32 window_ticks; address_match_set exempted; acl_check_access_filter_callback *exempted_filter; u64 ipv6_prefix_mask_high; u64 ipv6_prefix_mask_low; u32 ipv4_prefix_mask; s32 drop_default; // RRL_DROP except in log_only where it is RRL_PROCEED_DROP u8 ipv4_prefix_length; // 24 u8 ipv6_prefix_length; // bool log_only; // false bool enabled; }; typedef struct rrl_settings_s rrl_settings_s; #define CONFIG_TYPE rrl_settings_s #include CONFIG_BEGIN(config_rrl_desc) CONFIG_U32(responses_per_second, TOSTRING(RRL_RESPONSES_PER_SECOND_DEFAULT)) CONFIG_U32(errors_per_second, TOSTRING(RRL_ERRORS_PER_SECOND_DEFAULT)) CONFIG_U32(window, TOSTRING(RRL_WINDOW_DEFAULT)) CONFIG_U32(slip, TOSTRING(RRL_SLIP_DEFAULT)) CONFIG_U32(max_table_size, TOSTRING(RRL_QUEUE_SIZE_MAX_DEFAULT)) CONFIG_U32(min_table_size, TOSTRING(RRL_QUEUE_SIZE_MIN_DEFAULT)) CONFIG_U8(ipv4_prefix_length, TOSTRING(RRL_IPV4_PREFIX_LENGTH_DEFAULT)) CONFIG_U8(ipv6_prefix_length, TOSTRING(RRL_IPV6_PREFIX_LENGTH_DEFAULT)) CONFIG_BOOL(log_only, TOSTRING(RRL_LOG_ONLY_DEFAULT)) CONFIG_BOOL(enabled, TOSTRING(RRL_ENABLED_DEFAULT)) CONFIG_ACL_FILTER(exempted, RRL_EXEMPTED_DEFAULT) /* alias, aliased */ CONFIG_ALIAS(exempt-clients, exempted) CONFIG_ALIAS(enable, enabled) CONFIG_END(config_rrl_desc) #undef CONFIG_TYPE static mutex_t rrl_mtx; static random_ctx g_rrl_rnd; static struct rrl_settings_s g_rrl_settings; static ptr_vector g_rrl_list = PTR_VECTOR_EMPTY; static u64 g_rrl_start = 0; static u32 g_rrl_slip_bucket = 0; static s8 g_rrl_slip_bucket_bits = 0; static ya_result config_rrl_section_postprocess(struct config_section_descriptor_s *csd) { (void)csd; g_rrl_settings.window_ticks = g_rrl_settings.window * ONE_SECOND_TICKS; g_rrl_settings.exempted_filter = acl_get_check_access_filter(&g_rrl_settings.exempted); if(g_rrl_settings.ipv4_prefix_length == 0) { log_warn("ipv4-prefix-length set to 0, setting to recommended value: " TOSTRING(RRL_IPV4_PREFIX_LENGTH_DEFAULT)); g_rrl_settings.ipv4_prefix_length = RRL_IPV4_PREFIX_LENGTH_DEFAULT; } if(g_rrl_settings.ipv4_prefix_length < 32) { u32 mask = MAX_U32 << (32 - g_rrl_settings.ipv4_prefix_length); g_rrl_settings.ipv4_prefix_mask = htonl(mask); } else { log_warn("ipv4-prefix-length is wrong, setting to 32"); g_rrl_settings.ipv4_prefix_length = 32; g_rrl_settings.ipv4_prefix_mask = MAX_U32; } u64 mask_h, mask_l; if(g_rrl_settings.ipv6_prefix_length == 0) { log_warn("ipv6-prefix-length set to 0, setting to recommended value: " TOSTRING(RRL_IPV6_PREFIX_LENGTH_DEFAULT)); g_rrl_settings.ipv6_prefix_length = RRL_IPV6_PREFIX_LENGTH_DEFAULT; } if(g_rrl_settings.ipv6_prefix_length < 128) // [1;127] { if(g_rrl_settings.ipv6_prefix_length <= 64) // [1;64] { mask_h = MAX_U64 << (64 - g_rrl_settings.ipv6_prefix_length); // shift [63; 0] mask_l = 0; } else // [65;127] { mask_h = MAX_U64; mask_l = MAX_U64 << (128 - g_rrl_settings.ipv6_prefix_length); // shift [63; 1] } } else { log_warn("ipv6-prefix-length is wrong, setting to 128"); g_rrl_settings.ipv6_prefix_length = 128; mask_h = MAX_U64; mask_l = MAX_U64; } g_rrl_settings.ipv6_prefix_mask_high = htobe64(mask_h); g_rrl_settings.ipv6_prefix_mask_low = htobe64(mask_l); if(g_rrl_settings.min_table_size < RRL_QUEUE_SIZE_MIN) { log_warn("min-table-size too low, set to %d", g_rrl_settings.min_table_size = RRL_QUEUE_SIZE_MIN); } else if(g_rrl_settings.min_table_size > RRL_QUEUE_SIZE_MAX) { log_warn("min-table-size too high, set to %d", g_rrl_settings.min_table_size = RRL_QUEUE_SIZE_MAX); } if(g_rrl_settings.max_table_size < RRL_QUEUE_SIZE_MIN) { log_warn("max-table-size too low, set to %d", g_rrl_settings.max_table_size = RRL_QUEUE_SIZE_MIN); } else if(g_rrl_settings.max_table_size > RRL_QUEUE_SIZE_MAX) { log_warn("max-table-size too high, set to %d", g_rrl_settings.max_table_size = RRL_QUEUE_SIZE_MAX); } if(g_rrl_settings.min_table_size > g_rrl_settings.max_table_size) { log_warn("min-table-size > max-table-size (%d > %d) setting min-table-size to %d instead", g_rrl_settings.min_table_size, g_rrl_settings.max_table_size, g_rrl_settings.max_table_size); g_rrl_settings.min_table_size = g_rrl_settings.max_table_size; } ptr_vector_resize(&g_rrl_list, g_rrl_settings.min_table_size); g_rrl_settings.drop_default = (g_rrl_settings.log_only)?RRL_PROCEED_DROP:RRL_DROP; return SUCCESS; } ya_result config_register_rrl(s32 priority) { const char *section_name = "rrl"; ya_result return_code = config_register_struct(section_name, config_rrl_desc, &g_rrl_settings, priority); if(ISOK(return_code)) { // hook a new finaliser before the standard one config_section_descriptor_s *section_desc = config_section_get_descriptor(section_name); config_section_descriptor_vtbl_s *vtbl = (config_section_descriptor_vtbl_s *)section_desc->vtbl; vtbl->postprocess = config_rrl_section_postprocess; } return return_code; } /* * The item will be dynamic in size * the key being error_mask_ip_imputed_name, crafter every time for a (fast) memcmp comparison * The key should be a multiple of 8 bytes, padded with 0 (faster memcmp) * * The epoch should cover enough time. * It should have an imprecision lower than the second. * We can have it covering only a few minutes (8: 25.5, 16: 655.35, ...) * There is 32 bits available for a fast structure so I plan to simply use an epoch based on the start-time of the server. * The (currentTime - serverStartTime) >> 4 would give an acceptable precision (1/16 of a second) and cover 3106.89 days or 8.5 years * The (currentTime - serverStartTime) >> 6 would give an acceptable precision (1/64 of a second) and cover 776.72 days or 2.1 years * In the unlikely event the server is not restarted once before the covered time, the table would be flushed out and the serverStartTime reset * to the current time. */ struct rrl_item_s; struct rrl_item_children { struct rrl_item_s *left; struct rrl_item_s *right; }; union rrl_item_children_union { struct rrl_item_children lr; struct rrl_item_s *child[2]; }; /* * error_mask_ip_imputed_name format: * [ 0] : E000IPSZ * E : 1 = error, 0 = ok * IPSZ : number of bytes for the IP * 1 + 4 + name_length * * That was the first idea anyway ... now I settled for: * * [ 0 1 ] native endian 16 bits header * [ 2 .. ? ] IP bytes * [ ? .. n-1 ] NAME bytes * * header: [ E??????S SSSSSSSS ] * E: the msb is used to tell if it's an error or not * S: 9 bits are used to store the total size of the key (so the two first bytes included) * */ struct rrl_item_s { union rrl_item_children_union children; // 128 64 // AVL u32 timestamp; // 160 96 u32 lasttimestamp; // s32 hits; // s8 balance; // // AVL u8 reserved0; // alignment u16 slip_countdown; u8 error_mask_ip_imputed_name[1]; // max 1 + 16 + 255 = 272 }; // max 280 bytes #define RRL_KEY_SIZE_MAX (1+1+16+MAX_DOMAIN_LENGTH) typedef struct rrl_item_s rrl_item_s; static inline u32 rrl_item_key_size(const u8 *key) { u32 size = GET_U16_AT(key[0]) & 0x1ff; return size; } static inline u32 rrl_item_size_for_key(const u8 *key) { u32 size = rrl_item_key_size(key); size += sizeof(rrl_item_s) - 1; // -1 because the key takes originally 1 byte in the struct definition return size; } static inline u32 rrl_item_size(const rrl_item_s* rrl) { u32 size = rrl_item_size_for_key(rrl->error_mask_ip_imputed_name); return size; } static inline bool rrl_key_is_error(const u8 *key) { bool iserror = (GET_U16_AT(key[0]) & 0x8000) != 0; return iserror; } /** * out_key must be at least 1 + 1 + 16 + 255 bytes long * * returns the size of the key */ static inline u32 rrl_make_key(const message_data *mesg, const zdb_query_ex_answer *ans_auth_add, u8 *out_key) { u8 *tgt; const u8 *src; u32 size; u32 flags = 0; if(message_get_sender_sa_family(mesg) == AF_INET) { size = 4; u32 ip = message_get_sender_sa4(mesg)->sin_addr.s_addr; ip &= g_rrl_settings.ipv4_prefix_mask; SET_U32_AT(out_key[2], ip); tgt = &out_key[6]; } else { size = 16; u64 iph = GET_U64_AT(((u64*)&message_get_sender_sa6(mesg)->sin6_addr)[0]); iph &= g_rrl_settings.ipv6_prefix_mask_high; SET_U64_AT(out_key[ 2], iph); u64 ipl = GET_U64_AT(((u64*)&message_get_sender_sa6(mesg)->sin6_addr)[1]); ipl &= g_rrl_settings.ipv6_prefix_mask_low; SET_U64_AT(out_key[10], ipl); tgt = &out_key[18]; flags |= 0x2000; } // note: wildcard names are not handled (yet) switch(message_get_status(mesg)) { case FP_RCODE_NOERROR: { // take the answer if(ans_auth_add->delegation == 0) { src = message_get_canonised_fqdn(mesg); // query name } else { yassert(ans_auth_add->authority != NULL); src = ans_auth_add->authority->name; } break; } case FP_RCODE_NXDOMAIN: { flags |= 0x8000; // note: if we want to have a different key for NXDOMAIN and other errors, we can use 0xc000 instead if(ans_auth_add->authority != NULL) { src = ans_auth_add->authority->name; } else { src = message_get_canonised_fqdn(mesg); } break; } // case wildcard name ? default: { flags = 0x8000; src = message_get_canonised_fqdn(mesg); // query name } } size += dnsname_copy(tgt, src); size += 2; SET_U16_AT(out_key[0], size | flags); return size; } static inline void rrl_set_key(rrl_item_s *rrl, const u8 *key) { u32 key_size = GET_U16_AT(key[0]); key_size &= 0x01ff; memcpy(rrl->error_mask_ip_imputed_name, key, key_size); } static rrl_item_s* rrl_alloc(const u8 *key) { rrl_item_s *item; ZALLOC_ARRAY_OR_DIE(rrl_item_s*, item, rrl_item_size_for_key(key), RRLITEM_TAG); item->timestamp = 0; item->hits = 0; item->slip_countdown = 0; SET_U16_AT(item->error_mask_ip_imputed_name[0], 0); return item; } static void rrl_free(rrl_item_s *item) { /* * This assert is wrong because this is actually the payload that has just overwritten our node * assert(node->rc == 0 && node->sc == 0 && node->label.owners == NULL && node->star_label.owners == NULL & node->type_bit_maps == NULL); */ ZFREE_ARRAY(item, rrl_item_size(item)); } #ifdef AVL_DOES_NOT_DO_PAYLOAD_COPY_ANYMORE static void rrl_payload_copy(rrl_item_s *a, const rrl_item_s *b) { a->timestamp = b->timestamp; a->lasttimestamp = b->lasttimestamp; a->hits = b->hits; a->slip_countdown = b->slip_countdown; yassert(rrl_item_size(a) == rrl_item_size(b)); memcpy(a->error_mask_ip_imputed_name, b->error_mask_ip_imputed_name, rrl_item_size(a)); } #endif /* * AVL definition part begins here */ /* * The maximum depth of a tree. * 40 is enough for storing 433494436 items (worst case) * * Depth 0 is one node. * * Worst case : N is enough for sum[n = 0,N](Fn) where Fn is Fibonacci(n+1)1 * Best case : N is enough for (2^(N+1))-1 */ #define AVL_MAX_DEPTH 34 // 24157816 items max (worst case)*/ /* * The previx that will be put in front of each function name */ #define AVL_PREFIX rrl_set_ /* * The type that hold the node */ #define AVL_NODE_TYPE rrl_item_s /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_TREE_TYPE AVL_NODE_TYPE* typedef AVL_TREE_TYPE rrl_set_s; /* * The type that hold the tree (should be AVL_NODE_TYPE*) */ #define AVL_CONST_TREE_TYPE AVL_NODE_TYPE* const /* * How to find the root in the tree */ #define AVL_TREE_ROOT(__tree__) (*(__tree__)) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u8* #define AVL_REFERENCE_IS_POINTER TRUE #define AVL_REFERENCE_IS_CONST FALSE /* * The node has got a pointer to its parent * * 0 : disable * !=0 : enable */ #define AVL_HAS_PARENT_POINTER 0 #include /* * Access to the field that points to the left child * */ #define AVL_LEFT_CHILD(node) ((node)->children.lr.left) /* * Access to the field that points to the right child */ #define AVL_RIGHT_CHILD(node) ((node)->children.lr.right) /* * Access to the field that points to one of the children (0: left, 1: right) */ #define AVL_CHILD(node,id) ((node)->children.child[(id)]) /* * OPTIONAL : Access to the field that points the parent of the node. * * This field is optional but is mandatory if AVL_HAS_PARENT_POINTER is not 0 */ //#define AVL_PARENT(node) ((node)->parent) /* * Access to the field that keeps the balance (a signed byte) */ #define AVL_BALANCE(node) ((node)->balance) /* * The type used for comparing the nodes. */ #define AVL_REFERENCE_TYPE u8* /* * */ #define AVL_REFERENCE_FORMAT_STRING "%p" #define AVL_REFERENCE_FORMAT(reference) reference /* * A macro to initialize a node and setting the reference */ #define AVL_INIT_NODE(node,reference) rrl_set_key((node), reference) /* * A macro to allocate a new node */ #define AVL_ALLOC_NODE(node,reference) node = rrl_alloc(reference) /* * A macro to free a node allocated by ALLOC_NODE */ #define AVL_FREE_NODE(node) rrl_free(node) /* * A macro to print the node */ #define AVL_DUMP_NODE(node) format("node@%p",(node)); /* * A macro that returns the reference field of the node. * It must be of type REFERENCE_TYPE */ #define AVL_REFERENCE(node) (node)->error_mask_ip_imputed_name #define AVL_TERNARYCMP 1 #if !AVL_TERNARYCMP /* * A macro to compare two references * Returns TRUE if and only if the references are equal. */ #define AVL_ISEQUAL(reference_a,reference_b) (memcmp(&(reference_a)[0],&(reference_b)[0],rrl_item_key_size(reference_a))==0) /* * A macro to compare two references * Returns TRUE if and only if the first one is bigger than the second one. */ #define AVL_ISBIGGER(reference_a,reference_b) (memcmp(&(reference_a)[0],&(reference_b)[0],rrl_item_key_size(reference_a))>0) #else #define AVL_COMPARE(reference_a,reference_b) (memcmp(&(reference_a)[0],&(reference_b)[0],rrl_item_key_size(reference_a))) #endif /* * Copies the payload of a node * It MUST NOT copy the "proprietary" node fields : children, parent, balance * * NOTE: this macro is most likely not used anymore */ #define AVL_COPY_PAYLOAD(node_trg,node_src) rrl_payload_copy((node_trg), (node_src)) /* * A macro to preprocess a node before it is preprocessed for a delete (detach) * If there was anything to do BEFORE deleting a node, we would do it here * After this macro is exectuted, the node * _ is detached, then deleted with FREE_NODE * _ has got its content overwritten by the one of another node, then the other * node is deleted with FREE_NODE */ #define AVL_NODE_DELETE_CALLBACK(node) #include static rrl_set_s g_rrl = NULL; static bool rrl_initialised = FALSE; void rrl_init() { if(rrl_initialised) { return; } rrl_initialised = TRUE; mutex_init(&rrl_mtx); rrl_set_init(&g_rrl); g_rrl_start = timeus(); g_rrl_rnd = random_init_auto(); g_rrl_slip_bucket = random_next(g_rrl_rnd); g_rrl_slip_bucket_bits = 32; /* u32 responses_per_tick = (5 * 1000000) >> (20 - EPOCH_PRECISION); u32 errors_per_tick = (5 * 1000000) >> (20 - EPOCH_PRECISION); u32 window_ticks = (15 * 1000000) >> (20 - EPOCH_PRECISION); */ } void rrl_cull_all(); void rrl_finalize() { rrl_cull_all(); rrl_set_destroy(&g_rrl); ptr_vector_destroy(&g_rrl_list); mutex_destroy(&rrl_mtx); random_finalize(g_rrl_rnd); rrl_initialised = FALSE; } /** * * Called when maybe we should slip * * @param mesg * @return */ static inline s32 rrl_slip(message_data *mesg) { s32 return_code = RRL_DROP; // g_rrl_slip_bucket is a global random 32 bits number // for every slip call, its lsb is shifted out and used to ... // 1 : send a truncated answer // 0 : drop the answer // // every 32 calls, fill the bucket again with a random number if((g_rrl_slip_bucket & 1) != 0) { // slip #if DEBUG log_debug("rrl: %{sockaddrip} %{dnsname} %{dnstype} %{dnsclass}: slipping", message_get_sender_sa(mesg), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif return_code = RRL_SLIP; if(!g_rrl_settings.log_only) { /** * Give a truncated answer */ message_update_truncated_answer_status(mesg); message_set_answer_count_ne(mesg, 0); message_set_authority_additional_counts(mesg, 0, 0); if(message_is_edns0(mesg)) { /* 00 00 29 SS SS rr vv 80 00 00 00 */ message_set_additional_count_ne(mesg, NETWORK_ONE_16); u8 *ednsrecord = message_get_buffer_limit(mesg); *ednsrecord++ = 0; // fqdn SET_U16_AT(*ednsrecord, TYPE_OPT); // type ednsrecord += 2; SET_U16_AT(*ednsrecord, htons(message_edns0_getmaxsize())); // udp payload size ednsrecord += 2; SET_U32_AT(*ednsrecord, message_get_rcode_ext(mesg)); // edns flags ednsrecord += 4; SET_U16_AT(*ednsrecord, 0); // rdata size // nsid message_increase_size(mesg, EDNS0_RECORD_SIZE); } } } else { if(g_rrl_settings.log_only) { return_code = RRL_PROCEED_DROP; } } if(--g_rrl_slip_bucket_bits > 0) { g_rrl_slip_bucket >>= 1; } else { g_rrl_slip_bucket_bits = 32; g_rrl_slip_bucket = random_next(g_rrl_rnd); } return return_code; } /** * Look at the message for RRL processing. * Returns an RRL code. * After this call, the message may be truncated. * * @param mesg the query message * @param ans_auth_add the answer that would be given to the client * @return an RRL error code */ /** * Look at the message for RRL processing. * Returns an RRL code. * After this call, the message may be truncated. * * @param mesg the query message * @param ans_auth_add the answer that would be given to the client * @return an RRL error code */ ya_result rrl_process(message_data *mesg, zdb_query_ex_answer *ans_auth_add) { s32 return_code = RRL_PROCEED; // if the RRL is enabled and // if the sender is not exempted if(!g_rrl_settings.enabled || (g_rrl_settings.exempted_filter(mesg, &g_rrl_settings.exempted) > 0)) { #if DEBUG log_debug("rrl: %{sockaddrip} %{dnsname} %{dnstype} %{dnsclass}: disabled or exempted", message_get_sender_sa(mesg), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif zdb_query_message_update(mesg, ans_auth_add); return return_code; } u64 now = timeus(); u8 key[RRL_KEY_SIZE_MAX]; rrl_make_key(mesg, ans_auth_add, key); now -= g_rrl_start; // it's us so about 20 bits of (im)precision now >>= (20 - EPOCH_PRECISION); // 1 s ~ 61.035 ticks mutex_lock(&rrl_mtx); rrl_item_s *item = rrl_set_insert(&g_rrl, key); if(item->timestamp > 0) { s32 hits; s32 limit; // ensure no overflow of the 1s bucket if((now - item->lasttimestamp) >= ONE_SECOND_TICKS) { // nothing happened for 1 second, we cannot accumulate so ... // we cut at lasttimestamp, we remove (lasttimestamp - timestamp) * rps s32 tsd = (now - item->timestamp) & ~(ONE_SECOND_TICKS - 1); item->timestamp += tsd; s32 hsd = (tsd >> EPOCH_PRECISION) * g_rrl_settings.responses_per_second; #if DEBUG log_debug("rrl: %{sockaddrip} %{dnsname} %{dnstype} %{dnsclass}: 1s bucket overflow; delta time = %d (%ds); hits adjusted from %i to %i", message_get_sender_sa(mesg), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), tsd, tsd >> EPOCH_PRECISION, item->hits, MAX(item->hits - hsd, 0)); #endif item->hits -= hsd; if(item->hits < 0) { item->hits = 0; item->timestamp = now - ONE_SECOND_TICKS; } // tsd } item->lasttimestamp = now; u32 ticks = (now - item->timestamp); // 1s + delta time (so we see for 1 second) hits = item->hits + 1; // ensure now overflow of the hits counter if(hits == MAX_U16) { // divide hits by 16 // divide time by 16 // adjust hits >>= 4; item->hits = hits; ticks >>= 4; item->timestamp = now - ticks; } // compute the current limit if(!rrl_key_is_error(key)) { limit = ((g_rrl_settings.responses_per_second * ticks) >> EPOCH_PRECISION); #if DEBUG log_debug("rrl: %{sockaddrip} %{dnsname} %{dnstype} %{dnsclass}: %i responses with a limit of %i in %i ticks, %i/s, %is", message_get_sender_sa(mesg), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), hits, limit, ticks, g_rrl_settings.responses_per_second, ticks >> EPOCH_PRECISION); #endif } else { limit = ((g_rrl_settings.errors_per_second * ticks) >> EPOCH_PRECISION); #if DEBUG log_debug("rrl: %{sockaddrip} %{dnsname} %{dnstype} %{dnsclass}: %i errors with a limit of %i in %i ticks, %i/s, %is", message_get_sender_sa(mesg), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), hits, limit, ticks, g_rrl_settings.errors_per_second, ticks >> EPOCH_PRECISION); #endif } // test if we are in the allowed rate if(hits <= limit) { item->hits = hits; } else { #if DEBUG log_debug("rrl: %{sockaddrip} %{dnsname} %{dnstype} %{dnsclass}: rate exceeded", message_get_sender_sa(mesg), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif // rate exceeded, drop ... except if we slip return_code = g_rrl_settings.drop_default; if((g_rrl_settings.slip > 0 ) && (--item->slip_countdown == 0)) { #if DEBUG // pure debug log_debug("rrl: %{sockaddrip} %{dnsname} %{dnstype} %{dnsclass}: testing slip", message_get_sender_sa(mesg), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif item->slip_countdown = g_rrl_settings.slip; /* * Every 'slip' counts, compute if we slip or drop */ if((return_code = rrl_slip(mesg)) == RRL_SLIP) { // count it item->hits = hits; } } } mutex_unlock(&rrl_mtx); if(((return_code & (RRL_SLIP|RRL_DROP)) == 0) || g_rrl_settings.log_only) { #if DEBUG log_debug("rrl: %{sockaddrip} %{dnsname} %{dnstype} %{dnsclass}: %x | %i", message_get_sender_sa(mesg), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg), return_code, g_rrl_settings.log_only); #endif zdb_query_message_update(mesg, ans_auth_add); } } else { #if DEBUG // pure debug log_debug("rrl: %{sockaddrip} %{dnsname} %{dnstype} %{dnsclass}: new entry", message_get_sender_sa(mesg), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_query_class_ptr(mesg)); #endif item->timestamp = now - ONE_SECOND_TICKS; item->lasttimestamp = now; item->slip_countdown = g_rrl_settings.slip; if(g_rrl_list.offset + 1 < g_rrl_settings.max_table_size) { // enough room: append ptr_vector_append_restrict_size(&g_rrl_list, item, g_rrl_settings.max_table_size); } else { // full: replace s32 victim = random_next(g_rrl_rnd) % g_rrl_settings.max_table_size; #if DEBUG log_debug("rrl: table is full (%u), removing entry #%i", g_rrl_settings.max_table_size, victim); #endif rrl_item_s *victim_item = (rrl_item_s *)g_rrl_list.data[victim]; rrl_set_delete(&g_rrl, victim_item->error_mask_ip_imputed_name); g_rrl_list.data[victim] = item; } mutex_unlock(&rrl_mtx); zdb_query_message_update(mesg, ans_auth_add); } return return_code; } void rrl_cull() { u64 now = timeus(); now -= g_rrl_start; // it's us so about 20 bits of (im)precision now >>= (20 - EPOCH_PRECISION); mutex_lock(&rrl_mtx); for(s32 i = 0; i <= g_rrl_list.offset; i++) { rrl_item_s *item = (rrl_item_s *)g_rrl_list.data[i]; if(now - item->lasttimestamp > g_rrl_settings.window_ticks) { // put the end here (i == offset is irrelevant) g_rrl_list.data[i] = g_rrl_list.data[g_rrl_list.offset]; g_rrl_list.offset--; // remove from the tree rrl_set_delete(&g_rrl, item->error_mask_ip_imputed_name); } } mutex_unlock(&rrl_mtx); } void rrl_cull_all() { mutex_lock(&rrl_mtx); for(s32 i = 0; i <= g_rrl_list.offset; i++) { rrl_item_s *item = (rrl_item_s *)g_rrl_list.data[i]; g_rrl_list.data[i] = g_rrl_list.data[g_rrl_list.offset]; // remove from the tree rrl_set_delete(&g_rrl, item->error_mask_ip_imputed_name); } g_rrl_list.offset = -1; mutex_unlock(&rrl_mtx); } bool rrl_is_logonly() { return g_rrl_settings.log_only; } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/dynupdate_query_service.c0000644000000000000000000000013114505005533024000 xustar000000000000000030 mtime=1695812443.480997054 29 atime=1695812445.78203001 30 ctime=1695812495.698744918 yadifa-2.6.5-11201/sbin/yadifad/dynupdate_query_service.c0000664000374500037450000002760414505005533023754 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup * @ingroup * @brief * * * * @{ * *----------------------------------------------------------------------------*/ #include "server-config.h" #if HAS_PTHREAD_SETNAME_NP #if DEBUG #define _GNU_SOURCE 1 #endif #endif #include #include #include #include #include #include #include #include "database.h" #include "server.h" /*------------------------------------------------------------------------------ * GLOBAL VARIABLES */ #define MODULE_MSG_HANDLE g_server_logger /*------------------------------------------------------------------------------ * STATIC PROTOTYPES */ /*------------------------------------------------------------------------------ * FUNCTIONS */ /** @brief Function ... * * ... * * @param ... * * @retval OK * @retval NOK */ /** * * The dynupdate service loads the next update from the queue and runs it. */ static threaded_queue dynupdate_query_service_queue = THREADED_QUEUE_EMPTY; static u32 g_dynupdate_query_service_queue_size = 4096; typedef struct dynupdate_query_service_args dynupdate_query_service_args; #define DYNUPQSA_TAG 0x41535150554e5944 struct dynupdate_query_service_args { zdb *db; message_data *mesg; s64 timestamp; int sockfd; }; static const s64 dynupdate_query_timeout_us = ONE_SECOND_US * 3; static void dynupdate_query_service_queue_clear() { dynupdate_query_service_args* parms; while((parms = (dynupdate_query_service_args*)threaded_queue_try_dequeue(&dynupdate_query_service_queue)) != NULL) { message_free(parms->mesg); free(parms); } } static void dynupdate_query_service_wakeup(struct service_s *desc) { (void)desc; threaded_queue_try_enqueue(&dynupdate_query_service_queue, NULL); } static int dynupdate_query_service_thread(struct service_worker_s *worker) { log_info("dynupdate: service started"); service_set_servicing(worker); for(;;) { if(service_should_reconfigure_or_stop(worker)) { if(!service_should_run(worker)) { break; } // reconfiguring ... dynupdate_query_service_queue_clear(); service_clear_reconfigure(worker); continue; } /** * * Needs all the parameters for UDP answer. * Needs the time of the query. If it's too old (> 3s) forget it. * */ dynupdate_query_service_args* parms = (dynupdate_query_service_args*)threaded_ringbuffer_cw_dequeue(&dynupdate_query_service_queue); if(parms == NULL) { #if DEBUG log_debug("dynupdate_query_service_thread: woken up by an empty message"); #endif continue; } message_data *mesg = parms->mesg; s64 now = timeus(); if((now - parms->timestamp) <= dynupdate_query_timeout_us) { /* process */ zdb *database = parms->db; /* clone the message */ /* use the same scheduling mechanism as for TCP */ log_info("update (%04hx) %{dnsname} %{dnstype} (%{sockaddr})", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), message_get_sender_sa(mesg)); ya_result ret = database_update(database, mesg); if(FAIL(ret)) { if(message_get_query_type(mesg) == TYPE_SOA) { if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { log_info("update (%04hx) %{dnsname} temporary failure: zone file must be stored: %r", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), ret); } else { log_warn("update (%04hx) %{dnsname} failed: %r", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), ret); } } else { if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { log_info("update (%04hx) %{dnsname} %{dnstype} temporary failure: zone file must be stored: %r", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), ret); } else { log_warn("update (%04hx) %{dnsname} %{dnstype} failed: %r", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), ret); } } } //local_statistics->udp_fp[message_get_status(mesg)]++; #if !HAS_DROPALL_SUPPORT s32 sent; #if DEBUG log_debug("dynupdate_query_service_thread: sendto(%d, %p, %d, %d, %{sockaddr}, %d)", parms->sockfd, message_get_buffer_const(mesg), message_get_size(mesg), 0, message_get_sender_sa(mesg), message_get_sender_size(mesg)); log_memdump_ex(g_server_logger, MSG_DEBUG5, message_get_buffer_const(mesg), message_get_size(mesg), 16, OSPRINT_DUMP_HEXTEXT); #endif if(FAIL(sent = message_send_udp(mesg, parms->sockfd))) { ya_result err = sent; /** @warning server_st_process_udp needs to be modified */ log_err("update (%04hx) %{dnsname} %{dnstype} send failed: %r", ntohs(message_get_id(mesg)), message_get_canonised_fqdn(mesg), message_get_query_type_ptr(mesg), err); message_free(mesg); free(parms); continue; } //local_statistics->udp_output_size_total += sent; if(sent != (s32)message_get_size(mesg)) { /** @warning server_st_process_udp needs to be modified */ log_err("short byte count sent (%lli instead of %i)", sent, message_get_size(mesg)); } #else log_debug("dynupdate_query_service_thread: drop all"); #endif } message_free(mesg); free(parms); } log_info("dynupdate: service stopped"); return SUCCESS; } static struct service_s dynupdate_query_service_handler = UNINITIALIZED_SERVICE; ya_result dynupdate_query_service_init() { ya_result ret; if(ISOK(ret = service_init_ex2(&dynupdate_query_service_handler, dynupdate_query_service_thread, dynupdate_query_service_wakeup, "svrudpdu", 1))) { threaded_queue_init(&dynupdate_query_service_queue, g_dynupdate_query_service_queue_size); log_info("dynupdate: service initialised"); } else { log_err("dynupdate: failed to initialise service: %r", ret); } return ret; } ya_result dynupdate_query_service_start() { ya_result ret; log_debug("dynupdate_query_service_start: starting service"); ret = service_start(&dynupdate_query_service_handler); return ret; } ya_result dynupdate_query_service_stop() { ya_result ret = SUCCESS; if(service_initialised(&dynupdate_query_service_handler) && service_started(&dynupdate_query_service_handler)) { log_debug("dynupdate_query_service_stop: stopping dynamic update service"); threaded_queue_try_enqueue(&dynupdate_query_service_queue, NULL); // to wake up the service ret = service_stop(&dynupdate_query_service_handler); log_debug("dynupdate_query_service_stop: emptying dynamic update queue"); dynupdate_query_service_queue_clear(); log_debug("dynamic update service stopped"); } return ret; } void dynupdate_query_service_finalise() { if(service_initialised(&dynupdate_query_service_handler)) { dynupdate_query_service_stop(); service_finalize(&dynupdate_query_service_handler); dynupdate_query_service_queue_clear(); threaded_queue_finalize(&dynupdate_query_service_queue); } } ya_result dynupdate_query_service_enqueue(zdb *db, message_data *mesg, int sockfd) { if(!service_started(&dynupdate_query_service_handler)) { return SERVICE_NOT_RUNNING; } if(threaded_queue_size(&dynupdate_query_service_queue) == g_dynupdate_query_service_queue_size) { return MAKE_DNSMSG_ERROR(RCODE_SERVFAIL); // it will not be used as is, but that's what needs to be said } message_data *clone = message_dup(mesg); if(clone == NULL) { return BUFFER_WOULD_OVERFLOW; } // ensure the original message cannot be used anymore struct dynupdate_query_service_args *parms; MALLOC_OBJECT_OR_DIE(parms, dynupdate_query_service_args, DYNUPQSA_TAG); parms->db = db; parms->mesg = clone; parms->timestamp = timeus(); parms->sockfd = sockfd; threaded_queue_enqueue(&dynupdate_query_service_queue, parms); #if DNSCORE_HAS_TSIG_SUPPORT message_tsig_clear_key(mesg); #endif message_set_size(mesg, 0); // resets the message size return SUCCESS; } void dynupdate_query_service_reset() { if(service_initialised(&dynupdate_query_service_handler) && service_started(&dynupdate_query_service_handler)) { service_reconfigure(&dynupdate_query_service_handler); threaded_queue_enqueue(&dynupdate_query_service_queue, NULL); // to wake up the service } } /** @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/database-service-zone-resignature.c0000644000000000000000000000013114505005533025537 xustar000000000000000030 mtime=1695812443.478997026 29 atime=1695812445.78203001 30 ctime=1695812495.700744946 yadifa-2.6.5-11201/sbin/yadifad/database-service-zone-resignature.c0000664000374500037450000020145014505005533025504 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup database Routines for database manipulations * @ingroup yadifad * @brief database functions * * Implementation of routines for the database * - add zone file(s) * - clear zone file(s) * - print zone files(s) * - load db * - unload db * - lookup database result of a message * * @{ */ /*------------------------------------------------------------------------------ * * USE INCLUDES */ #include "server-config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "database-service.h" #include "database-service-zone-resignature.h" #include "notify.h" #include "zone-signature-policy.h" #if HAS_EVENT_DYNAMIC_MODULE #include "dynamic-module-handler.h" #endif #ifndef HAS_DYNUPDATE_DIFF_ENABLED #error "HAS_DYNUPDATE_DIFF_ENABLED not defined" #endif #if !HAS_RRSIG_MANAGEMENT_SUPPORT #error "RRSIG management support disabled : this file should not be compiled" #endif #define MODULE_MSG_HANDLE g_server_logger #define DBUPSIGP_TAG 0x5047495350554244 #define RESIGALR_TAG 0x524c414749534552 ya_result zone_policy_process(zone_desc_s *zone_desc); static struct thread_pool_s *database_service_zone_resignature_publish_dnskey_tp = NULL; static mutex_t database_service_zone_resignature_publish_dnskey_mtx = MUTEX_INITIALIZER; extern logger_handle *g_server_logger; extern zone_data_set database_zone_desc; struct database_service_zone_resignature_init_callback_s { zone_desc_s *zone_desc; dnskey_keyring keyring; u64 total_signature_valitity_time; // to compute the mean validity period u32 signature_count; u32 missing_signatures_count; u32 unverifiable_signatures_count; u32 earliest_expiration_epoch; u32 smallest_validity_period; u32 biggest_validity_period; }; struct database_service_zone_resignature_alarm_s { zone_desc_s *zone_desc; zdb_zone *zone; }; typedef struct database_service_zone_resignature_alarm_s database_service_zone_resignature_alarm_s; #define DSZZRPRM_TAG 0x4d5250525a5a5344 struct database_service_zone_resignature_dnskey_alarm_args { u8 *domain; u16 flags; u16 tag; u8 algorithm; }; typedef struct database_service_zone_resignature_dnskey_alarm_args database_service_zone_resignature_dnskey_alarm_args; struct database_service_zone_resignature_parms_s { zone_desc_s *zone_desc; }; typedef struct database_service_zone_resignature_parms_s database_service_zone_resignature_parms_s; static u32 database_service_zone_resignature_dnskey_alarm_unique_key(const dnssec_key *key, u32 operation) { u32 tag = dnskey_get_tag_const(key); u32 alg = dnskey_get_algorithm(key); return operation | (tag << 8) | (alg << 24); } database_service_zone_resignature_dnskey_alarm_args* database_service_zone_resignature_dnskey_alarm_args_new(const dnssec_key *key) { database_service_zone_resignature_dnskey_alarm_args *ret; ZALLOC_OBJECT_OR_DIE(ret,database_service_zone_resignature_dnskey_alarm_args, RESIGALR_TAG); ret->domain = dnsname_zdup(dnskey_get_domain(key)); ret->tag = dnskey_get_tag_const(key); ret->algorithm = dnskey_get_algorithm(key); ret->flags = key->flags; return ret; } void database_service_zone_resignature_dnskey_alarm_args_free(database_service_zone_resignature_dnskey_alarm_args *args) { dnsname_zfree(args->domain); ZFREE(args,database_service_zone_resignature_dnskey_alarm_args); } static ya_result database_service_zone_add_dnskey(dnssec_key *key) { // make a dynupdate query update that adds the record dynupdate_message dmsg; packet_unpack_reader_data reader; dynupdate_message_init(&dmsg, dnskey_get_domain(key), CLASS_IN); ya_result ret; if(ISOK(ret = dynupdate_message_add_dnskey(&dmsg, 86400, key))) { dynupdate_message_set_reader(&dmsg, &reader); u16 count = dynupdate_message_get_count(&dmsg); packet_reader_skip(&reader, DNS_HEADER_LENGTH); // eof checked below packet_reader_skip_fqdn(&reader); // eof checked below packet_reader_skip(&reader, 4); // eof checked below if(!packet_reader_eof(&reader)) { // the update is ready : push it zdb_zone *zone = zdb_acquire_zone_read_double_lock_from_fqdn(g_config->database, dnskey_get_domain(key), ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); if(zone != NULL) { for(;;) { u32 reader_offset = reader.offset; ret = dynupdate_diff(zone, &reader, count, ZDB_ZONE_MUTEX_DYNUPDATE, DYNUPDATE_DIFF_RUN); if(ISOK(ret)) { // done log_info("dnskey: %{dnsname}: +%03d+%05d/%d key added", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); //args->domain, args->algorithm, args->tag, ntohs(args->flags)); #if HAS_EVENT_DYNAMIC_MODULE if(dynamic_module_dnskey_interface_chain_available()) { dynamic_module_on_dnskey_publish(key); // we know this key has been pushed as we have crafted the update message } #endif notify_slaves(zone->origin); zdb_zone_set_maintained(zone, TRUE); } else if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { log_warn("dnskey: %{dnsname}: +%03d+%05d/%d could not add key as the journal is full", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); // trigger a background store of the zone //zdb_zone_info_background_store_zone(dnskey_get_domain(key)); if(ISOK(ret = zdb_zone_info_store_locked_zone(dnskey_get_domain(key)))) { reader.offset = reader_offset; continue; } else { log_err("dnskey: %{dnsname}: failed to store the zone on disk: %r", dnskey_get_domain(key), ret); } } break; } zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); zdb_zone_release(zone); } } else { ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } if(FAIL(ret)) { log_err("dnskey: %{dnsname}: +%03d+%05d/%d could not add key: %r", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)), ret); } dynupdate_message_finalize(&dmsg); return ret; } /** * Applies the dynamic update to that zone. * Note that the zone may be flushed on disk as a result (e.g. if the journal is full.) */ static ya_result database_service_zone_update_published_keys_flush(const u8 *fqdn, dynupdate_message *dmsg) { ya_result ret; packet_unpack_reader_data reader; dynupdate_message_set_reader(dmsg, &reader); u16 count = dynupdate_message_get_count(dmsg); packet_reader_skip(&reader, DNS_HEADER_LENGTH); // eof checked below packet_reader_skip_fqdn(&reader); // eof checked below packet_reader_skip(&reader, 4); // eof checked below if(!packet_reader_eof(&reader)) { // the update is ready : push it zdb_zone *zone = zdb_acquire_zone_read_double_lock_from_fqdn(g_config->database, fqdn, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); if(zone != NULL) { for(;;) { u32 reader_offset = reader.offset; ret = dynupdate_diff(zone, &reader, count, ZDB_ZONE_MUTEX_DYNUPDATE, DYNUPDATE_DIFF_RUN); if(ISOK(ret)) { // done } else if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { log_warn("dnskey: %{dnsname}: the journal is full", fqdn); // trigger a background store of the zone if(ISOK(ret = zdb_zone_info_store_locked_zone(fqdn))) { reader.offset = reader_offset; continue; // try again } else { log_err("dnskey: %{dnsname}: failed to store the zone on disk: %r", fqdn, ret); } } break; } zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); zdb_zone_release(zone); } else { ret = ZDB_ERROR_ZONE_NOT_IN_DATABASE; } } else { ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } return ret; } /* static void database_service_zone_maintain_presignatures_for_key(const u8 *fqdn, time_t now, dnssec_key *key) { zone_desc_s *zone_desc = zone_acquirebydnsname(fqdn); if(zone_desc != NULL) { zone_lock(zone_desc, ZONE_LOCK_READONLY); zdb_zone *zone = zone_get_loaded_zone(zone_desc); if(zone != NULL) { if(dnskey_is_activated_lenient(fqdn, now, zone->sig_validity_regeneration_seconds)) { // maintenance database_service_zone_dnssec_maintenance(zone_desc); } zdb_zone_release(zone); } zone_unlock(zone_desc, ZONE_LOCK_READONLY); zone_release(zone_desc); } } */ static ya_result database_service_zone_update_published_keys(const u8 *fqdn) { // make a dynupdate query update that adds the record zone_desc_s *zone_desc = zone_acquirebydnsname(fqdn); if(zone_desc == NULL) { return INVALID_STATE_ERROR; } ptr_vector publish_keys = EMPTY_PTR_VECTOR; ptr_vector delete_keys = EMPTY_PTR_VECTOR; if(dnssec_keystore_acquire_publish_delete_keys_from_fqdn_to_vectors(fqdn, &publish_keys, &delete_keys) == 0) { zone_release(zone_desc); return SUCCESS; // nothing to do } dynupdate_message dmsg; dynupdate_message_init(&dmsg, fqdn, CLASS_IN); ya_result ret = SUCCESS; int record_count = 0; bool should_star_maintenance = FALSE; bool some_work_done = FALSE; dnssec_policy *dp; bool is_dnssec_policy_managed = ((dp = zone_desc->dnssec_policy) != NULL); if(is_dnssec_policy_managed) { dnssec_policy_acquire(dp); } zone_release(zone_desc); for(int i = 0; i <= ptr_vector_last_index(&publish_keys); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&publish_keys, i); if(is_dnssec_policy_managed) { if(!dnssec_policy_is_key_matching(dp, key)) { continue; } } if(ISOK(ret = dynupdate_message_add_dnskey(&dmsg, 86400, key))) { bool key_should_start_maintenance = FALSE; zone_lock(zone_desc, ZONE_LOCK_READONLY); zdb_zone *zone = zone_get_loaded_zone(zone_desc); if(zone != NULL) { key_should_start_maintenance = dnskey_is_activated_lenient(key, time(NULL), zone->sig_validity_regeneration_seconds); should_star_maintenance |= key_should_start_maintenance; zdb_zone_release(zone); } zone_unlock(zone_desc, ZONE_LOCK_READONLY); log_info("dnskey: %{dnsname}: +%03d+%05d/%d key will be published %T => %T => %T => %T (%i)", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key), key_should_start_maintenance ); ++record_count; } else { // full ? if(record_count > 0) { // flush if(FAIL(ret = database_service_zone_update_published_keys_flush(fqdn, &dmsg))) { log_err("dnskey: %{dnsname}: key publication failed: %r", fqdn, ret); break; } some_work_done = TRUE; --i; record_count = 0; dynupdate_message_reset(&dmsg, fqdn, CLASS_IN); } else { log_err("dnskey: %{dnsname}: key publication message creation failed: %r", fqdn, ret); break; } } } if(is_dnssec_policy_managed) { dnssec_policy_release(dp); dp = NULL; } if(ISOK(ret)) { for(int i = 0; i <= ptr_vector_last_index(&delete_keys); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&delete_keys, i); if(ISOK(ret = dynupdate_message_del_dnskey(&dmsg, key))) { log_info("dnskey: %{dnsname}: +%03d+%05d/%d key will be unpublished %T => %T => %T => %T", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key)); ++record_count; } else { // full ? if(record_count > 0) { // flush if(FAIL(ret = database_service_zone_update_published_keys_flush(fqdn, &dmsg))) { log_err("dnskey: %{dnsname}: key deletion failed: %r", fqdn, ret); break; } some_work_done = TRUE; --i; record_count = 0; dynupdate_message_reset(&dmsg, fqdn, CLASS_IN); } else { log_err("dnskey: %{dnsname}: key deletion message creation failed: %r", fqdn, ret); break; } } } } if(ISOK(ret)) { if(record_count > 0) { if(ISOK(ret = database_service_zone_update_published_keys_flush(fqdn, &dmsg))) { some_work_done = TRUE; } else { log_err("dnskey: %{dnsname}: key publication failed: %r (last stage)", fqdn, ret); } } } // does the zone needs to have its chain(s) processed ? zone_desc = zone_acquirebydnsname(fqdn); if(zone_desc != NULL) { zone_lock(zone_desc, ZONE_LOCK_READONLY); zone_policy_process_dnssec_chain(zone_desc); zone_unlock(zone_desc, ZONE_LOCK_READONLY); zone_release(zone_desc); } dynupdate_message_finalize(&dmsg); dnssec_keystore_release_keys_from_vector(&delete_keys); dnssec_keystore_release_keys_from_vector(&publish_keys); ptr_vector_destroy(&delete_keys); ptr_vector_destroy(&publish_keys); if(some_work_done) { notify_slaves(fqdn); zdb_zone *zone = zdb_acquire_zone_read_double_lock_from_fqdn(g_config->database, fqdn, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); if(zone != NULL) { zdb_zone_set_maintained(zone, TRUE); zdb_zone_set_maintenance_paused(zone, FALSE); zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); zdb_zone_release(zone); } if(should_star_maintenance) { zone_desc = zone_acquirebydnsname(fqdn); if(zone_desc != NULL) { log_debug("dnskey: %{dnsname}: starting maintenance", fqdn); database_service_zone_dnssec_maintenance(zone_desc); zone_release(zone_desc); } else { log_err("dnskey: %{dnsname}: cannot start maintenance", fqdn); // which should never happen } } else { log_debug("dnskey: %{dnsname}: no maintenance needed", fqdn); } } return ret; } static ya_result database_service_zone_remove_dnskey(dnssec_key *key) { // make a dynupdate query update that removes the record dynupdate_message dmsg; packet_unpack_reader_data reader; dynupdate_message_init(&dmsg, dnskey_get_domain(key), CLASS_IN); ya_result ret; if(ISOK(ret = dynupdate_message_del_dnskey(&dmsg, key))) { dynupdate_message_set_reader(&dmsg, &reader); u16 count = dynupdate_message_get_count(&dmsg); packet_reader_skip(&reader, DNS_HEADER_LENGTH); // eof checked below packet_reader_skip_fqdn(&reader); // eof checked below packet_reader_skip(&reader, 4); // eof checked below // the update is ready : push it if(!packet_reader_eof(&reader)) { zdb_zone *zone = zdb_acquire_zone_read_double_lock_from_fqdn(g_config->database, dnskey_get_domain(key), ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); if(zone != NULL) { for(;;) { u32 reader_offset = reader.offset; ret = dynupdate_diff(zone, &reader, count, ZDB_ZONE_MUTEX_DYNUPDATE, DYNUPDATE_DIFF_RUN); if(ISOK(ret)) { // done log_info("dnskey: %{dnsname}: +%03d+%05d/%d key removed", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); #if HAS_EVENT_DYNAMIC_MODULE if(dynamic_module_dnskey_interface_chain_available()) { dynamic_module_on_dnskey_delete(key); } #endif notify_slaves(zone->origin); } else if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) { log_warn("dnskey: %{dnsname}: +%03d+%05d/%d could not remove key as the journal is full", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key))); // trigger a background store of the zone //zdb_zone_info_background_store_zone(dnskey_get_domain(key)); if(ISOK(ret = zdb_zone_info_store_locked_zone(dnskey_get_domain(key)))) { reader.offset = reader_offset; continue; } else { log_err("dnskey: %{dnsname}: failed to store the zone on disk: %r", dnskey_get_domain(key), ret); } } break; } zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); zdb_zone_release(zone); } } else { ret = MAKE_DNSMSG_ERROR(RCODE_FORMERR); } } if(FAIL(ret)) { log_err("dnskey: %{dnsname}: +%03d+%05d/%d could not remove key: %r", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag_const(key), ntohs(dnskey_get_flags(key)), ret); } dynupdate_message_finalize(&dmsg); return ret; } static void* database_service_zone_resignature_publish_dnskey_thread(void *args_) { database_service_zone_resignature_dnskey_alarm_args *args = (database_service_zone_resignature_dnskey_alarm_args*)args_; if(ISOK(database_service_zone_update_published_keys(args->domain))) { log_info("dnskey: %{dnsname}: DNSKEY rrset updated", args->domain); } else // failed, try to do the one { log_info("dnskey: %{dnsname}: +%03d+%05d/%d publish", args->domain, args->algorithm, args->tag, ntohs(args->flags)); // grab the key, ensure it should still be published, publish it dnssec_key *key; ya_result ret; if(ISOK(ret = dnssec_keystore_load_private_key_from_parameters(args->algorithm, args->tag, args->flags, args->domain, &key))) // key properly released { assert(key != NULL); time_t now = time(NULL); if(dnskey_is_published(key, now) && !dnskey_is_expired_now(key)) // do not smart-add an expired key (even if it's never unpublished) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: publish: in its publish time window", args->domain, args->algorithm, args->tag, ntohs(args->flags)); // has private KSK keys available now ? if(dnssec_keystore_has_usable_ksk(dnskey_get_domain(key), now)) { if(ISOK(ret = database_service_zone_update_published_keys(dnskey_get_domain(key)))) { // database_service_zone_maintain_presignatures_for_key(dnskey_get_domain(key), now, key); } else { if(FAIL(ret = database_service_zone_add_dnskey(key))) { log_warn("dnskey: %{dnsname}: +%03d+%05d/%d: publish: key not published: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } } } else { log_err("dnskey: %{dnsname}: +%03d+%05d/%d: publish: key not published as there is no usable KSK at this time", args->domain, args->algorithm, args->tag, ntohs(args->flags)); ret = DNSSEC_ERROR_RRSIG_NOUSABLEKEYS; } } else if(dnskey_is_unpublished(key, now)) { log_warn("dnskey: %{dnsname}: +%03d+%05d/%d: publish: key should not be published anymore", args->domain, args->algorithm, args->tag, ntohs(args->flags)); // delete the key if it's in the zone if(ISOK(ret = database_service_zone_remove_dnskey(key))) { // remove the key from the store and rename the files dnssec_keystore_delete_key(key); } else { // the key was not removed // if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) // try again later (zone_policy_process will be called) log_warn("dnskey: %{dnsname}: +%03d+%05d/%d: publish: unpublish failed: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } } else { log_warn("dnskey: %{dnsname}: +%03d+%05d/%d: publish: key should not be published yet", args->domain, args->algorithm, args->tag, ntohs(args->flags)); } dnskey_release(key); zone_desc_s *zone_desc = zone_acquirebydnsname(args->domain); if(zone_desc != NULL) { if(ISOK(ret = zone_policy_process(zone_desc))) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: publish: post-publish policy process done", args->domain, args->algorithm, args->tag, ntohs(args->flags)); } else { log_err("dnskey: %{dnsname}: +%03d+%05d/%d: publish: post-publish policy process failed: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } zone_release(zone_desc); } } else { assert(key == NULL); log_err("dnskey: %{dnsname}: +%03d+%05d/%d:publish: cancelled: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: publish: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); database_service_zone_resignature_dnskey_alarm_args_free(args); } return NULL; } static ya_result database_service_zone_resignature_publish_dnskey_alarm(void *args_, bool cancel) { database_service_zone_resignature_dnskey_alarm_args *args = (database_service_zone_resignature_dnskey_alarm_args*)args_; ya_result ret = SUCCESS; if(!cancel) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: publish ...", args->domain, args->algorithm, args->tag, ntohs(args->flags)); if(thread_pool_try_enqueue_call(database_service_zone_resignature_publish_dnskey_tp, database_service_zone_resignature_publish_dnskey_thread, args, NULL, "dnskey-publish alarm") == LOCK_TIMEOUT) { ret = ALARM_REARM; } } else { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: publish alarm cancelled", args->domain, args->algorithm, args->tag, ntohs(args->flags)); database_service_zone_resignature_dnskey_alarm_args_free(args); } return ret; } static void* database_service_zone_resignature_unpublish_dnskey_thread(void *args_) { database_service_zone_resignature_dnskey_alarm_args *args = (database_service_zone_resignature_dnskey_alarm_args*)args_; if(ISOK(database_service_zone_update_published_keys(args->domain))) // fails -> works { log_info("dnskey: %{dnsname}: DNSKEY rrset updated (unpublish)", args->domain); } else // failed, try to do the one { ya_result ret; log_info("dnskey: %{dnsname}: +%03d+%05d/%d: unpublish", args->domain, args->algorithm, args->tag, ntohs(args->flags)); // grab the key, ensure it should still be published, publish it dnssec_key *key = NULL; if(ISOK(ret = dnssec_keystore_load_private_key_from_parameters(args->algorithm, args->tag, args->flags, args->domain, &key))) // key properly released { assert(key != NULL); if(dnskey_is_unpublished(key, time(NULL))) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: unpublish: out of its publish time window", args->domain, args->algorithm, args->tag, ntohs(args->flags)); if(ISOK(ret = database_service_zone_remove_dnskey(key))) { // remove the key from the store and rename the files dnssec_keystore_delete_key(key); } else { // the key was not removed // if(ret == ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY) // try again later (zone_policy_process will be called) log_warn("dnskey: %{dnsname}: +%03d+%05d/%d: unpublish: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } } else { if(dnskey_has_explicit_delete(key)) { log_warn("dnskey: %{dnsname}: +%03d+%05d/%d: unpublish: key should not be unpublished (not until %T)", args->domain, args->algorithm, args->tag, ntohs(args->flags), key->epoch_delete); } else { log_warn("dnskey: %{dnsname}: +%03d+%05d/%d: unpublish: key should not be unpublished (ever)", args->domain, args->algorithm, args->tag, ntohs(args->flags)); } } dnskey_release(key); zone_desc_s *zone_desc = zone_acquirebydnsname(args->domain); if(zone_desc != NULL) { if(ISOK(ret = zone_policy_process(zone_desc))) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: unpublish: post-unpublish policy process done", args->domain, args->algorithm, args->tag, ntohs(args->flags)); } else { log_err("dnskey: %{dnsname}: +%03d+%05d/%d: unpublish: post-unpublish policy process failed: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } zone_release(zone_desc); } } else { assert(key == NULL); log_err("dnskey: %{dnsname}: +%03d+%05d/%d: unpublish cancelled: private key not available: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: unpublish: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } database_service_zone_resignature_dnskey_alarm_args_free(args); return NULL; } static ya_result database_service_zone_resignature_unpublish_dnskey_alarm(void *args_, bool cancel) { database_service_zone_resignature_dnskey_alarm_args *args = (database_service_zone_resignature_dnskey_alarm_args*)args_; ya_result ret = SUCCESS; if(!cancel) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: removal ...", args->domain, args->algorithm, args->tag, ntohs(args->flags)); if(thread_pool_try_enqueue_call(database_service_zone_resignature_publish_dnskey_tp, database_service_zone_resignature_unpublish_dnskey_thread, args, NULL, "dnskey-unpublish alarm") == LOCK_TIMEOUT) { ret = ALARM_REARM; } } else { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: removal alarm cancelled", args->domain, args->algorithm, args->tag, ntohs(args->flags)); database_service_zone_resignature_dnskey_alarm_args_free(args); } return ret; } static void* database_service_zone_resignature_activate_dnskey_thread(void *args_) { database_service_zone_resignature_dnskey_alarm_args *args = (database_service_zone_resignature_dnskey_alarm_args*)args_; dnssec_key *key = NULL; ya_result ret = dnssec_keystore_load_private_key_from_parameters(args->algorithm, args->tag, args->flags, args->domain, &key); if(ISOK(ret)) { u32 state = dnskey_state_get(key); if((state & DNSKEY_KEY_IS_ACTIVE) == 0) // not active yet ? { time_t now = time(NULL); if((state & DNSKEY_KEY_IS_IN_ZONE) == 0) // not in zone yet ? { // will be automatically added, except if there is no signing key for this /* * YADIFA-168 key point * * current: KSK or nothing * * should be: ((policy without a KSK) || (!policy but zone without a KSK)) => ZSK allowed, else KSK only */ bool can_edit_dnskey_rrsig = FALSE; zone_desc_s *zone_desc = zone_acquirebydnsname(args->domain); if(zone_desc != NULL) { dnssec_policy *dp = zone_desc->dnssec_policy; if(dp != NULL) { if(dnssec_policy_defines_ksk(dp)) { // ksk only can_edit_dnskey_rrsig = dnssec_keystore_has_usable_ksk(dnskey_get_domain(key), now); } else { can_edit_dnskey_rrsig = TRUE; // (args->flags == DNSKEY_FLAGS_KSK) || (args->flags == DNSKEY_FLAGS_ZSK); } } else { if(dnssec_keystore_has_any_ksk(dnskey_get_domain(key))) { can_edit_dnskey_rrsig = dnssec_keystore_has_usable_ksk(dnskey_get_domain(key), now); } else { can_edit_dnskey_rrsig = dnssec_keystore_has_usable_zsk(dnskey_get_domain(key), now); } } zone_release(zone_desc); } if(!can_edit_dnskey_rrsig) { log_info("dnskey: %{dnsname}: +%03d+%05d/%d: is not in the zone and cannot be added (no KSK can be used)", args->domain, args->algorithm, args->tag, ntohs(args->flags)); dnskey_release(key); database_service_zone_resignature_dnskey_alarm_args_free(args); return NULL; } if(ISOK(ret = database_service_zone_update_published_keys(args->domain))) { log_info("dnskey: %{dnsname}: DNSKEY rrset updated, triggered by key activation", args->domain); } else { log_err("dnskey: %{dnsname}: +%03d+%05d/%d: is not in the zone and cannot be added: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); dnskey_release(key); database_service_zone_resignature_dnskey_alarm_args_free(args); return NULL; } } zone_desc_s *zone_desc = zone_acquirebydnsname(args->domain); if(zone_desc != NULL) { dnskey_state_enable(key, DNSKEY_KEY_IS_ACTIVE); database_service_zone_dnssec_maintenance(zone_desc); #if HAS_EVENT_DYNAMIC_MODULE if(dynamic_module_dnskey_interface_chain_available()) { dynamic_module_on_dnskey_activate(key); } #endif zone_release(zone_desc); } } dnskey_release(key); log_info("dnskey: %{dnsname}: +%03d+%05d/%d: activation", args->domain, args->algorithm, args->tag, ntohs(args->flags)); } else { zone_desc_s *zone_desc = zone_acquirebydnsname(args->domain); if(zone_desc != NULL) { if(zone_rrsig_nsupdate_allowed(zone_desc)) { if(args->flags == DNSKEY_FLAGS_ZSK) { log_notice("dnskey: %{dnsname}: +%03d+%05d/%d: activation failed: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } else if(args->flags == DNSKEY_FLAGS_KSK) { log_info("dnskey: %{dnsname}: +%03d+%05d/%d: activation failed, which is probably expected: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } else { log_warn("dnskey: %{dnsname}: could not activate +%03d+%05d/%d: %r, and flags aren't ZSK nor KSK", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } } else { log_err("dnskey: %{dnsname}: +%03d+%05d/%d: activation failed: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } zone_release(zone_desc); } else { log_err("dnskey: %{dnsname}: +%03d+%05d/%d: activation failed: %r", args->domain, args->algorithm, args->tag, ntohs(args->flags), ret); } } database_service_zone_resignature_dnskey_alarm_args_free(args); return NULL; } static ya_result database_service_zone_resignature_activate_dnskey_alarm(void *args_, bool cancel) { database_service_zone_resignature_dnskey_alarm_args *args = (database_service_zone_resignature_dnskey_alarm_args*)args_; ya_result ret = SUCCESS; if(!cancel) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: activation ...", args->domain, args->algorithm, args->tag, ntohs(args->flags)); if(thread_pool_try_enqueue_call(database_service_zone_resignature_publish_dnskey_tp, database_service_zone_resignature_activate_dnskey_thread, args, NULL, "dnskey-activate alarm") == LOCK_TIMEOUT) { ret = ALARM_REARM; } } else { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: activation alarm cancelled", args->domain, args->algorithm, args->tag, ntohs(args->flags)); database_service_zone_resignature_dnskey_alarm_args_free(args); } return ret; } static void* database_service_zone_resignature_deactivate_dnskey_thread(void *args_) { database_service_zone_resignature_dnskey_alarm_args *args = (database_service_zone_resignature_dnskey_alarm_args*)args_; log_info("dnskey: %{dnsname}: +%03d+%05d/%d: deactivation", args->domain, args->algorithm, args->tag, ntohs(args->flags)); zone_desc_s *zone_desc = zone_acquirebydnsname(args->domain); if(zone_desc != NULL) { database_service_zone_dnssec_maintenance(zone_desc); #if HAS_EVENT_DYNAMIC_MODULE if(dynamic_module_dnskey_interface_chain_available()) { dnssec_key *key = NULL; ya_result ret = dnssec_keystore_load_private_key_from_parameters(args->algorithm, args->tag, args->flags, args->domain, &key); if(ISOK(ret)) { dynamic_module_on_dnskey_inactive(key); dnskey_release(key); } else { log_warn("dnskey: %{dnsname}: +%03d+%05d/%d: could not load key to notify deactivation to module", args->domain, args->algorithm, args->tag, ntohs(args->flags)); } } #endif zone_release(zone_desc); } database_service_zone_resignature_dnskey_alarm_args_free(args); return NULL; } static ya_result database_service_zone_resignature_deactivate_dnskey_alarm(void *args_, bool cancel) { database_service_zone_resignature_dnskey_alarm_args *args = (database_service_zone_resignature_dnskey_alarm_args*)args_; ya_result ret = SUCCESS; if(!cancel) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: deactivation ...", args->domain, args->algorithm, args->tag, ntohs(args->flags)); if(thread_pool_try_enqueue_call(database_service_zone_resignature_publish_dnskey_tp, database_service_zone_resignature_deactivate_dnskey_thread, args, NULL, "dnskey-deactivate alarm") == LOCK_TIMEOUT) { ret = ALARM_REARM; } } else { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: deactivation alarm cancelled", args->domain, args->algorithm, args->tag, ntohs(args->flags)); database_service_zone_resignature_dnskey_alarm_args_free(args); } return ret; } void database_service_zone_dnskey_set_alarms_for_key(zdb_zone *zone, dnssec_key *key) { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: setting alarms", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key))); time_t now = time(NULL); zdb_zone_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); bool in_zone = zdb_zone_contains_dnskey_record_for_key(zone, key); //bool signs = zdb_zone_apex_contains_rrsig_record_by_key(zone, key); zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); u32 state = dnskey_state_get(key); s32 publish_epoch = dnskey_get_publish_epoch(key); s32 active_epoch = dnskey_get_activate_epoch(key); s32 inactive_epoch = dnskey_get_inactive_epoch(key); s32 delete_epoch = dnskey_get_delete_epoch(key); bool give_up = FALSE; if(publish_epoch > active_epoch) { log_warn("dnskey: %{dnsname}: +%03d+%05d/%d: publication after activation %T > %T, setting publication to activation", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key)), publish_epoch, active_epoch); publish_epoch = active_epoch; } if(inactive_epoch > delete_epoch) { log_warn("dnskey: %{dnsname}: +%03d+%05d/%d: deactivation after delete %T > %T, setting delete to deactivation", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key)), inactive_epoch, delete_epoch); delete_epoch = inactive_epoch; } if((give_up |= (publish_epoch >= delete_epoch))) { log_err("dnskey: %{dnsname}: +%03d+%05d/%d: publication at or after deletion %T >= %T", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key)), publish_epoch, delete_epoch); } if((give_up |= (active_epoch >= inactive_epoch))) { log_err("dnskey: %{dnsname}: +%03d+%05d/%d: activation at or after deactivation %T >= %T", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key)), publish_epoch, delete_epoch); } if(give_up) { log_notice("dnskey: %{dnsname}: +%03d+%05d/%d: gave up setting alarms", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key))); return; } s32 when; // if the key will need to be published if(now < delete_epoch) { // and the key hasn't been published already bool publish_queued = FALSE; if(!in_zone) { // follow the rule, if the key is not in the zone and should be, arm its publication even if it's never activated if((state & DNSKEY_KEY_PUBLISH_ARMED) == 0) { // mark the key as timed for publication and arm said publication // once the key is added, activation will occur too if needed when = publish_epoch; dnskey_state_enable(key, DNSKEY_KEY_PUBLISH_ARMED); log_info("dnskey: %{dnsname}: +%03d+%05d/%d: will be published at %T", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key)), when); alarm_event_node *event = alarm_event_new( // dnskey publish (resignature) when, database_service_zone_resignature_dnskey_alarm_unique_key(key, ALARM_KEY_ZONE_DNSKEY_PUBLISH), database_service_zone_resignature_publish_dnskey_alarm, database_service_zone_resignature_dnskey_alarm_args_new(key), ALARM_DUP_REMOVE_LATEST, "dnskey publish to zone"); alarm_set(zone->alarm_handle, event); publish_queued = TRUE; } else { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: already marked to be published", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key))); } } // if the key needs to be activated ... if(now < inactive_epoch) { if((state & DNSKEY_KEY_ACTIVATE_ARMED) == 0) { // mark the key as timed for activation and arm said activation // sig_validity_regeneration when = MIN(MAX(active_epoch - zone->sig_validity_regeneration_seconds, now - zone->sig_validity_regeneration_seconds - 5), publish_epoch); #if DEBUG log_info("dnskey: %{dnsname}: +%03d+%05d/%d: activation alarm set to %T but activation is really at %T (regeneration is: %i)", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key)), when, active_epoch, zone->sig_validity_regeneration_seconds); #endif if(!(publish_queued && (when <= publish_epoch))) { dnskey_state_enable(key, DNSKEY_KEY_ACTIVATE_ARMED); log_info("dnskey: %{dnsname}: +%03d+%05d/%d: will be activated at %T", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key)), when); // set alarm alarm_event_node *event = alarm_event_new( // dnskey activate (resignature) when, database_service_zone_resignature_dnskey_alarm_unique_key(key, ALARM_KEY_ZONE_DNSKEY_ACTIVATE), database_service_zone_resignature_activate_dnskey_alarm, database_service_zone_resignature_dnskey_alarm_args_new(key), ALARM_DUP_REMOVE_LATEST, "dnskey activate from zone"); alarm_set(zone->alarm_handle, event); } else { log_info("dnskey: %{dnsname}: +%03d+%05d/%d: will be activated along with publication at %T", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key)), MAX(publish_epoch, now)); } } else { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: already marked to be activated", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key))); } } } // if now < delete epoch // the actions to take if the key was not in the zone or needed to be activated are made. // deactivate, remove ... if(in_zone) { if(now <= inactive_epoch) { if((state & DNSKEY_KEY_DEACTIVATE_ARMED) != 0) { // mark the key as timed for activation and arm said activation dnskey_state_enable(key, DNSKEY_KEY_DEACTIVATE_ARMED); when = inactive_epoch; log_info("dnskey: %{dnsname}: +%03d+%05d/%d: will be deactivated at %T", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key)), when); // set alarm alarm_event_node *event = alarm_event_new( // dnskey deactivate (resignature) when, database_service_zone_resignature_dnskey_alarm_unique_key(key, ALARM_KEY_ZONE_DNSKEY_DEACTIVATE), database_service_zone_resignature_deactivate_dnskey_alarm, database_service_zone_resignature_dnskey_alarm_args_new(key), ALARM_DUP_REMOVE_LATEST, "dnskey deactivate from zone"); alarm_set(zone->alarm_handle, event); } else { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: already marked to be deactivated", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key))); } } if((state & DNSKEY_KEY_DELETE_ARMED) == 0) { dnskey_state_enable(key, DNSKEY_KEY_DELETE_ARMED); when = delete_epoch; log_info("dnskey: %{dnsname}: +%03d+%05d/%d: will be unpublished at %T", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key)), when); alarm_event_node *event = alarm_event_new( // dnskey unpublish (resignature) when, database_service_zone_resignature_dnskey_alarm_unique_key(key, ALARM_KEY_ZONE_DNSKEY_UNPUBLISH), database_service_zone_resignature_unpublish_dnskey_alarm, database_service_zone_resignature_dnskey_alarm_args_new(key), ALARM_DUP_REMOVE_LATEST, "dnskey unpublish from zone"); alarm_set(zone->alarm_handle, event); } else { log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: already marked to be unpublished", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key))); } } // in zone log_debug("dnskey: %{dnsname}: +%03d+%05d/%d: alarms have been set", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ntohs(dnskey_get_flags(key))); } /** * * Fetches all (smart signing) events of all the keys of a zone and arms them. * * @param zone */ void database_service_zone_dnskey_set_alarms(zdb_zone *zone) { // set alarms for the timings of the keys // (publish, activate, inactivate, unpublish) // this should probably only be done after the zone is mounted (else race could occur) log_info("database-service: %{dnsname}: set DNSKEY alarms", zone->origin); time_t now = time(NULL); for(int i = 0; ; ++i) { dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_at_index(zone->origin, i); if(key == NULL) { break; } if(dnskey_get_flags(key) != (DNSKEY_FLAG_ZONEKEY | DNSKEY_FLAG_KEYSIGNINGKEY)) { if(!dnskey_is_activated(key, now)) { continue; } if(!dnskey_is_private(key)) { continue; } break; } database_service_zone_dnskey_set_alarms_for_key(zone, key); dnskey_release(key); } for(int i = 0; ; ++i) { dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_at_index(zone->origin, i); if(key == NULL) { break; } database_service_zone_dnskey_set_alarms_for_key(zone, key); dnskey_release(key); } log_debug("database-service: %{dnsname}: DNSKEY alarms have been set", zone->origin); } static ya_result database_service_zone_dnskey_set_alarms_on_all_zones_callback(zone_desc_s *zone_desc, void *args) { (void)args; bool is_master; zone_lock(zone_desc, ZONE_LOCK_READONLY); is_master = (zone_desc->type == ZT_MASTER); zdb_zone *zone = zone_get_loaded_zone(zone_desc); zone_unlock(zone_desc, ZONE_LOCK_READONLY); if(!is_master) { if(zone != NULL) { zdb_zone_release(zone); } log_debug("%{dnsname}: not master, skipping setting of the DNSKEY alarm (part of a batch)", zone_origin(zone_desc)); return SUCCESS; } if(zone != NULL) { if(zdb_zone_is_maintained(zone)) { log_debug("%{dnsname}: setting DNSKEY alarm (part of a batch)", zone->origin); database_service_zone_dnskey_set_alarms(zone); } else { log_debug("%{dnsname}: not maintained, skipping setting of the DNSKEY alarm (part of a batch)", zone->origin); } zdb_zone_release(zone); } return SUCCESS; } void database_service_zone_dnskey_set_alarms_on_all_zones() { zone_desc_for_all(database_service_zone_dnskey_set_alarms_on_all_zones_callback, NULL); } static database_service_zone_resignature_parms_s* database_service_zone_resignature_parms_alloc(zone_desc_s *zone_desc) { database_service_zone_resignature_parms_s *parm; ZALLOC_OBJECT_OR_DIE( parm, database_service_zone_resignature_parms_s, DSZZRPRM_TAG); parm->zone_desc = zone_desc; return parm; } void database_service_zone_resignature_parms_free(database_service_zone_resignature_parms_s *parm) { #if DEBUG memset(parm, 0xff, sizeof(database_service_zone_resignature_parms_s)); #endif ZFREE_OBJECT(parm); } #if ZDB_HAS_DNSSEC_SUPPORT && ZDB_HAS_RRSIG_MANAGEMENT_SUPPORT static void* database_service_zone_dnssec_maintenance_thread(void *parms_) { database_service_zone_resignature_parms_s *parms = (database_service_zone_resignature_parms_s*)parms_; zone_desc_s *zone_desc = parms->zone_desc; ya_result return_code; if(zone_desc == NULL) { // this happening probably means a buffer overrun has occurred, likely a corruption of the memory heap log_err("zone sign: database_service_zone_dnssec_maintenance_thread called with a NULL descriptor"); logger_flush(); // yes, it's important to flush for this database_service_zone_resignature_parms_free(parms); return NULL; } yassert(zone_desc != NULL); if(!zone_maintains_dnssec(zone_desc)) { log_warn("zone sign: %{dnsname}: resignature triggered although the feature was explicitly disabled : ignoring request.", zone_origin(zone_desc)); database_service_zone_resignature_parms_free(parms); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return NULL; } if(dnscore_shuttingdown()) { log_warn("zone sign: %{dnsname}: resignature called while shutting down : ignoring request.", zone_origin(zone_desc)); database_service_zone_resignature_parms_free(parms); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return NULL; } zone_lock(zone_desc, ZONE_LOCK_SIGNATURE); const u32 must_be_off = ZONE_STATUS_LOAD | ZONE_STATUS_LOADING | \ ZONE_STATUS_DROP | ZONE_STATUS_DROPPING | \ ZONE_STATUS_SAVING_ZONE_FILE | ZONE_STATUS_SAVING_AXFR_FILE | \ ZONE_STATUS_SIGNATURES_UPDATING | ZONE_STATUS_DYNAMIC_UPDATE | \ ZONE_STATUS_DYNAMIC_UPDATING; #if DEBUG log_debug("database_service_zone_dnssec_maintenance(%{dnsname}@%p=%i)", zone_origin(zone_desc), zone_desc, zone_desc->rc); #endif if((zone_get_status(zone_desc) & must_be_off) != 0) { log_err("zone sign: %{dnsname}: conflicting status: %08x instead of 0", zone_origin(zone_desc), (zone_get_status(zone_desc) & must_be_off)); zone_unlock(zone_desc, ZONE_LOCK_SIGNATURE); database_service_zone_resignature_parms_free(parms); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return NULL; } zone_set_status(zone_desc, ZONE_STATUS_SIGNATURES_UPDATING); // do a bunch of signatures zdb_zone *zone = zone_get_loaded_zone(zone_desc); if(zone != NULL) { // should have a starting point, cylcing trough the nodes // that way there will be no increasingly long scans if(zdb_zone_is_maintained(zone)) { log_debug("zone sign: %{dnsname}: signatures update", zone_origin(zone_desc)); if(FAIL(return_code = zdb_zone_maintenance(zone))) { #if DEBUG log_info("zone sign: %{dnsname}: failed with %r and earliest signature expiration happens at %T", zone_origin(zone_desc), return_code, zone->progressive_signature_update.earliest_signature_expiration); #endif switch(return_code) { case ZDB_ERROR_ZONE_IS_NOT_DNSSEC: log_warn("zone sign: %{dnsname}: unable to sign, it has not been configured as DNSSEC (disabling maintenance)", zone_origin(zone_desc)); zdb_zone_set_maintained(zone, FALSE); break; case ZDB_ERROR_ZONE_IS_ALREADY_BEING_SIGNED: log_info("zone sign: %{dnsname}: could not refresh signatures, it is already being signed", zone_origin(zone_desc)); break; case ZDB_ERROR_ZONE_NO_ZSK_PRIVATE_KEY_FILE: log_warn("zone sign: %{dnsname}: unable to try to refresh signatures because there are no private keys available (pausing maintenance)", zone_origin(zone_desc)); //zdb_zone_set_maintained(zone, FALSE); zdb_zone_set_maintenance_paused(zone, TRUE); break; case DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM: log_warn("zone sign: %{dnsname}: unable to refresh signatures because there is a key with an unsupported algorithm (disabling maintenance)", zone_origin(zone_desc)); zdb_zone_set_maintained(zone, FALSE); break; case ZDB_JOURNAL_MUST_SAFEGUARD_CONTINUITY: log_info("zone sign: %{dnsname}: unable to sign, the journal is full (pausing maintenance)", zone_origin(zone_desc)); zdb_zone_set_maintenance_paused(zone, TRUE); zone_clear_status(zone_desc, ZONE_STATUS_SIGNATURES_UPDATING); zdb_zone_info_background_store_zone(zone_origin(zone_desc)); break; default: log_err("zone sign: %{dnsname}: signature failed: %r", zone_origin(zone_desc), return_code); break; } } else if(return_code == 0) // no signature have been done, let's scan the current status { log_debug("zone sign: %{dnsname}: earliest signature expiration at %T", zone_origin(zone_desc), zone->progressive_signature_update.earliest_signature_expiration); time_t soon = time(NULL) + 1; if(zone->progressive_signature_update.earliest_signature_expiration < soon) { // queue database_zone_update_signatures(zone->origin, zone_desc, zone); } else { // the signature should happen before of course ... // alarm queue database_zone_update_signatures_at(zone, zone->progressive_signature_update.earliest_signature_expiration); } } else // let's just restart this asap { log_debug("zone sign: %{dnsname}: quota reached, signature will resume as soon as possible", zone_origin(zone_desc)); database_zone_update_signatures_resume(zone->origin, zone_desc, zone); if((zdb_zone_get_status(zone) & ZDB_ZONE_STATUS_MODIFIED) != 0) { notify_slaves(zone_origin(zone_desc)); } } } else { log_info("zone sign: %{dnsname}: maintenance disabled", zone_origin(zone_desc)); database_zone_update_signatures_allow_queue(zone->origin, zone_desc, zone); } zdb_zone_release(zone); } else { log_err("zone sign: %{dnsname}: zone has not been loaded yet", zone_origin(zone_desc)); } // release zone_clear_status(zone_desc, ZONE_STATUS_PROCESSING|ZONE_STATUS_SIGNATURES_UPDATE|ZONE_STATUS_SIGNATURES_UPDATING|ZONE_STATUS_PROCESSING); log_debug("zone sign: %{dnsname}: signatures update end", zone_origin(zone_desc)); database_service_zone_resignature_parms_free(parms); zone_unlock(zone_desc, ZONE_LOCK_SIGNATURE); database_fire_zone_processed(zone_desc); zone_release(zone_desc); return NULL; } ya_result database_service_zone_dnssec_maintenance_lock_for(zone_desc_s *zone_desc, u8 zone_desc_owner) // one thread for all the program { yassert(zone_desc != NULL); const u8 *origin = zone_origin(zone_desc); log_debug1("database_service_zone_dnssec_maintenance(%{dnsname}@%p=%i)", origin, zone_desc, zone_desc->rc); if(!zone_maintains_dnssec(zone_desc)) { log_debug1("database_service_zone_dnssec_maintenance: %{dnsname} has signature maintenance disabled", origin); return FEATURE_NOT_SUPPORTED; } log_debug1("zone sign: %{dnsname}: locking zone for signature update", origin); if(zone_desc_owner == 0) { if(FAIL(zone_lock(zone_desc, ZONE_LOCK_SIGNATURE))) { log_err("zone sign: %{dnsname}: failed to lock zone settings", origin); return INVALID_STATE_ERROR; } } log_debug("zone sign: %{dnsname}", origin); if(zone_get_status(zone_desc) & (ZONE_STATUS_SIGNATURES_UPDATE|ZONE_STATUS_SIGNATURES_UPDATING)) { // already loading #if DEBUG zone_desc_log(MODULE_MSG_HANDLE, MSG_DEBUG1, zone_desc, "database_service_zone_resignature"); #endif log_debug("zone sign: %{dnsname}: already having its signatures updated", origin); ya_result ret; if(zone_desc->loaded_zone != NULL) { database_zone_update_signatures_at(zone_desc->loaded_zone, time(NULL) + 5); ret = SERVICE_ALREADY_RUNNING; } else { log_err("zone sign: %{dnsname}: zone not bound", origin); ret = ZDB_READER_ZONENOTLOADED; } if(zone_desc_owner == 0) { zone_unlock(zone_desc, ZONE_LOCK_SIGNATURE); // locked in this call } return ret; } log_debug("zone sign: %{dnsname}: zone signatures update begin", origin); zone_clear_status(zone_desc, ZONE_STATUS_STARTING_UP); zone_set_status(zone_desc, ZONE_STATUS_SIGNATURES_UPDATE); database_service_zone_resignature_parms_s *database_zone_resignature_parms = database_service_zone_resignature_parms_alloc(zone_desc); zone_acquire(zone_desc); database_service_zone_resignature_queue_thread(database_service_zone_dnssec_maintenance_thread, database_zone_resignature_parms, NULL, "database_zone_resignature_thread"); log_debug1("zone sign: %{dnsname}: unlocking zone for signature update", origin); if(zone_desc_owner == 0) { zone_unlock(zone_desc, ZONE_LOCK_SIGNATURE); // locked in this call } return SUCCESS; } ya_result database_service_zone_dnssec_maintenance(zone_desc_s *zone_desc) // one thread for all the program { ya_result ret = database_service_zone_dnssec_maintenance_lock_for(zone_desc, ZONE_LOCK_SIGNATURE); return ret; } ya_result database_service_zone_resignature_init() { mutex_lock(&database_service_zone_resignature_publish_dnskey_mtx); if(database_service_zone_resignature_publish_dnskey_tp == NULL) { if(!g_config->hidden_master) { database_service_zone_resignature_publish_dnskey_tp = thread_pool_init_ex(1, 1024, "keypub"); } else { database_service_zone_resignature_publish_dnskey_tp = thread_pool_init_ex(8, 0x100000, "keypub"); } } mutex_unlock(&database_service_zone_resignature_publish_dnskey_mtx); return (database_service_zone_resignature_publish_dnskey_tp != NULL)?SUCCESS:THREAD_CREATION_ERROR; } ya_result database_service_zone_resignature_finalize() { mutex_lock(&database_service_zone_resignature_publish_dnskey_mtx); if(database_service_zone_resignature_publish_dnskey_tp != NULL) { thread_pool_destroy(database_service_zone_resignature_publish_dnskey_tp); database_service_zone_resignature_publish_dnskey_tp = NULL; } mutex_unlock(&database_service_zone_resignature_publish_dnskey_mtx); return (database_service_zone_resignature_publish_dnskey_tp != NULL)?SUCCESS:ERROR; } #endif /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config-denial.c0000644000000000000000000000013214505005533021536 xustar000000000000000030 mtime=1695812443.496997284 30 atime=1695812445.783030024 30 ctime=1695812495.702744975 yadifa-2.6.5-11201/sbin/yadifad/config-denial.c0000664000374500037450000003006114505005533021500 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup ### * @brief */ #include #include #include #include #include #include #include "dnssec-policy.h" #include "zone_desc.h" #include "zone-signature-policy.h" #include "server_error.h" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES #define MODULE_MSG_HANDLE g_server_logger #define DENIALCF_TAG 0x46434c41494e4544 static value_name_table dnssec_enum[]= { {ZONE_DNSSEC_FL_NSEC3 , "nsec3" }, {0, NULL} }; static ptr_set denial_desc_set = PTR_SET_ASCIIZ_EMPTY; /*----------------------------------------------------------------------------*/ #pragma mark CONFIG // denial container #define CONFIG_TYPE denial_desc_s CONFIG_BEGIN(config_section_denial_desc) CONFIG_STRING( id, NULL ) CONFIG_ENUM( type, "nsec3", dnssec_enum ) CONFIG_U32( resalting, "0" ) /// @todo 20160520 gve -- does not work in version 2.2.0 CONFIG_STRING( salt, NULL ) CONFIG_STRING( algorithm, "sha1" ) CONFIG_U16( iterations, "1" ) CONFIG_U8( salt_length, "0" ) CONFIG_BOOL( optout, "0" ) CONFIG_END(config_section_denial_desc) #undef CONFIG_TYPE /*----------------------------------------------------------------------------*/ #pragma mark STATIC FUNCTIONS static ya_result config_section_denial_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_denial_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)context; if(key != NULL) { return INVALID_ARGUMENT_ERROR; } return SUCCESS; } /** * @fn static ya_result config_section_denial_init(struct config_section_descriptor_s *csd) * * @brief initializing of a section: * * @details * the initializing of section is a NOP. * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_denial_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } /** * @fn static ya_result config_section_denial_start(struct config_section_descriptor_s *csd) * * @brief * start of a section csd->base will be initialized * * @details * csd->base will be initialized with denial * you can not have a start of a 'section' in a 'section' --> ERROR * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_denial_start(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: denial: start"); #endif if(csd->base != NULL) { return INVALID_STATE_ERROR; } denial_desc_s *denial; MALLOC_OBJECT_OR_DIE(denial, denial_desc_s, DENIALCF_TAG); ZEROMEMORY(denial, sizeof(denial_desc_s)); csd->base = denial; config_error_s cfgerr; config_error_reset(&cfgerr); config_set_section_default(csd, &cfgerr); return SUCCESS; } /** * @fn static ya_result config_section_denial_stop(struct config_section_descriptor_s *csd) * * @brief * stop of a section csd->base set to NULL --> ready for the * next section * put the 'denial' in a binary tree with index denial->id * * @details * make sure that 'salt_length' is correct * 'denial' is put in a binary tree for easy access when they need to be translated in the correct structure for 'yadifad' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_denial_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: denial: stop"); #endif // NOP denial_desc_s *denial = (denial_desc_s *) csd->base; csd->base = NULL; if(denial->id == NULL) { ttylog_err("config: denial: id not set"); return CONFIG_SECTION_ERROR; } if(strcasecmp(denial->algorithm, "sha1") == 0) { denial->algorithm_val= 1; } else { u32 parsed_algorithm = 0; if(ISOK(parse_u32_check_range(denial->algorithm, &parsed_algorithm, 1, 255, 10))) { denial->algorithm_val = (u8)parsed_algorithm; } else { return CONFIG_SECTION_ERROR; } } // Now allows empty salt. /* size_t salt_length = (denial->salt != NULL) ? strlen(denial->salt) : 0; if((denial->salt_length > 0) == (salt_length > 0)) { return CONFIG_SECTION_ERROR; } */ ptr_node *node = ptr_set_insert(&denial_desc_set, denial->id); if(node->value == NULL) { node->value = denial; return SUCCESS; } else { ttylog_err("config: denial: %s: already defined", denial->id); return CONFIG_SECTION_ERROR; } } /** * @fn static ya_result config_section_denial_postprocess(struct config_section_descriptor_s *csd) * * @brief create denial structure to be used by 'yadifad' * * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_denial_postprocess(struct config_section_descriptor_s *csd) { (void)csd; ya_result salt_length; ptr_set_iterator iter; ptr_set_iterator_init(&denial_desc_set, &iter); u8 buffer[256]; // go thru binary tree and check all the 'denial' sections while(ptr_set_iterator_hasnext(&iter)) { ptr_node *denial_node = ptr_set_iterator_next_node(&iter); denial_desc_s *denial_desc = (denial_desc_s *)denial_node->value; // check if there's a salt present if(denial_desc->salt != NULL) { if (FAIL(salt_length = base16_decode(denial_desc->salt, (u32) strlen(denial_desc->salt), buffer))) { ttylog_err("config: denial: %s: could not decode salt", denial_desc->id); return salt_length; // is ERROR code instead } // buffer has the base16 decode 'salt' dnssec_policy_denial_create(denial_desc->id, denial_desc->algorithm_val, denial_desc->iterations, buffer, (u8)salt_length, denial_desc->resalting, denial_desc->optout); } else { // if no salt present 'salt_length' has the correct length of the salt to be made by the system dnssec_policy_denial_create(denial_desc->id, denial_desc->algorithm_val, denial_desc->iterations, NULL, denial_desc->salt_length, denial_desc->resalting, denial_desc->optout); } } return SUCCESS; } /** * @fn static void denial_free(denial_desc_s *denial) * * @brief free all items: id, salt * * @details * just free all items of section * * * @param[in,out] denial_desc_s *denial * * return -- */ static void denial_free(denial_desc_s *denial) { free(denial->id); free(denial->salt); free(denial); } /** * @fn static ya_result config_section_denial_finalize(struct config_section_descriptor_s *csd) * * @brief free denial_desc_s completely * * @details * empty 'dnssec_policy' denial parameter and everything else * and free csd and set back to 'NULL' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_denial_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { denial_desc_s *denial = (denial_desc_s*)csd->base; denial_free(denial); #if DEBUG csd->base = NULL; #endif } free(csd); } return SUCCESS; } /*----------------------------------------------------------------------------*/ #pragma mark VIRTUAL TABLE static const config_section_descriptor_vtbl_s config_section_denial_descriptor_vtbl = { "denial", config_section_denial_desc, // no table config_section_denial_set_wild, config_section_denial_print_wild, config_section_denial_init, config_section_denial_start, config_section_denial_stop, config_section_denial_postprocess, config_section_denial_finalize }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result config_register_denial(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_denial(const char *null_or_key_name, s32 priority) { //null_or_key_name = "zone"; (void)null_or_key_name; config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_denial_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // scan-build false positive: either it is freed, either it is stored in a global collection } yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config-dnssec-policy.c0000644000000000000000000000013214505005533023056 xustar000000000000000030 mtime=1695812443.537997871 30 atime=1695812445.784030039 30 ctime=1695812495.704745004 yadifa-2.6.5-11201/sbin/yadifad/config-dnssec-policy.c0000664000374500037450000003576714505005533023042 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup configuration * @brief */ #include #include #include #include "config-dnssec-policy.h" #include "dnssec-policy.h" #include "server_error.h" /*----------------------------------------------------------------------------*/ #pragma mark DEFINES #define DP_FLAGS_WEAKER_KEY 0x01 #define DP_FLAGS_STRONGER_KEY 0x02 #define DP_KEY_SUITE_SIZE 4 /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES #define MODULE_MSG_HANDLE g_server_logger #define POLICYCF_TAG 0x46435943494c4f50 static ptr_set dnssec_policy_desc_set = PTR_SET_ASCIIZ_EMPTY; /*----------------------------------------------------------------------------*/ #pragma mark CONFIG // dnssec-policy container #define CONFIG_TYPE dnssec_policy_desc_s CONFIG_BEGIN(config_section_dnssec_policy_desc) CONFIG_STRING( id, NULL ) CONFIG_STRING( description, NULL ) CONFIG_STRING( denial, "nsec" ) CONFIG_STRING_ARRAY( key_suite, NULL, DP_KEY_SUITE_SIZE ) CONFIG_U32_RANGE( ds_ttl, "3600", 0, MAX_S32 ) CONFIG_FLAG8( weaker_key_removal, "0", flags, DP_FLAGS_WEAKER_KEY ) CONFIG_FLAG8( stronger_key_removal, "0", flags, DP_FLAGS_STRONGER_KEY) CONFIG_U8( max_key, "2" ) // it's the number of key suites /* alias, aliased */ CONFIG_ALIAS( max_keys, max_key ) CONFIG_END(config_section_dnssec_policy_desc) #undef CONFIG_TYPE /*----------------------------------------------------------------------------*/ #pragma mark STATIC FUNCTIONS static ya_result config_section_dnssec_policy_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_dnssec_policy_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)context; if(key != NULL) { return INVALID_ARGUMENT_ERROR; } return SUCCESS; } /** * @fn static ya_result config_section_dnssec_policy_init(struct config_section_descriptor_s *csd) * * @brief initializing of a section: * * @details * the initializing of section is a NOP. * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_dnssec_policy_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } /** * @fn static ya_result config_section_dnssec_policy_start(struct config_section_descriptor_s *csd) * * @brief * start of a section csd->base will be initialized * * @details * csd->base will be initialized with a new ptr_vector for key-suites * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_dnssec_policy_start(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: dnssec-policy: start"); #endif if(csd->base != NULL) { return INVALID_STATE_ERROR; } dnssec_policy_desc_s *dnssec_policy; MALLOC_OBJECT_OR_DIE(dnssec_policy, dnssec_policy_desc_s, POLICYCF_TAG); ZEROMEMORY(dnssec_policy, sizeof(dnssec_policy_desc_s)); ptr_vector_init(&dnssec_policy->key_suite); csd->base = dnssec_policy; return SUCCESS; } /** * @fn static ya_result config_section_dnssec_policy_stop(struct config_section_descriptor_s *csd) * * @brief * stop of a section csd->base set to NULL --> ready for the * next section * * @details * global variable dnssec_policy_desc_set will have a new node (node->value = dnssec_policy) for a * new id (node->id) * 'dnssec-policy' is put in a binary tree for easy access when they need to be translated in the correct structure for 'yadifad' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_dnssec_policy_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: dnssec-policy: stop"); #endif // NOP dnssec_policy_desc_s *dnssec_policy = (dnssec_policy_desc_s *) csd->base; csd->base = NULL; if(dnssec_policy->id == NULL) { ttylog_err("config: dnssec-policy: id not set"); return CONFIG_SECTION_ERROR; } if(dnssec_policy->denial == NULL) { ttylog_err("config: dnssec-policy: %s: denial not set", dnssec_policy->id); return CONFIG_SECTION_ERROR; } if(strcmp(dnssec_policy->denial, "nsec") != 0) { dnssec_denial *denial = dnssec_policy_denial_acquire(dnssec_policy->denial); if(denial == NULL) { ttylog_err("config: dnssec-policy: denial '%s' is undefined", dnssec_policy->denial); return CONFIG_SECTION_ERROR; } dnssec_policy_denial_release(denial); } if(ptr_vector_size(&dnssec_policy->key_suite) < 1) { ttylog_err("config: dnssec-policy: %s: no key-suite has been set", dnssec_policy->id); return CONFIG_SECTION_ERROR; } if(ptr_vector_size(&dnssec_policy->key_suite) > dnssec_policy->max_key) { ttylog_err("config: dnssec-policy: %s: too many key-suite have been set", dnssec_policy->id); return CONFIG_SECTION_ERROR; } ptr_node *node = ptr_set_insert(&dnssec_policy_desc_set, dnssec_policy->id); if(node->value == NULL) { node->value = dnssec_policy; return SUCCESS; } else { ttylog_err("config: dnssec-policy: %s: already defined", dnssec_policy->id); return CONFIG_SECTION_ERROR; } } /** * @fn static ya_result config_section_dnssec_policy_postprocess(struct config_section_descriptor_s *csd) * * @brief create dnssec-policies structure to be used by 'yadifad' * * @details * check for a dnssec-policy node that all 'key_suites' are present and 'denial' is present * if they are present add them to the global struct * * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_dnssec_policy_postprocess(struct config_section_descriptor_s *csd) { (void)csd; #if CONFIG_SETTINGS_DEBUG formatln("config: section: dnssec-policy: postprocess"); #endif ptr_set_iterator iter; ptr_set_iterator_init(&dnssec_policy_desc_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *dnssec_policy_node = ptr_set_iterator_next_node(&iter); dnssec_policy_desc_s *dnssec_policy_desc = (dnssec_policy_desc_s *)dnssec_policy_node->value; if((ptr_vector_size(&dnssec_policy_desc->key_suite) < 1) || (ptr_vector_size(&dnssec_policy_desc->key_suite) > 2)) { log_warn("config: dnssec-policy: %s: the dnssec-policy should have one (ZSK) or two (KSK and ZSK) key suites", dnssec_policy_desc->id); } // get the section from configuration dnssec_denial *dd = dnssec_policy_denial_acquire(dnssec_policy_desc->denial); // note that dd is allowed to be NULL bool has_zsk = FALSE; // get all sections for configuration // and put it in 'key_suites' ptr_vector key_suites = PTR_VECTOR_EMPTY; for(int i = 0; i <= ptr_vector_last_index(&dnssec_policy_desc->key_suite); ++i) { // get 'key-suite' name and check if it exists, if not return 'ERROR' const char *key_suite_name = (char*)ptr_vector_get(&dnssec_policy_desc->key_suite, i); dnssec_policy_key_suite *dpks = dnssec_policy_key_suite_acquire_from_name(key_suite_name); if(dpks != NULL) { if((dpks->key->flags & DNSKEY_FLAGS_KSK) == DNSKEY_FLAGS_ZSK) { has_zsk = TRUE; } ptr_vector_append(&key_suites, dpks); } else { ttylog_err("config: dnssec-policy: %s: key suite '%s' not defined", dnssec_policy_desc->id, key_suite_name); return POLICY_KEY_SUITE_UNDEFINED; } } if(!has_zsk) { ttylog_err("config: dnssec-policy: %s: at least one key suite with a ZSK is required", dnssec_policy_desc->id); return CONFIG_SECTION_ERROR; } // set the dnssec-policy structure for 'dnssec_policy_desc->id' with 'dd' and 'key_suites' // the value returned by dnssec_policy_create is also added to key_suites dnssec_policy_create(dnssec_policy_desc->id, dd, &key_suites); // if done remove everything and for ' with 'dnssec_policy_desc->id' for(int i = 0; i <= ptr_vector_last_index(&key_suites); ++i) { dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)ptr_vector_get(&key_suites, i); dnssec_policy_key_suite_release(dpks); } if(dd != NULL) { dnssec_policy_denial_release(dd); } ptr_vector_destroy(&key_suites); } return SUCCESS; } /** * @fn static void dnssec_policy_free(dnssec_policy_desc_s *dnssec_policy) * * @brief free dnssec_policy_desc_s completely * * @details * empty 'dnssec_policy' key_suite parameter and everything else * * @param[in,out] dnssec_policy_desc_s *dnssec_policy * * return -- */ static void dnssec_policy_free(dnssec_policy_desc_s *dnssec_policy) { free(dnssec_policy->id); free(dnssec_policy->description); free(dnssec_policy->denial); ptr_vector_callback_and_clear(&dnssec_policy->key_suite, free); free(dnssec_policy); } /** * @fn static ya_result config_section_dnssec_policy_finalize(struct config_section_descriptor_s *csd) * * @brief free dnssec_policy_desc_s completely * * @details * empty 'dnssec_policy' * and free csd and set back to 'NULL' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_dnssec_policy_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { dnssec_policy_desc_s *dnssec_policy = (dnssec_policy_desc_s*)csd->base; dnssec_policy_free(dnssec_policy); #if DEBUG csd->base = NULL; #endif } free(csd); } return SUCCESS; } /*----------------------------------------------------------------------------*/ #pragma mark VIRTUAL TABLE static const config_section_descriptor_vtbl_s config_section_dnssec_policy_descriptor_vtbl = { "dnssec-policy", config_section_dnssec_policy_desc, // no table config_section_dnssec_policy_set_wild, config_section_dnssec_policy_print_wild, config_section_dnssec_policy_init, config_section_dnssec_policy_start, config_section_dnssec_policy_stop, config_section_dnssec_policy_postprocess, config_section_dnssec_policy_finalize }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result config_register_dnssec_policy(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * , , and are needed for * get all of them before registering all sections * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_dnssec_policy(const char *null_or_key_name, s32 priority) { (void)null_or_key_name; // get all sections , , and config_register_key_roll(NULL, priority); priority++; config_register_denial(NULL, priority); priority++; config_register_key_template(NULL, priority); priority++; config_register_key_suite(NULL, priority); priority++; // get the correct virtual table and register section from // the configuration config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_dnssec_policy_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // scan-build false positive: either it is freed, either it is stored in a global collection } yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config-key-roll.c0000644000000000000000000000013114505005533022037 xustar000000000000000030 mtime=1695812443.477997011 29 atime=1695812445.78203001 30 ctime=1695812495.706745032 yadifa-2.6.5-11201/sbin/yadifad/config-key-roll.c0000664000374500037450000003525214505005533022011 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup ### * @brief */ #include #include #include "dnssec-policy.h" #include "config-key-roll-parser.h" #include "server_error.h" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES #define KEYROLCF_TAG 0x46434c4f5259454b static ptr_set key_roll_desc_set = PTR_SET_ASCIIZ_EMPTY; /*----------------------------------------------------------------------------*/ #pragma mark CONFIG // key-roll container #define CONFIG_TYPE key_roll_desc_s CONFIG_BEGIN(config_section_key_roll_desc) CONFIG_STRING(id, NULL) CONFIG_STRING(generate, NULL) CONFIG_STRING(publish, NULL) CONFIG_STRING(activate, NULL) CONFIG_STRING(inactive, NULL) CONFIG_STRING(remove, NULL) #if HAS_DS_PUBLICATION_SUPPORT CONFIG_STRING(ds_publish, NULL) CONFIG_STRING(ds_remove, NULL) #endif // if HAS_DS_PUBLICATION_SUPPORT> CONFIG_ALIAS(delete, remove) CONFIG_ALIAS(create, generate) CONFIG_ALIAS(created, generate) CONFIG_END(config_section_key_roll_desc) #undef CONFIG_TYPE #pragma mark STATIC FUNCTIONS static ya_result config_section_key_roll_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_key_roll_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)context; if(key != NULL) { return INVALID_ARGUMENT_ERROR; } return SUCCESS; } /** * @fn static ya_result config_section_key_roll_init(struct config_section_descriptor_s *csd) * * @brief initializing of a section: * * @details * the initializing of section is a NOP. * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_roll_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } /** * @fn static ya_result config_section_key_roll_start(struct config_section_descriptor_s *csd) * * @brief * start of a section csd->base will be initialized * * @details * csd->base will be initialized with key_roll * you can not have a start of a 'section' in a 'section' --> ERROR * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_roll_start(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_roll: start"); #endif if(csd->base != NULL) { return INVALID_STATE_ERROR; } key_roll_desc_s *key_roll; MALLOC_OBJECT_OR_DIE(key_roll, key_roll_desc_s, KEYROLCF_TAG); ZEROMEMORY(key_roll, sizeof(key_roll_desc_s)); csd->base = key_roll; return SUCCESS; } //#define KEY_ROLL_TOKEN_DELIMITER "" /** * @fn static ya_result config_section_key_roll_stop(struct config_section_descriptor_s *csd) * * @brief * stop of a section csd->base set to NULL --> ready for * parsing all items: generate, publish, activate, inactive, remove, ... * put the 'key-roll' in a binary tree with index key_roll->id * * @details * check if all items are there and of the correct types, otherwise give back an error * 'key-roll' is put in a binary tree for easy access when they need to be translated in the correct structure for 'yadifad' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_roll_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_roll: stop"); #endif key_roll_desc_s *key_roll = (key_roll_desc_s *) csd->base; if(key_roll->id == NULL) { ttylog_err("config: key-roll: id not set"); return CONFIG_SECTION_ERROR; } ya_result return_code; key_roll_line_s krl_generate; key_roll_line_s krl_publish; key_roll_line_s krl_activate; key_roll_line_s krl_inactive; key_roll_line_s krl_remove; key_roll_line_s krl_ds_publish; key_roll_line_s krl_ds_remove; if(FAIL(return_code = config_key_roll_parser_line(key_roll->generate, &krl_generate, KR_ACTION_GENERATE))) { ttylog_err("config: key-roll: %s: error in 'generate' (%r)", key_roll->id, return_code); return PARSE_INVALID_ARGUMENT; } if(FAIL(return_code = config_key_roll_parser_line(key_roll->publish, &krl_publish, KR_ACTION_GENERATE))) { ttylog_err("config: key-roll: %s: error in 'publish' (%r)", key_roll->id, return_code); return PARSE_INVALID_ARGUMENT; } if(FAIL(return_code = config_key_roll_parser_line(key_roll->activate, &krl_activate, KR_ACTION_PUBLISH))) { ttylog_err("config: key-roll: %s: error in 'activate' (%r)", key_roll->id, return_code); return PARSE_INVALID_ARGUMENT; } if(FAIL(return_code = config_key_roll_parser_line(key_roll->inactive, &krl_inactive, KR_ACTION_ACTIVATE))) { ttylog_err("config: key-roll: %s: error in 'inactive' (%r)", key_roll->id, return_code); return PARSE_INVALID_ARGUMENT; } if(FAIL(return_code = config_key_roll_parser_line(key_roll->remove, &krl_remove, KR_ACTION_INACTIVE))) { ttylog_err("config: key-roll: %s: error in 'remove' (%r)", key_roll->id, return_code); return PARSE_INVALID_ARGUMENT; } #if HAS_DS_PUBLICATION_SUPPORT if(FAIL(return_code = config_key_roll_parser_line(key_roll->ds_publish, &krl_ds_publish, KR_ACTION_DS_PUBLISH))) { if(return_code != PARSE_EMPTY_ARGUMENT) { return return_code; } else { /// @todo 20160610 gve -- still needs to write code for this } } if(FAIL(return_code = config_key_roll_parser_line(key_roll->ds_remove, &krl_ds_remove, KR_ACTION_DS_REMOVE))) { if(return_code != PARSE_EMPTY_ARGUMENT) { return return_code; } else { /// @todo 20160610 gve -- still needs to write code for this } return return_code; } #endif // if HAS_DS_PUBLICATION_SUPPORT if(krl_generate.type == krl_publish.type && krl_generate.type == krl_activate.type && krl_generate.type == krl_inactive.type && #if HAS_DS_PUBLICATION_SUPPORT /// @todo 20160603 gve -- still needs to test if they exist krl_generate.type == krl_remove.type && krl_generate.type == krl_ds_publish.type && krl_generate.type == krl_ds_remove.type) #else krl_generate.type == krl_remove.type) #endif // if HAS_DS_PUBLICATION_SUPPORT { // KER_ROLL_LINE_CRON_TYPE if(krl_generate.type) { return_code = zone_policy_roll_create_from_rules(key_roll->id, &krl_generate.policy.cron, &krl_publish.policy.cron, &krl_activate.policy.cron, &krl_inactive.policy.cron, &krl_remove.policy.cron, &krl_ds_publish.policy.cron, &krl_ds_remove.policy.cron); } // KER_ROLL_LINE_NON_CRON_TYPE else { return_code = zone_policy_roll_create_from_relatives(key_roll->id, &krl_generate.policy.relative, (u8) krl_generate.relative_to, &krl_publish.policy.relative, (u8) krl_publish.relative_to, &krl_activate.policy.relative, (u8) krl_activate.relative_to, &krl_inactive.policy.relative, (u8) krl_inactive.relative_to, &krl_remove.policy.relative, (u8) krl_remove.relative_to #if HAS_DS_PUBLICATION_SUPPORT , &krl_ds_publish.policy.relative, (u8) krl_ds_publish.relative_to, &krl_ds_remove.policy.relative, (u8) krl_ds_remove.relative_to #endif ); } if(FAIL(return_code)) { ttylog_err("config: key-roll: '%s' has invalid settings", key_roll->id); return CONFIG_SECTION_ERROR; } } else { ttylog_err("config: key-roll: %s: different key-roll types used in section", key_roll->id); return CONFIG_SECTION_ERROR; } csd->base = NULL; ptr_node *node = ptr_set_insert(&key_roll_desc_set, key_roll->id); if(node->value == NULL) { node->value = key_roll; return SUCCESS; } else { ttylog_err("config: key-roll: %s: already registered", key_roll->id); return CONFIG_SECTION_ERROR; } } /** * @fn static ya_result config_section_key_roll_postprocess(struct config_section_descriptor_s *csd) * * @brief no postprocessing needed * * @details * no postprocessing * * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_roll_postprocess(struct config_section_descriptor_s *csd) { (void)csd; return SUCCESS; } /** * @fn static void key_roll_free(key_roll_desc_s *key_roll) * * @brief free all items: generate, publish, ... * * @details * just free all items of section * * * @param[in,out] key_roll_desc_s *key_roll * * return -- */ static void key_roll_free(key_roll_desc_s *key_roll) { free(key_roll->id); free(key_roll->generate); free(key_roll->publish); free(key_roll->activate); free(key_roll->inactive); free(key_roll->remove); free(key_roll->ds_publish); free(key_roll->ds_remove); free(key_roll); } /** * @fn static ya_result config_section_key_roll_finalize(struct config_section_descriptor_s *csd) * * @brief free key_roll_desc_s completely * * @details * empty 'dnssec_policy' key_roll parameter and everything else * and free csd and set back to 'NULL' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_roll_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { key_roll_desc_s *key_roll = (key_roll_desc_s*)csd->base; key_roll_free(key_roll); #if DEBUG csd->base = NULL; #endif } free(csd); } return SUCCESS; } /*----------------------------------------------------------------------------*/ #pragma mark VIRTUAL TABLE static const config_section_descriptor_vtbl_s config_section_key_roll_descriptor_vtbl = { "key-roll", config_section_key_roll_desc, // no table config_section_key_roll_set_wild, config_section_key_roll_print_wild, config_section_key_roll_init, config_section_key_roll_start, config_section_key_roll_stop, config_section_key_roll_postprocess, config_section_key_roll_finalize }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result config_register_key_roll(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_key_roll(const char *null_or_key_name, s32 priority) { //null_or_key_name = "zone"; (void)null_or_key_name; config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_key_roll_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // scan-build false positive: either it is freed, either it is stored in a global collection } yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config-key-suite.c0000644000000000000000000000013114505005533022220 xustar000000000000000030 mtime=1695812443.470996912 29 atime=1695812445.78203001 30 ctime=1695812495.708745061 yadifa-2.6.5-11201/sbin/yadifad/config-key-suite.c0000664000374500037450000002510514505005533022166 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup ### * @brief */ #include #include #include #include "dnssec-policy.h" #include "zone-signature-policy.h" #include "server_error.h" #include "confs.h" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES #define MODULE_MSG_HANDLE g_server_logger #define KEYSUICF_TAG 0x464349555359454b static ptr_set key_suite_desc_set = PTR_SET_ASCIIZ_EMPTY; /*----------------------------------------------------------------------------*/ #pragma mark CONFIG // key-suite container #define CONFIG_TYPE key_suite_desc_s CONFIG_BEGIN(config_section_key_suite_desc) CONFIG_STRING(id, NULL) CONFIG_STRING(key_template, NULL) CONFIG_STRING(key_roll, NULL) CONFIG_END(config_section_key_suite_desc) #undef CONFIG_TYPE #pragma mark STATIC FUNCTIONS static ya_result config_section_key_suite_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_key_suite_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)context; if(key != NULL) { return INVALID_ARGUMENT_ERROR; } return SUCCESS; } /** * @fn static ya_result config_section_key_suite_init(struct config_section_descriptor_s *csd) * * @brief initializing of a section: * * @details * the initializing of section is a NOP. * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_suite_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } /** * @fn static ya_result config_section_key_suite_start(struct config_section_descriptor_s *csd) * * @brief * start of a section csd->base will be initialized * * @details * csd->base will be initialized with key_suite * you can not have a start of a 'section' in a 'section' --> ERROR * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_suite_start(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_suite: start"); #endif if(csd->base != NULL) { return INVALID_STATE_ERROR; } key_suite_desc_s *key_suite; MALLOC_OBJECT_OR_DIE(key_suite, key_suite_desc_s, KEYSUICF_TAG); ZEROMEMORY(key_suite, sizeof(key_suite_desc_s)); csd->base = key_suite; return SUCCESS; } /** * @fn static ya_result config_section_key_suite_stop(struct config_section_descriptor_s *csd) * * @brief * stop of a section csd->base set to NULL --> * put the 'key-suite' in a binary tree with index key_suite->id * * @details * 'key-suite' is put in a binary tree for easy access when they need to be translated in the correct structure for 'yadifad' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_suite_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_suite: stop"); #endif // NOP key_suite_desc_s *key_suite = (key_suite_desc_s *) csd->base; csd->base = NULL; if(key_suite->id == NULL) { ttylog_err("config: key-suite: id not set"); return CONFIG_SECTION_ERROR; } ptr_node *node = ptr_set_insert(&key_suite_desc_set, key_suite->id); if(node->value == NULL) { node->value = key_suite; return SUCCESS; } else { ttylog_err("config: key-suite: %s: already defined", key_suite->id); return CONFIG_SECTION_ERROR; } } /** * @fn static ya_result config_section_key_suite_postprocess(struct config_section_descriptor_s *csd) * * @brief iterate thru binary tree and create the needed 'key-suite' structures for 'yadifad' * * @details * 'key-suite' needs a 'key-roll' and a 'key-template' section * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_suite_postprocess(struct config_section_descriptor_s *csd) { (void)csd; ya_result ret = SUCCESS; if(g_config->check_policies) { time_t now = time(NULL); ret = dnssec_policy_roll_test_all(now, 315576000 /* 10 years */, TRUE, FALSE); flushout(); if(FAIL(ret)) { return ret; } } ptr_set_iterator iter; ptr_set_iterator_init(&key_suite_desc_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *key_suite_node = ptr_set_iterator_next_node(&iter); key_suite_desc_s *key_suite_desc = (key_suite_desc_s *)key_suite_node->value; dnssec_policy_key *dpk = dnssec_policy_key_acquire_from_name(key_suite_desc->key_template); if(dpk != NULL) { dnssec_policy_roll *dpr = dnssec_policy_roll_acquire_from_name(key_suite_desc->key_roll); if(dpr != NULL) { /*dnssec_policy_key_suite *dpks =*/ dnssec_policy_key_suite_create(key_suite_desc->id, dpk, dpr); dnssec_policy_roll_release(dpr); } else { ttylog_err("config: key-suite: %s: key-template %s not defined", key_suite_desc->id, key_suite_desc->key_roll); } dnssec_policy_key_release(dpk); } else { ttylog_err("config: key-suite: %s: key-template %s not defined", key_suite_desc->id, key_suite_desc->key_template); } } return ret; } /** * @fn static void key_suite_free(key_suite_desc_s *key_suite) * * @brief free * * @details * just free all items of section * * * @param[in] key_suite_desc_s *key_suite * * return -- */ static void key_suite_free(key_suite_desc_s *key_suite) { free(key_suite->id); free(key_suite->key_template); free(key_suite->key_roll); free(key_suite); } /** * @fn static ya_result config_section_key_suite_finalize(struct config_section_descriptor_s *csd) * * @brief free key_template_desc_s completely * * @details * empty 'dnssec_policy' key_suite parameter and everything else * and free csd and set back to 'NULL' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_suite_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { key_suite_desc_s *key_suite = (key_suite_desc_s*)csd->base; key_suite_free(key_suite); #if DEBUG csd->base = NULL; #endif } free(csd); } return SUCCESS; } /*----------------------------------------------------------------------------*/ #pragma mark VIRTUAL TABLE static const config_section_descriptor_vtbl_s config_section_key_suite_descriptor_vtbl = { "key-suite", config_section_key_suite_desc, // no table config_section_key_suite_set_wild, config_section_key_suite_print_wild, config_section_key_suite_init, config_section_key_suite_start, config_section_key_suite_stop, config_section_key_suite_postprocess, config_section_key_suite_finalize }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result config_register_key_suite(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_key_suite(const char *null_or_key_name, s32 priority) { //null_or_key_name = "zone"; (void)null_or_key_name; config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_key_suite_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // scan-build false positive: either it is freed, either it is stored in a global collection } yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config-key-template.c0000644000000000000000000000013014505005533022701 xustar000000000000000030 mtime=1695812443.483997097 29 atime=1695812445.78203001 29 ctime=1695812495.71074509 yadifa-2.6.5-11201/sbin/yadifad/config-key-template.c0000664000374500037450000003742114505005533022654 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup ### * @brief */ #include #include #include #include "dnssec-policy.h" #include "server_error.h" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES #define KEYTEMCF_TAG 0x46434d455459454b static ptr_set key_template_desc_set = PTR_SET_ASCIIZ_EMPTY; static value_name_table dnssec_algorithm_enum[] = { {DNSKEY_ALGORITHM_RSAMD5 , DNSKEY_ALGORITHM_RSAMD5_NAME }, {DNSKEY_ALGORITHM_RSAMD5 , "1" }, {DNSKEY_ALGORITHM_DIFFIE_HELLMAN , DNSKEY_ALGORITHM_DIFFIE_HELLMAN_NAME }, {DNSKEY_ALGORITHM_DIFFIE_HELLMAN , "2" }, {DNSKEY_ALGORITHM_DSASHA1 , DNSKEY_ALGORITHM_DSASHA1_NAME }, {DNSKEY_ALGORITHM_DSASHA1 , "3" }, {DNSKEY_ALGORITHM_RSASHA1 , DNSKEY_ALGORITHM_RSASHA1_NAME }, {DNSKEY_ALGORITHM_RSASHA1 , "5" }, {DNSKEY_ALGORITHM_DSASHA1_NSEC3 , DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME }, {DNSKEY_ALGORITHM_DSASHA1_NSEC3 , DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME2 }, {DNSKEY_ALGORITHM_DSASHA1_NSEC3 , "6" }, {DNSKEY_ALGORITHM_RSASHA1_NSEC3 , DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME }, {DNSKEY_ALGORITHM_RSASHA1_NSEC3 , DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME2 }, {DNSKEY_ALGORITHM_RSASHA1_NSEC3 , "7" }, {DNSKEY_ALGORITHM_RSASHA256_NSEC3, DNSKEY_ALGORITHM_RSASHA256_NSEC3_NAME}, {DNSKEY_ALGORITHM_RSASHA256_NSEC3, "8" }, {DNSKEY_ALGORITHM_RSASHA512_NSEC3, DNSKEY_ALGORITHM_RSASHA512_NSEC3_NAME}, {DNSKEY_ALGORITHM_RSASHA512_NSEC3, "10" }, {DNSKEY_ALGORITHM_GOST , DNSKEY_ALGORITHM_GOST_NAME }, {DNSKEY_ALGORITHM_GOST , "12" }, {DNSKEY_ALGORITHM_ECDSAP256SHA256, DNSKEY_ALGORITHM_ECDSAP256SHA256_NAME}, {DNSKEY_ALGORITHM_ECDSAP256SHA256, "13" }, {DNSKEY_ALGORITHM_ECDSAP384SHA384, DNSKEY_ALGORITHM_ECDSAP384SHA384_NAME}, {DNSKEY_ALGORITHM_ECDSAP384SHA384, "14" }, {DNSKEY_ALGORITHM_ED25519 , DNSKEY_ALGORITHM_ED25519_NAME }, {DNSKEY_ALGORITHM_ED25519 , "15" }, {DNSKEY_ALGORITHM_ED448 , DNSKEY_ALGORITHM_ED448_NAME }, {DNSKEY_ALGORITHM_ED448 , "16" }, #ifdef DNSKEY_ALGORITHM_DUMMY {DNSKEY_ALGORITHM_DUMMY , DNSKEY_ALGORITHM_DUMMY_NAME }, {DNSKEY_ALGORITHM_DUMMY , "254" }, #endif {0, NULL} }; #pragma mark CONFIG // key-template container #define CONFIG_TYPE key_template_desc_s CONFIG_BEGIN(config_section_key_template_desc) CONFIG_STRING( id, NULL ) CONFIG_BOOL( ksk, "0" ) CONFIG_ENUM( algorithm, DNSKEY_ALGORITHM_RSASHA256_NSEC3_NAME, dnssec_algorithm_enum) CONFIG_U16( size, "0" ) CONFIG_STRING( engine, NULL ) CONFIG_END(config_section_key_template_desc) #undef CONFIG_TYPE #pragma mark STATIC FUNCTIONS static ya_result config_section_key_template_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_key_template_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)context; if(key != NULL) { return INVALID_ARGUMENT_ERROR; } return SUCCESS; } /** * @fn static ya_result config_section_key_template_init(struct config_section_descriptor_s *csd) * * @brief initializing of a section: * * @details * the initializing of section is a NOP. * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_template_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } /** * @fn static ya_result config_section_key_template_start(struct config_section_descriptor_s *csd) * * @brief * start of a section csd->base will be initialized * * @details * csd->base will be initialized with key_template * you can not have a start of a 'section' in a 'section' --> ERROR * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_template_start(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_template: start"); #endif if(csd->base != NULL) { return INVALID_STATE_ERROR; } key_template_desc_s *key_template; MALLOC_OBJECT_OR_DIE(key_template, key_template_desc_s, KEYTEMCF_TAG); ZEROMEMORY(key_template, sizeof(key_template_desc_s)); csd->base = key_template; return SUCCESS; } /** * @fn static ya_result config_section_key_template_stop(struct config_section_descriptor_s *csd) * * @brief * stop of a section csd->base set to NULL * * put the 'key-template' in a binary tree with index key_template->id * * @details * 'key-template' is put in a binary tree for easy access when they need to be translated in the correct structure for 'yadifad' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_template_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_template: stop"); #endif // NOP key_template_desc_s *key_template = (key_template_desc_s *) csd->base; csd->base = NULL; // 2. set 'algorithm' if(key_template->id == NULL) { ttylog_err("config: key-template: id not set"); return CONFIG_SECTION_ERROR; } switch(key_template->algorithm) { case DNSKEY_ALGORITHM_RSAMD5: case DNSKEY_ALGORITHM_DIFFIE_HELLMAN: case DNSKEY_ALGORITHM_GOST: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; case DNSKEY_ALGORITHM_DSASHA1: case DNSKEY_ALGORITHM_DSASHA1_NSEC3: if(key_template->size == 0) { key_template->size = 1024; } if(key_template->size != 1024) { ttylog_err("dnssec-policy: key_template: %s: unsupported key size: %i. Only 256 bits is supported for this algorithm.", key_template->id, key_template->size); return PARSE_INVALID_ARGUMENT; } break; case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: if(key_template->ksk == 1) { if(key_template->size == 0) { key_template->size = 2048; } } else { if(key_template->size == 0) { key_template->size = 1024; } } /// @note 20160624 gve -- check if mod 256 == 0 break; case DNSKEY_ALGORITHM_ECDSAP256SHA256: if(key_template->size == 0) { key_template->size = 256; } if(key_template->size != 256) { ttylog_err("dnssec-policy: key_template: %s: unsupported key size: %i. Only 256 bits is supported for this algorithm.", key_template->id, key_template->size); return PARSE_INVALID_ARGUMENT; } break; case DNSKEY_ALGORITHM_ECDSAP384SHA384: if(key_template->size == 0) { key_template->size = 384; } if(key_template->size != 384) { ttylog_err("dnssec-policy: key_template: %s: unsupported key size: %i. Only 384 bits is supported for this algorithm.", key_template->id, key_template->size); return PARSE_INVALID_ARGUMENT; } break; case DNSKEY_ALGORITHM_ED25519: if(key_template->size == 0) { key_template->size = 256; } if(key_template->size != 256) { ttylog_err("dnssec-policy: key_template: %s: unsupported key size: %i. Only 256 bits is supported for this algorithm.", key_template->id, key_template->size); return PARSE_INVALID_ARGUMENT; } break; case DNSKEY_ALGORITHM_ED448: if(key_template->size == 0) { key_template->size = 456; } if(key_template->size != 456) { ttylog_err("dnssec-policy: key_template: %s: unsupported key size: %i. Only 384 bits is supported for this algorithm.", key_template->id, key_template->size); return PARSE_INVALID_ARGUMENT; } break; default: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } ptr_node *node = ptr_set_insert(&key_template_desc_set, key_template->id); if(node->value == NULL) { node->value = key_template; return SUCCESS; } else { ttylog_err("config: key-template: %s: already defined", key_template->id); return CONFIG_SECTION_ERROR; } } /** * @fn static ya_result config_section_key_template_postprocess(struct config_section_descriptor_s *csd) * * @brief iterate thru binary tree and create the needed 'key-template' structures for 'yadifad' * * @details * no 'engine' implementend * * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_template_postprocess(struct config_section_descriptor_s *csd) { (void)csd; ptr_set_iterator iter; ptr_set_iterator_init(&key_template_desc_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *key_template_node = ptr_set_iterator_next_node(&iter); key_template_desc_s *key_template_desc = (key_template_desc_s *)key_template_node->value; /*dnssec_policy_key *dpk =*/ dnssec_policy_key_create(key_template_desc->id, key_template_desc->algorithm, key_template_desc->size, key_template_desc->ksk, NULL); // no engine in YADIFA 2.2.0 } return SUCCESS; } /** * @fn static void key_template_free(key_template_desc_s *key_template) * * @brief free * * @details * just free all items of section * * * @param[in] key_template_desc_s *key_template * * return -- */ static void key_template_free(key_template_desc_s *key_template) { free(key_template->id); free(key_template->engine); free(key_template); } /** * @fn static ya_result config_section_key_template_finalize(struct config_section_descriptor_s *csd) * * @brief free key_template_desc_s completely * * @details * empty 'dnssec_policy' key_template parameter and everything else * and free csd and set back to 'NULL' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_template_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { key_template_desc_s *key_template = (key_template_desc_s*)csd->base; key_template_free(key_template); #if DEBUG csd->base = NULL; #endif } free(csd); } return SUCCESS; } /*----------------------------------------------------------------------------*/ #pragma mark VIRTUAL TABLE static const config_section_descriptor_vtbl_s config_section_key_template_descriptor_vtbl = { "key-template", config_section_key_template_desc, // no table config_section_key_template_set_wild, config_section_key_template_print_wild, config_section_key_template_init, config_section_key_template_start, config_section_key_template_stop, config_section_key_template_postprocess, config_section_key_template_finalize }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result config_register_key_template(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_key_template(const char *null_or_key_name, s32 priority) { //null_or_key_name = "zone"; (void)null_or_key_name; config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_key_template_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // scan-build false positive: either it is freed, either it is stored in a global collection } yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/config-key-roll-parser.c0000644000000000000000000000013214505005533023332 xustar000000000000000030 mtime=1695812443.547998014 30 atime=1695812445.785030053 30 ctime=1695812495.712745118 yadifa-2.6.5-11201/sbin/yadifad/config-key-roll-parser.c0000664000374500037450000003411314505005533023276 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup configuration * @brief */ #include #include #include "config-key-roll-parser.h" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES const char *week[7] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat" }; const char *month[12] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; const char *key_roll_actions[7] = { KR_ACTION_GENERATE_NAME, KR_ACTION_PUBLISH_NAME, KR_ACTION_ACTIVATE_NAME, KR_ACTION_INACTIVE_NAME, KR_ACTION_REMOVE_NAME, KR_ACTION_DS_PUBLISH_NAME, KR_ACTION_DS_REMOVE_NAME, }; /// @todo 20160601 gve -- probably this must be changed with accurate values (order!!!) const u8 key_roll_actions_relative[7] = { KR_ACTION_GENERATE, KR_ACTION_PUBLISH, KR_ACTION_ACTIVATE, KR_ACTION_INACTIVE, KR_ACTION_REMOVE, KR_ACTION_DS_PUBLISH, KR_ACTION_DS_REMOVE, }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result key_roll_item_validate(s32 *dst, const char *src, u32 min, u32 max, const char *array[]) * * @brief check if 'src' item exists in 'array' and put the result in 'dst' * * @details * * @param[in] const char *src * @param[out] s32 *dst * * @retval 0 or -1 * * return ya_result */ ya_result key_roll_item_validate(s32 *dst, const char *src, u32 min, u32 max, const char *array[]) { if(array != NULL) { if(max < min) { u32 tmp = max; max = min; min = tmp; } for(u32 i = 0; i <= max - min; i++) { if(strcasecmp(src, array[i]) == 0) { *dst = i + min; return 0; } } } return -1; } /** * @fn ya_result key_roll_item_parser(char *dest, size_t dest_size, const char **from, const char *delim) * * @brief parse 'from' which is a word with maybe a 'delim'eter * * @details * 'from' can have several values which if found will be given back in 'dest' and returned with '0' * the parser will stop if '\0' has been found, otherwise after finding a value 'dest' * return with '1' * * @param[in] const char *src * @param[out] s32 *dst * * @retval 0 or 1 * * return ya_result */ ya_result key_roll_item_parser(char *dest, size_t dest_size, const char **from, const char *delim) { const char *to = *from; for(;;) { char c = *to; if(c == '\0') { size_t len = to - *from; if(len > dest_size) { return PARSE_BUFFER_TOO_SMALL_ERROR; } memcpy(dest, *from, len); dest[len] = '\0'; return 0; } // for every delimiter, test if c if such a delimiter // if it is, then for(const char *d = delim; *d != 0; d++) { if(*d == c) { // end of word size_t len = to - *from; if(len > dest_size) { return PARSE_BUFFER_TOO_SMALL_ERROR; } memcpy(dest, *from, len); dest[len] = '\0'; // still need to go further *from = ++to; return 1; } } ++to; } } /** * @fn ya_result key_roll_item_value_check(s32 *dst, char *src, u32 min, u32 max, const char *array[]) * * @brief check is 'src' is in the correct range (min -- max) and that the 'value' is known by the 'array' * * @details * check if known in 'array' is done by 'key_roll_item_validate' * * @param[in] const char *src * @param[out] s32 *dst * * @retval 0 or return_code * * return ya_result */ ya_result key_roll_item_value_check(s32 *dst, char *src, u32 min, u32 max, const char *array[]) { ya_result return_code; if(FAIL(parse_u32_check_range(src, (u32 *)dst, min, max, BASE_10))) { if((strlen(src) == 1) && (*src == '*')) { *dst = -1; } else { if(FAIL(return_code = key_roll_item_validate(dst, src, min, max, array))) { return return_code; } } } return 0; } ya_result key_roll_item_value_bitmap_get(u64 *value, const char **needle, char *key_roll_item, size_t key_roll_item_size, u32 min, u32 max, const char *array[]) { yassert((min < 64) && (max < 64) && (min <= max)); ya_result return_code; *needle += strlen(key_roll_item); *needle = (char *)parse_skip_spaces(*needle); if(**needle == '\0') { return PARSER_REACHED_END_OF_LINE; } if(FAIL(return_code = parse_next_token(key_roll_item, key_roll_item_size, *needle, " \t"))) { return return_code; } char key_roll_item_part[16]; const char *needle2 = key_roll_item; *value = 0; s32 value_temp; for(;;) { value_temp = 0; // because the value may not be set again on the next iteration return_code = key_roll_item_parser(key_roll_item_part, sizeof(key_roll_item_part), &needle2, ","); if(return_code == 0) { break; } else if(return_code == 1) { if(FAIL(return_code = key_roll_item_value_check(&value_temp, key_roll_item_part, min, max, array))) { return return_code; } yassert((value_temp >= 0) && (value_temp < 64)); if(value_temp >= 0) { *value |= 1ULL << value_temp; } } else { return return_code; } } return_code = key_roll_item_value_check(&value_temp, key_roll_item_part, min, max, array); if(value_temp >= 0) { *value |= 1ULL << value_temp; } else { u64 tmp = 0; for(u32 i = min; i <= max; ++i) { tmp |= 1ULL << i; } *value = tmp; } return return_code; } ya_result key_roll_item_value_get(s32 *value, const char **needle, char *key_roll_item, size_t key_roll_item_size, u32 min, u32 max, const char *array[]) { ya_result return_code; *needle += strlen(key_roll_item); *needle = (char *)parse_skip_spaces(*needle); if(**needle == '\0') { return PARSER_REACHED_END_OF_LINE; } if(FAIL(return_code = parse_next_token(key_roll_item, key_roll_item_size, *needle, " \t"))) { return return_code; } return_code = key_roll_item_value_check(value, key_roll_item, min, max, array); return return_code; } ya_result key_roll_time_seconds(s32 *dst, const char *src) { ya_result return_code; u32 src_len = (u32)strlen(src); char lc = src[src_len - 1]; if(isdigit(lc)) { return_code = parse_s32_check_range_len_base10(src, src_len, dst, 0, MAX_S32); } else { s64 mult = 1; src_len--; switch(lc) { case 'w': case 'W': mult = 60 * 60 * 24 * 7; break; case 'd': case 'D': mult = 60 * 60 * 24; break; case 'h': case 'H': mult = 60 * 60; break; case 'm': case 'M': mult = 60; break; case 's': case 'S': break; default: { return PARSER_UNKNOWN_TIME_UNIT; } } s32 time32; if(ISOK(return_code = parse_s32_check_range_len_base10(src, src_len, &time32, 0, MAX_S32))) { mult *= time32; if(mult <= MAX_S32) { *dst = (s32)mult; } else { return_code = PARSEINT_ERROR; } } } return return_code; } u8 key_roll_item_relative_to(u8 dst) { return key_roll_actions_relative[dst]; } ya_result config_key_roll_parser_line(const char *key_roll_line, key_roll_line_s *krl, u8 action) { ya_result return_code; char key_roll_item[256]; krl->type = KEY_ROLL_LINE_CRON_TYPE; if(key_roll_line == NULL) { return PARSE_EMPTY_ARGUMENT; } memset(key_roll_item, 0, sizeof(key_roll_item)); // 1. start parsing 2 first tokens to find key_roll type const char *needle = key_roll_line; // action krl->action = action; /* // get second token needle += strlen(key_roll_line); */ needle = (char*)parse_skip_spaces(needle); if(*needle == '\0') { // this is bad return -1; } // 2. if parser find for second token a "+" sign this means the NON-CRON key_roll type if(strchr(needle, '+') != NULL) { if(FAIL(return_code = parse_next_token(key_roll_item, sizeof(key_roll_item), needle, " \t"))) { return return_code; } krl->type = KEY_ROLL_LINE_RELATIVE_TYPE; // relative seconds const char *p = key_roll_item; p++; u32 value; if(FAIL(return_code = key_roll_time_seconds((s32*)&value, p))) { return return_code; } krl->policy.relative.seconds = value; krl->policy.relative.type = ZONE_POLICY_RELATIVE; // 3. start parsing next two tokens for RELATIVE key_roll type // action relative to needle += strlen(key_roll_item); needle = (char*)parse_skip_spaces(needle); if(*needle == '\0') { krl->relative_to = key_roll_item_relative_to((u8)krl->action); } else { if(FAIL(return_code = parse_next_token(key_roll_item, sizeof(key_roll_item), needle, " \t"))) { return return_code; } if(FAIL(return_code = key_roll_item_validate(&krl->relative_to, key_roll_item, 0, 6, key_roll_actions))) { return return_code; } } } else { // 4. else start parsing next lines for CRON key_roll_type u64 bitmap; // minutes if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 0, 59, NULL))) { return return_code; } if(bitmap == 0) bitmap = 0x0fffffffffffffffLLU; // if no bits are set, all have to be krl->policy.cron.minute = bitmap; // hour if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 0, 23, NULL))) { return return_code; } if(bitmap == 0) bitmap = 0x0000000000ffffffLLU; krl->policy.cron.hour = bitmap; // day of month if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 1, 31, NULL))) { return return_code; } assert((bitmap & 1) == 0); // because [1;31] bitmap >>= 1; // because the bitmap needs [0;30] if(bitmap == 0) bitmap = 0x000000007fffffffLLU; krl->policy.cron.day = bitmap; // month if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 1, 12, month))) { return return_code; } assert((bitmap & 1) == 0); // because [1;12] bitmap >>= 1; // because the bitmap needs [0;11] if(bitmap == 0) bitmap = 0x0000000000000fffLLU; krl->policy.cron.month = (u16)bitmap; // day of week if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 0, 6, week))) { return return_code; } if(bitmap == 0) bitmap = 0x000000000000003fLLU; krl->policy.cron.weekday = bitmap; // week if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 0, 4, NULL))) { return return_code; } if(bitmap == 0) bitmap = 0x000000000000000fLLU; krl->policy.cron.week = bitmap; } return 0; } yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/zone-signature-policy.c0000644000000000000000000000013214505005533023306 xustar000000000000000030 mtime=1695812443.321994778 30 atime=1695812445.781029996 30 ctime=1695812495.714745147 yadifa-2.6.5-11201/sbin/yadifad/zone-signature-policy.c0000664000374500037450000037276314505005533023272 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #include "server-config.h" #include "zone-signature-policy.h" #include "zone_desc.h" #include "confs.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "database-service-zone-resignature.h" #if HAS_EVENT_DYNAMIC_MODULE #include "dynamic-module-handler.h" #endif #ifndef HAS_DYNUPDATE_DIFF_ENABLED #error "HAS_DYNUPDATE_DIFF_ENABLED not defined" #endif #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; #include "server_error.h" #include "zone.h" #define DNSECPOL_TAG 0x4c4f504345534e44 #define DPOLKYST_TAG 0x5453594b4c4f5044 #define DPOLKEY_TAG 0x0059454b4c4f5044 #define DPOLDNIL_TAG 0x4c494e444c4f5044 #define DPOLSALT_TAG 0x544c41534c4f5044 #define DPOLROLL_TAG 0x4c4c4f524c4f5044 #define DPOLRULE_TAG 0x454c55524c4f5044 #define DPOLQUEU_TAG 0x554555514c4f5044 #define KEY_POLICY_EPOCH_MATCH_MARGIN 180 // how close two epochs have to be to be considered a match #define DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS 0 #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS #pragma message("WARNING: DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS enabled !") #endif static u32_set zone_policy_rule_definition_set = U32_SET_EMPTY; static group_mutex_t zone_policy_rule_definition_set_mtx = GROUP_MUTEX_INITIALIZER; static volatile u32 zone_policy_rule_definition_next_index = 0; // local functions definitions ya_result zone_policy_date_init_at_next_rule(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule); ya_result zone_policy_date_init_at_prev_rule(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule); ya_result zone_policy_date_init_from_rule(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule); ya_result zone_policy_date_init_from_date(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule); static ya_result dnssec_policy_alarm_handler(void *args, bool cancel); // static ptr_set origin_to_dnssec_policy_queue_set = PTR_SET_DNSNAME_EMPTY; static mutex_t origin_to_dnssec_policy_queue_mtx = MUTEX_INITIALIZER; // static ptr_set dnssec_policy_roll_set = PTR_SET_ASCIIZ_EMPTY; static group_mutex_t dnssec_policy_roll_set_mtx = GROUP_MUTEX_INITIALIZER; static group_mutex_t dnssec_policy_roll_mtx = GROUP_MUTEX_INITIALIZER; // static ptr_set dnssec_policy_set = PTR_SET_ASCIIZ_EMPTY; static group_mutex_t dnssec_policy_set_mtx = GROUP_MUTEX_INITIALIZER; static group_mutex_t dnssec_policy_mtx = GROUP_MUTEX_INITIALIZER; // static ptr_set dnssec_denial_set = PTR_SET_ASCIIZ_EMPTY; static group_mutex_t dnssec_denial_set_mtx = GROUP_MUTEX_INITIALIZER; static group_mutex_t dnssec_denial_mtx = GROUP_MUTEX_INITIALIZER; // static ptr_set dnssec_policy_key_set = PTR_SET_ASCIIZ_EMPTY; static group_mutex_t dnssec_policy_key_set_mtx = GROUP_MUTEX_INITIALIZER; static group_mutex_t dnssec_policy_key_mtx = GROUP_MUTEX_INITIALIZER; // static ptr_set dnssec_policy_key_suite_set = PTR_SET_ASCIIZ_EMPTY; static group_mutex_t dnssec_policy_key_suite_set_mtx = GROUP_MUTEX_INITIALIZER; static group_mutex_t dnssec_policy_key_suite_mtx = GROUP_MUTEX_INITIALIZER; // static volatile int dnssec_policy_queue_serial = 0; static void zone_policy_process_alarm_arm(zone_desc_s *zone_desc, u32 delay_in_seconds); static void zone_policy_date_format_handler_method(const void *restrict val, output_stream *os, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { zone_policy_date *date = (zone_policy_date*)val; (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; switch(date->type.type) { case ZONE_POLICY_ABSOLUTE: { osformat(os, "%4u-%02u-%02u %02u:%02u:00U", date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month + 1, date->absolute.day + 1, date->absolute.hour, date->absolute.minute); break; } case ZONE_POLICY_RELATIVE: { osformat(os, "(%u)+%us", date->relative.seconds, date->relative.relativeto); break; } case ZONE_POLICY_RULE: { zone_policy_rule_definition_s *def = zone_policy_rule_definition_get_from_rule(date); osformat(os, "[%016x %06x %08x %02x %x %x]", def->minute, def->hour, def->day, def->month, def->weekday, def->week); break; } default: { output_stream_write(os, "?", 1); break; } } } dnssec_policy_queue* dnssec_policy_queue_new(const u8 *fqdn) { dnssec_policy_queue *cmd; ZALLOC_OBJECT_OR_DIE( cmd, dnssec_policy_queue, DPOLQUEU_TAG); ZEROMEMORY(cmd, sizeof(dnssec_policy_queue)); cmd->origin = dnsname_zdup(fqdn); // weak return cmd; } bool dnssec_policy_queue_equals(const dnssec_policy_queue *a, const dnssec_policy_queue *b) { if(a->command == b->command) { switch(a->command) { case DNSSEC_POLICY_COMMAND_INIT: { return TRUE; // as time is "asap" } case DNSSEC_POLICY_COMMAND_GENERATE_KEY: { return (a->epoch == b->epoch) && (a->parameters.generate_key.suite == b->parameters.generate_key.suite); } default: { // not implemented log_err("dnssec_policy_queue_equals: command not implemented"); abort(); } } } else { return FALSE; } } bool dnssec_policy_queue_has_command(dnssec_policy_queue *cmd) { bool ret = FALSE; mutex_lock(&origin_to_dnssec_policy_queue_mtx); ptr_node *queue_node = ptr_set_find(&origin_to_dnssec_policy_queue_set, cmd->origin); if(queue_node != NULL) { dnssec_policy_queue* cmdq = (dnssec_policy_queue*)queue_node->value; while(cmdq != NULL) { if(dnssec_policy_queue_equals(cmdq, cmd)) { ret = TRUE; break; } cmdq = cmdq->next; } } mutex_unlock(&origin_to_dnssec_policy_queue_mtx); return ret; } bool dnssec_policy_queue_has_command_type(const u8 *fqdn, int command) { bool ret = FALSE; mutex_lock(&origin_to_dnssec_policy_queue_mtx); ptr_node *queue_node = ptr_set_find(&origin_to_dnssec_policy_queue_set, fqdn); if(queue_node != NULL) { dnssec_policy_queue* cmdq = (dnssec_policy_queue*)queue_node->value; while(cmdq != NULL) { if(cmdq->command == command) { ret = TRUE; break; } cmdq = cmdq->next; } } mutex_unlock(&origin_to_dnssec_policy_queue_mtx); return ret; } static int dnssec_policy_queue_add_command(dnssec_policy_queue *cmd) { #if DEBUG log_debug("dnssec-policy: %{dnsname}: add command %p", cmd->origin, cmd); #endif yassert(!cmd->queued); mutex_lock(&origin_to_dnssec_policy_queue_mtx); int ret = dnssec_policy_queue_serial; dnssec_policy_queue_serial += 0x100; ptr_node *queue_node = ptr_set_insert(&origin_to_dnssec_policy_queue_set, cmd->origin); if(queue_node->value == NULL) { queue_node->key = dnsname_zdup(cmd->origin); } dnssec_policy_queue** cmdqp = (dnssec_policy_queue**)&queue_node->value; cmd->next = *cmdqp; cmd->queued = TRUE; *cmdqp = cmd; mutex_unlock(&origin_to_dnssec_policy_queue_mtx); return ret; } void dnssec_policy_queue_add_command_at_epoch(dnssec_policy_queue *cmd, alarm_t hndl, time_t at) { int serial = dnssec_policy_queue_add_command(cmd) | ALARM_KEY_DNSSEC_POLICY_EVENT; alarm_event_node *event = alarm_event_new( // policy : key generation at, serial, dnssec_policy_alarm_handler, cmd, ALARM_DUP_REMOVE_LATEST, "dnssec-policy-generate-key"); alarm_set(hndl, event); } void dnssec_policy_queue_remove_command(dnssec_policy_queue *cmd) { if(cmd->queued) { #if DEBUG log_debug("dnssec-policy: %{dnsname}: remove command %p", cmd->origin, cmd); #endif mutex_lock(&origin_to_dnssec_policy_queue_mtx); ptr_node *queue_node = ptr_set_insert(&origin_to_dnssec_policy_queue_set, cmd->origin); dnssec_policy_queue** cmdqp = (dnssec_policy_queue**)&queue_node->value; while(*cmdqp != NULL) { if(*cmdqp == cmd) { *cmdqp = cmd->next; cmd->next = NULL; cmd->queued = FALSE; break; } cmdqp = &(*cmdqp)->next; } if(queue_node->value == NULL) { u8* key = (u8*)queue_node->key; ptr_set_delete(&origin_to_dnssec_policy_queue_set, cmd->origin); dnsname_zfree(key); } mutex_unlock(&origin_to_dnssec_policy_queue_mtx); } #if DEBUG else { log_debug("dnssec-policy: %{dnsname}: remove command %p: not queued", cmd->origin, cmd); } #endif } void dnssec_policy_queue_delete_command(dnssec_policy_queue *cmd) { #if DEBUG log_debug("dnssec-policy: %{dnsname}: delete command %p", cmd->origin, cmd); #endif dnssec_policy_queue_remove_command(cmd); switch(cmd->command) { case DNSSEC_POLICY_COMMAND_INIT: { break; } case DNSSEC_POLICY_COMMAND_GENERATE_KEY: { if(cmd->parameters.generate_key.suite != NULL) { dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite); zone_release(cmd->parameters.generate_key.zone_desc); } break; } } #if DEBUG intptr cmd_address = (intptr)cmd; #endif dnsname_zfree(cmd->origin); ZFREE_OBJECT(cmd); #if DEBUG log_debug("dnssec-policy: delete command %p: done", cmd_address); // scan-build false positive : the memory pointed by cmd is freed, but cmd's value is still valid. #endif } ya_result dnssec_policy_queue_add_generate_key_create_at(zone_desc_s *zone_desc, struct dnssec_policy_key_suite *kr, time_t epoch) { zone_policy_table_s tbl; zone_policy_date now_date; ya_result ret; ret = zone_policy_date_init_from_epoch(&now_date, epoch); if(FAIL(ret)) { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_table_init_from_date returned an error: %r", ret); return ret; } ret = zone_policy_table_init_from_date(&tbl, &kr->roll->time_table, &now_date); if(FAIL(ret)) { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_table_init_from_date returned an error: %r", ret); return ret; } #if DEBUG format_writer n_fw = {zone_policy_date_format_handler_method, &now_date}; format_writer c_fw = {zone_policy_date_format_handler_method, &tbl.created}; format_writer p_fw = {zone_policy_date_format_handler_method, &tbl.publish}; format_writer a_fw = {zone_policy_date_format_handler_method, &tbl.activate}; format_writer d_fw = {zone_policy_date_format_handler_method, &tbl.inactive}; format_writer r_fw = {zone_policy_date_format_handler_method, &tbl.delete}; log_debug("dnssec-policy: %{dnsname}: %s: at %T = %U = %w: queued key: create=%w, publish=%w, activate=%w, deactivate=%w, remove=%w", zone_origin(zone_desc), kr->name, epoch, epoch, &n_fw, &c_fw, &p_fw, &a_fw, &d_fw, &r_fw); #endif #if 1 yassert(tbl.created.type.type == ZONE_POLICY_ABSOLUTE); time_t alarm_epoch; if(FAIL(ret = zone_policy_date_get_epoch(&tbl.created, &alarm_epoch))) // note: created should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch returned an error: %r", ret); return ret; } #if DEBUG log_debug("dnssec-policy: %{dnsname}: %s: alarm set to %T", zone_origin(zone_desc), kr->name, alarm_epoch); logger_flush(); #endif dnssec_policy_queue *cmd = dnssec_policy_queue_new(zone_origin(zone_desc)); dnssec_policy_key_suite_acquire(kr); // scan-build doesn't get this prevents the free to happen zone_acquire(zone_desc); cmd->epoch = epoch; cmd->command = DNSSEC_POLICY_COMMAND_GENERATE_KEY; cmd->parameters.generate_key.suite = kr; // must be done else the dnssec_policy_queue_has_command will fail cmd->parameters.generate_key.zone_desc = zone_desc; if(!dnssec_policy_queue_has_command(cmd)) { log_debug("dnssec-policy: %{dnsname}: %s: at %T will generate a key with time parameter: %T", zone_origin(zone_desc), kr->name, alarm_epoch, epoch); // add the command zone_policy_key_suite_mark_processed(zone_desc, kr); dnssec_policy_queue_add_command_at_epoch(cmd, zone_desc->loaded_zone->alarm_handle, alarm_epoch); } else { // note: kr is part of cmd, so it cannot be use dafter cmd has been deleted log_debug("dnssec-policy: %{dnsname}: %s: key generation for policy already set", zone_origin(zone_desc), kr->name); dnssec_policy_queue_delete_command(cmd); } #else time_t created_epoch; time_t publish_epoch; time_t activate_epoch; time_t deactivate_epoch; time_t unpublish_epoch; if(FAIL(ret = zone_policy_date_get_epoch(&tbl.created, &created_epoch))) // note: created should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (created_epoch) returned an error: %r", ret); return ret; } if(FAIL(ret = zone_policy_date_get_epoch(&tbl.publish, &publish_epoch))) // note: publish should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (publish_epoch) returned an error: %r", ret); return ret; } if(FAIL(ret = zone_policy_date_get_epoch(&tbl.activate, &activate_epoch))) // note: activate should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (activate_epoch) returned an error: %r", ret); return ret; } if(FAIL(ret = zone_policy_date_get_epoch(&tbl.inactive, &deactivate_epoch))) // note: deactivate should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (deactivate_epoch) returned an error: %r", ret); return ret; } if(FAIL(ret = zone_policy_date_get_epoch(&tbl.delete, &unpublish_epoch))) // note: unpublish should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (unpublish_epoch) returned an error: %r", ret); return ret; } keyroll_generate_dnskey_ex(keyroll, kr->key->size, kr->key->algorithm, ONE_SECOND_US * created_epoch, ONE_SECOND_US * publish_epoch, ONE_SECOND_US * activate_epoch, ONE_SECOND_US * deactivate_epoch, ONE_SECOND_US * unpublish_epoch, (kr->key->flags == DNSKEY_FLAGS_KSK)); yassert(tbl.created.type.type == ZONE_POLICY_ABSOLUTE); time_t alarm_epoch; if(FAIL(ret = zone_policy_date_get_epoch(&tbl.created, &alarm_epoch))) // note: created should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch returned an error: %r", ret); return ret; } #if DEBUG log_debug("dnssec-policy: %{dnsname}: %s: key created set at %T", zone_origin(zone_desc), kr->name, alarm_epoch); #endif #endif // #if 0 #else return SUCCESS; } /** * Works only with RULEs (cron) key suites * * @param zone_desc * @param kr * @param active_at * @param will_be_inactive_at a pointer that'll receive the inactive epoch (can be NULL) */ ya_result dnssec_policy_queue_add_generate_key_active_at(zone_desc_s *zone_desc, struct dnssec_policy_key_suite *kr, time_t active_at, time_t *will_be_inactive_at) { zone_policy_date creation_date; zone_policy_date publish_date; zone_policy_date activate_date; zone_policy_date inactive_date; zone_policy_date unpublish_date; zone_policy_date now_date; ya_result ret; if(FAIL(ret = zone_policy_date_init_from_epoch(&now_date, active_at))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_prev_rule(&activate_date, &now_date, &kr->roll->time_table.activate))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_prev_rule(&publish_date, &activate_date, &kr->roll->time_table.publish))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_prev_rule(&creation_date, &publish_date, &kr->roll->time_table.created))) { return ret; } time_t creation_epoch = 60; time_t activate_epoch = 60; if(FAIL(ret = zone_policy_date_get_epoch(&creation_date, &creation_epoch))) { return ret; } if(FAIL(ret = zone_policy_date_get_epoch(&activate_date, &activate_epoch))) { return ret; } #if DEBUG format_writer c_fw = {zone_policy_date_format_handler_method, &creation_date}; { format_writer a_fw0 = {zone_policy_date_format_handler_method, &activate_date}; format_writer p_fw0 = {zone_policy_date_format_handler_method, &publish_date}; log_debug1("dnssec-policy: %{dnsname}: %s: base %w <= %w <= %w : %T", zone_origin(zone_desc), kr->name, &c_fw, &p_fw0, &a_fw0, creation_epoch); } #endif if(FAIL(ret = zone_policy_date_init_at_next_rule(&publish_date, &creation_date, &kr->roll->time_table.publish))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_next_rule(&activate_date, &publish_date, &kr->roll->time_table.activate))) { return ret; } #if DEBUG format_writer p_fw = {zone_policy_date_format_handler_method, &publish_date}; format_writer a_fw = {zone_policy_date_format_handler_method, &activate_date}; { log_debug1("dnssec-policy: %{dnsname}: %s: base %w => %w => %w : %T (after forward correction)", zone_origin(zone_desc), kr->name, &c_fw, &p_fw, &a_fw, creation_epoch); } #endif // compute the future key timings to ensure there will be no period without a signature zone_policy_date next_creation_date; zone_policy_date next_publish_date; zone_policy_date next_activate_date; if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_creation_date, &activate_date, &kr->roll->time_table.created))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_publish_date, &next_creation_date, &kr->roll->time_table.publish))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_activate_date, &next_publish_date, &kr->roll->time_table.activate))) { return ret; } #if DEBUG { format_writer na_fw = {zone_policy_date_format_handler_method, &next_activate_date}; format_writer np_fw = {zone_policy_date_format_handler_method, &next_publish_date}; format_writer nc_fw = {zone_policy_date_format_handler_method, &next_creation_date}; log_debug1("dnssec-policy: %{dnsname}: %s: next %w => %w => %w", zone_origin(zone_desc), kr->name, &nc_fw, &np_fw, &na_fw); } #endif // and use this next_activate as a base for the current deactivate if(FAIL(ret = zone_policy_date_init_at_next_rule(&inactive_date, &next_activate_date, &kr->roll->time_table.inactive))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_next_rule(&unpublish_date, &inactive_date, &kr->roll->time_table.delete))) { return ret; } time_t inactive_epoch = 0; if(FAIL(ret = zone_policy_date_get_epoch(&inactive_date, &inactive_epoch))) { return ret; } if(inactive_epoch - activate_epoch < DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS) { double d = inactive_epoch - activate_epoch; d /= 86400.0; double c = DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS; c /= 86400.0; log_warn("dnssec-policy: %{dnsname}: %s: the key will only be activated for %.3f days, consider increasing this value to at least %.3f days", zone_origin(zone_desc), kr->name, d, c); } if(inactive_epoch < active_at) { log_err("dnssec-policy: %{dnsname}: %s: computing timings to be in the current activated time window produces an already expired key", zone_origin(zone_desc), kr->name ); return INVALID_STATE_ERROR; } if(will_be_inactive_at != NULL) { *will_be_inactive_at = inactive_epoch; } #if DEBUG format_writer d_fw = {zone_policy_date_format_handler_method, &inactive_date}; zone_policy_date remove_date; ret = zone_policy_date_init_at_next_rule(&remove_date, &inactive_date, &kr->roll->time_table.delete); (void)ret; format_writer r_fw = {zone_policy_date_format_handler_method, &unpublish_date}; log_debug("dnssec-policy: %{dnsname}: %s: rule key: create=%w, publish=%w, activate=%w, deactivate=%w, remove=%w", zone_origin(zone_desc), kr->name, &c_fw, &p_fw, &a_fw, &d_fw, &r_fw); #endif log_debug("dnssec-policy: %{dnsname}: %s: will generate a key at %T (rule new) to be active at %T", zone_origin(zone_desc), kr->name, creation_epoch, active_at); #if DEBUG logger_flush(); #endif // add the command ret = dnssec_policy_queue_add_generate_key_create_at(zone_desc, kr, creation_epoch); return ret; } ya_result dnssec_policy_roll_test_at(struct dnssec_policy_roll *kr, time_t active_at, time_t *will_be_inactive_at, bool print_text, bool log_text) { zone_policy_date creation_date; zone_policy_date publish_date; zone_policy_date activate_date; zone_policy_date inactive_date; zone_policy_date unpublish_date; zone_policy_date now_date; ya_result ret; if(FAIL(ret = zone_policy_date_init_from_epoch(&now_date, active_at))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_prev_rule(&activate_date, &now_date, &kr->time_table.activate))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_prev_rule(&publish_date, &activate_date, &kr->time_table.publish))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_prev_rule(&creation_date, &publish_date, &kr->time_table.created))) { return ret; } time_t creation_epoch = 60; time_t activate_epoch = 60; if(FAIL(ret = zone_policy_date_get_epoch(&creation_date, &creation_epoch))) { return ret; } if(FAIL(ret = zone_policy_date_get_epoch(&activate_date, &activate_epoch))) { return ret; } #if DEBUG format_writer c_fw = {zone_policy_date_format_handler_method, &creation_date}; { format_writer a_fw0 = {zone_policy_date_format_handler_method, &activate_date}; format_writer p_fw0 = {zone_policy_date_format_handler_method, &publish_date}; log_debug1("key-roll: %s: base %w <= %w <= %w : %T", kr->name, &c_fw, &p_fw0, &a_fw0, creation_epoch); } #endif if(FAIL(ret = zone_policy_date_init_at_next_rule(&publish_date, &creation_date, &kr->time_table.publish))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_next_rule(&activate_date, &publish_date, &kr->time_table.activate))) { return ret; } #if DEBUG format_writer p_fw = {zone_policy_date_format_handler_method, &publish_date}; format_writer a_fw = {zone_policy_date_format_handler_method, &activate_date}; { log_debug1("key-roll: %s: base %w => %w => %w : %T (after forward correction)", kr->name, &c_fw, &p_fw, &a_fw, creation_epoch); } #endif // compute the future key timings to ensure there will be no period without a signature zone_policy_date next_creation_date; zone_policy_date next_publish_date; zone_policy_date next_activate_date; if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_creation_date, &activate_date, &kr->time_table.created))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_publish_date, &next_creation_date, &kr->time_table.publish))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_activate_date, &next_publish_date, &kr->time_table.activate))) { return ret; } #if DEBUG { format_writer na_fw = {zone_policy_date_format_handler_method, &next_activate_date}; format_writer np_fw = {zone_policy_date_format_handler_method, &next_publish_date}; format_writer nc_fw = {zone_policy_date_format_handler_method, &next_creation_date}; log_debug1("key-roll: %s: next %w => %w => %w", kr->name, &nc_fw, &np_fw, &na_fw); } #endif // and use this next_activate as a base for the current deactivate if(FAIL(ret = zone_policy_date_init_at_next_rule(&inactive_date, &next_activate_date, &kr->time_table.inactive))) { return ret; } if(FAIL(ret = zone_policy_date_init_at_next_rule(&unpublish_date, &inactive_date, &kr->time_table.delete))) { return ret; } time_t inactive_epoch = 0; if(FAIL(ret = zone_policy_date_get_epoch(&inactive_date, &inactive_epoch))) { return ret; } if(inactive_epoch - activate_epoch < DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS) { double d = inactive_epoch - activate_epoch; d /= 86400.0; double c = DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS; c /= 86400.0; if(log_text) { log_warn("key-roll: %s: the key will only be activated for %.3f days, consider increasing this value to at least %.3f days", kr->name, d, c); } if(print_text) { formatln("key-roll: %s: the key will only be activated for %.3f days, consider increasing this value to at least %.3f days", kr->name, d, c); } } if(inactive_epoch < active_at) { if(log_text) { log_err("key-roll: %s: computing timings to be in the current activated time window produces an already expired key", kr->name); } if(print_text) { formatln("key-roll: %s: computing timings to be in the current activated time window produces an already expired key", kr->name); } return INVALID_STATE_ERROR; } if(will_be_inactive_at != NULL) { *will_be_inactive_at = inactive_epoch; } #if DEBUG format_writer d_fw = {zone_policy_date_format_handler_method, &inactive_date}; zone_policy_date remove_date; ret = zone_policy_date_init_at_next_rule(&remove_date, &inactive_date, &kr->time_table.delete); (void)ret; format_writer r_fw = {zone_policy_date_format_handler_method, &unpublish_date}; log_debug("key-roll: %s: rule key: create=%w, publish=%w, activate=%w, deactivate=%w, remove=%w", kr->name, &c_fw, &p_fw, &a_fw, &d_fw, &r_fw); #endif log_debug("key-roll: %s: will generate a key at %T (rule new) to be active at %T", kr->name, creation_epoch, active_at); if(log_text || print_text) { format_writer c_fw0 = {zone_policy_date_format_handler_method, &creation_date}; format_writer p_fw0 = {zone_policy_date_format_handler_method, &publish_date}; format_writer a_fw0 = {zone_policy_date_format_handler_method, &activate_date}; format_writer i_fw0 = {zone_policy_date_format_handler_method, &inactive_date}; format_writer u_fw0 = {zone_policy_date_format_handler_method, &unpublish_date}; u32 delta_seconds = inactive_epoch - activate_epoch; float delta_value; const char *delta_units; if(delta_seconds > 2592000) { delta_value = 1.0f * delta_seconds / 2592000.f; delta_units = "months"; } else if(delta_seconds > 604800) { delta_value = 1.f * delta_seconds / 604800.f; delta_units = "weeks"; } else if(delta_seconds > 86400) { delta_value = 1.f * delta_seconds / 86400.f; delta_units = "days"; } else if(delta_seconds > 3600) { delta_value = 1.f * delta_seconds / 3600.f; delta_units = "hours"; } else if(delta_seconds > 60) { delta_value = 1.f * delta_seconds / 60.f; delta_units = "minutes"; } else { delta_value = 1.f * delta_seconds; delta_units = "seconds"; } if(log_text) { log_info("key-roll: %s: creation at %w, publication at %w, activation at %w, deactivation at %w, removal at %w, %6.1f %s", kr->name, &c_fw0, &p_fw0, &a_fw0, &i_fw0, &u_fw0, delta_value, delta_units); } if(print_text) { formatln("key-roll: %s: creation at %w, publication at %w, activation at %w, deactivation at %w, removal at %w, %6.1f %s", kr->name, &c_fw0, &p_fw0, &a_fw0, &i_fw0, &u_fw0, delta_value, delta_units); } } #if DEBUG logger_flush(); #endif return ret; } ya_result dnssec_policy_roll_test(struct dnssec_policy_roll *kr, time_t active_at, u32 duration_seconds, bool print_text, bool log_text) { ya_result ret; time_t end_at = active_at + duration_seconds; time_t inactive_at = 0; if(print_text) { formatln("key-roll: %s: testing policy sets of dates from %T to %T", kr->name, active_at, end_at); } if(log_text) { formatln("key-roll: %s: testing policy sets of dates from %T to %T", kr->name, active_at, end_at); } while(active_at < end_at) { if(FAIL(ret = dnssec_policy_roll_test_at(kr, active_at, &inactive_at, print_text, log_text))) { if(log_text) { log_info("key-roll: %s: could not find a matching set of dates from %T", kr->name, active_at); } if(print_text) { formatln("key-roll: %s: could not find a matching set of dates from %T", kr->name, active_at); } return ret; } active_at = inactive_at; } if(print_text) { formatln("key-roll: %s: policy sets of dates from %T to %T computed", kr->name, active_at, end_at); } if(log_text) { formatln("key-roll: %s: policy sets of dates from %T to %T computed", kr->name, active_at, end_at); } return SUCCESS; } /** * Compare two dates together. * Absolute with Absolute * Relative with Relative * * Any other combination will return -1 * * @param d1 first date * @param d2 second date * @return <0,0,>0 if d1 is less than, equal to, or greater than d2 */ int zone_policy_date_compare(const zone_policy_date *d1, const zone_policy_date *d2) { int ret; if(d1->type.type == ZONE_POLICY_ABSOLUTE && d2->type.type == ZONE_POLICY_ABSOLUTE) { ret = d1->absolute.year; ret -= d2->absolute.year; if(ret == 0) { ret = d1->absolute.month; ret -= d2->absolute.month; if(ret == 0) { ret = d1->absolute.day; ret -= d2->absolute.day; if(ret == 0) { ret = d1->absolute.hour; ret -= d2->absolute.hour; if(ret == 0) { ret = d1->absolute.minute; ret -= d2->absolute.minute; } } } } return ret; } else if(d1->type.type == ZONE_POLICY_RELATIVE && d2->type.type == ZONE_POLICY_RELATIVE) { ret = d1->relative.seconds; ret -= d2->relative.seconds; return ret; } return POLICY_ILLEGAL_DATE_COMPARE; } /** * Retrieves the first day of the month. * * 0 is Sunday * * @param year 0-based * @param month 0-based * @param week 0 to 4, week of the day * @param wday 0 to 6, day of the week, 0 for Sunday * @return the number of the day of the month or an error code */ ya_result zone_policy_get_mday_from_year_month_week_wday(int year, int month, int week, int wday) { int mday1 = time_first_day_of_month(year, month); if(mday1 >= 0) { /** * @note this can obviously be simplified (++week) but I think it's clearer this way (for now) */ if(wday < mday1) { // 0 1 2 3 4 5 6 // // X Y Z 1 2 3 4 // 4[6]7 8 9 ... return wday - mday1 + 7 * (week + 1); } else { // 0 1 2 3 4 5 6 // // X Y Z 1 2 3 4 // 4 6 7 8[9]... return wday - mday1 + 7 * week; } } else { return POLICY_ILLEGAL_DATE; } } /** * Initialises an absolute date from a year, month, week and week-day * * ie: 2nd Wednesday of January 2001 * * 0 is Sunday * * @param date the date to initialise * @param year 0-based * @param month 0-based * @param week 0 to 4, week of the day * @param wday 0 to 6, day of the week, 0 for Sunday * @return an error code */ ya_result zone_policy_date_init_from_year_month_week_wday(zone_policy_date *date, int year, int month, int week, int wday) { struct tm tm; ZEROMEMORY(&tm, sizeof(struct tm)); tm.tm_mday = 1; tm.tm_mon = month; tm.tm_year = year - 1900; time_t t = mkgmtime(&tm); if(t >= 0) { if(tm.tm_wday >= 0) { /** * @note this can obviously be simplified (++week) but I think it's clearer this way (for now) * * tm_wday is the first week-day of the month */ if(wday < tm.tm_wday) // [0 .. 7] < [1 .. 31] ? { // 0 1 2 3 4 5 6 // // X Y Z 1 2 3 4 // 4[6]7 8 9 ... tm.tm_mday = wday - tm.tm_wday + 7 * (week + 1) + 1; } else { // 0 1 2 3 4 5 6 // // X Y Z 1 2 3 4 // 4 6 7 8[9]... tm.tm_mday = wday - tm.tm_wday + 7 * week + 1; } t = mkgmtime(&tm); if(t >= 0) { if(tm.tm_year < 228) { date->type.type = ZONE_POLICY_ABSOLUTE; date->absolute.year = tm.tm_year - (ZONE_POLICY_DATE_YEAR_BASE - 1900); // 1900 based to 2000 based date->absolute.month = tm.tm_mon; date->absolute.day = tm.tm_mday - 1; // 1 based to 0 based date->absolute.hour = tm.tm_hour; date->absolute.minute = tm.tm_min; return SUCCESS; } } } } return POLICY_ILLEGAL_DATE_PARAMETERS; } /** * Initialises an absolute date from a UNIX epoch * * @param date * @param epoch * @return an error code */ ya_result zone_policy_date_init_from_epoch(zone_policy_date *date, time_t epoch) { time_t t = epoch; struct tm d; // if it worked and there was no overflow ... if((gmtime_r(&t, &d) != NULL) && (d.tm_year < 228)) { date->type.type = ZONE_POLICY_ABSOLUTE; date->absolute.year = d.tm_year - (ZONE_POLICY_DATE_YEAR_BASE - 1900); // 1900 based to 2000 based date->absolute.month = d.tm_mon; date->absolute.day = d.tm_mday - 1; // 1 based to 0 based date->absolute.hour = d.tm_hour; date->absolute.minute = d.tm_min; return SUCCESS; } return POLICY_ILLEGAL_DATE_PARAMETERS; } /** * Gets the UNIX epoch from an absolute date * * @param date * @param epoch a pointer to hold the result * @return an error code */ ya_result zone_policy_date_get_epoch(const zone_policy_date *date, time_t *epoch) { time_t t; struct tm d; yassert(epoch != NULL); if(date->type.type != ZONE_POLICY_ABSOLUTE) // only works with absolute dates { return POLICY_ILLEGAL_DATE_TYPE; } ZEROMEMORY(&d, sizeof(struct tm)); d.tm_year = date->absolute.year + (ZONE_POLICY_DATE_YEAR_BASE - 1900); // 2000 based to 1900 based d.tm_mon = date->absolute.month; d.tm_mday = date->absolute.day + 1; // 0 based to 1 based d.tm_hour = date->absolute.hour; d.tm_min = date->absolute.minute; d.tm_sec = 0; t = mkgmtime(&d); if(t != -1) { *epoch = t; return SUCCESS; } else { return MAKE_ERRNO_ERROR(EOVERFLOW); } } /** * Initialises the absolute date with an epoch plus time in seconds. * * @param date * @param epoch an epoch to add the seconds to * @param seconds * @return an error code */ ya_result zone_policy_date_init_after_epoch(zone_policy_date *date, time_t epoch, u32 seconds) { ya_result ret = zone_policy_date_init_from_epoch(date, epoch + seconds); return ret; } /** * Initialises the absolute date with an absolute date plus time in seconds. * * @param date * @param from an absolute date to add the seconds to * @param seconds * @return an error code */ ya_result zone_policy_date_init_after_date(zone_policy_date *date, const zone_policy_date *from, u32 seconds) { ya_result ret; time_t epoch; if(ISOK(ret = zone_policy_date_get_epoch(from, &epoch))) { ret = zone_policy_date_init_from_epoch(date, epoch + seconds); } return ret; } /** * Initialises a date using a rule applied on an epoch * * @param result_date * @param rule_date * @param after_epoch * @return */ ya_result zone_policy_date_init_from_rule_applied_with_epoch(zone_policy_date *result_date, const zone_policy_date *rule_date, time_t after_epoch) { zone_policy_date after_date; ya_result ret; if(ISOK(ret = zone_policy_date_init_from_epoch(&after_date, after_epoch))) { ret = zone_policy_date_init_at_next_date(result_date, &after_date, rule_date); } return ret; } /** * Initialises an epoch from a rule applied on an epoch * * @param rule_date * @param after_epoch * @param result_epoch * @return */ ya_result zone_policy_get_epoch_from_rule_applied_with_epoch(const zone_policy_date *rule_date, time_t after_epoch, time_t *result_epoch) { zone_policy_date result_date; ya_result ret; if(ISOK(ret = zone_policy_date_init_from_rule_applied_with_epoch(&result_date, rule_date, after_epoch))) { ret = zone_policy_date_get_epoch(&result_date, result_epoch); } return ret; } zone_policy_rule_definition_s* zone_policy_rule_definition_get_from_index(u32 index) { zone_policy_rule_definition_s *ret = NULL; group_mutex_read_lock(&zone_policy_rule_definition_set_mtx); u32_node *node = u32_set_find(&zone_policy_rule_definition_set, index); if(node != NULL) { ret = (zone_policy_rule_definition_s*)node->value; } group_mutex_read_unlock(&zone_policy_rule_definition_set_mtx); return ret; } zone_policy_rule_definition_s* zone_policy_rule_definition_get_from_rule(const zone_policy_date *rule) { zone_policy_rule_definition_s *ret = NULL; if(rule->type.type == ZONE_POLICY_RULE) { ret = zone_policy_rule_definition_get_from_index(rule->rule.index); } return ret; } void zone_policy_rule_init(zone_policy_rule_s *rule, const zone_policy_rule_definition_s *rule_definition) { group_mutex_write_lock(&zone_policy_rule_definition_set_mtx); yassert(zone_policy_rule_definition_next_index < 0x40000000); for(;;) { ++zone_policy_rule_definition_next_index; if(zone_policy_rule_definition_next_index == 0x40000000) { zone_policy_rule_definition_next_index = 0; } u32_node *node = u32_set_insert(&zone_policy_rule_definition_set, zone_policy_rule_definition_next_index); if(node->value == NULL) { rule->index = zone_policy_rule_definition_next_index; rule->type = ZONE_POLICY_RULE; zone_policy_rule_definition_s *new_rule_definition; ZALLOC_OBJECT_OR_DIE( new_rule_definition, zone_policy_rule_definition_s, DPOLRULE_TAG); memcpy(new_rule_definition, rule_definition, sizeof(zone_policy_rule_definition_s)); node->value = new_rule_definition; break; } } group_mutex_write_unlock(&zone_policy_rule_definition_set_mtx); } void zone_policy_rule_finalize(zone_policy_rule_s *rule) { group_mutex_write_lock(&zone_policy_rule_definition_set_mtx); u32_node *node = u32_set_find(&zone_policy_rule_definition_set, rule->index); if(node != NULL) { if(node->value != NULL) { ZFREE(node->value, zone_policy_rule_definition_s); } u32_set_delete(&zone_policy_rule_definition_set, rule->index); } group_mutex_write_unlock(&zone_policy_rule_definition_set_mtx); } void zone_policy_date_init_from_rule_definition(zone_policy_date *date, const zone_policy_rule_definition_s *rule_definition) { date->type.type = ZONE_POLICY_RULE; zone_policy_rule_init(&date->rule, rule_definition); } /** * Initialises a date with the earliest matching of the rule starting after 'from' * * @param date * @param from * @param rule * * @return an error code */ ya_result zone_policy_date_init_at_next_date(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule) { ya_result ret; if((((intptr)date) == 0) | (((intptr)from) == 0) | (((intptr)rule) == 0)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } #if DEBUG format_writer from_fw = {zone_policy_date_format_handler_method, from}; format_writer rule_fw = {zone_policy_date_format_handler_method, rule}; format_writer date_fw = {zone_policy_date_format_handler_method, date}; #endif if(from->type.type != ZONE_POLICY_ABSOLUTE) { #if DEBUG log_debug1("zone_policy_date_init_at_next_date(%p, %w, %w): can only work from an absolute time", date, &from_fw, &rule_fw); #endif return POLICY_ILLEGAL_DATE_TYPE; } switch(rule->type.type) { case ZONE_POLICY_RELATIVE: { memcpy(date, from, sizeof(zone_policy_date)); #if DEBUG log_debug1("zone_policy_date_init_at_next_date(%p, %w, %w): initialising relative time", date, &from_fw, &rule_fw); #endif ret = zone_policy_date_init_after_date(date, from, rule->relative.seconds); // +60 because it must be after and because of minute granularity #if DEBUG log_debug1("zone_policy_date_init_at_next_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw); #endif return ret; } case ZONE_POLICY_RULE: { #if DEBUG log_debug1("zone_policy_date_init_at_next_date(%p, %w, %w): initialising rule-based time", date, &from_fw, &rule_fw); #endif ret = zone_policy_date_init_at_next_rule(date, from, rule); #if DEBUG log_debug1("zone_policy_date_init_at_next_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw); #endif return ret; } default: { #if DEBUG log_debug1("zone_policy_date_init_at_next_date(%p, %w, %w): unexpected type", date, &from_fw, &rule_fw); #endif return POLICY_ILLEGAL_DATE_TYPE; } } } static zone_policy_date* zone_policy_table_get_date_by_index(zone_policy_table_s *tbl, int index) { switch(index) { case ZONE_POLICY_RELATIVE_TO_GENERATE: return &tbl->created; case ZONE_POLICY_RELATIVE_TO_PUBLISH: return &tbl->publish; case ZONE_POLICY_RELATIVE_TO_ACTIVATE: return &tbl->activate; case ZONE_POLICY_RELATIVE_TO_INACTIVE: return &tbl->inactive; case ZONE_POLICY_RELATIVE_TO_REMOVE: return &tbl->delete; #if HAS_DS_PUBLICATION_SUPPORT case ZONE_POLICY_RELATIVE_TO_DS_PUBLISH: return &tbl->ds_publish; case ZONE_POLICY_RELATIVE_TO_DS_REMOVE: return &tbl->ds_remove; #endif default: log_err("zone_policy_table_get_date_by_index(%p, %i): index out of range [%i, %i]", tbl, index, ZONE_POLICY_RELATIVE_TO_GENERATE, ZONE_POLICY_RELATIVE_TO_REMOVE); return NULL; } } /** * This initialises a date with the earliest matching of the rule starting from 'from' * * @param date * @param from * @param rule * * @return an error code */ ya_result zone_policy_date_init_from_date(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule) { ya_result ret; #if DEBUG format_writer from_fw = {zone_policy_date_format_handler_method, from}; format_writer rule_fw = {zone_policy_date_format_handler_method, rule}; format_writer date_fw = {zone_policy_date_format_handler_method, date}; #endif if(from->type.type != ZONE_POLICY_ABSOLUTE) { #if DEBUG log_debug1("zone_policy_date_init_from_date(%p, %w, %w): can only work from an absolute time", date, &from_fw, &rule_fw); #endif return POLICY_ILLEGAL_DATE_TYPE; } switch(rule->type.type) { case ZONE_POLICY_RELATIVE: { memcpy(date, from, sizeof(zone_policy_date)); #if DEBUG log_debug1("zone_policy_date_init_from_date(%p, %w, %w): initialising relative time", date, &from_fw, &rule_fw); #endif ret = zone_policy_date_init_after_date(date, from, rule->relative.seconds); #if DEBUG log_debug1("zone_policy_date_init_from_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw); #endif return ret; } case ZONE_POLICY_RULE: { #if DEBUG log_debug1("zone_policy_date_init_from_date(%p, %w, %w): initialising rule-based time", date, &from_fw, &rule_fw); #endif ret = zone_policy_date_init_from_rule(date, from, rule); #if DEBUG log_debug1("zone_policy_date_init_from_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw); #endif return ret; } default: { #if DEBUG log_debug1("zone_policy_date_init_from_date(%p, %w, %w): unexpected type", date, &from_fw, &rule_fw); #endif return POLICY_ILLEGAL_DATE_TYPE; } } } ya_result zone_policy_table_init_from_date(zone_policy_table_s *tbl, zone_policy_table_s *with, zone_policy_date *from) { ya_result ret; if(with->created.type.type == ZONE_POLICY_RULE) { if(ISOK(ret = zone_policy_date_init_from_date(&tbl->created, from, &with->created))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->activate, &tbl->publish, &with->activate))) { #if DEBUG format_writer c_fw = {zone_policy_date_format_handler_method, &tbl->created}; format_writer p_fw = {zone_policy_date_format_handler_method, &tbl->publish}; format_writer a_fw = {zone_policy_date_format_handler_method, &tbl->activate}; log_debug("zone_policy_table_init: base c:%w => p:%w => a:%w", &c_fw, &p_fw, &a_fw); #endif // compute the future key timings to ensure there will be no period without a signature zone_policy_date next_creation_date; zone_policy_date next_publish_date; zone_policy_date next_activate_date; if(ISOK(ret = zone_policy_date_init_at_next_date(&next_creation_date, &tbl->activate, &with->created))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&next_publish_date, &next_creation_date, &with->publish))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&next_activate_date, &next_publish_date, &with->activate))) { #if DEBUG format_writer na_fw = {zone_policy_date_format_handler_method, &next_activate_date}; format_writer np_fw = {zone_policy_date_format_handler_method, &next_publish_date}; format_writer nc_fw = {zone_policy_date_format_handler_method, &next_creation_date}; log_debug("zone_policy_table_init: next c:%w => p:%w => a:%w", &nc_fw, &np_fw, &na_fw); #endif if(ISOK(ret = zone_policy_date_init_from_date(&tbl->inactive, &next_activate_date, &with->inactive))) { #if HAS_DS_PUBLICATION_SUPPORT if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->ds_add, &tbl->created, &with->ds_add))) { ret = zone_policy_date_init_at_next_date(&tbl->ds_del, &tbl->ds_add, &with->ds_del); } } #else ret = zone_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete); #if DEBUG format_writer i_fw = {zone_policy_date_format_handler_method, &tbl->inactive}; format_writer d_fw = {zone_policy_date_format_handler_method, &tbl->delete}; log_debug("zone_policy_table_init_from_date: base i:%w => d:%w", &i_fw, &d_fw); #endif #endif } } } } } } } } else if(with->created.type.type == ZONE_POLICY_RELATIVE) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->created, from, &with->created))) // here ! { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->activate, zone_policy_table_get_date_by_index(tbl, with->activate.relative.relativeto), &with->activate))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->inactive, zone_policy_table_get_date_by_index(tbl, with->inactive.relative.relativeto), &with->inactive))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->delete, zone_policy_table_get_date_by_index(tbl, with->delete.relative.relativeto), &with->delete))) { } } } } } } else { ret = POLICY_ILLEGAL_DATE_TYPE; } return ret; } ya_result zone_policy_table_init_from_created_epoch(zone_policy_table_s *tbl, zone_policy_table_s *with, time_t created_epoch) { ya_result ret; if(FAIL(ret = zone_policy_date_init_from_epoch(&tbl->created, created_epoch))) { return ret; } if(with->created.type.type == ZONE_POLICY_RULE) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->activate, &tbl->publish, &with->activate))) { #if DEBUG format_writer c_fw = {zone_policy_date_format_handler_method, &tbl->created}; format_writer p_fw = {zone_policy_date_format_handler_method, &tbl->publish}; format_writer a_fw = {zone_policy_date_format_handler_method, &tbl->activate}; log_debug("zone_policy_table_init: base %w => %w => %w", &c_fw, &p_fw, &a_fw); #endif // compute the future key timings to ensure there will be no period without a signature zone_policy_date next_creation_date; zone_policy_date next_publish_date; zone_policy_date next_activate_date; if(ISOK(ret = zone_policy_date_init_at_next_date(&next_creation_date, &tbl->activate, &with->created))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&next_publish_date, &next_creation_date, &with->publish))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&next_activate_date, &next_publish_date, &with->activate))) { #if DEBUG format_writer na_fw = {zone_policy_date_format_handler_method, &next_activate_date}; format_writer np_fw = {zone_policy_date_format_handler_method, &next_publish_date}; format_writer nc_fw = {zone_policy_date_format_handler_method, &next_creation_date}; log_debug("zone_policy_table_init: next %w => %w => %w", &nc_fw, &np_fw, &na_fw); #endif if(ISOK(ret = zone_policy_date_init_from_date(&tbl->inactive, &next_activate_date, &with->inactive))) { #if HAS_DS_PUBLICATION_SUPPORT if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->ds_add, &tbl->created, &with->ds_add))) { ret = zone_policy_date_init_at_next_date(&tbl->ds_del, &tbl->ds_add, &with->ds_del); } } #else ret = zone_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete); #endif } } } } } } } else if(with->created.type.type == ZONE_POLICY_RELATIVE) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->activate, zone_policy_table_get_date_by_index(tbl, with->activate.relative.relativeto), &with->activate))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->inactive, zone_policy_table_get_date_by_index(tbl, with->inactive.relative.relativeto), &with->inactive))) { if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->delete, zone_policy_table_get_date_by_index(tbl, with->delete.relative.relativeto), &with->delete))) { } } } } } else { ret = POLICY_ILLEGAL_DATE_TYPE; } return ret; } ya_result zone_policy_table_init_from_epoch(zone_policy_table_s *tbl, zone_policy_table_s *with, time_t created_epoch) { ya_result ret; zone_policy_date epoch_date; zone_policy_date_init_from_epoch(&epoch_date, created_epoch); ret = zone_policy_table_init_from_date(tbl, with, &epoch_date); return ret; } static bool zone_policy_key_roll_matches(const struct dnssec_policy_key_suite *kr, const dnssec_key *key) { yassert((kr->key->flags == DNSKEY_FLAGS_KSK) || (kr->key->flags == DNSKEY_FLAGS_ZSK)); if(dnskey_get_algorithm(key) == kr->key->algorithm) { // matches flags if((dnskey_get_flags(key) & DNSKEY_FLAGS_KSK) == kr->key->flags) { int key_size = dnskey_get_size(key); if((key_size - kr->key->size) < 48) { // algorithm, flags and size are matching // now what about the times if((key->epoch_created != 0) && (key->epoch_publish != 0) && (key->epoch_activate != 0) && (key->epoch_inactive != 0) && (key->epoch_delete != 0)) { log_debug1("dnssec-policy: %s: %s: key %05d/%d timings: %T %T %T %T %T", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), key->epoch_created, key->epoch_publish, key->epoch_activate, key->epoch_inactive, key->epoch_delete); zone_policy_table_s key_tbl; if(ISOK(zone_policy_table_init_from_created_epoch(&key_tbl, &kr->roll->time_table, key->epoch_created))) { time_t key_created = 0, key_publish = 0, key_activate = 0, key_inactive = 0, key_delete = 0; zone_policy_date_get_epoch(&key_tbl.created, &key_created); zone_policy_date_get_epoch(&key_tbl.publish, &key_publish); zone_policy_date_get_epoch(&key_tbl.activate, &key_activate); zone_policy_date_get_epoch(&key_tbl.inactive, &key_inactive); zone_policy_date_get_epoch(&key_tbl.delete, &key_delete); s64 pait = key_inactive - key_activate; s64 kait = key->epoch_inactive - key->epoch_activate; s64 dait = labs(pait - kait); s64 pidt = key_delete - key_inactive; s64 kidt = key->epoch_delete - key->epoch_inactive; s64 didt = labs(pidt - kidt); s64 dc = labs(key_created - key->epoch_created); s64 dp = labs(key_publish - key->epoch_publish); s64 da = labs(key_activate - key->epoch_activate); s64 di = labs(key_inactive - key->epoch_inactive); s64 dd = labs(key_delete - key->epoch_delete); //bool match = (/*dc < KEY_POLICY_EPOCH_MATCH_MARGIN &&*/ dp < KEY_POLICY_EPOCH_MATCH_MARGIN && da < KEY_POLICY_EPOCH_MATCH_MARGIN && di < KEY_POLICY_EPOCH_MATCH_MARGIN && dd < KEY_POLICY_EPOCH_MATCH_MARGIN); // This checks if the key matches were it counts. We already know flags & size are a match, now if it lives long enough and is deleted in time, then it is a match. // The next key generation will have to align to these timings to find when will be the next one. bool match = (dait < KEY_POLICY_EPOCH_MATCH_MARGIN) && (didt < KEY_POLICY_EPOCH_MATCH_MARGIN); log_debug2("dnssec-policy: %s: %s: key %05d/%d pkd: ai=%lli id=%lli, with a margin of %lli", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), dait, didt, KEY_POLICY_EPOCH_MATCH_MARGIN); log_debug2("dnssec-policy: %s: %s: key %05d/%d deltas: (%lli) %lli %lli %lli %lli, with a margin of %lli", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), dc, dp, da, di, dd, KEY_POLICY_EPOCH_MATCH_MARGIN); log_debug1("dnssec-policy: %s: %s: key %05d/%d expects: %T %T %T %T %T : %s", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), key_created, key_publish, key_activate, key_inactive, key_delete, ((match)?"MATCH":"DIFFERS")); return match; } // else zone_policy_table_init_from_created_epoch failed and something is wrong => false else { log_err("dnssec-policy: %s: %s: key %05d/%d matching triggered an error in zone_policy_table_init_from_created_epoch", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags)); } } else { log_debug1("dnssec-policy: %s: %s: key %05d/%d is not a match as it has no time table (skipping)", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags)); } } else { log_debug1("dnssec-policy: %s: %s: key %05d/%d of size %i is not a match as the expected size is %i (skipping for this key roll)", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), key_size, kr->key->size); } } else { log_debug1("dnssec-policy: %s: %s: key %05d/%d is not a match as the expected flags is %i (skipping for this key roll)", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), ntohs(kr->key->flags)); } } else { log_debug1("dnssec-policy: %s: %s: key %05d/%d is not a match as the expected algorithm is %i (skipping for this key roll)", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), kr->key->algorithm); } return FALSE; } /** * Compares keys by activation time, inactivation time and tag. * Handles 0 epoch as "never" (as expected) * * @param a_ * @param b_ * @return */ static int zone_policy_dnssec_key_ptr_vector_qsort_by_activation_time_callback(const void *a_, const void *b_) { const dnssec_key *a = (const dnssec_key*)a_; const dnssec_key *b = (const dnssec_key*)b_; s64 a_a = a->epoch_activate; if(a_a == 0) { a_a = MAX_S64; } s64 b_a = b->epoch_activate; if(b_a == 0) { b_a = MAX_S64; } s64 r = a_a - b_a; if(r == 0) { s64 a_i = a->epoch_inactive; if(a_i == 0) { a_i = MAX_S64; } s64 b_i = b->epoch_inactive; if(b_i == 0) { b_i = MAX_S64; } r = a_i - b_i; if(r == 0) { r = dnskey_get_tag_const(a) - dnskey_get_tag_const(b); } } return r; } static void zone_policy_log_debug_key(const char *prefix, const dnssec_key *key) { EPOCHZ_DEF2(created, key->epoch_created); EPOCHZ_DEF2(publish, key->epoch_publish); EPOCHZ_DEF2(activate, key->epoch_activate); EPOCHZ_DEF2(inactive, key->epoch_inactive); EPOCHZ_DEF2(delete, key->epoch_delete); #if 0 /* fix */ #else log_debug("%sK%{dnsname}+%03d+%05d/%d created=%1w publish=%1w activate=%1w inactive=%1w delete=%1w", prefix, key->owner_name, key->algorithm, dnskey_get_tag_const(key), ntohs(key->flags), EPOCHZ_REF(created), EPOCHZ_REF(publish), EPOCHZ_REF(activate), EPOCHZ_REF(inactive), EPOCHZ_REF(delete)); #endif } static struct service_s dnssec_policy_command_service_handler = UNINITIALIZED_SERVICE; static threaded_dll_cw dnssec_policy_command_service_handler_queue; static bool dnssec_policy_command_service_handler_initialised = FALSE; static ya_result dnssec_policy_alarm_command_generate_key(dnssec_policy_queue *cmd); void dnssec_policy_queue_delete_command(dnssec_policy_queue *cmd); static int dnssec_policy_command_service(struct service_worker_s *worker) { log_info("dnssec-policy: command execution service started"); while(service_should_run(worker)) { dnssec_policy_queue *cmd = (dnssec_policy_queue*)threaded_dll_cw_dequeue(&dnssec_policy_command_service_handler_queue); if(cmd == NULL) { break; } switch(cmd->command) { case DNSSEC_POLICY_COMMAND_INIT: { #if DEBUG log_debug("dnssec-policy: init command"); #endif dnssec_policy_queue_delete_command(cmd); break; } case DNSSEC_POLICY_COMMAND_GENERATE_KEY: { #if DEBUG log_debug("dnssec-policy: generate key command"); #endif dnssec_policy_alarm_command_generate_key(cmd); // deletes the command break; } default: { log_err("dnssec-policy: unknown command %i", cmd->command); dnssec_policy_queue_delete_command(cmd); break; } } } log_info("dnssec-policy: command execution service stopped"); return SUCCESS; } void dnssec_policy_command_service_start() { ya_result ret; if(!dnssec_policy_command_service_handler_initialised) { if(ISOK(ret = service_init_ex(&dnssec_policy_command_service_handler, dnssec_policy_command_service, "dpcmd", 8))) { threaded_dll_cw_init(&dnssec_policy_command_service_handler_queue, 1000000); dnssec_policy_command_service_handler_initialised = TRUE; } service_start(&dnssec_policy_command_service_handler); } } void dnssec_policy_command_service_stop() { threaded_dll_cw_finalize(&dnssec_policy_command_service_handler_queue); } void dnssec_policy_command_queue(dnssec_policy_queue *cmd) { threaded_dll_cw_enqueue(&dnssec_policy_command_service_handler_queue, cmd); } static ya_result dnssec_policy_alarm_command_generate_key(dnssec_policy_queue *cmd) { zone_policy_table_s tbl; zone_policy_date from; const char *algorithm_name = dns_encryption_algorithm_get_name(cmd->parameters.generate_key.suite->key->algorithm); char domain[MAX_DOMAIN_LENGTH]; // from ... the time to take as a base for generation, which is the previous log_info("dnssec-policy: %{dnsname}: generating %s key of size %hu with time parameter %T", cmd->origin, algorithm_name, cmd->parameters.generate_key.suite->key->size, cmd->epoch); dnsname_to_cstr(domain, cmd->origin); ya_result ret; if(FAIL(ret = zone_policy_date_init_from_epoch(&from, cmd->epoch))) { log_err("dnssec-policy: %{dnsname}: failed to generate %s key of size %hu with time parameter %T: %r", cmd->origin, algorithm_name, cmd->parameters.generate_key.suite->key->size, cmd->epoch, ret); zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite); dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite); cmd->parameters.generate_key.suite = NULL; dnssec_policy_queue_delete_command(cmd); return ret; } if(FAIL(ret = zone_policy_table_init_from_date(&tbl, &cmd->parameters.generate_key.suite->roll->time_table, &from))) { log_err("dnssec-policy: %{dnsname}: failed to generate time-table for %s key of size %hu with time parameter %T: %r", cmd->origin, algorithm_name, cmd->parameters.generate_key.suite->key->size, cmd->epoch, ret); zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite); dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite); cmd->parameters.generate_key.suite = NULL; dnssec_policy_queue_delete_command(cmd); return ret; } log_debug("dnssec-policy: %{dnsname}: time-table for %s key of size %hu with time parameter %T generated", cmd->origin, algorithm_name, cmd->parameters.generate_key.suite->key->size, cmd->epoch); time_t created_epoch; time_t publish_epoch; time_t activate_epoch; time_t deactivate_epoch; time_t unpublish_epoch; if(FAIL(ret = zone_policy_date_get_epoch(&tbl.created, &created_epoch))) // note: created should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (created_epoch) returned an error: %r", ret); zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite); dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite); cmd->parameters.generate_key.suite = NULL; dnssec_policy_queue_delete_command(cmd); return ret; } if(FAIL(ret = zone_policy_date_get_epoch(&tbl.publish, &publish_epoch))) // note: publish should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (publish_epoch) returned an error: %r", ret); zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite); dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite); cmd->parameters.generate_key.suite = NULL; dnssec_policy_queue_delete_command(cmd); return ret; } if(FAIL(ret = zone_policy_date_get_epoch(&tbl.activate, &activate_epoch))) // note: activate should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (activate_epoch) returned an error: %r", ret); zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite); dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite); cmd->parameters.generate_key.suite = NULL; dnssec_policy_queue_delete_command(cmd); return ret; } if(FAIL(ret = zone_policy_date_get_epoch(&tbl.inactive, &deactivate_epoch))) // note: deactivate should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (deactivate_epoch) returned an error: %r", ret); zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite); dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite); cmd->parameters.generate_key.suite = NULL; dnssec_policy_queue_delete_command(cmd); return ret; } if(FAIL(ret = zone_policy_date_get_epoch(&tbl.delete, &unpublish_epoch))) // note: unpublish should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (unpublish_epoch) returned an error: %r", ret); zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite); dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite); cmd->parameters.generate_key.suite = NULL; dnssec_policy_queue_delete_command(cmd); return ret; } dnskey_smart_fields_t smart_fields; smart_fields.created_epoch = created_epoch; smart_fields.publish_epoch = publish_epoch; smart_fields.activate_epoch = activate_epoch; smart_fields.deactivate_epoch = deactivate_epoch; smart_fields.unpublish_epoch = unpublish_epoch; smart_fields.fields = DNSKEY_KEY_HAS_SMART_FIELD_CREATED|DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE; dnssec_key *key; ret = dnssec_keystore_new_key(cmd->parameters.generate_key.suite->key->algorithm, cmd->parameters.generate_key.suite->key->size, cmd->parameters.generate_key.suite->key->flags|DNSKEY_FLAGS_ZSK, domain, &smart_fields, &key); if(ISOK(ret)) { // note: the keystore has already stored the key on disk log_info("dnssec-policy: %{dnsname}: key K%{dnsname}+%03d+%05d/%d generated from %T: created at %T, publish at %T, activate at %T, inactive at %T, delete at %T", cmd->origin, cmd->origin, key->algorithm, dnskey_get_tag(key), ntohs(key->flags), cmd->epoch, key->epoch_created, key->epoch_publish, key->epoch_activate, key->epoch_inactive, key->epoch_delete); #if HAS_EVENT_DYNAMIC_MODULE if(dynamic_module_dnskey_interface_chain_available()) { dynamic_module_on_dnskey_created(key); } #endif zdb_zone* zone = zdb_acquire_zone_read_from_fqdn(g_config->database, cmd->origin); if(zone != NULL) { database_service_zone_dnskey_set_alarms(zone); zdb_zone_release(zone); } zone_desc_s *zone_desc = cmd->parameters.generate_key.zone_desc; dnssec_policy_key_suite *kr = cmd->parameters.generate_key.suite; if(kr->roll->time_table.created.type.type == ZONE_POLICY_RELATIVE) { if(FAIL(ret = dnssec_policy_queue_add_generate_key_create_at(zone_desc, kr, key->epoch_created))) { log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from previous key: %r", zone_origin(zone_desc), kr->name, ret); } } else if(kr->roll->time_table.created.type.type == ZONE_POLICY_RULE) { if(FAIL(ret = dnssec_policy_queue_add_generate_key_active_at(zone_desc, kr, key->epoch_inactive, NULL))) { log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from previous end period: %r", zone_origin(zone_desc), kr->name, ret); } } dnskey_release(key); } else { log_err("dnssec-policy: %{dnsname}: failed to generate key: %r This is likely to break the policy maintenance state for the zone.", cmd->origin, ret); // try to run the policies again in one minute zone_policy_process_alarm_arm(cmd->parameters.generate_key.zone_desc, 60); } zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite); dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite); cmd->parameters.generate_key.suite = NULL; dnssec_policy_queue_delete_command(cmd); return ret; } static ya_result dnssec_policy_alarm_handler(void *args, bool cancel) { dnssec_policy_queue *cmd = (dnssec_policy_queue*)args; #if DEBUG log_debug("dnssec-policy: alarm(%p,%i)", cmd, cancel); #endif if(cancel) { dnssec_policy_queue_remove_command(cmd); dnssec_policy_queue_delete_command(cmd); return SUCCESS; } dnssec_policy_command_queue(cmd); return SUCCESS; } static void zone_policy_nsec_enable(zdb_zone *zone) { //zdb_zone_double_lock(); zdb_zone_double_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC); if(zdb_rr_label_has_rrset(zone->apex, TYPE_DNSKEY)) { nsec_zone_set_status(zone, ZDB_ZONE_MUTEX_DYNUPDATE, NSEC_ZONE_ENABLED|NSEC_ZONE_GENERATING); } zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); } static void zone_policy_nsec3_enable(zdb_zone *zone, dnssec_denial *denial) { u8 *salt; u8 salt_len; u8 flags = (denial->optout)?1:0; u8 current_status = 0; u8 salt_buffer[256]; zdb_zone_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); if(denial->salt != NULL) { salt = denial->salt; salt_len = denial->salt_length; } else { ya_result matched = nsec3_zone_get_first_salt_matching(zone, denial->algorithm, flags, denial->iterations, denial->salt_length, salt_buffer); if(matched == 0) { random_ctx rnd = random_init_auto(); salt = &salt_buffer[0]; salt_len = denial->salt_length; for(int i = 0; i < salt_len; ++i) { salt[i] = random_next(rnd); } random_finalize(rnd); } else { salt = &salt_buffer[0]; salt_len = denial->salt_length; } } if(zdb_rr_label_has_rrset(zone->apex, TYPE_DNSKEY)) { ya_result got_status = nsec3_zone_get_status(zone, denial->algorithm, flags, denial->iterations, salt, salt_len, ¤t_status); zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); if(got_status == 1) { if(current_status & NSEC3_ZONE_ENABLED) { return; } } zdb_zone_double_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); nsec3_zone_set_status(zone, ZDB_ZONE_MUTEX_DYNUPDATE, denial->algorithm, flags, denial->iterations, salt, salt_len, NSEC3_ZONE_ENABLED|NSEC3_ZONE_GENERATING); zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE); } else { zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER); } } ya_result zone_policy_roll_create_from_rules(const char *id, const zone_policy_rule_definition_s *generate, const zone_policy_rule_definition_s *publish, const zone_policy_rule_definition_s *activate, const zone_policy_rule_definition_s *inactive, const zone_policy_rule_definition_s *remove, const zone_policy_rule_definition_s *ds_publish, const zone_policy_rule_definition_s *ds_remove) { log_debug("dnssec-policy-roll: %s: (rules stuff)", id); dnssec_policy_roll *dpr; ZALLOC_OBJECT_OR_DIE( dpr, dnssec_policy_roll, DPOLROLL_TAG); dpr->name = strdup(id); group_mutex_write_lock(&dnssec_policy_roll_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_policy_roll_set, dpr->name); if(node->value != NULL) { dnssec_policy_roll_release((dnssec_policy_roll*)node->value); node->key = dpr->name; } zone_policy_rule_init(&dpr->time_table.created.rule, generate); zone_policy_rule_init(&dpr->time_table.publish.rule, publish); zone_policy_rule_init(&dpr->time_table.activate.rule, activate); zone_policy_rule_init(&dpr->time_table.inactive.rule, inactive); zone_policy_rule_init(&dpr->time_table.delete.rule, remove); #if HAS_DS_PUBLICATION_SUPPORT zone_policy_rule_init(&dpr->time_table.ds_add.rule, ds_publish); zone_policy_rule_init(&dpr->time_table.ds_del.rule, ds_remove); #else (void)ds_publish; (void)ds_remove; #endif dpr->rc = 1; node->value = dpr; group_mutex_write_unlock(&dnssec_policy_roll_set_mtx); return 0; } ya_result zone_policy_roll_create_from_relatives(const char *id, const zone_policy_relative_s *generate, u8 generate_from, const zone_policy_relative_s *publish, u8 publish_from, const zone_policy_relative_s *activate, u8 activate_from, const zone_policy_relative_s *inactive, u8 inactive_from, const zone_policy_relative_s *remove, u8 remove_from #if HAS_DS_PUBLICATION_SUPPORT , const zone_policy_relative_s *ds_publish, u8 ds_publish_from, const zone_policy_relative_s *ds_remove, u8 ds_remove_from #endif ) { log_debug("dnssec-policy-roll: %s: (relative stuff)", id); if(generate->seconds < 60) { log_err("dnssec-policy: %s: generate parameter cannot be less than one minute", id); return POLICY_ILLEGAL_DATE_PARAMETERS; } if(inactive->seconds - activate->seconds < 60) { log_err("dnssec-policy: %s: key appears to not be activated for even one minute", id); return POLICY_ILLEGAL_DATE_PARAMETERS; } if(generate->seconds < 3600) { log_warn("dnssec-policy: %s: key is generated every %i seconds. Keys are expected to be generated every few weeks, months or years.", id, generate->seconds); } if(inactive->seconds - activate->seconds < generate->seconds) { log_warn("dnssec-policy: %s: key appears to not be activated for less time than the generation period", id); } dnssec_policy_roll *dpr; ZALLOC_OBJECT_OR_DIE( dpr, dnssec_policy_roll, DPOLROLL_TAG); dpr->name = strdup(id); group_mutex_write_lock(&dnssec_policy_roll_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_policy_roll_set, dpr->name); if(node->value != NULL) { dnssec_policy_roll_release((dnssec_policy_roll*)node->value); node->value = NULL; } dpr->time_table.created.relative = *generate; dpr->time_table.publish.relative = *publish; dpr->time_table.activate.relative = *activate; dpr->time_table.inactive.relative = *inactive; dpr->time_table.delete.relative = *remove; dpr->time_table.created.relative.seconds += 59; dpr->time_table.created.relative.seconds -= (dpr->time_table.created.relative.seconds % 60); dpr->time_table.publish.relative.seconds += 59; dpr->time_table.publish.relative.seconds -= (dpr->time_table.publish.relative.seconds % 60); dpr->time_table.activate.relative.seconds += 59; dpr->time_table.activate.relative.seconds -= (dpr->time_table.activate.relative.seconds % 60); dpr->time_table.inactive.relative.seconds += 59; dpr->time_table.inactive.relative.seconds -= (dpr->time_table.inactive.relative.seconds % 60); dpr->time_table.delete.relative.seconds += 59; dpr->time_table.delete.relative.seconds -= (dpr->time_table.delete.relative.seconds % 60); #if HAS_DS_PUBLICATION_SUPPORT dpr->time_table.ds_add.relative = *ds_publish; dpr->time_table.ds_del.relative = *ds_remove; #endif yassert(publish_from <= ZONE_POLICY_RELATIVE_TO_GENERATE); yassert(activate_from <= ZONE_POLICY_RELATIVE_TO_PUBLISH); yassert(inactive_from <= ZONE_POLICY_RELATIVE_TO_INACTIVE); yassert(remove_from <= ZONE_POLICY_RELATIVE_TO_REMOVE); #if HAS_DS_PUBLICATION_SUPPORT yassert(ds_publish_from <= ZONE_POLICY_RELATIVE_TO_DS_PUBLISH); yassert(ds_remove_from <= ZONE_POLICY_RELATIVE_TO_DS_REMOVE); #endif dpr->time_table.created.relative.relativeto = generate_from; dpr->time_table.publish.relative.relativeto = publish_from; dpr->time_table.activate.relative.relativeto = activate_from; dpr->time_table.inactive.relative.relativeto = inactive_from; dpr->time_table.delete.relative.relativeto = remove_from; #if HAS_DS_PUBLICATION_SUPPORT dpr->time_table.ds_add.relative.relativeto = ds_publish_from; dpr->time_table.ds_del.relative.relativeto = ds_remove_from; #endif dpr->rc = 1; node->key = dpr->name; node->value = dpr; group_mutex_write_unlock(&dnssec_policy_roll_set_mtx); return 0; } dnssec_policy_roll * dnssec_policy_roll_acquire_from_name(const char *id) { dnssec_policy_roll *dpr = NULL; group_mutex_read_lock(&dnssec_policy_roll_set_mtx); ptr_node *node = ptr_set_find(&dnssec_policy_roll_set, id); if(node != NULL) { dpr = (dnssec_policy_roll*)node->value; group_mutex_write_lock(&dnssec_policy_roll_mtx); ++dpr->rc; group_mutex_write_unlock(&dnssec_policy_roll_mtx); } group_mutex_read_unlock(&dnssec_policy_roll_set_mtx); return dpr; } ya_result dnssec_policy_roll_test_all(time_t active_at, u32 duration_seconds, bool print_text, bool log_text) { ya_result ret = SUCCESS; group_mutex_read_lock(&dnssec_policy_roll_set_mtx); ptr_set_iterator iter; ptr_set_iterator_init(&dnssec_policy_roll_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); if(node->value != NULL) { dnssec_policy_roll *dpr = (dnssec_policy_roll*)node->value; if(FAIL(ret = dnssec_policy_roll_test(dpr, active_at, duration_seconds, print_text, log_text))) { break; } } } group_mutex_read_unlock(&dnssec_policy_roll_set_mtx); return ret; } dnssec_policy_roll * dnssec_policy_roll_acquire_from_index(int index) { dnssec_policy_roll *dpr = NULL; if(index >= 0) { group_mutex_read_lock(&dnssec_policy_roll_set_mtx); ptr_set_iterator iter; ptr_set_iterator_init(&dnssec_policy_roll_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); if(index == 0) { if(node->value != NULL) { dpr = (dnssec_policy_roll*)node->value; group_mutex_write_lock(&dnssec_policy_roll_mtx); ++dpr->rc; group_mutex_write_unlock(&dnssec_policy_roll_mtx); } break; } --index; } group_mutex_read_unlock(&dnssec_policy_roll_set_mtx); } return dpr; } void dnssec_policy_roll_release(dnssec_policy_roll *dpr) { group_mutex_write_lock(&dnssec_policy_roll_mtx); if(--dpr->rc == 0) { // destroy the table if(dpr->time_table.created.type.type == ZONE_POLICY_RULE) { zone_policy_rule_finalize(&dpr->time_table.created.rule); } if(dpr->time_table.publish.type.type == ZONE_POLICY_RULE) { zone_policy_rule_finalize(&dpr->time_table.publish.rule); } if(dpr->time_table.activate.type.type == ZONE_POLICY_RULE) { zone_policy_rule_finalize(&dpr->time_table.activate.rule); } if(dpr->time_table.inactive.type.type == ZONE_POLICY_RULE) { zone_policy_rule_finalize(&dpr->time_table.inactive.rule); } if(dpr->time_table.delete.type.type == ZONE_POLICY_RULE) { zone_policy_rule_finalize(&dpr->time_table.delete.rule); } #if HAS_DS_PUBLICATION_SUPPORT if(dpr->time_table.ds_add.type.type == ZONE_POLICY_RULE) { zone_policy_rule_finalize(&dpr->time_table.ds_add.rule); } if(dpr->time_table.ds_del.type.type == ZONE_POLICY_RULE) { zone_policy_rule_finalize(&dpr->time_table.ds_del.rule); } #endif free(dpr->name); ZFREE_OBJECT(dpr); } group_mutex_write_unlock(&dnssec_policy_roll_mtx); } dnssec_denial * dnssec_policy_denial_create(const char *id, u8 algorithm, u16 iterations, const u8 *salt, u8 salt_length, u32 resalting, bool optout) { log_debug("dnssec-policy-denial: %s: algorithm=%hhu, iterations=%hu, salt@%p, salt_length=%hhu, resalting=%u", id, algorithm, iterations, salt, salt_length, resalting); dnssec_denial *dd = NULL; ZALLOC_OBJECT_OR_DIE( dd, dnssec_denial, DPOLDNIL_TAG); dd->name = strdup(id); if(salt != NULL && salt_length > 0) { ZALLOC_ARRAY_OR_DIE(u8*, dd->salt, salt_length, DPOLSALT_TAG); memcpy(dd->salt, salt, salt_length); } else { dd->salt = NULL; } dd->resalting = resalting; dd->iterations = iterations; dd->algorithm = algorithm; dd->salt_length = salt_length; dd->optout = optout; dd->rc = 1; group_mutex_write_lock(&dnssec_denial_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_denial_set, dd->name); if(node->value != NULL) { dnssec_policy_denial_release((dnssec_denial*)node->value); } node->key = dd->name; node->value = dd; group_mutex_write_unlock(&dnssec_denial_set_mtx); return dd; } dnssec_denial * dnssec_policy_denial_acquire(const char *id) { dnssec_denial *dd = NULL; group_mutex_read_lock(&dnssec_denial_set_mtx); ptr_node *node = ptr_set_find(&dnssec_denial_set, id); if(node != NULL && node->value != NULL) { dd = (dnssec_denial*)node->value; group_mutex_write_lock(&dnssec_denial_mtx); ++dd->rc; group_mutex_write_unlock(&dnssec_denial_mtx); } group_mutex_read_unlock(&dnssec_denial_set_mtx); return dd; } void dnssec_policy_denial_release(dnssec_denial *dd) { if(dd == NULL) return; group_mutex_write_lock(&dnssec_denial_mtx); if(--dd->rc == 0) { if(dd->salt != NULL) { ZFREE_ARRAY(dd->salt, dd->salt_length); } free(dd->name); ZFREE_OBJECT(dd); } group_mutex_write_unlock(&dnssec_denial_mtx); } dnssec_policy_key * dnssec_policy_key_create(const char *id, u8 algorithm, u16 size, bool ksk, char* engine) { log_debug("dnssec-policy-key: %s: algorithm=%hhu, size=%hu, ksk=%i, engine=%s", id, algorithm, size, ksk, STRNULL(engine)); (void)engine; dnssec_policy_key *dpk = NULL; ZALLOC_OBJECT_OR_DIE( dpk, dnssec_policy_key, DPOLKEY_TAG); dpk->name = strdup(id); dpk->flags = (ksk)?DNSKEY_FLAGS_KSK:DNSKEY_FLAGS_ZSK; dpk->size = size; dpk->algorithm = algorithm; dpk->rc = 1; group_mutex_write_lock(&dnssec_policy_key_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_policy_key_set, dpk->name); if(node->value != NULL) { dnssec_policy_key_release((dnssec_policy_key*)node->value); node->key = dpk->name; } node->value = dpk; group_mutex_write_unlock(&dnssec_policy_key_set_mtx); return dpk; } dnssec_policy_key * dnssec_policy_key_acquire_from_name(const char *id) { dnssec_policy_key *dpk = NULL; group_mutex_read_lock(&dnssec_policy_key_set_mtx); ptr_node *node = ptr_set_find(&dnssec_policy_key_set, id); if(node != NULL && node->value != NULL) { dpk = (dnssec_policy_key*)node->value; group_mutex_write_lock(&dnssec_policy_key_mtx); ++dpk->rc; group_mutex_write_unlock(&dnssec_policy_key_mtx); } group_mutex_read_unlock(&dnssec_policy_key_set_mtx); return dpk; } void dnssec_policy_key_release(dnssec_policy_key *dpk) { group_mutex_write_lock(&dnssec_policy_key_mtx); if(--dpk->rc == 0) { free(dpk->name); ZFREE_OBJECT(dpk); } group_mutex_write_unlock(&dnssec_policy_key_mtx); } dnssec_policy_key_suite * dnssec_policy_key_suite_create(const char *id, dnssec_policy_key *dpk, dnssec_policy_roll *dpr) { log_debug("dnssec-policy-key-suite: %s: policy-key=%s, policy-roll=%s", id, dpk->name, dpr->name); dnssec_policy_key_suite *dpks = NULL; ZALLOC_OBJECT_OR_DIE( dpks, dnssec_policy_key_suite, DPOLKYST_TAG); dpks->name = strdup(id); dpks->key = dnssec_policy_key_acquire_from_name(dpk->name); dpks->roll = dnssec_policy_roll_acquire_from_name(dpr->name); dpks->rc = 1; group_mutex_write_lock(&dnssec_policy_key_suite_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_policy_key_suite_set, dpks->name); if(node->value != NULL) { dnssec_policy_key_suite_release((dnssec_policy_key_suite*)node->value); } node->key = dpks->name; node->value = dpks; group_mutex_write_unlock(&dnssec_policy_key_suite_set_mtx); return dpks; } dnssec_policy_key_suite * dnssec_policy_key_suite_acquire_from_name(const char *id) { dnssec_policy_key_suite *dpks = NULL; group_mutex_read_lock(&dnssec_policy_key_suite_set_mtx); ptr_node *node = ptr_set_find(&dnssec_policy_key_suite_set, id); if(node != NULL && node->value != NULL) { dpks = (dnssec_policy_key_suite*)node->value; group_mutex_write_lock(&dnssec_policy_key_suite_mtx); ++dpks->rc; group_mutex_write_unlock(&dnssec_policy_key_suite_mtx); } group_mutex_read_unlock(&dnssec_policy_key_suite_set_mtx); return dpks; } void dnssec_policy_key_suite_acquire(dnssec_policy_key_suite *dpks) { group_mutex_write_lock(&dnssec_policy_key_suite_mtx); ++dpks->rc; group_mutex_write_unlock(&dnssec_policy_key_suite_mtx); } void dnssec_policy_key_suite_release(dnssec_policy_key_suite *dpks) { group_mutex_write_lock(&dnssec_policy_key_suite_mtx); if(--dpks->rc == 0) { free(dpks->name); dnssec_policy_key_release(dpks->key); dnssec_policy_roll_release(dpks->roll); ZFREE_OBJECT(dpks); } group_mutex_write_unlock(&dnssec_policy_key_suite_mtx); } dnssec_policy * dnssec_policy_create(char *name, dnssec_denial *dd, ptr_vector *key_suite) { dnssec_policy *dp = NULL; log_debug("dnssec-policy: %s: denial=%s", name, (dd!=NULL)?dd->name:"nsec"); bool has_zsk = FALSE; ZALLOC_OBJECT_OR_DIE( dp, dnssec_policy, DNSECPOL_TAG); dp->name = strdup(name); dp->denial= (dd!=NULL)?dnssec_policy_denial_acquire(dd->name):NULL; ptr_vector_init_ex(&dp->key_suite, ptr_vector_size(key_suite)); for(int i = 0; i <= ptr_vector_last_index(key_suite); ++i) { dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)ptr_vector_get(key_suite, i); if((dpks->key->flags & DNSKEY_FLAGS_KSK) != DNSKEY_FLAGS_KSK) { has_zsk = TRUE; } dnssec_policy_key_suite *dpks_a = dnssec_policy_key_suite_acquire_from_name(dpks->name); yassert(dpks_a != NULL); for(int j = 0; j <= ptr_vector_last_index(&dp->key_suite); ++j) { dnssec_policy_key_suite* dpks_b = (dnssec_policy_key_suite*)ptr_vector_get(&dp->key_suite, j); if(dpks_a == dpks_b) { // dup log_warn("dnssec-policy: %s: key-suite %s is a duplicate entry", name, dpks->name); dnssec_policy_key_suite_release(dpks_a); dpks_a = NULL; break; } } if(dpks_a != NULL) { ptr_vector_append(&dp->key_suite, dpks_a); log_debug("dnssec-policy: %s: key-suite %s added", name, dpks->name); } } dp->rc = 1; if(has_zsk) { log_warn("dnssec-policy: %s: no key-signing-key in the key-suite", name); } group_mutex_write_lock(&dnssec_policy_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_policy_set, dp->name); if(node->value != NULL) { dnssec_policy_release((dnssec_policy*)node->value); node->key = dp->name; } node->value = dp; group_mutex_write_unlock(&dnssec_policy_set_mtx); return dp; } dnssec_policy * dnssec_policy_acquire_from_name(const char *id) { dnssec_policy *dp = NULL; group_mutex_read_lock(&dnssec_policy_set_mtx); ptr_node *node = ptr_set_find(&dnssec_policy_set, id); if(node != NULL && node->value != NULL) { dp = (dnssec_policy*)node->value; group_mutex_write_lock(&dnssec_policy_mtx); ++dp->rc; group_mutex_write_unlock(&dnssec_policy_mtx); } group_mutex_read_unlock(&dnssec_policy_set_mtx); return dp; } void dnssec_policy_acquire(dnssec_policy *dp) { group_mutex_write_lock(&dnssec_policy_mtx); ++dp->rc; group_mutex_write_unlock(&dnssec_policy_mtx); } void dnssec_policy_release(dnssec_policy *dp) { group_mutex_write_lock(&dnssec_policy_mtx); if(--dp->rc == 0) { free(dp->name); dnssec_policy_denial_release(dp->denial); for(int i = 0; i <= ptr_vector_last_index(&dp->key_suite); ++i) { dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)ptr_vector_get(&dp->key_suite, i); dnssec_policy_key_suite_release(dpks); } ptr_vector_destroy(&dp->key_suite); ZFREE_OBJECT(dp); } group_mutex_write_unlock(&dnssec_policy_mtx); } bool dnssec_policy_is_key_matching(dnssec_policy *dp, dnssec_key *key) { bool explicit_deactivate = dnskey_has_explicit_deactivate(key); if(!explicit_deactivate) { return FALSE; } bool explicit_delete = dnskey_has_explicit_delete(key); if(!explicit_delete) { return FALSE; } bool matching = FALSE; for(int i = 0; i <= ptr_vector_last_index(&dp->key_suite); ++i) { dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)ptr_vector_get(&dp->key_suite, i); if(dpks->key != NULL) { if(dpks->key->algorithm == dnskey_get_algorithm(key)) { if(dpks->key->flags == dnskey_get_flags(key)) { if(dpks->key->size == dnskey_get_size(key)) { matching = TRUE; break; } else if(abs((int)dpks->key->size - (int)dnskey_get_size(key)) < 16) { log_debug("key K%{dnsname}+%03i+%05i only loosely matches the '%s' policy", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), dp->name); matching = TRUE; break; } #if DEBUG else { log_debug("key not matching the '%s' policy because size %i differs from %i", dp->name, dpks->key->size, dnskey_get_size(key)); } #endif } } } } return matching; } bool dnssec_policy_defines_ksk(dnssec_policy *dp) { for(int i = 0; i <= ptr_vector_last_index(&dp->key_suite); ++i) { dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)ptr_vector_get(&dp->key_suite, i); if(dpks->key != NULL) { if(dpks->key->flags == DNSKEY_FLAGS_KSK) { return TRUE; } } } return FALSE; } ya_result dnssec_policy_zone_desc_config(const char *value, void *dest, anytype sizeoftarget) { (void)sizeoftarget; dnssec_policy **dp = (dnssec_policy**)dest; if(*dp != NULL) { dnssec_policy_release(*dp); } if(value != NULL) { *dp = dnssec_policy_acquire_from_name(value); return (*dp != NULL)?SUCCESS:POLICY_UNDEFINED; } else { return POLICY_NULL_REQUESTED; } } static void zone_policy_process_release_keys_cb(void *ptr) { dnssec_key *key = (dnssec_key*)ptr; if(key != NULL) { dnskey_release(key); } } //////////////////////////////////////////////////////////////////////////////////////////////// // // This is where yadifad and the keyroll fundamentally differs // //////////////////////////////////////////////////////////////////////////////////////////////// /** * Sets the DNSSEC mode of the zone using the policy. */ ya_result zone_policy_process_dnssec_chain(zone_desc_s *zone_desc) { zdb_zone *zone = zone_desc->loaded_zone; if(zone == NULL) { return INVALID_STATE_ERROR; } const dnssec_policy *policy = zone_desc->dnssec_policy; if(policy == NULL) { return SUCCESS; // nothing to do } u8 zone_dnssec_type = zone_policy_guess_dnssec_type(zone); if(policy->denial == NULL) { // zone is expected to be NSEC zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC); switch(zone_dnssec_type) { case ZONE_DNSSEC_FL_NOSEC: { // generate NSEC now log_info("dnssec-policy: %{dnsname}: zone will be secured with NSEC", zone_origin(zone_desc)); zone_policy_nsec_enable(zone); break; } case ZONE_DNSSEC_FL_NSEC: { // do nothing if((zone->nsec.nsec->children.lr.right == NULL) && (zone->nsec.nsec->children.lr.left == NULL)) { log_info("dnssec-policy: %{dnsname}: zone is NSEC, chain is probably incomplete", zone_origin(zone_desc)); zone_policy_nsec_enable(zone); } else { log_info("dnssec-policy: %{dnsname}: zone is NSEC", zone_origin(zone_desc)); } break; } case ZONE_DNSSEC_FL_NSEC3: case ZONE_DNSSEC_FL_NSEC3_OPTOUT: { log_warn("dnssec-policy: %{dnsname}: zone is secured by NSEC3 but policy is made for NSEC", zone_origin(zone_desc)); break; } } } else { if(policy->denial->optout) { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT); } else { zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3); } // zone is expected to be NSEC3 switch(zone_dnssec_type) { case ZONE_DNSSEC_FL_NOSEC: { // generate NSEC now log_info("dnssec-policy: %{dnsname}: zone will be secured with NSEC3", zone_origin(zone_desc)); zone_policy_nsec3_enable(zone, policy->denial); break; } case ZONE_DNSSEC_FL_NSEC: { // do nothing log_warn("dnssec-policy: %{dnsname}: zone is an NSEC type but policy is made for NSEC3", zone_origin(zone_desc)); break; } case ZONE_DNSSEC_FL_NSEC3: case ZONE_DNSSEC_FL_NSEC3_OPTOUT: { if((zone->nsec.nsec3->items->children.lr.left == NULL) && (zone->nsec.nsec3->items->children.lr.right == NULL)) { log_info("dnssec-policy: %{dnsname}: zone is NSEC3, chain is probably incomplete", zone_origin(zone_desc)); zone_policy_nsec3_enable(zone, policy->denial); } else { log_info("dnssec-policy: %{dnsname}: zone is NSEC3", zone_origin(zone_desc)); } break; } } } return SUCCESS; } ya_result zone_policy_process(zone_desc_s *zone_desc) { // the policy is referenced by the zone desc // and the zone desc by the parent // no need to acquire anything here ya_result final_ret = SUCCESS; ya_result ret; dnssec_policy_initialise(); log_debug("dnssec-policy: %{dnsname} process", zone_origin(zone_desc)); if(zone_desc->type != ZT_MASTER) { log_debug("dnssec-policy: %{dnsname} is not a master zone", zone_origin(zone_desc)); return INVALID_STATE_ERROR; // not a master zone } const dnssec_policy *policy = zone_desc->dnssec_policy; if(policy == NULL) { log_debug("dnssec-policy: %{dnsname} has no policy", zone_origin(zone_desc)); zone_lock(zone_desc, ZONE_LOCK_READONLY); zdb_zone *zone = zone_desc->loaded_zone; if(zone != NULL) { zdb_zone_acquire(zone); if(zdb_zone_isvalid(zone)) { /* if(zone_desc->dnssec_mode != 0) { zdb_zone_set_maintained(zone, TRUE); //zone_desc_dnssec_mode = zone_desc->dnssec_mode << ZDB_ZONE_DNSSEC_SHIFT; } */ } zdb_zone_release(zone); } zone_unlock(zone_desc, ZONE_LOCK_READONLY); return SUCCESS; } // Look in the commands for a full init. If one is present then nothing more can be done. if(dnssec_policy_queue_has_command_type(zone_origin(zone_desc), DNSSEC_POLICY_COMMAND_INIT)) { log_debug("dnssec-policy: %{dnsname} is already marked for full generation", zone_origin(zone_desc)); return SUCCESS; } const char *denial_name = (policy->denial == NULL)?"nsec":policy->denial->name; log_debug("dnssec-policy: %{dnsname} has policy %s/%s with %i keys", zone_origin(zone_desc), policy->name, denial_name, ptr_vector_size(&policy->key_suite)); // get the current DNSSEC status of the zone zone_lock(zone_desc, ZONE_LOCK_READONLY); zdb_zone *zone = zone_desc->loaded_zone; if(zone != NULL) { zdb_zone_acquire(zone); zone_unlock(zone_desc, ZONE_LOCK_READONLY); } else { log_warn("dnssec-policy: %{dnsname}: settings are not linked to a loaded zone", zone_origin(zone_desc)); zone_unlock(zone_desc, ZONE_LOCK_READONLY); return POLICY_ZONE_NOT_READY; } log_debug("dnssec-policy: %{dnsname} zone acquired", zone->origin); if(zdb_zone_isvalid(zone)) { zone->sig_validity_regeneration_seconds = zone_desc->signature.sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S; zone->sig_validity_interval_seconds = zone_desc->signature.sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S; zone->sig_validity_jitter_seconds = zone_desc->signature.sig_validity_jitter * SIGNATURE_VALIDITY_JITTER_S; #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS zone->sig_validity_regeneration_seconds = 90; zone->sig_validity_interval_seconds = 180; zone->sig_validity_jitter_seconds = 5; #endif zdb_zone_set_maintained(zone, TRUE); // set DNSSEC mode using the policy zone_policy_process_dnssec_chain(zone_desc); } else // zone is not valid { log_err("dnssec-policy: %{dnsname}: unable to manage DNSSEC status of invalid zone", zone_origin(zone_desc)); log_debug("dnssec-policy: %{dnsname} released", zone->origin); zdb_zone_release(zone); return INVALID_STATE_ERROR; } // enumerate the available keys and if they are in the zone and being used and so on. // KEEP, IGNORE, REMOVE ptr_vector key_roll_keys[DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM]; for(int i = 0; i < DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM; ++i) { ptr_vector_init_ex(&key_roll_keys[i], 0); // with an initial capacity set to 0, no allocation is made until at least one item is added } yassert(ptr_vector_size(&policy->key_suite) <= 8); for(int i = 0; ; ++i) { dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_at_index(zone_origin(zone_desc), i); if(key == NULL) { break; } zone_policy_log_debug_key("dnssec-policy: found ", key); /* * @note 20160425 edf -- care must be taken here, keys may be generated in an another thread. * also, a key can only effectively be found after its generation (which discards the idea of virtual key) * so whatever is done here, pending key creation tasks should be taken into account (other operations are "real time") * * If the key is expired, * ignore it (it should be handled by the smart signing). * If the key is out of the expected parameters (size/alg) and it is not acceptable, * edit the times of the keys and remember the smart signing should be triggered. * If the key is valid, keep it on the side. * */ if(dnskey_is_expired_now(key) || (key->epoch_publish == 0) || (key->epoch_inactive == 0)) { zone_policy_log_debug_key("dnssec-policy: ignore ", key); // this key is irrelevant. It will be released after this control block. } else { // for all key suite, if the key matches the suite, add the key to the suite array for(int j = 0; j <= ptr_vector_last_index(&policy->key_suite); ++j) { const struct dnssec_policy_key_suite *kr = (const struct dnssec_policy_key_suite*)ptr_vector_get(&policy->key_suite, j); if(zone_policy_key_suite_is_marked_processed(zone_desc, kr)) { continue; } if(zone_policy_key_roll_matches(kr, key)) { char tmp[512]; snformat(tmp,sizeof(tmp), "dnssec-policy: matches %s", policy->name); zone_policy_log_debug_key(tmp, key); dnskey_acquire(key); ptr_vector_append(&key_roll_keys[j], key); //zone_policy_key_suite_mark_processed(zone_desc, kr); } } } dnskey_release(key); } /* * For all key suites ... * * sort-out the remaining keys * trigger the generation of keys * * keys of the array are matching the policy */ for(int ksi = 0; ksi <= ptr_vector_last_index(&policy->key_suite); ++ksi) { struct dnssec_policy_key_suite *kr = (struct dnssec_policy_key_suite*)ptr_vector_get(&policy->key_suite, ksi); if(zone_policy_key_suite_is_marked_processed(zone_desc, kr)) { log_debug("dnssec-policy: %{dnsname}: %s: key suite is already being processed", zone_origin(zone_desc), kr->name); continue; } log_debug("dnssec-policy: %{dnsname}: %s: key suite has %i matching keys", zone_origin(zone_desc), kr->name, ptr_vector_size(&key_roll_keys[ksi])); if(ptr_vector_size(&key_roll_keys[ksi]) > 0) { // sort array by time if(ptr_vector_size(&key_roll_keys[ksi]) > 1) // avoids the call but ptr_vector_qsort already checks this { ptr_vector_qsort(&key_roll_keys[ksi], zone_policy_dnssec_key_ptr_vector_qsort_by_activation_time_callback); } // ensure we have continuity // start with a base period dnssec_key *previous_key = NULL; s64 previous_begin_period; s64 previous_next_period; s64 previous_end_period; { previous_key = (dnssec_key*)ptr_vector_get(&key_roll_keys[ksi], 0); #if DEBUG log_debug("dnssec-policy: %s: %s: key %05d/%d timings: %T %T %T %T %T [0]", previous_key->origin, kr->name, dnskey_get_tag_const(previous_key), ntohs(previous_key->flags), previous_key->epoch_created, previous_key->epoch_publish, previous_key->epoch_activate, previous_key->epoch_inactive, previous_key->epoch_delete); #endif database_service_zone_dnskey_set_alarms_for_key(zone, previous_key); previous_begin_period = previous_key->epoch_activate; previous_next_period = previous_begin_period; previous_end_period = previous_key->epoch_inactive; } log_debug("dnssec-policy: %{dnsname}: %s: first key will be inactive at %T", zone_origin(zone_desc), kr->name, previous_end_period); for(int i = 1; i <= ptr_vector_last_index(&key_roll_keys[ksi]); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&key_roll_keys[ksi], i); #if DEBUG log_debug("dnssec-policy: %s: %s: key %05d/%d timings: %T %T %T %T %T [%i]", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), key->epoch_created, key->epoch_publish, key->epoch_activate, key->epoch_inactive, key->epoch_delete, i); #endif previous_next_period = key->epoch_activate; // ensure the key chains with this interval if(key->epoch_activate > previous_end_period /*|| key->epoch_inactive < begin_period irrelevant because of the sort */) { // bad log_warn("dnssec-policy: timeline hole of %d seconds from %d to %d", key->epoch_activate - previous_end_period , previous_end_period, key->epoch_activate); zone_policy_log_debug_key("dnssec-policy: unchained ", key); /* * This case happens if there is at least one key K with timings in the future but the last key L of the valid chain is made inactive * before K is being made active. * * _ Create key(s) for the gap ? * _ Only create one key to fill that gap <- probably the best solution */ break; } else // the key chains fine { // if the previous key ends before this one we keep it if(previous_end_period < key->epoch_inactive) { database_service_zone_dnskey_set_alarms_for_key(zone, key); previous_key = key; previous_end_period = key->epoch_inactive; } else { // else the key is irrelevant for the chain } } } log_debug("dnssec-policy: %{dnsname}: %s: covered from %T to %T, last key activates at %T", zone_origin(zone_desc), kr->name, previous_begin_period, previous_end_period, previous_next_period); time_t now = time(NULL); if(previous_key->epoch_created <= now) { if(kr->roll->time_table.created.type.type == ZONE_POLICY_RELATIVE) { if(FAIL(ret = dnssec_policy_queue_add_generate_key_create_at(zone_desc, kr, previous_key->epoch_created))) { log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from previous key: %r", zone_origin(zone_desc), kr->name, ret); final_ret = ret; } } else if(kr->roll->time_table.created.type.type == ZONE_POLICY_RULE) { if(FAIL(ret = dnssec_policy_queue_add_generate_key_active_at(zone_desc, kr, previous_end_period, NULL))) { log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from previous end period: %r", zone_origin(zone_desc), kr->name, ret); final_ret = ret; } } else { log_err("dnssec-policy: %{dnsname}: %s: is not supported by this version of the policies", zone_origin(zone_desc), kr->name); } } ptr_vector_callback_and_destroy(&key_roll_keys[ksi], zone_policy_process_release_keys_cb); } else { // no key at all ? do a full init (with (re)signature) log_info("dnssec-policy: %{dnsname}: %s: will be completely initialised", zone_origin(zone_desc), kr->name); // for relative rules: do it now // for cron rules: generate it back-dated if(kr->roll->time_table.created.type.type == ZONE_POLICY_RELATIVE) { // now time_t now = time(NULL); // add the command, aim to be active "now" s64 delta = kr->roll->time_table.created.relative.seconds + // from the previous created key ... kr->roll->time_table.publish.relative.seconds + kr->roll->time_table.activate.relative.seconds ; if(delta > (s64)now) { delta = (s64)now; // } time_t first_key_create = now - (s32)delta; if(ISOK(ret = dnssec_policy_queue_add_generate_key_create_at(zone_desc, kr, first_key_create))) // works on any kind of dates { log_debug("dnssec-policy: %{dnsname}: %s: will generate a first key at %T minus %i = %T", zone_origin(zone_desc), kr->name, now, (s32)delta, first_key_create); // scan-build false-positive : kr isn't freed here (scan-build missed the acquire before the release) } else { log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation before now: %r", zone_origin(zone_desc), kr->name, ret); final_ret = ret; } } else if(kr->roll->time_table.created.type.type == ZONE_POLICY_RULE) { // compute the back-dated epoch time_t now = time(NULL); time_t will_be_inactive_at = 0; if(ISOK(ret = dnssec_policy_queue_add_generate_key_active_at(zone_desc, kr, now, &will_be_inactive_at))) // @note : only works on rules { log_debug("dnssec-policy: %{dnsname}: %s: will generate a first key that'll be inactive at %T", zone_origin(zone_desc), kr->name, will_be_inactive_at); // scan-build false-positive : kr isn't freed here (scan-build missed the acquire before the release) } else { log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from now: %r", zone_origin(zone_desc), kr->name, ret); final_ret = ret; } } else { log_err("dnssec-policy: %{dnsname}: %s: don't know how to proceed", zone_origin(zone_desc), kr->name); } } } // for all key suites zdb_zone_release(zone); log_debug("dnssec-policy: %{dnsname} released", zone_origin(zone_desc)); for(int i = 0; i < DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM; ++i) { ptr_vector_callback_and_destroy(&key_roll_keys[i], zone_policy_process_release_keys_cb); } // decide what to do return final_ret; // returns success or the last error from the key generation part } #define ALARM_KEY_POLICY_DELAYED_INITIALISATION ALARM_KEY_ZONE_NEXT_AVAILABLE_ID static ya_result zone_policy_process_alarm(void *args, bool cancel) { zone_desc_s *zone_desc = (zone_desc_s*)args; if(!cancel) { zone_policy_process(zone_desc); } zone_release(zone_desc); return SUCCESS; } static void zone_policy_process_alarm_arm(zone_desc_s *zone_desc, u32 delay_in_seconds) { if(zone_desc != NULL) { zone_lock(zone_desc, ZONE_LOCK_READONLY); zdb_zone *zone = zone_get_loaded_zone(zone_desc); if(zone != NULL) { zone_acquire(zone_desc); alarm_event_node *event = alarm_event_new( // zone refresh time(NULL) + delay_in_seconds, ALARM_KEY_POLICY_DELAYED_INITIALISATION, zone_policy_process_alarm, zone_desc, ALARM_DUP_REMOVE_LATEST, "database-zone-policy-alarm"); alarm_set(zone->alarm_handle, event); } zone_unlock(zone_desc, ZONE_LOCK_READONLY); } } void dnssec_policy_initialise() { dnssec_policy_command_service_start(); } void dnssec_policy_finalize() { ptr_set_iterator iter; // group_mutex_write_lock(&dnssec_policy_set_mtx); ptr_set_iterator_init(&dnssec_policy_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); dnssec_policy *dp = (dnssec_policy*)node->value; group_mutex_write_lock(&dnssec_policy_mtx); int rc = dp->rc; group_mutex_write_unlock(&dnssec_policy_mtx); if(rc == 1) { // destroy it log_debug("dnssec-policy: %s: policy released", dp->name); dnssec_policy_release(dp); } else { log_warn("dnssec-policy: %s: policy is still referenced %i times", dp->name, rc); } } ptr_set_destroy(&dnssec_policy_set); group_mutex_write_unlock(&dnssec_policy_set_mtx); // group_mutex_write_lock(&dnssec_policy_key_suite_set_mtx); ptr_set_iterator_init(&dnssec_policy_key_suite_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)node->value; group_mutex_write_lock(&dnssec_policy_key_suite_mtx); int rc = dpks->rc; group_mutex_write_unlock(&dnssec_policy_key_suite_mtx); if(rc == 1) { // destroy it log_debug("dnssec-policy: %s: key suite released", dpks->name); dnssec_policy_key_suite_release(dpks); } else { log_warn("dnssec-policy: %s: key suite is still referenced %i times", dpks->name, rc); } } ptr_set_destroy(&dnssec_policy_key_suite_set); group_mutex_write_unlock(&dnssec_policy_key_suite_set_mtx); // group_mutex_write_lock(&dnssec_policy_key_set_mtx); ptr_set_iterator_init(&dnssec_policy_key_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); dnssec_policy_key *dpk = (dnssec_policy_key*)node->value; group_mutex_write_lock(&dnssec_policy_key_mtx); int rc = dpk->rc; group_mutex_write_unlock(&dnssec_policy_key_mtx); if(rc == 1) { // destroy it log_debug("dnssec-policy: %s: key released", dpk->name); dnssec_policy_key_release(dpk); } else { log_warn("dnssec-policy: %s: key is still referenced %i times", dpk->name, rc); } } ptr_set_destroy(&dnssec_policy_key_set); group_mutex_write_unlock(&dnssec_policy_key_set_mtx); // group_mutex_write_lock(&dnssec_policy_roll_set_mtx); ptr_set_iterator_init(&dnssec_policy_roll_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); dnssec_policy_roll *dpr = (dnssec_policy_roll*)node->value; group_mutex_write_lock(&dnssec_policy_roll_mtx); int rc = dpr->rc; group_mutex_write_unlock(&dnssec_policy_roll_mtx); if(rc == 1) { // destroy it log_debug("dnssec-policy: %s: roll released", dpr->name); dnssec_policy_roll_release(dpr); } else { log_warn("dnssec-policy: %s: roll is still referenced %i times", dpr->name, rc); } } ptr_set_destroy(&dnssec_policy_roll_set); group_mutex_write_unlock(&dnssec_policy_roll_set_mtx); // group_mutex_write_lock(&dnssec_denial_set_mtx); ptr_set_iterator_init(&dnssec_denial_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); dnssec_denial *dd = (dnssec_denial*)node->value; group_mutex_write_lock(&dnssec_denial_mtx); int rc = dd->rc; group_mutex_write_unlock(&dnssec_denial_mtx); if(rc == 1) { // destroy it log_debug("dnssec-policy: %s: denial released", dd->name); dnssec_policy_denial_release(dd); } else { log_warn("dnssec-policy: %s: denial is still referenced %i times", dd->name, rc); } } ptr_set_destroy(&dnssec_denial_set); mutex_lock(&origin_to_dnssec_policy_queue_mtx); ptr_set_iterator_init(&origin_to_dnssec_policy_queue_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); dnsname_zfree(node->key); dnssec_policy_queue* cmd = (dnssec_policy_queue*)node->value; while(cmd != NULL) { dnssec_policy_queue *tmp = cmd; dnsname_zfree(cmd->origin); cmd = cmd->next; ZFREE_OBJECT(tmp); } } ptr_set_destroy(&origin_to_dnssec_policy_queue_set); mutex_unlock(&origin_to_dnssec_policy_queue_mtx); group_mutex_write_unlock(&dnssec_denial_set_mtx); } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/zone-signature-date-next.c0000644000000000000000000000013214505005533023700 xustar000000000000000030 mtime=1695812443.518997599 30 atime=1695812445.784030039 30 ctime=1695812495.716745175 yadifa-2.6.5-11201/sbin/yadifad/zone-signature-date-next.c0000664000374500037450000003527514505005533023656 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #include #include #include "dnssec-policy.h" #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; #include "server_error.h" /** * Returns the first index matching the rule in the mask, starting from the first value, * going up to the msb then looping from the lsb. * * @param from the first index to test * @param mask the bitmask to test (64 bits max) * @param limit the number of bits in the mask * * @return the first matching index * */ static int zone_policy_date_next_mask(int from, u64 mask, int limit) { assert(from >= 0); assert(limit >= 0); for(int ret = from; ret < limit; ++ret) { if((mask & (1ULL << ret)) != 0) { return ret; } } for(int ret = 0; ret < from; ++ret) { if((mask & (1ULL << ret)) != 0) { return ret; } } return -1; // no match } static bool zone_policy_date_next_month(zone_policy_date *date, const zone_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int month = zone_policy_date_next_mask(date->absolute.month, def->month, 12); yassert(month >= 0); if(month != date->absolute.month) { ret = FALSE; date->absolute.day = 0; date->absolute.hour = 0; date->absolute.minute = 0; if(month < date->absolute.month) { date->absolute.month = month; ++date->absolute.year; continue; } else { date->absolute.month = month; return FALSE; } } else { return ret; } } } static void zone_policy_date_next_month_move(zone_policy_date *date, const zone_policy_rule_definition_s *def) { date->absolute.day = 0; date->absolute.hour = 0; date->absolute.minute = 0; if(date->absolute.month < 11) { ++date->absolute.month; } else { ++date->absolute.year; date->absolute.month = 0; } zone_policy_date_next_month(date, def); } static bool zone_policy_date_next_week(zone_policy_date *date, const zone_policy_rule_definition_s *def) { bool ret = TRUE; if((def->week == ZONE_POLICY_RULE_ANYWEEK) && (def->weekday == ZONE_POLICY_RULE_ANYWEEKDAY)) { return ret; } for(;;) { int fdom = time_first_day_of_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month); // no change made by the week, what about the week-day ? if(def->weekday != ZONE_POLICY_RULE_ANYWEEKDAY) { int wday = (date->absolute.day + fdom) % 7; // obtain the day name from the absolute day number (0 = sunday) int newwday = zone_policy_date_next_mask(wday, def->weekday, 7); // matching week day if(newwday != wday) { ret = FALSE; int dday = newwday - wday; if(dday < 0) { dday += 7; } int day = date->absolute.day + dday; if(day >= time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month)) // no -1 here { // month changed //date->absolute.day = zone_policy_date_next_earliest_day_from_week(def); //date->absolute.hour = 0; //date->absolute.minute = 0; zone_policy_date_next_month_move(date, def); } else { date->absolute.day = day; date->absolute.hour = 0; date->absolute.minute = 0; } continue; } } // endif (def->weekday != ZONE_POLICY_RULE_ANYWEEKDAY) if(def->week != ZONE_POLICY_RULE_ANYWEEK) { // from the first day of the Month, the base of the week can be found // sunday = 0, but we want to start a Monday int week_base = 7 - (fdom + 6) % 7; // if we want to start a Sunday we add 0 instead // need to find the base of the month int week = (date->absolute.day - week_base); int newweek; if(week >= 0) // don't divide directly { week /= 7; newweek = zone_policy_date_next_mask(week, def->week, 4); // matching week } else { week = -1; newweek = zone_policy_date_next_mask(0, def->week, 4); // matching week } if(newweek != week) { ret = FALSE; // the week changed later in this month if(newweek < week) // newweek < week : the week changed to the next month { // month changed zone_policy_date_next_month_move(date, def); continue; } else { // move the day to the next week date->absolute.day = week_base + newweek * 7; date->absolute.hour = 0; date->absolute.minute = 0; } } // else nothing changed } // endif (def->week != ZONE_POLICY_RULE_ANYWEEK) break; } return ret; } static bool zone_policy_date_next_day(zone_policy_date *date, const zone_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int day = zone_policy_date_next_mask(date->absolute.day, def->day, time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month)); yassert(day >= 0); if(day != date->absolute.day) { ret = FALSE; date->absolute.hour = 0; date->absolute.minute = 0; if(day < date->absolute.day) { // the day has looped to the next month zone_policy_date_next_month_move(date, def); continue; } else // the day has changed { date->absolute.day = day; } } // we have a day that may or may not match the week and the week-day if(zone_policy_date_next_week(date, def)) { // week is good return ret; } ret = FALSE; } } static void zone_policy_date_next_day_move(zone_policy_date *date, const zone_policy_rule_definition_s *def) { date->absolute.hour = 0; date->absolute.minute = 0; // [0;n] [1;n+1] if(date->absolute.day < time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month) - 1) { ++date->absolute.day; } else { zone_policy_date_next_month_move(date, def); } zone_policy_date_next_day(date, def); } static bool zone_policy_date_next_hour(zone_policy_date *date, const zone_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int hour = zone_policy_date_next_mask(date->absolute.hour, def->hour, 24); if(hour != date->absolute.hour) { ret = FALSE; date->absolute.minute = 0; if(hour < date->absolute.hour) { zone_policy_date_next_day_move(date, def); } else { date->absolute.hour = hour; } } else { return ret; } } } static void zone_policy_date_next_hour_move(zone_policy_date *date, const zone_policy_rule_definition_s *def) { // hour could loop back into the nextious year too date->absolute.minute = 0; if(date->absolute.hour < 23) { ++date->absolute.hour; } else { zone_policy_date_next_day_move(date, def); } zone_policy_date_next_hour(date, def); } static bool zone_policy_date_next_minute(zone_policy_date *date, const zone_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int minute = zone_policy_date_next_mask(date->absolute.minute, def->minute, 60); if(date->absolute.minute != minute) { ret = FALSE; if(minute < date->absolute.minute) { zone_policy_date_next_hour_move(date, def); } else { date->absolute.minute = minute; } } else { return ret; } } } ya_result zone_policy_date_init_at_next_rule(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule) { yassert(from->type.type == ZONE_POLICY_ABSOLUTE); if(rule->type.type == ZONE_POLICY_RULE) { const zone_policy_rule_definition_s *def = zone_policy_rule_definition_get_from_rule(rule); time_t epoch; zone_policy_date_get_epoch(from, &epoch); if(rule->type.type == ZONE_POLICY_RULE) { epoch += 60; } zone_policy_date_init_from_epoch(date, epoch); zone_policy_date_next_month(date, def); zone_policy_date_next_day(date, def); zone_policy_date_next_hour(date, def); zone_policy_date_next_minute(date, def); return SUCCESS; } else if(rule->type.type == ZONE_POLICY_RELATIVE) { time_t epoch; zone_policy_date_get_epoch(from, &epoch); epoch += rule->relative.seconds; zone_policy_date_init_from_epoch(date, epoch); return SUCCESS; } else { return POLICY_ILLEGAL_DATE_TYPE; } } ya_result zone_policy_date_init_from_rule(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule) { yassert(from->type.type == ZONE_POLICY_ABSOLUTE); if(rule->type.type == ZONE_POLICY_RULE) { const zone_policy_rule_definition_s *def = zone_policy_rule_definition_get_from_rule(rule); time_t epoch; zone_policy_date_get_epoch(from, &epoch); zone_policy_date_init_from_epoch(date, epoch); zone_policy_date_next_month(date, def); zone_policy_date_next_day(date, def); zone_policy_date_next_hour(date, def); zone_policy_date_next_minute(date, def); return SUCCESS; } else if(rule->type.type == ZONE_POLICY_RELATIVE) { time_t epoch; zone_policy_date_get_epoch(from, &epoch); epoch += rule->relative.seconds; zone_policy_date_init_from_epoch(date, epoch); return SUCCESS; } else { return POLICY_ILLEGAL_DATE_TYPE; } } bool zone_policy_date_matches(zone_policy_date *date, const zone_policy_rule_definition_s *def) { int month = zone_policy_date_next_mask(date->absolute.month, def->month, 12); if(month != date->absolute.month) { return FALSE; } int fdom = time_first_day_of_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month); if(def->week == ZONE_POLICY_RULE_ANYWEEK) { // from the first day of the Month, the base of the week can be found // sunday = 0, but we want to start a Monday int week_base = (fdom + 6 % 7); // if we want to start a Sunday we add 0 instead // need to find the base of the month int week = (date->absolute.day - week_base); int newweek; if(week >= 0) // don't divide directly { week /= 7; newweek = zone_policy_date_next_mask(week, def->week, 4); // matching week } else { week = -1; newweek = zone_policy_date_next_mask(0, def->week, 4); // matching week } if(newweek != week) { return FALSE; } } if(def->weekday != ZONE_POLICY_RULE_ANYWEEKDAY) { int fdom = time_first_day_of_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month); int wday = (date->absolute.day + fdom) % 7; // obtain the day name from the absolute day number (0 = sunday) int newwday = zone_policy_date_next_mask(wday, def->weekday, 7); // matching week day if(newwday != wday) { return FALSE; } } int day = zone_policy_date_next_mask(date->absolute.day, def->day, time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month)); if(day != date->absolute.day) { return FALSE; } int hour = zone_policy_date_next_mask(date->absolute.hour, def->hour, 24); if(hour != date->absolute.hour) { return FALSE; } int minute = zone_policy_date_next_mask(date->absolute.minute, def->minute, 60); if(minute != date->absolute.minute) { return FALSE; } return TRUE; } /** * @} */ yadifa-2.6.5-11201/sbin/yadifad/PaxHeaders.1636/zone-signature-date-prev.c0000644000000000000000000000013214505005533023676 xustar000000000000000030 mtime=1695812443.312994648 30 atime=1695812445.781029996 30 ctime=1695812495.719745218 yadifa-2.6.5-11201/sbin/yadifad/zone-signature-date-prev.c0000664000374500037450000003125414505005533023645 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #include #include #include "dnssec-policy.h" #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; #include "server_error.h" static bool zone_policy_date_prev_day(zone_policy_date *date, const zone_policy_rule_definition_s *def); static void zone_policy_date_prev_day_move(zone_policy_date *date, const zone_policy_rule_definition_s *def); /** * Returns the first index matching the rule in the mask, starting from the first value, * going down to the lsb then looping from the msb. * * @param from the first index to test * @param mask the bitmask to test (64 bits max) * @param limit the number of bits in the mask * * @return the first matching index * */ static int zone_policy_date_prev_mask(int from, u64 mask, int limit) { assert(from >= 0); assert(limit >= 0); for(int ret = from; ret >= 0; --ret) { if((mask & (1ULL << ret)) != 0) { return ret; } } for(int ret = limit - 1; ret > from; --ret) { if((mask & (1ULL << ret)) != 0) { return ret; } } return -1; // no match } static ya_result zone_policy_date_prev_month(zone_policy_date *date, const zone_policy_rule_definition_s *def) { ya_result ret = 1; for(;;) { int month = zone_policy_date_prev_mask(date->absolute.month, def->month, 12); yassert(month >= 0); if(month != date->absolute.month) { ret = 0; date->absolute.day = time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, month) - 1; date->absolute.hour = 23; date->absolute.minute = 59; if(month > date->absolute.month) { if(date->absolute.year == 0) { log_err("previous month outside of supported time range"); logger_flush(); return ERROR; } date->absolute.month = 11; --date->absolute.year; continue; } else { date->absolute.month = month; return 0; } // the caller is supposed to proceed on day (then hour, then minute) correction } else { return ret; // no change } } } // the "move" version of the function guarantees the value will be changed static void zone_policy_date_prev_month_move(zone_policy_date *date, const zone_policy_rule_definition_s *def) { // month could loop back into the previous year too date->absolute.hour = 23; date->absolute.minute = 59; if(date->absolute.month > 0) { --date->absolute.month; date->absolute.day = time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month) - 1; } else { if(date->absolute.year == 0) { log_err("previous month outside of supported time range"); logger_flush(); } --date->absolute.year; date->absolute.month = 11; date->absolute.day = time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month) - 1; } zone_policy_date_prev_month(date, def); } static bool zone_policy_date_prev_week(zone_policy_date *date, const zone_policy_rule_definition_s *def) { bool ret = TRUE; if((def->week == ZONE_POLICY_RULE_ANYWEEK) && (def->weekday == ZONE_POLICY_RULE_ANYWEEKDAY)) { return ret; } for(;;) { int fdom = time_first_day_of_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month); if(def->week != ZONE_POLICY_RULE_ANYWEEK) { // from the first day of the Month, the base of the week can be found // sunday = 0, but we want to start a Monday int week_base = 7 - (fdom + 6) % 7; // if we want to start a Sunday we add 0 instead // need to find the base of the month int week = (date->absolute.day - week_base); int newweek; if(week >= 0) // don't divide directly { week /= 7; newweek = zone_policy_date_prev_mask(week, def->week, 4); // matching week } else { week = -1; newweek = zone_policy_date_prev_mask(5, def->week, 4); // matching week } if(newweek != week) { ret = FALSE; // the week changed earlier in this month if(newweek > week) { // month changed zone_policy_date_prev_month_move(date, def); continue; } else // newweek > week : the week changed to the prev month { // move the day to the prev week date->absolute.day = week_base + newweek * 7 + 6; // + 6 because we want the last day of that week date->absolute.hour = 23; date->absolute.minute = 59; } } // else nothing changed } // endif (def->week != ZONE_POLICY_RULE_ANYWEEK) // no change made for the week, what about the week-day ? if(def->weekday != ZONE_POLICY_RULE_ANYWEEKDAY) { int wday = (date->absolute.day + fdom) % 7; int newwday = zone_policy_date_prev_mask(wday, def->weekday, 7); // matching week day if(newwday != wday) { ret = FALSE; int dday = wday - newwday; if(dday < 0) // verify this { dday += 7; } int day = date->absolute.day - dday; if(day < 0) { // month changed zone_policy_date_prev_month_move(date, def); } else { date->absolute.day = day; date->absolute.hour = 23; date->absolute.minute = 59; } continue; } } // endif (def->weekday != ZONE_POLICY_RULE_ANYWEEKDAY) break; } return ret; } static bool zone_policy_date_prev_day(zone_policy_date *date, const zone_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int day = zone_policy_date_prev_mask(date->absolute.day, def->day, time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month)); yassert(day >= 0); if(day != date->absolute.day) // the current day didn't match (so it changed) { ret = FALSE; date->absolute.hour = 23; date->absolute.minute = 59; if(day > date->absolute.day) // the day has looped up, the month must decrement { // the day has looped to the prev month zone_policy_date_prev_month_move(date, def); // _move functions enforce a change then call their non-_move version to check a match continue; } else // the day has changed, we will match time down from the top of the day (23:59) { date->absolute.day = day; } } // we have a day that may or may not match the week and the week-day, we check that here if(zone_policy_date_prev_week(date, def)) // if true, it's a match { // week is good return ret; } ret = FALSE; } } static void zone_policy_date_prev_day_move(zone_policy_date *date, const zone_policy_rule_definition_s *def) { date->absolute.hour = 23; date->absolute.minute = 59; if(date->absolute.day > 0) { --date->absolute.day; } else { zone_policy_date_prev_month_move(date, def); } zone_policy_date_prev_day(date, def); } static bool zone_policy_date_prev_hour(zone_policy_date *date, const zone_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int hour = zone_policy_date_prev_mask(date->absolute.hour, def->hour, 24); if(hour != date->absolute.hour) { ret = FALSE; date->absolute.minute = 59; if(hour > date->absolute.hour) { zone_policy_date_prev_day_move(date, def); } else { date->absolute.hour = hour; } } else { return ret; } } } static void zone_policy_date_prev_hour_move(zone_policy_date *date, const zone_policy_rule_definition_s *def) { // hour could loop back into the previous year too date->absolute.minute = 59; if(date->absolute.hour > 0) { --date->absolute.hour; } else { zone_policy_date_prev_day_move(date, def); } zone_policy_date_prev_hour(date, def); } static bool zone_policy_date_prev_minute(zone_policy_date *date, const zone_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int minute = zone_policy_date_prev_mask(date->absolute.minute, def->minute, 60); if(minute != date->absolute.minute) { ret = FALSE; if(minute > date->absolute.minute) { zone_policy_date_prev_hour_move(date, def); } else { date->absolute.minute = minute; } } else { return ret; } } } ya_result zone_policy_date_init_at_prev_rule(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule) { yassert(from->type.type == ZONE_POLICY_ABSOLUTE); if(rule->type.type == ZONE_POLICY_RULE) { const zone_policy_rule_definition_s *def = zone_policy_rule_definition_get_from_rule(rule); time_t epoch; zone_policy_date_get_epoch(from, &epoch); if(rule->type.type == ZONE_POLICY_RULE) { epoch -= 60; // force a move back in time } zone_policy_date_init_from_epoch(date, epoch); ya_result ret; if(FAIL(ret = zone_policy_date_prev_month(date, def))) { return ret; } zone_policy_date_prev_day(date, def); zone_policy_date_prev_hour(date, def); zone_policy_date_prev_minute(date, def); return SUCCESS; } else if(rule->type.type == ZONE_POLICY_RELATIVE) { time_t epoch; zone_policy_date_get_epoch(from, &epoch); epoch -= rule->relative.seconds; zone_policy_date_init_from_epoch(date, epoch); return SUCCESS; } else { return POLICY_ILLEGAL_DATE_TYPE; } } /** * @} */ yadifa-2.6.5-11201/sbin/PaxHeaders.1636/yakeyrolld0000644000000000000000000000013214505005617017377 xustar000000000000000030 mtime=1695812495.820746665 30 atime=1695812499.083793398 30 ctime=1695812495.820746665 yadifa-2.6.5-11201/sbin/yakeyrolld/0000775000374500037450000000000014505005617017416 5ustar00signersigner00000000000000yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/Makefile.in0000644000000000000000000000013114505005547021522 xustar000000000000000030 mtime=1695812455.633171098 29 atime=1695812461.82025971 30 ctime=1695812495.788746207 yadifa-2.6.5-11201/sbin/yakeyrolld/Makefile.in0000664000374500037450000011154114505005547021470 0ustar00signersigner00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 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@ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ # # ALL # ################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' 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@ DIST_COMMON = $(srcdir)/../../mk/common-settings.mk \ $(srcdir)/../../mk/common-labels.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/depcomp \ $(am__noinst_HEADERS_DIST) @USES_SUNC_TRUE@am__append_1 = @USES_SUNC_FALSE@am__append_2 = -O0 @IS_DARWIN_OS_TRUE@am__append_3 = -Wno-deprecated @HAS_CC_NO_IDENT_TRUE@am__append_4 = -fno-ident @HAS_CC_ANSI_TRUE@am__append_5 = -ansi @HAS_CC_PEDANTIC_TRUE@am__append_6 = -pedantic @HAS_CC_WALL_TRUE@am__append_7 = -Wall -Wno-unknown-pragmas @HAS_CC_MISSING_FIELD_INITIALIZERS_TRUE@am__append_8 = -Werror=missing-field-initializers @HAS_CC_STD_GNU11_TRUE@am__append_9 = -std=gnu11 @HAS_CC_STD_C11_TRUE@@HAS_CC_STD_GNU11_FALSE@am__append_10 = -std=c11 -D_GNU_SOURCE @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_TRUE@am__append_11 = -std=gnu99 @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_C99_TRUE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_FALSE@am__append_12 = -std=c99 @HAS_CC_STD_C11_FALSE@@HAS_CC_STD_C99_FALSE@@HAS_CC_STD_GNU11_FALSE@@HAS_CC_STD_GNU99_FALSE@@HAS_CC_XC99_TRUE@am__append_13 = -xc99 @HAS_CC_TUNE_NATIVE_TRUE@am__append_14 = -mtune=native @FORCE64BITS_TRUE@@HAS_CC_M64_TRUE@am__append_15 = -m64 @FORCE64BITS_TRUE@@HAS_CC_M64_TRUE@am__append_16 = -m64 @FORCE32BITS_TRUE@@FORCE64BITS_FALSE@@HAS_CC_M32_TRUE@am__append_17 = -m32 @FORCE32BITS_TRUE@@FORCE64BITS_FALSE@@HAS_CC_M32_TRUE@am__append_18 = -m32 # # DEBUG # @HAS_CC_G3_TRUE@am__append_19 = -g3 @HAS_CC_G3_FALSE@@HAS_CC_G_TRUE@am__append_20 = -g @HAS_CC_DWARF4_TRUE@am__append_21 = -gdwarf-4 @HAS_CC_DWARF3_TRUE@@HAS_CC_DWARF4_FALSE@am__append_22 = -gdwarf-3 # # Intel C Compiler # ############################################################################### #ICC #IPO= -ipo (need to use the intel xiar instead of ar) @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@am__append_23 = -DLTO -ipo @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@am__append_24 = -ipo @USES_ICC_TRUE@am__append_25 = -DUSES_ICC @HAS_CC_ANSI_ALIAS_TRUE@@USES_ICC_TRUE@am__append_26 = -ansi-alias -U__STRICT_ANSI__ @USES_ICC_TRUE@am__append_27 = -DMODE_DEBUG_ICC # # LLVM Clang # ############################################################################### # CLANG @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@am__append_28 = -DLTO -flto @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@am__append_29 = -flto @USES_CLANG_TRUE@am__append_30 = -DUSES_LLVM -Wno-gnu #-Wno-extended-offsetof @USES_CLANG_TRUE@am__append_31 = -DMODE_DEBUG_CLANG -fsanitize=address -fsanitize=bounds @IS_LINUX_FAMILY_TRUE@@USES_CLANG_TRUE@am__append_32 = -Wl,-z,stack-size=8388608 # Note: add a _d suffix for debug builds ? # # Gnu C # ############################################################################### #GCC @HAS_CPU_NIAGARA_TRUE@@USES_GCC_TRUE@am__append_33 = -mcpu=niagara @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_34 = -DLTO -flto -fwhole-program -fno-fat-lto-objects -fuse-linker-plugin @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_35 = -flto \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fwhole-program \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fno-fat-lto-objects \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -fuse-linker-plugin \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -Wl,-Map=module.map \ @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@ -Wl,--cref @USES_GCC_TRUE@am__append_36 = -DUSES_GCC @USES_GCC_TRUE@am__append_37 = -DMODE_DEBUG_GCC -fstack-check -fstack-protector-strong @HAS_BFD_DEBUG_SUPPORT_TRUE@@USES_GCC_TRUE@am__append_38 = -rdynamic @IS_LINUX_FAMILY_TRUE@@USES_GCC_TRUE@am__append_39 = -Wl,-z,stack-size=8388608 @USES_SUNC_TRUE@am__append_40 = -DUSES_SUNC @USES_SUNC_TRUE@am__append_41 = -DMODE_DEBUG_SUNC # Note: add a _d suffix for debug builds ? # # Unknown compiler # ############################################################################### # if an unknown compiler is used, it should have its own section @USES_UNKNOWN_TRUE@am__append_42 = -DUSES_UNKNOWN_COMPILER @USES_UNKNOWN_TRUE@am__append_43 = -DMODE_DEBUG_UNKNOWN # # Some BSD-based OSes need this # @IS_BSD_FAMILY_TRUE@am__append_44 = -I./include @IS_SOLARIS_FAMILY_TRUE@am__append_45 = -D_POSIX_PTHREAD_SEMANTICS @HAS_TOOLS_TRUE@am__append_46 = -I$(top_srcdir)/lib/dnscore/include \ @HAS_TOOLS_TRUE@ -I$(top_builddir)/lib/dnscore/include \ @HAS_TOOLS_TRUE@ -I$(top_srcdir)/lib/dnsdb/include \ @HAS_TOOLS_TRUE@ -I$(top_builddir)/lib/dnsdb/include @HAS_TOOLS_TRUE@sbin_PROGRAMS = yakeyrolld$(EXEEXT) subdir = sbin/yakeyrolld ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(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)/m4/eurid.m4 $(top_srcdir)/m4/yadifa.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am__yakeyrolld_SOURCES_DIST = main.c config-dnssec-policy.c \ config-key-roll.c config-key-roll-parser.c config-key-suite.c \ config-key-template.c date-next.c date-prev.c dnssec-policy.c \ keyroll.c @HAS_TOOLS_TRUE@am_yakeyrolld_OBJECTS = main.$(OBJEXT) \ @HAS_TOOLS_TRUE@ config-dnssec-policy.$(OBJEXT) \ @HAS_TOOLS_TRUE@ config-key-roll.$(OBJEXT) \ @HAS_TOOLS_TRUE@ config-key-roll-parser.$(OBJEXT) \ @HAS_TOOLS_TRUE@ config-key-suite.$(OBJEXT) \ @HAS_TOOLS_TRUE@ config-key-template.$(OBJEXT) \ @HAS_TOOLS_TRUE@ date-next.$(OBJEXT) date-prev.$(OBJEXT) \ @HAS_TOOLS_TRUE@ dnssec-policy.$(OBJEXT) keyroll.$(OBJEXT) yakeyrolld_OBJECTS = $(am_yakeyrolld_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__depfiles_maybe = depfiles 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 = $(yakeyrolld_SOURCES) DIST_SOURCES = $(am__yakeyrolld_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__noinst_HEADERS_DIST = config-dnssec-policy.h \ config-key-roll-parser.h dnssec-policy.h keyroll.h HEADERS = $(noinst_HEADERS) 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)` ETAGS = etags CTAGS = ctags 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@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CCOPTIMISATIONFLAGS = @CCOPTIMISATIONFLAGS@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DNSCORE = @DNSCORE@ DNSDB = @DNSDB@ DNSLG = @DNSLG@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAS_ACL_SUPPORT = @HAS_ACL_SUPPORT@ HAS_BFD_DEBUG_SUPPORT = @HAS_BFD_DEBUG_SUPPORT@ HAS_BIG_ENDIAN = @HAS_BIG_ENDIAN@ HAS_BUILD_TIMESTAMP = @HAS_BUILD_TIMESTAMP@ HAS_CC_ADDRESS_SANITIZER_CHECK = @HAS_CC_ADDRESS_SANITIZER_CHECK@ HAS_CC_ANSI = @HAS_CC_ANSI@ HAS_CC_ANSI_ALIAS = @HAS_CC_ANSI_ALIAS@ HAS_CC_CATCH_UNDEFINED_BEHAVIOR = @HAS_CC_CATCH_UNDEFINED_BEHAVIOR@ HAS_CC_DWARF2 = @HAS_CC_DWARF2@ HAS_CC_DWARF3 = @HAS_CC_DWARF3@ HAS_CC_DWARF4 = @HAS_CC_DWARF4@ HAS_CC_EXCEPTIONS = @HAS_CC_EXCEPTIONS@ HAS_CC_G = @HAS_CC_G@ HAS_CC_G3 = @HAS_CC_G3@ HAS_CC_M32 = @HAS_CC_M32@ HAS_CC_M64 = @HAS_CC_M64@ HAS_CC_MISSING_FIELD_INITIALIZERS = @HAS_CC_MISSING_FIELD_INITIALIZERS@ HAS_CC_NO_IDENT = @HAS_CC_NO_IDENT@ HAS_CC_NO_OMIT_FRAME_POINTER = @HAS_CC_NO_OMIT_FRAME_POINTER@ HAS_CC_PEDANTIC = @HAS_CC_PEDANTIC@ HAS_CC_RDYNAMIC = @HAS_CC_RDYNAMIC@ HAS_CC_SANITIZE_ADDRESS = @HAS_CC_SANITIZE_ADDRESS@ HAS_CC_STACK_PROTECTOR = @HAS_CC_STACK_PROTECTOR@ HAS_CC_STD_C11 = @HAS_CC_STD_C11@ HAS_CC_STD_C99 = @HAS_CC_STD_C99@ HAS_CC_STD_GNU11 = @HAS_CC_STD_GNU11@ HAS_CC_STD_GNU99 = @HAS_CC_STD_GNU99@ HAS_CC_TUNE_NATIVE = @HAS_CC_TUNE_NATIVE@ HAS_CC_WALL = @HAS_CC_WALL@ HAS_CC_XC99 = @HAS_CC_XC99@ HAS_CLOSE_EX_REF = @HAS_CLOSE_EX_REF@ HAS_CTRL = @HAS_CTRL@ HAS_DNSSEC_TOOLS = @HAS_DNSSEC_TOOLS@ HAS_DYNUPDATE_SUPPORT = @HAS_DYNUPDATE_SUPPORT@ HAS_ECDSA_SUPPORT = @HAS_ECDSA_SUPPORT@ HAS_EDDSA = @HAS_EDDSA@ HAS_EVENT_DYNAMIC_MODULE = @HAS_EVENT_DYNAMIC_MODULE@ HAS_FULL_ASCII7 = @HAS_FULL_ASCII7@ HAS_KEYGEN = @HAS_KEYGEN@ HAS_LIBC_MALLOC_DEBUG_SUPPORT = @HAS_LIBC_MALLOC_DEBUG_SUPPORT@ HAS_LITTLE_ENDIAN = @HAS_LITTLE_ENDIAN@ HAS_LOCK_DEBUG_SUPPORT = @HAS_LOCK_DEBUG_SUPPORT@ HAS_LOGDIR = @HAS_LOGDIR@ HAS_LOG_PID = @HAS_LOG_PID@ HAS_LOG_THREAD_ID = @HAS_LOG_THREAD_ID@ HAS_LOG_THREAD_TAG = @HAS_LOG_THREAD_TAG@ HAS_MALLOC_DEBUG_SUPPORT = @HAS_MALLOC_DEBUG_SUPPORT@ HAS_MASTER_SUPPORT = @HAS_MASTER_SUPPORT@ HAS_MEMALIGN_ISSUES = @HAS_MEMALIGN_ISSUES@ HAS_MUTEX_DEBUG_SUPPORT = @HAS_MUTEX_DEBUG_SUPPORT@ HAS_NON_AA_AXFR_SUPPORT = @HAS_NON_AA_AXFR_SUPPORT@ HAS_NSEC3_SUPPORT = @HAS_NSEC3_SUPPORT@ HAS_NSEC_SUPPORT = @HAS_NSEC_SUPPORT@ HAS_NSID_SUPPORT = @HAS_NSID_SUPPORT@ HAS_RRL_SUPPORT = @HAS_RRL_SUPPORT@ HAS_RRSIG_MANAGEMENT_SUPPORT = @HAS_RRSIG_MANAGEMENT_SUPPORT@ HAS_SYNC_BUILTINS = @HAS_SYNC_BUILTINS@ HAS_SYSTEMD_RESOLVED_AVOIDANCE = @HAS_SYSTEMD_RESOLVED_AVOIDANCE@ HAS_TESTS = @HAS_TESTS@ HAS_TOOLS = @HAS_TOOLS@ HAS_TRACK_ZONES_DEBUG_SUPPORT = @HAS_TRACK_ZONES_DEBUG_SUPPORT@ HAS_TSIG_SUPPORT = @HAS_TSIG_SUPPORT@ HAS_YADIFA = @HAS_YADIFA@ HAS_ZALLOC_DEBUG_SUPPORT = @HAS_ZALLOC_DEBUG_SUPPORT@ HAS_ZALLOC_STATISTICS_SUPPORT = @HAS_ZALLOC_STATISTICS_SUPPORT@ HAS_ZALLOC_SUPPORT = @HAS_ZALLOC_SUPPORT@ HAVE_RECVMMSG = @HAVE_RECVMMSG@ HAVE_SENDMMSG = @HAVE_SENDMMSG@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IS_BSD_FAMILY = @IS_BSD_FAMILY@ IS_DARWIN_GE14 = @IS_DARWIN_GE14@ IS_DARWIN_OS = @IS_DARWIN_OS@ IS_LINUX_FAMILY = @IS_LINUX_FAMILY@ IS_SOLARIS_FAMILY = @IS_SOLARIS_FAMILY@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL = @OPENSSL@ 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@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ ZDB_HAS_DNSSEC_SUPPORT = @ZDB_HAS_DNSSEC_SUPPORT@ 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_CXX = @ac_ct_CXX@ 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@ 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@ logdir = @logdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I ../../m4 # # # AM_CFLAGS = -D_THREAD_SAFE -D_REENTRANT -D_FILE_OFFSET_BITS=64 \ -I$(abs_builddir) -I$(abs_builddir)/include \ -I$(abs_srcdir)/include $(am__append_3) $(am__append_4) \ $(am__append_5) $(am__append_6) $(am__append_7) \ $(am__append_8) $(am__append_9) $(am__append_10) \ $(am__append_11) $(am__append_12) $(am__append_13) \ $(am__append_14) $(am__append_15) $(am__append_17) \ $(am__append_23) $(am__append_25) $(am__append_26) \ $(am__append_28) $(am__append_30) $(am__append_33) \ $(am__append_34) $(am__append_36) $(am__append_38) \ $(am__append_40) $(am__append_42) $(am__append_44) \ $(am__append_45) $(LOCALFLAGS) $(am__append_46) AM_LDFLAGS = $(am__append_16) $(am__append_18) $(am__append_24) \ $(am__append_29) $(am__append_32) $(am__append_35) \ $(am__append_39) DEBUGFLAGS = $(am__append_1) $(am__append_2) $(am__append_19) \ $(am__append_20) $(am__append_21) $(am__append_22) \ $(am__append_27) $(am__append_31) $(am__append_37) \ $(am__append_41) $(am__append_43) LOCALFLAGS = -DPREFIX='"$(prefix)"' -DSYSCONFDIR='"$(sysconfdir)"' -DLOCALSTATEDIR='"$(localstatedir)"' -DDATAROOTDIR='"$(datarootdir)"' -DDATADIR='"$(datadir)"' -DLOCALEDIR='"$(localedir)"' -DLOGDIR='"$(logdir)"' -DTCLDIR='"$(tcldir)"' @HAS_LTO_SUPPORT_FALSE@@USES_CLANG_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_FALSE@@USES_GCC_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@AM_AR = llvm-ar @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@AM_AR = gcc-ar @HAS_LTO_SUPPORT_TRUE@@USES_ICC_TRUE@AM_AR = xiar # # Sun C # ############################################################################### # SUNC @USES_SUNC_TRUE@AM_AR = ar @HAS_LTO_SUPPORT_FALSE@@USES_CLANG_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_FALSE@@USES_GCC_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_TRUE@@USES_CLANG_TRUE@AM_LD = ld.gold @USES_ICC_TRUE@AM_LD = ld @USES_SUNC_TRUE@AM_LD = ld @HAS_LTO_SUPPORT_TRUE@@USES_GCC_TRUE@AM_RANLIB = gcc-ranlib BUILT_SOURCES = buildinfo.h keyroll-config.h @HAS_TOOLS_TRUE@yakeyrolld_SOURCES = main.c config-dnssec-policy.c config-key-roll.c config-key-roll-parser.c config-key-suite.c config-key-template.c date-next.c date-prev.c dnssec-policy.c keyroll.c @HAS_TOOLS_TRUE@yakeyrolld_LDADD = \ @HAS_TOOLS_TRUE@ $(top_builddir)/lib/dnscore/libdnscore.la \ @HAS_TOOLS_TRUE@ $(top_builddir)/lib/dnsdb/libdnsdb.la @HAS_TOOLS_TRUE@noinst_HEADERS = config-dnssec-policy.h config-key-roll-parser.h dnssec-policy.h keyroll.h @HAS_TOOLS_TRUE@yakeyrolld_DEPENDENCIES = keyroll-config.h CLEANFILES = buildinfo.h keyroll-config.h all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../mk/common-settings.mk $(srcdir)/../../mk/common-labels.mk $(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) --gnu sbin/yakeyrolld/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu sbin/yakeyrolld/Makefile .PRECIOUS: 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__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(srcdir)/../../mk/common-settings.mk $(srcdir)/../../mk/common-labels.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || 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)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || 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)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_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 yakeyrolld$(EXEEXT): $(yakeyrolld_OBJECTS) $(yakeyrolld_DEPENDENCIES) $(EXTRA_yakeyrolld_DEPENDENCIES) @rm -f yakeyrolld$(EXEEXT) $(AM_V_CCLD)$(LINK) $(yakeyrolld_OBJECTS) $(yakeyrolld_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-dnssec-policy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-key-roll-parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-key-roll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-key-suite.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config-key-template.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/date-next.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/date-prev.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-policy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyroll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ .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 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: $(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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) 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: -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." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags 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-sbinPROGRAMS 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 -rf ./$(DEPDIR) -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: uninstall-am: uninstall-sbinPROGRAMS .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir 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-sbinPROGRAMS 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 uninstall uninstall-am uninstall-sbinPROGRAMS ### YRCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -g -DCMR ### YPCFLAGS = -DNDEBUG $(CCOPTIMISATIONFLAGS) -pg -DCMP ### YDCFLAGS = -DDEBUG $(DEBUGFLAGS) -DCMD ### YSCFLAGS = $(YRCFLAGS) ### ### YRLDFLAGS = -g ### YPLDFLAGS = -pg ### YDLDFLAGS = -g ### ### if HAS_CC_RDYNAMIC ### YPLDFLAGS += -rdynamic ### YDLDFLAGS += -rdynamic ### endif ### ### if USES_CLANG ### # workaround a bug where clang does not handle properly profiling and optimizations ### YPCFLAGS += -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer ### endif ### ### YSLDFLAGS = $(YRLDFLAGS) ### ### AM_CFLAGS += $(YCFLAGS) ### AM_LDFLAGS += $(YLDFLAGS) ### ### AM_MAKEFLAGS=MODE_CFLAGS="$(AM_CFLAGS)" CC=$(CC) AR=$(AM_AR) LD=$(AM_LD) buildinfo.h: $(abs_top_builddir)/config.log echo \#pragma once > buildinfo.h 2> /dev/null echo // generated file, do not modify >> buildinfo.h 2> /dev/null echo \#define BUILD_OPTIONS \"$$(grep "/configure" $(abs_top_builddir)/config.log | head -1 | sed 's/.*\.\/configure *//')\" >> buildinfo.h 2> /dev/null keyroll-config.h: ../../config.h cp ../../config.h keyroll-config.h features: # 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: yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/Makefile.am0000644000000000000000000000013214505005533021505 xustar000000000000000030 mtime=1695812443.262993932 30 atime=1695812445.786030067 30 ctime=1695812495.790746236 yadifa-2.6.5-11201/sbin/yakeyrolld/Makefile.am0000664000374500037450000000533014505005533021450 0ustar00signersigner00000000000000################################################################################ # # Copyright (c) 2011-2023, EURid vzw. All rights reserved. # The YADIFA TM software product is provided under the BSD 3-clause license: # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of EURid nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ ACLOCAL_AMFLAGS = -I ../../m4 include ../../mk/common-settings.mk BUILT_SOURCES=buildinfo.h keyroll-config.h if HAS_TOOLS AM_CFLAGS += -I$(top_srcdir)/lib/dnscore/include -I$(top_builddir)/lib/dnscore/include AM_CFLAGS += -I$(top_srcdir)/lib/dnsdb/include -I$(top_builddir)/lib/dnsdb/include sbin_PROGRAMS = yakeyrolld yakeyrolld_SOURCES = main.c config-dnssec-policy.c config-key-roll.c config-key-roll-parser.c config-key-suite.c config-key-template.c date-next.c date-prev.c dnssec-policy.c keyroll.c yakeyrolld_LDADD = $(top_builddir)/lib/dnscore/libdnscore.la yakeyrolld_LDADD += $(top_builddir)/lib/dnsdb/libdnsdb.la noinst_HEADERS = config-dnssec-policy.h config-key-roll-parser.h dnssec-policy.h keyroll.h yakeyrolld_DEPENDENCIES = keyroll-config.h endif include ../../mk/common-labels.mk keyroll-config.h: ../../config.h cp ../../config.h keyroll-config.h CLEANFILES += keyroll-config.h features: yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/config-dnssec-policy.h0000644000000000000000000000013114505005533023640 xustar000000000000000029 mtime=1695812443.25999389 30 atime=1695812445.786030067 30 ctime=1695812495.793746278 yadifa-2.6.5-11201/sbin/yakeyrolld/config-dnssec-policy.h0000664000374500037450000001272614505005533023613 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup configuration * @brief */ #pragma once #include typedef struct dnssec_policy_desc_s dnssec_policy_desc_s; struct dnssec_policy_desc_s { char *id; char *description; ptr_vector key_suite; s32 ds_ttl; u8 flags; // weaker-key & stronger-key u8 max_key; }; typedef struct key_suite_desc_s key_suite_desc_s; struct key_suite_desc_s { char *id; char *key_template; char *key_roll; }; typedef struct key_template_desc_s key_template_desc_s; struct key_template_desc_s { char *id; bool ksk; u32 algorithm; u16 size; char *engine; }; typedef struct denial_desc_s denial_desc_s; struct denial_desc_s { char *id; u32 type; u32 resalting; char *salt; char *algorithm; u8 algorithm_val; u16 iterations; u8 salt_length; bool optout; }; typedef struct key_roll_desc_s key_roll_desc_s; struct key_roll_desc_s { char *id; char *generate; char *publish; char *activate; char *inactive; char *remove; char *ds_publish; char *ds_remove; }; ya_result config_register_key_roll(const char *null_or_key_name, s32 priority); ya_result config_register_key_suite(const char *null_or_key_name, s32 priority); ya_result config_register_key_template(const char *null_or_key_name, s32 priority); ya_result config_register_denial(const char *null_or_key_name, s32 priority); /** * @fn ya_result config_register_dnssec_policy(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * , , and are needed for * get all of them before registering all sections * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_dnssec_policy(const char *null_or_key_name, s32 priority); yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/config-key-roll-parser.h0000644000000000000000000000013114505005533024114 xustar000000000000000029 mtime=1695812443.25099376 30 atime=1695812445.785030053 30 ctime=1695812495.795746307 yadifa-2.6.5-11201/sbin/yakeyrolld/config-key-roll-parser.h0000664000374500037450000000703114505005533024060 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifa * @ingroup ### * @brief */ #pragma once #include #include #include "dnssec-policy.h" /*----------------------------------------------------------------------------*/ #pragma mark DEFINES #define KEY_ROLL_LINE_CRON_TYPE true #define KEY_ROLL_LINE_RELATIVE_TYPE false // key roll actions values #define KR_ACTION_GENERATE 0 #define KR_ACTION_PUBLISH 1 #define KR_ACTION_ACTIVATE 2 #define KR_ACTION_INACTIVE 3 #define KR_ACTION_REMOVE 4 #define KR_ACTION_DS_PUBLISH 5 #define KR_ACTION_DS_REMOVE 6 // key roll actions names #define KR_ACTION_GENERATE_NAME "generate" #define KR_ACTION_PUBLISH_NAME "publish" #define KR_ACTION_ACTIVATE_NAME "activate" #define KR_ACTION_INACTIVE_NAME "inactive" #define KR_ACTION_REMOVE_NAME "remove" #define KR_ACTION_DS_PUBLISH_NAME "ds-publish" #define KR_ACTION_DS_REMOVE_NAME "ds-remove" /*----------------------------------------------------------------------------*/ #pragma mark STRUCTS typedef struct key_roll_line_s key_roll_line_s; struct key_roll_line_s { union { dnssec_policy_rule_definition_s cron; dnssec_policy_relative_s relative; } policy; s32 action; s32 relative_to; bool type; }; /*----------------------------------------------------------------------------*/ #pragma mark PROTOTYPES ya_result config_key_roll_parser_line(const char *key_roll_line, key_roll_line_s *krl, u8 action); yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/dnssec-policy.h0000644000000000000000000000013214505005533022376 xustar000000000000000030 mtime=1695812443.255993832 30 atime=1695812445.785030053 30 ctime=1695812495.797746336 yadifa-2.6.5-11201/sbin/yakeyrolld/dnssec-policy.h0000664000374500037450000003531114505005533022343 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ // YYYY MM DD hh mm // 7 4 5 5 6 : 27 bits : one bit is not worth it, shifts it is // 134217728 : // 68567040 : 26.031 bits => 27 bits #pragma once #include #include #include #include #include #include "keyroll.h" #define ZONE_POLICY_DATE_YEAR_BASE 2000 #define DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM 2 #if DEBUG #define DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS (7*86400) #else #define DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS (3600) #endif #define ZONE_POLICY_ABSOLUTE 1 #define ZONE_POLICY_RELATIVE 2 #define ZONE_POLICY_RULE 3 // index to a rule typedef struct dnssec_policy_rule_definition_s dnssec_policy_rule_definition_s; #define ZONE_POLICY_RULE_ANYMINUTE 0x0fffffffffffffffLL #define ZONE_POLICY_RULE_ANYWEEK 0x0000000f #define ZONE_POLICY_RULE_ANYHOUR 0x00ffffff #define ZONE_POLICY_RULE_ANYDAY 0x7fffffff #define ZONE_POLICY_RULE_ANYWEEKDAY 0x0000007f #define ZONE_POLICY_RULE_ANYMONTH 0x00000fff #define ZONE_POLICY_RELATIVE_TO_GENERATE 0 #define ZONE_POLICY_RELATIVE_TO_PUBLISH 1 #define ZONE_POLICY_RELATIVE_TO_ACTIVATE 2 #define ZONE_POLICY_RELATIVE_TO_INACTIVE 3 #define ZONE_POLICY_RELATIVE_TO_REMOVE 4 #define ZONE_POLICY_RELATIVE_TO_DS_PUBLISH 5 #define ZONE_POLICY_RELATIVE_TO_DS_REMOVE 6 #define DNSSEC_POLICY_FLAGS_REMOVE_OTHER_KEYS 0x01 // remove keys not matching a policy #define POLICY_ERROR_BASE 0x81000000 #define POLICY_ERROR_CODE(code_) ((s32)(POLICY_ERROR_BASE+(code_))) #define POLICY_ILLEGAL_DATE POLICY_ERROR_CODE(0) #define POLICY_ILLEGAL_DATE_TYPE POLICY_ERROR_CODE(1) #define POLICY_ILLEGAL_DATE_PARAMETERS POLICY_ERROR_CODE(2) #define POLICY_ILLEGAL_DATE_COMPARE POLICY_ERROR_CODE(3) #define POLICY_UNDEFINED POLICY_ERROR_CODE(4) #define POLICY_KEY_SUITE_UNDEFINED POLICY_ERROR_CODE(5) #define POLICY_NULL_REQUESTED POLICY_ERROR_CODE(6) #define POLICY_ZONE_NOT_READY POLICY_ERROR_CODE(7) #define ZONE_DNSSEC_FL_NOSEC 0 #define ZONE_DNSSEC_FL_NSEC 1 #define ZONE_DNSSEC_FL_NSEC3 2 #define ZONE_DNSSEC_FL_NSEC3_OPTOUT 3 #define ZONE_DNSSEC_FL_MASK 7 struct dnssec_policy_rule_definition_s // rule-like match { u64 minute:60,week:4; // 64 / 0 minutes, nth dayname of month u64 hour:24,day:31,weekday:7; // 62 / 2 hours, day of month, day of week u16 month:12; // 12 / 4 month of year }; struct dnssec_policy_time_type_s { u32 reserved:30,type:2; }; struct dnssec_policy_absolute_s // all zero-based except year 2000-based { u32 minute:6,hour:5,day:5,month:4,year:7,zeroes:3,type:2; }; // 60 + 24 + 31 + 12 + 7 + 4 = 138 typedef struct dnssec_policy_rule_s dnssec_policy_rule_s; struct dnssec_policy_rule_s // points to a rule-like match { u32 index:30,type:2; }; typedef struct dnssec_policy_relative_s dnssec_policy_relative_s; struct dnssec_policy_relative_s { // 25 bits ~ 1 year, 26 2, 27 ~ 4 u32 seconds:27, relativeto:3, type:2; }; typedef union dnssec_policy_date dnssec_policy_date; union dnssec_policy_date { struct dnssec_policy_time_type_s type; struct dnssec_policy_absolute_s absolute; struct dnssec_policy_rule_s rule; struct dnssec_policy_relative_s relative; }; typedef struct dnssec_policy_table_s dnssec_policy_table_s; struct dnssec_policy_table_s { dnssec_policy_date created; // from previous created ? dnssec_policy_date publish; // from created dnssec_policy_date activate; // from publish dnssec_policy_date inactive; // from activate dnssec_policy_date delete; // from inactive #if HAS_DS_PUBLICATION_SUPPORT dnssec_policy_date ds_add; // from publish dnssec_policy_date ds_del; // from delete #endif }; typedef struct dnssec_policy_key dnssec_policy_key; struct dnssec_policy_key { char *name; // default u16 size; // 1024 u16 flags; // 0 u8 algorithm; // RSA-SHA256 volatile int rc; }; typedef struct dnssec_policy_roll dnssec_policy_roll; struct dnssec_policy_roll { char *name; // default struct dnssec_policy_table_s time_table; volatile int rc; }; typedef struct dnssec_policy_key_suite dnssec_policy_key_suite; struct dnssec_policy_key_suite { char *name; dnssec_policy_key *key; dnssec_policy_roll *roll; volatile int rc; }; struct dnssec_policy { char *name; // default struct dnssec_denial *denial; ptr_vector key_suite; u8 flags; u8 dnskey_count_max; volatile int rc; }; typedef struct dnssec_policy dnssec_policy; struct dnssec_policy_subject { union { u8 *domain; u8 *origin; }; ptr_set dnssec_policy_processed_key_suites; //dnssec_policy *dnssec_policy; }; typedef struct dnssec_policy_subject dnssec_policy_subject; #define DNSSEC_POLICY_COMMAND_INIT 0 #define DNSSEC_POLICY_COMMAND_GENERATE_KEY 1 #define ALARM_KEY_DNSSEC_POLICY_EVENT 16 struct dnssec_policy_queue_parameter_generate_key { struct dnssec_policy_key_suite *suite; keyroll_t *keyroll; }; typedef struct dnssec_policy_queue dnssec_policy_queue; struct dnssec_policy_queue { struct dnssec_policy_queue *next; u8 *origin; time_t epoch; // 0 for ASAP // create one key with these parameters ... // first signature of a zone ... (with or without key generation) // ... u8 command; bool queued; union { struct dnssec_policy_queue_parameter_generate_key generate_key; } parameters; }; /** * Compare two dates together. * Absolute with Absolute * Relative with Relative * * Any other combination will return -1 * * @param d1 first date * @param d2 second date * @return <0,0,>0 if d1 is less than, equal to, or greater than d2 */ int dnssec_policy_date_compare(const dnssec_policy_date *d1, const dnssec_policy_date *d2); /** * Retrieves the first day of the month. * * 0 is Sunday * * @param year 0-based * @param month 0-based * @return the number of the day of the month or an error code */ ya_result dnssec_policy_get_first_day_from_year_month(int year, int month); /** * Retrieves the first day of the month. * * 0 is Sunday * * @param year 0-based * @param month 0-based * @param week 0 to 4, week of the day * @param wday 0 to 6, day of the week, 0 for Sunday * @return the number of the day of the month or an error code */ ya_result dnssec_policy_get_mday_from_year_month_week_wday(int year, int month, int week, int wday); /** * Initialises an absolute date from a year, month, week and week-day * * ie: 2nd Wednesday of January 2001 * * 0 is Sunday * * @param date the date to initialise * @param year 0-based * @param month 0-based * @param week 0 to 4, week of the day * @param wday 0 to 6, day of the week, 0 for Sunday * @return an error code */ ya_result dnssec_policy_date_init_from_year_month_week_wday(dnssec_policy_date *date, int year, int month, int week, int wday); /** * Initialises an absolute date from a UNIX epoch * * @param date * @param epoch * @return an error code */ ya_result dnssec_policy_date_init_from_epoch(dnssec_policy_date *date, time_t epoch); /** * Gets the UNIX epoch from an absolute date * * @param date * @param epoch a pointer to hold the result * @return an error code */ ya_result dnssec_policy_date_get_epoch(const dnssec_policy_date *date, time_t *epoch); /** * Initialises the absolute date with an epoch plus time in seconds. * * @param date * @param epoch an epoch to add the seconds to * @param seconds * @return an error code */ ya_result dnssec_policy_date_init_after_epoch(dnssec_policy_date *date, time_t epoch, u32 seconds); /** * Initialises the absolute date with an absolute date plus time in seconds. * * @param date * @param from an absolute date to add the seconds to * @param seconds * @return an error code */ ya_result dnssec_policy_date_init_after_date(dnssec_policy_date *date, const dnssec_policy_date *from, u32 seconds); bool dnssec_policy_date_matches(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def); /** * Initialises an epoch from a rule applied on an epoch * * @param rule_date * @param after_epoch * @param result_epoch * @return */ ya_result dnssec_policy_get_epoch_from_rule_applied_with_epoch(const dnssec_policy_date *rule_date, time_t after_epoch, time_t *result_epoch); dnssec_policy_rule_definition_s *dnssec_policy_rule_definition_get_from_index(u32 index); dnssec_policy_rule_definition_s *dnssec_policy_rule_definition_get_from_rule(const dnssec_policy_date *rule); /** * This complicated functions initialises a date with the earliest matching of the rule starting from 'from' * * @param date * @param from * @param rule * * @return an error code */ ya_result dnssec_policy_date_init_at_next_date(dnssec_policy_date *date, const dnssec_policy_date *from, const dnssec_policy_date *rule); ya_result dnssec_policy_table_init_from_date(dnssec_policy_table_s *tbl, dnssec_policy_table_s *with, dnssec_policy_date *from); ya_result dnssec_policy_process(keyroll_t *keyroll, const dnssec_policy *policy, s64 from, s64 until); ya_result dnssec_policy_roll_create_from_rules(const char *id, const dnssec_policy_rule_definition_s *generate, const dnssec_policy_rule_definition_s *publish, const dnssec_policy_rule_definition_s *activate, const dnssec_policy_rule_definition_s *inactive, const dnssec_policy_rule_definition_s *remove, const dnssec_policy_rule_definition_s *ds_publish, const dnssec_policy_rule_definition_s *ds_remove); ya_result dnssec_policy_roll_create_from_relatives(const char *id, const dnssec_policy_relative_s *generate, u8 generate_from, const dnssec_policy_relative_s *publish, u8 publish_from, const dnssec_policy_relative_s *activate, u8 activate_from, const dnssec_policy_relative_s *inactive, u8 inactive_from, const dnssec_policy_relative_s *remove, u8 remove_from #if HAS_DS_PUBLICATION_SUPPORT , const dnssec_policy_relative_s *ds_publish, u8 ds_publish_from, const dnssec_policy_relative_s *ds_remove, u8 ds_remove_from #endif ); dnssec_policy_roll *dnssec_policy_roll_acquire_from_name(const char *id); dnssec_policy_roll *dnssec_policy_roll_acquire_from_index(int index); void dnssec_policy_roll_release(dnssec_policy_roll *dpr); dnssec_policy_key *dnssec_policy_key_create(const char *id, u8 algorithm, u16 size, bool ksk, char* engine); dnssec_policy_key *dnssec_policy_key_acquire_from_name(const char *id); void dnssec_policy_key_release(dnssec_policy_key *dpk); dnssec_policy_key_suite *dnssec_policy_key_suite_create(const char *id, dnssec_policy_key *dpk, dnssec_policy_roll *dpr); dnssec_policy_key_suite *dnssec_policy_key_suite_acquire_from_name(const char *id); void dnssec_policy_key_suite_acquire(dnssec_policy_key_suite *dpks); void dnssec_policy_key_suite_release(dnssec_policy_key_suite *dpks); dnssec_policy *dnssec_policy_create(char *name, ptr_vector *key_suite); dnssec_policy *dnssec_policy_acquire_from_name(const char *id); void dnssec_policy_acquire(dnssec_policy *dp); void dnssec_policy_release(dnssec_policy *dp); #define CONFIG_DNSSEC_POLICY(fieldname_) {#fieldname_,offsetof(CONFIG_TYPE, fieldname_), (config_set_field_function*)dnssec_policy_zone_desc_config, NULL,{._intptr=0}, sizeof(dnssec_policy), sizeof(((CONFIG_TYPE*)0)->fieldname_), CONFIG_TABLE_SOURCE_NONE, CONFIG_FIELD_ALLOCATION_DIRECT }, ya_result dnssec_policy_zone_desc_config(const char *value, void *dest, anytype sizeoftarget); void dnssec_policy_initialise(); // remove all previously defined policies void dnssec_policy_finalize(); /** * @} */ yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/keyroll.h0000644000000000000000000000013214505005533021303 xustar000000000000000030 mtime=1695812443.260993904 30 atime=1695812445.786030067 30 ctime=1695812495.799746364 yadifa-2.6.5-11201/sbin/yakeyrolld/keyroll.h0000664000374500037450000002472214505005533021254 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once #include #include #include #include #ifndef PACKAGE_VERSION #include "keyroll-config.h" #endif #define YKEYROLL_NAME "yakeyrolld" #define YKEYROLL_VERSION PACKAGE_VERSION #define YKEYROLL_KSK_SUFFIX "_SECRET_KEYSIGNINGKEY" #define DNSKEY_TTL_DEFAULT 86400 #define KEYROLL_QUERY_TIMEOUT_S 10 // seconds #define KEYROLL_ERROR_BASE 0x80100000 #define KEYROLL_ERROR_CODE(code_) ((s32)(KEYROLL_ERROR_BASE+(code_))) #define KEYROLL_EXPECTED_IDENTICAL_RECORDS KEYROLL_ERROR_CODE(1) #define KEYROLL_EXPECTED_IDENTICAL_SIZE_RRSETS KEYROLL_ERROR_CODE(2) #define KEYROLL_EXPECTED_DNSKEY_OR_RRSIG KEYROLL_ERROR_CODE(3) #define KEYROLL_UPDATE_SUBCOMMAND_ERROR KEYROLL_ERROR_CODE(4) #define KEYROLL_HOLE_IN_TIMELINE KEYROLL_ERROR_CODE(5) #define KEYROLL_MUST_REINITIALIZE KEYROLL_ERROR_CODE(6) enum KeyrollAction { Publish = 1, Activate = 2, Deactivate = 4, Unpublish = 8 }; struct keyroll_s; typedef struct keyroll_step_s { struct keyroll_s* keyroll; // link back to the keyroll s64 epochus; ptr_vector dnskey_del; // keys added at this instant ptr_vector dnskey_add; // keys demoved at this instant ptr_vector rrsig_add; // signatures added at this instant ptr_vector expect; // dns_resource_record vector ptr_vector endresult; // dns_resource_record vector ptr_set file_add; // list of the files to be added + content ptr_vector file_del; // list of the files to be deleted u64 fingerprint; // number generated from dnskey_set, based on currently present tags u8 keyroll_action; bool dirty; bool from_merge; } keyroll_step_t; typedef struct keyroll_key_parameters_s { u32 activate_after; // publish + u32 deactivate_after; // publish + u32 delete_after; // publish + u32 estimated_signing_time; u16 size; u8 algorithm; } keyroll_key_parameters_t; typedef struct keyroll_s { u8 *domain; host_address *server; dnskey_keyring *keyring; char *plan_path; char *keys_path; char *private_keys_path; u64_set steps; keyroll_key_parameters_t ksk_parameters; keyroll_key_parameters_t zsk_parameters; s64 ksk_next_deactivation; s64 zsk_next_deactivation; u32 update_apply_verify_retries; // if an update wasn't applied successfully, retry CHECKING this amount of times u32 update_apply_verify_retries_delay; // time between the above retries u32 match_verify_retries; // if there is not match, retry checking this amount of times u32 match_verify_retries_delay; // time between the above retries u32 steps_count; bool generation_mode; // current key records } keyroll_t; void keyroll_errors_register(); s64 keyroll_set_timing_steps(keyroll_t *keyroll, dnssec_key *key, bool dirty); /** * Keyroll initialisation for a domain * * @param domain the domain * @param plan_path the directory containing the plan files (the sequence of steps) * @param keys_path the directory where to put the keys * @param server the server address */ ya_result keyroll_init(keyroll_t* keyroll, const u8 *domain, const char *plan_path, const char *keys_path, const host_address *server, bool generation_mode); /** * Connects to the server, fetches the public keys and add them to the keyring. */ ya_result keyroll_fetch_public_keys_from_server(keyroll_t* keyroll); /** * Does an keyroll_init followed by a keyroll_fetch_public_keys_from_server. */ ya_result keyroll_init_from_server(keyroll_t* keyroll, const u8 *domain, const char *plan_path, const char *keys_path, const host_address *server); ya_result keyroll_update_apply_verify_retries_set(keyroll_t* keyroll, u32 retries, u32 delay); ya_result keyroll_match_verify_retries_set(keyroll_t* keyroll, u32 retries, u32 delay); void keyroll_finalize(keyroll_t *keyroll); /** * Generates a DNSKEY to be published at the given epoch. * The DNSKEY can be set as a KSK or ZSK using the ksk parameter. * This function creates steps at the various time fields of the key. */ ya_result keyroll_generate_dnskey(keyroll_t *keyroll, s64 publication_epochus, bool ksk); /** * Generates a DNSKEY to be published at the given epoch. * The DNSKEY can be set as a KSK or ZSK using the ksk parameter. * This functions requires the time fields to be set manually. * This function creates steps at the various time fields of the key. */ ya_result keyroll_generate_dnskey_ex(keyroll_t *keyroll, u32 size, u8 algorithm, s64 creation_epochus, s64 publication_epochus, s64 activate_epochus, s64 deactivate_epochus, s64 unpublish_epochus, bool ksk, dnssec_key **out_keyp); /** * Returns the step at the given epoch, or create an empty one */ keyroll_step_t* keyroll_get_step(keyroll_t *keyroll, s64 epochus); /** * Queries the server for its current state (DNSKEY + RRSIG DNSKEY records) * * Appends found dns_resource_record* to the ptr_vector * * The ptr_vector is expected to be initialised and empty, or at the very least only filled with * dns_resource_record* * */ ya_result keyroll_dnskey_state_query(const keyroll_t *keyroll, ptr_vector *current_dnskey_rrsig_rr); /** * Releases the memory used by dns_resource_record* in the ptr_vector */ void keyroll_dnskey_state_destroy(ptr_vector *current_dnskey_rrsig_rr); /** * Compares the expected state at a given step with the state on the server * (queried with keyroll_dnskey_state_query) * * Returns SUCCESS iff it's a match. */ ya_result keyroll_step_expects_matched(const keyroll_step_t *step, const ptr_vector *dnskey_rrsig_rr); /** * Scans the plan for the step matching the given state * * Returns the matching step or NULL */ keyroll_step_t* keyroll_step_scan_matching_expectations(const keyroll_t *keyroll, ptr_vector *current_dnskey_rrsig_rr); /** * Plays a step on the server * * @param step the step to play * @param delete_all_dnskey delete all keys on the server. */ ya_result keyroll_step_play(const keyroll_step_t *step, bool delete_all_dnskey); /** * Plays all the steps in a given epoch range. */ ya_result keyroll_step_play_range_ex(const keyroll_t *keyroll, s64 seek_from , s64 now, bool delete_all_dnskey, keyroll_step_t **first_stepp); /** * Plays all the steps in a given epoch range. */ ya_result keyroll_step_play_range(const keyroll_t *keyroll, s64 seek_from , s64 now); /** * Plays the first step of a plan if it's before a given epoch. * If the first step is in the future, it's not played. * Returns the first step in the parameter. * Returns an error code. */ ya_result keyroll_play_first_step(const keyroll_t *keyroll, s64 now, keyroll_step_t **first_stepp); /** * Returns the step being active at the given epoch or NULL if there is no such step. * If a step starts at the given epoch, it's the one returned. */ keyroll_step_t* keyroll_get_current_step_at(const keyroll_t *keyroll, s64 epochus); /** * Returns the next step to be active from the given epoch or NULL if there is no such step. * If a step starts at the given epoch, it's the one returned. */ keyroll_step_t* keyroll_get_next_step_from(const keyroll_t *keyroll, s64 epochus); /** * Destroys all the .keyroll, .key and .private files of a plan (obviously dangerous) */ ya_result keyroll_plan_purge(keyroll_t *keyroll); /** * Loads a plan from disk (all the steps). * Loads KSK private keys if they are available. */ ya_result keyroll_plan_load(keyroll_t *keyroll); /** * Generates a plan using a DNSSEC policy. */ ya_result keyroll_plan_with_policy(keyroll_t *keyroll, s64 generate_from, s64 generate_until, const char* policy_name); /** * Generates a simple plan. * Do not use this. * Use the DNSSEC policy one instead. */ ya_result keyroll_plan(keyroll_t *keyroll, s64 generate_until); /** * Prints a step. */ void keyroll_step_print(keyroll_step_t *step); /** * Prints a plan. */ ya_result keyroll_print(keyroll_t *keyroll, output_stream *os); /** * Prints a plan to the given output stream in a JSON format. */ ya_result keyroll_print_json(keyroll_t *keyroll, output_stream *os); /** * Stores the plan on disk (several files, private KSK files, ...) */ ya_result keyroll_store(keyroll_t *keyroll); ya_result keyroll_get_state_find_match_and_play(const keyroll_t *keyrollp, s64 now, const keyroll_step_t *current_step, const keyroll_step_t ** matched_stepp); /** * Enables or disables dryrun mode (no updates is ever sent) */ void keyroll_set_dryrun_mode(bool enabled); u32 keyroll_deactivation_margin(u32 activate_epoch, u32 deactivate_epoch, u32 delete_epoch); yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/main.c0000644000000000000000000000013114505005533020540 xustar000000000000000029 mtime=1695812443.25999389 30 atime=1695812445.785030053 30 ctime=1695812495.801746393 yadifa-2.6.5-11201/sbin/yakeyrolld/main.c0000664000374500037450000013133114505005533020505 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup test * @ingroup test * @brief skeleton file * * * Query for all DNSKEYs * * Generate KSK (Publish: none, Active: now, Inactive: never, Delete: never) + ZSK (Publish none: Active +60s, Inactive +180s, Delete: never) * Remove all DNSKEYs and add KSK and ZSK * * loop: * Generate ZSK (Publish none: Active +60s, Inactive +180s, Delete: never) * Wait for update time + 60 seconds. * Remove previous ZSK and add new ZSK * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "keyroll.h" #include "keyroll-config.h" #include "config-dnssec-policy.h" #include "dnssec-policy.h" #include "buildinfo.h" #define PURGE_QUESTION "YES" extern logger_handle *g_dnssec_logger; extern logger_handle *g_keyroll_logger; #define MODULE_MSG_HANDLE g_keyroll_logger #define FIRST_JANUARY_2019_00_00_00 1546300800 #define FIRST_JANUARY_2021_00_00_00 1609459200 #define SERVER_FAILURE_RETRY_DELAY 30 #define CONSECUTIVE_ERRORS_BEFORE_RESTART 60 #define WAIT_MARGIN (ONE_SECOND_US * 10) #define PROGRAM_NAME "yakeyrolld" #define KEYROLL_CONFIG_SECTION "yakeyrolld" #define RELEASEDATE YADIFA_DNSCORE_RELEASE_DATE // mount -t tmpfs -o size=16384 tmpfs /registry/yadifa/var/log/yakeyrolld static random_ctx rnd; enum PROGRAM_MODE { NONE = 0, GENERATE, PLAY, PLAYLOOP, PRINT, PRINT_JSON, TEST }; static value_name_table program_mode_enum_table[]= { {NONE, "none"}, {PLAY, "play"}, {PLAYLOOP, "playloop"}, {GENERATE, "generate"}, {PRINT, "print"}, {PRINT_JSON, "print-json"}, {TEST, "test"}, {0, NULL} }; struct main_args { ptr_vector domains; ptr_vector fqdns; char *configuration_file_path; char *log_path; char *keys_path; char *plan_path; char *pid_path; char *pid_file; char *generate_from; char *generate_until; char *policy_name; host_address *server; uid_t uid; gid_t gid; u32 timeout; u32 ttl; u32 update_apply_verify_retries; // if an update wasn't applied successfully, retry CHECKING this amount of times u32 update_apply_verify_retries_delay; // time between the above retries u32 match_verify_retries; // if there is not match, retry checking this amount of times u32 match_verify_retries_delay; // time between the above retries int program_mode; bool reset; bool purge; bool dryrun; bool wait_for_yadifad; bool daemonise; bool print_plan; bool user_confirmation; #if DEBUG bool with_secret_keys; #endif }; typedef struct main_args main_args; struct testing_args { s64 timeus_offset; }; typedef struct testing_args testing_args; static ya_result directory_writable(const char *path) { if(path == NULL) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } struct stat ds; if(stat(path, &ds) < 0) { int err = errno; log_err("error: '%s': %s", path, strerror(err)); formatln("error: '%s': %s", path, strerror(err)); return MAKE_ERRNO_ERROR(err); } if((ds.st_mode & S_IFMT) != S_IFDIR) { log_err("error: '%s' is not a directory", path); formatln("error: '%s' is not a directory", path); return INVALID_PATH; } ya_result ret; if(FAIL(ret = access_check(path, ACCESS_CHECK_READWRITE))) { formatln("error: '%s' is not writable as (%d:%d): %r", path, getuid(), getgid(), ret); } return ret; } #ifndef PREFIX #define PREFIX "/usr/local" #endif #ifndef LOCALSTATEDIR #define LOCALSTATEDIR PREFIX "/var" #endif #ifndef SYSCONFDIR #define SYSCONFDIR PREFIX "/etc" #endif #define CONFIGURATION_FILE_PATH_DEFAULT SYSCONFDIR "/yakeyrolld.conf" #define CONFIG_TYPE main_args CONFIG_BEGIN(main_args_desc) CONFIG_STRING_ARRAY(domains,NULL, 200) // I'm using a thread-pool for this, it cannot go beyond THREAD_POOL_SIZE_LIMIT_MAX threads. CONFIG_PATH(log_path, LOCALSTATEDIR "/log/yakeyrolld") // doc CONFIG_FILE(configuration_file_path, CONFIGURATION_FILE_PATH_DEFAULT) // cmdline CONFIG_PATH(keys_path, LOCALSTATEDIR "/zones/keys") // doc CONFIG_PATH(plan_path, LOCALSTATEDIR "/plans") // doc CONFIG_PATH(pid_path, LOCALSTATEDIR "/run") // doc CONFIG_STRING(pid_file, "yakeyrolld.pid") // doc CONFIG_HOST_LIST(server, "127.0.0.1") // doc CONFIG_U32(timeout, "3") // doc CONFIG_U32(ttl, "600") // doc CONFIG_U32_RANGE(update_apply_verify_retries, "60", 0, 3600) // doc // if an update wasn't applied successfully, retry CHECKING this amount of times CONFIG_U32_RANGE(update_apply_verify_retries_delay, "1", 1, 60) // doc // time between the above retries CONFIG_U32_RANGE(match_verify_retries, "60", 0, 3600) // doc // if there is not match, retry checking this amount of times CONFIG_U32_RANGE(match_verify_retries_delay, "1", 1, 60) // doc // time between the above retries CONFIG_STRING(generate_from, "now") // doc CONFIG_STRING(generate_until, "+1y") // doc CONFIG_STRING(policy_name, "") // doc CONFIG_UID(uid, "0") // doc CONFIG_GID(gid, "0") // doc CONFIG_BOOL(reset, "0") // cmdline CONFIG_BOOL(dryrun, "0") // cmdline CONFIG_BOOL(wait_for_yadifad, "1") // CONFIG_BOOL(daemonise, "0") // CONFIG_BOOL(print_plan, "0") // cmdline (!doc) CONFIG_BOOL(user_confirmation, "1") // cmdline (!doc) #if DEBUG CONFIG_BOOL(with_secret_keys, "0") // debug #endif CONFIG_ENUM(program_mode, "none", program_mode_enum_table) // cmdline CONFIG_ALIAS(policy, policy_name) CONFIG_ALIAS(domain, domains) CONFIG_ALIAS(daemon, daemonise) CONFIG_ALIAS(plans_path, plan_path) CONFIG_END(main_args_desc) #undef CONFIG_TYPE #define CONFIG_TYPE testing_args CONFIG_BEGIN(testing_args_desc) CONFIG_U64(timeus_offset, "0") CONFIG_END(testing_args_desc) CMDLINE_BEGIN(keyroll_cmdline) CMDLINE_VERSION_HELP(keyroll_cmdline) CMDLINE_SECTION(KEYROLL_CONFIG_SECTION) CMDLINE_OPT("config", 'c', "configuration_file_path") CMDLINE_HELP("", "sets the configuration file to use (default: " CONFIGURATION_FILE_PATH_DEFAULT ")") CMDLINE_OPT("mode", 'm', "program_mode") CMDLINE_HELP("", "sets the program mode (generate,play,playloop,print,json)") CMDLINE_OPT("domain",0,"domain") CMDLINE_HELP("fqdn", "the domain name, overrides the domains from the configuration file") CMDLINE_OPT("path",'p',"keys_path") CMDLINE_HELP("directory", "the directory where to store the keys") CMDLINE_OPT("server",'s',"server") CMDLINE_HELP("address", "the address of the server") CMDLINE_OPT("ttl",'t',"ttl") CMDLINE_HELP("seconds", "the TTL to use for both DNSKEY and RRSIG records") CMDLINE_BOOL("reset",0,"reset") CMDLINE_HELP("", "start by removing all the keys, create a new KSK and a new ZSK") CMDLINE_OPT("policy",0,"policy_name") CMDLINE_HELP("", "name of the policy to use") CMDLINE_OPT("from",0,"generate_from") CMDLINE_HELP("time", "at what time the plan starts (e.g. : now, -1y, YYYYMMDDHHSS in UTC).") CMDLINE_OPT("until",0,"generate_until") CMDLINE_HELP("time", "the upper time limit covered by the plan (+1y, YYYYMMDDHHSS in UTC).") CMDLINE_BLANK() CMDLINE_INDENT(4) CMDLINE_IMSG("", "time values can be:") CMDLINE_BLANK() CMDLINE_INDENT(4) CMDLINE_IMSG("", "now") CMDLINE_IMSG("", "tomorrow") CMDLINE_IMSG("", "yesterday") CMDLINE_IMSG("", "[+-]#{years|months|weeks|days|seconds} where # is an integer") CMDLINE_IMSG("", "YYYY-MM-DD") CMDLINE_IMSG("", "YYYYMMDD") CMDLINE_IMSG("", "YYYYMMDDHHMMSSUUUUUU") CMDLINE_BLANK() CMDLINE_INDENT(-8) CMDLINE_BOOL("dryrun",0,"dryrun") CMDLINE_HELP("", "do not send the update to the server") CMDLINE_BOOL("wait", 0, "wait_for_yadifad") CMDLINE_HELP("", "wait for yadifad to answer before starting to work (default)") CMDLINE_BOOL_NOT("nowait", 0, "wait_for_yadifad") CMDLINE_HELP("", "do not wait for yadifad to answer before starting to work") CMDLINE_BOOL("daemon", 0, "daemonise") CMDLINE_HELP("", "daemonise the program for supported modes (default)") CMDLINE_BOOL_NOT("nodaemon", 0, "daemonise") CMDLINE_HELP("", "do not daemonise the program (needed for systemd)") CMDLINE_BOOL_NOT("noconfirm",'Y', "user_confirmation") CMDLINE_HELP("", "do not ask for confirmation before destroying steps and .key and .private files") CMDLINE_BOOL("print-plan", 0, "print_plan") CMDLINE_HELP("", "prints the complete plan after generation or after loading") #if DEBUG CMDLINE_BOOL("with-secret-keys", 0, "with_secret_keys") #endif #if DEBUG CMDLINE_SECTION("testing") CMDLINE_OPT("timeus-offset", 0, "timeus_offset") CMDLINE_HELP("", "fakes the current time changing the time by that many seconds (testing)") #endif CMDLINE_BLANK() CMDLINE_END(keyroll_cmdline) static main_args g_config; // initilised in main_config(argc, argv) static testing_args g_testing = {0}; static void help_print(const char *name) { formatln("%s [-c configurationfile] [...]\n\n", name); cmdline_print_help(keyroll_cmdline, 16, 28, " : ", 48, termout); } /** * To abstract key generation or reading from storage */ static ya_result main_config_main_postprocess(struct config_section_descriptor_s *csd) { (void)csd; // no logger if help is requested if(cmdline_help_get() || cmdline_version_get()) { return SUCCESS; } config_set_log_base_path(g_config.log_path); keyroll_set_dryrun_mode(g_config.dryrun); logger_start(); logger_handle_create("keyroll", &g_keyroll_logger); logger_handle_create("dnssec", &g_dnssec_logger); timeus_set_offset(g_testing.timeus_offset); logger_flush(); return SUCCESS; } static void yakeyrolld_print_authors() { print("\n" "\t\tYADIFAD authors:\n" "\t\t---------------\n" "\t\t\n" "\t\tGery Van Emelen\n" "\t\tEric Diaz Fernandez\n" "\n" "\t\tContact: " PACKAGE_BUGREPORT "\n" ); flushout(); } static void yakeyrolld_show_version(u8 level) { switch(level) { case 1: osformatln(termout, "%s %s (%s)\n", YKEYROLL_NAME, YKEYROLL_VERSION, RELEASEDATE); break; case 2: #if HAS_BUILD_TIMESTAMP && defined(__DATE__) osformatln(termout, "%s %s (released %s, compiled %s)\n\nbuild settings: %s\n", YKEYROLL_NAME, YKEYROLL_VERSION, RELEASEDATE, __DATE__, BUILD_OPTIONS); #else osformatln(termout, "%s %s (released %s)\n\nbuild settings: %s\n", YKEYROLL_NAME, YKEYROLL_VERSION, RELEASEDATE, BUILD_OPTIONS); #endif break; case 3: default: #if HAS_BUILD_TIMESTAMP && defined(__DATE__) osformatln(termout, "%s %s (released %s, compiled %s)\n", PROGRAM_NAME, YKEYROLL_VERSION, RELEASEDATE, __DATE__); #else osformatln(termout, "%s %s (released %s)\n", YKEYROLL_NAME, YKEYROLL_VERSION, RELEASEDATE); #endif yakeyrolld_print_authors(); break; } flushout(); } /** * Reads the configuration. * It's only a command line but extending to a file is relatively trivial. */ static ya_result main_config(int argc, char *argv[]) { config_error_s cfg_error; ya_result ret; config_init(); memset(&g_config, 0, sizeof(g_config)); ptr_vector_init(&g_config.domains); ptr_vector_init(&g_config.fqdns); int priority = 0; if(FAIL(ret = config_register_cmdline(priority++))) // without this line, the help will not work { return ret; } if(FAIL(ret = config_register_struct(KEYROLL_CONFIG_SECTION, main_args_desc, &g_config, priority++))) { return ret; } if(FAIL(ret = config_register_struct("testing", testing_args_desc, &g_testing, priority++))) { return ret; } // hook the post-processing to know what to do with the logger // this is a bit dirty but the vtbl is a copy of an original and the const is a safeguard here // I'll need to add a registration function that allows to overwrite these. // also registers key-roll denial key-template and key-suite (hence the + 5) if(FAIL(ret = config_register_dnssec_policy(NULL, priority))) { return ret; } priority += 5; if(FAIL(ret = config_register_logger(NULL, NULL, priority))) { return ret; } // priority += 2; // shouldn't this be 2 sources instead of twice one ? struct config_source_s sources[1]; if(FAIL(ret = config_source_set_commandline(&sources[0], keyroll_cmdline, argc, argv))) { formatln("command line definition: %r", ret); return ret; } if(FAIL(ret = config_read_from_sources(sources, 1, &cfg_error))) { if(cmdline_help_get()) { help_print(argv[0]); ret = SUCCESS; } else if(cmdline_version_get()) { yakeyrolld_show_version(cmdline_version_get()); ret = SUCCESS; } else { formatln("settings: (%s:%i) %s: %s: %r", cfg_error.file, cfg_error.line_number, cfg_error.line, cfg_error.variable_name, ret); } flushout(); return ret; } if(cmdline_help_get()) { help_print(argv[0]); return SUCCESS; } if(cmdline_version_get()) { yakeyrolld_show_version(cmdline_version_get()); return SUCCESS; } config_source_set_file(&sources[0], g_config.configuration_file_path, CONFIG_SOURCE_FILE); config_section_descriptor_s *main_desc = config_section_get_descriptor(KEYROLL_CONFIG_SECTION); config_section_descriptor_vtbl_s *vtbl = (config_section_descriptor_vtbl_s*)main_desc->vtbl; vtbl->postprocess = main_config_main_postprocess; if(FAIL(ret = config_read_from_sources(sources, 1, &cfg_error))) { formatln("settings: (%s:%i) %s %s: %r", cfg_error.file, cfg_error.line_number, cfg_error.line, cfg_error.variable_name, ret); flushout(); return ret; } if(g_config.server->port == 0) { g_config.server->port = NU16(DNS_DEFAULT_PORT); } for(int i = 0; i <= ptr_vector_last_index(&g_config.domains); ++i) { const char *name = (const char*)ptr_vector_get(&g_config.domains, i); u8 *fqdn = dnsname_zdup_from_name(name); if(fqdn == NULL) { formatln("cannot parse domain name: %s", name); ret = PARSESTRING_ERROR; return ret; } ptr_vector_append(&g_config.fqdns, fqdn); } // no stdout channel in daemon mode if(!((g_config.program_mode == PLAYLOOP) && g_config.daemonise)) { if(!config_logger_isconfigured()) { output_stream stdout_os; logger_channel *stdout_channel; fd_output_stream_attach(&stdout_os, dup_ex(1)); buffer_output_stream_init(&stdout_os, &stdout_os, 65536); stdout_channel = logger_channel_alloc(); if(stdout_channel == NULL) { return INVALID_STATE_ERROR; } logger_channel_stream_open(&stdout_os, FALSE, stdout_channel); logger_channel_register("stdout", stdout_channel); #if !DEBUG logger_handle_add_channel("keyroll", MSG_PROD_MASK, "stdout"); #else logger_handle_add_channel("keyroll", MSG_ALL_MASK, "stdout"); logger_handle_add_channel("dnssec", MSG_ALL_MASK, "stdout"); #endif } } if(FAIL(ret = directory_writable(g_config.log_path))) { return ret; } return ret; } static ya_result get_user_confirmation() { ya_result ret = SUCCESS; log_notice("Asking user to confirm by typing '" PURGE_QUESTION "'"); print("Please confirm by typing '" PURGE_QUESTION "' (without the '') followed by the ENTER key: "); flushout(); char *line_buffer = NULL; size_t line_buffer_size = 0; ssize_t n = getline(&line_buffer, &line_buffer_size, stdin); if(n < 0) { ret = ERRNO_ERROR; formatln("getline failed: %r", ret); flushout(); free(line_buffer); return ret; } while((n > 0) && isspace(line_buffer[--n])) { line_buffer[n] = '\0'; } if(strcmp(line_buffer, PURGE_QUESTION) != 0) { log_err("expected: '" PURGE_QUESTION "', got '%s': stopping", line_buffer); formatln("expected: '" PURGE_QUESTION "', got '%s': stopping", line_buffer); flushout(); free(line_buffer); return PARSEWORD_NOMATCH_ERROR; } else { log_notice("Got user confirmation"); } return ret; } static ya_result program_mode_generate(const u8 *domain) { ya_result ret; rnd = random_init(0); if(dirent_get_file_type(g_config.plan_path, ".") == DT_UNKNOWN) { formatln("%{dnsname}: having trouble with directory '%s'", domain, g_config.plan_path); return INVALID_PATH; } keyroll_t keyroll; if(FAIL(ret = keyroll_init(&keyroll, domain, g_config.plan_path, g_config.keys_path, g_config.server, TRUE))) { return ret; } if(FAIL(ret = keyroll_update_apply_verify_retries_set(&keyroll, g_config.update_apply_verify_retries, g_config.update_apply_verify_retries_delay))) { log_err("%{dnsname}: update apply retry combination out of acceptable range", domain); formatln("%{dnsname}: update apply retry combination out of acceptable range", domain); keyroll_finalize(&keyroll); return ret; } if(FAIL(ret = keyroll_match_verify_retries_set(&keyroll, g_config.match_verify_retries, g_config.match_verify_retries_delay))) { log_err("%{dnsname}: match retry combination out of acceptable range", domain); formatln("%{dnsname}: match retry combination out of acceptable range", domain); keyroll_finalize(&keyroll); return ret; } // at this point: // _ we know the present state on the server // _ we know the plan folder for this domain exists if(g_config.reset) { // delete the content of the plan folder if(!g_config.dryrun) { log_info("%{dnsname}: deleting the plan and private keys for domain", keyroll.domain); formatln("%{dnsname}: deleting the plan and private keys for domain", keyroll.domain); keyroll_plan_purge(&keyroll); } else { log_info("%{dnsname}: dryrun: not really deleting the plan and private keys for domain", keyroll.domain); formatln("%{dnsname}: dryrun: not really deleting the plan and private keys for domain", keyroll.domain); } } else { if(FAIL(ret = keyroll_plan_load(&keyroll))) { if(ret != MAKE_ERRNO_ERROR(ENOENT)) { log_err("%{dnsname}: plan loading failed: %r", keyroll.domain, ret); formatln("%{dnsname}: plan loading failed: %r", keyroll.domain, ret); keyroll_finalize(&keyroll); return ret; } log_info("%{dnsname}: there are no plans for the domain in the directory '%s'", keyroll.domain, g_config.plan_path); formatln("%{dnsname}: there are no plans for the domain in the directory '%s'", keyroll.domain, g_config.plan_path); } } s64 generate_from = timeus_from_smarttime(g_config.generate_from); if(generate_from < 0) { log_err("%{dnsname}: cannot parse '%s'", domain, g_config.generate_from); formatln("%{dnsname}: cannot parse '%s'", domain, g_config.generate_from); keyroll_finalize(&keyroll); return ret; } generate_from /= ONE_SECOND_US; generate_from *= ONE_SECOND_US; s64 generate_until = timeus_from_smarttime_ex(g_config.generate_until, generate_from); if(generate_until < 0) { log_err("%{dnsname}: cannot parse '%s'", domain, g_config.generate_until); formatln("%{dnsname}: cannot parse '%s'", domain, g_config.generate_until); return ret; } log_info("%{dnsname}: covering %llU to %llU", domain, generate_from, generate_until); formatln("%{dnsname}: covering %llU to %llU", domain, generate_from, generate_until); if(FAIL(ret = keyroll_plan_with_policy(&keyroll, generate_from, generate_until, g_config.policy_name))) { log_err("%{dnsname}: policy-based planning failed: %r", domain, ret); formatln("%{dnsname}: policy-based planning failed: %r", domain, ret); return ret; } if(g_config.print_plan) { if(FAIL(ret = keyroll_print(&keyroll, termout))) { log_err("%{dnsname}: the plan is not perfect", domain); formatln("%{dnsname}: the plan is not perfect", domain); } } if(g_config.dryrun) { log_info("%{dnsname}: dryrun: not storing the plan", domain); formatln("%{dnsname}: dryrun: not storing the plan", domain); ret = SUCCESS; } else { if(ISOK(ret = keyroll_store(&keyroll))) { log_info("%{dnsname}: plan stored", domain); formatln("%{dnsname}: plan stored", domain); } else { log_err("%{dnsname}: failed to store the plan: %r", domain, ret); formatln("%{dnsname}: failed to store the plan: %r", domain, ret); } } keyroll_finalize(&keyroll); return ret; } static ya_result program_mode_generate_all() { pid_t pid; ya_result ret; char pid_file_path_buffer[PATH_MAX]; char *pid_file_path = &pid_file_path_buffer[0]; snformat(pid_file_path_buffer, sizeof(pid_file_path_buffer), "%s/%s", g_config.pid_path, g_config.pid_file); if(FAIL(ret = pid_check_running_program(pid_file_path, &pid))) { log_err("already running with pid: %lu (%s)", pid, pid_file_path); return ret; } if(FAIL(ret = directory_writable(g_config.plan_path))) { return ret; } if(ISOK(ret = server_setup_env(&pid, &pid_file_path, g_config.uid, g_config.gid, SETUP_CREATE_PID_FILE|SETUP_ID_CHANGE|SETUP_CORE_LIMITS))) { if(g_config.reset && g_config.user_confirmation) { println("WARNING: A full data reset has been required for the following domains:"); // delete the content of the plan folder for(int i = 0; i <= ptr_vector_last_index(&g_config.fqdns); ++i) { const u8 *domain = (const u8*)ptr_vector_get(&g_config.fqdns, i); formatln(" %{dnsname}", domain); } println("All currently stored steps and private keys for the above domains will be erased.\nThis operation cannot be undone."); if(FAIL(ret = get_user_confirmation())) { return ret; } } for(int i = 0; i <= ptr_vector_last_index(&g_config.fqdns); ++i) { const u8 *domain = (const u8*)ptr_vector_get(&g_config.fqdns, i); log_info("zone generate: %{dnsname}", domain); if(FAIL(ret = program_mode_generate(domain))) { log_err("zone generate: %{dnsname} failed: %r", domain, ret); break; } } unlink(pid_file_path); } return ret; } static void signal_int(u8 signum) { (void)signum; if(!dnscore_shuttingdown()) { dnscore_shutdown(); } signal_handler_stop(); } static void signal_hup(u8 signum) { (void)signum; logger_reopen(); } static ya_result program_mode_play(const u8 *domain, bool does_loop) { ya_result ret; int consecutive_errors = 0; rnd = random_init(0); if(dirent_get_file_type(g_config.plan_path, ".") == DT_UNKNOWN) { log_info("play: %{dnsname}: having trouble with directory '%s'", domain, g_config.plan_path); return INVALID_PATH; } keyroll_t keyroll; // start from an empty state if(FAIL(ret = keyroll_init(&keyroll, domain, g_config.plan_path, g_config.keys_path, g_config.server, FALSE))) { return ret; } // at this point: // _ we know the present state on the server // _ we know the plan folder for this domain exists if(does_loop) { log_info("play: %{dnsname}: loading plan", domain); logger_flush(); } if(FAIL(ret = keyroll_plan_load(&keyroll))) { if(ret != MAKE_ERRNO_ERROR(ENOENT)) { log_info("play: %{dnsname}: plan loading failed: %r", domain, ret); } else { log_info("play: %{dnsname}: there are no plans on storage (%s)", domain, g_config.plan_path); } logger_flush(); keyroll_finalize(&keyroll); return ret; } s64 step_time; do { step_time = timeus_with_offset(); log_info("play: %{dnsname}: now is %llU (%lli)", domain, step_time, step_time); keyroll_step_t *current_step = keyroll_get_current_step_at(&keyroll, step_time); if(current_step == NULL) { log_info("play: %{dnsname}: there are no steps registered for this time", domain); keyroll_finalize(&keyroll); return INVALID_STATE_ERROR; } log_info("play: %{dnsname}: the current step happened at %llU (%lli)", domain, current_step->epochus, current_step->epochus); keyroll_step_t *next_step = keyroll_get_next_step_from(&keyroll, step_time + 1); s64 next_step_time; if(next_step != NULL) { next_step_time = next_step->epochus; log_info("play: %{dnsname}: the step that will follow will happen at %llU (%lli)", domain, next_step_time, next_step_time); } else { next_step_time = ONE_SECOND_US * MAX_U32; } /* // check the expected set with the server // do a query for all DNSKEY + RRSIG and compare with the step ptr_vector current_dnskey_rrsig_rr; ptr_vector_init_ex(¤t_dnskey_rrsig_rr, 32); */ const keyroll_step_t *matched_step = NULL; ret = keyroll_get_state_find_match_and_play(&keyroll, step_time, current_step, &matched_step); if(ISOK(ret)) { log_info("play: %{dnsname}: first loop ended (%u)", domain, ret); break; } if(ret != STOPPED_BY_APPLICATION_SHUTDOWN) { log_info("play: %{dnsname}: keyroll_get_state_find_match returned %r (retrying in " TOSTRING(SERVER_FAILURE_RETRY_DELAY) " seconds)", domain, ret); s64 now = timeus(); if(now + ONE_SECOND_US * SERVER_FAILURE_RETRY_DELAY < next_step_time) { for(int i = 0; (i < SERVER_FAILURE_RETRY_DELAY) && !dnscore_shuttingdown(); ++i) { sleep(1); } } else { // we have gone through a step, current computations are invalid : restart the roll for this domain ret = KEYROLL_MUST_REINITIALIZE; keyroll_finalize(&keyroll); return ret; } } } while(g_config.wait_for_yadifad && !dnscore_shuttingdown()); if(FAIL(ret)) { log_notice("play: %{dnsname}: keyroll_get_state_find_match returned %r", domain, ret); keyroll_finalize(&keyroll); return ret; } keyroll_step_t *next_step = keyroll_get_next_step_from(&keyroll, step_time); if(next_step != NULL) { log_info("play: %{dnsname}: the next step happens at %llU (%lli)", domain, next_step->epochus, next_step->epochus); // find the interval for now s64 last_warning_us = 0; // wait until the next event while(!dnscore_shuttingdown()) { log_info("play: %{dnsname}: waiting until %llU (%lli)", domain, next_step->epochus, next_step->epochus); do { s64 now = timeus_with_offset(); if(now - WAIT_MARGIN >= next_step->epochus) { break; } else { usleep(MAX(MIN(next_step->epochus - (now - WAIT_MARGIN), WAIT_MARGIN), 1000)); } } while(!dnscore_shuttingdown()); if(dnscore_shuttingdown()) { log_info("play: %{dnsname}: shutting down", domain); logger_flush(); break; } step_time = timeus_with_offset(); keyroll_step_t *current_step = keyroll_get_current_step_at(&keyroll, step_time); if(current_step == NULL) { log_err("play: %{dnsname}: there are no steps registered for this time: shutting down", domain); break; } ret = keyroll_get_state_find_match_and_play(&keyroll, step_time, current_step, NULL); log_warn("play: %{dnsname}: match and play returned: %r (%x)", domain, ret, ret); if(ISOK(ret)) { consecutive_errors = 0; } else { // test for error conditions warranting a retry switch(ret) { case MAKE_ERRNO_ERROR(ETIMEDOUT): case MAKE_ERRNO_ERROR(EADDRNOTAVAIL): case MAKE_ERRNO_ERROR(EAGAIN): case MAKE_RCODE_ERROR(RCODE_SERVFAIL): case MAKE_RCODE_ERROR(RCODE_REFUSED): case MAKE_ERRNO_ERROR(ECONNREFUSED): case UNABLE_TO_COMPLETE_FULL_READ: { ++consecutive_errors; if(consecutive_errors < CONSECUTIVE_ERRORS_BEFORE_RESTART) { step_time = timeus_with_offset(); if(step_time - last_warning_us >= ONE_SECOND_US * 60) { log_warn("play: %{dnsname}: step play failure: %r: trying again (this message will only be printed every minute)", domain, ret); last_warning_us = step_time; } sleep(1); continue; } else { log_warn("play: %{dnsname}: step play failure: %r: restarting", domain, ret); ret = KEYROLL_MUST_REINITIALIZE; break; } } default: { // unrecoverable error log_err("play: %{dnsname}: step play failure: %r (%x): shutting down. Please restart after fixing the issue.", domain, ret, ret); break; } } break; } if(!does_loop) { break; } next_step = keyroll_get_next_step_from(&keyroll, next_step->epochus + 1); } } else { log_info("play: %{dnsname}: there is no next step recorded after %llU", domain, step_time); } keyroll_finalize(&keyroll); return ret; } struct program_mode_play_thread_args { const u8 *fqdn; bool does_loop; }; typedef struct program_mode_play_thread_args program_mode_play_thread_args; static void* program_mode_play_thread(void *args_) { program_mode_play_thread_args *args = (program_mode_play_thread_args*)args_; while(!dnscore_shuttingdown()) { ya_result ret = program_mode_play(args->fqdn, args->does_loop); if(ISOK(ret)) { log_info("%{dnsname}: key roll stopped", args->fqdn); break; } else { if(ret == KEYROLL_MUST_REINITIALIZE) { log_warn("%{dnsname}: trying again from the start", args->fqdn); } else if(ret == STOPPED_BY_APPLICATION_SHUTDOWN) { log_warn("%{dnsname}: keyroll is shutting down", args->fqdn); break; } else { log_err("%{dnsname}: shutting down (%r)", args->fqdn, ret); logger_flush(); dnscore_shutdown(); break; } } } return NULL; } static ya_result program_mode_play_all(bool does_loop, bool daemonise) { ya_result ret; pid_t pid; char pid_file_path_buffer[PATH_MAX]; char *pid_file_path = &pid_file_path_buffer[0]; snformat(pid_file_path_buffer, sizeof(pid_file_path_buffer), "%s/%s", g_config.pid_path, g_config.pid_file); if(FAIL(ret = pid_check_running_program(pid_file_path, &pid))) { log_err("already running with pid: %lu (%s)", pid, pid_file_path); return ret; } if(FAIL(ret = directory_writable(g_config.keys_path))) { return ret; } if(ISOK(ret = server_setup_env(&pid, &pid_file_path, g_config.uid, g_config.gid, SETUP_CREATE_PID_FILE|SETUP_ID_CHANGE|SETUP_CORE_LIMITS))) { if(daemonise) { if(!does_loop) { log_warn("daemonise requires to enable loops"); does_loop = true; } signal_handler_finalize(); server_setup_daemon_go(); u32 setup_flags = SETUP_CORE_LIMITS | SETUP_ID_CHANGE | SETUP_CREATE_PID_FILE; if(FAIL(ret = server_setup_env(NULL, &pid_file_path, g_config.uid, g_config.gid, setup_flags))) { log_err("server setup failed: %r", ret); return EXIT_FAILURE; } if(FAIL(ret = signal_handler_init())) { log_err("failed to setup the signal handler: %r", ret); osformatln(termerr, "error: failed to setup the signal handler: %r", ret); flusherr(); logger_flush(); return ret; } signal_handler_set(SIGINT, signal_int); signal_handler_set(SIGTERM, signal_int); signal_handler_set(SIGHUP, signal_hup); } } else { log_err("server setup failed: %r", ret); return ret; } struct thread_pool_s *tp = thread_pool_init(ptr_vector_size(&g_config.fqdns), ptr_vector_size(&g_config.fqdns) * 2); if(tp != NULL) { program_mode_play_thread_args *args; MALLOC_OBJECT_ARRAY_OR_DIE(args, program_mode_play_thread_args, ptr_vector_size(&g_config.fqdns), GENERIC_TAG); thread_pool_task_counter counter; thread_pool_counter_init(&counter, 0); for(int i = 0; i <= ptr_vector_last_index(&g_config.fqdns); ++i) { char *domain = (char*)ptr_vector_get(&g_config.domains, i); u8 *fqdn = (u8*)ptr_vector_get(&g_config.fqdns, i); log_info("zone play: %{dnsname}", fqdn); args[i].fqdn = fqdn; // VS false positive (nonsense) args[i].does_loop = does_loop; thread_pool_enqueue_call(tp, program_mode_play_thread, &args[i], &counter, domain); } // ensure the counter was incremented thread_pool_wait_queue_empty(tp); // wait for the shutdown or for workers to stop for(;;) { ret = thread_pool_counter_wait_equal_with_timeout(&counter, 0, ONE_SECOND_US * 30); log_debug("keyroll: waiting for the threads to stop (%r)", ret); if(dnscore_shuttingdown()) { break; } } s64 wait_stop_begin = timeus(); bool wait_stop_error_message = FALSE; for(u32 wait_count = 0; thread_pool_counter_get_value(&counter) > 0; ++wait_count) { sleep(1); s64 wait_stop_now = timeus(); s64 wait_stop_duration = wait_stop_now - wait_stop_begin; if(dnscore_shuttingdown() && (wait_stop_duration > (ONE_SECOND_US * 30)) ) { if(!wait_stop_error_message) { log_err("keyroll workers aren't stopping"); logger_flush(); wait_stop_error_message = TRUE; } if(wait_stop_duration > (ONE_SECOND_US * 60)) { log_err("not waiting anymore"); logger_flush(); } } } thread_pool_destroy(tp); tp = NULL; free(args); } else { log_err("failed to create the thread pool: %r", THREAD_CREATION_ERROR); } if(does_loop) { log_info("keyroll stopped"); } unlink(pid_file_path); return SUCCESS; } static ya_result program_mode_print(const u8 *domain) { ya_result ret; if(dirent_get_file_type(g_config.plan_path, ".") == DT_UNKNOWN) { log_info("print: %{dnsname}: having trouble with directory '%s'", domain, g_config.plan_path); return INVALID_PATH; } keyroll_t keyroll; // start from an empty state if(FAIL(ret = keyroll_init(&keyroll, domain, g_config.plan_path, g_config.keys_path, g_config.server, FALSE))) { return ret; } // at this point: // _ we know the present state on the server // _ we know the plan folder for this domain exists if(FAIL(ret = keyroll_plan_load(&keyroll))) { if(ret != MAKE_ERRNO_ERROR(ENOENT)) { log_info("print: %{dnsname}: plan loading failed: %r", domain, ret); formatln("print: %{dnsname}: plan loading failed: %r", domain, ret); } else { log_info("print: %{dnsname}: there are no plans on storage (%s)", domain, g_config.plan_path); formatln("print: %{dnsname}: there are no plans on storage (%s)", domain, g_config.plan_path); } return ret; } ret = keyroll_print(&keyroll, termout); return ret; } static ya_result program_mode_print_json(const u8 *domain) { ya_result ret; if(dirent_get_file_type(g_config.plan_path, ".") == DT_UNKNOWN) { log_info("print: %{dnsname}: having trouble with directory '%s'", domain, g_config.plan_path); return INVALID_PATH; } keyroll_t keyroll; // start from an empty state if(FAIL(ret = keyroll_init(&keyroll, domain, g_config.plan_path, g_config.keys_path, g_config.server, FALSE))) { return ret; } // at this point: // _ we know the present state on the server // _ we know the plan folder for this domain exists if(FAIL(ret = keyroll_plan_load(&keyroll))) { if(ret != MAKE_ERRNO_ERROR(ENOENT)) { log_info("print: %{dnsname}: plan loading failed: %r", domain, ret); formatln("print: %{dnsname}: plan loading failed: %r", domain, ret); } else { log_info("print: %{dnsname}: there are no plans on storage (%s)", domain, g_config.plan_path); formatln("print: %{dnsname}: there are no plans on storage (%s)", domain, g_config.plan_path); } return ret; } ret = keyroll_print_json(&keyroll, termout); return ret; } static ya_result program_mode_test() { return SUCCESS; } int main(int argc, char *argv[]) { /* initializes the core library */ dnscore_init(); keyroll_errors_register(); ya_result ret = main_config(argc, argv); if(FAIL(ret)) { return EXIT_FAILURE; } if(cmdline_help_get() || cmdline_version_get()) { return EXIT_SUCCESS; } if(g_config.dryrun) { println("dryrun mode"); log_notice("dryrun mode"); } if(ptr_vector_size(&g_config.fqdns) == 0) { log_err("No domain has been configured."); println("No domain has been configured."); flushout(); return EXIT_FAILURE; } signal_handler_init(); signal_handler_set(SIGINT, signal_int); signal_handler_set(SIGTERM, signal_int); signal_handler_set(SIGHUP, signal_hup); flushout(); flusherr(); logger_flush(); switch(g_config.program_mode) { case NONE: { println("\nno -m option given\n"); help_print(argv[0]); break; } case GENERATE: { ret = program_mode_generate_all(); break; } case PLAY: { ret = program_mode_play_all(FALSE, FALSE); break; } case PLAYLOOP: { ret = program_mode_play_all(TRUE, g_config.daemonise); break; } case PRINT: { for(int i = 0; i <= ptr_vector_last_index(&g_config.fqdns); ++i) { u8 *fqdn = (u8*)ptr_vector_get(&g_config.fqdns, i); program_mode_print(fqdn); } break; } case PRINT_JSON: { formatln("{\"version\": \"" YKEYROLL_VERSION "\", \"plans\": ["); for(int i = 0; i <= ptr_vector_last_index(&g_config.fqdns); ++i) { if(i > 0) { println(","); } u8 *fqdn = (u8*)ptr_vector_get(&g_config.fqdns, i); program_mode_print_json(fqdn); } println("]}"); break; } case TEST: { ret = program_mode_test(); break; } default: { ret = INVALID_STATE_ERROR; break; } } if(FAIL(ret)) { log_err("failed with: %r", ret); osformatln(termerr, "failed with: %r", ret); } flushout(); flusherr(); fflush(NULL); signal_handler_finalize(); dnscore_finalize(); return ISOK(ret)?EXIT_SUCCESS:EXIT_FAILURE; } yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/config-dnssec-policy.c0000644000000000000000000000013214505005533023634 xustar000000000000000030 mtime=1695812443.254993818 30 atime=1695812445.785030053 30 ctime=1695812495.803746422 yadifa-2.6.5-11201/sbin/yakeyrolld/config-dnssec-policy.c0000664000374500037450000003344714505005533023611 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup configuration * @brief */ #include #include #include #include #include "dnssec-policy.h" #include "config-dnssec-policy.h" /*----------------------------------------------------------------------------*/ #pragma mark DEFINES #define DP_FLAGS_WEAKER_KEY 0x01 #define DP_FLAGS_STRONGER_KEY 0x02 #define DP_KEY_SUITE_SIZE 4 /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES #define POLICYCF_TAG 0x46435943494c4f50 static ptr_set dnssec_policy_desc_set = PTR_SET_ASCIIZ_EMPTY; /*----------------------------------------------------------------------------*/ #pragma mark CONFIG // dnssec-policy container #define CONFIG_TYPE dnssec_policy_desc_s CONFIG_BEGIN(config_section_dnssec_policy_desc) CONFIG_STRING( id, NULL ) CONFIG_STRING( description, NULL ) CONFIG_STRING_ARRAY( key_suite, NULL, DP_KEY_SUITE_SIZE ) CONFIG_U32_RANGE( ds_ttl, "3600", 0, MAX_S32 ) CONFIG_FLAG8( weaker_key_removal, "0", flags, DP_FLAGS_WEAKER_KEY ) /// @note 20211109 edf -- unused, for now CONFIG_FLAG8( stronger_key_removal, "0", flags, DP_FLAGS_STRONGER_KEY) /// @note 20211109 edf -- unused, for now CONFIG_U8( max_key, "2" ) /// @note it's the maximum number of key suites /* alias, aliased */ CONFIG_ALIAS( max_keys, max_key ) CONFIG_END(config_section_dnssec_policy_desc) #undef CONFIG_TYPE /*----------------------------------------------------------------------------*/ #pragma mark STATIC FUNCTIONS static ya_result config_section_dnssec_policy_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_dnssec_policy_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)context; if(key != NULL) { return INVALID_ARGUMENT_ERROR; } return SUCCESS; } /** * @fn static ya_result config_section_dnssec_policy_init(struct config_section_descriptor_s *csd) * * @brief initializing of a section: * * @details * the initializing of section is a NOP. * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_dnssec_policy_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } /** * @fn static ya_result config_section_dnssec_policy_start(struct config_section_descriptor_s *csd) * * @brief * start of a section csd->base will be initialized * * @details * csd->base will be initialized with a new ptr_vector for key-suites * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_dnssec_policy_start(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: dnssec-policy: start"); #endif if(csd->base != NULL) { return INVALID_STATE_ERROR; } dnssec_policy_desc_s *dnssec_policy; MALLOC_OBJECT_OR_DIE(dnssec_policy, dnssec_policy_desc_s, POLICYCF_TAG); ZEROMEMORY(dnssec_policy, sizeof(dnssec_policy_desc_s)); ptr_vector_init(&dnssec_policy->key_suite); csd->base = dnssec_policy; return SUCCESS; } /** * @fn static ya_result config_section_dnssec_policy_stop(struct config_section_descriptor_s *csd) * * @brief * stop of a section csd->base set to NULL --> ready for the * next section * * @details * global variable dnssec_policy_desc_set will have a new node (node->value = dnssec_policy) for a * new id (node->id) * 'dnssec-policy' is put in a binary tree for easy access when they need to be translated in the correct structure for 'yadifad' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_dnssec_policy_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: dnssec-policy: stop"); #endif // NOP dnssec_policy_desc_s *dnssec_policy = (dnssec_policy_desc_s *) csd->base; csd->base = NULL; if(dnssec_policy->id == NULL) { formatln("config: dnssec-policy: id not set"); return CONFIG_SECTION_ERROR; } if(ptr_vector_size(&dnssec_policy->key_suite) < 1) { formatln("config: dnssec-policy: %s: no key-suite has been set", dnssec_policy->id); return CONFIG_SECTION_ERROR; } ptr_node *node = ptr_set_insert(&dnssec_policy_desc_set, dnssec_policy->id); if(node->value == NULL) { node->value = dnssec_policy; return SUCCESS; } else { formatln("config: dnssec-policy: %s: already defined", dnssec_policy->id); return CONFIG_SECTION_ERROR; } } /** * @fn static ya_result config_section_dnssec_policy_postprocess(struct config_section_descriptor_s *csd) * * @brief create dnssec-policies structure to be used by 'yadifad' * * @details * check for a dnssec-policy node that all 'key_suites' are present and 'denial' is present * if they are present add them to the global struct * * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_dnssec_policy_postprocess(struct config_section_descriptor_s *csd) { (void)csd; #if CONFIG_SETTINGS_DEBUG formatln("config: section: dnssec-policy: postprocess"); #endif ptr_set_iterator iter; ptr_set_iterator_init(&dnssec_policy_desc_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *dnssec_policy_node = ptr_set_iterator_next_node(&iter); dnssec_policy_desc_s *dnssec_policy_desc = (dnssec_policy_desc_s *)dnssec_policy_node->value; if((ptr_vector_size(&dnssec_policy_desc->key_suite) < 1) || (ptr_vector_size(&dnssec_policy_desc->key_suite) > 2)) { formatln("config: dnssec-policy: %s: the dnssec-policy should have one (ZSK) or two (KSK and ZSK) key suites", dnssec_policy_desc->id); } bool has_zsk = FALSE; // get all sections for configuration // and put it in 'key_suites' ptr_vector key_suites = PTR_VECTOR_EMPTY; for(int i = 0; i <= ptr_vector_last_index(&dnssec_policy_desc->key_suite); ++i) { // get 'key-suite' name and check if it exists, if not return 'ERROR' const char *key_suite_name = (char*)ptr_vector_get(&dnssec_policy_desc->key_suite, i); dnssec_policy_key_suite *dpks = dnssec_policy_key_suite_acquire_from_name(key_suite_name); if(dpks != NULL) { if((dpks->key->flags & DNSKEY_FLAGS_KSK) == DNSKEY_FLAGS_ZSK) { has_zsk = TRUE; } ptr_vector_append(&key_suites, dpks); } else { formatln("config: dnssec-policy: %s: key suite '%s' not defined", dnssec_policy_desc->id, key_suite_name); return POLICY_KEY_SUITE_UNDEFINED; } } if(!has_zsk) { formatln("config: dnssec-policy: %s: at least one key suite with a ZSK is required", dnssec_policy_desc->id); return CONFIG_SECTION_ERROR; } // set the dnssec-policy structure for 'dnssec_policy_desc->id' with 'dd' and 'key_suites' // the value returned by dnssec_policy_create is also added to key_suites dnssec_policy_create(dnssec_policy_desc->id, &key_suites); // if done remove everything and for ' with 'dnssec_policy_desc->id' for(int i = 0; i <= ptr_vector_last_index(&key_suites); ++i) { dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)ptr_vector_get(&key_suites, i); dnssec_policy_key_suite_release(dpks); } ptr_vector_destroy(&key_suites); } return SUCCESS; } /** * @fn static void dnssec_policy_free(dnssec_policy_desc_s *dnssec_policy) * * @brief free dnssec_policy_desc_s completely * * @details * empty 'dnssec_policy' key_suite parameter and everything else * * @param[in,out] dnssec_policy_desc_s *dnssec_policy * * return -- */ static void dnssec_policy_free(dnssec_policy_desc_s *dnssec_policy) { free(dnssec_policy->id); free(dnssec_policy->description); ptr_vector_callback_and_clear(&dnssec_policy->key_suite, free); free(dnssec_policy); } /** * @fn static ya_result config_section_dnssec_policy_finalize(struct config_section_descriptor_s *csd) * * @brief free dnssec_policy_desc_s completely * * @details * empty 'dnssec_policy' * and free csd and set back to 'NULL' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_dnssec_policy_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { dnssec_policy_desc_s *dnssec_policy = (dnssec_policy_desc_s*)csd->base; dnssec_policy_free(dnssec_policy); #if DEBUG csd->base = NULL; #endif } free(csd); } return SUCCESS; } /*----------------------------------------------------------------------------*/ #pragma mark VIRTUAL TABLE static const config_section_descriptor_vtbl_s config_section_dnssec_policy_descriptor_vtbl = { "dnssec-policy", config_section_dnssec_policy_desc, // no table config_section_dnssec_policy_set_wild, config_section_dnssec_policy_print_wild, config_section_dnssec_policy_init, config_section_dnssec_policy_start, config_section_dnssec_policy_stop, config_section_dnssec_policy_postprocess, config_section_dnssec_policy_finalize }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result config_register_dnssec_policy(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * , , and are needed for * get all of them before registering all sections * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_dnssec_policy(const char *null_or_key_name, s32 priority) { (void)null_or_key_name; // get all sections , , and config_register_key_roll(NULL, priority); priority++; config_register_key_template(NULL, priority); priority++; config_register_key_suite(NULL, priority); priority++; // get the correct virtual table and register section from // the configuration config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_dnssec_policy_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // scan-build false positive: either it is freed, either it is stored in a global collection } yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/config-key-roll.c0000644000000000000000000000013114505005533022615 xustar000000000000000030 mtime=1695812443.251993775 30 atime=1695812445.785030053 29 ctime=1695812495.80574645 yadifa-2.6.5-11201/sbin/yakeyrolld/config-key-roll.c0000664000374500037450000003511614505005533022566 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup ### * @brief */ #include #include #include #include "config-dnssec-policy.h" #include "config-key-roll-parser.h" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES #define KEYROLCF_TAG 0x46434c4f5259454b static ptr_set key_roll_desc_set = PTR_SET_ASCIIZ_EMPTY; /*----------------------------------------------------------------------------*/ #pragma mark CONFIG // key-roll container #define CONFIG_TYPE key_roll_desc_s CONFIG_BEGIN(config_section_key_roll_desc) CONFIG_STRING(id, NULL) CONFIG_STRING(generate, NULL) CONFIG_STRING(publish, NULL) CONFIG_STRING(activate, NULL) CONFIG_STRING(inactive, NULL) CONFIG_STRING(remove, NULL) #if HAS_DS_PUBLICATION_SUPPORT CONFIG_STRING(ds_publish, NULL) CONFIG_STRING(ds_remove, NULL) #endif // if HAS_DS_PUBLICATION_SUPPORT> CONFIG_ALIAS(delete, remove) CONFIG_ALIAS(create, generate) CONFIG_ALIAS(created, generate) CONFIG_END(config_section_key_roll_desc) #undef CONFIG_TYPE #pragma mark STATIC FUNCTIONS static ya_result config_section_key_roll_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_key_roll_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)context; if(key != NULL) { return INVALID_ARGUMENT_ERROR; } return SUCCESS; } /** * @fn static ya_result config_section_key_roll_init(struct config_section_descriptor_s *csd) * * @brief initializing of a section: * * @details * the initializing of section is a NOP. * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_roll_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } /** * @fn static ya_result config_section_key_roll_start(struct config_section_descriptor_s *csd) * * @brief * start of a section csd->base will be initialized * * @details * csd->base will be initialized with key_roll * you can not have a start of a 'section' in a 'section' --> ERROR * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_roll_start(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_roll: start"); #endif if(csd->base != NULL) { return INVALID_STATE_ERROR; } key_roll_desc_s *key_roll; MALLOC_OBJECT_OR_DIE(key_roll, key_roll_desc_s, KEYROLCF_TAG); ZEROMEMORY(key_roll, sizeof(key_roll_desc_s)); csd->base = key_roll; return SUCCESS; } //#define KEY_ROLL_TOKEN_DELIMITER "" /** * @fn static ya_result config_section_key_roll_stop(struct config_section_descriptor_s *csd) * * @brief * stop of a section csd->base set to NULL --> ready for * parsing all items: generate, publish, activate, inactive, remove, ... * put the 'key-roll' in a binary tree with index key_roll->id * * @details * check if all items are there and of the correct types, otherwise give back an error * 'key-roll' is put in a binary tree for easy access when they need to be translated in the correct structure for 'yadifad' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_roll_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_roll: stop"); #endif key_roll_desc_s *key_roll = (key_roll_desc_s *) csd->base; if(key_roll->id == NULL) { formatln("config: key-roll: id not set"); return CONFIG_SECTION_ERROR; } ya_result return_code; key_roll_line_s krl_generate; key_roll_line_s krl_publish; key_roll_line_s krl_activate; key_roll_line_s krl_inactive; key_roll_line_s krl_remove; key_roll_line_s krl_ds_publish; key_roll_line_s krl_ds_remove; if(FAIL(return_code = config_key_roll_parser_line(key_roll->generate, &krl_generate, KR_ACTION_GENERATE))) { formatln("config: key-roll: %s: error in 'generate'", key_roll->id); return PARSE_INVALID_ARGUMENT; } if(FAIL(return_code = config_key_roll_parser_line(key_roll->publish, &krl_publish, KR_ACTION_GENERATE))) { formatln("config: key-roll: %s: error in 'publish'", key_roll->id); return PARSE_INVALID_ARGUMENT; } if(FAIL(return_code = config_key_roll_parser_line(key_roll->activate, &krl_activate, KR_ACTION_PUBLISH))) { formatln("config: key-roll: %s: error in 'activate'", key_roll->id); return PARSE_INVALID_ARGUMENT; } if(FAIL(return_code = config_key_roll_parser_line(key_roll->inactive, &krl_inactive, KR_ACTION_ACTIVATE))) { formatln("config: key-roll: %s: error in 'inactive'", key_roll->id); return PARSE_INVALID_ARGUMENT; } if(FAIL(return_code = config_key_roll_parser_line(key_roll->remove, &krl_remove, KR_ACTION_INACTIVE))) { formatln("config: key-roll: %s: error in 'remove'", key_roll->id); return PARSE_INVALID_ARGUMENT; } #if HAS_DS_PUBLICATION_SUPPORT if(FAIL(return_code = config_key_roll_parser_line(key_roll->ds_publish, &krl_ds_publish, KR_ACTION_DS_PUBLISH))) { if(return_code != PARSE_EMPTY_ARGUMENT) { return return_code; } else { /// @todo 20160610 gve -- still needs to write code for this } } if(FAIL(return_code = config_key_roll_parser_line(key_roll->ds_remove, &krl_ds_remove, KR_ACTION_DS_REMOVE))) { if(return_code != PARSE_EMPTY_ARGUMENT) { return return_code; } else { /// @todo 20160610 gve -- still needs to write code for this } return return_code; } #endif // if HAS_DS_PUBLICATION_SUPPORT if(krl_generate.type == krl_publish.type && krl_generate.type == krl_activate.type && krl_generate.type == krl_inactive.type && #if HAS_DS_PUBLICATION_SUPPORT /// @todo 20160603 gve -- still needs to test if they exist krl_generate.type == krl_remove.type && krl_generate.type == krl_ds_publish.type && krl_generate.type == krl_ds_remove.type) #else krl_generate.type == krl_remove.type) #endif // if HAS_DS_PUBLICATION_SUPPORT { // KER_ROLL_LINE_CRON_TYPE if(krl_generate.type) { return_code = dnssec_policy_roll_create_from_rules(key_roll->id, &krl_generate.policy.cron, &krl_publish.policy.cron, &krl_activate.policy.cron, &krl_inactive.policy.cron, &krl_remove.policy.cron, &krl_ds_publish.policy.cron, &krl_ds_remove.policy.cron); } // KER_ROLL_LINE_NON_CRON_TYPE else { return_code = dnssec_policy_roll_create_from_relatives(key_roll->id, &krl_generate.policy.relative, (u8) krl_generate.relative_to, &krl_publish.policy.relative, (u8) krl_publish.relative_to, &krl_activate.policy.relative, (u8) krl_activate.relative_to, &krl_inactive.policy.relative, (u8) krl_inactive.relative_to, &krl_remove.policy.relative, (u8) krl_remove.relative_to #if HAS_DS_PUBLICATION_SUPPORT , &krl_ds_publish.policy.relative, (u8) krl_ds_publish.relative_to, &krl_ds_remove.policy.relative, (u8) krl_ds_remove.relative_to #endif ); } if(FAIL(return_code)) { formatln("config: key-roll: '%s' has invalid settings", key_roll->id); return CONFIG_SECTION_ERROR; } } else { formatln("config: key-roll: %s: different key-roll types used in section", key_roll->id); return CONFIG_SECTION_ERROR; } csd->base = NULL; ptr_node *node = ptr_set_insert(&key_roll_desc_set, key_roll->id); if(node->value == NULL) { node->value = key_roll; return SUCCESS; } else { formatln("config: key-roll: %s: already registered", key_roll->id); return CONFIG_SECTION_ERROR; } } /** * @fn static ya_result config_section_key_roll_postprocess(struct config_section_descriptor_s *csd) * * @brief no postprocessing needed * * @details * no postprocessing * * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_roll_postprocess(struct config_section_descriptor_s *csd) { (void)csd; return SUCCESS; } /** * @fn static void key_roll_free(key_roll_desc_s *key_roll) * * @brief free all items: generate, publish, ... * * @details * just free all items of section * * * @param[in,out] key_roll_desc_s *key_roll * * return -- */ static void key_roll_free(key_roll_desc_s *key_roll) { free(key_roll->id); free(key_roll->generate); free(key_roll->publish); free(key_roll->activate); free(key_roll->inactive); free(key_roll->remove); free(key_roll->ds_publish); free(key_roll->ds_remove); free(key_roll); } /** * @fn static ya_result config_section_key_roll_finalize(struct config_section_descriptor_s *csd) * * @brief free key_roll_desc_s completely * * @details * empty 'dnssec_policy' key_roll parameter and everything else * and free csd and set back to 'NULL' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_roll_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { key_roll_desc_s *key_roll = (key_roll_desc_s*)csd->base; key_roll_free(key_roll); #if DEBUG csd->base = NULL; #endif } free(csd); } return SUCCESS; } /*----------------------------------------------------------------------------*/ #pragma mark VIRTUAL TABLE static const config_section_descriptor_vtbl_s config_section_key_roll_descriptor_vtbl = { "key-roll", config_section_key_roll_desc, // no table config_section_key_roll_set_wild, config_section_key_roll_print_wild, config_section_key_roll_init, config_section_key_roll_start, config_section_key_roll_stop, config_section_key_roll_postprocess, config_section_key_roll_finalize }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result config_register_key_roll(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_key_roll(const char *null_or_key_name, s32 priority) { //null_or_key_name = "zone"; (void)null_or_key_name; config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_key_roll_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // scan-build false positive: either it is freed, either it is stored in a global collection } yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/config-key-roll-parser.c0000644000000000000000000000013214505005533024110 xustar000000000000000030 mtime=1695812443.264993961 30 atime=1695812445.786030067 30 ctime=1695812495.807746479 yadifa-2.6.5-11201/sbin/yakeyrolld/config-key-roll-parser.c0000664000374500037450000003411414505005533024055 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup configuration * @brief */ #include #include #include "config-key-roll-parser.h" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES const char *week[7] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat" }; const char *month[12] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; const char *key_roll_actions[7] = { KR_ACTION_GENERATE_NAME, KR_ACTION_PUBLISH_NAME, KR_ACTION_ACTIVATE_NAME, KR_ACTION_INACTIVE_NAME, KR_ACTION_REMOVE_NAME, KR_ACTION_DS_PUBLISH_NAME, KR_ACTION_DS_REMOVE_NAME, }; /// @todo 20160601 gve -- probably this must be changed with accurate values (order!!!) const u8 key_roll_actions_relative[7] = { KR_ACTION_GENERATE, KR_ACTION_PUBLISH, KR_ACTION_ACTIVATE, KR_ACTION_INACTIVE, KR_ACTION_REMOVE, KR_ACTION_DS_PUBLISH, KR_ACTION_DS_REMOVE, }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result key_roll_item_validate(s32 *dst, const char *src, u32 min, u32 max, const char *array[]) * * @brief check if 'src' item exists in 'array' and put the result in 'dst' * * @details * * @param[in] const char *src * @param[out] s32 *dst * * @retval 0 or -1 * * return ya_result */ ya_result key_roll_item_validate(s32 *dst, const char *src, u32 min, u32 max, const char *array[]) { if(array != NULL) { if(max < min) { u32 tmp = max; max = min; min = tmp; } for(u32 i = 0; i <= max - min; i++) { if(strcasecmp(src, array[i]) == 0) { *dst = i + min; return 0; } } } return -1; } /** * @fn ya_result key_roll_item_parser(char *dest, size_t dest_size, const char **from, const char *delim) * * @brief parse 'from' which is a word with maybe a 'delim'eter * * @details * 'from' can have several values which if found will be given back in 'dest' and returned with '0' * the parser will stop if '\0' has been found, otherwise after finding a value 'dest' * return with '1' * * @param[in] const char *src * @param[out] s32 *dst * * @retval 0 or 1 * * return ya_result */ ya_result key_roll_item_parser(char *dest, size_t dest_size, const char **from, const char *delim) { const char *to = *from; for(;;) { char c = *to; if(c == '\0') { size_t len = to - *from; if(len > dest_size) { return PARSE_BUFFER_TOO_SMALL_ERROR; } memcpy(dest, *from, len); dest[len] = '\0'; return 0; } // for every delimiter, test if c if such a delimiter // if it is, then for(const char *d = delim; *d != 0; d++) { if(*d == c) { // end of word size_t len = to - *from; if(len > dest_size) { return PARSE_BUFFER_TOO_SMALL_ERROR; } memcpy(dest, *from, len); dest[len] = '\0'; // still need to go further *from = ++to; return 1; } } ++to; } } /** * @fn ya_result key_roll_item_value_check(s32 *dst, char *src, u32 min, u32 max, const char *array[]) * * @brief check is 'src' is in the correct range (min -- max) and that the 'value' is known by the 'array' * * @details * check if known in 'array' is done by 'key_roll_item_validate' * * @param[in] const char *src * @param[out] s32 *dst * * @retval 0 or return_code * * return ya_result */ ya_result key_roll_item_value_check(s32 *dst, char *src, u32 min, u32 max, const char *array[]) { ya_result return_code; if(FAIL(parse_u32_check_range(src, (u32 *)dst, min, max, BASE_10))) { if((strlen(src) == 1) && (*src == '*')) { *dst = -1; } else { if(FAIL(return_code = key_roll_item_validate(dst, src, min, max, array))) { return return_code; } } } return 0; } ya_result key_roll_item_value_bitmap_get(u64 *value, const char **needle, char *key_roll_item, size_t key_roll_item_size, u32 min, u32 max, const char *array[]) { yassert((min < 64) && (max < 64) && (min <= max)); ya_result return_code; *needle += strlen(key_roll_item); *needle = (char *)parse_skip_spaces(*needle); if(**needle == '\0') { return PARSER_REACHED_END_OF_LINE; } if(FAIL(return_code = parse_next_token(key_roll_item, key_roll_item_size, *needle, " \t"))) { return return_code; } char key_roll_item_part[1024]; const char *needle2 = key_roll_item; *value = 0; s32 value_temp; for(;;) { value_temp = 0; // because the value may not be set again on the next iteration return_code = key_roll_item_parser(key_roll_item_part, sizeof(key_roll_item_part), &needle2, ","); if(return_code == 0) { break; } else if(return_code == 1) { if(FAIL(return_code = key_roll_item_value_check(&value_temp, key_roll_item_part, min, max, array))) { return return_code; } yassert((value_temp >= 0) && (value_temp < 64)); if(value_temp >= 0) { *value |= 1ULL << value_temp; } } else { return return_code; } } return_code = key_roll_item_value_check(&value_temp, key_roll_item_part, min, max, array); if(value_temp >= 0) { *value |= 1ULL << value_temp; } else { u64 tmp = 0; for(u32 i = min; i <= max; ++i) { tmp |= 1ULL << i; } *value = tmp; } return return_code; } ya_result key_roll_item_value_get(s32 *value, const char **needle, char *key_roll_item, size_t key_roll_item_size, u32 min, u32 max, const char *array[]) { ya_result return_code; *needle += strlen(key_roll_item); *needle = (char *)parse_skip_spaces(*needle); if(**needle == '\0') { return PARSER_REACHED_END_OF_LINE; } if(FAIL(return_code = parse_next_token(key_roll_item, key_roll_item_size, *needle, " \t"))) { return return_code; } return_code = key_roll_item_value_check(value, key_roll_item, min, max, array); return return_code; } ya_result key_roll_time_seconds(s32 *dst, const char *src) { ya_result return_code; u32 src_len = (u32)strlen(src); char lc = src[src_len - 1]; if(isdigit(lc)) { return_code = parse_s32_check_range_len_base10(src, src_len, dst, 0, MAX_S32); } else { s64 mult = 1; src_len--; switch(lc) { case 'w': case 'W': mult = 60 * 60 * 24 * 7; break; case 'd': case 'D': mult = 60 * 60 * 24; break; case 'h': case 'H': mult = 60 * 60; break; case 'm': case 'M': mult = 60; break; case 's': case 'S': break; default: { return PARSER_UNKNOWN_TIME_UNIT; } } s32 time32; if(ISOK(return_code = parse_s32_check_range_len_base10(src, src_len, &time32, 0, MAX_S32))) { mult *= time32; if(mult <= MAX_S32) { *dst = (s32)mult; } else { return_code = PARSEINT_ERROR; } } } return return_code; } u8 key_roll_item_relative_to(u8 dst) { return key_roll_actions_relative[dst]; } ya_result config_key_roll_parser_line(const char *key_roll_line, key_roll_line_s *krl, u8 action) { ya_result return_code; char key_roll_item[1024]; memset(key_roll_item, 0, sizeof(key_roll_item)); krl->type = KEY_ROLL_LINE_CRON_TYPE; if(key_roll_line == NULL) { return PARSE_EMPTY_ARGUMENT; } // 1. start parsing 2 first tokens to find key_roll type const char *needle = key_roll_line; // action krl->action = action; // get second token needle += strlen(key_roll_item); needle = (char*)parse_skip_spaces(needle); if(*needle == '\0') { // this is bad return -1; } // 2. if parser find for second token a "+" sign this means the NON-CRON key_roll type if(strchr(needle, '+') != NULL) { if(FAIL(return_code = parse_next_token(key_roll_item, sizeof(key_roll_item), needle, " \t"))) { return return_code; } krl->type = KEY_ROLL_LINE_RELATIVE_TYPE; // relative seconds const char *p = key_roll_item; p++; u32 value; if(FAIL(return_code = key_roll_time_seconds((s32*)&value, p))) { return return_code; } krl->policy.relative.seconds = value; krl->policy.relative.type = ZONE_POLICY_RELATIVE; // 3. start parsing next two tokens for RELATIVE key_roll type // action relative to needle += strlen(key_roll_item); needle = (char*)parse_skip_spaces(needle); if(*needle == '\0') { krl->relative_to = key_roll_item_relative_to((u8)krl->action); } else { if(FAIL(return_code = parse_next_token(key_roll_item, sizeof(key_roll_item), needle, " \t"))) { return return_code; } if(FAIL(return_code = key_roll_item_validate(&krl->relative_to, key_roll_item, 0, 6, key_roll_actions))) { return return_code; } } } else { // 4. else start parsing next lines for CRON key_roll_type u64 bitmap; // minutes if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 0, 59, NULL))) { return return_code; } if(bitmap == 0) bitmap = 0x0fffffffffffffffLLU; // if no bits are set, all have to be krl->policy.cron.minute = bitmap; // hour if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 0, 23, NULL))) { return return_code; } if(bitmap == 0) bitmap = 0x0000000000ffffffLLU; krl->policy.cron.hour = bitmap; // day of month if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 1, 31, NULL))) { return return_code; } assert((bitmap & 1) == 0); // because [1;31] bitmap >>= 1; // because the bitmap needs [0;30] if(bitmap == 0) bitmap = 0x000000007fffffffLLU; krl->policy.cron.day = bitmap; // month if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 1, 12, month))) { return return_code; } assert((bitmap & 1) == 0); // because [1;12] bitmap >>= 1; // because the bitmap needs [0;11] if(bitmap == 0) bitmap = 0x0000000000000fffLLU; krl->policy.cron.month = (u16)bitmap; // day of week if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 0, 6, week))) { return return_code; } if(bitmap == 0) bitmap = 0x000000000000003fLLU; krl->policy.cron.weekday = bitmap; // week if(FAIL(return_code = key_roll_item_value_bitmap_get(&bitmap, &needle, key_roll_item, sizeof(key_roll_item), 0, 4, NULL))) { return return_code; } if(bitmap == 0) bitmap = 0x000000000000000fLLU; krl->policy.cron.week = bitmap; } return 0; } yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/config-key-suite.c0000644000000000000000000000013214505005533022777 xustar000000000000000030 mtime=1695812443.258993875 30 atime=1695812445.785030053 30 ctime=1695812495.809746508 yadifa-2.6.5-11201/sbin/yakeyrolld/config-key-suite.c0000664000374500037450000002444514505005533022752 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup ### * @brief */ #include #include #include #include "dnssec-policy.h" #include "config-dnssec-policy.h" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES extern logger_handle *g_server_logger; #define MODULE_MSG_HANDLE g_server_logger #define KEYSUICF_TAG 0x464349555359454b static ptr_set key_suite_desc_set = PTR_SET_ASCIIZ_EMPTY; /*----------------------------------------------------------------------------*/ #pragma mark CONFIG // key-suite container #define CONFIG_TYPE key_suite_desc_s CONFIG_BEGIN(config_section_key_suite_desc) CONFIG_STRING(id, NULL) CONFIG_STRING(key_template, NULL) CONFIG_STRING(key_roll, NULL) CONFIG_END(config_section_key_suite_desc) #undef CONFIG_TYPE #pragma mark STATIC FUNCTIONS static ya_result config_section_key_suite_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_key_suite_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)context; if(key != NULL) { return INVALID_ARGUMENT_ERROR; } return SUCCESS; } /** * @fn static ya_result config_section_key_suite_init(struct config_section_descriptor_s *csd) * * @brief initializing of a section: * * @details * the initializing of section is a NOP. * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_suite_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } /** * @fn static ya_result config_section_key_suite_start(struct config_section_descriptor_s *csd) * * @brief * start of a section csd->base will be initialized * * @details * csd->base will be initialized with key_suite * you can not have a start of a 'section' in a 'section' --> ERROR * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_suite_start(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_suite: start"); #endif if(csd->base != NULL) { return INVALID_STATE_ERROR; } key_suite_desc_s *key_suite; MALLOC_OBJECT_OR_DIE(key_suite, key_suite_desc_s, KEYSUICF_TAG); ZEROMEMORY(key_suite, sizeof(key_suite_desc_s)); csd->base = key_suite; return SUCCESS; } /** * @fn static ya_result config_section_key_suite_stop(struct config_section_descriptor_s *csd) * * @brief * stop of a section csd->base set to NULL --> * put the 'key-suite' in a binary tree with index key_suite->id * * @details * 'key-suite' is put in a binary tree for easy access when they need to be translated in the correct structure for 'yadifad' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_suite_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_suite: stop"); #endif // NOP key_suite_desc_s *key_suite = (key_suite_desc_s *) csd->base; csd->base = NULL; if(key_suite->id == NULL) { formatln("config: key-suite: id not set"); return CONFIG_SECTION_ERROR; } ptr_node *node = ptr_set_insert(&key_suite_desc_set, key_suite->id); if(node->value == NULL) { node->value = key_suite; return SUCCESS; } else { formatln("config: key-suite: %s: already defined", key_suite->id); return CONFIG_SECTION_ERROR; } } /** * @fn static ya_result config_section_key_suite_postprocess(struct config_section_descriptor_s *csd) * * @brief iterate thru binary tree and create the needed 'key-suite' structures for 'yadifad' * * @details * 'key-suite' needs a 'key-roll' and a 'key-template' section * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_suite_postprocess(struct config_section_descriptor_s *csd) { (void)csd; ptr_set_iterator iter; ptr_set_iterator_init(&key_suite_desc_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *key_suite_node = ptr_set_iterator_next_node(&iter); key_suite_desc_s *key_suite_desc = (key_suite_desc_s *)key_suite_node->value; dnssec_policy_key *dpk = dnssec_policy_key_acquire_from_name(key_suite_desc->key_template); if(dpk != NULL) { dnssec_policy_roll *dpr = dnssec_policy_roll_acquire_from_name(key_suite_desc->key_roll); if(dpr != NULL) { /*dnssec_policy_key_suite *dpks =*/ dnssec_policy_key_suite_create(key_suite_desc->id, dpk, dpr); dnssec_policy_roll_release(dpr); } else { formatln("config: key-suite: %s: key-template %s not defined", key_suite_desc->id, key_suite_desc->key_roll); } dnssec_policy_key_release(dpk); } else { formatln("config: key-suite: %s: key-template %s not defined", key_suite_desc->id, key_suite_desc->key_template); } } return SUCCESS; } /** * @fn static void key_suite_free(key_suite_desc_s *key_suite) * * @brief free * * @details * just free all items of section * * * @param[in] key_suite_desc_s *key_suite * * return -- */ static void key_suite_free(key_suite_desc_s *key_suite) { free(key_suite->id); free(key_suite->key_template); free(key_suite->key_roll); free(key_suite); } /** * @fn static ya_result config_section_key_suite_finalize(struct config_section_descriptor_s *csd) * * @brief free key_template_desc_s completely * * @details * empty 'dnssec_policy' key_suite parameter and everything else * and free csd and set back to 'NULL' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_suite_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { key_suite_desc_s *key_suite = (key_suite_desc_s*)csd->base; key_suite_free(key_suite); #if DEBUG csd->base = NULL; #endif } free(csd); } return SUCCESS; } /*----------------------------------------------------------------------------*/ #pragma mark VIRTUAL TABLE static const config_section_descriptor_vtbl_s config_section_key_suite_descriptor_vtbl = { "key-suite", config_section_key_suite_desc, // no table config_section_key_suite_set_wild, config_section_key_suite_print_wild, config_section_key_suite_init, config_section_key_suite_start, config_section_key_suite_stop, config_section_key_suite_postprocess, config_section_key_suite_finalize }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result config_register_key_suite(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_key_suite(const char *null_or_key_name, s32 priority) { //null_or_key_name = "zone"; (void)null_or_key_name; config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_key_suite_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // scan-build false positive: either it is freed, either it is stored in a global collection } yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/config-key-template.c0000644000000000000000000000013214505005533023461 xustar000000000000000030 mtime=1695812443.252993789 30 atime=1695812445.785030053 30 ctime=1695812495.811746536 yadifa-2.6.5-11201/sbin/yakeyrolld/config-key-template.c0000664000374500037450000003771214505005533023435 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifad * @ingroup ### * @brief */ #include #include #include #include #include "config-dnssec-policy.h" #include "dnssec-policy.h" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES #define KEYTEMCF_TAG 0x46434d455459454b static ptr_set key_template_desc_set = PTR_SET_ASCIIZ_EMPTY; static value_name_table dnssec_algorithm_enum[] = { {DNSKEY_ALGORITHM_RSAMD5 , DNSKEY_ALGORITHM_RSAMD5_NAME }, {DNSKEY_ALGORITHM_RSAMD5 , "1" }, {DNSKEY_ALGORITHM_DIFFIE_HELLMAN , DNSKEY_ALGORITHM_DIFFIE_HELLMAN_NAME }, {DNSKEY_ALGORITHM_DIFFIE_HELLMAN , "2" }, {DNSKEY_ALGORITHM_DSASHA1 , DNSKEY_ALGORITHM_DSASHA1_NAME }, {DNSKEY_ALGORITHM_DSASHA1 , "3" }, {DNSKEY_ALGORITHM_RSASHA1 , DNSKEY_ALGORITHM_RSASHA1_NAME }, {DNSKEY_ALGORITHM_RSASHA1 , "5" }, {DNSKEY_ALGORITHM_DSASHA1_NSEC3 , DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME }, {DNSKEY_ALGORITHM_DSASHA1_NSEC3 , DNSKEY_ALGORITHM_DSASHA1_NSEC3_NAME2 }, {DNSKEY_ALGORITHM_DSASHA1_NSEC3 , "6" }, {DNSKEY_ALGORITHM_RSASHA1_NSEC3 , DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME }, {DNSKEY_ALGORITHM_RSASHA1_NSEC3 , DNSKEY_ALGORITHM_RSASHA1_NSEC3_NAME2 }, {DNSKEY_ALGORITHM_RSASHA1_NSEC3 , "7" }, {DNSKEY_ALGORITHM_RSASHA256_NSEC3, DNSKEY_ALGORITHM_RSASHA256_NSEC3_NAME}, {DNSKEY_ALGORITHM_RSASHA256_NSEC3, "8" }, {DNSKEY_ALGORITHM_RSASHA512_NSEC3, DNSKEY_ALGORITHM_RSASHA512_NSEC3_NAME}, {DNSKEY_ALGORITHM_RSASHA512_NSEC3, "10" }, {DNSKEY_ALGORITHM_GOST , DNSKEY_ALGORITHM_GOST_NAME }, {DNSKEY_ALGORITHM_GOST , "12" }, {DNSKEY_ALGORITHM_ECDSAP256SHA256, DNSKEY_ALGORITHM_ECDSAP256SHA256_NAME}, {DNSKEY_ALGORITHM_ECDSAP256SHA256, "13" }, {DNSKEY_ALGORITHM_ECDSAP384SHA384, DNSKEY_ALGORITHM_ECDSAP384SHA384_NAME}, {DNSKEY_ALGORITHM_ECDSAP384SHA384, "14" }, {DNSKEY_ALGORITHM_ED25519 , DNSKEY_ALGORITHM_ED25519_NAME }, {DNSKEY_ALGORITHM_ED25519 , "15" }, {DNSKEY_ALGORITHM_ED448 , DNSKEY_ALGORITHM_ED448_NAME }, {DNSKEY_ALGORITHM_ED448 , "16" }, #ifdef DNSKEY_ALGORITHM_DUMMY {DNSKEY_ALGORITHM_DUMMY , DNSKEY_ALGORITHM_DUMMY_NAME}, {DNSKEY_ALGORITHM_DUMMY , "254"}, #endif {0, NULL} }; /*----------------------------------------------------------------------------*/ #pragma mark CONFIG // key-template container #define CONFIG_TYPE key_template_desc_s CONFIG_BEGIN(config_section_key_template_desc) CONFIG_STRING( id, NULL ) CONFIG_BOOL( ksk, "0" ) CONFIG_ENUM( algorithm, DNSKEY_ALGORITHM_RSASHA256_NSEC3_NAME, dnssec_algorithm_enum) CONFIG_U16( size, "0" ) CONFIG_STRING( engine, NULL ) CONFIG_END(config_section_key_template_desc) #undef CONFIG_TYPE #pragma mark STATIC FUNCTIONS static ya_result config_section_key_template_set_wild(struct config_section_descriptor_s *csd, const char *key, const char *value) { (void)csd; (void)key; (void)value; return CONFIG_UNKNOWN_SETTING; } static ya_result config_section_key_template_print_wild(const struct config_section_descriptor_s *csd, output_stream *os, const char *key, void **context) { (void)csd; (void)os; (void)context; if(key != NULL) { return INVALID_ARGUMENT_ERROR; } return SUCCESS; } /** * @fn static ya_result config_section_key_template_init(struct config_section_descriptor_s *csd) * * @brief initializing of a section: * * @details * the initializing of section is a NOP. * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_template_init(struct config_section_descriptor_s *csd) { // NOP if(csd->base != NULL) { return INVALID_STATE_ERROR; // base SHOULD be NULL at init } return SUCCESS; } /** * @fn static ya_result config_section_key_template_start(struct config_section_descriptor_s *csd) * * @brief * start of a section csd->base will be initialized * * @details * csd->base will be initialized with key_template * you can not have a start of a 'section' in a 'section' --> ERROR * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_template_start(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_template: start"); #endif if(csd->base != NULL) { return INVALID_STATE_ERROR; } key_template_desc_s *key_template; MALLOC_OBJECT_OR_DIE(key_template, key_template_desc_s, KEYTEMCF_TAG); ZEROMEMORY(key_template, sizeof(key_template_desc_s)); csd->base = key_template; return SUCCESS; } /** * @fn static ya_result config_section_key_template_stop(struct config_section_descriptor_s *csd) * * @brief * stop of a section csd->base set to NULL * * put the 'key-template' in a binary tree with index key_template->id * * @details * 'key-template' is put in a binary tree for easy access when they need to be translated in the correct structure for 'yadifad' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_template_stop(struct config_section_descriptor_s *csd) { #if CONFIG_SETTINGS_DEBUG formatln("config: section: key_template: stop"); #endif // NOP key_template_desc_s *key_template = (key_template_desc_s *) csd->base; csd->base = NULL; // 2. set 'algorithm' if(key_template->id == NULL) { formatln("config: key-template: id not set"); return CONFIG_SECTION_ERROR; } switch(key_template->algorithm) { case DNSKEY_ALGORITHM_RSAMD5: case DNSKEY_ALGORITHM_DIFFIE_HELLMAN: case DNSKEY_ALGORITHM_GOST: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; case DNSKEY_ALGORITHM_DSASHA1: case DNSKEY_ALGORITHM_DSASHA1_NSEC3: if(key_template->size == 0) { key_template->size = 1024; } if(key_template->size != 1024) { formatln("dnssec-policy: key_template: %s: unsupported key size: %i. Only 256 bits is supported for this algorithm.", key_template->id, key_template->size); return PARSE_INVALID_ARGUMENT; } break; case DNSKEY_ALGORITHM_RSASHA1: case DNSKEY_ALGORITHM_RSASHA1_NSEC3: case DNSKEY_ALGORITHM_RSASHA256_NSEC3: case DNSKEY_ALGORITHM_RSASHA512_NSEC3: if(key_template->ksk == 1) { if(key_template->size == 0) { key_template->size = 2048; } } else { if(key_template->size == 0) { key_template->size = 1024; } } /// @note 20160624 gve -- check if mod 256 == 0 break; case DNSKEY_ALGORITHM_ECDSAP256SHA256: if(key_template->size == 0) { key_template->size = 256; } if(key_template->size != 256) { formatln("dnssec-policy: key_template: %s: unsupported key size: %i. Only 256 bits is supported for this algorithm.", key_template->id, key_template->size); return PARSE_INVALID_ARGUMENT; } break; case DNSKEY_ALGORITHM_ECDSAP384SHA384: if(key_template->size == 0) { key_template->size = 384; } if(key_template->size != 384) { formatln("dnssec-policy: key_template: %s: unsupported key size: %i. Only 384 bits is supported for this algorithm.", key_template->id, key_template->size); return PARSE_INVALID_ARGUMENT; } break; case DNSKEY_ALGORITHM_ED25519: if(key_template->size == 0) { key_template->size = 256; } if(key_template->size != 256) { formatln("dnssec-policy: key_template: %s: unsupported key size: %i. Only 256 bits is supported for this algorithm.", key_template->id, key_template->size); return PARSE_INVALID_ARGUMENT; } break; case DNSKEY_ALGORITHM_ED448: if(key_template->size == 0) { key_template->size = 456; } if(key_template->size != 456) { formatln("dnssec-policy: key_template: %s: unsupported key size: %i. Only 384 bits is supported for this algorithm.", key_template->id, key_template->size); return PARSE_INVALID_ARGUMENT; } break; #ifdef DNSKEY_ALGORITHM_DUMMY case DNSKEY_ALGORITHM_DUMMY: key_template->size = 16; break; #endif default: return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM; } ptr_node *node = ptr_set_insert(&key_template_desc_set, key_template->id); if(node->value == NULL) { node->value = key_template; return SUCCESS; } else { formatln("config: key-template: %s: already defined", key_template->id); return CONFIG_SECTION_ERROR; } } /** * @fn static ya_result config_section_key_template_postprocess(struct config_section_descriptor_s *csd) * * @brief iterate thru binary tree and create the needed 'key-template' structures for 'yadifad' * * @details * no 'engine' implemented * * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_template_postprocess(struct config_section_descriptor_s *csd) { (void)csd; ptr_set_iterator iter; ptr_set_iterator_init(&key_template_desc_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *key_template_node = ptr_set_iterator_next_node(&iter); key_template_desc_s *key_template_desc = (key_template_desc_s *)key_template_node->value; /*dnssec_policy_key *dpk =*/ dnssec_policy_key_create(key_template_desc->id, key_template_desc->algorithm, key_template_desc->size, key_template_desc->ksk, NULL); // no engine in YADIFA 2.2.0 } return SUCCESS; } /** * @fn static void key_template_free(key_template_desc_s *key_template) * * @brief free * * @details * just free all items of section * * * @param[in] key_template_desc_s *key_template * * return -- */ static void key_template_free(key_template_desc_s *key_template) { free(key_template->id); free(key_template->engine); free(key_template); } /** * @fn static ya_result config_section_key_template_finalize(struct config_section_descriptor_s *csd) * * @brief free key_template_desc_s completely * * @details * empty 'dnssec_policy' key_template parameter and everything else * and free csd and set back to 'NULL' * * @param[in] struct config_section_description_s *csd * * @retval ERROR or SUCCESS * * return ya_result */ static ya_result config_section_key_template_finalize(struct config_section_descriptor_s *csd) { if(csd != NULL) { if(csd->base != NULL) { key_template_desc_s *key_template = (key_template_desc_s*)csd->base; key_template_free(key_template); #if DEBUG csd->base = NULL; #endif } free(csd); } return SUCCESS; } /*----------------------------------------------------------------------------*/ #pragma mark VIRTUAL TABLE static const config_section_descriptor_vtbl_s config_section_key_template_descriptor_vtbl = { "key-template", config_section_key_template_desc, // no table config_section_key_template_set_wild, config_section_key_template_print_wild, config_section_key_template_init, config_section_key_template_start, config_section_key_template_stop, config_section_key_template_postprocess, config_section_key_template_finalize }; /*----------------------------------------------------------------------------*/ #pragma mark FUNCTIONS /** * @fn ya_result config_register_key_template(const char *null_or_key_name, s32 priority) * * @brief register all sections needed for sections * * @details * * @param[in] const char *null_or_key_name * @param[in] s32 priority * * @retval return_code -- from other functions * * return ya_result */ ya_result config_register_key_template(const char *null_or_key_name, s32 priority) { //null_or_key_name = "zone"; (void)null_or_key_name; config_section_descriptor_s *desc; MALLOC_OBJECT_OR_DIE(desc, config_section_descriptor_s, CFGSDESC_TAG); desc->base = NULL; desc->vtbl = &config_section_key_template_descriptor_vtbl; ya_result return_code = config_register(desc, priority); if(FAIL(return_code)) { free(desc); } return return_code; // scan-build false positive: either it is freed, either it is stored in a global collection } yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/date-next.c0000644000000000000000000000013214505005533021506 xustar000000000000000030 mtime=1695812443.263993947 30 atime=1695812445.786030067 30 ctime=1695812495.813746565 yadifa-2.6.5-11201/sbin/yakeyrolld/date-next.c0000664000374500037450000003553514505005533021463 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #include "dnssec-policy.h" #include #include #include #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; /** * Returns the first index matching the rule in the mask, starting from the first value, * going up to the msb then looping from the lsb. * * @param from the first index to test * @param mask the bitmask to test (64 bits max) * @param limit the number of bits in the mask * * @return the first matching index * */ static int dnssec_policy_date_next_mask(int from, u64 mask, int limit) { assert(from >= 0); assert(limit >= 0); for(int ret = from; ret < limit; ++ret) { if((mask & (1ULL << ret)) != 0) { return ret; } } for(int ret = 0; ret < from; ++ret) { if((mask & (1ULL << ret)) != 0) { return ret; } } return -1; // no match } static bool dnssec_policy_date_next_month(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int month = dnssec_policy_date_next_mask(date->absolute.month, def->month, 12); yassert(month >= 0); if(month != date->absolute.month) { ret = FALSE; date->absolute.day = 0; date->absolute.hour = 0; date->absolute.minute = 0; if(month < date->absolute.month) { date->absolute.month = month; ++date->absolute.year; continue; } else { date->absolute.month = month; return FALSE; } } else { return ret; } } } static void dnssec_policy_date_next_month_move(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { date->absolute.day = 0; date->absolute.hour = 0; date->absolute.minute = 0; if(date->absolute.month < 11) { ++date->absolute.month; } else { ++date->absolute.year; date->absolute.month = 0; } dnssec_policy_date_next_month(date, def); } static bool dnssec_policy_date_next_week(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { bool ret = TRUE; if((def->week == ZONE_POLICY_RULE_ANYWEEK) && (def->weekday == ZONE_POLICY_RULE_ANYWEEKDAY)) { return ret; } for(;;) { int fdom = time_first_day_of_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month); // no change made by the week, what about the week-day ? if(def->weekday != ZONE_POLICY_RULE_ANYWEEKDAY) { int wday = (date->absolute.day + fdom) % 7; // obtain the day name from the absolute day number (0 = sunday) int newwday = dnssec_policy_date_next_mask(wday, def->weekday, 7); // matching week day if(newwday != wday) { ret = FALSE; int dday = newwday - wday; if(dday < 0) { dday += 7; } int day = date->absolute.day + dday; if(day >= time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month)) // no -1 here { // month changed //date->absolute.day = dnssec_policy_date_next_earliest_day_from_week(def); //date->absolute.hour = 0; //date->absolute.minute = 0; dnssec_policy_date_next_month_move(date, def); } else { date->absolute.day = day; date->absolute.hour = 0; date->absolute.minute = 0; } continue; } } // endif (def->weekday != ZONE_POLICY_RULE_ANYWEEKDAY) if(def->week != ZONE_POLICY_RULE_ANYWEEK) { // from the first day of the Month, the base of the week can be found // sunday = 0, but we want to start a Monday int week_base = 7 - (fdom + 6) % 7; // if we want to start a Sunday we add 0 instead // need to find the base of the month int week = (date->absolute.day - week_base); int newweek; if(week >= 0) // don't divide directly { week /= 7; newweek = dnssec_policy_date_next_mask(week, def->week, 4); // matching week } else { week = -1; newweek = dnssec_policy_date_next_mask(0, def->week, 4); // matching week } if(newweek != week) { ret = FALSE; // the week changed later in this month if(newweek < week) // newweek < week : the week changed to the next month { // month changed dnssec_policy_date_next_month_move(date, def); continue; } else { // move the day to the next week date->absolute.day = week_base + newweek * 7; date->absolute.hour = 0; date->absolute.minute = 0; } } // else nothing changed } // endif (def->week != ZONE_POLICY_RULE_ANYWEEK) break; } return ret; } static bool dnssec_policy_date_next_day(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int day = dnssec_policy_date_next_mask(date->absolute.day, def->day, time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month)); yassert(day >= 0); if(day != date->absolute.day) { ret = FALSE; date->absolute.hour = 0; date->absolute.minute = 0; if(day < date->absolute.day) { // the day has looped to the next month dnssec_policy_date_next_month_move(date, def); continue; } else // the day has changed { date->absolute.day = day; } } // we have a day that may or may not match the week and the week-day if(dnssec_policy_date_next_week(date, def)) { // week is good return ret; } ret = FALSE; } } static void dnssec_policy_date_next_day_move(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { date->absolute.hour = 0; date->absolute.minute = 0; // [0;n] [1;n+1] if(date->absolute.day < time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month) - 1) { ++date->absolute.day; } else { dnssec_policy_date_next_month_move(date, def); } dnssec_policy_date_next_day(date, def); } static bool dnssec_policy_date_next_hour(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int hour = dnssec_policy_date_next_mask(date->absolute.hour, def->hour, 24); if(hour != date->absolute.hour) { ret = FALSE; date->absolute.minute = 0; if(hour < date->absolute.hour) { dnssec_policy_date_next_day_move(date, def); } else { date->absolute.hour = hour; } } else { return ret; } } } static void dnssec_policy_date_next_hour_move(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { // hour could loop back into the nextious year too date->absolute.minute = 0; if(date->absolute.hour < 23) { ++date->absolute.hour; } else { dnssec_policy_date_next_day_move(date, def); } dnssec_policy_date_next_hour(date, def); } static bool dnssec_policy_date_next_minute(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int minute = dnssec_policy_date_next_mask(date->absolute.minute, def->minute, 60); if(date->absolute.minute != minute) { ret = FALSE; if(minute < date->absolute.minute) { dnssec_policy_date_next_hour_move(date, def); } else { date->absolute.minute = minute; } } else { return ret; } } } ya_result dnssec_policy_date_init_at_next_rule(dnssec_policy_date *date, const dnssec_policy_date *from, const dnssec_policy_date *rule) { yassert(from->type.type == ZONE_POLICY_ABSOLUTE); if(rule->type.type == ZONE_POLICY_RULE) { const dnssec_policy_rule_definition_s *def = dnssec_policy_rule_definition_get_from_rule(rule); time_t epoch; dnssec_policy_date_get_epoch(from, &epoch); if(rule->type.type == ZONE_POLICY_RULE) { epoch += 60; } dnssec_policy_date_init_from_epoch(date, epoch); dnssec_policy_date_next_month(date, def); dnssec_policy_date_next_day(date, def); dnssec_policy_date_next_hour(date, def); dnssec_policy_date_next_minute(date, def); return SUCCESS; } else if(rule->type.type == ZONE_POLICY_RELATIVE) { time_t epoch; dnssec_policy_date_get_epoch(from, &epoch); epoch += rule->relative.seconds; dnssec_policy_date_init_from_epoch(date, epoch); return SUCCESS; } else { return POLICY_ILLEGAL_DATE_TYPE; } } ya_result dnssec_policy_date_init_from_rule(dnssec_policy_date *date, const dnssec_policy_date *from, const dnssec_policy_date *rule) { yassert(from->type.type == ZONE_POLICY_ABSOLUTE); if(rule->type.type == ZONE_POLICY_RULE) { const dnssec_policy_rule_definition_s *def = dnssec_policy_rule_definition_get_from_rule(rule); time_t epoch; dnssec_policy_date_get_epoch(from, &epoch); dnssec_policy_date_init_from_epoch(date, epoch); dnssec_policy_date_next_month(date, def); dnssec_policy_date_next_day(date, def); dnssec_policy_date_next_hour(date, def); dnssec_policy_date_next_minute(date, def); return SUCCESS; } else if(rule->type.type == ZONE_POLICY_RELATIVE) { time_t epoch; dnssec_policy_date_get_epoch(from, &epoch); epoch += rule->relative.seconds; dnssec_policy_date_init_from_epoch(date, epoch); return SUCCESS; } else { return POLICY_ILLEGAL_DATE_TYPE; } } bool dnssec_policy_date_matches(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { int month = dnssec_policy_date_next_mask(date->absolute.month, def->month, 12); if(month != date->absolute.month) { return FALSE; } int fdom = time_first_day_of_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month); if(def->week == ZONE_POLICY_RULE_ANYWEEK) { // from the first day of the Month, the base of the week can be found // sunday = 0, but we want to start a Monday int week_base = (fdom + 6 % 7); // if we want to start a Sunday we add 0 instead // need to find the base of the month int week = (date->absolute.day - week_base); if(week >= 0) // don't divide directly { week /= 7; int newweek = dnssec_policy_date_next_mask(week, def->week, 4); // matching week if(newweek != week) { return FALSE; } } else { return FALSE; } } if(def->weekday != ZONE_POLICY_RULE_ANYWEEKDAY) { int fdom = time_first_day_of_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month); int wday = (date->absolute.day + fdom) % 7; // obtain the day name from the absolute day number (0 = sunday) int newwday = dnssec_policy_date_next_mask(wday, def->weekday, 7); // matching week day if(newwday != wday) { return FALSE; } } int day = dnssec_policy_date_next_mask(date->absolute.day, def->day, time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month)); if(day != date->absolute.day) { return FALSE; } int hour = dnssec_policy_date_next_mask(date->absolute.hour, def->hour, 24); if(hour != date->absolute.hour) { return FALSE; } int minute = dnssec_policy_date_next_mask(date->absolute.minute, def->minute, 60); if(minute != date->absolute.minute) { return FALSE; } return TRUE; } /** * @} */ yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/date-prev.c0000644000000000000000000000013214505005533021504 xustar000000000000000030 mtime=1695812443.261993918 30 atime=1695812445.786030067 30 ctime=1695812495.815746594 yadifa-2.6.5-11201/sbin/yakeyrolld/date-prev.c0000664000374500037450000003140014505005533021444 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #include "dnssec-policy.h" #include #include #include #define MODULE_MSG_HANDLE g_dnssec_logger extern logger_handle *g_dnssec_logger; static bool dnssec_policy_date_prev_day(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def); static void dnssec_policy_date_prev_day_move(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def); /** * Returns the first index matching the rule in the mask, starting from the first value, * going down to the lsb then looping from the msb. * * @param from the first index to test * @param mask the bitmask to test (64 bits max) * @param limit the number of bits in the mask * * @return the first matching index * */ static int dnssec_policy_date_prev_mask(int from, u64 mask, int limit) { assert(from >= 0); assert(limit >= 0); for(int ret = from; ret >= 0; --ret) { if((mask & (1ULL << ret)) != 0) { return ret; } } for(int ret = limit - 1; ret > from; --ret) { if((mask & (1ULL << ret)) != 0) { return ret; } } return -1; // no match } static bool dnssec_policy_date_prev_month(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int month = dnssec_policy_date_prev_mask(date->absolute.month, def->month, 12); yassert(month >= 0); if(month != date->absolute.month) { ret = FALSE; date->absolute.day = time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, month) - 1; date->absolute.hour = 23; date->absolute.minute = 59; if(month > date->absolute.month) { if(date->absolute.year == 0) { log_err("previous month outside of supported time range"); logger_flush(); } date->absolute.month = 11; --date->absolute.year; continue; } else { date->absolute.month = month; return FALSE; } // the caller is supposed to proceed on day (then hour, then minute) correction } else { return ret; // no change } } } // the "move" version of the function guarantees the value will be changed static void dnssec_policy_date_prev_month_move(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { // month could loop back into the previous year too date->absolute.hour = 23; date->absolute.minute = 59; if(date->absolute.month > 0) { --date->absolute.month; date->absolute.day = time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month) - 1; } else { if(date->absolute.year == 0) { log_err("previous month outside of supported time range"); logger_flush(); } --date->absolute.year; date->absolute.month = 11; date->absolute.day = time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month) - 1; } dnssec_policy_date_prev_month(date, def); } static bool dnssec_policy_date_prev_week(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { bool ret = TRUE; if((def->week == ZONE_POLICY_RULE_ANYWEEK) && (def->weekday == ZONE_POLICY_RULE_ANYWEEKDAY)) { return ret; } for(;;) { int fdom = time_first_day_of_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month); if(def->week != ZONE_POLICY_RULE_ANYWEEK) { // from the first day of the Month, the base of the week can be found // sunday = 0, but we want to start a Monday int week_base = 7 - (fdom + 6) % 7; // if we want to start a Sunday we add 0 instead // need to find the base of the month int week = (date->absolute.day - week_base); int newweek; if(week >= 0) // don't divide directly { week /= 7; newweek = dnssec_policy_date_prev_mask(week, def->week, 4); // matching week } else { week = -1; newweek = dnssec_policy_date_prev_mask(5, def->week, 4); // matching week } if(newweek != week) { ret = FALSE; // the week changed earlier in this month if(newweek > week) { // month changed dnssec_policy_date_prev_month_move(date, def); continue; } else // newweek > week : the week changed to the prev month { // move the day to the prev week date->absolute.day = week_base + newweek * 7 + 6; // + 6 because we want the last day of that week date->absolute.hour = 23; date->absolute.minute = 59; } } // else nothing changed } // endif (def->week != ZONE_POLICY_RULE_ANYWEEK) // no change made for the week, what about the week-day ? if(def->weekday != ZONE_POLICY_RULE_ANYWEEKDAY) { int wday = (date->absolute.day + fdom) % 7; int newwday = dnssec_policy_date_prev_mask(wday, def->weekday, 7); // matching week day if(newwday != wday) { ret = FALSE; int dday = wday - newwday; if(dday < 0) // verify this { dday += 7; } int day = date->absolute.day - dday; if(day < 0) { // month changed dnssec_policy_date_prev_month_move(date, def); } else { date->absolute.day = day; date->absolute.hour = 23; date->absolute.minute = 59; } continue; } } // endif (def->weekday != ZONE_POLICY_RULE_ANYWEEKDAY) break; } return ret; } static bool dnssec_policy_date_prev_day(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int day = dnssec_policy_date_prev_mask(date->absolute.day, def->day, time_days_in_month(date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month) - 1); yassert(day >= 0); if(day != date->absolute.day) // the current day didn't match (so it changed) { ret = FALSE; date->absolute.hour = 23; date->absolute.minute = 59; if(day > date->absolute.day) // the day has looped up, the month must decrement { // the day has looped to the prev month dnssec_policy_date_prev_month_move(date, def); // _move functions enforce a change then call their non-_move version to check a match continue; } else // the day has changed, we will match time down from the top of the day (23:59) { date->absolute.day = day; } } // we have a day that may or may not match the week and the week-day, we check that here if(dnssec_policy_date_prev_week(date, def)) // if true, it's a match { // week is good return ret; } ret = FALSE; } } static void dnssec_policy_date_prev_day_move(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { date->absolute.hour = 23; date->absolute.minute = 59; if(date->absolute.day > 0) { --date->absolute.day; } else { dnssec_policy_date_prev_month_move(date, def); } dnssec_policy_date_prev_day(date, def); } static bool dnssec_policy_date_prev_hour(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int hour = dnssec_policy_date_prev_mask(date->absolute.hour, def->hour, 24); if(hour != date->absolute.hour) { ret = FALSE; date->absolute.minute = 59; if(hour > date->absolute.hour) { dnssec_policy_date_prev_day_move(date, def); } else { date->absolute.hour = hour; } } else { return ret; } } } static void dnssec_policy_date_prev_hour_move(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { // hour could loop back into the previous year too date->absolute.minute = 59; if(date->absolute.hour > 0) { --date->absolute.hour; } else { dnssec_policy_date_prev_day_move(date, def); } dnssec_policy_date_prev_hour(date, def); } static bool dnssec_policy_date_prev_minute(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *def) { bool ret = TRUE; for(;;) { int minute = dnssec_policy_date_prev_mask(date->absolute.minute, def->minute, 60); if(minute != date->absolute.minute) { ret = FALSE; if(minute > date->absolute.minute) { dnssec_policy_date_prev_hour_move(date, def); } else { date->absolute.minute = minute; } } else { return ret; } } } ya_result dnssec_policy_date_init_at_prev_rule(dnssec_policy_date *date, const dnssec_policy_date *from, const dnssec_policy_date *rule) { yassert(from->type.type == ZONE_POLICY_ABSOLUTE); if(rule->type.type == ZONE_POLICY_RULE) { const dnssec_policy_rule_definition_s *def = dnssec_policy_rule_definition_get_from_rule(rule); time_t epoch; dnssec_policy_date_get_epoch(from, &epoch); if(rule->type.type == ZONE_POLICY_RULE) { epoch -= 60; // force a move back in time } dnssec_policy_date_init_from_epoch(date, epoch); dnssec_policy_date_prev_month(date, def); dnssec_policy_date_prev_day(date, def); dnssec_policy_date_prev_hour(date, def); dnssec_policy_date_prev_minute(date, def); return SUCCESS; } else if(rule->type.type == ZONE_POLICY_RELATIVE) { time_t epoch; dnssec_policy_date_get_epoch(from, &epoch); epoch -= rule->relative.seconds; dnssec_policy_date_init_from_epoch(date, epoch); return SUCCESS; } else { return POLICY_ILLEGAL_DATE_TYPE; } } /** * @} */ yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/dnssec-policy.c0000644000000000000000000000013214505005533022371 xustar000000000000000030 mtime=1695812443.253993803 30 atime=1695812445.785030053 30 ctime=1695812495.818746636 yadifa-2.6.5-11201/sbin/yakeyrolld/dnssec-policy.c0000664000374500037450000025022014505005533022334 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup ### ####### * @ingroup yadifad * @brief * * @{ */ #include "dnssec-policy.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef HAS_DYNUPDATE_DIFF_ENABLED #error "HAS_DYNUPDATE_DIFF_ENABLED not defined" #endif #define MODULE_MSG_HANDLE g_dnssec_logger logger_handle *g_dnssec_logger = LOGGER_HANDLE_SINK; #define DNSECPOL_TAG 0x4c4f504345534e44 #define DPOLKYST_TAG 0x5453594b4c4f5044 #define DPOLKEY_TAG 0x0059454b4c4f5044 #define DPOLDNIL_TAG 0x4c494e444c4f5044 #define DPOLSALT_TAG 0x544c41534c4f5044 #define DPOLROLL_TAG 0x4c4c4f524c4f5044 #define DPOLRULE_TAG 0x454c55524c4f5044 #define DPOLQUEU_TAG 0x554555514c4f5044 #define DNSSEC_POLICY_EPOCH_DOOMSDAY 0x3ac7d61800 // ~ 1st January 3970 #define KEY_POLICY_EPOCH_MATCH_MARGIN 180 // how close two epochs have to be to be considered a match #define DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS 0 #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS #pragma message("WARNING: DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS enabled !") #endif static u32_set dnssec_policy_rule_definition_set = U32_SET_EMPTY; static group_mutex_t dnssec_policy_rule_definition_set_mtx = GROUP_MUTEX_INITIALIZER; static volatile u32 dnssec_policy_rule_definition_next_index = 0; // local functions definitions ya_result dnssec_policy_date_init_at_next_rule(dnssec_policy_date *date, const dnssec_policy_date *from, const dnssec_policy_date *rule); ya_result dnssec_policy_date_init_at_prev_rule(dnssec_policy_date *date, const dnssec_policy_date *from, const dnssec_policy_date *rule); ya_result dnssec_policy_date_init_from_rule(dnssec_policy_date *date, const dnssec_policy_date *from, const dnssec_policy_date *rule); // static ptr_set dnssec_policy_roll_set = PTR_SET_ASCIIZ_EMPTY; static group_mutex_t dnssec_policy_roll_set_mtx = GROUP_MUTEX_INITIALIZER; static group_mutex_t dnssec_policy_roll_mtx = GROUP_MUTEX_INITIALIZER; // static ptr_set dnssec_policy_set = PTR_SET_ASCIIZ_EMPTY; static group_mutex_t dnssec_policy_set_mtx = GROUP_MUTEX_INITIALIZER; static group_mutex_t dnssec_policy_mtx = GROUP_MUTEX_INITIALIZER; // #if 0 static ptr_set dnssec_denial_set = PTR_SET_ASCIIZ_EMPTY; static group_mutex_t dnssec_denial_set_mtx = GROUP_MUTEX_INITIALIZER; static group_mutex_t dnssec_denial_mtx = GROUP_MUTEX_INITIALIZER; #endif // static ptr_set dnssec_policy_key_set = PTR_SET_ASCIIZ_EMPTY; static group_mutex_t dnssec_policy_key_set_mtx = GROUP_MUTEX_INITIALIZER; static group_mutex_t dnssec_policy_key_mtx = GROUP_MUTEX_INITIALIZER; // static ptr_set dnssec_policy_key_suite_set = PTR_SET_ASCIIZ_EMPTY; static group_mutex_t dnssec_policy_key_suite_set_mtx = GROUP_MUTEX_INITIALIZER; static group_mutex_t dnssec_policy_key_suite_mtx = GROUP_MUTEX_INITIALIZER; // #if DEBUG static void dnssec_policy_date_format_handler_method(const void *restrict val, output_stream *os, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters) { dnssec_policy_date *date = (dnssec_policy_date*)val; (void)padding; (void)pad_char; (void)left_justified; (void)reserved_for_method_parameters; switch(date->type.type) { case ZONE_POLICY_ABSOLUTE: { osformat(os, "%4u-%02u-%02u %02u:%02u:00U", date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month + 1, date->absolute.day + 1, date->absolute.hour, date->absolute.minute); break; } case ZONE_POLICY_RELATIVE: { osformat(os, "(%u)+%us", date->relative.seconds, date->relative.relativeto); break; } case ZONE_POLICY_RULE: { dnssec_policy_rule_definition_s *def = dnssec_policy_rule_definition_get_from_rule(date); osformat(os, "[%016x %06x %08x %02x %x %x]", def->minute, def->hour, def->day, def->month, def->weekday, def->week); break; } default: { output_stream_write(os, "?", 1); break; } } } #endif ya_result dnssec_policy_add_generate_key_create_at(keyroll_t *keyroll, struct dnssec_policy_key_suite *kr, time_t epoch, dnssec_key **out_keyp) { dnssec_policy_table_s tbl; dnssec_policy_date now_date; ya_result ret; ret = dnssec_policy_date_init_from_epoch(&now_date, epoch); if(FAIL(ret)) { log_err("dnssec_policy_add_generate_key_create_at: dnssec_policy_table_init_from_date returned an error: %r", ret); return ret; } ret = dnssec_policy_table_init_from_date(&tbl, &kr->roll->time_table, &now_date); if(FAIL(ret)) { log_err("dnssec_policy_add_generate_key_create_at: dnssec_policy_table_init_from_date returned an error: %r", ret); return ret; } #if DEBUG format_writer n_fw = {dnssec_policy_date_format_handler_method, &now_date}; format_writer c_fw = {dnssec_policy_date_format_handler_method, &tbl.created}; format_writer p_fw = {dnssec_policy_date_format_handler_method, &tbl.publish}; format_writer a_fw = {dnssec_policy_date_format_handler_method, &tbl.activate}; format_writer d_fw = {dnssec_policy_date_format_handler_method, &tbl.inactive}; format_writer r_fw = {dnssec_policy_date_format_handler_method, &tbl.delete}; log_debug("dnssec-policy: %{dnsname}: %s: at %U = %U = %w: queued key: create=%w, publish=%w, activate=%w, deactivate=%w, remove=%w", keyroll->domain, kr->name, epoch, epoch, &n_fw, &c_fw, &p_fw, &a_fw, &d_fw, &r_fw); #endif time_t created_epoch; time_t publish_epoch; time_t activate_epoch; time_t deactivate_epoch; time_t unpublish_epoch; if(FAIL(ret = dnssec_policy_date_get_epoch(&tbl.created, &created_epoch))) // note: created should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_add_generate_key_create_at: dnssec_policy_date_get_epoch (created_epoch) returned an error: %r", ret); return ret; } if(FAIL(ret = dnssec_policy_date_get_epoch(&tbl.publish, &publish_epoch))) // note: publish should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_add_generate_key_create_at: dnssec_policy_date_get_epoch (publish_epoch) returned an error: %r", ret); return ret; } if(FAIL(ret = dnssec_policy_date_get_epoch(&tbl.activate, &activate_epoch))) // note: activate should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_add_generate_key_create_at: dnssec_policy_date_get_epoch (activate_epoch) returned an error: %r", ret); return ret; } if(FAIL(ret = dnssec_policy_date_get_epoch(&tbl.inactive, &deactivate_epoch))) // note: deactivate should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_add_generate_key_create_at: dnssec_policy_date_get_epoch (deactivate_epoch) returned an error: %r", ret); return ret; } if(FAIL(ret = dnssec_policy_date_get_epoch(&tbl.delete, &unpublish_epoch))) // note: unpublish should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_add_generate_key_create_at: dnssec_policy_date_get_epoch (unpublish_epoch) returned an error: %r", ret); return ret; } if(FAIL(ret = keyroll_generate_dnskey_ex(keyroll, kr->key->size, kr->key->algorithm, ONE_SECOND_US * created_epoch, ONE_SECOND_US * publish_epoch, ONE_SECOND_US * activate_epoch, ONE_SECOND_US * deactivate_epoch, ONE_SECOND_US * unpublish_epoch, (kr->key->flags == DNSKEY_FLAGS_KSK), out_keyp))) { log_err("dnssec_policy_add_generate_key_create_at: dnssec_policy_date_get_epoch (unpublish_epoch) returned an error: %r", ret); return ret; } yassert(tbl.created.type.type == ZONE_POLICY_ABSOLUTE); time_t alarm_epoch; if(FAIL(ret = dnssec_policy_date_get_epoch(&tbl.created, &alarm_epoch))) // note: created should be of type ZONE_POLICY_ABSOLUTE { log_err("dnssec_policy_add_generate_key_create_at: dnssec_policy_date_get_epoch returned an error: %r", ret); return ret; } #if DEBUG log_debug("dnssec-policy: %{dnsname}: %s: key created set at %U", keyroll->domain, kr->name, alarm_epoch); #endif return SUCCESS; } /** * Works only with RULEs (cron) key suites * * @param zone_desc * @param kr * @param active_at */ ya_result dnssec_policy_add_generate_key_active_at(keyroll_t *keyroll, struct dnssec_policy_key_suite *kr, time_t active_at) { dnssec_policy_date creation_date; dnssec_policy_date publish_date; dnssec_policy_date activate_date; dnssec_policy_date inactive_date; dnssec_policy_date unpublish_date; dnssec_policy_date now_date; ya_result ret; // set now_date to active epoch if(FAIL(ret = dnssec_policy_date_init_from_epoch(&now_date, active_at))) { return ret; } // find the previous match for active date if(FAIL(ret = dnssec_policy_date_init_at_prev_rule(&activate_date, &now_date, &kr->roll->time_table.activate))) { return ret; } // find the previous match for publish date if(FAIL(ret = dnssec_policy_date_init_at_prev_rule(&publish_date, &activate_date, &kr->roll->time_table.publish))) { return ret; } // find the previous match for create date if(FAIL(ret = dnssec_policy_date_init_at_prev_rule(&creation_date, &publish_date, &kr->roll->time_table.created))) { return ret; } time_t creation_epoch = 60; time_t activate_epoch = 60; // get the computed create epoch if(FAIL(ret = dnssec_policy_date_get_epoch(&creation_date, &creation_epoch))) { return ret; } // get the computed active epoch if(FAIL(ret = dnssec_policy_date_get_epoch(&activate_date, &activate_epoch))) { return ret; } //creation_epoch -= 60; #if DEBUG format_writer c_fw = {dnssec_policy_date_format_handler_method, &creation_date}; { format_writer a_fw0 = {dnssec_policy_date_format_handler_method, &activate_date}; format_writer p_fw0 = {dnssec_policy_date_format_handler_method, &publish_date}; format_writer n_fw0 = {dnssec_policy_date_format_handler_method, &now_date}; log_debug1("dnssec-policy: %{dnsname}: %s: base create: %w <= public: %w <= activate: %w : %U (%w)", keyroll->domain, kr->name, &c_fw, &p_fw0, &a_fw0, creation_epoch, &n_fw0); } #endif // compute the forward publish date from the creation date if(FAIL(ret = dnssec_policy_date_init_at_next_rule(&publish_date, &creation_date, &kr->roll->time_table.publish))) { return ret; } // compute the forward activate date from the publish date if(FAIL(ret = dnssec_policy_date_init_at_next_rule(&activate_date, &publish_date, &kr->roll->time_table.activate))) { return ret; } #if DEBUG format_writer p_fw = {dnssec_policy_date_format_handler_method, &publish_date}; format_writer a_fw = {dnssec_policy_date_format_handler_method, &activate_date}; { log_debug1("dnssec-policy: %{dnsname}: %s: base create: %w => publish: %w => activate: %w : %U (after forward correction)", keyroll->domain, kr->name, &c_fw, &p_fw, &a_fw, creation_epoch); } #endif // compute the future key timings to ensure there will be no period without a signature dnssec_policy_date next_creation_date; dnssec_policy_date next_publish_date; dnssec_policy_date next_activate_date; if(FAIL(ret = dnssec_policy_date_init_at_next_rule(&next_creation_date, &activate_date, &kr->roll->time_table.created))) { return ret; } if(FAIL(ret = dnssec_policy_date_init_at_next_rule(&next_publish_date, &next_creation_date, &kr->roll->time_table.publish))) { return ret; } if(FAIL(ret = dnssec_policy_date_init_at_next_rule(&next_activate_date, &next_publish_date, &kr->roll->time_table.activate))) { return ret; } #if DEBUG { format_writer na_fw = {dnssec_policy_date_format_handler_method, &next_activate_date}; format_writer np_fw = {dnssec_policy_date_format_handler_method, &next_publish_date}; format_writer nc_fw = {dnssec_policy_date_format_handler_method, &next_creation_date}; log_debug1("dnssec-policy: %{dnsname}: %s: next activate: %w => publish: %w => activate: %w", keyroll->domain, kr->name, &nc_fw, &np_fw, &na_fw); } #endif // and use this next_activate as a base for the current deactivate if(FAIL(ret = dnssec_policy_date_init_at_next_rule(&inactive_date, &next_activate_date, &kr->roll->time_table.inactive))) { return ret; } if(FAIL(ret = dnssec_policy_date_init_at_next_rule(&unpublish_date, &inactive_date, &kr->roll->time_table.delete))) { return ret; } time_t inactive_epoch = 0; if(FAIL(ret = dnssec_policy_date_get_epoch(&inactive_date, &inactive_epoch))) { return ret; } if(inactive_epoch - activate_epoch < DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS) { double d = inactive_epoch - activate_epoch; d /= 86400.0; double c = DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS; c /= 86400.0; log_warn("dnssec-policy: %{dnsname}: %s: the key will only be activated for %.3f days, consider increasing this value to at least %.3f days", keyroll->domain, kr->name, d, c); } if(inactive_epoch < active_at) { log_err("dnssec-policy: %{dnsname}: %s: computing timings to be in the current activated time window produces an already expired key", keyroll->domain, kr->name ); return INVALID_STATE_ERROR; } #if DEBUG format_writer d_fw = {dnssec_policy_date_format_handler_method, &inactive_date}; dnssec_policy_date remove_date; ret = dnssec_policy_date_init_at_next_rule(&remove_date, &inactive_date, &kr->roll->time_table.delete); (void)ret; format_writer r_fw = {dnssec_policy_date_format_handler_method, &unpublish_date}; log_debug("dnssec-policy: %{dnsname}: %s: rule key: create=%w, publish=%w, activate=%w, deactivate=%w, remove=%w", keyroll->domain, kr->name, &c_fw, &p_fw, &a_fw, &d_fw, &r_fw); #endif log_debug("dnssec-policy: %{dnsname}: %s: will generate a key at %U (rule new) to be active at %U (%lli)", keyroll->domain, kr->name, creation_epoch, active_at, active_at); //// { dnssec_policy_table_s tbl; dnssec_policy_date now_date; ya_result ret; ret = dnssec_policy_date_init_from_epoch(&now_date, creation_epoch); if(FAIL(ret)) { return ret; } ret = dnssec_policy_table_init_from_date(&tbl, &kr->roll->time_table, &now_date); if(FAIL(ret)) { return ret; } time_t active_epoch; ret = dnssec_policy_date_get_epoch(&tbl.activate, &active_epoch); if(FAIL(ret)) { return ret; } time_t inactive_epoch; ret = dnssec_policy_date_get_epoch(&tbl.inactive, &inactive_epoch); if(FAIL(ret)) { return ret; } if((active_epoch > active_at) || (inactive_epoch < active_at)) { flushout(); return ERROR; } } //// #if DEBUG logger_flush(); #endif // add the command dnssec_key *key = NULL; ret = dnssec_policy_add_generate_key_create_at(keyroll, kr, creation_epoch, &key); if(key != NULL) { if(ISOK(ret)) { if(!dnskey_is_activated(key, active_at)) { s32 key_active_at = dnskey_get_activate_epoch(key); s32 key_inactive_at = dnskey_get_inactive_epoch(key); log_err("key expected to be active at %u but is active from %u to %u (%U [%U; %U])", active_at, key_active_at, key_inactive_at, active_at, key_active_at, key_inactive_at); logger_flush(); ret = ERROR; } } dnskey_release(key); } return ret; } /** * Compare two dates together. * Absolute with Absolute * Relative with Relative * * Any other combination will return -1 * * @param d1 first date * @param d2 second date * @return <0,0,>0 if d1 is less than, equal to, or greater than d2 */ int dnssec_policy_date_compare(const dnssec_policy_date *d1, const dnssec_policy_date *d2) { int ret; if(d1->type.type == ZONE_POLICY_ABSOLUTE && d2->type.type == ZONE_POLICY_ABSOLUTE) { ret = d1->absolute.year; ret -= d2->absolute.year; if(ret == 0) { ret = d1->absolute.month; ret -= d2->absolute.month; if(ret == 0) { ret = d1->absolute.day; ret -= d2->absolute.day; if(ret == 0) { ret = d1->absolute.hour; ret -= d2->absolute.hour; if(ret == 0) { ret = d1->absolute.minute; ret -= d2->absolute.minute; } } } } return ret; } else if(d1->type.type == ZONE_POLICY_RELATIVE && d2->type.type == ZONE_POLICY_RELATIVE) { ret = d1->relative.seconds; ret -= d2->relative.seconds; return ret; } return POLICY_ILLEGAL_DATE_COMPARE; } /** * Retrieves the first day of the month. * * 0 is Sunday * * @param year 0-based * @param month 0-based * @param week 0 to 4, week of the day * @param wday 0 to 6, day of the week, 0 for Sunday * @return the number of the day of the month or an error code */ ya_result dnssec_policy_get_mday_from_year_month_week_wday(int year, int month, int week, int wday) { int mday1 = time_first_day_of_month(year, month); if(mday1 >= 0) { /** * @note this can obviously be simplified (++week) but I think it's clearer this way (for now) */ if(wday < mday1) { // 0 1 2 3 4 5 6 // // X Y Z 1 2 3 4 // 4[6]7 8 9 ... return wday - mday1 + 7 * (week + 1); } else { // 0 1 2 3 4 5 6 // // X Y Z 1 2 3 4 // 4 6 7 8[9]... return wday - mday1 + 7 * week; } } else { return POLICY_ILLEGAL_DATE; } } /** * Initialises an absolute date from a year, month, week and week-day * * ie: 2nd Wednesday of January 2001 * * 0 is Sunday * * @param date the date to initialise * @param year 0-based * @param month 0-based * @param week 0 to 4, week of the day * @param wday 0 to 6, day of the week, 0 for Sunday * @return an error code */ ya_result dnssec_policy_date_init_from_year_month_week_wday(dnssec_policy_date *date, int year, int month, int week, int wday) { struct tm tm; ZEROMEMORY(&tm, sizeof(struct tm)); tm.tm_mday = 1; tm.tm_mon = month; tm.tm_year = year - 1900; time_t t = mkgmtime(&tm); if(t >= 0) { if(tm.tm_wday >= 0) { /** * @note this can obviously be simplified (++week) but I think it's clearer this way (for now) * * tm_wday is the first week-day of the month */ if(wday < tm.tm_wday) // [0 .. 7] < [1 .. 31] ? { // 0 1 2 3 4 5 6 // // X Y Z 1 2 3 4 // 4[6]7 8 9 ... tm.tm_mday = wday - tm.tm_wday + 7 * (week + 1) + 1; } else { // 0 1 2 3 4 5 6 // // X Y Z 1 2 3 4 // 4 6 7 8[9]... tm.tm_mday = wday - tm.tm_wday + 7 * week + 1; } t = mkgmtime(&tm); if(t >= 0) { if(tm.tm_year < 228) { date->type.type = ZONE_POLICY_ABSOLUTE; date->absolute.year = tm.tm_year - (ZONE_POLICY_DATE_YEAR_BASE - 1900); // 1900 based to 2000 based date->absolute.month = tm.tm_mon; date->absolute.day = tm.tm_mday - 1; // 1 based to 0 based date->absolute.hour = tm.tm_hour; date->absolute.minute = tm.tm_min; return SUCCESS; } } } } return POLICY_ILLEGAL_DATE_PARAMETERS; } /** * Initialises an absolute date from a UNIX epoch * * @param date * @param epoch * @return an error code */ ya_result dnssec_policy_date_init_from_epoch(dnssec_policy_date *date, time_t epoch) { time_t t = epoch; struct tm d; // if it worked and there was no overflow ... if((gmtime_r(&t, &d) != NULL) && (d.tm_year < 228)) { date->type.type = ZONE_POLICY_ABSOLUTE; date->absolute.year = d.tm_year - (ZONE_POLICY_DATE_YEAR_BASE - 1900); // 1900 based to 2000 based date->absolute.month = d.tm_mon; date->absolute.day = d.tm_mday - 1; // 1 based to 0 based date->absolute.hour = d.tm_hour; date->absolute.minute = d.tm_min; return SUCCESS; } return POLICY_ILLEGAL_DATE_PARAMETERS; } /** * Gets the UNIX epoch from an absolute date * * @param date * @param epoch a pointer to hold the result * @return an error code */ ya_result dnssec_policy_date_get_epoch(const dnssec_policy_date *date, time_t *epoch) { time_t t; struct tm d; yassert(epoch != NULL); if(date->type.type != ZONE_POLICY_ABSOLUTE) // only works with absolute dates { return POLICY_ILLEGAL_DATE_TYPE; } ZEROMEMORY(&d, sizeof(struct tm)); d.tm_year = date->absolute.year + (ZONE_POLICY_DATE_YEAR_BASE - 1900); // 2000 based to 1900 based d.tm_mon = date->absolute.month; d.tm_mday = date->absolute.day + 1; // 0 based to 1 based d.tm_hour = date->absolute.hour; d.tm_min = date->absolute.minute; d.tm_sec = 0; t = mkgmtime(&d); if(t != -1) { *epoch = t; return SUCCESS; } else { return MAKE_ERRNO_ERROR(EOVERFLOW); } } /** * Initialises the absolute date with an epoch plus time in seconds. * * @param date * @param epoch an epoch to add the seconds to * @param seconds * @return an error code */ ya_result dnssec_policy_date_init_after_epoch(dnssec_policy_date *date, time_t epoch, u32 seconds) { ya_result ret = dnssec_policy_date_init_from_epoch(date, epoch + seconds); return ret; } /** * Initialises the absolute date with an absolute date plus time in seconds. * * @param date * @param from an absolute date to add the seconds to * @param seconds * @return an error code */ ya_result dnssec_policy_date_init_after_date(dnssec_policy_date *date, const dnssec_policy_date *from, u32 seconds) { ya_result ret; time_t epoch; if(ISOK(ret = dnssec_policy_date_get_epoch(from, &epoch))) { ret = dnssec_policy_date_init_from_epoch(date, epoch + seconds); } return ret; } dnssec_policy_rule_definition_s* dnssec_policy_rule_definition_get_from_index(u32 index) { dnssec_policy_rule_definition_s *ret = NULL; group_mutex_read_lock(&dnssec_policy_rule_definition_set_mtx); u32_node *node = u32_set_find(&dnssec_policy_rule_definition_set, index); if(node != NULL) { ret = (dnssec_policy_rule_definition_s*)node->value; } group_mutex_read_unlock(&dnssec_policy_rule_definition_set_mtx); return ret; } dnssec_policy_rule_definition_s* dnssec_policy_rule_definition_get_from_rule(const dnssec_policy_date *rule) { dnssec_policy_rule_definition_s *ret = NULL; if(rule->type.type == ZONE_POLICY_RULE) { ret = dnssec_policy_rule_definition_get_from_index(rule->rule.index); } return ret; } void dnssec_policy_rule_init(dnssec_policy_rule_s *rule, const dnssec_policy_rule_definition_s *rule_definition) { group_mutex_write_lock(&dnssec_policy_rule_definition_set_mtx); yassert(dnssec_policy_rule_definition_next_index < 0x40000000); for(;;) { ++dnssec_policy_rule_definition_next_index; if(dnssec_policy_rule_definition_next_index == 0x40000000) { dnssec_policy_rule_definition_next_index = 0; } u32_node *node = u32_set_insert(&dnssec_policy_rule_definition_set, dnssec_policy_rule_definition_next_index); if(node->value == NULL) { rule->index = dnssec_policy_rule_definition_next_index; rule->type = ZONE_POLICY_RULE; dnssec_policy_rule_definition_s *new_rule_definition; ZALLOC_OBJECT_OR_DIE( new_rule_definition, dnssec_policy_rule_definition_s, DPOLRULE_TAG); memcpy(new_rule_definition, rule_definition, sizeof(dnssec_policy_rule_definition_s)); node->value = new_rule_definition; break; } } group_mutex_write_unlock(&dnssec_policy_rule_definition_set_mtx); } void dnssec_policy_rule_finalize(dnssec_policy_rule_s *rule) { group_mutex_write_lock(&dnssec_policy_rule_definition_set_mtx); u32_node *node = u32_set_find(&dnssec_policy_rule_definition_set, rule->index); if(node != NULL) { if(node->value != NULL) { ZFREE(node->value, dnssec_policy_rule_definition_s); } u32_set_delete(&dnssec_policy_rule_definition_set, rule->index); } group_mutex_write_unlock(&dnssec_policy_rule_definition_set_mtx); } void dnssec_policy_date_init_from_rule_definition(dnssec_policy_date *date, const dnssec_policy_rule_definition_s *rule_definition) { date->type.type = ZONE_POLICY_RULE; dnssec_policy_rule_init(&date->rule, rule_definition); } /** * This complicated functions initialises a date with the earliest matching of the rule starting from 'from' * * @param date * @param from * @param rule * * @return an error code */ ya_result dnssec_policy_date_init_from_date(dnssec_policy_date *date, const dnssec_policy_date *from, const dnssec_policy_date *rule) { ya_result ret; #if DEBUG format_writer from_fw = {dnssec_policy_date_format_handler_method, from}; format_writer rule_fw = {dnssec_policy_date_format_handler_method, rule}; format_writer date_fw = {dnssec_policy_date_format_handler_method, date}; #endif if(from->type.type != ZONE_POLICY_ABSOLUTE) { #if DEBUG log_debug1("dnssec_policy_date_init_from_date(%p, %w, %w): can only work from an absolute time", date, &from_fw, &rule_fw); #endif return POLICY_ILLEGAL_DATE_TYPE; } switch(rule->type.type) { case ZONE_POLICY_RELATIVE: { memcpy(date, from, sizeof(dnssec_policy_date)); #if DEBUG log_debug1("dnssec_policy_date_init_from_date(%p, %w, %w): initialising relative time", date, &from_fw, &rule_fw); #endif ret = dnssec_policy_date_init_after_date(date, from, rule->relative.seconds); // +60 because it must be after and because of minute granularity #if DEBUG log_debug1("dnssec_policy_date_init_from_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw); #endif return ret; } case ZONE_POLICY_RULE: { #if DEBUG log_debug1("dnssec_policy_date_init_from_date(%p, %w, %w): initialising rule-based time", date, &from_fw, &rule_fw); #endif ret = dnssec_policy_date_init_from_rule(date, from, rule); #if DEBUG log_debug1("dnssec_policy_date_init_from_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw); #endif return ret; } default: { #if DEBUG log_debug1("dnssec_policy_date_init_from_date(%p, %w, %w): unexpected type", date, &from_fw, &rule_fw); #endif return POLICY_ILLEGAL_DATE_TYPE; } } } /** * This complicated functions initialises a date with the earliest matching of the rule starting after 'from' * * @param date * @param from * @param rule * * @return an error code */ ya_result dnssec_policy_date_init_at_next_date(dnssec_policy_date *date, const dnssec_policy_date *from, const dnssec_policy_date *rule) { ya_result ret; #if DEBUG format_writer from_fw = {dnssec_policy_date_format_handler_method, from}; format_writer rule_fw = {dnssec_policy_date_format_handler_method, rule}; format_writer date_fw = {dnssec_policy_date_format_handler_method, date}; #endif if(from->type.type != ZONE_POLICY_ABSOLUTE) { #if DEBUG log_debug1("dnssec_policy_date_init_at_next_date(%p, %w, %w): can only work from an absolute time", date, &from_fw, &rule_fw); #endif return POLICY_ILLEGAL_DATE_TYPE; } switch(rule->type.type) { case ZONE_POLICY_RELATIVE: { memcpy(date, from, sizeof(dnssec_policy_date)); #if DEBUG log_debug1("dnssec_policy_date_init_at_next_date(%p, %w, %w): initialising relative time", date, &from_fw, &rule_fw); #endif ret = dnssec_policy_date_init_from_date(date, from + 60, rule); // +60 because it must be after and because of minute granularity #if DEBUG log_debug1("dnssec_policy_date_init_at_next_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw); #endif return ret; } case ZONE_POLICY_RULE: { #if DEBUG log_debug1("dnssec_policy_date_init_at_next_date(%p, %w, %w): initialising rule-based time", date, &from_fw, &rule_fw); #endif ret = dnssec_policy_date_init_at_next_rule(date, from, rule); #if DEBUG log_debug1("dnssec_policy_date_init_at_next_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw); #endif return ret; } default: { #if DEBUG log_debug1("dnssec_policy_date_init_at_next_date(%p, %w, %w): unexpected type", date, &from_fw, &rule_fw); #endif return POLICY_ILLEGAL_DATE_TYPE; } } } static dnssec_policy_date* dnssec_policy_table_get_date_by_index(dnssec_policy_table_s *tbl, int index) { switch(index) { case ZONE_POLICY_RELATIVE_TO_GENERATE: return &tbl->created; case ZONE_POLICY_RELATIVE_TO_PUBLISH: return &tbl->publish; case ZONE_POLICY_RELATIVE_TO_ACTIVATE: return &tbl->activate; case ZONE_POLICY_RELATIVE_TO_INACTIVE: return &tbl->inactive; case ZONE_POLICY_RELATIVE_TO_REMOVE: return &tbl->delete; #if HAS_DS_PUBLICATION_SUPPORT case ZONE_POLICY_RELATIVE_TO_DS_PUBLISH: return &tbl->ds_publish; case ZONE_POLICY_RELATIVE_TO_DS_REMOVE: return &tbl->ds_remove; #endif default: return NULL; } } ya_result dnssec_policy_table_init_from_date(dnssec_policy_table_s *tbl, dnssec_policy_table_s *with, dnssec_policy_date *from) { ya_result ret; if(with->created.type.type == ZONE_POLICY_RULE) { if(ISOK(ret = dnssec_policy_date_init_from_date(&tbl->created, from, &with->created))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->activate, &tbl->publish, &with->activate))) { #if DEBUG format_writer c_fw = {dnssec_policy_date_format_handler_method, &tbl->created}; format_writer p_fw = {dnssec_policy_date_format_handler_method, &tbl->publish}; format_writer a_fw = {dnssec_policy_date_format_handler_method, &tbl->activate}; log_debug("dnssec_policy_table_init: base c:%w => p:%w => a:%w", &c_fw, &p_fw, &a_fw); #endif // compute the future key timings to ensure there will be no period without a signature dnssec_policy_date next_creation_date; dnssec_policy_date next_publish_date; dnssec_policy_date next_activate_date; if(ISOK(ret = dnssec_policy_date_init_at_next_date(&next_creation_date, &tbl->activate, &with->created))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&next_publish_date, &next_creation_date, &with->publish))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&next_activate_date, &next_publish_date, &with->activate))) { #if DEBUG format_writer na_fw = {dnssec_policy_date_format_handler_method, &next_activate_date}; format_writer np_fw = {dnssec_policy_date_format_handler_method, &next_publish_date}; format_writer nc_fw = {dnssec_policy_date_format_handler_method, &next_creation_date}; log_debug("dnssec_policy_table_init: next c:%w => p:%w => a:%w", &nc_fw, &np_fw, &na_fw); #endif if(ISOK(ret = dnssec_policy_date_init_from_date(&tbl->inactive, &next_activate_date, &with->inactive))) { #if HAS_DS_PUBLICATION_SUPPORT if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->ds_add, &tbl->created, &with->ds_add))) { ret = dnssec_policy_date_init_at_next_date(&tbl->ds_del, &tbl->ds_add, &with->ds_del); } } #else ret = dnssec_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete); #if DEBUG format_writer i_fw = {dnssec_policy_date_format_handler_method, &tbl->inactive}; format_writer d_fw = {dnssec_policy_date_format_handler_method, &tbl->delete}; log_debug("dnssec_policy_table_init: base i:%w => d:%w", &i_fw, &d_fw); #endif #endif } } } } } } } } else if(with->created.type.type == ZONE_POLICY_RELATIVE) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->created, from, &with->created))) // here ! { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->activate, dnssec_policy_table_get_date_by_index(tbl, with->activate.relative.relativeto), &with->activate))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->inactive, dnssec_policy_table_get_date_by_index(tbl, with->inactive.relative.relativeto), &with->inactive))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->delete, dnssec_policy_table_get_date_by_index(tbl, with->delete.relative.relativeto), &with->delete))) { } } } } } } else { ret = POLICY_ILLEGAL_DATE_TYPE; } return ret; } ya_result dnssec_policy_table_init_from_created_epoch(dnssec_policy_table_s *tbl, dnssec_policy_table_s *with, time_t created_epoch) { ya_result ret; if(FAIL(ret = dnssec_policy_date_init_from_epoch(&tbl->created, created_epoch))) { return ret; } if(with->created.type.type == ZONE_POLICY_RULE) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->activate, &tbl->publish, &with->activate))) { #if DEBUG format_writer c_fw = {dnssec_policy_date_format_handler_method, &tbl->created}; format_writer p_fw = {dnssec_policy_date_format_handler_method, &tbl->publish}; format_writer a_fw = {dnssec_policy_date_format_handler_method, &tbl->activate}; log_debug("dnssec_policy_table_init: base %w => %w => %w", &c_fw, &p_fw, &a_fw); #endif // compute the future key timings to ensure there will be no period without a signature dnssec_policy_date next_creation_date; dnssec_policy_date next_publish_date; dnssec_policy_date next_activate_date; if(ISOK(ret = dnssec_policy_date_init_at_next_date(&next_creation_date, &tbl->activate, &with->created))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&next_publish_date, &next_creation_date, &with->publish))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&next_activate_date, &next_publish_date, &with->activate))) { #if DEBUG format_writer na_fw = {dnssec_policy_date_format_handler_method, &next_activate_date}; format_writer np_fw = {dnssec_policy_date_format_handler_method, &next_publish_date}; format_writer nc_fw = {dnssec_policy_date_format_handler_method, &next_creation_date}; log_debug("dnssec_policy_table_init: next %w => %w => %w", &nc_fw, &np_fw, &na_fw); #endif if(ISOK(ret = dnssec_policy_date_init_from_date(&tbl->inactive, &next_activate_date, &with->inactive))) { #if HAS_DS_PUBLICATION_SUPPORT if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->ds_add, &tbl->created, &with->ds_add))) { ret = dnssec_policy_date_init_at_next_date(&tbl->ds_del, &tbl->ds_add, &with->ds_del); } } #else ret = dnssec_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete); #endif } } } } } } } else if(with->created.type.type == ZONE_POLICY_RELATIVE) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->activate, dnssec_policy_table_get_date_by_index(tbl, with->activate.relative.relativeto), &with->activate))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->inactive, dnssec_policy_table_get_date_by_index(tbl, with->inactive.relative.relativeto), &with->inactive))) { if(ISOK(ret = dnssec_policy_date_init_at_next_date(&tbl->delete, dnssec_policy_table_get_date_by_index(tbl, with->delete.relative.relativeto), &with->delete))) { } } } } } else { ret = POLICY_ILLEGAL_DATE_TYPE; } return ret; } static bool dnssec_policy_key_roll_matches(const struct dnssec_policy_key_suite *kr, const dnssec_key *key) { yassert((kr->key->flags == DNSKEY_FLAGS_KSK) || (kr->key->flags == DNSKEY_FLAGS_ZSK)); if(dnskey_get_algorithm(key) == kr->key->algorithm) { // matches flags if((dnskey_get_flags(key) & DNSKEY_FLAGS_KSK) == kr->key->flags) { int key_size = dnskey_get_size(key); if((key_size - kr->key->size) < 48) { // algorithm, flags and size are matching // now what about the times if((key->epoch_created != 0) && (key->epoch_publish != 0) && (key->epoch_activate != 0) && (key->epoch_inactive != 0) && (key->epoch_delete != 0)) { log_debug1("dnssec-policy: %s: %s: key %05d/%d timings: %U %U %U %U %U", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), key->epoch_created, key->epoch_publish, key->epoch_activate, key->epoch_inactive, key->epoch_delete); dnssec_policy_table_s key_tbl; // kr->roll->time_table.created.type //dnssec_policy_table_init_from_epoch(&key_tbl, &kr->roll->time_table, key->epoch_created); // .. 33900 //dnssec_policy_table_init_from_date(dnssec_policy_table_s *tbl, dnssec_policy_table_s *with, dnssec_policy_date *from) if(ISOK(dnssec_policy_table_init_from_created_epoch(&key_tbl, &kr->roll->time_table, key->epoch_created))) { time_t key_created = 0, key_publish = 0, key_activate = 0, key_inactive = 0, key_delete = 0; dnssec_policy_date_get_epoch(&key_tbl.created, &key_created); dnssec_policy_date_get_epoch(&key_tbl.publish, &key_publish); dnssec_policy_date_get_epoch(&key_tbl.activate, &key_activate); dnssec_policy_date_get_epoch(&key_tbl.inactive, &key_inactive); dnssec_policy_date_get_epoch(&key_tbl.delete, &key_delete); u32 margin = keyroll_deactivation_margin(key_activate, key_inactive, key_delete); s64 pait = (key_inactive + margin) - key_activate; s64 kait = key->epoch_inactive - key->epoch_activate; s64 dait = labs(pait - kait); s64 pidt = key_delete - (key_inactive + margin); s64 kidt = key->epoch_delete - key->epoch_inactive; s64 didt = labs(pidt - kidt); s64 dc = labs(key_created - key->epoch_created); s64 dp = labs(key_publish - key->epoch_publish); s64 da = labs(key_activate - key->epoch_activate); s64 di = labs((key_inactive + margin) - key->epoch_inactive); s64 dd = labs(key_delete - key->epoch_delete); //bool match = (/*dc < KEY_POLICY_EPOCH_MATCH_MARGIN &&*/ dp < KEY_POLICY_EPOCH_MATCH_MARGIN && da < KEY_POLICY_EPOCH_MATCH_MARGIN && di < KEY_POLICY_EPOCH_MATCH_MARGIN && dd < KEY_POLICY_EPOCH_MATCH_MARGIN); // This checks if the key matches were it counts. We already know flags & size are a match, now if it lives long enough and is deleted in time, then it is a match. // The next key generation will have to align to these timings to find when will be the next one. bool match = (dait < KEY_POLICY_EPOCH_MATCH_MARGIN) && (didt < KEY_POLICY_EPOCH_MATCH_MARGIN); log_debug2("dnssec-policy: %s: %s: key %05d/%d pkd: ai=%lli id=%lli, with a margin of %lli", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), dait, didt, KEY_POLICY_EPOCH_MATCH_MARGIN); log_debug2("dnssec-policy: %s: %s: key %05d/%d deltas: (%lli) %lli %lli %lli %lli, with a margin of %lli", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), dc, dp, da, di, dd, KEY_POLICY_EPOCH_MATCH_MARGIN); log_debug1("dnssec-policy: %s: %s: key %05d/%d expects: %U %U %U %U %U : %s", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), key_created, key_publish, key_activate, key_inactive, key_delete, ((match)?"MATCH":"DIFFERS")); return match; } // else dnssec_policy_table_init_from_created_epoch failed and something is wrong => false else { log_err("dnssec-policy: %s: %s: key %05d/%d matching triggered an error in dnssec_policy_table_init_from_created_epoch", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags)); } } else { log_debug1("dnssec-policy: %s: %s: key %05d/%d is not a match as it has no time table (skipping)", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags)); } } else { log_debug1("dnssec-policy: %s: %s: key %05d/%d of size %i is not a match as the expected size is %i (skipping for this key roll)", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), key_size, kr->key->size); } } else { log_debug1("dnssec-policy: %s: %s: key %05d/%d is not a match as the expected flags is %i (skipping for this key roll)", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), ntohs(kr->key->flags)); } } else { log_debug1("dnssec-policy: %s: %s: key %05d/%d is not a match as the expected algorithm is %i (skipping for this key roll)", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), kr->key->algorithm); } return FALSE; } /** * Compares keys by activation time, inactivation time and tag. * Handles 0 epoch as "never" (as expected) * * @param a_ * @param b_ * @return */ static int dnssec_policy_dnssec_key_ptr_vector_qsort_by_activation_time_callback(const void *a_, const void *b_) { const dnssec_key *a = (const dnssec_key*)a_; const dnssec_key *b = (const dnssec_key*)b_; if(a == b) { return 0; } s64 a_a = a->epoch_activate; if(a_a == 0) { a_a = DNSSEC_POLICY_EPOCH_DOOMSDAY; } s64 b_a = b->epoch_activate; if(b_a == 0) { b_a = DNSSEC_POLICY_EPOCH_DOOMSDAY; } s64 r = a_a - b_a; if(r == 0) { s64 a_i = a->epoch_inactive; if(a_i == 0) { a_i = DNSSEC_POLICY_EPOCH_DOOMSDAY; } s64 b_i = b->epoch_inactive; if(b_i == 0) { b_i = DNSSEC_POLICY_EPOCH_DOOMSDAY; } r = a_i - b_i; if(r == 0) { r = dnskey_get_tag_const(a) - dnskey_get_tag_const(b); if(r == 0) { r = dnskey_get_algorithm(a) - dnskey_get_algorithm(b); if(r == 0) { u8 a_bytes[1024]; u8 b_bytes[1024]; u32 a_size = a->vtbl->dnssec_key_writerdata(a, a_bytes, sizeof(a_bytes)); u32 b_size = b->vtbl->dnssec_key_writerdata(b, b_bytes, sizeof(b_bytes)); r = a_size - b_size; if(r == 0) { r = memcmp(a_bytes, b_bytes, a_size); } } } } } return r; } static void dnssec_policy_log_debug_key(const char *prefix, const dnssec_key *key) { EPOCHZ_DEF2(created, key->epoch_created); EPOCHZ_DEF2(publish, key->epoch_publish); EPOCHZ_DEF2(activate, key->epoch_activate); EPOCHZ_DEF2(inactive, key->epoch_inactive); EPOCHZ_DEF2(delete, key->epoch_delete); #if 0 /* fix */ #else log_debug("%sK%{dnsname}+%03d+%05d/%d created=%1w publish=%1w activate=%1w inactive=%1w delete=%1w", prefix, key->owner_name, key->algorithm, dnskey_get_tag_const(key), ntohs(key->flags), EPOCHZ_REF(created), EPOCHZ_REF(publish), EPOCHZ_REF(activate), EPOCHZ_REF(inactive), EPOCHZ_REF(delete)); #endif } #if 0 static void dnssec_policy_print_key(const char *prefix, const dnssec_key *key) { EPOCHZ_DEF2(created, key->epoch_created); EPOCHZ_DEF2(publish, key->epoch_publish); EPOCHZ_DEF2(activate, key->epoch_activate); EPOCHZ_DEF2(inactive, key->epoch_inactive); EPOCHZ_DEF2(delete, key->epoch_delete); #if 0 /* fix */ #else formatln("%sK%{dnsname}+%03d+%05d/%d created=%1w publish=%1w activate=%1w inactive=%1w delete=%1w", prefix, key->owner_name, key->algorithm, dnskey_get_tag_const(key), ntohs(key->flags), EPOCHZ_REF(created), EPOCHZ_REF(publish), EPOCHZ_REF(activate), EPOCHZ_REF(inactive), EPOCHZ_REF(delete)); #endif } #endif ya_result dnssec_policy_roll_create_from_rules(const char *id, const dnssec_policy_rule_definition_s *generate, const dnssec_policy_rule_definition_s *publish, const dnssec_policy_rule_definition_s *activate, const dnssec_policy_rule_definition_s *inactive, const dnssec_policy_rule_definition_s *remove, const dnssec_policy_rule_definition_s *ds_publish, const dnssec_policy_rule_definition_s *ds_remove) { log_debug("dnssec-policy-roll: %s: (rules stuff)", id); dnssec_policy_roll *dpr; ZALLOC_OBJECT_OR_DIE( dpr, dnssec_policy_roll, DPOLROLL_TAG); dpr->name = strdup(id); group_mutex_write_lock(&dnssec_policy_roll_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_policy_roll_set, dpr->name); if(node->value != NULL) { dnssec_policy_roll_release((dnssec_policy_roll*)node->value); node->key = dpr->name; } dnssec_policy_rule_init(&dpr->time_table.created.rule, generate); dnssec_policy_rule_init(&dpr->time_table.publish.rule, publish); dnssec_policy_rule_init(&dpr->time_table.activate.rule, activate); dnssec_policy_rule_init(&dpr->time_table.inactive.rule, inactive); dnssec_policy_rule_init(&dpr->time_table.delete.rule, remove); #if HAS_DS_PUBLICATION_SUPPORT dnssec_policy_rule_init(&dpr->time_table.ds_add.rule, ds_publish); dnssec_policy_rule_init(&dpr->time_table.ds_del.rule, ds_remove); #else (void)ds_publish; (void)ds_remove; #endif dpr->rc = 1; node->value = dpr; group_mutex_write_unlock(&dnssec_policy_roll_set_mtx); return 0; } ya_result dnssec_policy_roll_create_from_relatives(const char *id, const dnssec_policy_relative_s *generate, u8 generate_from, const dnssec_policy_relative_s *publish, u8 publish_from, const dnssec_policy_relative_s *activate, u8 activate_from, const dnssec_policy_relative_s *inactive, u8 inactive_from, const dnssec_policy_relative_s *remove, u8 remove_from #if HAS_DS_PUBLICATION_SUPPORT , const dnssec_policy_relative_s *ds_publish, u8 ds_publish_from, const dnssec_policy_relative_s *ds_remove, u8 ds_remove_from #endif ) { log_debug("dnssec-policy-roll: %s: (relative stuff)", id); if(generate->seconds < 60) { log_err("dnssec-policy: %s: generate parameter cannot be less than one minute", id); return POLICY_ILLEGAL_DATE_PARAMETERS; } if(inactive->seconds - activate->seconds < 60) { log_err("dnssec-policy: %s: key appears to not be activated for even one minute", id); return POLICY_ILLEGAL_DATE_PARAMETERS; } if(generate->seconds < 3600) { log_warn("dnssec-policy: %s: key is generated every %i seconds. Keys are expected to be generated every few weeks, months or years.", id, generate->seconds); } if(inactive->seconds - activate->seconds < generate->seconds) { log_warn("dnssec-policy: %s: key appears to not be activated for less time than the generation period", id); } dnssec_policy_roll *dpr; ZALLOC_OBJECT_OR_DIE( dpr, dnssec_policy_roll, DPOLROLL_TAG); dpr->name = strdup(id); group_mutex_write_lock(&dnssec_policy_roll_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_policy_roll_set, dpr->name); if(node->value != NULL) { dnssec_policy_roll_release((dnssec_policy_roll*)node->value); node->value = NULL; } dpr->time_table.created.relative = *generate; dpr->time_table.publish.relative = *publish; dpr->time_table.activate.relative = *activate; dpr->time_table.inactive.relative = *inactive; dpr->time_table.delete.relative = *remove; dpr->time_table.created.relative.seconds += 59; dpr->time_table.created.relative.seconds -= (dpr->time_table.created.relative.seconds % 60); dpr->time_table.publish.relative.seconds += 59; dpr->time_table.publish.relative.seconds -= (dpr->time_table.publish.relative.seconds % 60); dpr->time_table.activate.relative.seconds += 59; dpr->time_table.activate.relative.seconds -= (dpr->time_table.activate.relative.seconds % 60); dpr->time_table.inactive.relative.seconds += 59; dpr->time_table.inactive.relative.seconds -= (dpr->time_table.inactive.relative.seconds % 60); dpr->time_table.delete.relative.seconds += 59; dpr->time_table.delete.relative.seconds -= (dpr->time_table.delete.relative.seconds % 60); #if HAS_DS_PUBLICATION_SUPPORT dpr->time_table.ds_add.relative = *ds_publish; dpr->time_table.ds_del.relative = *ds_remove; #endif yassert(publish_from <= ZONE_POLICY_RELATIVE_TO_GENERATE); yassert(activate_from <= ZONE_POLICY_RELATIVE_TO_PUBLISH); yassert(inactive_from <= ZONE_POLICY_RELATIVE_TO_INACTIVE); yassert(remove_from <= ZONE_POLICY_RELATIVE_TO_REMOVE); #if HAS_DS_PUBLICATION_SUPPORT yassert(ds_publish_from <= ZONE_POLICY_RELATIVE_TO_DS_PUBLISH); yassert(ds_remove_from <= ZONE_POLICY_RELATIVE_TO_DS_REMOVE); #endif dpr->time_table.created.relative.relativeto = generate_from; dpr->time_table.publish.relative.relativeto = publish_from; dpr->time_table.activate.relative.relativeto = activate_from; dpr->time_table.inactive.relative.relativeto = inactive_from; dpr->time_table.delete.relative.relativeto = remove_from; #if HAS_DS_PUBLICATION_SUPPORT dpr->time_table.ds_add.relative.relativeto = ds_publish_from; dpr->time_table.ds_del.relative.relativeto = ds_remove_from; #endif dpr->rc = 1; node->key = dpr->name; node->value = dpr; group_mutex_write_unlock(&dnssec_policy_roll_set_mtx); return 0; } dnssec_policy_roll * dnssec_policy_roll_acquire_from_name(const char *id) { dnssec_policy_roll *dpr = NULL; group_mutex_read_lock(&dnssec_policy_roll_set_mtx); ptr_node *node = ptr_set_find(&dnssec_policy_roll_set, id); if(node != NULL) { dpr = (dnssec_policy_roll*)node->value; group_mutex_write_lock(&dnssec_policy_roll_mtx); ++dpr->rc; group_mutex_write_unlock(&dnssec_policy_roll_mtx); } group_mutex_read_unlock(&dnssec_policy_roll_set_mtx); return dpr; } #if 0 ya_result dnssec_policy_roll_test_all(time_t active_at, u32 duration_seconds, bool print_text, bool log_text) { group_mutex_read_lock(&dnssec_policy_roll_set_mtx); ptr_set_iterator iter; ptr_set_iterator_init(&dnssec_policy_roll_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); if(index == 0) { if(node->value != NULL) { dnssec_policy_roll *dpr = (dnssec_policy_roll*)node->value; group_mutex_write_lock(&dnssec_policy_roll_mtx); ret = dnssec_policy_key_roll_test( dpr, active_at, duration_seconds, print_text, log_text); group_mutex_write_unlock(&dnssec_policy_roll_mtx); } break; } --index; } group_mutex_read_unlock(&dnssec_policy_roll_set_mtx); } #endif dnssec_policy_roll * dnssec_policy_roll_acquire_from_index(int index) { dnssec_policy_roll *dpr = NULL; if(index >= 0) { group_mutex_read_lock(&dnssec_policy_roll_set_mtx); ptr_set_iterator iter; ptr_set_iterator_init(&dnssec_policy_roll_set, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); if(index == 0) { if(node->value != NULL) { dpr = (dnssec_policy_roll*)node->value; group_mutex_write_lock(&dnssec_policy_roll_mtx); ++dpr->rc; group_mutex_write_unlock(&dnssec_policy_roll_mtx); } break; } --index; } group_mutex_read_unlock(&dnssec_policy_roll_set_mtx); } return dpr; } void dnssec_policy_roll_release(dnssec_policy_roll *dpr) { group_mutex_write_lock(&dnssec_policy_roll_mtx); if(--dpr->rc == 0) { // destroy the table if(dpr->time_table.created.type.type == ZONE_POLICY_RULE) { dnssec_policy_rule_finalize(&dpr->time_table.created.rule); } if(dpr->time_table.publish.type.type == ZONE_POLICY_RULE) { dnssec_policy_rule_finalize(&dpr->time_table.publish.rule); } if(dpr->time_table.activate.type.type == ZONE_POLICY_RULE) { dnssec_policy_rule_finalize(&dpr->time_table.activate.rule); } if(dpr->time_table.inactive.type.type == ZONE_POLICY_RULE) { dnssec_policy_rule_finalize(&dpr->time_table.inactive.rule); } if(dpr->time_table.delete.type.type == ZONE_POLICY_RULE) { dnssec_policy_rule_finalize(&dpr->time_table.delete.rule); } #if HAS_DS_PUBLICATION_SUPPORT if(dpr->time_table.ds_add.type.type == ZONE_POLICY_RULE) { dnssec_policy_rule_finalize(&dpr->time_table.ds_add.rule); } if(dpr->time_table.ds_del.type.type == ZONE_POLICY_RULE) { dnssec_policy_rule_finalize(&dpr->time_table.ds_del.rule); } #endif free(dpr->name); ZFREE_OBJECT(dpr); } group_mutex_write_unlock(&dnssec_policy_roll_mtx); } dnssec_policy_key * dnssec_policy_key_create(const char *id, u8 algorithm, u16 size, bool ksk, char* engine) { log_debug("dnssec-policy-key: %s: algorithm=%hhu, size=%hu, ksk=%i, engine=%s", id, algorithm, size, ksk, STRNULL(engine)); (void)engine; dnssec_policy_key *dpk = NULL; ZALLOC_OBJECT_OR_DIE( dpk, dnssec_policy_key, DPOLKEY_TAG); dpk->name = strdup(id); dpk->flags = (ksk)?DNSKEY_FLAGS_KSK:DNSKEY_FLAGS_ZSK; dpk->size = size; dpk->algorithm = algorithm; dpk->rc = 1; group_mutex_write_lock(&dnssec_policy_key_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_policy_key_set, dpk->name); if(node->value != NULL) { dnssec_policy_key_release((dnssec_policy_key*)node->value); node->key = dpk->name; } node->value = dpk; group_mutex_write_unlock(&dnssec_policy_key_set_mtx); return dpk; } dnssec_policy_key * dnssec_policy_key_acquire_from_name(const char *id) { dnssec_policy_key *dpk = NULL; group_mutex_read_lock(&dnssec_policy_key_set_mtx); ptr_node *node = ptr_set_find(&dnssec_policy_key_set, id); if(node != NULL && node->value != NULL) { dpk = (dnssec_policy_key*)node->value; group_mutex_write_lock(&dnssec_policy_key_mtx); ++dpk->rc; group_mutex_write_unlock(&dnssec_policy_key_mtx); } group_mutex_read_unlock(&dnssec_policy_key_set_mtx); return dpk; } void dnssec_policy_key_release(dnssec_policy_key *dpk) { group_mutex_write_lock(&dnssec_policy_key_mtx); if(--dpk->rc == 0) { free(dpk->name); ZFREE_OBJECT(dpk); } group_mutex_write_unlock(&dnssec_policy_key_mtx); } dnssec_policy_key_suite * dnssec_policy_key_suite_create(const char *id, dnssec_policy_key *dpk, dnssec_policy_roll *dpr) { log_debug("dnssec-policy-key-suite: %s: policy-key=%s, policy-roll=%s", id, dpk->name, dpr->name); dnssec_policy_key_suite *dpks = NULL; ZALLOC_OBJECT_OR_DIE( dpks, dnssec_policy_key_suite, DPOLKYST_TAG); dpks->name = strdup(id); dpks->key = dnssec_policy_key_acquire_from_name(dpk->name); dpks->roll = dnssec_policy_roll_acquire_from_name(dpr->name); dpks->rc = 1; group_mutex_write_lock(&dnssec_policy_key_suite_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_policy_key_suite_set, dpks->name); if(node->value != NULL) { dnssec_policy_key_suite_release((dnssec_policy_key_suite*)node->value); } node->key = dpks->name; node->value = dpks; group_mutex_write_unlock(&dnssec_policy_key_suite_set_mtx); return dpks; } dnssec_policy_key_suite * dnssec_policy_key_suite_acquire_from_name(const char *id) { dnssec_policy_key_suite *dpks = NULL; group_mutex_read_lock(&dnssec_policy_key_suite_set_mtx); ptr_node *node = ptr_set_find(&dnssec_policy_key_suite_set, id); if(node != NULL && node->value != NULL) { dpks = (dnssec_policy_key_suite*)node->value; group_mutex_write_lock(&dnssec_policy_key_suite_mtx); ++dpks->rc; group_mutex_write_unlock(&dnssec_policy_key_suite_mtx); } group_mutex_read_unlock(&dnssec_policy_key_suite_set_mtx); return dpks; } void dnssec_policy_key_suite_acquire(dnssec_policy_key_suite *dpks) { group_mutex_write_lock(&dnssec_policy_key_suite_mtx); ++dpks->rc; group_mutex_write_unlock(&dnssec_policy_key_suite_mtx); } void dnssec_policy_key_suite_release(dnssec_policy_key_suite *dpks) { group_mutex_write_lock(&dnssec_policy_key_suite_mtx); if(--dpks->rc == 0) { free(dpks->name); dnssec_policy_key_release(dpks->key); dnssec_policy_roll_release(dpks->roll); ZFREE_OBJECT(dpks); } group_mutex_write_unlock(&dnssec_policy_key_suite_mtx); } static int ptr_vector_qsort_key_suite_callback(const void *ptr1, const void *ptr2) { const dnssec_policy_key_suite *ks1 = (const dnssec_policy_key_suite*)ptr1; const dnssec_policy_key_suite *ks2 = (const dnssec_policy_key_suite*)ptr2; if(ks1->key != NULL) { if(ks2->key != NULL) { int f1 = ntohs(ks1->key->flags); int f2 = ntohs(ks2->key->flags); int ret = f2 - f1; // KSK before ZSK if(ret == 0) { ret = ks2->key->algorithm - ks1 ->key->algorithm; // recent algorithms before older ones if(ret == 0) { ret = ks2->key->size - ks1->key->size; if(ret == 0) { ret = strcmp(ks1->name, ks2->name); } } } return ret; } else { return 1; } } else { if(ks2->key != NULL) { return -1; } else { return 0; } } } dnssec_policy * dnssec_policy_create(char *name, ptr_vector *key_suite) { dnssec_policy *dp = NULL; log_debug("dnssec-policy: %s", name); bool has_zsk = FALSE; ZALLOC_OBJECT_OR_DIE( dp, dnssec_policy, DNSECPOL_TAG); dp->name = strdup(name); ptr_vector_init_ex(&dp->key_suite, ptr_vector_size(key_suite)); for(int i = 0; i <= ptr_vector_last_index(key_suite); ++i) { dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)ptr_vector_get(key_suite, i); if((dpks->key->flags & DNSKEY_FLAGS_KSK) != DNSKEY_FLAGS_KSK) { has_zsk = TRUE; } dnssec_policy_key_suite *dpks_a = dnssec_policy_key_suite_acquire_from_name(dpks->name); for(int j = 0; j <= ptr_vector_last_index(&dp->key_suite); ++j) { dnssec_policy_key_suite* dpks_b = (dnssec_policy_key_suite*)ptr_vector_get(&dp->key_suite, j); if(dpks_a == dpks_b) { // dup log_warn("dnssec-policy: %s: key-suite %s is a duplicate entry", name, dpks->name); dnssec_policy_key_suite_release(dpks_a); dpks_a = NULL; break; } } if(dpks_a != NULL) { ptr_vector_append(&dp->key_suite, dpks_a); log_debug("dnssec-policy: %s: key-suite %s added", name, dpks->name); } } dp->rc = 1; ptr_vector_qsort(&dp->key_suite, ptr_vector_qsort_key_suite_callback); if(has_zsk) { log_warn("dnssec-policy: %s: no key-signing-key in the key-suite", name); } group_mutex_write_lock(&dnssec_policy_set_mtx); ptr_node *node = ptr_set_insert(&dnssec_policy_set, dp->name); if(node->value != NULL) { dnssec_policy_release((dnssec_policy*)node->value); node->key = dp->name; } node->value = dp; group_mutex_write_unlock(&dnssec_policy_set_mtx); return dp; } dnssec_policy * dnssec_policy_acquire_from_name(const char *id) { dnssec_policy *dp = NULL; group_mutex_read_lock(&dnssec_policy_set_mtx); ptr_node *node = ptr_set_find(&dnssec_policy_set, id); if(node != NULL && node->value != NULL) { dp = (dnssec_policy*)node->value; group_mutex_write_lock(&dnssec_policy_mtx); ++dp->rc; group_mutex_write_unlock(&dnssec_policy_mtx); } group_mutex_read_unlock(&dnssec_policy_set_mtx); return dp; } void dnssec_policy_acquire(dnssec_policy *dp) { group_mutex_write_lock(&dnssec_policy_mtx); ++dp->rc; group_mutex_write_unlock(&dnssec_policy_mtx); } void dnssec_policy_release(dnssec_policy *dp) { group_mutex_write_lock(&dnssec_policy_mtx); if(--dp->rc == 0) { free(dp->name); #if DEBUG dp->name = NULL; #endif for(int i = 0; i <= ptr_vector_last_index(&dp->key_suite); ++i) { dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)ptr_vector_get(&dp->key_suite, i); dnssec_policy_key_suite_release(dpks); } ZFREE_OBJECT(dp); } group_mutex_write_unlock(&dnssec_policy_mtx); } ya_result dnssec_policy_zone_desc_config(const char *value, void *dest, anytype sizeoftarget) { (void)sizeoftarget; dnssec_policy **dp = (dnssec_policy**)dest; if(*dp != NULL) { dnssec_policy_release(*dp); } if(value != NULL) { *dp = dnssec_policy_acquire_from_name(value); return (*dp != NULL)?SUCCESS:POLICY_UNDEFINED; } else { return POLICY_NULL_REQUESTED; } } static void dnssec_policy_process_release_keys_cb(void *ptr) { dnssec_key *key = (dnssec_key*)ptr; if(key != NULL) { dnskey_release(key); } } static ya_result dnssec_policy_key_roll_keys_generate_at(keyroll_t *keyroll, struct dnssec_policy_key_suite *kr, ptr_vector *key_roll_keys_vector, time_t now) { const u8 *origin = keyroll->domain; ya_result ret = ERROR; log_debug("dnssec-policy: %{dnsname}: %s: key suite has %i matching keys", origin, kr->name, ptr_vector_size(key_roll_keys_vector)); if(ptr_vector_size(key_roll_keys_vector) > 0) { // sort array by time if(ptr_vector_last_index(key_roll_keys_vector) > 0) // more than one item in the collection { ptr_vector_qsort(key_roll_keys_vector, dnssec_policy_dnssec_key_ptr_vector_qsort_by_activation_time_callback); } // ensure we have continuity // start with a base period dnssec_key *previous_key = NULL; s64 previous_begin_period; s64 previous_next_period; s64 previous_end_period; { previous_key = (dnssec_key*)ptr_vector_get(key_roll_keys_vector, 0); #if DEBUG log_debug("dnssec-policy: %s: %s: key %05d/%d timings: %U %U %U %U %U [0]", previous_key->origin, kr->name, dnskey_get_tag_const(previous_key), ntohs(previous_key->flags), previous_key->epoch_created, previous_key->epoch_publish, previous_key->epoch_activate, previous_key->epoch_inactive, previous_key->epoch_delete); #endif previous_begin_period = previous_key->epoch_activate; previous_next_period = previous_begin_period; previous_end_period = previous_key->epoch_inactive; } log_debug("dnssec-policy: %{dnsname}: %s: first key will be inactive at %U", origin, kr->name, previous_end_period); for(int i = 1; i <= ptr_vector_last_index(key_roll_keys_vector); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(key_roll_keys_vector, i); #if DEBUG bool print_details = (i > MAX(0, ptr_vector_last_index(key_roll_keys_vector) - 3)); if(print_details) { log_debug("dnssec-policy: %s: %s: key %05d/%d timings: %U %U %U %U %U [%i / %i]", key->origin, kr->name, dnskey_get_tag_const(key), ntohs(key->flags), key->epoch_created, key->epoch_publish, key->epoch_activate, key->epoch_inactive, key->epoch_delete, i, ptr_vector_last_index(key_roll_keys_vector)); } #endif previous_next_period = key->epoch_activate; // ensure the key chains with this interval if(key->epoch_activate > previous_end_period /*|| key->epoch_inactive < begin_period irrelevant because of the sort */) { // bad log_err("dnssec-policy: %{dnsname}: timeline hole of %d seconds (%.1f days) from %U to %U (%U)", origin, key->epoch_activate - previous_end_period, (1.0f * (key->epoch_activate - previous_end_period)) / 86400.0f, previous_end_period, key->epoch_activate, now); dnssec_policy_log_debug_key("dnssec-policy: unchained ", key); /* * This case happens if there is at least one key K with timings in the future but the last key L of the valid chain is made inactive * before K is being made active. */ ret = KEYROLL_HOLE_IN_TIMELINE; return ret; } else // the key chains fine { // if the previous key ends before this one we keep it if(previous_end_period < key->epoch_inactive) { previous_key = key; previous_end_period = key->epoch_inactive; } else { // else the key is irrelevant for the chain } } } if(dnskey_get_flags(previous_key) == DNSKEY_FLAGS_KSK) { keyroll->ksk_next_deactivation = ONE_SECOND_US * dnskey_get_inactive_epoch(previous_key); } else { keyroll->zsk_next_deactivation = ONE_SECOND_US * dnskey_get_inactive_epoch(previous_key); } log_debug("dnssec-policy: %{dnsname}: %s: covered from %U to %U, last key activates at %U (kr: K=%lU, Z=%lU)", origin, kr->name, previous_begin_period, previous_end_period, previous_next_period, keyroll->ksk_next_deactivation, keyroll->zsk_next_deactivation); if(previous_key->epoch_created <= now) { if(kr->roll->time_table.created.type.type == ZONE_POLICY_RELATIVE) { if(FAIL(ret = dnssec_policy_add_generate_key_create_at(keyroll, kr, previous_key->epoch_created, NULL))) { log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from previous key: %r", origin, kr->name, ret); } } else if(kr->roll->time_table.created.type.type == ZONE_POLICY_RULE) { if(FAIL(ret = dnssec_policy_add_generate_key_active_at(keyroll, kr, previous_end_period + 60))) { log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from previous end period: %r", origin, kr->name, ret); } } else { log_err("dnssec-policy: %{dnsname}: %s: is not supported by this version of the policies", origin, kr->name); } } else { // formatln("%U <= %U", previous_key->epoch_created <= now); ret = SUCCESS; // ignore } ptr_vector_callback_and_destroy(key_roll_keys_vector, dnssec_policy_process_release_keys_cb); } else { // no key at all ? do a full init (with (re)signature) log_info("dnssec-policy: %{dnsname}: %s: will be completely initialised", origin, kr->name); // for relative rules: do it now // for cron rules: generate it back-dated if(kr->roll->time_table.created.type.type == ZONE_POLICY_RELATIVE) { // add the command, aim to be active "now" s32 delta = kr->roll->time_table.created.relative.seconds + // from the previous created key ... kr->roll->time_table.publish.relative.seconds + kr->roll->time_table.activate.relative.seconds ; if(delta > now) { delta = now - 1; } log_debug("dnssec-policy: %{dnsname}: %s: will generate a first key at %U minus %i = %U", origin, kr->name, now, delta, now - delta); if(FAIL(ret = dnssec_policy_add_generate_key_create_at(keyroll, kr, now - delta, NULL))) // works on any kind of dates { log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation before %U: %r", origin, kr->name, now - delta, ret); } } else if(kr->roll->time_table.created.type.type == ZONE_POLICY_RULE) { // compute the back-dated epoch if(FAIL(ret = dnssec_policy_add_generate_key_active_at(keyroll, kr, now))) // @note : only works on rules { log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from %U: %r", origin, kr->name, now, ret); } } else { log_err("dnssec-policy: %{dnsname}: %s: don't know how to proceed", origin, kr->name); ret = INVALID_STATE_ERROR; } } return ret; } ya_result dnssec_policy_process_at(keyroll_t *keyroll, const dnssec_policy *policy, time_t now) { // the policy is referenced by the zone desc // and the zone desc by the parent // no need to acquire anything here ya_result ret = SUCCESS; const u8 *origin = keyroll->domain; log_debug("dnssec-policy: %{dnsname} applying policy %s with %i keys", origin, policy->name, ptr_vector_size(&policy->key_suite)); // // enumerate the available keys and if they are in the zone and being used and so on. // KEEP, IGNORE, REMOVE ptr_vector key_roll_keys[DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM]; for(int i = 0; i < DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM; ++i) { ptr_vector_init_ex(&key_roll_keys[i], 0); // with an initial capacity set to 0, no allocation is made until at one item is added } yassert(ptr_vector_size(&policy->key_suite) <= 8); int origin_key_count = 0; int origin_ksk_count = 0; int origin_zsk_count = 0; int origin_key_ignored = 0; int origin_key_added = 0; int origin_key_not_matched = 0; for(int keystore_key_index = 0;; ++keystore_key_index) { dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_at_index(origin, keystore_key_index); if(key == NULL) { // formatln("origin_key_count=%i origin_ksk_count=%i origin_zsk_count=%i origin_key_ignored=%i origin_key_added=%i origin_key_not_matched=%i", origin_key_count, origin_ksk_count, origin_zsk_count, origin_key_ignored, origin_key_added, origin_key_not_matched); break; } ++origin_key_count; if(dnskey_get_flags(key) == DNSKEY_FLAGS_KSK) { ++origin_ksk_count; } else { ++origin_zsk_count; } dnssec_policy_log_debug_key("dnssec-policy: found ", key); /* * @note 20160425 edf -- care must be taken here, keys may be generated in a background processing. * also, a key can only effectively be found after its generation (which discards the idea of virtual key) * so whatever is done here, pending key creation tasks should be taken into account (other operations are "real time") * * If the key is expired, * ignore it (it should be handled by the smart signing). * If the key is out of the expected parameters (size/alg) and it is not acceptable, * edit the times of the keys and remember the smart signing should be triggered. * If the key is valid, keep it on the side. * */ if(!dnskey_is_private(key) || dnskey_is_expired(key, now) || (key->epoch_publish == 0) || (key->epoch_inactive == 0)) { //dnssec_policy_log_debug_key("dnssec-policy: ignore ", key); //dnssec_policy_print_key("dnssec-policy: ignore ", key); // this key is irrelevant. It will be released after this control block. ++origin_key_ignored; } else { // for all key suite, if the key matches the suite, add the key to the suite array bool got_match = FALSE; //formatln("%{dnsname}: suite '%s' contains %i suites", origin, policy->name, ptr_vector_size(&policy->key_suite)); for(int ksi = 0; ksi <= ptr_vector_last_index(&policy->key_suite); ++ksi) { const struct dnssec_policy_key_suite *kr = (const struct dnssec_policy_key_suite*)ptr_vector_get(&policy->key_suite, ksi); if(dnssec_policy_key_roll_matches(kr, key)) { log_debug("%{dnsname}: key matches suite '%s'", origin, kr->name); dnskey_acquire(key); ptr_vector_append(&key_roll_keys[ksi], key); ++origin_key_added; got_match = TRUE; } // else not part of this policy } if(!got_match) { log_debug("%{dnsname}: key doesn't match any suite", origin); ++origin_key_not_matched; } } dnskey_release(key); } log_debug("dnssec-policy: %{dnsname} released", origin); /* * sort-out the remaining keys * trigger the generation of keys * * keys of the array are matching the policy */ for(int ksi = 0; ksi <= ptr_vector_last_index(&policy->key_suite); ++ksi) { struct dnssec_policy_key_suite *kr = (struct dnssec_policy_key_suite*)ptr_vector_get(&policy->key_suite, ksi); if(FAIL(ret = dnssec_policy_key_roll_keys_generate_at(keyroll, kr, &key_roll_keys[ksi], now))) { break; } } // for all key suites for(int i = 0; i < DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM; ++i) { ptr_vector_callback_and_destroy(&key_roll_keys[i], dnssec_policy_process_release_keys_cb); } // decide what to do return ret; // returns success or the last error from the key generation part } ya_result dnssec_policy_process(keyroll_t *keyroll, const dnssec_policy *policy, s64 from, s64 until) { s64 t = from; if(t < until) { ya_result ret; do { #if DEBUG log_debug("------------------------------------------------------------------------------"); #endif log_info("keyroll: %{dnsname} processing: %s from %llU to %llU", keyroll->domain, policy->name, t, until); formatln("keyroll: %{dnsname} processing: %s from %llU to %llU", keyroll->domain, policy->name, t, until); #if DEBUG logger_flush(); // 2019-08-13 23:45:00.000000 flushout(); flusherr(); #endif if(ISOK(ret = dnssec_policy_process_at(keyroll, policy, t / ONE_SECOND_US))) { t = MIN(keyroll->ksk_next_deactivation, keyroll->zsk_next_deactivation); log_debug("keyroll: %{dnsname}: processed: %s covers: %llU , %llU", keyroll->domain, policy->name, keyroll->ksk_next_deactivation, keyroll->zsk_next_deactivation); #if DEBUG logger_flush(); // 2019-08-13 23:45:00.000000 #endif } else { break; } if(dnscore_shuttingdown()) { ret = STOPPED_BY_APPLICATION_SHUTDOWN; break; } } while(t < until); return ret; } else { return INVALID_STATE_ERROR; } } /** * @} */ yadifa-2.6.5-11201/sbin/yakeyrolld/PaxHeaders.1636/keyroll.c0000644000000000000000000000013214505005533021276 xustar000000000000000030 mtime=1695812443.257993861 30 atime=1695812445.785030053 30 ctime=1695812495.820746665 yadifa-2.6.5-11201/sbin/yakeyrolld/keyroll.c0000664000374500037450000040165014505005533021246 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #include "keyroll.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dnssec-policy.h" #include "buildinfo.h" #define TTL 86400 #define RRSIG_ANTEDATING 86400 // sign from the day before #define DNSKEY_DEACTIVATION_MARGIN 86400 #define UPDATE_SUBCOMMAND_ADD 0 #define UPDATE_SUBCOMMAND_DELETE 1 #define RECORD_SIZE_MAX (2 + 1 + 1 + 4 + 4 + 4 + 2 + 256 + 1024) #define MODULE_MSG_HANDLE g_keyroll_logger #define NEXT_SIGNATURE_EPOCH_MARGIN 57 // one minute should be enough, and adding a non-minute multiple makes is easier to notice #define KEYROLL_STEPS_MAX 1000 // Typically: 13 keys a year, ready for two years. More is kind of counter-productive. So 1000 is plenty. // exceptions requiring a bigger limit are corner-cases tests #define ISTREAMP_TAG 0x504d414552545349 logger_handle *g_keyroll_logger = LOGGER_HANDLE_SINK; static bool keyroll_dryrun_mode = FALSE; u32 keyroll_deactivation_margin(u32 activate_epoch, u32 deactivate_epoch, u32 delete_epoch) { u32 margin; #if 1 s64 total_activated_time = deactivate_epoch; total_activated_time -= activate_epoch; if(total_activated_time >= 0) { s64 total_lingering_time = delete_epoch; total_lingering_time -= deactivate_epoch; if(total_lingering_time < 0) { log_err("keyroll: inverted activated and deactivated epoch"); margin = DNSKEY_DEACTIVATION_MARGIN; } else if(total_lingering_time / 2 > DNSKEY_DEACTIVATION_MARGIN) { margin = DNSKEY_DEACTIVATION_MARGIN; } else { margin = total_lingering_time / 2; } } else { log_err("keyroll: inverted activated and deactivated epoch"); margin = DNSKEY_DEACTIVATION_MARGIN; } #else margin = 57; #endif u32 remainder = margin % 60; margin -= remainder; margin += 57; if(margin < 60) { margin += 60; } log_debug("keyroll_deactivation_margin: %u", DNSKEY_DEACTIVATION_MARGIN); return margin; } ya_result keyroll_step_delete(keyroll_step_t *step); //static const char *token_delmiter = " \t\r\n"; static int keyroll_dns_resource_record_ptr_vector_qsort_callback(const void *a, const void *b) { const dns_resource_record *ra = (const dns_resource_record*)a; const dns_resource_record *rb = (const dns_resource_record*)b; int ret = dns_resource_record_compare(ra, rb); return ret; } void keyroll_errors_register() { error_register(KEYROLL_ERROR_BASE, "KEYROLL_ERROR_BASE"); error_register(KEYROLL_EXPECTED_IDENTICAL_RECORDS, "KEYROLL_EXPECTED_IDENTICAL_RECORDS"); error_register(KEYROLL_EXPECTED_IDENTICAL_SIZE_RRSETS, "KEYROLL_EXPECTED_IDENTICAL_SIZE_RRSETS"); error_register(KEYROLL_EXPECTED_DNSKEY_OR_RRSIG, "KEYROLL_EXPECTED_DNSKEY_OR_RRSIG"); error_register(KEYROLL_UPDATE_SUBCOMMAND_ERROR, "KEYROLL_UPDATE_SUBCOMMAND_ERROR"); error_register(KEYROLL_HOLE_IN_TIMELINE, "KEYROLL_HOLE_IN_TIMELINE"); error_register(KEYROLL_MUST_REINITIALIZE, "KEYROLL_MUST_REINITIALIZE"); } ya_result keyroll_init(keyroll_t* keyroll, const u8 *domain, const char *plan_path, const char *keys_path, const host_address *server, bool generation_mode) { ya_result ret = SUCCESS; memset(keyroll, 0, sizeof(keyroll_t)); keyroll->ksk_parameters.algorithm = DNSKEY_ALGORITHM_RSASHA256_NSEC3; keyroll->ksk_parameters.size = /*4096*/2048; keyroll->ksk_parameters.activate_after = 86400; keyroll->ksk_parameters.deactivate_after = 86400 + 86400*366; keyroll->ksk_parameters.delete_after = 86400 + 86400*366 + 86400; keyroll->ksk_parameters.estimated_signing_time = 86400; keyroll->zsk_parameters.algorithm = DNSKEY_ALGORITHM_RSASHA256_NSEC3; keyroll->zsk_parameters.size = 2048; keyroll->zsk_parameters.activate_after = 86400; keyroll->zsk_parameters.deactivate_after = 86400 + 86400*31; keyroll->zsk_parameters.delete_after = 86400 + 86400*31 + 86400; keyroll->zsk_parameters.estimated_signing_time = 86400 * 7; keyroll->update_apply_verify_retries = 60; // if an update wasn't applied successfully, retry CHECKING this amount of times keyroll->update_apply_verify_retries_delay = 1; // time between the above retries keyroll->match_verify_retries = 60; // if there is no match, retry checking this amount of times keyroll->match_verify_retries_delay = 1; // time between the above retries keyroll->generation_mode = generation_mode; asformat(&keyroll->plan_path, "%s/%{dnsname}", plan_path, domain); if(generation_mode) { if(FAIL(ret = mkdir_ex(keyroll->plan_path, 0700, 0))) { log_err("keyroll: %{dnsname}: could not create directory: '%s'", domain, keyroll->plan_path); free(keyroll->plan_path); keyroll->plan_path = NULL; return ret; } asformat(&keyroll->private_keys_path, "%s/%{dnsname}" YKEYROLL_KSK_SUFFIX, plan_path, domain); if(FAIL(ret = mkdir_ex(keyroll->private_keys_path, 0700, 0))) { log_err("keyroll: %{dnsname}: could not create directory: '%s'", domain, keyroll->private_keys_path); free(keyroll->plan_path); keyroll->plan_path = NULL; free(keyroll->private_keys_path); keyroll->private_keys_path = NULL; return ret; } dnssec_keystore_add_domain(domain, keyroll->private_keys_path); } else { if(FAIL(ret = file_is_directory(keyroll->plan_path))) { log_err("keyroll: %{dnsname}: could not find directory: '%s'", domain, keyroll->plan_path); } } keyroll->keys_path = strdup(keys_path); keyroll->domain = dnsname_zdup(domain); keyroll->domain = dnsname_zdup(domain); keyroll->server = host_address_copy(server); keyroll->keyring = dnskey_keyring_new(); return ret; } static void keyroll_finalize_steps_delete_callback(u64_node *node) { keyroll_step_t *step = (keyroll_step_t*)node->value; keyroll_step_delete(step); } void keyroll_finalize(keyroll_t *keyroll) { if(keyroll != NULL) { free(keyroll->private_keys_path); keyroll->private_keys_path = NULL; free(keyroll->plan_path); keyroll->plan_path = NULL; free(keyroll->keys_path); keyroll->keys_path = NULL; if(keyroll->domain != NULL) { dnsname_zfree(keyroll->domain); keyroll->domain = NULL; } if(keyroll->server != NULL) { host_address_delete(keyroll->server); keyroll->server = NULL; } if(keyroll->keyring != NULL) { dnskey_keyring_free(keyroll->keyring); keyroll->keyring = NULL; } u64_set_callback_and_destroy(&keyroll->steps, keyroll_finalize_steps_delete_callback); memset(keyroll, 0, sizeof(keyroll_t)); } } ya_result keyroll_fetch_public_keys_from_server(keyroll_t* keyroll) { ya_result ret; const u8 *domain = keyroll->domain; const host_address *server = keyroll->server; /* memset(keyroll, 0, sizeof(keyroll_t)); asformat(&keyroll->plan_path, "%s/%{dnsname}", plan_path, domain); if(FAIL(ret = mkdir_ex(keyroll->plan_path, 0700, 0))) { free(keyroll->plan_path); return ret; } keyroll->keys_path = strdup(keys_path); keyroll->private_keys_path = strdup(private_keys_path); dnssec_keystore_add_domain(domain, private_keys_path); */ message_data *mesg = message_new_instance(); dnskey_keyring *keyring = keyroll->keyring; //u8 fqdn[MAX_DOMAIN_LENGTH]; //message_set_edns0(mesg, TRUE); message_make_query(mesg, rand(), domain, TYPE_DNSKEY, CLASS_IN); if(ISOK(ret = message_query(mesg, server))) { // extract DNSKEY (and maybe their RRSIG) struct packet_unpack_reader_data pr; packet_reader_init_from_message(&pr, mesg); // ensure there is exactly one answer // skip the matching query content, or fail if(ISOK(ret = (message_get_query_count(mesg) == 1)?SUCCESS:ERROR) && ISOK(ret = packet_reader_skip_query(&pr, domain, TYPE_DNSKEY, CLASS_IN))) { u16 answer_count = message_get_answer_count(mesg); if(answer_count > 0) { size_t buffer_size = 0x20000; u8 *buffer; MALLOC_OBJECT_ARRAY_OR_DIE(buffer, u8, buffer_size, GENERIC_TAG); dns_resource_record rr; dns_resource_record_init(&rr); for(u16 i = 0; i < answer_count; ++i) { if(FAIL(ret = packet_reader_read_dns_resource_record(&pr, &rr))) { break; } if(rr.tctr.qtype == TYPE_DNSKEY) { dnssec_key *key; if(FAIL(ret = dnskey_new_from_rdata(rr.rdata, rr.rdata_size, domain, &key))) { break; } // got one key if(FAIL(ret = dnskey_keyring_add(keyring, key))) { // e.g.: collision dnskey_release(key); } } dns_resource_record_clear(&rr); } dns_resource_record_finalize(&rr); free(buffer); } } } message_free(mesg); return ret; } ya_result keyroll_init_from_server(keyroll_t* keyroll, const u8 *domain, const char *plan_path, const char *keys_path, const host_address *server) { ya_result ret; if(FAIL(ret = keyroll_init(keyroll, domain, plan_path, keys_path, server, TRUE))) { return ret; } ret = keyroll_fetch_public_keys_from_server(keyroll); if(FAIL(ret)) { keyroll_finalize(keyroll); } return ret; } ya_result keyroll_update_apply_verify_retries_set(keyroll_t* keyroll, u32 retries, u32 delay) { if(retries * delay < 3600) { keyroll->update_apply_verify_retries = retries; keyroll->update_apply_verify_retries_delay = delay; return SUCCESS; } else { return CONFIG_VALUE_OUT_OF_RANGE; } } ya_result keyroll_match_verify_retries_set(keyroll_t* keyroll, u32 retries, u32 delay) { if(retries * delay < 3600) { keyroll->match_verify_retries = retries; keyroll->match_verify_retries_delay = delay; return SUCCESS; } else { return CONFIG_VALUE_OUT_OF_RANGE; } } typedef struct keyroll_file_item_s { char *name; u8 *data; size_t size; bool name_allocated; bool data_allocated; } keyroll_file_item_t; typedef struct keyroll_file_s { u8 *data; size_t data_size; output_stream baos; input_stream bais; } keyroll_file_t; void keyroll_file_init(keyroll_file_t *kf) { kf->data = NULL; kf->data_size = 0; output_stream_set_void(&kf->baos); input_stream_set_void(&kf->bais); } void keyroll_file_write_start(keyroll_file_t *kf) { bytearray_output_stream_init_ex(&kf->baos, kf->data, kf->data_size, BYTEARRAY_DYNAMIC); } void keyroll_file_write(keyroll_file_t *kf, const char* filename, const void *data, size_t data_size) { size_t filename_len = strlen(filename) + 1; // +1 for the terminator output_stream_write_u8(&kf->baos, filename_len); output_stream_write(&kf->baos, filename, filename_len); output_stream_write_u16(&kf->baos, data_size); output_stream_write(&kf->baos, data, data_size); } void keyroll_file_write_stop(keyroll_file_t *kf) { kf->data_size = bytearray_output_stream_size(&kf->baos); kf->data = bytearray_output_stream_detach(&kf->baos); output_stream_close(&kf->baos); } static ya_result input_stream_create_from_base64_text(input_stream* is, const char *text, const char* text_limit) { ya_result ret; output_stream baos; char tmp[128]; u8 decoded[128]; bytearray_output_stream_init(&baos, NULL, 0); for(;;) { int i; for(i = 0; (i < (int)sizeof(tmp)) && (text < text_limit); ++text) { char c = *text; if(base64_character_set_contains(c)) { tmp[i++] = c; } } if(i == 0) { break; } ya_result n = base64_decode(tmp, i, decoded); if(FAIL(n)) { ret = n; output_stream_close(&baos); return ret; } output_stream_write(&baos, decoded, n); } bytearray_input_stream_init(is, bytearray_output_stream_buffer(&baos), bytearray_output_stream_size(&baos), TRUE); bytearray_output_stream_detach(&baos); ret = (ya_result)bytearray_input_stream_size(is); return ret; } static ya_result keyroll_parse_record(parser_s *parser, dns_resource_record **rrp) { ya_result ret; s32 rttl; s32 rdata_size = RECORD_SIZE_MAX; u16 rtype; u8 fqdn[MAX_DOMAIN_LENGTH]; u8 rdata[RECORD_SIZE_MAX]; // enough for a 8192 bits key // parse the domain (must match) if(FAIL(ret = parser_copy_next_fqdn(parser, fqdn))) { return ret; } // parse the TTL if(FAIL(ret = parser_copy_next_ttl(parser, &rttl))) { return ret; } // parse the type (should be DNSKEY or RRSIG) if(FAIL(ret = parser_copy_next_type(parser, &rtype))) { return ret; } if((rtype == TYPE_DNSKEY) || (rtype == TYPE_RRSIG)) { // parse the rdata using zone_reader_text_copy_rdata if(FAIL(ret = parser_concat_next_tokens(parser))) { return ret; } char *rdata_text = (char*)parser_text(parser); u32 rdata_text_size = parser_text_length(parser); ret = zone_reader_text_len_copy_rdata(rdata_text, rdata_text_size, rtype, rdata, rdata_size, fqdn); if(ISOK(ret)) { rdata_size = ret; if(rtype == TYPE_RRSIG) { if(rrsig_get_type_covered_from_rdata(rdata, rdata_size) != TYPE_DNSKEY) { return INVALID_STATE_ERROR; } } *rrp = dns_resource_record_new_instance(); dns_resource_record_init_record(*rrp, fqdn, rtype, CLASS_IN, rttl, rdata_size, rdata); } } else { // error ret = KEYROLL_EXPECTED_DNSKEY_OR_RRSIG; } return ret; } static inline bool equals_char_array(const char *command, const char *text, size_t text_len) { size_t command_len = strlen(command); if(command_len == text_len) { return (memcmp(command, text, text_len) == 0); } else { return FALSE; } } #define equals_static_string(command_, text_) equals_char_array((command_), (text_), sizeof(text_) - 1) static ya_result keyroll_plan_step_load(keyroll_t *keyroll, const char *file) { keyroll_step_t *step = NULL; input_stream fis; s64 epochus; ya_result ret; // keyroll file // load file // read the whole file in memory // read it line by line struct parser_s parser; char full_path[PATH_MAX]; if(FAIL(ret = parser_init(&parser, "", // by 2 "", // by 2 "", // by 1 " \r\t", // by 1 "\\"))) // by 1 { return ret; } log_debug("parsing '%s'", file); snformat(full_path, sizeof(full_path), "%s/%s", keyroll->plan_path, file); ret = file_input_stream_open(&fis, full_path); if(ISOK(ret)) { if(ISOK(ret = parser_push_stream(&parser, &fis))) { // start to parse // it's always: // command words // parameters dnskey_keyring *kr = dnskey_keyring_new(); char command[32]; for(;;) { if(FAIL(ret = parser_copy_next_word(&parser, command, sizeof(command)))) { if(step != NULL) { if(ret == PARSER_REACHED_END_OF_LINE) { continue; } if(ret == PARSER_REACHED_END_OF_FILE) { ret = SUCCESS; } } break; } if(step == NULL) { if(equals_static_string(command, "epochus")) { char epochus_buffer[24]; if(FAIL(ret = parser_copy_next_word(&parser, epochus_buffer, sizeof(epochus_buffer)))) { break; } int n = ret; if(FAIL(ret = parse_u64_check_range_len_base10(epochus_buffer, n, (u64*)&epochus, 0, MAX_S64))) { break; } step = keyroll_get_step(keyroll, epochus); } else { log_err("parsing '%s': the first keyword of a step should be 'epochus', not '%s'", file, command); ret = PARSESTRING_ERROR; break; } } else // step != NULL { if(equals_static_string(command, "dateus")) { // human readable, epochus check char date_buffer[16]; char time_buffer[20]; if(FAIL(ret = parser_copy_next_word(&parser, date_buffer, sizeof(date_buffer)))) { break; } if(FAIL(ret = parser_copy_next_word(&parser, time_buffer, sizeof(time_buffer)))) { break; } char datetime_check[64]; char datetime_check2[64]; snformat(datetime_check, sizeof(datetime_check), "%llU", step->epochus); strcpy(datetime_check2, date_buffer); strcat(datetime_check2, " "); strcat(datetime_check2, time_buffer); if(strcmp(datetime_check, datetime_check2) != 0) { flushout(); osformatln(termerr, "'%s' does not match '%s' (%lli)", datetime_check, datetime_check2, step->epochus); flusherr(); log_err("'%s' does not match '%s' (%lli)", datetime_check, datetime_check2, step->epochus); ret = INVALID_STATE_ERROR; break; } } else if(equals_static_string(command, "actions") || equals_static_string(command, "version") || equals_static_string(command, "debug")) { // human-readable, implies some of the commands that will follow // version, ignored for(;;) { ret = parser_next_word(&parser); if(FAIL(ret)) { break; } } if(ret == PARSER_REACHED_END_OF_LINE) { continue; } else { break; } } else if( (equals_static_string(command, "add")) || (equals_static_string(command, "del")) ) { // filename base64 of a file char file_name[MAX_DOMAIN_TEXT_LENGTH + 2]; char domain_name[MAX_DOMAIN_TEXT_LENGTH + 2]; if(FAIL(ret = parser_copy_next_word(&parser, file_name, sizeof(file_name)))) { break; } if(ret < 16) // name has to be a bare minimal size 1 + 1 + 4 + 6 + (4,8) = (15,19) { ret = PARSESTRING_ERROR; break; } if(step == NULL) { return INVALID_STATE_ERROR; } int n = ret; // line += n; // everything else is the base64 encoding of a file u32 algorithm; u32 tag; if(sscanf(file_name, "K%255[^+]+%03u+%05u.", domain_name, &algorithm, &tag) != 3) { ret = PARSESTRING_ERROR; break; } bool is_public = (memcmp(&file_name[n - 4], ".key", 4) == 0); bool is_private = !is_public && (memcmp(&file_name[n - 8], ".private", 8) == 0); if(command[0] == 'd') { // delete ptr_vector_append(&step->file_del, strdup(file_name)); if(FAIL(ret = parser_concat_next_tokens_nospace(&parser))) { break; } } else { // add if(FAIL(ret = parser_concat_next_tokens_nospace(&parser))) { break; } input_stream bais; if(FAIL(ret = input_stream_create_from_base64_text(&bais, parser_text(&parser), &parser_text(&parser)[parser_text_length(&parser)]))) { break; } if(is_public) { dnssec_key *key; if(ISOK(ret = dnskey_new_public_key_from_stream(&bais, &key))) { dnskey_keyring_add(kr, key); dnskey_release(key); } else { log_err("failed to get new public key from stream: %r", ret); } // keep a copy of the added file ptr_node *node = ptr_set_insert(&step->file_add, file_name); if(node->value == NULL) { node->key = strdup(file_name); input_stream *is; ZALLOC_OBJECT_OR_DIE(is, input_stream, ISTREAMP_TAG); input_stream_create_from_base64_text(is, parser_text(&parser), &parser_text(&parser)[parser_text_length(&parser)]); node->value = is; } else { // already exists ret = INVALID_STATE_ERROR; break; } // } else if(is_private) { dnssec_key *key = dnskey_keyring_acquire(kr, algorithm, tag, keyroll->domain); ret = dnskey_add_private_key_from_stream(&bais, key, NULL, dnskey_get_algorithm(key)); log_debug("adding key to keystore: %i, %i, create=%llU publish=%llU activate=%llU deactivate=%llU unpublish=%llU", dnskey_get_algorithm(key), ntohs(dnskey_get_flags(key)), ONE_SECOND_US * dnskey_get_created_epoch(key), ONE_SECOND_US * dnskey_get_publish_epoch(key), ONE_SECOND_US * dnskey_get_activate_epoch(key), ONE_SECOND_US * dnskey_get_inactive_epoch(key), ONE_SECOND_US * dnskey_get_delete_epoch(key)); #if 0 if(dnskey_get_publish_epoch(key) == 0) { keyroll_set_timing_steps(keyroll, key, FALSE); log_debug("------ key to keystore: %i, %i, create=%llU publish=%llU activate=%llU deactivate=%llU unpublish=%llU", dnskey_get_algorithm(key), ntohs(dnskey_get_flags(key)), ONE_SECOND_US * dnskey_get_created_epoch(key), ONE_SECOND_US * dnskey_get_publish_epoch(key), ONE_SECOND_US * dnskey_get_activate_epoch(key), ONE_SECOND_US * dnskey_get_inactive_epoch(key), ONE_SECOND_US * dnskey_get_delete_epoch(key)); } #endif dnssec_keystore_add_key(key); /* if(command[0] == 'd') { ptr_vector_append(&step->dnskey_del, key); dnskey_acquire(key); } else { ptr_vector_append(&step->dnskey_add, key); dnskey_acquire(key); } */ step->dirty = FALSE; if(is_public || (is_private && (dnskey_get_flags(key) != DNSKEY_FLAGS_KSK))) { // keep a copy of the added file ptr_node *node = ptr_set_insert(&step->file_add, file_name); if(node->value == NULL) { char *name = strdup(file_name); node->key = name; input_stream *is; ZALLOC_OBJECT_OR_DIE(is, input_stream, ISTREAMP_TAG); input_stream_create_from_base64_text(is, parser_text(&parser), &parser_text(&parser)[parser_text_length(&parser)]); node->value = is; } else { ret = INVALID_STATE_ERROR; break; } // } dnskey_release(key); } else { ret = PARSESTRING_ERROR; } } if(FAIL(ret)) { break; } } else if(equals_static_string(command, "update")) { // the list of nsupdate commands (add and delete) char subcommand[16]; if(FAIL(ret = parser_copy_next_word(&parser, subcommand, sizeof(subcommand)))) { break; } int subcommand_type; if(equals_static_string(subcommand, "add")) { subcommand_type = UPDATE_SUBCOMMAND_ADD; } else if(equals_static_string(subcommand, "delete")) { subcommand_type = UPDATE_SUBCOMMAND_DELETE; } else { ret = KEYROLL_UPDATE_SUBCOMMAND_ERROR; break; } // parse the record dns_resource_record *rr = NULL; if(ISOK(ret = keyroll_parse_record(&parser, &rr))) { log_debug("update add %{dnszrr}", rr); if(subcommand_type == UPDATE_SUBCOMMAND_ADD) { switch(rr->tctr.qtype) // scan-build false positive (ISOK => rr not NULL) { case TYPE_RRSIG: { u16 tag = rrsig_get_key_tag_from_rdata(rr->rdata, rr->rdata_size); //u8 algorithm = rrsig_get_algorithm_from_rdata(rr->rdata, rr->rdata_size); dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_with_tag(keyroll->domain, tag); if(key != NULL) { if(dnskey_get_flags(key) == DNSKEY_FLAGS_KSK) { u32 valid_from = rrsig_get_valid_from_from_rdata(rr->rdata, rr->rdata_size); u32 valid_until = rrsig_get_valid_until_from_rdata(rr->rdata, rr->rdata_size); if(!dnskey_has_explicit_activate(key)) { dnskey_set_activate_epoch(key, valid_from + RRSIG_ANTEDATING * 2); } if(!dnskey_has_explicit_deactivate(key)) { dnskey_set_inactive_epoch(key, valid_until); } } ptr_vector_append(&step->rrsig_add, rr); dnskey_release(key); } else { ptr_vector_append(&step->rrsig_add, rr); } break; } case TYPE_DNSKEY: { // if the key is a KZK, load its private key if it's available dnssec_key *key = NULL; if(keyroll->generation_mode && (DNSKEY_FLAGS_FROM_RDATA(rr->rdata) == DNSKEY_FLAGS_KSK)) { ret = dnssec_keystore_load_private_key_from_rdata(rr->rdata, rr->rdata_size, rr->name, &key); if(ISOK(ret)) { if(!dnskey_is_private(key)) { log_err("parsing '%s': private file for key signing key K%{dnsname}+%03i+%05i is missing", file, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key)); ret = ERROR; } } } else { ret = dnssec_keystore_load_public_key_from_rdata(rr->rdata, rr->rdata_size, rr->name, &key); } if(FAIL(ret)) { if(key != NULL) { dnskey_release(key); } rdata_desc rdatadesc = {TYPE_DNSKEY, rr->rdata_size, rr->rdata}; flushout(); osformatln(termerr, "parsing '%s': unable to load key: %{dnsname} IN %{typerdatadesc}: %r", file, rr->name, &rdatadesc, ret); flusherr(); log_err("parsing '%s': unable to load key: %{dnsname} IN %{typerdatadesc}: %r", file, rr->name, &rdatadesc, ret); return ret; } // ignore duplicates for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_add); ++i) { dnssec_key *keyi = (dnssec_key*)ptr_vector_get(&step->dnskey_add, i); if(dnskey_equals(keyi, key)) { dnskey_release(key); key = NULL; break; } } if(key != NULL) { if(dnskey_get_publish_epoch(key) == 0) { dnskey_set_publish_epoch(key, step->epochus / ONE_SECOND_US); } ptr_vector_append(&step->dnskey_add, key); } dns_resource_record_free(rr); break; } default: { log_warn("parsing '%s': unexpected add record type: %{dnszrr}", file, rr); dns_resource_record_free(rr); break; } } } else // UPDATE_SUBCOMMAND_DELETE { switch(rr->tctr.qtype) // scan-build false positive (ISOK => rr not NULL) { case TYPE_DNSKEY: { // if the key is a KZK, load its private key if it's available dnssec_key *key = NULL; if(keyroll->generation_mode && (DNSKEY_FLAGS_FROM_RDATA(rr->rdata) == DNSKEY_FLAGS_KSK)) { ret = dnssec_keystore_load_private_key_from_rdata(rr->rdata, rr->rdata_size, rr->name, &key); if(ISOK(ret)) { if(!dnskey_is_private(key)) { log_err("parsing '%s': private file for key signing key K%{dnsname}+%03i+%05i is missing", file, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key)); ret = ERROR; } } } else { ret = dnssec_keystore_load_public_key_from_rdata(rr->rdata, rr->rdata_size, rr->name, &key); } if(FAIL(ret)) { rdata_desc rdatadesc = {TYPE_DNSKEY, rr->rdata_size, rr->rdata}; flushout(); osformatln(termerr, "parsing '%s': unable to load key: %{dnsname} IN %{typerdatadesc}: %r", file, rr->name, &rdatadesc, ret); flusherr(); log_err("parsing '%s': unable to load key: %{dnsname} IN %{typerdatadesc}: %r", file, rr->name, &rdatadesc, ret); return ret; } // ignore duplicates for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_del); ++i) { dnssec_key *keyi = (dnssec_key*)ptr_vector_get(&step->dnskey_del, i); if(dnskey_equals(keyi, key)) { dnskey_release(key); key = NULL; break; } } if(key != NULL) { if(!dnskey_has_explicit_delete(key)) { dnskey_set_delete_epoch(key, step->epochus / ONE_SECOND_US); } ptr_vector_append(&step->dnskey_del, key); } dns_resource_record_free(rr); break; } default: { log_warn("parsing '%s': unexpected del record type: %{dnszrr}", file, rr); dns_resource_record_free(rr); break; } } } } else { // error ret = ERROR; break; } } else if(equals_static_string(command, "expect")) { // if the master is queried after this step, // these are the records that should be returned in the answer // parse record dns_resource_record *rr = NULL; if(ISOK(ret = keyroll_parse_record(&parser, &rr))) { ptr_vector_append(&step->expect, rr); log_debug("expect %{dnszrr}", rr); } else { // error ret = ERROR; break; } } else if(equals_static_string(command, "endresult")) { // if the master is queried after this step, // these are the records that should be returned in the answer // parse record dns_resource_record *rr = NULL; if(ISOK(ret = keyroll_parse_record(&parser, &rr))) { ptr_vector_append(&step->endresult, rr); log_debug("expect %{dnszrr}", rr); } else { // error ret = ERROR; break; } } else { log_err("parsing '%s': unexpected keyword '%s'", file, command); ret = PARSESTRING_ERROR; break; } } // endif step != NULL ret = parser_expect_eol(&parser); if(FAIL(ret)) { break; } } parser_pop_stream(&parser); } else { log_err("parsing '%s': could not push stream of file '%s'", file, full_path); } input_stream_close(&fis); if(ISOK(ret)) { if(step != NULL) { ptr_vector_qsort(&step->expect, keyroll_dns_resource_record_ptr_vector_qsort_callback); ptr_vector_qsort(&step->endresult, keyroll_dns_resource_record_ptr_vector_qsort_callback); } else { ret = INVALID_STATE_ERROR; } } else { log_err("parsing '%s': keyroll_plan_step_load: failure: %r", file, ret); } } else { log_err("parsing '%s': could not open stream for file '%s'", file, full_path); } parser_finalize(&parser); return ret; } static ya_result keyroll_purge_step_readdir_forall_callback(const char *basedir, const char* file, u8 filetype, void *args) { if(filetype == DT_REG) { const char *domain = (char*)args; size_t domain_len = strlen(domain); size_t name_len = strlen(file); if(name_len > domain_len) { if(memcmp(&file[name_len - domain_len], domain, domain_len) == 0) { if(unlink_ex(basedir, file) < 0) { ya_result ret = ERRNO_ERROR; flushout(); osformatln(termerr, "failed to delete '%s': %r", file, ret); log_err("failed to delete '%s': %r", file, ret); flusherr(); return ret; } } } } return READDIR_CALLBACK_CONTINUE; } static ya_result keyroll_purge_key_readdir_forall_callback(const char *basedir, const char* file, u8 filetype, void *args) { (void)args; if(filetype == DT_REG) { size_t name_len = strlen(file); if((name_len > 8) && (memcmp(&file[name_len - 8], ".private", 8) == 0)) { if(unlink_ex(basedir, file) < 0) { ya_result ret = ERRNO_ERROR; flushout(); osformatln(termerr, "failed to delete '%s': %r", file, ret); flusherr(); log_err("failed to delete '%s': %r", file, ret); return ret; } } else if((name_len > 4) && (memcmp(&file[name_len - 4], ".key", 4) == 0)) { if(unlink_ex(basedir, file) < 0) { ya_result ret = ERRNO_ERROR; flushout(); osformatln(termerr, "failed to delete '%s': %r", file, ret); flusherr(); log_err("failed to delete '%s': %r", file, ret); return ret; } } } return READDIR_CALLBACK_CONTINUE; } ya_result keyroll_plan_purge(keyroll_t *keyroll) { ya_result ret; char domain[MAX_DOMAIN_TEXT_LENGTH]; dnsname_to_cstr(domain, keyroll->domain); if(ISOK(ret = readdir_forall(keyroll->plan_path, keyroll_purge_step_readdir_forall_callback, domain))) { ret = readdir_forall(keyroll->private_keys_path, keyroll_purge_key_readdir_forall_callback, NULL); } return ret; } static ya_result keyroll_plan_load_readdir_forall_callback(const char *basedir, const char *file, u8 filetype, void *args) { (void)basedir; (void)args; s64 epochus; u32 year, month, day; u32 hours, minutes, seconds; u32 microseconds; char fqdn[256]; #ifndef WIN32 if(filetype == DT_CHR) { return READDIR_CALLBACK_CONTINUE; } #endif if(sscanf(file, "%04u-%02u-%02u-%02u:%02u:%02u.%06uZ_%016lli_%255s.keyroll", &year, &month, &day, &hours, &minutes, &seconds, µseconds, &epochus, fqdn) == 9) { char date_check[64]; snformat(date_check, sizeof(date_check), "%llU", epochus); size_t date_check_len = strlen(date_check); date_check[10] = '-'; if(memcmp(file, date_check, date_check_len) == 0) { ptr_vector *files = (ptr_vector*)args; ptr_vector_append(files, strdup(file)); } else { formatln("ERROR: date for %lli should start '%s' but its '%s'", epochus, date_check, file); flushout(); return INVALID_STATE_ERROR; } } return SUCCESS; } static int keyroll_plan_load_ptr_vector_qsort_callback(const void *a, const void *b) { int ret = strcmp((char*)a, (char*)b); return ret; } /** * Loads a plan from disk. (all the steps) * Loads KSK private keys if they are available. */ ya_result keyroll_plan_load(keyroll_t *keyroll) { // reload all private keys (KSK in this case) dnssec_keystore_reload_domain(keyroll->domain); ptr_vector files; ptr_vector_init_ex(&files, 1024); ya_result ret = readdir_forall(keyroll->plan_path, keyroll_plan_load_readdir_forall_callback, &files); if(ISOK(ret)) { ptr_vector_qsort(&files, keyroll_plan_load_ptr_vector_qsort_callback); for(int i = 0; i <= ptr_vector_last_index(&files); ++i) { char *file = (char*)ptr_vector_get(&files, i); if(FAIL(ret = keyroll_plan_step_load(keyroll, file))) { log_err("failed to load '%s' : %r", file, ret); break; } ++keyroll->steps_count; if(keyroll->steps_count > KEYROLL_STEPS_MAX) { keyroll_finalize(keyroll); return BUFFER_WOULD_OVERFLOW; } } } for(int i = 0; i <= ptr_vector_last_index(&files); ++i) { char *file = (char*)ptr_vector_get(&files, i); free(file); } ptr_vector_destroy(&files); return ret; } keyroll_step_t* keyroll_step_new_instance() { keyroll_step_t *step; ZALLOC_OBJECT_OR_DIE(step, keyroll_step_t, GENERIC_TAG); memset(step, 0 ,sizeof(keyroll_step_t)); step->keyroll = NULL; step->epochus = 0; ptr_vector_init_empty(&step->dnskey_del); ptr_vector_init_empty(&step->dnskey_add); ptr_vector_init_empty(&step->rrsig_add); ptr_vector_init_empty(&step->expect); ptr_vector_init_empty(&step->endresult); ptr_set_init(&step->file_add); step->file_add.compare = ptr_set_asciizp_node_compare; ptr_vector_init_empty(&step->file_del); //u32_set_init(&step->dnskey_set); step->fingerprint = 0; step->from_merge = FALSE; return step; } static void keyroll_step_delete_dnskey_callback(void *key_) { dnssec_key *key = (dnssec_key*)key_; dnskey_release(key); } static void keyroll_step_delete_dns_resource_record_callback(void *rr_) { dns_resource_record *rr = (dns_resource_record*)rr_; dns_resource_record_free(rr); } static void keyroll_step_delete_file_add_callback(ptr_node *node) { free(node->key); input_stream *is = (input_stream*)node->value; input_stream_close(is); ZFREE_OBJECT(is); } static void keyroll_step_delete_file_del_callback(void *str_) { free(str_); } ya_result keyroll_step_delete(keyroll_step_t *step) { if(step != NULL) { ptr_vector_callback_and_destroy(&step->dnskey_del, keyroll_step_delete_dnskey_callback); ptr_vector_callback_and_destroy(&step->dnskey_add, keyroll_step_delete_dnskey_callback); ptr_vector_callback_and_destroy(&step->rrsig_add, keyroll_step_delete_dns_resource_record_callback); ptr_vector_callback_and_destroy(&step->expect, keyroll_step_delete_dns_resource_record_callback); ptr_vector_callback_and_destroy(&step->endresult, keyroll_step_delete_dns_resource_record_callback); ptr_set_callback_and_destroy(&step->file_add, keyroll_step_delete_file_add_callback); ptr_vector_callback_and_destroy(&step->file_del, keyroll_step_delete_file_del_callback); step->keyroll = NULL; step->epochus = 0; ZFREE_OBJECT(step); } return SUCCESS; } /** * Returns the step at the given epoch, or create an empty one */ keyroll_step_t* keyroll_get_step(keyroll_t *keyroll, s64 epochus) { u64_node* node = u64_set_insert(&keyroll->steps, epochus); if(node->value != NULL) { return (keyroll_step_t*)node->value; } else { keyroll_step_t *step = keyroll_step_new_instance(); step->keyroll = keyroll; step->epochus = epochus; node->value = step; return step; } } /** * Merges two consecutive steps. */ ya_result keyroll_step_merge(keyroll_step_t *into, keyroll_step_t *step) { if(into->keyroll == NULL) { into->keyroll = step->keyroll; } else if(into->keyroll != step->keyroll) { return INVALID_STATE_ERROR; } if(into->epochus < step->epochus) { into->epochus = step->epochus; } else { return INVALID_STATE_ERROR; } into->from_merge = TRUE; for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_del); ++i) { dnssec_key *keyi = (dnssec_key*)ptr_vector_get(&step->dnskey_del, i); bool not_added_anymore = FALSE; for(int j = 0; j <= ptr_vector_last_index(&into->dnskey_add); ++j) { dnssec_key *keyj = (dnssec_key*)ptr_vector_get(&into->dnskey_add, j); if(dnskey_equals(keyi, keyj)) { log_info("DNSKEY K%{dnsname}+%03d+%05d not added anymore", dnskey_get_domain(keyj), dnskey_get_algorithm(keyj), dnskey_get_tag_const(keyj)); ptr_vector_end_swap(&into->dnskey_add, j); ptr_vector_pop(&into->dnskey_add); dnskey_release(keyj); not_added_anymore = TRUE; } } if(!not_added_anymore) { dnskey_acquire(keyi); ptr_vector_append(&into->dnskey_del, keyi); } } for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_add); ++i) { dnssec_key *keyi = (dnssec_key*)ptr_vector_get(&step->dnskey_add, i); dnskey_acquire(keyi); ptr_vector_append(&into->dnskey_add, keyi); log_info("DNSKEY K%{dnsname}+%03d+%05d added", dnskey_get_domain(keyi), dnskey_get_algorithm(keyi), dnskey_get_tag_const(keyi)); } if((ptr_vector_last_index(&step->dnskey_add) >= 0) || (ptr_vector_last_index(&step->dnskey_del) >= 0)) { // if any DNSKEY is added/removed, then no current RRSIG is valid for(int i = 0; i <= ptr_vector_last_index(&into->rrsig_add); ++i) { dns_resource_record *rr = (dns_resource_record*)ptr_vector_get(&into->rrsig_add, i); dns_resource_record_free(rr); } ptr_vector_clear(&into->rrsig_add); } for(int i = 0; i <= ptr_vector_last_index(&step->rrsig_add); ++i) { dns_resource_record *rr = (dns_resource_record*)ptr_vector_get(&step->rrsig_add, i); dns_resource_record *rr_copy = dns_resource_record_new_instance(); dns_resource_init_from_record(rr_copy, rr); ptr_vector_append(&into->rrsig_add, rr_copy); } for(int i = 0; i <= ptr_vector_last_index(&into->expect); ++i) { dns_resource_record *rr = (dns_resource_record*)ptr_vector_get(&into->expect, i); dns_resource_record_free(rr); } ptr_vector_clear(&into->expect); for(int i = 0; i <= ptr_vector_last_index(&step->expect); ++i) { dns_resource_record *rr = (dns_resource_record*)ptr_vector_get(&step->expect, i); dns_resource_record *rr_copy = dns_resource_record_new_instance(); dns_resource_init_from_record(rr_copy, rr); ptr_vector_append(&into->expect, rr_copy); } ptr_vector_clear(&into->endresult); for(int i = 0; i <= ptr_vector_last_index(&step->endresult); ++i) { dns_resource_record *rr = (dns_resource_record*)ptr_vector_get(&step->endresult, i); dns_resource_record *rr_copy = dns_resource_record_new_instance(); dns_resource_init_from_record(rr_copy, rr); ptr_vector_append(&into->endresult, rr_copy); } for(int i = 0; i <= ptr_vector_last_index(&step->file_del); ++i) { char *filename = (char*)ptr_vector_get(&step->file_del, i); //bool not_added_anymore = FALSE; ptr_node *node = ptr_set_find(&into->file_add, filename); if(node != NULL) { log_info("'%s' not added anymore", filename); char *key = (char*)node->key; input_stream *is = (input_stream*)node->value; // VS false positive: 'is' cannot be NULL or the node would not exist input_stream_close(is); ZFREE_OBJECT(is); node->value = NULL; ptr_set_delete(&into->file_add, filename); free(key); //not_added_anymore = TRUE; } // always delete first, as there can be any kind of obsolete files //if(!not_added_anymore) { ptr_vector_append(&into->file_del, strdup(filename)); } } ptr_set_iterator iter; ptr_set_iterator_init(&step->file_add, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); char *filename = node->key; ptr_node *into_node = ptr_set_insert(&into->file_add, filename); if(into_node->value == NULL) { log_info("'%s' will be added", filename); // clone the data into_node->key = strdup(filename); into_node->value = bytearray_input_stream_clone((input_stream*)node->value); } else { log_warn("'%s' is a duplicate file add entry", filename); } } return SUCCESS; } /** * Queries the server for its current state (DNSKEY + RRSIG DNSKEY records) * * Appends found dns_resource_record* to the ptr_vector * * The ptr_vector is expected to be initialised and empty, or at the very least only filled with * dns_resource_record* * */ ya_result keyroll_dnskey_state_query(const keyroll_t *keyroll, ptr_vector *current_dnskey_rrsig_rr) { ya_result ret; message_data *mesg = message_new_instance(); message_make_query_ex(mesg, rand(), keyroll->domain, TYPE_DNSKEY, CLASS_IN, MESSAGE_EDNS0_DNSSEC); if(ISOK(ret = message_query_tcp_with_timeout(mesg, keyroll->server, KEYROLL_QUERY_TIMEOUT_S))) { // extract dnskey + rrsig if(message_isauthoritative(mesg)) { packet_unpack_reader_data purd; packet_reader_init_from_message(&purd, mesg); //u16 qc = message_get_query_count(mesg); u16 an = message_get_answer_count(mesg); u16 ns = message_get_authority_count(mesg); //u16 ar = message_get_additional_count(mesg); int total = an; total += ns; if(ISOK(ret = packet_reader_skip_query_section(&purd))) { for(int i = 0 ; i < total; ++i) { dns_resource_record *rr = dns_resource_record_new_instance(); if(FAIL(ret = packet_reader_read_dns_resource_record(&purd, rr))) { dns_resource_record_free(rr); break; } if((rr->tctr.qtype == TYPE_DNSKEY) || ((rr->tctr.qtype == TYPE_RRSIG) && (rrsig_get_type_covered_from_rdata(rr->rdata, rr->rdata_size) == TYPE_DNSKEY))) { ptr_vector_append(current_dnskey_rrsig_rr, rr); } } } if(ISOK(ret)) { ptr_vector_qsort(current_dnskey_rrsig_rr, keyroll_dns_resource_record_ptr_vector_qsort_callback); } } else { log_err("message_query_tcp_with_timeout(mesg, %{hostaddr}, %i) server is not authoritative", keyroll->server, KEYROLL_QUERY_TIMEOUT_S); // server is not authoritative ret = INVALID_STATE_ERROR; } } else { log_err("message_query_tcp_with_timeout(mesg, %{hostaddr}, %i) returned %r", keyroll->server, KEYROLL_QUERY_TIMEOUT_S, ret); } message_free(mesg); return ret; } /** * Releases the memory used by dns_resource_record* in the ptr_vector */ void keyroll_dnskey_state_destroy(ptr_vector *current_dnskey_rrsig_rr) { for(int i = 0; i <= ptr_vector_last_index(current_dnskey_rrsig_rr); ++i) { dns_resource_record *rr = (dns_resource_record*)ptr_vector_get(current_dnskey_rrsig_rr, i); dns_resource_record_free(rr); } ptr_vector_clear(current_dnskey_rrsig_rr); // ptr_vector_destroy(current_dnskey_rrsig_rr); } /** * Compares the expected state at a given step with the state on the server * (queried with keyroll_dnskey_state_query) * * Returns SUCCESS iff it's a match. */ ya_result keyroll_step_expects_matched(const keyroll_step_t *step, const ptr_vector *dnskey_rrsig_rr) { // ensure a perfect match between expected records and whatever is in dnskey_rrsig_rr // both ptr_vector are sorted if(ptr_vector_last_index(&step->expect) == ptr_vector_last_index(dnskey_rrsig_rr)) { for(int i = 0; i <= ptr_vector_last_index(dnskey_rrsig_rr); ++i) { dns_resource_record *ra = ptr_vector_get(&step->expect, i); dns_resource_record *rb = ptr_vector_get(dnskey_rrsig_rr, i); if(dns_resource_record_compare(ra, rb) != 0) { return KEYROLL_EXPECTED_IDENTICAL_RECORDS; } } return SUCCESS; } return KEYROLL_EXPECTED_IDENTICAL_SIZE_RRSETS; } /** * Compares the end-result state at a given step with the state on the server * (queried with keyroll_dnskey_state_query) * * Returns SUCCESS iff it's a match. */ ya_result keyroll_step_endresult_matched(const keyroll_step_t *step, const ptr_vector *dnskey_rrsig_rr) { // ensure a perfect match between end-result records and whatever is in dnskey_rrsig_rr // both ptr_vector are sorted if(ptr_vector_last_index(&step->endresult) == ptr_vector_last_index(dnskey_rrsig_rr)) { for(int i = 0; i <= ptr_vector_last_index(dnskey_rrsig_rr); ++i) { dns_resource_record *ra = ptr_vector_get(&step->endresult, i); dns_resource_record *rb = ptr_vector_get(dnskey_rrsig_rr, i); if(dns_resource_record_compare(ra, rb) != 0) { return KEYROLL_EXPECTED_IDENTICAL_RECORDS; } } return SUCCESS; } return KEYROLL_EXPECTED_IDENTICAL_SIZE_RRSETS; } /** * Plays a step on the server * * @param step the step to play * @param delete_all_dnskey delete all keys on the server. */ ya_result keyroll_step_play(const keyroll_step_t *step, bool delete_all_dnskey) { char path[PATH_MAX]; // delete the files for(int i = 0; i <= ptr_vector_last_index(&step->file_del); ++i) { const char *name = (char*)ptr_vector_get(&step->file_del, i); // delete the file from the right directory log_info("%{dnsname}: deleting file: '%s'", step->keyroll->domain, name); unlink_ex(step->keyroll->keys_path, name); } // copy the files ya_result ret; ptr_set_iterator iter; ptr_set_iterator_init(&step->file_add, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); const char *name = (char*)node->key; // copy the input stream in the right directory snformat(path, sizeof(path), "%s/%s", step->keyroll->keys_path, name); int n = strlen(name); bool is_private_key_file = (n > 8) && (memcmp(&name[n - 8], ".private", 8) == 0); log_info("%{dnsname}: creating file: '%s'", step->keyroll->domain, path); output_stream os; if(ISOK(ret = file_output_stream_create(&os, path, 0640))) { input_stream *is = (input_stream*)node->value; bytearray_input_stream_reset(is); if(is_private_key_file) { // read the file line by line // remove Publish and Delete lines for(;;) { ret = input_stream_read_line(is, path, sizeof(path)); if(ISOK(ret)) { if(ret == 0) { break; } if(memcmp(path, "Publish:", 8) == 0) { continue; } else if(memcmp(path, "Delete:", 7) == 0) { continue; } output_stream_write(&os, path, ret); } else { log_err("keyroll step failure reading bytes for: '%s'", path); break; } } } else { for(;;) { ret = input_stream_read(is, path, sizeof(path)); if(ISOK(ret)) { if(ret == 0) { break; } output_stream_write(&os, path, ret); } else { log_err("keyroll step failure reading bytes for: '%s'", path); break; } } } output_stream_close(&os); if(FAIL(ret)) { return ret; } } else { log_err("keyroll could not create file '%s'", path); return ret; } } if((ptr_vector_size(&step->dnskey_del) + ptr_vector_size(&step->dnskey_add) + ptr_vector_size(&step->rrsig_add)) == 0) { // nothing to do return SUCCESS; } // build an update packet // commit update packet // optionally check the server for an expected match message_data *mesg = message_new_instance(); message_data *answer = message_new_instance(); struct packet_writer pw; message_make_dnsupdate_init(mesg, rand(), step->keyroll->domain, CLASS_IN, 65535, &pw); if(delete_all_dnskey) { log_info("%{dnsname}: all previous DNSKEY will be removed", step->keyroll->domain); message_make_dnsupdate_delete_rrset(mesg, &pw, step->keyroll->domain, TYPE_DNSKEY); } for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_del); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_del, i); message_make_dnsupdate_delete_dnskey(mesg, &pw, key); } for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_add); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_add, i); message_make_dnsupdate_add_dnskey(mesg, &pw, key, DNSKEY_TTL_DEFAULT); } for(int i = 0; i <= ptr_vector_last_index(&step->rrsig_add); ++i) { dns_resource_record *rrsig = (dns_resource_record*)ptr_vector_get(&step->rrsig_add, i); message_make_dnsupdate_add_dns_resource_record(mesg, &pw, rrsig); } if(ISOK(ret = message_make_dnsupdate_finalize(mesg, &pw))) { // message has been properly built message_log(g_keyroll_logger, LOG_INFO, mesg); bool dnskey_rrsig_needed = (ptr_vector_last_index(&step->dnskey_del) >= 0) || (ptr_vector_last_index(&step->dnskey_add) >= 0); bool dnskey_rrsig_added = (ptr_vector_last_index(&step->rrsig_add) >= 0); if(dnskey_rrsig_needed && !dnskey_rrsig_added) { log_err("%s%{dnsname}: internal state error: no DNSKEY RRSIG added while the DNSKEY rrset is being modified", " ", step->keyroll->domain); dnscore_shutdown(); return INVALID_STATE_ERROR; } if(!keyroll_dryrun_mode) { ret = STOPPED_BY_APPLICATION_SHUTDOWN; int loops = 0; // only used to display a message once (tries most errors forever) u32 apply_verify_try_count = 0; while(!dnscore_shuttingdown()) { if(ISOK(ret = message_query_tcp_with_timeout_ex(mesg, step->keyroll->server, answer, KEYROLL_QUERY_TIMEOUT_S))) { log_info("%{dnsname}: sent message to %{hostaddr}", step->keyroll->domain, step->keyroll->server); if(message_get_status(answer) == FP_RCODE_NOERROR) { log_info("%{dnsname}: %{hostaddr} server replied it did the update", step->keyroll->domain, step->keyroll->server); // now let's check if the server said the truth ptr_vector current_dnskey_rrsig_rr; ptr_vector_init_ex(¤t_dnskey_rrsig_rr, 32); if(ISOK(ret = keyroll_dnskey_state_query(step->keyroll, ¤t_dnskey_rrsig_rr))) { // current_dnskey_rrsig_rr contains the records currently on the server ya_result matched_expectations = keyroll_step_endresult_matched(step, ¤t_dnskey_rrsig_rr); log_info("%{dnsname}: current step (%llU) should result in:", step->keyroll->domain, step->epochus); for(int i = 0; i <= ptr_vector_last_index(&step->endresult); ++i) { log_info("%{dnszrr}", ptr_vector_get(&step->endresult, i)); } log_info("%{dnsname}: server (%{hostaddr}) update resulted in:", step->keyroll->domain, step->keyroll->server); for(int i = 0; i <= ptr_vector_last_index(¤t_dnskey_rrsig_rr); ++i) { log_info("%{dnszrr}", ptr_vector_get(¤t_dnskey_rrsig_rr, i)); } if(ISOK(matched_expectations)) { log_info("%{dnsname}: update was applied successfully", step->keyroll->domain); } else { ++apply_verify_try_count; log_err("%{dnsname}: update was not applied successfully (try %i/%i)", step->keyroll->domain, apply_verify_try_count, step->keyroll->update_apply_verify_retries + 1); // 1 vs 1 => must do if(apply_verify_try_count <= step->keyroll->update_apply_verify_retries) { // ret = EAGAIN; // unused usleep_ex(ONE_SECOND_US * step->keyroll->update_apply_verify_retries_delay); continue; } else { log_err("%{dnsname}: update was not applied successfully, no retry left.", step->keyroll->domain); ret = KEYROLL_MUST_REINITIALIZE; } } } keyroll_dnskey_state_destroy(¤t_dnskey_rrsig_rr); break; } log_err("%{dnsname}: %{hostaddr} server replied with an error: %s", step->keyroll->domain, step->keyroll->server, dns_message_rcode_get_name(message_get_status(answer))); ret = MAKE_DNSMSG_ERROR(message_get_status(answer)); break; } if(!((ret == MAKE_ERRNO_ERROR(ETIMEDOUT)) || (ret == MAKE_ERRNO_ERROR(EAGAIN) || (ret == UNEXPECTED_EOF)))) { log_notice("%{dnsname}: sending message to %{hostaddr} failed: %r", step->keyroll->domain, step->keyroll->server, ret); break; } if(!dnscore_shuttingdown()) { log_warn("%{dnsname}: sending message to %{hostaddr} failed: %r (retrying in one second)", step->keyroll->domain, step->keyroll->server, ret); sleep(1); if(++loops == 1) // show the message exactly once { if(ret != UNABLE_TO_COMPLETE_FULL_READ) { message_log(MODULE_MSG_HANDLE, MSG_INFO, mesg); } } } ret = STOPPED_BY_APPLICATION_SHUTDOWN; } } else { log_warn("%{dnsname}: dryrun mode : no update has been sent", step->keyroll->domain); } } message_free(answer); message_free(mesg); return ret; } /** * Plays all the steps in a given epoch range. */ ya_result keyroll_step_play_range_ex(const keyroll_t *keyroll, s64 seek_from , s64 now, bool delete_all_dnskey, keyroll_step_t **first_stepp) { if(seek_from > now) { log_err("%{dnsname}: play range from the future to the past (%llU to %llU)", keyroll->domain, seek_from, now); return INVALID_ARGUMENT_ERROR; } ya_result ret; keyroll_step_t *first_step = keyroll_get_next_step_from(keyroll, seek_from); if(first_step == NULL) { log_info("%{dnsname}: play range has no first step", keyroll->domain); return INVALID_STATE_ERROR; } log_info("%{dnsname}: first step epoch is %llU", keyroll->domain, first_step->epochus); if(first_step->epochus > now) { if(first_stepp != NULL) { *first_stepp = first_step; } log_info("%{dnsname}: play range will not play %llU as its first step as it's after %llU", keyroll->domain, first_step->epochus, now); return SUCCESS; } log_info("%{dnsname}: play range from %llU", keyroll->domain, first_step->epochus); keyroll_step_t *merge = keyroll_step_new_instance(); // if a merge occurs, it's important to log it in case something goes wrong log_info("%{dnsname}: -------------------------------------------", keyroll->domain); log_info("%{dnsname}: merging step:", keyroll->domain); log_info("%{dnsname}: -------------------------------------------", keyroll->domain); keyroll_step_print(merge); log_info("%{dnsname}: -------------------------------------------", keyroll->domain); log_info("%{dnsname}: with step:", keyroll->domain); log_info("%{dnsname}: -------------------------------------------", keyroll->domain); keyroll_step_print(first_step); logger_flush(); keyroll_step_merge(merge, first_step); log_info("%{dnsname}: -------------------------------------------", keyroll->domain); log_info("%{dnsname}: resulting in:", keyroll->domain); log_info("%{dnsname}: -------------------------------------------", keyroll->domain); keyroll_step_print(merge); s64 tick = first_step->epochus; while(tick < now) { keyroll_step_t *next_step = keyroll_get_next_step_from(keyroll, tick + 1); if((next_step == NULL) || (next_step->epochus > now)) { break; } log_info("%{dnsname}: then with step:", keyroll->domain); log_info("%{dnsname}: -------------------------------------------", keyroll->domain); keyroll_step_print(next_step); // logger_flush(); keyroll_step_merge(merge, next_step); log_info("%{dnsname}: -------------------------------------------", keyroll->domain); log_info("%{dnsname}: resulting in:", keyroll->domain); log_info("%{dnsname}: -------------------------------------------", keyroll->domain); keyroll_step_print(merge); tick = next_step->epochus; } log_info("%{dnsname}: play range ends up with the step: ", keyroll->domain); log_info("%{dnsname}: -------------------------------------------", keyroll->domain); keyroll_step_print(merge); log_info("%{dnsname}: -------------------------------------------", keyroll->domain); logger_flush(); if(FAIL(ret = keyroll_step_play(merge, delete_all_dnskey))) { log_err("%{dnsname}: play range step execute failed: %r", keyroll->domain, ret); } if(first_stepp != NULL) { *first_stepp = merge; } return ret; } /** * Plays all the steps in a given epoch range. */ ya_result keyroll_step_play_range(const keyroll_t *keyroll, s64 seek_from , s64 now) { ya_result ret; ret = keyroll_step_play_range_ex(keyroll, seek_from, now, FALSE, NULL); return ret; } /** * Plays the first step of a plan if it's before a given epoch. * If the first step is in the future, it's not played. * Returns the first step in the parameter. * Returns an error code. */ ya_result keyroll_play_first_step(const keyroll_t *keyroll, s64 now, keyroll_step_t **first_stepp) { ya_result ret; ret = keyroll_step_play_range_ex(keyroll, 0 , now, TRUE, first_stepp); return ret; } /** * Scans the plan for the step matching the given state * * Returns the matching step or NULL */ keyroll_step_t* keyroll_step_scan_matching_expectations(const keyroll_t *keyroll, ptr_vector *current_dnskey_rrsig_rr) { s64 t = 0; for(;;) { keyroll_step_t *step = keyroll_get_next_step_from(keyroll, t); if(step == NULL) { return NULL; } ya_result ret = keyroll_step_expects_matched(step, current_dnskey_rrsig_rr); if(ret == SUCCESS) { return step; } t = step->epochus + 1; } } /** * Returns the step being active at the given epoch or NULL if there is no such step. * If a step starts at the given epoch, it's the one returned. */ keyroll_step_t* keyroll_get_current_step_at(const keyroll_t *keyroll, s64 epochus) { u64_node* node = u64_set_find_key_or_prev(&keyroll->steps, epochus); if(node != NULL) { return (keyroll_step_t*)node->value; } else { return NULL; } } /** * Returns the next step to be active from the given epoch or NULL if there is no such step. * If a step starts at the given epoch, it's the one returned. */ keyroll_step_t* keyroll_get_next_step_from(const keyroll_t *keyroll, s64 epochus) { u64_node* node = u64_set_find_key_or_next(&keyroll->steps, epochus); if(node != NULL) { return (keyroll_step_t*)node->value; } else { return NULL; } } /** * Generates a DNSKEY to be published at the given epoch. * The DNSKEY can be set as a KSK or ZSK using the ksk parameter. * This function creates steps at the various time fields of the key. */ ya_result keyroll_generate_dnskey(keyroll_t *keyroll, s64 publication_epochus, bool ksk) { dnssec_key *key = NULL; ya_result ret; const keyroll_key_parameters_t *kp = ksk?&keyroll->ksk_parameters:&keyroll->zsk_parameters; s64 *next_deactivationp = ksk?&keyroll->ksk_next_deactivation:&keyroll->zsk_next_deactivation; char name[MAX_DOMAIN_TEXT_LENGTH]; if(FAIL(ret = dnsname_to_cstr(name, keyroll->domain))) { return ret; } log_info("%{dnsname}: generating %cSK key to publish at %llU", keyroll->domain, ksk?'K':'Z', publication_epochus); if(ISOK(ret = dnskey_newinstance( kp->size, kp->algorithm, ksk?(DNSKEY_FLAG_ZONEKEY | DNSKEY_FLAG_KEYSIGNINGKEY):DNSKEY_FLAG_ZONEKEY, name, &key))) { log_info("%{dnsname}: generated %cSK key to publish at %llU", keyroll->domain, ksk?'K':'Z', publication_epochus); //u16 tag = dnskey_get_tag(key); keyroll_step_t* publication_step = keyroll_get_step(keyroll, publication_epochus); publication_step->keyroll_action |= /*KeyrollAction::*/Publish; ptr_vector_append(&publication_step->dnskey_add, key); dnskey_acquire(key); publication_step->dirty = TRUE; dnskey_set_publish_epoch(key, publication_epochus / ONE_SECOND_US); s64 activate_epochus = publication_epochus + ONE_SECOND_US * kp->activate_after; keyroll_step_t *activation_step = keyroll_get_step(keyroll, activate_epochus); activation_step->keyroll_action |= /*KeyrollAction::*/Activate; activation_step->dirty = TRUE; dnskey_set_activate_epoch(key, activate_epochus / ONE_SECOND_US); s64 deactivate_epochus = publication_epochus + ONE_SECOND_US * kp->deactivate_after; keyroll_step_t *deactivation_step = keyroll_get_step(keyroll, deactivate_epochus); deactivation_step->keyroll_action |= /*KeyrollAction::*/Deactivate; deactivation_step->dirty = TRUE; s64 unpublish_epochus = publication_epochus + ONE_SECOND_US * kp->delete_after; time_t deactivate_epoch_margin = keyroll_deactivation_margin(dnskey_get_activate_epoch(key), deactivate_epochus / ONE_SECOND_US, unpublish_epochus / ONE_SECOND_US); time_t deactivate_epoch = (deactivate_epochus/ ONE_SECOND_US) + deactivate_epoch_margin; dnskey_set_inactive_epoch(key, deactivate_epoch); if(*next_deactivationp < deactivation_step->epochus) { *next_deactivationp = deactivation_step->epochus; } keyroll_step_t *unpublication_step = keyroll_get_step(keyroll, unpublish_epochus); ptr_vector_append(&unpublication_step->dnskey_del, key); dnskey_acquire(key); unpublication_step->keyroll_action |= /*KeyrollAction::*/Unpublish; unpublication_step->dirty = TRUE; time_t unpublish_epoch = MAX(unpublish_epochus / ONE_SECOND_US, deactivate_epoch); dnskey_set_delete_epoch(key, unpublish_epoch); /* formatln("created key: tag=%i, algorithm=%i, flags=%i, create=%U publish=%U activate=%U deactivate=%U unpublish=%U", dnskey_get_tag(key), dnskey_get_algorithm(key), ntohs(dnskey_get_flags(key)), dnskey_get_created_epoch(key), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key)); */ dnskey_release(key); // the original reference if(keyroll->steps_count > KEYROLL_STEPS_MAX) { return BUFFER_WOULD_OVERFLOW; } } else { log_info("%{dnsname}: failed to generate %cSK key to publish at %llU: %r", keyroll->domain, ksk?'K':'Z', publication_epochus, ret); } return ret; } s64 keyroll_set_timing_steps(keyroll_t *keyroll, dnssec_key *key, bool dirty) { s64 publication_epochus = ONE_SECOND_US * dnskey_get_publish_epoch(key); keyroll_step_t* publication_step = keyroll_get_step(keyroll, publication_epochus); publication_step->keyroll_action |= /*KeyrollAction::*/Publish; ptr_vector_append(&publication_step->dnskey_add, key); dnskey_acquire(key); publication_step->dirty = dirty; dnskey_set_publish_epoch(key, publication_epochus / ONE_SECOND_US); s64 activate_epochus = ONE_SECOND_US * dnskey_get_activate_epoch(key); keyroll_step_t *activation_step = keyroll_get_step(keyroll, activate_epochus); activation_step->keyroll_action |= /*KeyrollAction::*/Activate; activation_step->dirty = dirty; dnskey_set_activate_epoch(key, activate_epochus / ONE_SECOND_US); s64 deactivate_epochus = ONE_SECOND_US * dnskey_get_inactive_epoch(key); keyroll_step_t *deactivation_step = keyroll_get_step(keyroll, deactivate_epochus); deactivation_step->keyroll_action |= /*KeyrollAction::*/Deactivate; deactivation_step->dirty = dirty; s64 unpublish_epochus = ONE_SECOND_US * dnskey_get_delete_epoch(key); time_t deactivate_epoch_margin = keyroll_deactivation_margin(dnskey_get_activate_epoch(key), deactivate_epochus / ONE_SECOND_US, unpublish_epochus / ONE_SECOND_US); time_t deactivation_epoch = (deactivate_epochus / ONE_SECOND_US) + deactivate_epoch_margin; dnskey_set_inactive_epoch(key, deactivation_epoch); keyroll_step_t *unpublication_step = keyroll_get_step(keyroll, unpublish_epochus); ptr_vector_append(&unpublication_step->dnskey_del, key); dnskey_acquire(key); unpublication_step->keyroll_action |= /*KeyrollAction::*/Unpublish; unpublication_step->dirty = dirty; time_t unpublish_epoch = MAX(unpublish_epochus / ONE_SECOND_US, deactivation_epoch); dnskey_set_delete_epoch(key, unpublish_epoch); return deactivate_epochus; } /** * Generates a DNSKEY to be published at the given epoch. * The DNSKEY can be set as a KSK or ZSK using the ksk parameter. * This functions requires the time fields to be set manually. * This function creates steps at the various time fields of the key. */ ya_result keyroll_generate_dnskey_ex(keyroll_t *keyroll, u32 size, u8 algorithm, s64 creation_epochus, s64 publication_epochus, s64 activate_epochus, s64 deactivate_epochus, s64 unpublish_epochus, bool ksk, dnssec_key **out_keyp) { dnssec_key *key = NULL; ya_result ret; if((keyroll == NULL) || (keyroll->domain == NULL)) { return INVALID_STATE_ERROR; } //formatln("%{dnsname}: generate %s key %llU %llU %llU %llU %llU", keyroll->domain, (ksk?"KSK":"ZSK"), creation_epochus, publication_epochus, activate_epochus, deactivate_epochus,unpublish_epochus); s64 *next_deactivationp = ksk?&keyroll->ksk_next_deactivation:&keyroll->zsk_next_deactivation; char name[MAX_DOMAIN_TEXT_LENGTH]; if(FAIL(ret = dnsname_to_cstr(name, keyroll->domain))) { return ret; } log_info("%{dnsname}: generating %cSK key to publish at %llU", keyroll->domain, ksk?'K':'Z', publication_epochus); while(!dnscore_shuttingdown()) // while there are tag collisions { if(ISOK(ret = dnskey_newinstance( size, algorithm, ksk?(DNSKEY_FLAG_ZONEKEY | DNSKEY_FLAG_KEYSIGNINGKEY):DNSKEY_FLAG_ZONEKEY, name, &key))) { dnssec_key *previous_key_with_same_tag = dnssec_keystore_acquire_key_from_fqdn_with_tag(dnskey_get_domain(key), dnskey_get_tag(key)); if(previous_key_with_same_tag != NULL) { log_notice("%{dnsname}: a tag collision happened creating a %cSK key. Discarding and trying again.", keyroll->domain, ksk?'K':'Z'); dnskey_release(previous_key_with_same_tag); dnskey_release(key); ret = DNSSEC_ERROR_DUPLICATEKEY; // actually the tag is a duplicate ... continue; } log_info("%{dnsname}: generated %cSK key to publish at %llU", keyroll->domain, ksk?'K':'Z', publication_epochus); //u16 tag = dnskey_get_tag(key); dnskey_set_created_epoch(key, creation_epochus / ONE_SECOND_US); keyroll_step_t* publication_step = keyroll_get_step(keyroll, publication_epochus); publication_step->keyroll_action |= /*KeyrollAction::*/Publish; ptr_vector_append(&publication_step->dnskey_add, key); dnskey_acquire(key); publication_step->dirty = TRUE; dnskey_set_publish_epoch(key, publication_epochus / ONE_SECOND_US); keyroll_step_t *activation_step = keyroll_get_step(keyroll, activate_epochus); activation_step->keyroll_action |= /*KeyrollAction::*/Activate; activation_step->dirty = TRUE; dnskey_set_activate_epoch(key, activate_epochus / ONE_SECOND_US); time_t deactivate_epoch_margin = keyroll_deactivation_margin(dnskey_get_activate_epoch(key), deactivate_epochus / ONE_SECOND_US, unpublish_epochus / ONE_SECOND_US); time_t deactivate_epoch = (deactivate_epochus / ONE_SECOND_US) + deactivate_epoch_margin; keyroll_step_t *deactivation_step = keyroll_get_step(keyroll, deactivate_epoch * ONE_SECOND_US); deactivation_step->keyroll_action |= /*KeyrollAction::*/Deactivate; deactivation_step->dirty = TRUE; dnskey_set_inactive_epoch(key, deactivate_epoch); if(*next_deactivationp < deactivate_epochus) { *next_deactivationp = deactivate_epochus; } keyroll_step_t *unpublication_step = keyroll_get_step(keyroll, unpublish_epochus); ptr_vector_append(&unpublication_step->dnskey_del, key); dnskey_acquire(key); unpublication_step->keyroll_action |= /*KeyrollAction::*/Unpublish; unpublication_step->dirty = TRUE; time_t unpublish_epoch = MAX(unpublish_epochus / ONE_SECOND_US, deactivate_epoch); dnskey_set_delete_epoch(key, unpublish_epoch); dnssec_keystore_add_key(key); #if DEBUG log_debug("created key: domain=%{dnsname}, tag=%i, algorithm=%i, flags=%i, create=%U publish=%U activate=%U deactivate=%U unpublish=%U", dnskey_get_domain(key), dnskey_get_tag(key), dnskey_get_algorithm(key), ntohs(dnskey_get_flags(key)), dnskey_get_created_epoch(key), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key)); logger_flush(); #endif dnskey_release(key); // the original reference } else { // note: %llU => prints UTC time log_err("%{dnsname}: failed to generate %cSK key to publish at %llU: %r", keyroll->domain, ksk?'K':'Z', publication_epochus, ret); } break; } // while(!dnscore_isshuttingdown()) if(dnscore_shuttingdown()) { ret = STOPPED_BY_APPLICATION_SHUTDOWN; if(key != NULL) { dnskey_release(key); } } else if(ISOK(ret) && (out_keyp != NULL)) { dnskey_acquire(key); *out_keyp = key; } return ret; } /** * Generates a plan using a DNSSEC policy. */ ya_result keyroll_plan_with_policy(keyroll_t *keyroll, s64 generate_from, s64 generate_until, const char* policy_name) { dnssec_policy *policy = dnssec_policy_acquire_from_name(policy_name); if(policy == NULL) { log_err("couldn't load '%s' policy", policy_name); return INVALID_ARGUMENT_ERROR; } ya_result ret; ret = dnssec_policy_process(keyroll, policy, generate_from, generate_until); // dnssec_policy_date_init_from_epoch return ret; } static u32 keyroll_key_hash(dnssec_key *key) { u32 key_hash = dnskey_get_flags(key); key_hash <<= 5; key_hash |= dnskey_get_algorithm(key); key_hash <<= 16; key_hash |= dnskey_get_tag(key); return key_hash; } static void keyroll_print_u32_set_destroy_callback(u32_node *node) { dnssec_key *key = (dnssec_key*)node->value; dnskey_release(key); } void keyroll_step_print(keyroll_step_t *step) { log_info("================================"); log_info("At %llU = %llu", step->epochus, step->epochus); log_info("================================"); log_info("- update -----------------------"); for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_del); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_del, i); log_info("del record K%{dnsname}+%03u+%05d %-5i bits %cSK %U => %U => %U => %U", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), dnskey_get_size(key), ((dnskey_get_flags(key)&DNSKEY_FLAG_KEYSIGNINGKEY)!=0)?'K':'Z', dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key)); } for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_add); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_add, i); log_info("add record K%{dnsname}+%03u+%05d %-5i bits %cSK %U => %U => %U => %U", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), dnskey_get_size(key), ((dnskey_get_flags(key)&DNSKEY_FLAG_KEYSIGNINGKEY)!=0)?'K':'Z', dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key)); } for(int i = 0; i <= ptr_vector_last_index(&step->rrsig_add); ++i) { dns_resource_record *rr = (dns_resource_record*)ptr_vector_get(&step->rrsig_add, i); log_info("add record %{dnsrr}", rr); } for(int i = 0; i <= ptr_vector_last_index(&step->expect); ++i) { dns_resource_record *rr = (dns_resource_record*)ptr_vector_get(&step->expect, i); log_info("expects record %{dnsrr}", rr); } for(int i = 0; i <= ptr_vector_last_index(&step->file_del); ++i) { char *filename = (char*)ptr_vector_get(&step->file_del, i); log_info("delete file '%s'", filename); } ptr_set_iterator iter; ptr_set_iterator_init(&step->file_add, &iter); while(ptr_set_iterator_hasnext(&iter)) { ptr_node *node = ptr_set_iterator_next_node(&iter); char *filename = (char*)node->key; log_info("create file '%s'", filename); } } #define log_print_info(...) log_info(__VA_ARGS__);formatln(__VA_ARGS__) #define log_print_warn(...) log_warn(__VA_ARGS__);formatln("WARNING: " __VA_ARGS__) /** * Prints a plan. */ ya_result keyroll_print(keyroll_t *keyroll, output_stream *os) { ya_result ret = SUCCESS; u32_set current; u32_set_init(¤t); s64 ksk_next_deactivation = 0; s64 zsk_next_deactivation = 0; u64_set_iterator iter; u64_set_iterator_init(&keyroll->steps, &iter); if(!u64_set_iterator_hasnext(&iter)) { osprintln(os, "*** ERROR *** No steps have been loaded"); return INVALID_STATE_ERROR; } while(u64_set_iterator_hasnext(&iter)) { u64_node *step_node = u64_set_iterator_next_node(&iter); keyroll_step_t *step = (keyroll_step_t*)step_node->value; if(step == NULL) { osformatln(os, "*** ERROR *** Empty step at %llU", step_node->key); continue; } osprintln(os, "================================================================================"); osformatln(os, "At %llU (epoch %llu)", step->epochus, step->epochus); osprintln(os, "================================================================================"); time_t now = (time_t)(step->epochus / ONE_SECOND_US); osprintln(os, "DNS updates:"); osprintln(os, "------------"); for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_del); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_del, i); formatln("del K%{dnsname}+%03u+%05d %-5i bits %cSK publish at %U, activate at %U, deactivate at %U, unpublish at %U", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), dnskey_get_size(key), ((dnskey_get_flags(key)&DNSKEY_FLAG_KEYSIGNINGKEY)!=0)?'K':'Z', dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key)); u32 key_hash = keyroll_key_hash(key); u32_node *node = u32_set_find(¤t, key_hash); if(node != NULL) { dnssec_key *node_key = (dnssec_key*)node->value; dnskey_release(node_key); u32_set_delete(¤t, key_hash); } else { osprintln(os, "*** WARNING *** Key isn't in the current set"); } } for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_add); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_add, i); osformatln(os, "add K%{dnsname}+%03u+%05d %-5i bits %cSK publish at %U, activate at %U, deactivate at %U, unpublish at %U", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), dnskey_get_size(key), ((dnskey_get_flags(key)&DNSKEY_FLAG_KEYSIGNINGKEY)!=0)?'K':'Z', dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key)); u32 key_hash = keyroll_key_hash(key); u32_node *node = u32_set_find(¤t, key_hash); if(node == NULL) { node = u32_set_insert(¤t, key_hash); node->value = key; dnskey_acquire(key); } else { osprintln(os, "*** WARNING *** Key is in the current set already"); } } osprintln(os, "DNS state:"); osprintln(os, "----------"); { bool has_active_ksk = FALSE; bool has_active_zsk = FALSE; u32_set_iterator iter; u32_set_iterator_init(¤t, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); dnssec_key *key = (dnssec_key*)node->value; bool published = dnskey_is_published(key, now); bool activated = dnskey_is_activated(key, now); bool deactivated = dnskey_is_deactivated(key, now); bool unpublished = dnskey_is_unpublished(key, now); if((dnskey_get_flags(key) & DNSKEY_FLAG_KEYSIGNINGKEY) != 0) { has_active_ksk |= activated; ksk_next_deactivation = ONE_SECOND_US * dnskey_get_inactive_epoch(key); } else { has_active_zsk |= activated; zsk_next_deactivation = ONE_SECOND_US * dnskey_get_inactive_epoch(key); } osformatln(os, "=== K%{dnsname}+%03u+%05d %cSK %c %c %c %c", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ((dnskey_get_flags(key)&DNSKEY_FLAG_KEYSIGNINGKEY)!=0)?'K':'Z', (published?'P':'-'), (activated?'A':'-'), (deactivated?'D':'-'), (unpublished?'U':'-') // this one should not appear ); } for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_del); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_del, i); osformatln(os, "=== K%{dnsname}+%03u+%05d %cSK - - D U", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key), ((dnskey_get_flags(key)&DNSKEY_FLAG_KEYSIGNINGKEY)!=0)?'K':'Z'); } } flushout(); } if((ksk_next_deactivation > 0) || (zsk_next_deactivation > 0)) { osprintln(os, "- wrapping up ------------------"); if(ksk_next_deactivation > 0) { osformatln(os, "Next KSK will need to be active way before %llU", ksk_next_deactivation); } if(zsk_next_deactivation > 0) { osformatln(os, "Next ZSK will need to be active way before %llU", zsk_next_deactivation); } } u32_set_callback_and_destroy(¤t, keyroll_print_u32_set_destroy_callback); return ret; } /** * Prints a plan. */ ya_result keyroll_print_json(keyroll_t *keyroll, output_stream *os) { ya_result ret = SUCCESS; if((keyroll == NULL) || (os == NULL)) { return UNEXPECTED_NULL_ARGUMENT_ERROR; } u32_set current; u32_set_init(¤t); s64 ksk_next_deactivation = 0; s64 zsk_next_deactivation = 0; u64_set_iterator iter; u64_set_iterator_init(&keyroll->steps, &iter); if(!u64_set_iterator_hasnext(&iter)) { return INVALID_STATE_ERROR; } osformatln(os, "{\"domain\": \"%{dnsname}\", \"steps\": [", keyroll->domain); const char *step_separator = ""; while(u64_set_iterator_hasnext(&iter)) { u64_node *step_node = u64_set_iterator_next_node(&iter); keyroll_step_t *step = (keyroll_step_t*)step_node->value; osformat(os, step_separator); step_separator = ", "; if(step == NULL) { log_print_info("*** ERROR *** EMPTY STEP AT %llU", step_node->key); osformat(os, "{\"time\": \"%llU\", \"epoch\": %llu}\n", step_node->key, step_node->key); continue; } time_t now = (time_t)(step->epochus / ONE_SECOND_US); osformat(os, "{\"time\": \"%llU\", \"epochUs\": %llu, \"updates\": [", step_node->key, step_node->key); const char *update_separator = ""; for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_del); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_del, i); osformat(os, "%s{\"operation\": \"delete\", \"algorithm\": %u, \"tag\": %u, \"size\": %u, \"flags\": \"%cZK\", " "\"publish\": \"%lU\", " "\"activate\": \"%lU\", " "\"deactivate\": \"%lU\", " "\"unpublish\": \"%lU\", " "\"publishEpoch\": \"%llu\", " "\"activateEpoch\": \"%llu\", " "\"deactivateEpoch\": \"%llu\", " "\"unpublishEpoch\": \"%llu\"" "}\n", update_separator, dnskey_get_algorithm(key), dnskey_get_tag(key), dnskey_get_size(key), ((dnskey_get_flags(key)&DNSKEY_FLAG_KEYSIGNINGKEY)!=0)?'K':'Z', time_to_timeus(dnskey_get_publish_epoch(key)), time_to_timeus(dnskey_get_activate_epoch(key)), time_to_timeus(dnskey_get_inactive_epoch(key)), time_to_timeus(dnskey_get_delete_epoch(key)), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key)); update_separator = ", "; u32 key_hash = keyroll_key_hash(key); u32_node *node = u32_set_find(¤t, key_hash); if(node != NULL) { dnssec_key *node_key = (dnssec_key*)node->value; dnskey_release(node_key); u32_set_delete(¤t, key_hash); } else { // log_print_warn("key isn't in the current set"); } } for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_add); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_add, i); osformat(os, "%s{\"operation\": \"add\", \"algorithm\": %u, \"tag\": %u, \"size\": %u, \"flags\": \"%cZK\", " "\"publish\": \"%lU\", " "\"activate\": \"%lU\", " "\"deactivate\": \"%lU\", " "\"unpublish\": \"%lU\", " "\"publishEpoch\": \"%llu\", " "\"activateEpoch\": \"%llu\", " "\"deactivateEpoch\": \"%llu\", " "\"unpublishEpoch\": \"%llu\"" "}\n", update_separator, dnskey_get_algorithm(key), dnskey_get_tag(key), dnskey_get_size(key), ((dnskey_get_flags(key)&DNSKEY_FLAG_KEYSIGNINGKEY)!=0)?'K':'Z', time_to_timeus(dnskey_get_publish_epoch(key)), time_to_timeus(dnskey_get_activate_epoch(key)), time_to_timeus(dnskey_get_inactive_epoch(key)), time_to_timeus(dnskey_get_delete_epoch(key)), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key)); update_separator = ", "; u32 key_hash = keyroll_key_hash(key); u32_node *node = u32_set_find(¤t, key_hash); if(node == NULL) { node = u32_set_insert(¤t, key_hash); node->value = key; dnskey_acquire(key); } else { //log_print_warn("key is in the current set already"); } } osformat(os, "], \"keyState\": ["); const char *keystate_separator = ""; { bool has_active_ksk = FALSE; bool has_active_zsk = FALSE; u32_set_iterator iter; u32_set_iterator_init(¤t, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); dnssec_key *key = (dnssec_key*)node->value; bool published = dnskey_is_published(key, now); bool activated = dnskey_is_activated(key, now); bool deactivated = dnskey_is_deactivated(key, now); bool unpublished = dnskey_is_unpublished(key, now); if((dnskey_get_flags(key) & DNSKEY_FLAG_KEYSIGNINGKEY) != 0) { has_active_ksk |= activated; ksk_next_deactivation = ONE_SECOND_US * dnskey_get_inactive_epoch(key); } else { has_active_zsk |= activated; zsk_next_deactivation = ONE_SECOND_US * dnskey_get_inactive_epoch(key); } osformat(os, "%s{\"algorithm\": %u, \"tag\": %u, \"flags\": \"%cSK\", \"published\": %s, \"activated\": %s, \"deactivated\": %s, \"unpublished\": %s}\n", keystate_separator, dnskey_get_algorithm(key), dnskey_get_tag(key), ((dnskey_get_flags(key)&DNSKEY_FLAG_KEYSIGNINGKEY)!=0)?'K':'Z', (published?"true":"false"), (activated?"true":"false"), (deactivated?"true":"false"), (unpublished?"true":"false") ); keystate_separator = ", "; } for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_del); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_del, i); osformat(os, "%s{\"algorithm\": %u, \"tag\": %u, \"flags\": \"%cSK\", \"published\": false, \"activated\": false, \"deactivated\": true, \"unpublished\": true}\n", keystate_separator, dnskey_get_algorithm(key), dnskey_get_tag(key), ((dnskey_get_flags(key)&DNSKEY_FLAG_KEYSIGNINGKEY)!=0)?'K':'Z' ); keystate_separator = ", "; } } osformat(os,"]}"); } osformat(os,"], \"followUp\": {\"nextKeySigningKeyActivationRequiredAt\": \"%llU\", \"nextZoneSigningKeyActivationRequiredAt\": \"%llU\"}", ksk_next_deactivation, zsk_next_deactivation ); osformatln(os, "}\n"); u32_set_callback_and_destroy(¤t, keyroll_print_u32_set_destroy_callback); return ret; } /** * Stores the plan on disk (several files, private KSK files, ...) */ ya_result keyroll_store(keyroll_t *keyroll) { ya_result ret = SUCCESS; u32_set current; u32_set_init(¤t); ptr_vector expected_rrsig; ptr_vector_init_ex(&expected_rrsig, 16); output_stream baos; output_stream previous_end_result_os; char file_path[PATH_MAX]; u8 *rdata = (u8*)file_path; // both buffers can coexist bytearray_output_stream_init(&baos, NULL, 8192); bytearray_output_stream_init(&previous_end_result_os, NULL, 8192); u64_set_iterator iter; u64_set_iterator_init(&keyroll->steps, &iter); while(u64_set_iterator_hasnext(&iter)) { u64_node *node = u64_set_iterator_next_node(&iter); keyroll_step_t *step = (keyroll_step_t*)node->value; if(step == NULL) { continue; } if(!step->dirty) { continue; } // look for the next signature update s32 next_signature_update_epoch = MAX_S32; for(keyroll_step_t *next_step = step; ;) { next_step = keyroll_get_next_step_from(keyroll, next_step->epochus + 1); if(next_step == NULL) { break; } if((ptr_vector_size(&next_step->dnskey_add) + ptr_vector_size(&next_step->dnskey_del)) > 0) { next_signature_update_epoch = (next_step->epochus / ONE_SECOND_US); next_signature_update_epoch = (s32)MIN((s64)next_signature_update_epoch + NEXT_SIGNATURE_EPOCH_MARGIN, (s64)MAX_S32); break; } } bool has_zsk = FALSE; bool has_ksk = FALSE; for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_add); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_add, i); has_ksk |= (dnskey_get_flags(key) == DNSKEY_FLAGS_KSK); has_zsk |= (dnskey_get_flags(key) == DNSKEY_FLAGS_ZSK); } snformat(file_path, sizeof(file_path) - 16, "%s/%llU_%016lli_%{dnsname}", keyroll->plan_path, node->key, node->key, keyroll->domain); for(int i = 0; file_path[i] != '\0'; ++i) { if(file_path[i] == ' ') { file_path[i] = '-'; } } log_info("storing '%s'", file_path); output_stream fos; ret = file_output_stream_create(&fos, file_path, 0644); if(FAIL(ret)) { log_info("failed to create '%s': %r", file_path, ret); return ret; } buffer_output_stream_init(&fos, &fos, 4096); osformatln(&fos, "epochus %llu", step->epochus); osformatln(&fos, "dateus %llU", step->epochus); osprintln(&fos, "version " YKEYROLL_VERSION); osprint(&fos, "actions"); if(step->keyroll_action != 0) { if(step->keyroll_action & Publish) // add commands { osprint(&fos, " publish"); } if(step->keyroll_action & Activate) { osprint(&fos, " activate"); } if(step->keyroll_action & Deactivate) { osprint(&fos, " deactivate"); } if(step->keyroll_action & Unpublish) // delete commands { osprint(&fos, " unpublish"); } } else { osprint(&fos, " none"); } osprintln(&fos, ""); { u8 *previous_end_result_text = bytearray_output_stream_buffer(&previous_end_result_os); u32 previous_end_result_size = bytearray_output_stream_size(&previous_end_result_os); output_stream_write(&fos, previous_end_result_text, previous_end_result_size); bytearray_output_stream_reset(&previous_end_result_os); } for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_del); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_del, i); if(dnskey_get_flags(key) == DNSKEY_FLAGS_ZSK) { osformat(&fos, "del K%{dnsname}+%03u+%05d.key ", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key)); bytearray_output_stream_reset(&baos); dnskey_store_public_key_to_stream(key, &baos); osprint_base64(&fos, bytearray_output_stream_buffer(&baos), bytearray_output_stream_size(&baos)); osprintln(&fos, ""); #define NOTHING_TO_SEE_HERE_BASE64 "IyBub3RoaW5nIHRvIHNlZSBoZXJlCg==" osformatln(&fos, "del K%{dnsname}+%03u+%05d.private " NOTHING_TO_SEE_HERE_BASE64, dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key)); } else { // the file is not supposed to be transferred : there is nothing to delete } } for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_add); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_add, i); if(dnskey_get_flags(key) == DNSKEY_FLAGS_ZSK) { osformat(&fos, "add K%{dnsname}+%03u+%05d.key ", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key)); bytearray_output_stream_reset(&baos); dnskey_store_public_key_to_stream(key, &baos); osprint_base64(&fos, bytearray_output_stream_buffer(&baos), bytearray_output_stream_size(&baos)); osprintln(&fos, ""); osformat(&fos, "add K%{dnsname}+%03u+%05d.private ", dnskey_get_domain(key), dnskey_get_algorithm(key), dnskey_get_tag(key)); bytearray_output_stream_reset(&baos); dnskey_store_private_key_to_stream(key, &baos); osprint_base64(&fos, bytearray_output_stream_buffer(&baos), bytearray_output_stream_size(&baos)); osprintln(&fos, ""); osformatln(&fos, "debug tag=%i flags=%s created=%U publish=%U activate=%U deactivate=%U unpublish=%U", dnskey_get_tag(key), ((dnskey_get_flags(key) == DNSKEY_FLAGS_KSK)?"KSK":"ZSK"), dnskey_get_created_epoch(key), dnskey_get_publish_epoch(key), dnskey_get_activate_epoch(key), dnskey_get_inactive_epoch(key), dnskey_get_delete_epoch(key)); } else { // store the private key separately dnssec_keystore_add_domain(keyroll->domain, keyroll->private_keys_path); if(FAIL(ret = dnssec_keystore_store_private_key(key))) { log_err("could not store private key-signing key"); return ret; } if(FAIL(ret = dnssec_keystore_store_public_key(key))) { log_err("could not store public key-signing key"); return ret; } } } bool has_changes = (ptr_vector_size(&step->dnskey_del) + ptr_vector_size(&step->dnskey_add)) > 0; if(has_changes) { // signatures will be cleared as soon as this happens (change(s) in the DNSKEY rrset) /* // now the rrsig is held by the step for(int i = 0; i <= ptr_vector_last_index(&expected_rrsig); ++i) { dns_resource_record *rrsig = (dns_resource_record*)ptr_vector_get(&expected_rrsig, i); dns_resource_record_finalize(rrsig); } */ ptr_vector_clear(&expected_rrsig); // the DNSKEY records to delete for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_del); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_del, i); int rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, PATH_MAX); rdata_desc dnskeyrdata = {TYPE_DNSKEY, rdata_size, rdata}; osformatln(&fos, "update delete %{dnsname} %i %{typerdatadesc}", keyroll->domain, TTL, &dnskeyrdata); u32 key_hash = keyroll_key_hash(key); u32_node *node = u32_set_find(¤t, key_hash); if(node != NULL) { dnssec_key *node_key = (dnssec_key*)node->value; dnskey_release(node_key); u32_set_delete(¤t, key_hash); } } // the DNSKEY records to add for(int i = 0; i <= ptr_vector_last_index(&step->dnskey_add); ++i) { dnssec_key *key = (dnssec_key*)ptr_vector_get(&step->dnskey_add, i); int rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, PATH_MAX); rdata_desc dnskeyrdata = {TYPE_DNSKEY, rdata_size, rdata}; osformatln(&fos, "update add %{dnsname} %i %{typerdatadesc}", keyroll->domain, TTL, &dnskeyrdata); u32 key_hash = keyroll_key_hash(key); u32_node *node = u32_set_find(¤t, key_hash); if(node == NULL) { node = u32_set_insert(¤t, key_hash); node->value = key; dnskey_acquire(key); } } // the RRSIG records to add { struct resource_record_view rrv; dnskey_signature ds; // the signature should cover the earliest key deletion // the signature should cover the earliest ksk deactivation dns_resource_record *rrsig; // build the set of records ptr_vector rrset; ptr_vector_init(&rrset); u32_set_iterator iter; u32_set_iterator_init(¤t, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); dnssec_key *key = (dnssec_key*)node->value; int rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, PATH_MAX); rdata_desc dnskeyrdata = {TYPE_DNSKEY, rdata_size, rdata}; osformatln(&fos, "endresult %{dnsname} %i %{typerdatadesc}", keyroll->domain, TTL, &dnskeyrdata); osformatln(&previous_end_result_os, "expect %{dnsname} %i %{typerdatadesc}", keyroll->domain, TTL, &dnskeyrdata); dns_resource_record *rr = dns_resource_record_new_instance(); dnskey_init_dns_resource_record(key, TTL, rr); ptr_vector_append(&rrset, rr); } // for all active KSK, generate a signature u32_set_iterator_init(¤t, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); dnssec_key *key = (dnssec_key*)node->value; if(dnskey_get_flags(key) == DNSKEY_FLAGS_KSK) { dns_resource_record_resource_record_view_init(&rrv); dnskey_signature_init(&ds); s32 from = (step->epochus / ONE_SECOND_US) - RRSIG_ANTEDATING; // sign from the day before log_debug("%{dnsname}: %llT signing DNSKEY RRSET with key %hu, inactive at %T (%T)", keyroll->domain, step->epochus, dnskey_get_tag(key), dnskey_get_inactive_epoch(key), next_signature_update_epoch); if(dnskey_get_inactive_epoch(key) > next_signature_update_epoch) { log_debug("%{dnsname}: %llT key %hu is inactive at %T which is after the planned expiration time %T", keyroll->domain, step->epochus, dnskey_get_tag(key), dnskey_get_inactive_epoch(key), next_signature_update_epoch); } s32 to = MAX(dnskey_get_inactive_epoch(key), next_signature_update_epoch); log_info("signing from %U to %U", from, to); dnskey_signature_set_view(&ds, &rrv); dnskey_signature_set_validity(&ds, from, to); dnskey_signature_set_rrset_reference(&ds, &rrset); ret = dnskey_signature_sign(&ds, key, (void**)&rrsig); dnskey_signature_finalize(&ds); if(FAIL(ret)) { log_info("signature failed: %r", ret); return ret; } osformatln(&fos, "update add %{dnszrr}", rrsig); ptr_vector_append(&step->rrsig_add, rrsig); ptr_vector_append(&expected_rrsig, rrsig); } } for(int i = 0; i <= ptr_vector_last_index(&rrset); ++i) { dns_resource_record *rr = (dns_resource_record*)ptr_vector_get(&rrset, i); dns_resource_record_free(rr); } ptr_vector_destroy(&rrset); } // current set sub-block } // has changes else { u32_set_iterator iter; u32_set_iterator_init(¤t, &iter); while(u32_set_iterator_hasnext(&iter)) { u32_node *node = u32_set_iterator_next_node(&iter); dnssec_key *key = (dnssec_key*)node->value; int rdata_size = key->vtbl->dnssec_key_writerdata(key, rdata, PATH_MAX); rdata_desc dnskeyrdata = {TYPE_DNSKEY, rdata_size, rdata}; osformatln(&fos, "endresult %{dnsname} %i %{typerdatadesc}", keyroll->domain, TTL, &dnskeyrdata); osformatln(&previous_end_result_os, "expect %{dnsname} %i %{typerdatadesc}", keyroll->domain, TTL, &dnskeyrdata); } } for(int i = 0; i <= ptr_vector_last_index(&expected_rrsig); ++i) { dns_resource_record *rrsig = (dns_resource_record*)ptr_vector_get(&expected_rrsig, i); osformatln(&fos, "endresult %{dnszrr}", rrsig); osformatln(&previous_end_result_os, "expect %{dnszrr}", rrsig); } output_stream_close(&fos); flushout(); } /* // now the rrsig is held by the step for(int i = 0; i <= ptr_vector_last_index(&expected_rrsig); ++i) { dns_resource_record *rrsig = (dns_resource_record*)ptr_vector_get(&expected_rrsig, i); dns_resource_record_finalize(rrsig); } */ ptr_vector_destroy(&expected_rrsig); u32_set_callback_and_destroy(¤t, keyroll_print_u32_set_destroy_callback); return ret; } /** * */ ya_result keyroll_get_state_find_match_and_play(const keyroll_t *keyrollp, s64 now, const keyroll_step_t *current_step, const keyroll_step_t **matched_stepp) { // check the expected set with the server // do a query for all DNSKEY + RRSIG and compare with the step ya_result ret = STOPPED_BY_APPLICATION_SHUTDOWN; u32 match_verify_try_count = 0; ptr_vector current_dnskey_rrsig_rr; ptr_vector_init_ex(¤t_dnskey_rrsig_rr, 32); while(!dnscore_shuttingdown() && ISOK(ret = keyroll_dnskey_state_query(keyrollp, ¤t_dnskey_rrsig_rr))) { // current_dnskey_rrsig_rr contains the records currently on the server ya_result matched_expectations = keyroll_step_expects_matched(current_step, ¤t_dnskey_rrsig_rr); log_info("current step (%llU) expects to start from:", current_step->epochus); for(int i = 0; i <= ptr_vector_last_index(¤t_step->expect); ++i) { log_info("%{dnszrr}", ptr_vector_get(¤t_step->expect, i)); } log_info("server (%{hostaddr}) has:", keyrollp->server); for(int i = 0; i <= ptr_vector_last_index(¤t_dnskey_rrsig_rr); ++i) { log_info("%{dnszrr}", ptr_vector_get(¤t_dnskey_rrsig_rr, i)); } if(ISOK(matched_expectations)) { log_debug("zone %{dnsname}: expectations are matched", current_step->keyroll->domain); keyroll_dnskey_state_destroy(¤t_dnskey_rrsig_rr); // leads to an exit ret = keyroll_step_play(current_step, FALSE); if(matched_stepp != NULL) { *matched_stepp = current_step; } return ret; } else { log_notice("zone %{dnsname} expectations are NOT matched", current_step->keyroll->domain); bool nameserver_has_no_dnskey = (ptr_vector_last_index(¤t_dnskey_rrsig_rr) < 0); if(nameserver_has_no_dnskey) { keyroll_dnskey_state_destroy(¤t_dnskey_rrsig_rr); // leads to an exit // there are no keys on the server (and implicitely, some were expected) // so we start playing from the start until now keyroll_step_t *first_step; if(FAIL(ret = keyroll_play_first_step(keyrollp, now, &first_step))) { return ret; } // now play all the steps until the one we are supposed to be currently in ret = keyroll_step_play_range(keyrollp, first_step->epochus + 1 , now); log_info("zone %{dnsname}: done replaying steps: %r", current_step->keyroll->domain, ret); return ret; } else { log_info("zone %{dnsname}: scanning for a match", current_step->keyroll->domain); keyroll_step_t* step = keyroll_step_scan_matching_expectations(keyrollp, ¤t_dnskey_rrsig_rr); keyroll_dnskey_state_destroy(¤t_dnskey_rrsig_rr); // leads to an exit or loops if(step == NULL) { log_info("zone %{dnsname}: no match found, looking for first step after %llU", current_step->keyroll->domain, now); keyroll_step_t *first_step; if(FAIL(ret = keyroll_play_first_step(keyrollp, now, &first_step))) { if(ret == MAKE_ERRNO_ERROR(EPERM)) { log_err("zone %{dnsname}: failed to find step: %r (%i:%i)", current_step->keyroll->domain, ret, getuid(), getgid()); } else { log_err("zone %{dnsname}: failed to play step: %r", current_step->keyroll->domain, ret); } ++match_verify_try_count; if(ret == MAKE_DNSMSG_ERROR(RCODE_SERVFAIL)) { log_err("%{dnsname}: server cannot apply the update at the moment (try %i/%i)", current_step->keyroll->domain, match_verify_try_count, current_step->keyroll->match_verify_retries); } else { log_err("%{dnsname}: could not find a match (try %i/%i)", current_step->keyroll->domain, match_verify_try_count, current_step->keyroll->match_verify_retries); } // 1 vs 1 => must do if(match_verify_try_count <= current_step->keyroll->match_verify_retries) { if(!dnscore_shuttingdown()) { usleep_ex(ONE_SECOND_US * current_step->keyroll->match_verify_retries_delay); } ptr_vector_init_ex(¤t_dnskey_rrsig_rr, 32); // because the array was destroyed ret = STOPPED_BY_APPLICATION_SHUTDOWN; continue; } else { return ret; } } step = first_step; } else { log_info("zone %{dnsname}: match found at %llU", current_step->keyroll->domain, step->epochus); keyroll_step_print(step); log_info("--------------"); } if(now >= step->epochus + 1) { log_info("zone %{dnsname}: will play range from %llU until %llU", current_step->keyroll->domain, step->epochus + 1, now); ret = keyroll_step_play_range(keyrollp, step->epochus + 1 , now); log_info("zone %{dnsname}: done replaying steps: %r", current_step->keyroll->domain, ret); } else { log_info("zone %{dnsname}: no range to replay", current_step->keyroll->domain); } // will end with a return ret; } // endif } // endif break; } return ret; } void keyroll_set_dryrun_mode(bool enabled) { keyroll_dryrun_mode = enabled; } yadifa-2.6.5-11201/PaxHeaders.1636/bin0000644000000000000000000000013214505005617015035 xustar000000000000000030 mtime=1695812495.963748713 30 atime=1695812499.083793398 30 ctime=1695812495.963748713 yadifa-2.6.5-11201/bin/0000775000374500037450000000000014505005617015054 5ustar00signersigner00000000000000yadifa-2.6.5-11201/bin/PaxHeaders.1636/yadifa0000644000000000000000000000013214505005620016264 xustar000000000000000030 mtime=1695812496.097750632 30 atime=1695812499.083793398 30 ctime=1695812496.097750632 yadifa-2.6.5-11201/bin/yadifa/0000775000374500037450000000000014505005620016303 5ustar00signersigner00000000000000yadifa-2.6.5-11201/bin/yadifa/PaxHeaders.1636/module0000644000000000000000000000013214505005620017551 xustar000000000000000030 mtime=1695812496.105750747 30 atime=1695812499.083793398 30 ctime=1695812496.105750747 yadifa-2.6.5-11201/bin/yadifa/module/0000775000374500037450000000000014505005620017570 5ustar00signersigner00000000000000yadifa-2.6.5-11201/bin/yadifa/module/PaxHeaders.1636/ctrl.h0000644000000000000000000000013214505005532020745 xustar000000000000000030 mtime=1695812442.650985167 30 atime=1695812445.804030325 30 ctime=1695812496.060750103 yadifa-2.6.5-11201/bin/yadifa/module/ctrl.h0000664000374500037450000000660114505005532020712 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once /** @defgroup yadifa * @ingroup ### * @brief yadifa */ #include "module.h" #include struct tsig_item; typedef struct yadifa_ctrl_settings_s yadifa_ctrl_settings_s; struct yadifa_ctrl_settings_s { host_address *server; u8 *qname; u8 *tsig_key_name; // u8 *file; char *config_file; struct tsig_item *tsig_key_item; // for the -y option u8 log_level; /* ------------------------------------------------------------ */ u16 qclass; u16 qtype; u16 port; bool clean; /** @todo 20150219 gve -- #if HAS_TCL must be set, before release */ //#if HAS_TCL bool interactive; //#endif // HAS_TCL bool verbose; bool enable; }; #ifndef CTRL_C_ extern const module_s ctrl_program; #endif yadifa-2.6.5-11201/bin/yadifa/module/PaxHeaders.1636/zonesign.h0000644000000000000000000000013214505005532021635 xustar000000000000000030 mtime=1695812442.648985138 30 atime=1695812445.804030325 30 ctime=1695812496.062750131 yadifa-2.6.5-11201/bin/yadifa/module/zonesign.h0000664000374500037450000000521314505005532021600 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once /** @defgroup yadifa * @ingroup ### * @brief yadifa */ #include "module.h" #include struct tsig_item; typedef struct yadifa_zonesign_settings_s yadifa_zonesign_settings_s; struct yadifa_zonesign_settings_s { char *keys_path; char *output_file; char *input_file; char *journal_file; char *from_time_text; char *to_time_text; char *nsec3_salt_text; char *now_text; s64 now; u8 *origin; u32 new_serial; u32 from_time; u32 to_time; u32 interval; u32 jitter; s32 dnskey_ttl; u32 dnssec_mode; s32 nsec3_salt_size; u16 nsec3_iterations; u8 verbose; bool read_journal; bool nsec3_optout; bool smart_signing; u8 nsec3_salt[256]; }; #ifndef ZONSIGN_C_ extern const module_s zonesign_program; #endif yadifa-2.6.5-11201/bin/yadifa/module/PaxHeaders.1636/keygen.h0000644000000000000000000000013114505005532021262 xustar000000000000000030 mtime=1695812442.656985253 30 atime=1695812445.804030325 29 ctime=1695812496.06475016 yadifa-2.6.5-11201/bin/yadifa/module/keygen.h0000664000374500037450000000727614505005532021241 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once /** @defgroup yadifa * @ingroup ### * @brief yadifa */ #include "module.h" typedef struct yadifa_keygen_settings_s yadifa_keygen_settings_s; struct yadifa_keygen_settings_s { u8 *origin; //char *config_file; char *keys_path; char *random_device_file; char *key_flag; char *algorithm; char *publication_date_text; char *activation_date_text; char *revocation_date_text; char *inactivation_date_text; char *deletion_date_text; int ttl; int key_size; int digest; int interval; int verbosity_level; u8 test; /// @TODO 20160511 gve -- needs to be removed afterward bool generate_key_only; bool backward_compatible_key; bool successor_key; bool nsec3_capable; }; #ifndef KEYGEN_C_ extern const module_s keygen_program; #endif yadifa-2.6.5-11201/bin/yadifa/module/PaxHeaders.1636/dnssec-tool.h0000644000000000000000000000013114505005532022232 xustar000000000000000029 mtime=1695812442.64698511 30 atime=1695812445.804030325 30 ctime=1695812496.066750188 yadifa-2.6.5-11201/bin/yadifa/module/dnssec-tool.h0000664000374500037450000000571414505005532022204 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ #pragma once /** @defgroup yadifa * @ingroup ### * @brief yadifa */ #include "module.h" #include typedef struct dnssec_tool_settings_s dnssec_tool_settings_s; struct dnssec_tool_settings_s { ptr_vector servers; host_address *qname; u16 protocol; u16 view_mode; u16 question_mode; u16 view_mode_with; u32 edns; u32 edns_max; int16_t qclass; int16_t qtype; // host_address *qzone; }; #ifndef DNSSEC_TOOL_C_ extern const module_s dnssec_tool_program; #endif yadifa-2.6.5-11201/bin/yadifa/module/PaxHeaders.1636/ctrl.c0000644000000000000000000000013214505005532020740 xustar000000000000000030 mtime=1695812442.650985167 30 atime=1695812445.804030325 30 ctime=1695812496.099750661 yadifa-2.6.5-11201/bin/yadifa/module/ctrl.c0000664000374500037450000006761714505005532020723 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifa * @ingroup ### * @brief */ #define CTRL_C_ 1 /** @note: here we define the variable that is holding the default logger handle for the current source file * Such a handle should NEVER been set in an include file. */ #include "client-config.h" #include #include #include #include "common-config.h" #include "common.h" #include "module.h" #include "ya-conf.h" #include "module/ctrl.h" #include "query-result.h" #include "message-viewer-dig.h" #include #include #include #include #include #include #include #include // needed because of an issue in cmdline #include #include #include #include /*----------------------------------------------------------------------------*/ #pragma mark DEFINES #define DEF_VAL_CLASS "CTRL" #define DEF_VAL_TYPE "TYPE0" #define DEF_YADIFA_CONF SYSCONFDIR "/yadifa.conf" #define CTRL_SECTION_NAME "yadifa-ctrl" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES extern logger_handle *g_yadifa_logger; #define MODULE_MSG_HANDLE g_yadifa_logger // ******************************************************************************** // ***** module settings // ******************************************************************************** static yadifa_ctrl_settings_s g_yadifa_ctrl_settings; #define CONFIG_TYPE yadifa_ctrl_settings_s CONFIG_BEGIN(yadifa_ctrl_settings_desc) CONFIG_HOST_LIST_EX( server, DEF_VAL_SERVER, CONFIG_HOST_LIST_FLAGS_DEFAULT, 1 ) CONFIG_DNS_CLASS( qclass, DEF_VAL_CLASS ) CONFIG_DNS_TYPE( qtype, DEF_VAL_TYPE ) CONFIG_U16( port, DEF_VAL_SERVERPORT ) CONFIG_FQDN( qname, NULL ) CONFIG_FQDN( tsig_key_name, "ctrl-key" ) CONFIG_BOOL( enable, "on" ) CONFIG_BOOL( clean, "off" ) CONFIG_STRING( config_file, DEF_YADIFA_CONF ) CONFIG_TSIG_ITEM( tsig_key_item, NULL) CONFIG_ALIAS(key, tsig_key_name) CONFIG_BOOL( verbose, "off" ) /** @todo 20150219 gve -- must be removed before release */ CONFIG_U8( log_level, "6" ) // 6 is MSG_INFO CONFIG_END(yadifa_ctrl_settings_desc) // ******************************************************************************** // ***** module command line struct // ******************************************************************************** /** * The filter gets all words not taken by the rest of the CMDLINE struct */ static ya_result ctrl_cmdline_filter_callback(const struct cmdline_desc_s *desc, const char *arg_name, void *callback_owned) { void *arg = CMDLINE_CALLBACK_ARG_GET(desc); (void)arg; (void)callback_owned; ya_result ret; if(arg_name[0] == '@') { // @ip ret = cmdline_get_opt_short(desc, "s", &arg_name[1]); // do NOT return "ret" here (see why after the else block) } else { // states of the friendly command begin -> x -> y -> end enum CTRL_CMD_STATE { CTRL_CMD_STATE_BEGIN = 0, CTRL_CMD_STATE_ZONERELOAD, CTRL_CMD_STATE_ZONECFGRELOAD, CTRL_CMD_STATE_ZONESYNC, CTRL_CMD_STATE_ZONESYNC_FQDN, CTRL_CMD_STATE_SRVQUERYLOG, CTRL_CMD_STATE_SRVLOGLEVEL, CTRL_CMD_STATE_SRVCFGRELOAD, CTRL_CMD_STATE_SRVLOGREOPEN, CTRL_CMD_STATE_SRVSHUTDOWN, CTRL_CMD_STATE_FREEZE, CTRL_CMD_STATE_UNFREEZE, CTRL_CMD_STATE_FREEZEALL, CTRL_CMD_STATE_UNFREEZEALL, CTRL_CMD_STATE_ZONENOTIFY, CTRL_CMD_STATE_END }; static const u16 CTRL_CMD_STATE_TO_TYPE_CTRL[] = { 0, TYPE_CTRL_ZONERELOAD, TYPE_CTRL_ZONECFGRELOAD, TYPE_CTRL_ZONESYNC, 0, TYPE_CTRL_SRVQUERYLOG, TYPE_CTRL_SRVLOGLEVEL, TYPE_CTRL_SRVCFGRELOAD, TYPE_CTRL_SRVLOGREOPEN, TYPE_CTRL_SRVSHUTDOWN, TYPE_CTRL_ZONEFREEZE, TYPE_CTRL_ZONEUNFREEZE, TYPE_CTRL_ZONEFREEZEALL, TYPE_CTRL_ZONEUNFREEZEALL, TYPE_CTRL_ZONENOTIFY, 0 }; // key words: the right column is used as key here static const value_name_table keywords[] = { {CTRL_CMD_STATE_ZONERELOAD, "reload"}, {CTRL_CMD_STATE_ZONECFGRELOAD, "zonecfgreload"}, {CTRL_CMD_STATE_ZONESYNC, "sync"}, {CTRL_CMD_STATE_SRVQUERYLOG, "querylog"}, {CTRL_CMD_STATE_SRVLOGLEVEL, "loglevel"}, {CTRL_CMD_STATE_SRVCFGRELOAD, "cfgreload"}, {CTRL_CMD_STATE_SRVLOGREOPEN, "logreopen"}, {CTRL_CMD_STATE_SRVSHUTDOWN, "shutdown"}, {CTRL_CMD_STATE_FREEZE, "freeze"}, {CTRL_CMD_STATE_UNFREEZE, "unfreeze"}, {CTRL_CMD_STATE_UNFREEZE, "thaw"}, {CTRL_CMD_STATE_FREEZEALL, "freezeall"}, {CTRL_CMD_STATE_UNFREEZEALL, "unfreezeall"}, {CTRL_CMD_STATE_UNFREEZE, "thawall"}, {CTRL_CMD_STATE_ZONENOTIFY, "notify"}, {0, NULL} }; static enum CTRL_CMD_STATE cmdline_state = CTRL_CMD_STATE_BEGIN; switch(cmdline_state) { case CTRL_CMD_STATE_BEGIN: { u32 keyword_value; ret = value_name_table_get_value_from_casename(keywords, arg_name, &keyword_value); if(ISOK(ret)) { // cmdline_state = keyword_value; u16 qtype = CTRL_CMD_STATE_TO_TYPE_CTRL[keyword_value]; const char * qtype_name = dns_type_get_name(qtype); if(qtype_name != NULL) { ret = cmdline_get_opt_short(desc, "t", qtype_name); } else { ret = CONFIG_PARSE_UNKNOWN_KEYWORD; // check in dns_type_get_name if the type exists } } else { if(strcmp(arg_name, "help") == 0) { ret = cmdline_get_opt_short(desc, "h", NULL); } else { ret = CONFIG_PARSE_UNKNOWN_KEYWORD; } } break; } case CTRL_CMD_STATE_FREEZE: case CTRL_CMD_STATE_UNFREEZE: case CTRL_CMD_STATE_ZONERELOAD: case CTRL_CMD_STATE_ZONECFGRELOAD: case CTRL_CMD_STATE_ZONENOTIFY: { ret = cmdline_get_opt_short(desc, "q", arg_name); // cmdline_state = CTRL_CMD_STATE_END; break; } case CTRL_CMD_STATE_ZONESYNC: { // solve an ambiguity: if the fqdn is "clean.", then we assume it's the option "clean" and there is no fqdn. // if the users really means "clean.", then he must explicitly use "-q clean." or "-q clean --clean" if(strcasecmp(arg_name, "clean") == 0) { g_yadifa_ctrl_settings.clean = TRUE; ret = cmdline_get_opt_long(desc, "clean", NULL); // cmdline_state = CTRL_CMD_STATE_END; } else { ret = cmdline_get_opt_short(desc, "q", arg_name); } // cmdline_state = CTRL_CMD_STATE_ZONESYNC_FQDN; break; } case CTRL_CMD_STATE_ZONESYNC_FQDN: { if(strcasecmp(arg_name, "clean") == 0) { g_yadifa_ctrl_settings.clean = TRUE; ret = cmdline_get_opt_long(desc, "clean", NULL); // cmdline_state = CTRL_CMD_STATE_END; } else { ret = PARSE_INVALID_ARGUMENT; } break; } case CTRL_CMD_STATE_SRVQUERYLOG: { if(strcmp(arg_name, "enable") == 0) { g_yadifa_ctrl_settings.enable = TRUE; /*ret = */ cmdline_get_opt_long(desc, "enable", NULL); ret = SUCCESS; } else if(strcmp(arg_name, "disable") == 0) { g_yadifa_ctrl_settings.enable = FALSE; /*ret = */ cmdline_get_opt_long(desc, "disable", NULL); ret = SUCCESS; } else { ret = PARSE_INVALID_ARGUMENT; } // cmdline_state = CTRL_CMD_STATE_END; break; } case CTRL_CMD_STATE_SRVLOGLEVEL: { ret = cmdline_get_opt_short(desc, "l", arg_name); // cmdline_state = CTRL_CMD_STATE_END; break; } case CTRL_CMD_STATE_SRVCFGRELOAD: case CTRL_CMD_STATE_SRVLOGREOPEN: case CTRL_CMD_STATE_SRVSHUTDOWN: case CTRL_CMD_STATE_END: { ret = PARSE_INVALID_ARGUMENT; break; } default: { ret = INVALID_PROTOCOL; } } } if(ISOK(ret)) { ret = SUCCESS; // some success values are stopping command line processing, we do not want that to happen. } return ret; } CMDLINE_BEGIN(yadifa_cmdline) CMDLINE_FILTER(ctrl_cmdline_filter_callback, NULL) // NULL is passed to the callback as a parameter (callback_owned) // main hooks CMDLINE_INDENT(4) CMDLINE_IMSG("options:", "") CMDLINE_INDENT(4) CMDLINE_SECTION(MAIN_SECTION_NAME) CMDLINE_OPT("config",'c', "config_file" ) CMDLINE_HELP("", "use as configuration (default: " DEF_YADIFA_CONF ")") CMDLINE_SECTION(CTRL_SECTION_NAME) CMDLINE_OPT("server", 's', "server" ) CMDLINE_HELP("", "sets the name server to connect to") CMDLINE_IMSGS("", "can be an ip address or an ip address with a port number") CMDLINE_IMSGS("", "e.g. \"192.0.2.1 port 53\"") CMDLINE_IMSGS("", "note: the quotes are needed") CMDLINE_IMSGS("@", "equivalent to --server ") CMDLINE_OPT("port", 'p', "port") CMDLINE_HELP("", "sets the DNS server port (default: 53)") CMDLINE_OPT("key-name", 'K', "tsig_key_name" ) CMDLINE_HELP("", "name of the TSIG key to use for authentication (requires configuration file)") CMDLINE_OPT("key", 'y', "tsig_key_item") CMDLINE_HELP("[hmac:]name:key", "TSIG key to use for authentication (default hmac: hmac-md5)") // command line CMDLINE_VERSION_HELP(yadifa_cmdline) CMDLINE_SECTION(CTRL_SECTION_NAME) // CMDLINE_VERSION_HELP changes the section CMDLINE_BOOL("enable", 0, "enable") CMDLINE_BOOL_NOT("disable", 0, "enable") CMDLINE_BOOL("verbose", 'v', "verbose") CMDLINE_INDENT(-4) CMDLINE_BLANK() CMDLINE_IMSG("commands:", "") CMDLINE_INDENT(4) CMDLINE_IMSGS("cfgreload", "reloads settings from disk") CMDLINE_IMSGS("freeze []", "prevents dynamic updates to one or every zones") CMDLINE_IMSGS("freezeall", "prevents dynamic updates to every zone currently loaded") CMDLINE_IMSGS("loglevel ", "sets up the maximum level of log [0;15], 6 = INFO, 15 = ALL") CMDLINE_IMSGS("logreopen", "closes and reopens all the log files") CMDLINE_IMSGS("notify []", "send notifies to slaves of these zones") CMDLINE_IMSGS("querylog [enable|disable]", "enables or disables the query logging (default: enable)") CMDLINE_IMSGS("reload ", "reloads a zone from disk") CMDLINE_IMSGS("shutdown", "shuts the server down") CMDLINE_IMSGS("sync [] [clean]", "writes the zone file on disk, optionally cleans up the journal") CMDLINE_IMSGS("thaw []", "allows dynamic updates to one or every zones again") CMDLINE_IMSGS("thawall", "allows dynamic updates to every zone again") CMDLINE_IMSGS("unfreeze []", "allows dynamic updates to one or every zones again") CMDLINE_IMSGS("unfreezeall", "allows dynamic updates to every zone again") CMDLINE_IMSGS("zonecfgreload []", "reloads all (or specified) zone settings from disk") CMDLINE_INDENT(-4) CMDLINE_BLANK() CMDLINE_IMSG("alternative:", "") CMDLINE_INDENT(4) CMDLINE_BOOL( "clean", 0, "clean" ) CMDLINE_HELP("", "sets the \"clean\" flag of the \"sync\" command") CMDLINE_OPT( "level", 'l', "log_level" ) CMDLINE_HELP("", "sets the \"level\" of the \"loglevel\" command") CMDLINE_OPT( "qname", 'q', "qname" ) CMDLINE_HELP("", "sets the zone parameter of a command") CMDLINE_OPT( "type", 't', "qtype" ) CMDLINE_HELP("", "sets the command, can be:") CMDLINE_IMSGS("", " SHUTDOWN, RELOAD, LOGREOPEN, QUERYLOG, LOGLEVEL,") CMDLINE_IMSGS("", " FREEZE, UNFREEZE, FREEZEALL, UNFREEZEALL, SYNC,") CMDLINE_IMSGS("", " ZONENOTIFY, CFGRELOAD, CFGLOAD, ZONECFGRELOAD,") CMDLINE_IMSGS("", " ZONECFGRELOADALL") //CMDLINE_BOOL_NOT( "noclean",0, "clean" ) //CMDLINE_HELP("","clears the \"clean\" flag of the \"sync\" command") // resolver section //CMDLINE_RESOLVER(yadifa_cmdline) CMDLINE_END(yadifa_cmdline) // ******************************************************************************** // ***** module register // ******************************************************************************** static int ctrl_config_register(int priority) { // register all config blocs required by the server ZEROMEMORY(&g_yadifa_ctrl_settings, sizeof(g_yadifa_ctrl_settings)); ya_result ret; if(FAIL(ret = config_register_struct(CTRL_SECTION_NAME, yadifa_ctrl_settings_desc, &g_yadifa_ctrl_settings, priority))) { return ret; // internal error } return ret; } // ******************************************************************************** // ***** module run // ******************************************************************************** static ya_result ctrl_run() { ya_result return_code = OK; for(host_address *ha = g_yadifa_ctrl_settings.server; ha != NULL; ha = ha->next) { if(ha->port == 0) { ha->port = htons(g_yadifa_ctrl_settings.port); } #if DEBUG osformatln(termout, ";; DEBUG: server address: %{hostaddr}", ha); #endif } /* ------------------------------------------------------------ */ message_data_with_buffer mesg_buff; message_data *mesg; s64 query_time_send; s64 query_time_received; u8 go_tcp = OK; /* ------------------------------------------------------------ */ /* give ID from config or randomized */ u16 id = dns_new_id(); u16 qtype = htons(g_yadifa_ctrl_settings.qtype); u8 *qname = g_yadifa_ctrl_settings.qname; #if 0 /* fix */ #else u16 question_mode = 0; #endif // if 0 /* prepare root tld */ char *root = "."; u8 root_fqdn[MAX_DOMAIN_LENGTH]; cstr_to_dnsname(root_fqdn, root); mesg = message_data_with_buffer_init(&mesg_buff); switch(qtype) { case TYPE_NONE: /// @note this should have been caught in the module->setup() call so the help would be printed return_code = COMMAND_ARGUMENT_EXPECTED; formatln("control command required"); return return_code; case TYPE_CTRL_ZONEFREEZE: case TYPE_CTRL_ZONEUNFREEZE: case TYPE_CTRL_ZONERELOAD: case TYPE_CTRL_ZONECFGRELOAD: case TYPE_CTRL_ZONENOTIFY: { message_make_query(mesg, id, root_fqdn, qtype, CLASS_CTRL); packet_writer pw; packet_writer_init_append_to_message(&pw, mesg); if(qname != NULL) { packet_writer_add_record(&pw, root_fqdn, qtype, CLASS_CTRL, 0, qname, (u16)dnsname_len(qname)); message_set_answer_count_ne(mesg, NETWORK_ONE_16); // fqdn parameter is expected in the "answer" section } message_set_size(mesg, packet_writer_get_offset(&pw)); break; } /* the same as zone freeze, but without extra information */ case TYPE_CTRL_ZONEFREEZEALL: { message_make_query(mesg, id, root_fqdn, TYPE_CTRL_ZONEFREEZE, CLASS_CTRL); break; } /* the same as zone freeze, but without extra information */ case TYPE_CTRL_ZONEUNFREEZEALL: { message_make_query(mesg, id, root_fqdn, TYPE_CTRL_ZONEUNFREEZE, CLASS_CTRL); break; } /* the same as zone unfreeze, but without extra information */ case TYPE_CTRL_ZONECFGRELOADALL: { message_make_query(mesg, id, root_fqdn, TYPE_CTRL_ZONECFGRELOAD, CLASS_CTRL); break; } case TYPE_CTRL_SRVLOGLEVEL: { /* 1. create rdata part for the 'added record' - 1 byte (0 or 1) from --clean command line parameter - qname */ u8 buffer[256]; // max domain name length + 1 byte for clean value buffer[0] = MIN(g_yadifa_ctrl_settings.log_level, MSG_ALL); u16 buffer_len = 1; /* 2. make message */ message_make_query(mesg, id, root_fqdn, qtype, CLASS_CTRL); /* 3. modify message, add an extra resource record */ packet_writer pw; packet_writer_init_append_to_message(&pw, mesg); packet_writer_add_record(&pw, root_fqdn, qtype, CLASS_CTRL, 0, buffer, buffer_len); message_set_answer_count_ne(mesg, NETWORK_ONE_16); message_set_size(mesg, packet_writer_get_offset(&pw)); break; } /** @todo 20150219 gve -- still needs to check this on yadifad side */ case TYPE_CTRL_ZONESYNC: { /* 1. create rdata part for the 'added record' - 1 byte (0 or 1) from --clean command line parameter - qname */ u8 buffer[256]; // max domain name length + 1 byte for clean value buffer[0] = (u8)g_yadifa_ctrl_settings.clean; u16 buffer_len = 1; /* 2. make message */ message_make_query(mesg, id, root_fqdn, qtype, CLASS_CTRL); /* 3. modify message, add an extra resource record */ packet_writer pw; packet_writer_init_append_to_message(&pw, mesg); if(qname != NULL) { dnsname_copy(&buffer[1], qname); buffer_len += (u16)dnsname_len(qname); packet_writer_add_record(&pw, root_fqdn, qtype, CLASS_CTRL, 0, buffer, buffer_len); message_set_answer_count_ne(mesg, NETWORK_ONE_16); } else if(g_yadifa_ctrl_settings.clean) // if the clean flag is set then the parameter is required { packet_writer_add_record(&pw, root_fqdn, qtype, CLASS_CTRL, 0, buffer, buffer_len); message_set_answer_count_ne(mesg, NETWORK_ONE_16); } message_set_size(mesg, packet_writer_get_offset(&pw)); break; } case TYPE_CTRL_SRVQUERYLOG: { /* 1. make message */ message_make_query(mesg, id, root_fqdn, qtype, CLASS_CTRL); /* 2. modify message, add an extra resource record */ packet_writer pw; packet_writer_init_append_to_message(&pw, mesg); u8 flags = (g_yadifa_ctrl_settings.enable)?1:0; packet_writer_add_record(&pw, root_fqdn, qtype, CLASS_CTRL, 0, &flags, 1); message_set_answer_count_ne(mesg, NETWORK_ONE_16); message_set_size(mesg, packet_writer_get_offset(&pw)); break; } // case TYPE_CTRL_LOGREOPEN: // case TYPE_CTRL_SHUTDOWN // case TYPE_CTRL_SRVCFGRELOAD (-t cfgreload) default: { message_make_query(mesg, id, root_fqdn, qtype, CLASS_CTRL); break; } } message_set_opcode(mesg, OPCODE_CTRL); const u8 *tsig_key_name = (g_yadifa_ctrl_settings.tsig_key_item != NULL)?g_yadifa_ctrl_settings.tsig_key_item->name:g_yadifa_ctrl_settings.tsig_key_name; /** TSIG check and returns if not good * @note TSIG is always needed for the controller */ if(FAIL(return_code = message_sign_query_by_name(mesg, tsig_key_name))) { /** @todo 20150217 gve -- needs to send back a good return value */ if(return_code == TSIG_BADKEY) { osformatln(termerr, "The key used for signing the control queries isn't correct.\n" "Please verify that the controller key on the server is named '%{dnsname}.\n" "Please verify that a section for a key named '%{dnsname}' matching the one on the server is defined.\n" "\n" "e.g.:\n" "\n" "\n" " key %{dnsname}\n" " ...\n" "\n" "\n" "\n" " name %{dnsname}\n" " algorithm hmac-XXX\n" " secret XXXXXXXXXXXXXXXXX\n" "\n" "\n" "Please refer to man 8 yadifa.conf for more information.\n", g_yadifa_ctrl_settings.tsig_key_name, // BE SURE TO MATCH THE %{dnsname} IN THE ABOVE TEXT g_yadifa_ctrl_settings.tsig_key_name, g_yadifa_ctrl_settings.tsig_key_name, g_yadifa_ctrl_settings.tsig_key_name ); flusherr(); } else if(return_code == TSIG_SIZE_LIMIT_ERROR) { osformatln(termerr, "The size of the key %{dnsname} is not supported.\n", g_yadifa_ctrl_settings.tsig_key_name); flusherr(); } return return_code; } #if DEBUG osformatln(termout, ";;; DEBUG INFORMATION"); message_print_format_dig(termout, message_get_buffer(mesg), message_get_size(mesg), MESSAGE_VIEWER_SIMPLE_QUERY, -1); osformatln(termout, ";;; DEBUG INFORMATION (END)"); #endif /* set timer before send */ query_time_send = timems(); u8 connect_timeout = 6; ya_result query_return_code = message_query_tcp_with_timeout(mesg, g_yadifa_ctrl_settings.server, connect_timeout); query_time_received = timems(); if(FAIL(query_return_code)) { if(g_yadifa_ctrl_settings.verbose) { message_viewer mv; message_viewer_dig_init(&mv, termout, 0); // do not print any section mv.host = g_yadifa_ctrl_settings.server; // so the server(s) can be printed if needed query_result_view(&mv, mesg, MAX(query_time_received - query_time_send, 0), query_return_code); } else { osformatln(termerr, "command to %{hostaddr} failed: %r", g_yadifa_ctrl_settings.server, query_return_code); } return query_return_code; } /* stop timer after received */ #if 0 /* fix */ #else u16 protocol = 0; #endif // if 0 return_code = query_result_check(id, protocol, question_mode, mesg, &go_tcp); /* show the result if verbose */ if(g_yadifa_ctrl_settings.verbose) { /// @todo 20150715 gve -- needs to be modified for view_with_mode message_viewer mv; message_viewer_dig_init(&mv, termout, MESSAGE_VIEWER_SIMPLE_QUERY); mv.host = g_yadifa_ctrl_settings.server; // so the server(s) can be printed if needed return_code = query_result_view(&mv, mesg, MAX(query_time_received - query_time_send, 0), query_return_code); println(""); if(FAIL(return_code)) { return return_code; } } if(ISOK(return_code)) { // osformatln(termout, "%s", dns_message_rcode_get_name(message_get_rcode(mesg))); } else { osformatln(termerr, "error: %r", return_code); } return return_code; } // ******************************************************************************** // ***** module virtual table // ******************************************************************************** const module_s ctrl_program = { module_default_init, // module initializer module_default_finalize, // module finalizer ctrl_config_register, // module register module_default_setup, // module setup ctrl_run, // module run module_default_cmdline_help_print, // yadifa_cmdline, // module command line struct NULL, // module command line callback NULL, // module filter arguments "yadifad controller", // module public name "yctrl", // module command (name as executable match) "ctrl", // module parameter (name as first parameter) /*ctrl_cmdline_help*/ NULL, // module text to be printed upon help request ".yadifa.rc" // module rc file (ie: ".module.rc" }; yadifa-2.6.5-11201/bin/yadifa/module/PaxHeaders.1636/zonesign.c0000644000000000000000000000013014505005532021626 xustar000000000000000029 mtime=1695812442.66098531 30 atime=1695812445.804030325 29 ctime=1695812496.10175069 yadifa-2.6.5-11201/bin/yadifa/module/zonesign.c0000664000374500037450000017554114505005532021607 0ustar00signersigner00000000000000/*------------------------------------------------------------------------------ * * Copyright (c) 2011-2023, EURid vzw. All rights reserved. * The YADIFA TM software product is provided under the BSD 3-clause license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of EURid nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * *------------------------------------------------------------------------------ * */ /** @defgroup yadifa * @ingroup ### * @brief */ #define ZONESIGN_C_ 1 /** @note: here we define the variable that is holding the default logger handle for the current source file * Such a handle should NEVER been set in an include file. */ #include "client-config.h" #include #include #include #include "common-config.h" #include "common.h" #include "module.h" #include "module/zonesign.h" #include #include #include #include #include #include // needed because of an issue in cmdline #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*----------------------------------------------------------------------------*/ #pragma mark DEFINES #define ZONESIGN_SECTION_NAME "yadifa-zonesign" /*----------------------------------------------------------------------------*/ #pragma mark GLOBAL VARIABLES extern logger_handle *g_yadifa_logger; #define MODULE_MSG_HANDLE g_yadifa_logger // ******************************************************************************** // ***** module settings // ******************************************************************************** static yadifa_zonesign_settings_s g_yadifa_zonesign_settings; static random_ctx rndctx = NULL; static value_name_table dnssec_enum[]= { {ZDB_ZONE_MAINTAIN_NSEC , "nsec" }, {ZDB_ZONE_MAINTAIN_NSEC3 , "nsec3" }, {ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT, "nsec3-optout"}, {0, NULL} }; #define KEYS_PATH_DEFAULT LOCALSTATEDIR "/zones/keys/" #define SIGN_FROM_DEFAULT "-1d" #define SIGN_TO_DEFAULT "+31d" #define CONFIG_TYPE yadifa_zonesign_settings_s CONFIG_BEGIN(yadifa_zonesign_settings_desc) CONFIG_PATH(keys_path, KEYS_PATH_DEFAULT) CONFIG_FILE(input_file, NULL) CONFIG_FILE(journal_file, NULL) CONFIG_FILE(output_file, NULL) CONFIG_FQDN(origin, NULL) CONFIG_STRING(from_time_text, SIGN_FROM_DEFAULT) CONFIG_STRING(to_time_text, SIGN_TO_DEFAULT) CONFIG_STRING(now_text, "now") CONFIG_STRING(nsec3_salt_text, NULL) CONFIG_U32_RANGE(interval, "0", 0, MAX_S32) CONFIG_U32_RANGE(jitter, "0", 0, MAX_S32) CONFIG_U32_RANGE(dnskey_ttl, "86400", 0, MAX_S32) CONFIG_U32(new_serial, "0") CONFIG_U16(nsec3_iterations, "1") CONFIG_BOOL(nsec3_optout, "0") CONFIG_BOOL(read_journal, "0") CONFIG_BOOL(smart_signing, "0") CONFIG_ENUM(dnssec_mode, "nsec3", dnssec_enum) CONFIG_U8_INC(verbose) CONFIG_END(yadifa_zonesign_settings_desc) // ******************************************************************************** // ***** module command line struct // ******************************************************************************** /** * The filter gets all words not taken by the rest of the CMDLINE struct */ static ya_result zonesign_cmdline_filter_callback(const struct cmdline_desc_s *desc, const char *arg_name, void *callback_owned) { void *arg = CMDLINE_CALLBACK_ARG_GET(desc); (void)arg; (void)callback_owned; ya_result ret = cmdline_get_opt_long(desc, "input-file", arg_name); return ret; } CMDLINE_BEGIN(yadifa_cmdline) CMDLINE_FILTER(zonesign_cmdline_filter_callback, NULL) // NULL is passed to the callback as a parameter (callback_owned) // main hooks CMDLINE_INDENT(4) CMDLINE_IMSG("options:", "") CMDLINE_INDENT(4) CMDLINE_SECTION(ZONESIGN_SECTION_NAME) CMDLINE_BOOL("smart-signing", 'S', "smart_signing") CMDLINE_HELP("", "load keys found in the directory specified by keys-path and add the published ones to the zone") CMDLINE_OPT("keys-path", 'K', "keys_path" ) CMDLINE_HELP("", "directory to find key files (default: " KEYS_PATH_DEFAULT ")") CMDLINE_OPT("sign-start", 's', "from_time_text") CMDLINE_HELP("